ecacef6657ebc2a60dda16c6dcceba908d328b38
[obnox/wireshark/wip.git] / epan / dissectors / packet-ldp.c
1 /* packet-ldp.c
2  * Routines for LDP (RFC 3036) packet disassembly
3  *
4  * $Id$
5  *
6  * Copyright (c) November 2000 by Richard Sharpe <rsharpe@ns.aus.com>
7  *
8  * CRLDP (RFC3212) is now supported
9  *   - (c) 2002 Michael Rozhavsky <mike[AT]tochna.technion.ac.il>
10  *
11  * Ethereal - Network traffic analyzer
12  * By Gerald Combs <gerald@ethereal.com>
13  * Copyright 1999 Gerald Combs
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
28  */
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <ctype.h>
37 #include <time.h>
38 #include <glib.h>
39 #include <string.h>
40 #include <epan/packet.h>
41 #include <epan/addr_resolv.h>
42 #include "prefs.h"
43 #include "afn.h"
44
45 #include "packet-frame.h"
46 #include "packet-diffserv-mpls-common.h"
47
48 #define TCP_PORT_LDP 646
49 #define UDP_PORT_LDP 646
50
51 void proto_reg_handoff_ldp(void);
52
53 static int proto_ldp = -1;
54
55 /* Delete the following if you do not use it, or add to it if you need */
56 static int hf_ldp_req = -1;
57 static int hf_ldp_rsp = -1;
58 static int hf_ldp_version = -1;
59 static int hf_ldp_pdu_len = -1;
60 static int hf_ldp_lsr = -1;
61 static int hf_ldp_ls_id = -1;
62 static int hf_ldp_msg_ubit = -1;
63 static int hf_ldp_msg_type = -1;
64 static int hf_ldp_msg_len = -1;
65 static int hf_ldp_msg_id = -1;
66 static int hf_ldp_msg_vendor_id = -1;
67 static int hf_ldp_msg_experiment_id = -1;
68 static int hf_ldp_tlv_value = -1;
69 static int hf_ldp_tlv_type = -1;
70 static int hf_ldp_tlv_unknown = -1;
71 static int hf_ldp_tlv_len = -1;
72 static int hf_ldp_tlv_val_hold = -1;
73 static int hf_ldp_tlv_val_target = -1;
74 static int hf_ldp_tlv_val_request = -1;
75 static int hf_ldp_tlv_val_res = -1;
76 static int hf_ldp_tlv_ipv4_taddr = -1;
77 static int hf_ldp_tlv_config_seqno = -1;
78 static int hf_ldp_tlv_ipv6_taddr = -1;
79 static int hf_ldp_tlv_fec_wc = -1;
80 static int hf_ldp_tlv_fec_af = -1;
81 static int hf_ldp_tlv_fec_len = -1;
82 static int hf_ldp_tlv_fec_pfval = -1;
83 static int hf_ldp_tlv_fec_hoval = -1;
84 static int hf_ldp_tlv_addrl_addr_family = -1;
85 static int hf_ldp_tlv_addrl_addr = -1;
86 static int hf_ldp_tlv_hc_value = -1;
87 static int hf_ldp_tlv_pv_lsrid = -1;
88 static int hf_ldp_tlv_generic_label = -1;
89 static int hf_ldp_tlv_atm_label_vbits = -1;
90 static int hf_ldp_tlv_atm_label_vpi = -1;
91 static int hf_ldp_tlv_atm_label_vci = -1;
92 static int hf_ldp_tlv_fr_label_len = -1;
93 static int hf_ldp_tlv_fr_label_dlci = -1;
94 static int hf_ldp_tlv_ft_protect_sequence_num = -1;
95 static int hf_ldp_tlv_status_ebit = -1;
96 static int hf_ldp_tlv_status_fbit = -1;
97 static int hf_ldp_tlv_status_data = -1;
98 static int hf_ldp_tlv_status_msg_id = -1;
99 static int hf_ldp_tlv_status_msg_type = -1;
100 static int hf_ldp_tlv_extstatus_data = -1;
101 static int hf_ldp_tlv_returned_version = -1;
102 static int hf_ldp_tlv_returned_pdu_len = -1;
103 static int hf_ldp_tlv_returned_lsr = -1;
104 static int hf_ldp_tlv_returned_ls_id = -1;
105 static int hf_ldp_tlv_returned_msg_ubit = -1;
106 static int hf_ldp_tlv_returned_msg_type = -1;
107 static int hf_ldp_tlv_returned_msg_len = -1;
108 static int hf_ldp_tlv_returned_msg_id = -1;
109 static int hf_ldp_tlv_mac = -1;
110 static int hf_ldp_tlv_sess_ver = -1;
111 static int hf_ldp_tlv_sess_ka = -1;
112 static int hf_ldp_tlv_sess_advbit = -1;
113 static int hf_ldp_tlv_sess_ldetbit = -1;
114 static int hf_ldp_tlv_sess_pvlim = -1;
115 static int hf_ldp_tlv_sess_mxpdu = -1;
116 static int hf_ldp_tlv_sess_rxlsr = -1;
117 static int hf_ldp_tlv_sess_rxls = -1;
118 static int hf_ldp_tlv_sess_atm_merge = -1;
119 static int hf_ldp_tlv_sess_atm_lr = -1;
120 static int hf_ldp_tlv_sess_atm_dir = -1;
121 static int hf_ldp_tlv_sess_atm_minvpi = -1;
122 static int hf_ldp_tlv_sess_atm_maxvpi = -1;
123 static int hf_ldp_tlv_sess_atm_minvci = -1;
124 static int hf_ldp_tlv_sess_atm_maxvci = -1;
125 static int hf_ldp_tlv_sess_fr_merge = -1;
126 static int hf_ldp_tlv_sess_fr_lr = -1;
127 static int hf_ldp_tlv_sess_fr_dir = -1;
128 static int hf_ldp_tlv_sess_fr_len = -1;
129 static int hf_ldp_tlv_sess_fr_mindlci = -1;
130 static int hf_ldp_tlv_sess_fr_maxdlci = -1;
131 static int hf_ldp_tlv_ft_sess_flags = -1;
132 static int hf_ldp_tlv_ft_sess_flag_r = -1;
133 static int hf_ldp_tlv_ft_sess_flag_res = -1;
134 static int hf_ldp_tlv_ft_sess_flag_s = -1;
135 static int hf_ldp_tlv_ft_sess_flag_a = -1;
136 static int hf_ldp_tlv_ft_sess_flag_c = -1;
137 static int hf_ldp_tlv_ft_sess_flag_l = -1;
138 static int hf_ldp_tlv_ft_sess_res = -1;
139 static int hf_ldp_tlv_ft_sess_reconn_to = -1;
140 static int hf_ldp_tlv_ft_sess_recovery_time = -1;
141 static int hf_ldp_tlv_ft_ack_sequence_num = -1;
142 static int hf_ldp_tlv_lbl_req_msg_id = -1;
143 static int hf_ldp_tlv_vendor_id = -1;
144 static int hf_ldp_tlv_experiment_id = -1;
145 static int hf_ldp_tlv_fec_vc_controlword = -1;
146 static int hf_ldp_tlv_fec_vc_vctype = -1;
147 static int hf_ldp_tlv_fec_vc_infolength = -1;
148 static int hf_ldp_tlv_fec_vc_groupid = -1;
149 static int hf_ldp_tlv_fec_vc_vcid = -1;
150 static int hf_ldp_tlv_fec_vc_intparam_length = -1;
151 static int hf_ldp_tlv_fec_vc_intparam_mtu = -1;
152 static int hf_ldp_tlv_fec_vc_intparam_tdmbps = -1;
153 static int hf_ldp_tlv_fec_vc_intparam_id = -1;
154 static int hf_ldp_tlv_fec_vc_intparam_maxcatmcells = -1;
155 static int hf_ldp_tlv_fec_vc_intparam_desc = -1;
156 static int hf_ldp_tlv_fec_vc_intparam_cepbytes = -1;
157 static int hf_ldp_tlv_fec_vc_intparam_cepopt_ais = -1;
158 static int hf_ldp_tlv_fec_vc_intparam_cepopt_une = -1;
159 static int hf_ldp_tlv_fec_vc_intparam_cepopt_rtp = -1;
160 static int hf_ldp_tlv_fec_vc_intparam_cepopt_ebm = -1;
161 static int hf_ldp_tlv_fec_vc_intparam_cepopt_mah = -1;
162 static int hf_ldp_tlv_fec_vc_intparam_cepopt_res = -1;
163 static int hf_ldp_tlv_fec_vc_intparam_cepopt_ceptype = -1;
164 static int hf_ldp_tlv_fec_vc_intparam_cepopt_t3 = -1;
165 static int hf_ldp_tlv_fec_vc_intparam_cepopt_e3 = -1;
166 static int hf_ldp_tlv_fec_vc_intparam_vlanid = -1;
167 static int hf_ldp_tlv_fec_vc_intparam_dlcilen = -1;
168 static int hf_ldp_tlv_fec_vc_intparam_fcslen = -1;
169 static int hf_ldp_tlv_fec_vc_intparam_tdmopt_r = -1;
170 static int hf_ldp_tlv_fec_vc_intparam_tdmopt_d = -1;
171 static int hf_ldp_tlv_fec_vc_intparam_tdmopt_f = -1;
172 static int hf_ldp_tlv_fec_vc_intparam_tdmopt_res1 = -1;
173 static int hf_ldp_tlv_fec_vc_intparam_tdmopt_pt = -1;
174 static int hf_ldp_tlv_fec_vc_intparam_tdmopt_res2 = -1;
175 static int hf_ldp_tlv_fec_vc_intparam_tdmopt_freq = -1;
176 static int hf_ldp_tlv_fec_vc_intparam_tdmopt_ssrc = -1;
177 static int hf_ldp_tlv_fec_vc_intparam_vccv_cctype_cw = -1;
178 static int hf_ldp_tlv_fec_vc_intparam_vccv_cctype_mplsra = -1;
179 static int hf_ldp_tlv_fec_vc_intparam_vccv_cctype_ttl1 = -1;
180 static int hf_ldp_tlv_fec_vc_intparam_vccv_cvtype_icmpping = -1;
181 static int hf_ldp_tlv_fec_vc_intparam_vccv_cvtype_lspping = -1;
182 static int hf_ldp_tlv_fec_vc_intparam_vccv_cvtype_bfd = -1;
183 static int hf_ldp_tlv_lspid_act_flg = -1;
184 static int hf_ldp_tlv_lspid_cr_lsp = -1;
185 static int hf_ldp_tlv_lspid_ldpid = -1;
186 static int hf_ldp_tlv_er_hop_loose = -1;
187 static int hf_ldp_tlv_er_hop_prelen = -1;
188 static int hf_ldp_tlv_er_hop_prefix4 = -1;
189 static int hf_ldp_tlv_er_hop_prefix6 = -1;
190 static int hf_ldp_tlv_er_hop_as = -1;
191 static int hf_ldp_tlv_er_hop_cr_lsp = -1;
192 static int hf_ldp_tlv_er_hop_ldpid = -1;
193 static int hf_ldp_tlv_flags_reserv = -1;
194 static int hf_ldp_tlv_flags_weight = -1;
195 static int hf_ldp_tlv_flags_ebs = -1;
196 static int hf_ldp_tlv_flags_cbs = -1;
197 static int hf_ldp_tlv_flags_cdr = -1;
198 static int hf_ldp_tlv_flags_pbs = -1;
199 static int hf_ldp_tlv_flags_pdr = -1;
200 static int hf_ldp_tlv_frequency = -1;
201 static int hf_ldp_tlv_pdr = -1;
202 static int hf_ldp_tlv_pbs = -1;
203 static int hf_ldp_tlv_cdr = -1;
204 static int hf_ldp_tlv_cbs = -1;
205 static int hf_ldp_tlv_ebs = -1;
206 static int hf_ldp_tlv_weight = -1;
207 static int hf_ldp_tlv_set_prio = -1;
208 static int hf_ldp_tlv_hold_prio = -1;
209 static int hf_ldp_tlv_route_pinning = -1;
210 static int hf_ldp_tlv_resource_class = -1;
211 static int hf_ldp_tlv_diffserv = -1;
212 static int hf_ldp_tlv_diffserv_type = -1;
213 static int hf_ldp_tlv_diffserv_mapnb = -1;
214 static int hf_ldp_tlv_diffserv_map = -1;
215 static int hf_ldp_tlv_diffserv_map_exp = -1;
216 static int hf_ldp_tlv_diffserv_phbid = -1;
217 static int hf_ldp_tlv_diffserv_phbid_dscp = -1;
218 static int hf_ldp_tlv_diffserv_phbid_code = -1;
219 static int hf_ldp_tlv_diffserv_phbid_bit14 = -1;
220 static int hf_ldp_tlv_diffserv_phbid_bit15 = -1;
221 static int ett_ldp = -1;
222 static int ett_ldp_header = -1;
223 static int ett_ldp_ldpid = -1;
224 static int ett_ldp_message = -1;
225 static int ett_ldp_tlv = -1;
226 static int ett_ldp_tlv_val = -1;
227 static int ett_ldp_tlv_ft_flags = -1;
228 static int ett_ldp_fec = -1;
229 static int ett_ldp_fec_vc_interfaceparam = -1;
230 static int ett_ldp_fec_vc_interfaceparam_cepopt = -1;
231 static int ett_ldp_fec_vc_interfaceparam_vccvtype = -1;
232 static int ett_ldp_diffserv_map = -1;
233 static int ett_ldp_diffserv_map_phbid = -1;
234
235 static int tcp_port = 0;
236 static int udp_port = 0;
237
238 /* desegmentation of LDP over TCP */
239 static gboolean ldp_desegment = FALSE;
240
241 /* Add your functions here */
242
243 static guint32 global_ldp_tcp_port = TCP_PORT_LDP;
244 static guint32 global_ldp_udp_port = UDP_PORT_LDP;
245
246 /*
247  * The following define all the TLV types I know about
248  */
249
250 #define TLV_FEC                    0x0100
251 #define TLV_ADDRESS_LIST           0x0101
252 #define TLV_HOP_COUNT              0x0103
253 #define TLV_PATH_VECTOR            0x0104
254 #define TLV_GENERIC_LABEL          0x0200
255 #define TLV_ATM_LABEL              0x0201
256 #define TLV_FRAME_LABEL            0x0202
257 #define TLV_FT_PROTECTION          0x0203
258 #define TLV_STATUS                 0x0300
259 #define TLV_EXTENDED_STATUS        0x0301
260 #define TLV_RETURNED_PDU           0x0302
261 #define TLV_RETURNED_MESSAGE       0x0303
262 #define TLV_COMMON_HELLO_PARMS     0x0400
263 #define TLV_IPV4_TRANSPORT_ADDRESS 0x0401
264 #define TLV_CONFIGURATION_SEQNO    0x0402
265 #define TLV_IPV6_TRANSPORT_ADDRESS 0x0403
266 #define TLV_MAC                    0x0404
267 #define TLV_COMMON_SESSION_PARMS   0x0500
268 #define TLV_ATM_SESSION_PARMS      0x0501
269 #define TLV_FRAME_RELAY_SESSION_PARMS 0x0502
270 #define TLV_FT_SESSION             0x0503
271 #define TLV_FT_ACK                 0x0504
272 #define TLV_FT_CORK                0x0505
273 #define TLV_LABEL_REQUEST_MESSAGE_ID 0x0600
274 #define TLV_ER                     0x0800
275 #define TLV_ER_HOP_IPV4            0x0801
276 #define TLV_ER_HOP_IPV6            0x0802
277 #define TLV_ER_HOP_AS              0x0803
278 #define TLV_ER_HOP_LSPID           0x0804
279 #define TLV_TRAFFIC_PARAM          0x0810
280 #define TLV_PREEMPTION             0x0820
281 #define TLV_LSPID                  0x0821
282 #define TLV_RESOURCE_CLASS         0x0822
283 #define TLV_ROUTE_PINNING          0x0823
284 #define TLV_DIFFSERV               0x0901
285 #define TLV_VENDOR_PRIVATE_START   0x3E00
286 #define TLV_VENDOR_PRIVATE_END     0x3EFF
287 #define TLV_EXPERIMENTAL_START     0x3F00
288 #define TLV_EXPERIMENTAL_END       0x3FFF
289
290 static const value_string tlv_type_names[] = {
291   { TLV_FEC,                       "Forwarding Equivalence Classes TLV" },
292   { TLV_ADDRESS_LIST,              "Address List TLV"},
293   { TLV_HOP_COUNT,                 "Hop Count TLV"},
294   { TLV_PATH_VECTOR,               "Path Vector TLV"},
295   { TLV_GENERIC_LABEL,             "Generic Label TLV"},
296   { TLV_ATM_LABEL,                 "ATM Label TLV"},
297   { TLV_FRAME_LABEL,               "Frame Label TLV"},
298   { TLV_FT_PROTECTION,             "FT Protection TLV"},
299   { TLV_STATUS,                    "Status TLV"},
300   { TLV_EXTENDED_STATUS,           "Extended Status TLV"},
301   { TLV_RETURNED_PDU,              "Returned PDU TLV"},
302   { TLV_RETURNED_MESSAGE,          "Returned Message TLV"},
303   { TLV_COMMON_HELLO_PARMS,        "Common Hello Parameters TLV"},
304   { TLV_IPV4_TRANSPORT_ADDRESS,    "IPv4 Transport Address TLV"},
305   { TLV_CONFIGURATION_SEQNO,       "Configuration Sequence Number TLV"},
306   { TLV_IPV6_TRANSPORT_ADDRESS,    "IPv6 Transport Address TLV"},
307   { TLV_MAC,                       "MAC TLV"},
308   { TLV_COMMON_SESSION_PARMS,      "Common Session Parameters TLV"},
309   { TLV_ATM_SESSION_PARMS,         "ATM Session Parameters TLV"},
310   { TLV_FRAME_RELAY_SESSION_PARMS, "Frame Relay Session Parameters TLV"},
311   { TLV_FT_SESSION,                "FT Session TLV"},
312   { TLV_FT_ACK,                    "FT ACK TLV"},
313   { TLV_FT_CORK,                   "FT Cork TLV"},
314   { TLV_LABEL_REQUEST_MESSAGE_ID,  "Label Request Message ID TLV"},
315   { TLV_LSPID,                     "LSP ID TLV"},
316   { TLV_ER,                        "Explicit route TLV"},
317   { TLV_ER_HOP_IPV4,               "ER hop IPv4 prefix TLV"},
318   { TLV_ER_HOP_IPV6,               "ER hop IPv6 prefix TLV"},
319   { TLV_ER_HOP_AS,                 "ER hop Autonomous system number prefix TLV"},
320   { TLV_TRAFFIC_PARAM,             "Traffic parameters TLV"},
321   { TLV_PREEMPTION,                "Preemption TLV"},
322   { TLV_ER_HOP_LSPID,              "ER hop LSPID prefix TLV"},
323   { TLV_RESOURCE_CLASS,            "Resource Class (Color) TLV"},
324   { TLV_ROUTE_PINNING,             "Route Pinning TLV"},
325   { TLV_DIFFSERV,                  "Diff-Serv TLV"},
326   { TLV_VENDOR_PRIVATE_START,   "Vendor Private TLV"},
327   { TLV_EXPERIMENTAL_START,     "Experimental TLV"},
328   { 0, NULL}
329 };
330
331 /*
332  * The following define all the message types I know about
333  */
334
335 #define LDP_NOTIFICATION       0x0001
336 #define LDP_HELLO              0x0100
337 #define LDP_INITIALIZATION     0x0200
338 #define LDP_KEEPALIVE          0x0201
339 #define LDP_ADDRESS            0x0300
340 #define LDP_ADDRESS_WITHDRAWAL 0x0301
341 #define LDP_LABEL_MAPPING      0x0400
342 #define LDP_LABEL_REQUEST      0x0401
343 #define LDP_LABEL_WITHDRAWAL   0x0402
344 #define LDP_LABEL_RELEASE      0x0403
345 #define LDP_LABEL_ABORT_REQUEST 0x0404
346 #define LDP_VENDOR_PRIVATE_START 0x3E00
347 #define LDP_VENDOR_PRIVATE_END   0x3EFF
348 #define LDP_EXPERIMENTAL_MESSAGE_START 0x3F00
349 #define LDP_EXPERIMENTAL_MESSAGE_END   0x3FFF
350
351 static const value_string ldp_message_types[] = {
352   {LDP_NOTIFICATION,             "Notification Message"},
353   {LDP_HELLO,                    "Hello Message"},
354   {LDP_INITIALIZATION,           "Initialization Message"},
355   {LDP_KEEPALIVE,                "Keep Alive Message"},
356   {LDP_ADDRESS,                  "Address Message"},
357   {LDP_ADDRESS_WITHDRAWAL,       "Address Withdrawal Message"},
358   {LDP_LABEL_MAPPING,            "Label Mapping Message"},
359   {LDP_LABEL_REQUEST,            "Label Request Message"},
360   {LDP_LABEL_WITHDRAWAL,         "Label Withdrawal Message"},
361   {LDP_LABEL_RELEASE,            "Label Release Message"},
362   {LDP_LABEL_ABORT_REQUEST,      "Label Abort Request Message"},
363   {LDP_VENDOR_PRIVATE_START,     "Vendor-Private Message"},
364   {LDP_EXPERIMENTAL_MESSAGE_START,     "Experimental Message"},
365   {0, NULL}
366 };
367
368 static const true_false_string ldp_message_ubit = {
369   "Unknown bit set",
370   "Unknown bit not set"
371 };
372
373 static const true_false_string hello_targeted_vals = {
374   "Targeted Hello",
375   "Link Hello"
376 };
377
378 static const value_string tlv_unknown_vals[] = {
379   {0, "Known TLV, do not Forward"},
380   {1, "Known TLV, do Forward"},
381   {2, "Unknown TLV, do not Forward"},
382   {3, "Unknown TLV, do Forward"},
383   {0, NULL}
384 };
385
386 #define WILDCARD_FEC    1
387 #define PREFIX_FEC      2
388 #define HOST_FEC        3
389 #define CRLSP_FEC       4
390 #define VC_FEC          0x80    /* draft-martini-l2circuit-trans-mpls */
391
392 static const value_string fec_types[] = {
393   {WILDCARD_FEC, "Wildcard FEC"},
394   {PREFIX_FEC, "Prefix FEC"},
395   {HOST_FEC, "Host Address FEC"},
396   {CRLSP_FEC, "CR LSP FEC"},
397   {VC_FEC, "Virtual Circuit FEC"},
398   {0, NULL}
399 };
400
401
402 const value_string fec_vc_types_vals[] = {
403   {0x0001, "Frame Relay DLCI"},
404   {0x0002, "ATM AAL5 SDU VCC transport"},
405   {0x0003, "ATM transparent cell transport"},
406   {0x0004, "Ethernet VLAN"},
407   {0x0005, "Ethernet"},
408   {0x0006, "HDLC"},
409   {0x0007, "PPP"},
410   {0x0008, "SONET/SDH Circuit Emulation Service"},
411   {0x0009, "ATM n-to-one VCC cell transport"},
412   {0x000A, "ATM n-to-one VPC cell transport"},
413   {0x000B, "IP layer2 transport"},
414   {0x000C, "ATM one-to-one VCC Cell Mode"},
415   {0x000D, "ATM one-to-one VPC Cell Mode"},
416   {0x000E, "ATM AAL5 PDU VCC transport"},
417   {0x000F, "Frame-Relay Port mode"},
418   {0x0010, "SONET/SDH Circuit Emulation over Packet"},
419   {0x0011, "Structure-agnostic E1 over Packet"},
420   {0x0012, "Structure-agnostic T1 (DS1) over Packet"},
421   {0x0013, "Structure-agnostic E3 over Packet"},
422   {0x0014, "Structure-agnostic T3 (DS3) over Packet"},
423   {0x0015, "CESoPSN basic mode"},
424   {0x0016, "TDMoIP basic mode"},
425   {0x0017, "CESoPSN TDM with CAS"},
426   {0x0018, "TDMoIP TDM with CAS"},
427   {0, NULL}
428 };
429
430
431 static const value_string fec_vc_ceptype_vals[] = {
432   {0, "SPE mode (STS-1/STS-Mc)"},
433   {1, "VT mode (VT1.5/VT2/VT3/VT6)"},
434   {2, "Fractional SPE (STS-1/VC-3/VC-4)"},
435   {0, NULL}
436 };
437
438 static const true_false_string fec_vc_tdmopt_r = {
439   "Expects to receive RTP Header",
440   "Does not expect to receive RTP Header"
441 };
442
443 static const true_false_string fec_vc_tdmopt_d = {
444   "Expects the peer to use Differential timestamping",
445   "Does not expect the peer to use Differential timestamping"
446 };
447
448 static const true_false_string fec_vc_tdmopt_f = {
449   "Expects TDMoIP encapsulation",
450   "Expects CESoPSN encapsulation"
451 };
452
453
454 #define FEC_VC_INTERFACEPARAM_MTU          0x01
455 #define FEC_VC_INTERFACEPARAM_MAXCATMCELLS 0x02
456 #define FEC_VC_INTERFACEPARAM_DESCRIPTION  0x03
457 #define FEC_VC_INTERFACEPARAM_CEPBYTES     0x04
458 #define FEC_VC_INTERFACEPARAM_CEPOPTIONS   0x05
459 #define FEC_VC_INTERFACEPARAM_VLANID       0x06
460 #define FEC_VC_INTERFACEPARAM_TDMBPS       0x07
461 #define FEC_VC_INTERFACEPARAM_FRDLCILEN    0x08
462 #define FEC_VC_INTERFACEPARAM_FRAGIND      0x09
463 #define FEC_VC_INTERFACEPARAM_FCSRETENT    0x0A
464 #define FEC_VC_INTERFACEPARAM_TDMOPTION    0x0B
465 #define FEC_VC_INTERFACEPARAM_VCCV         0x0C
466
467
468
469 static const value_string fec_vc_interfaceparm[] = {
470   {FEC_VC_INTERFACEPARAM_MTU, "MTU"},
471   {FEC_VC_INTERFACEPARAM_MAXCATMCELLS, "Max Concatenated ATM cells"},
472   {FEC_VC_INTERFACEPARAM_DESCRIPTION, "Interface Description"},
473   {FEC_VC_INTERFACEPARAM_CEPBYTES, "CEP/TDM Payload Bytes"},
474   {FEC_VC_INTERFACEPARAM_CEPOPTIONS, "CEP options"},
475   {FEC_VC_INTERFACEPARAM_VLANID, "Requested VLAN ID"},
476   {FEC_VC_INTERFACEPARAM_TDMBPS, "CEP/TDM bit-rate"},
477   {FEC_VC_INTERFACEPARAM_FRDLCILEN, "Frame-Relay DLCI Length"},
478   {FEC_VC_INTERFACEPARAM_FRAGIND, "Fragmentation indicator"},
479   {FEC_VC_INTERFACEPARAM_FCSRETENT, "FCS retention indicator"},
480   {FEC_VC_INTERFACEPARAM_TDMOPTION, "TDM options"},
481   {FEC_VC_INTERFACEPARAM_VCCV, "VCCV"},
482   {0, NULL},
483 };
484
485 static const true_false_string fec_vc_cbit = {
486   "Control Word Present",
487   "Control Word NOT Present"
488 };
489
490
491
492 static const value_string tlv_atm_merge_vals[] = {
493   {0, "Merge not supported"},
494   {1, "VP merge supported"},
495   {2, "VC merge supported"},
496   {3, "VP & VC merge supported"},
497   {0, NULL}
498 };
499
500 static const value_string tlv_atm_vbits_vals[] = {
501   {0, "VPI & VCI Significant"},
502   {1, "Only VPI Significant"},
503   {2, "Only VCI Significant"},
504   {3, "VPI & VCI not Significant, nonsense"},
505   {0, NULL}
506 };
507
508 static const value_string tlv_fr_merge_vals[] = {
509   {0, "Merge not supported"},
510   {1, "Merge supported"},
511   {2, "Unspecified"},
512   {3, "Unspecified"},
513   {0, NULL}
514 };
515
516 static const value_string tlv_fr_len_vals[] = {
517   {0, "10 bits"},
518   {1, "Reserved"},
519   {2, "23 bits"},
520   {3, "Reserved"},
521   {0, NULL}
522 };
523
524 static const value_string tlv_ft_flags[] = {
525   {0, "Invalid"},
526   {1, "Using LDP Graceful Restart"},
527   {2, "Check-Pointing of all labels"},
528   {3, "Invalid"},
529   {4, "Invalid"},
530   {5, "Invalid"},
531   {6, "Check-Pointing of all labels"},
532   {7, "Invalid"},
533   {8, "Full FT on selected labels"},
534   {9, "Invalid"},
535   {10, "Full FT on selected labels"},
536   {11, "Invalid"},
537   {12, "Full FT on all labels"},
538   {13, "Invalid"},
539   {14, "Full FT on all labels"},
540   {15, "Invalid"},
541   {0, NULL}
542 };
543
544 static const true_false_string tlv_ft_r = {
545   "LSR has preserved state and resources for all FT-Labels",
546   "LSR has not preserved state and resources for all FT-Labels"
547 };
548
549 static const true_false_string tlv_ft_s = {
550   "FT Protection TLV supported on other than KeepAlive",
551   "FT Protection TLV not supported on other than KeepAlive"
552 };
553
554 static const true_false_string tlv_ft_a = {
555   "Treat all labels as Sequence Numbered FT Labels",
556   "May treat some labels as FT and others as non-FT"
557 };
558
559 static const true_false_string tlv_ft_c = {
560   "Check-Pointing procedures in use",
561   "Check-Pointing procedures not in use"
562 };
563
564 static const true_false_string tlv_ft_l = {
565   "Re-learn the state from the network",
566   "Do not re-learn the state from the network"
567 };
568
569 static const value_string ldp_act_flg_vals[] = {
570   {0, "indicates initial LSP setup"},
571   {1, "indicates modify LSP"},
572   {0, NULL}
573 };
574
575 static const value_string route_pinning_vals[] = {
576   {0, "route pinning is not requested"},
577   {1, "route pinning is requested"},
578   {0, NULL}
579 };
580
581 static const value_string diffserv_type_vals[] = {
582   {0, "E-LSP"},
583   {1, "L-LSP"},
584   {0, NULL}
585 };
586
587 static const value_string ldp_loose_vals[] = {
588   {0, "strict hop"},
589   {1, "loose hop"},
590   {0, NULL}
591 };
592
593 static const true_false_string tlv_negotiable = {
594   "Negotiable",
595   "Not negotiable"
596 };
597
598 static const value_string freq_values[] = {
599   {0, "Unspecified"},
600   {1, "Frequent"},
601   {2, "VeryFrequent"},
602   {0, NULL}
603 };
604
605 static const true_false_string tlv_atm_dirbit = {
606   "Bidirectional capability",
607   "Unidirectional capability"
608 };
609
610 static const true_false_string hello_requested_vals = {
611   "Source requests periodic hellos",
612   "Source does not request periodic hellos"
613 };
614
615 static const true_false_string tlv_sess_advbit_vals = {
616   "Downstream On Demand proposed",
617   "Downstream Unsolicited proposed"
618 };
619
620 static const true_false_string tlv_sess_ldetbit_vals = {
621   "Loop Detection Enabled",
622   "Loop Detection Disabled"
623 };
624
625 static const true_false_string tlv_status_ebit = {
626   "Fatal Error Notification",
627   "Advisory Notification"
628 };
629
630 static const true_false_string tlv_status_fbit = {
631   "Notification should be Forwarded",
632   "Notification should NOT be Forwarded"
633 };
634
635 static const value_string tlv_status_data[] = {
636   {0, "Success"},
637   {1, "Bad LDP Identifier"},
638   {2, "Bad Protocol Version"},
639   {3, "Bad PDU Length"},
640   {4, "Unknown Message Type"},
641   {5, "Bad Message Length"},
642   {6, "Unknown TLV"},
643   {7, "Bad TLV Length"},
644   {8, "Malformed TLV Value"},
645   {9, "Hold Timer Expired"},
646   {10, "Shutdown"},
647   {11, "Loop Detected"},
648   {12, "Unknown FEC"},
649   {13, "No Route"},
650   {14, "No Label Resources"},
651   {15, "Label Resources / Available"},
652   {16, "Session Rejected / No Hello"},
653   {17, "Session Rejected / Parameters Advertisement Mode"},
654   {18, "Session Rejected / Parameters Max PDU Length"},
655   {19, "Session Rejected / Parameters Label Range"},
656   {20, "KeepAlive Timer Expired"},
657   {21, "Label Request Aborted"},
658   {22, "Missing Message Parameters"},
659   {23, "Unsoported Address Family"},
660   {24, "Session Rejected / Bad KeepAlive Time"},
661   {25, "Internal Error"},
662   {26, "No LDP Session"},
663   {27, "Zero FT seqnum"},
664   {28, "Unexpected TLV / Session Not FT"},
665   {29, "Unexpected TLV / Label Not FT"},
666   {30, "Missing FT Protection TLV"},
667   {31, "FT ACK sequence error"},
668   {32, "Temporary Shutdown"},
669   {33, "FT Seq Numbers Exhausted"},
670   {34, "FT Session parameters / changed"},
671   {35, "Unexpected FT Cork TLV"},
672   {0x01000001,"Unexpected Diff-Serv TLV"},
673   {0x01000002,"Unsupported PHB"},
674   {0x01000003,"Invalid EXP<->PHB Mapping"},
675   {0x01000004,"Unsupported PSC"},
676   {0x01000005,"Per-LSP context allocation failure"},
677   {0x04000001,"Bad Explicit Routing TLV Error"},
678   {0x04000002,"Bad Strict Node Error"},
679   {0x04000003,"Bad Strict Node Error"},
680   {0x04000004,"Bad Initial ER-Hop Error"},
681   {0x04000005,"Resource Unavailable"},
682   {0x04000006,"Traffic Parameters Unavailable"},
683   {0x04000007,"LSP Preempted"},
684   {0x04000008,"Modify Request Not Supported"},
685   {0x20000001,"Illegal C-Bit"},
686   {0x20000002,"Wrong C-Bit"},
687   {0, NULL}
688 };
689
690 /* Define storage class for a string handler function
691  * with a const guint8 * argument, and returning a gchar *
692  */
693 typedef gchar *(string_handler_func)(const guint8 *);
694
695 /* Default handler for address to string conversion */
696 static gchar *
697 default_str_handler(const guint8 * bytes _U_)
698 {
699         return "<Support for this Address Family not implemented>";
700 }
701         
702 /* Dissect FEC TLV */
703
704 static void
705 dissect_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
706 {
707         proto_tree *ti=NULL, *val_tree=NULL, *fec_tree=NULL, *vcintparam_tree=NULL;
708         proto_tree *cepopt_tree=NULL, *vccvtype_tree=NULL;
709         guint16 family, ix=1, ax;
710         guint8  addr_size=0, *addr, implemented, prefix_len_octets, prefix_len, host_len, vc_len;
711         guint8  intparam_len;
712         string_handler_func *str_handler = default_str_handler;
713         char *str;
714
715         if (tree) {
716                 ti=proto_tree_add_text(tree, tvb, offset, rem, "FEC Elements");
717                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
718                 if(val_tree == NULL) return;
719
720                 while (rem > 0){
721                         switch (tvb_get_guint8(tvb, offset)) {
722                         case WILDCARD_FEC:
723                         case CRLSP_FEC:
724                                 ti = proto_tree_add_text(val_tree, tvb, offset, 1, "FEC Element %u", ix);
725                                 fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
726                                 if(fec_tree == NULL) return;
727                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc,tvb, offset, 1, FALSE);
728                                 rem -= 1;
729                                 offset += 1;
730                                 break;
731
732                         case PREFIX_FEC:
733                                 if( rem < 4 ){/*not enough*/
734                                         proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
735                                         return;
736                                 }
737                                 family=tvb_get_ntohs(tvb, offset+1);
738                                 prefix_len=tvb_get_guint8(tvb, offset+3);
739                                 prefix_len_octets=(prefix_len+7)/8;
740
741                                 implemented=1;
742                                 switch(family) {
743                                         case AFNUM_INET: /*IPv4*/
744                                                 addr_size=4;
745                                                 str_handler=ip_to_str;
746                                                 break;
747                                         case AFNUM_INET6: /*IPv6*/
748                                                 addr_size=16;
749                                                 str_handler = (string_handler_func *) ip6_to_str;
750                                                 break;
751                                         default:
752                                                 implemented=0;
753                                                 break;
754                                 }
755
756                                 if( !implemented ) {
757                                         guint16 noctets;
758
759                                         noctets= rem>4+prefix_len_octets?4+prefix_len_octets:rem;
760                                         proto_tree_add_text(val_tree, tvb, offset, noctets,"Support for Address Family not implemented");
761                                         offset+=noctets;
762                                         rem-=noctets;
763                                         break;
764                                 }
765
766                                 if( rem < 4+MIN(addr_size, prefix_len_octets) ){
767                                         proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
768                                         return;
769                                 }
770
771                                 /*Add a subtree for this*/
772                                 ti = proto_tree_add_text(val_tree, tvb, offset, 4+MIN(addr_size, prefix_len_octets), "FEC Element %u", ix);
773                                 fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
774                                 if(fec_tree == NULL) return;
775                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc, tvb, offset, 1, FALSE);
776                                 offset += 1;
777
778                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_af, tvb, offset, 2, FALSE);
779                                 offset += 2;
780
781                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_len, tvb, offset, 1, FALSE);
782                                 offset += 1;
783
784
785                                 if( addr_size < prefix_len_octets) {
786                                         offset+=addr_size;
787                                         rem-=addr_size;
788                                         proto_tree_add_text(fec_tree, tvb, offset-1, 1, "Invalid prefix %u length for family %s", prefix_len, val_to_str(family, afn_vals, "Unknown Family"));
789                                         break;
790                                 }
791
792                                 if( (addr=g_malloc0(addr_size)) == NULL ){
793                                         /*big big trouble, no mem or bad addr_size*/
794                                         fprintf(stderr, "packet-ldp: dissect_tlv_fec() malloc failed\n");
795                                         return;
796                                 }
797
798                                 for(ax=0; ax+1 <= prefix_len_octets; ax++)
799                                         addr[ax]=tvb_get_guint8(tvb, offset+ax);
800                                 if( prefix_len % 8 )
801                                         addr[ax-1] = addr[ax-1]&(0xFF<<(8-prefix_len%8));
802
803                                 str = str_handler((const guint8 *)addr);
804                                 proto_tree_add_string_format(fec_tree, hf_ldp_tlv_fec_pfval, tvb, offset, prefix_len_octets, str, "Prefix: %s", str);
805
806                                 offset += prefix_len_octets;
807                                 rem -= 4+prefix_len_octets;
808                                 g_free(addr);
809                                 break;
810
811                         case HOST_FEC:
812                                 if( rem < 4 ){/*not enough*/
813                                         proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
814                                         return;
815                                 }
816                                 family=tvb_get_ntohs(tvb, offset+1);
817                                 host_len=tvb_get_guint8(tvb, offset+3);
818
819                                 implemented=1;
820                                 switch(family) {
821                                         case AFNUM_INET: /*IPv4*/
822                                                 addr_size=4;
823                                                 str_handler=ip_to_str;
824                                                 break;
825                                         case AFNUM_INET6: /*IPv6*/
826                                                 addr_size=16;
827                                                 str_handler = (string_handler_func *) ip6_to_str;
828                                                 break;
829                                         default:
830                                                 implemented=0;
831                                                 break;
832                                 }
833
834                                 if( !implemented ) {
835                                         guint16 noctets;
836
837                                         noctets= rem>4+host_len?4+host_len:rem;
838                                         proto_tree_add_text(val_tree, tvb, offset, noctets,"Support for Address Family not implemented");
839                                         offset+=noctets;
840                                         rem-=noctets;
841                                         break;
842                                 }
843
844                                 if( rem < 4+addr_size ){
845                                         proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
846                                         return;
847                                 }
848
849                                 /*Add a subtree for this*/
850                                 ti = proto_tree_add_text(val_tree, tvb, offset, 4+addr_size, "FEC Element %u", ix);
851                                 fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
852                                 if(fec_tree == NULL) return;
853                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc, tvb, offset, 1, FALSE);
854                                 offset += 1;
855
856                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_af, tvb, offset, 2, FALSE);
857                                 offset += 2;
858
859                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_len, tvb, offset, 1, FALSE);
860                                 offset += 1;
861
862
863                                 if( addr_size != host_len) {
864                                         offset+=addr_size;
865                                         rem-=addr_size;
866                                         proto_tree_add_text(fec_tree, tvb, offset-1, 1, "Invalid address length %u length for family %s", host_len, val_to_str(family, afn_vals, "Unknown Family"));
867                                         break;
868                                 }
869
870                                 if( (addr=g_malloc0(addr_size)) == NULL ){
871                                         /*big big xtrouble, no mem or bad addr_size*/
872                                         fprintf(stderr, "packet-ldp: dissect_tlv_fec() malloc failed\n");
873                                         return;
874                                 }
875
876                                 for(ax=0; ax+1 <= host_len; ax++)
877                                         addr[ax]=tvb_get_guint8(tvb, offset+ax);
878
879                                 str = str_handler((const guint8 *)addr);
880                                 proto_tree_add_string_format(fec_tree, hf_ldp_tlv_fec_hoval, tvb, offset, host_len, str, "Address: %s", str);
881
882                                 offset += host_len;
883                                 rem -= 4+host_len;
884                                 g_free(addr);
885                                 break;
886
887                         case VC_FEC:
888                           if( rem < 8 ){/*not enough bytes for a minimal VC_FEC*/
889                             proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
890                             return;
891                           }
892                           vc_len = tvb_get_guint8 (tvb, offset+3);
893
894
895                           ti = proto_tree_add_text(val_tree, tvb, offset, 8+vc_len, "FEC Element %u", ix);
896                           fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
897                           if(fec_tree == NULL) return;
898                           proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc, tvb, offset, 1, FALSE);
899                           proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_controlword, tvb, offset+1, 1, FALSE);
900                           proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_vctype, tvb, offset+1, 2, FALSE);
901                           proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_infolength, tvb, offset+3,1,FALSE);
902                           proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_groupid,tvb, offset +4, 4, FALSE);
903                           rem -=8;
904                           offset +=8;
905
906                           if ( (vc_len > 3) && ( rem > 3 ) ) { /* there is enough room for vcid */
907                             proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_vcid,tvb, offset, 4, FALSE);
908                             proto_item_append_text (ti," VCID: %u",tvb_get_ntohl(tvb,offset));
909
910                           } else {
911                             proto_tree_add_text(val_tree,tvb,offset +4, 8 +vc_len, "VC FEC size format error");
912                             return;
913                           }
914                           rem -= 4;
915                           vc_len -= 4;
916                           offset += 4;
917
918                           while ( (vc_len > 1) && (rem > 1) ) { /* enough to include id and length */
919                             intparam_len = tvb_get_guint8(tvb, offset+1);
920                             ti = proto_tree_add_text(fec_tree, tvb, offset, intparam_len, "Interface Parameter");
921                             vcintparam_tree = proto_item_add_subtree(ti, ett_ldp_fec_vc_interfaceparam);
922                             if(vcintparam_tree == NULL) return;
923                             proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_id,tvb,offset,1,FALSE);
924                             proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_length,tvb, offset+1, 1, FALSE);
925                             if (intparam_len < 2){ /* At least Type and Len, protect against len = 0 */
926                               proto_tree_add_text(vcintparam_tree, tvb, offset +1, 1, "malformed interface parameter");
927                               return;
928                             }
929
930                             if ( (vc_len -intparam_len) <0 && (rem -intparam_len) <0 ) { /* error condition */
931                               proto_tree_add_text(vcintparam_tree, tvb, offset +2, MIN(vc_len,rem), "malformed data");
932                               return;
933                             }
934                             switch (tvb_get_guint8(tvb, offset)) {
935                             case FEC_VC_INTERFACEPARAM_MTU:
936                               proto_item_append_text(ti,": MTU %u", tvb_get_ntohs(tvb,offset+2));
937                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_mtu,tvb, offset+2, 2, FALSE);
938                               break;
939                             case FEC_VC_INTERFACEPARAM_TDMBPS:
940                               /* draft-ietf-pwe3-control-protocol-06.txt */
941                               proto_item_append_text(ti,": BPS %u", tvb_get_ntohl(tvb,offset+2));
942                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_tdmbps,tvb, offset+2, 4, FALSE);
943                               break;
944                             case FEC_VC_INTERFACEPARAM_MAXCATMCELLS:
945                               proto_item_append_text(ti,": Max ATM Concat Cells %u", tvb_get_ntohs(tvb,offset+2));
946                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_maxcatmcells,tvb, offset+2, 2, FALSE);
947                               break;
948                             case FEC_VC_INTERFACEPARAM_DESCRIPTION:
949                               proto_item_append_text(ti,": Description");
950                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_desc,tvb, offset+2, (intparam_len -2), FALSE);
951                               break;
952                             case FEC_VC_INTERFACEPARAM_CEPBYTES:
953                               proto_item_append_text(ti,": CEP/TDM Payload Bytes %u", tvb_get_ntohs(tvb,offset+2));
954                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_cepbytes,tvb, offset+2, 2, FALSE);
955                               break;
956                             case FEC_VC_INTERFACEPARAM_CEPOPTIONS:
957                               /* draft-ietf-pwe3-sonet-05.txt */
958                               proto_item_append_text(ti,": CEP Options");
959                               ti = proto_tree_add_text(vcintparam_tree, tvb, offset + 2, 2, "CEP Options");
960                               cepopt_tree = proto_item_add_subtree(ti, ett_ldp_fec_vc_interfaceparam_cepopt);
961                               if(cepopt_tree == NULL) return;
962                               proto_tree_add_item(cepopt_tree, hf_ldp_tlv_fec_vc_intparam_cepopt_ais, tvb, offset + 2, 2, FALSE);
963                               proto_tree_add_item(cepopt_tree, hf_ldp_tlv_fec_vc_intparam_cepopt_une, tvb, offset + 2, 2, FALSE);
964                               proto_tree_add_item(cepopt_tree, hf_ldp_tlv_fec_vc_intparam_cepopt_rtp, tvb, offset + 2, 2, FALSE);
965                               proto_tree_add_item(cepopt_tree, hf_ldp_tlv_fec_vc_intparam_cepopt_ebm, tvb, offset + 2, 2, FALSE);
966                               proto_tree_add_item(cepopt_tree, hf_ldp_tlv_fec_vc_intparam_cepopt_mah, tvb, offset + 2, 2, FALSE);
967                               proto_tree_add_item(cepopt_tree, hf_ldp_tlv_fec_vc_intparam_cepopt_res, tvb, offset + 2, 2, FALSE);
968                               proto_tree_add_item(cepopt_tree, hf_ldp_tlv_fec_vc_intparam_cepopt_ceptype, tvb, offset + 2, 2, FALSE);
969                               proto_tree_add_item(cepopt_tree, hf_ldp_tlv_fec_vc_intparam_cepopt_t3, tvb, offset + 2, 2, FALSE);
970                               proto_tree_add_item(cepopt_tree, hf_ldp_tlv_fec_vc_intparam_cepopt_e3, tvb, offset + 2, 2, FALSE);
971                               break;
972                             case FEC_VC_INTERFACEPARAM_VLANID:
973                               proto_item_append_text(ti,": VLAN Id %u", tvb_get_ntohs(tvb,offset+2));
974                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_vlanid, tvb, offset+2, 2, FALSE);
975                               break;
976                             case FEC_VC_INTERFACEPARAM_FRDLCILEN:
977                               proto_item_append_text(ti,": DLCI Length %u", tvb_get_ntohs(tvb,offset+2));
978                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_dlcilen, tvb, offset+2, 2, FALSE);
979                               break;
980                             case FEC_VC_INTERFACEPARAM_FRAGIND:
981                               /* draft-ietf-pwe3-fragmentation-05.txt */
982                               proto_item_append_text(ti,": Fragmentation");      
983                               break;
984                             case FEC_VC_INTERFACEPARAM_FCSRETENT:
985                               /* draft-ietf-pwe3-fcs-retention-02.txt */
986                               proto_item_append_text(ti,": FCS retention, FCS Length %u Bytes", tvb_get_ntohs(tvb,offset+2));      
987                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_fcslen, tvb, offset+2, 2, FALSE);
988                               break;
989                             case FEC_VC_INTERFACEPARAM_TDMOPTION:
990                               /* draft-vainshtein-pwe3-tdm-control-protocol-extensions */
991                               proto_item_append_text(ti,": TDM Options");
992                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_tdmopt_r, tvb, offset+2, 2, FALSE);
993                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_tdmopt_d, tvb, offset+2, 2, FALSE);
994                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_tdmopt_f, tvb, offset+2, 2, FALSE);
995                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_tdmopt_res1, tvb, offset+2, 2, FALSE);
996                               if (intparam_len >= 8){
997                                 proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_tdmopt_pt, tvb, offset+4, 1, FALSE);
998                                 proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_tdmopt_res2, tvb, offset+5, 1, FALSE);
999                                 proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_tdmopt_freq, tvb, offset+6, 2, FALSE);
1000                               }
1001                               if (intparam_len >= 12){
1002                                 proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_tdmopt_ssrc, tvb, offset+8, 4, FALSE);
1003                               }
1004                               break;
1005                             case FEC_VC_INTERFACEPARAM_VCCV:
1006                               /* draft-ietf-pwe3-vccv-03.txt */
1007                               proto_item_append_text(ti,": VCCV");
1008                               ti = proto_tree_add_text(vcintparam_tree, tvb, offset + 2, 1, "CC Type");
1009                               vccvtype_tree = proto_item_add_subtree(ti, ett_ldp_fec_vc_interfaceparam_vccvtype);
1010                               if(vccvtype_tree == NULL) return;
1011                               proto_tree_add_item(vccvtype_tree, hf_ldp_tlv_fec_vc_intparam_vccv_cctype_cw, tvb, offset+2, 1, FALSE);
1012                               proto_tree_add_item(vccvtype_tree, hf_ldp_tlv_fec_vc_intparam_vccv_cctype_mplsra, tvb, offset+2, 1, FALSE);
1013                               proto_tree_add_item(vccvtype_tree, hf_ldp_tlv_fec_vc_intparam_vccv_cctype_ttl1, tvb, offset+2, 1, FALSE);
1014                               ti = proto_tree_add_text(vcintparam_tree, tvb, offset + 3, 1, "CV Type");
1015                               vccvtype_tree = proto_item_add_subtree(ti, ett_ldp_fec_vc_interfaceparam_vccvtype);
1016                               if(vccvtype_tree == NULL) return;
1017                               proto_tree_add_item(vccvtype_tree, hf_ldp_tlv_fec_vc_intparam_vccv_cvtype_icmpping, tvb, offset+3, 1, FALSE);
1018                               proto_tree_add_item(vccvtype_tree, hf_ldp_tlv_fec_vc_intparam_vccv_cvtype_lspping, tvb, offset+3, 1, FALSE);
1019                               proto_tree_add_item(vccvtype_tree, hf_ldp_tlv_fec_vc_intparam_vccv_cvtype_bfd, tvb, offset+3, 1, FALSE);
1020                               break;
1021                             default: /* unknown */
1022                               proto_item_append_text(ti," unknown");
1023                               proto_tree_add_text(vcintparam_tree,tvb, offset+2, (intparam_len -2), "Unknown data");
1024
1025                               break;
1026                             }
1027                             rem -= intparam_len;
1028                             vc_len -= intparam_len;
1029                             offset += intparam_len;
1030                           }
1031                           break;
1032
1033                         default:  /* Unknown */
1034                         /* XXX - do all FEC's have a length that's a multiple of 4? */
1035                         /* Hmmm, don't think so. Will check. RJS. */
1036                         /* If we don't know its structure, we have to exit */
1037                                 ti = proto_tree_add_text(val_tree, tvb, offset, 4, "FEC Element %u", ix);
1038                                 fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
1039                                 if(fec_tree == NULL) return;
1040                                 proto_tree_add_text(fec_tree, tvb, offset, rem, "Unknown FEC TLV type");
1041                                 return;
1042                         }
1043                         ix++;
1044                 }
1045         }
1046 }
1047
1048 /* Dissect Address List TLV */
1049
1050 static void
1051 dissect_tlv_address_list(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1052 {
1053         proto_tree *ti = NULL, *val_tree = NULL;
1054         guint16 family, ix;
1055         guint8  addr_size, *addr;
1056         string_handler_func *str_handler = default_str_handler;
1057         char *str;
1058
1059         if (tree) {
1060                 if( rem < 2 ) {
1061                         proto_tree_add_text(tree, tvb, offset, rem,
1062                             "Error processing Address List TLV: length is %d, should be >= 2",
1063                             rem);
1064                         return;
1065                 }
1066
1067                 family=tvb_get_ntohs(tvb, offset);
1068                 proto_tree_add_item(tree, hf_ldp_tlv_addrl_addr_family, tvb,
1069                                          offset, 2, FALSE);
1070                 switch(family) {
1071                         case AFNUM_INET: /*IPv4*/
1072                                 addr_size=4;
1073                                 str_handler=ip_to_str;
1074                                 break;
1075                         case AFNUM_INET6: /*IPv6*/
1076                                 addr_size=16;
1077                                 str_handler = (string_handler_func *) ip6_to_str;
1078                                 break;
1079                         default:
1080                                 proto_tree_add_text(tree, tvb, offset+2, rem-2,
1081                                  "Support for Address Family not implemented");
1082                                 return;
1083                 }
1084
1085                 offset+=2; rem-=2;
1086                 ti=proto_tree_add_text(tree, tvb, offset, rem, "Addresses");
1087                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
1088
1089                 if(val_tree == NULL) return;
1090                 if( (addr=g_malloc(addr_size)) == NULL ){
1091                         /*big big trouble*/
1092                         fprintf(stderr, "packet-ldp: dissect_tlv_address_list() malloc failed\n");
1093                         return;
1094                 }
1095
1096                 for(ix=1; rem >= addr_size; ix++, offset += addr_size,
1097                                                          rem -= addr_size) {
1098                         if( (tvb_memcpy(tvb, addr, offset, addr_size))
1099                                                          == NULL)
1100                                 break;
1101
1102                         str = str_handler((const guint8 *)addr);
1103                         proto_tree_add_string_format(val_tree,
1104                             hf_ldp_tlv_addrl_addr, tvb, offset, addr_size, str,
1105                             "Address %u: %s", ix, str);
1106                 }
1107                 if(rem)
1108                         proto_tree_add_text(val_tree, tvb, offset, rem,
1109                             "Error processing TLV: Extra data at end of address list");
1110                 g_free(addr);
1111         }
1112 }
1113
1114 /* Dissect Path Vector TLV */
1115
1116 static void
1117 dissect_tlv_path_vector(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1118 {
1119         proto_tree *ti = NULL, *val_tree = NULL;
1120         guint8  ix;
1121         guint32 addr;
1122
1123         if (tree) {
1124                 ti=proto_tree_add_text(tree, tvb, offset, rem, "LSR IDs");
1125                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
1126
1127                 if(val_tree == NULL) return;
1128
1129                 for(ix=1; rem >= 4; ix++, offset += 4, rem -= 4) {
1130                         tvb_memcpy(tvb, (guint8 *)&addr, offset, 4);
1131                         proto_tree_add_ipv4_format(val_tree,
1132                             hf_ldp_tlv_pv_lsrid, tvb, offset, 4,
1133                             addr, "LSR Id %u: %s", ix,
1134                             ip_to_str((guint8 *)&addr));
1135                 }
1136                 if(rem)
1137                         proto_tree_add_text(val_tree, tvb, offset, rem,
1138                             "Error processing TLV: Extra data at end of path vector");
1139         }
1140 }
1141
1142 /* Dissect ATM Label TLV */
1143
1144 static void
1145 dissect_tlv_atm_label(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1146 {
1147         proto_tree *ti = NULL, *val_tree = NULL;
1148         guint16 id;
1149
1150         if(tree) {
1151                 if(rem != 4){
1152                         proto_tree_add_text(tree, tvb, offset, rem,
1153                             "Error processing ATM Label TLV: length is %d, should be 4",
1154                             rem);
1155                         return;
1156                 }
1157                 ti=proto_tree_add_text(tree, tvb, offset, rem, "ATM Label");
1158                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
1159                 if(val_tree == NULL) return;
1160
1161                 proto_tree_add_item(val_tree, hf_ldp_tlv_atm_label_vbits, tvb, offset, 1, FALSE);
1162
1163                 id=tvb_get_ntohs(tvb, offset)&0x0FFF;
1164                 proto_tree_add_uint_format(val_tree, hf_ldp_tlv_atm_label_vpi, tvb, offset, 2, id, "VPI: %u", id);
1165
1166                 id=tvb_get_ntohs(tvb, offset+2);
1167                 proto_tree_add_uint_format(val_tree, hf_ldp_tlv_atm_label_vci, tvb, offset+2, 2, id, "VCI: %u", id);
1168         }
1169 }
1170
1171 /* Dissect FRAME RELAY Label TLV */
1172
1173 static void
1174 dissect_tlv_frame_label(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1175 {
1176         proto_tree *ti = NULL, *val_tree = NULL;
1177         guint8  len;
1178         guint32 id;
1179
1180         if(tree) {
1181                 if(rem != 4){
1182                         proto_tree_add_text(tree, tvb, offset, rem,
1183                             "Error processing Frame Relay Label TLV: length is %d, should be 4",
1184                             rem);
1185                         return;
1186                 }
1187                 ti=proto_tree_add_text(tree, tvb, offset, rem, "Frame Relay Label");
1188                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
1189                 if(val_tree == NULL) return;
1190
1191                 len=(guint8)(tvb_get_ntohs(tvb, offset)>>7) & 0x03;
1192                 proto_tree_add_uint_format(val_tree, hf_ldp_tlv_fr_label_len, tvb, offset, 2, len, "Number of DLCI bits: %s (%u)", val_to_str(len, tlv_fr_len_vals, "Unknown Length"), len);
1193
1194                 id=tvb_get_ntoh24(tvb, offset+1)&0x7FFFFF;
1195                 proto_tree_add_uint_format(val_tree,
1196                 hf_ldp_tlv_fr_label_dlci, tvb, offset+1, 3, id, "DLCI: %u", id);
1197         }
1198 }
1199
1200 /* Dissect STATUS TLV */
1201
1202 static void
1203 dissect_tlv_status(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1204 {
1205         proto_tree *ti = NULL, *val_tree = NULL;
1206         guint32 data;
1207
1208         if(tree) {
1209                 if(rem != 10){
1210                         proto_tree_add_text(tree, tvb, offset, rem,
1211                             "Error processing Status TLV: length is %d, should be 10",
1212                             rem);
1213                         return;
1214                 }
1215
1216                 ti=proto_tree_add_text(tree, tvb, offset, rem, "Status");
1217                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
1218                 if(val_tree == NULL) return;
1219
1220                 proto_tree_add_item(val_tree, hf_ldp_tlv_status_ebit, tvb, offset, 1, FALSE);
1221                 proto_tree_add_item(val_tree, hf_ldp_tlv_status_fbit, tvb, offset, 1, FALSE);
1222
1223                 data=tvb_get_ntohl(tvb, offset)&0x3FFFFFFF;
1224                 proto_tree_add_uint_format(val_tree, hf_ldp_tlv_status_data, tvb, offset, 4, data, "Status Data: %s (0x%X)", val_to_str(data, tlv_status_data, "Unknown Status Data"), data);
1225
1226                 proto_tree_add_item(val_tree, hf_ldp_tlv_status_msg_id, tvb, offset+4, 4, FALSE);
1227                 proto_tree_add_item(val_tree, hf_ldp_tlv_status_msg_type, tvb, offset+8, 2, FALSE);
1228         }
1229 }
1230
1231 /* Dissect Returned PDU TLV */
1232
1233 static void
1234 dissect_tlv_returned_pdu(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1235 {
1236         proto_tree *ti = NULL, *val_tree = NULL;
1237
1238         if(tree) {
1239                 if(rem < 10){
1240                         proto_tree_add_text(tree, tvb, offset, rem,
1241                             "Error processing Returned PDU TLV: length is %d, should be >= 10",
1242                             rem);
1243                         return;
1244                 }
1245                 ti=proto_tree_add_text(tree, tvb, offset, rem, "Returned PDU");
1246                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
1247                 if(val_tree == NULL) return;
1248
1249                 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_version, tvb, offset, 2, FALSE);
1250                 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_pdu_len, tvb, offset+2, 2, FALSE);
1251                 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_lsr, tvb, offset+4, 4, FALSE);
1252                 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_ls_id, tvb, offset+8, 2, FALSE);
1253                 offset += 10;
1254                 rem -= 10;
1255
1256                 if( rem > 0 ) {
1257                 /*XXX - dissect returned pdu data*/
1258                         proto_tree_add_text(val_tree, tvb, offset, rem, "Returned PDU Data");
1259                 }
1260         }
1261 }
1262
1263 /* Dissect Returned MESSAGE TLV */
1264
1265 static void
1266 dissect_tlv_returned_message(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1267 {
1268         proto_tree *ti = NULL, *val_tree = NULL;
1269         guint16 type;
1270
1271         if(tree) {
1272                 if(rem < 4){
1273                         proto_tree_add_text(tree, tvb, offset, rem,
1274                             "Error processing Returned Message TLV: length is %d, should be >= 4",
1275                             rem);
1276                         return;
1277                 }
1278                 ti=proto_tree_add_text(tree, tvb, offset, rem, "Returned Message");
1279                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
1280                 if(val_tree == NULL) return;
1281
1282                 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_ubit, tvb, offset, 1, FALSE);
1283
1284                 type=tvb_get_ntohs(tvb, offset)&0x7FFF;
1285                 proto_tree_add_uint_format(val_tree, hf_ldp_tlv_returned_msg_type, tvb, offset, 2, type, "Message Type: %s (0x%X)", val_to_str(type, ldp_message_types,"Unknown Message Type"), type);
1286
1287                 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_len, tvb, offset+2, 2, FALSE);
1288                 offset += 4;
1289                 rem -= 4;
1290
1291                 if( rem >= 4  ) { /*have msg_id*/
1292                         proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_id, tvb, offset, 4, FALSE);
1293                         offset += 4;
1294                         rem -= 4;
1295                 }
1296
1297                 if( rem > 0 ) {
1298                 /*XXX - dissect returned msg parameters*/
1299                         proto_tree_add_text(val_tree, tvb, offset, rem, "Returned Message Parameters");
1300                 }
1301         }
1302 }
1303
1304 /* Dissect the common hello params */
1305
1306 static void
1307 #if 0
1308 dissect_tlv_common_hello_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1309 #else
1310 dissect_tlv_common_hello_parms(tvbuff_t *tvb, guint offset, proto_tree *tree)
1311 #endif
1312 {
1313 #if 0
1314         proto_tree *ti = NULL;
1315 #endif
1316         proto_tree *val_tree = NULL;
1317
1318         if (tree) {
1319 #if 0
1320                 ti = proto_tree_add_item(tree, hf_ldp_tlv_value, tvb, offset, rem, FALSE);
1321                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1322                 if(val_tree == NULL) return;
1323 #else
1324                 val_tree=tree;
1325 #endif
1326                 proto_tree_add_item(val_tree, hf_ldp_tlv_val_hold, tvb, offset, 2, FALSE);
1327                 proto_tree_add_item(val_tree, hf_ldp_tlv_val_target, tvb, offset + 2, 2, FALSE);
1328                 proto_tree_add_item(val_tree, hf_ldp_tlv_val_request, tvb, offset + 2, 2, FALSE);
1329                 proto_tree_add_item(val_tree, hf_ldp_tlv_val_res, tvb, offset + 2, 2, FALSE);
1330         }
1331 }
1332
1333 /* Dissect MAC TLV */
1334
1335 static void
1336 dissect_tlv_mac(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1337 {
1338         proto_tree *ti = NULL, *val_tree = NULL;
1339         guint8  ix;
1340         const guint8 *mac;
1341
1342         if (tree) {
1343                 ti=proto_tree_add_text(tree, tvb, offset, rem, "MAC addresses");
1344                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
1345
1346                 if(val_tree == NULL) return;
1347
1348                 for(ix=1; rem >= 6; ix++, offset += 6, rem -= 6) {
1349                         mac = tvb_get_ptr(tvb, offset, 6);
1350                         proto_tree_add_ether(val_tree,
1351                              hf_ldp_tlv_mac, tvb, offset, 6, mac);
1352                 }
1353                 if(rem)
1354                         proto_tree_add_text(val_tree, tvb, offset, rem,
1355                             "Error processing TLV: Extra data at end of path vector");
1356         }
1357 }
1358
1359
1360
1361 /* Dissect the common session params */
1362
1363 static void
1364 dissect_tlv_common_session_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1365 {
1366         proto_tree *ti = NULL, *val_tree = NULL;
1367
1368         if (tree != NULL) {
1369                 if( rem != 14) { /*length of Comm Sess Parms tlv*/
1370                         proto_tree_add_text(tree, tvb, offset, rem,
1371                             "Error processing Common Session Parameters TLV: length is %d, should be 14",
1372                             rem);
1373                         return;
1374                 }
1375                 ti = proto_tree_add_text(tree, tvb, offset, rem, "Parameters");
1376                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1377
1378                 if(val_tree != NULL) {
1379                         /*Protocol Version*/
1380                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_ver, tvb,offset, 2, FALSE);
1381
1382                         /*KeepAlive Time*/
1383                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_ka, tvb,offset + 2, 2, FALSE);
1384
1385                         /*A bit*/
1386                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_advbit,tvb, offset + 4, 1, FALSE);
1387
1388                         /*D bit*/
1389                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_ldetbit,tvb, offset + 4, 1, FALSE);
1390
1391                         /*Path Vector Limit*/
1392                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_pvlim,tvb, offset + 5, 1, FALSE);
1393
1394                         /*Max PDU Length*/
1395                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_mxpdu,tvb, offset + 6, 2, FALSE);
1396
1397                         /*Rx LSR*/
1398                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_rxlsr,tvb, offset + 8, 4, FALSE);
1399
1400                         /*Rx LS*/
1401                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_rxls,tvb, offset + 12, 2, FALSE);
1402                 }
1403         }
1404 }
1405
1406 /* Dissect the atm session params */
1407
1408 static void
1409 dissect_tlv_atm_session_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1410 {
1411         proto_tree *ti = NULL, *val_tree = NULL, *lbl_tree = NULL;
1412         guint8 numlr, ix;
1413         guint16 id;
1414
1415         if (tree != NULL) {
1416                 if(rem < 4) {
1417                         proto_tree_add_text(tree, tvb, offset, rem,
1418                             "Error processing ATM Parameters TLV: length is %d, should be >= 4",
1419                             rem);
1420                         return;
1421                 }
1422
1423                 ti = proto_tree_add_text(tree, tvb, offset, rem,"ATM Parameters");
1424                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1425
1426                 if(val_tree != NULL) {
1427                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_atm_merge,tvb, offset, 1, FALSE);
1428
1429                         /*get the number of label ranges*/
1430                         numlr=(tvb_get_guint8(tvb, offset)>>2) & 0x0F;
1431                         proto_tree_add_uint_format(val_tree, hf_ldp_tlv_sess_atm_lr,
1432                         tvb, offset, 1, numlr, "Number of Label Range components: %u",
1433                         numlr);
1434
1435                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_atm_dir,tvb, offset, 1, FALSE);
1436
1437                         /*move into range components*/
1438                         offset += 4;
1439                         rem -= 4;
1440                         ti = proto_tree_add_text(val_tree, tvb, offset, rem,"ATM Label Range Components");
1441
1442                         if(numlr) {
1443                                 val_tree=proto_item_add_subtree(ti,ett_ldp_tlv_val);
1444                                 if( ! val_tree ) return;
1445                         }
1446                         /*now dissect ranges*/
1447                         for(ix=1; numlr > 0 && rem >= 8; ix++, rem-=8, numlr--) {
1448                                 ti=proto_tree_add_text(val_tree, tvb, offset, 8,
1449                                  "ATM Label Range Component %u", ix);
1450                                 lbl_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
1451
1452                                 if( lbl_tree == NULL ) break;
1453
1454                                 id=tvb_get_ntohs(tvb, offset)&0x0FFF;
1455                                 proto_tree_add_uint_format(lbl_tree,
1456                                     hf_ldp_tlv_sess_atm_minvpi,
1457                                     tvb, offset, 2,
1458                                     id, "Minimum VPI: %u", id);
1459                                 id=tvb_get_ntohs(tvb, offset+4)&0x0FFF;
1460                                 proto_tree_add_uint_format(lbl_tree,
1461                                     hf_ldp_tlv_sess_atm_maxvpi,
1462                                     tvb, (offset+4), 2, id,
1463                                     "Maximum VPI: %u", id);
1464
1465                                 id=tvb_get_ntohs(tvb, offset+2);
1466                                 proto_tree_add_uint_format(lbl_tree,
1467                                     hf_ldp_tlv_sess_atm_minvci,
1468                                     tvb, offset+2, 2,
1469                                     id, "Minimum VCI: %u", id);
1470                                 id=tvb_get_ntohs(tvb, offset+6);
1471                                 proto_tree_add_uint_format(lbl_tree,
1472                                     hf_ldp_tlv_sess_atm_maxvci,
1473                                     tvb, offset+6, 2,
1474                                     id, "Maximum VCI: %u", id);
1475
1476                                 offset += 8;
1477                         }
1478                         if( rem || numlr)
1479                                 proto_tree_add_text(val_tree, tvb, offset, rem,
1480                                     "Error processing TLV: Extra data at end of TLV");
1481                 }
1482         }
1483 }
1484
1485 /* Dissect the frame relay session params */
1486
1487 static void
1488 dissect_tlv_frame_relay_session_parms(tvbuff_t *tvb, guint offset,proto_tree *tree, int rem)
1489 {
1490         proto_tree *ti = NULL, *val_tree = NULL, *lbl_tree = NULL;
1491         guint8 numlr, ix, len;
1492         guint32 id;
1493
1494         if (tree != NULL) {
1495                 if(rem < 4) {
1496                         proto_tree_add_text(tree, tvb, offset, rem,
1497                             "Error processing Frame Relay Parameters TLV: length is %d, should be >= 4",
1498                             rem);
1499                         return;
1500                 }
1501
1502                 ti = proto_tree_add_text(tree, tvb, offset, rem,
1503                                                  "Frame Relay Parameters");
1504                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1505
1506                 if(val_tree != NULL) {
1507                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_fr_merge,
1508                                 tvb, offset, 1, FALSE);
1509
1510                         /*get the number of label ranges*/
1511                         numlr=(tvb_get_guint8(tvb, offset)>>2) & 0x0F;
1512                         proto_tree_add_uint_format(val_tree, hf_ldp_tlv_sess_fr_lr,
1513                         tvb, offset, 1, numlr, "Number of Label Range components: %u",
1514                         numlr);
1515
1516                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_fr_dir,
1517                                  tvb, offset, 1, FALSE);
1518
1519                         /*move into range components*/
1520                         offset += 4;
1521                         rem -= 4;
1522                         ti = proto_tree_add_text(val_tree, tvb, offset, rem,
1523                                  "Frame Relay Label Range Components");
1524
1525                         if(numlr) {
1526                                 val_tree=proto_item_add_subtree(ti,
1527                                                          ett_ldp_tlv_val);
1528                                 if( ! val_tree ) return;
1529                         }
1530
1531                         /*now dissect ranges*/
1532                         for(ix=1; numlr > 0 && rem >= 8; ix++, rem-=8, numlr--) {
1533                                 ti=proto_tree_add_text(val_tree, tvb, offset, 8,
1534                                 "Frame Relay Label Range Component %u", ix);
1535                                 lbl_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
1536
1537                                 if( lbl_tree == NULL ) break;
1538
1539                                 len=(guint8)(tvb_get_ntohs(tvb, offset)>>7) & 0x03;
1540                                 proto_tree_add_uint_format(lbl_tree, hf_ldp_tlv_sess_fr_len, tvb, offset, 2, len, "Number of DLCI bits: %s (%u)", val_to_str(len, tlv_fr_len_vals, "Unknown Length"), len);
1541
1542                                 id=tvb_get_ntoh24(tvb, offset+1)&0x7FFFFF;
1543                                 proto_tree_add_uint_format(lbl_tree,
1544                         hf_ldp_tlv_sess_fr_mindlci, tvb, offset+1, 3, id, "Minimum DLCI %u", id);
1545                                 id=tvb_get_ntoh24(tvb, offset+5)&0x7FFFFF;
1546                                 proto_tree_add_uint_format(lbl_tree,
1547                         hf_ldp_tlv_sess_fr_maxdlci, tvb, offset+5, 3, id, "Maximum DLCI %u", id);
1548
1549                                 offset += 8;
1550                         }
1551
1552                         if( rem || numlr)
1553                                 proto_tree_add_text(val_tree, tvb, offset, rem,
1554                                  "Error processing TLV: Extra data at end of TLV");
1555                 }
1556         }
1557 }
1558
1559 /* Dissect the Fault Tolerant (FT) Session TLV */
1560
1561 static void
1562 dissect_tlv_ft_session(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1563 {
1564         proto_tree *ti = NULL, *val_tree = NULL, *flags_tree = NULL;
1565         guint16 flags = 0;
1566
1567         if (tree != NULL) {
1568                 if(rem != 12){
1569                         /* error, length must be 12 bytes */
1570                         proto_tree_add_text(tree, tvb, offset, rem,
1571                             "Error processing FT Session TLV: length is %d, should be 12",
1572                             rem);
1573                         return;
1574                 }
1575
1576                 ti = proto_tree_add_text(tree, tvb, offset, rem, "FT Session Parameters");
1577                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1578
1579                 if(val_tree != NULL) {
1580                         /* Flags */
1581                         ti = proto_tree_add_item(val_tree, hf_ldp_tlv_ft_sess_flags, tvb, offset, 2, FALSE);
1582                         flags_tree = proto_item_add_subtree(ti,  ett_ldp_tlv_ft_flags);
1583                         if (flags_tree == NULL)
1584                                 return;
1585
1586                         flags = tvb_get_ntohs(tvb, offset);
1587                         proto_item_append_text(ti, " (%s%s)", (flags & 0x8000) ? "R, " : "",
1588                             val_to_str(flags & 0xF, tlv_ft_flags, "Invalid"));
1589                         proto_tree_add_item(flags_tree, hf_ldp_tlv_ft_sess_flag_r, tvb, offset, 2, FALSE);
1590                         proto_tree_add_item(flags_tree, hf_ldp_tlv_ft_sess_flag_res, tvb, offset, 2, FALSE);
1591                         proto_tree_add_item(flags_tree, hf_ldp_tlv_ft_sess_flag_s, tvb, offset, 2, FALSE);
1592                         proto_tree_add_item(flags_tree, hf_ldp_tlv_ft_sess_flag_a, tvb, offset, 2, FALSE);
1593                         proto_tree_add_item(flags_tree, hf_ldp_tlv_ft_sess_flag_c, tvb, offset, 2, FALSE);
1594                         proto_tree_add_item(flags_tree, hf_ldp_tlv_ft_sess_flag_l, tvb, offset, 2, FALSE);
1595
1596                         /* Reserved */
1597                         proto_tree_add_item(val_tree, hf_ldp_tlv_ft_sess_res, tvb, offset + 2, 2, FALSE);
1598
1599                         /* FT Reconnect TO */
1600                         proto_tree_add_item(val_tree, hf_ldp_tlv_ft_sess_reconn_to, tvb, offset + 4,
1601                             4, FALSE);
1602
1603                         /* Recovery Time */
1604                         proto_tree_add_item(val_tree, hf_ldp_tlv_ft_sess_recovery_time, tvb, offset + 8,
1605                             4, FALSE);
1606                 }
1607         }
1608
1609 }
1610
1611 static void
1612 dissect_tlv_lspid(tvbuff_t *tvb, guint offset,proto_tree *tree, int rem)
1613 {
1614         proto_tree *ti = NULL, *val_tree = NULL;
1615
1616         if (tree != NULL) {
1617                 if(rem != 8) {
1618                         proto_tree_add_text(tree, tvb, offset, rem,
1619                             "Error processing LSP ID TLV: length is %d, should be 8",
1620                             rem);
1621                         return;
1622                 }
1623
1624                 ti = proto_tree_add_text(tree, tvb, offset, rem,
1625                                                 "LSP ID");
1626                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1627
1628                 if(val_tree != NULL) {
1629                         proto_tree_add_item(val_tree, hf_ldp_tlv_lspid_act_flg,
1630                                            tvb, offset, 2, FALSE);
1631                         offset += 2;
1632                         proto_tree_add_item(val_tree, hf_ldp_tlv_lspid_cr_lsp,
1633                                            tvb, offset, 2, FALSE);
1634                         offset += 2;
1635                         proto_tree_add_item(val_tree, hf_ldp_tlv_lspid_ldpid,
1636                                            tvb, offset, 4, FALSE);
1637                 }
1638         }
1639 }
1640
1641 static void
1642 dissect_tlv_er_hop_ipv4(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1643 {
1644         proto_tree *ti = NULL, *val_tree = NULL;
1645
1646
1647         if (tree != NULL) {
1648                 if(rem != 8) {
1649                         proto_tree_add_text(tree, tvb, offset, rem,
1650                             "Error processing ER HOP IPv4 TLV: length is %d, should be 8",
1651                             rem);
1652                         return;
1653                 }
1654                 ti = proto_tree_add_text(tree, tvb, offset, rem, "ER HOP IPv4");
1655                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1656
1657                 if(val_tree != NULL) {
1658                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_loose,
1659                                            tvb, offset, 3, FALSE);
1660                         offset += 3;
1661                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_prelen,
1662                                            tvb, offset, 1, FALSE);
1663                         offset ++;
1664                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_prefix4,
1665                                            tvb, offset, 4, FALSE);
1666                 }
1667         }
1668 }
1669
1670 static void
1671 dissect_tlv_er_hop_ipv6(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1672 {
1673         proto_tree *ti = NULL, *val_tree = NULL;
1674
1675         if (tree != NULL) {
1676                 if(rem != 20) {
1677                         proto_tree_add_text(tree, tvb, offset, rem,
1678                             "Error processing ER HOP IPv6 TLV: length is %d, should be 20",
1679                             rem);
1680                         return;
1681                 }
1682                 ti = proto_tree_add_text(tree, tvb, offset, rem, "ER HOP IPv6");
1683                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1684
1685                 if(val_tree != NULL) {
1686                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_loose,
1687                                            tvb, offset, 3, FALSE);
1688                         offset += 3;
1689                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_prelen,
1690                                           tvb, offset, 1, FALSE);
1691                         offset ++;
1692                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_prefix6,
1693                                            tvb, offset, 16, FALSE);
1694                 }
1695         }
1696 }
1697
1698 static void
1699 dissect_tlv_er_hop_as(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1700 {
1701         proto_tree *ti = NULL, *val_tree = NULL;
1702
1703         if (tree != NULL) {
1704                 if(rem != 4) {
1705                         proto_tree_add_text(tree, tvb, offset, rem,
1706                             "Error processing ER HOP AS TLV: length is %d, should be 4",
1707                             rem);
1708                         return;
1709                 }
1710                 ti = proto_tree_add_text(tree, tvb, offset, rem, "ER HOP AS");
1711                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1712
1713                 if(val_tree != NULL) {
1714                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_loose,
1715                                            tvb, offset, 2, FALSE);
1716                         offset += 2;
1717                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_as,
1718                                            tvb, offset, 2, FALSE);
1719                 }
1720         }
1721 }
1722
1723 static void
1724 dissect_tlv_er_hop_lspid(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1725 {
1726         proto_tree *ti = NULL, *val_tree = NULL;
1727
1728         if (tree != NULL) {
1729                 if(rem != 8) {
1730                         proto_tree_add_text(tree, tvb, offset, rem,
1731                             "Error processing ER HOP LSPID TLV: length is %d, should be 8",
1732                             rem);
1733                         return;
1734                 }
1735                 ti = proto_tree_add_text(tree, tvb, offset, rem, "ER HOP LSPID");
1736                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1737
1738                 if(val_tree != NULL) {
1739                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_loose,
1740                                            tvb, offset, 2, FALSE);
1741                         offset += 2;
1742                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_cr_lsp,
1743                                            tvb, offset, 2, FALSE);
1744                         offset += 2;
1745                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_ldpid,
1746                                            tvb, offset, 4, FALSE);
1747                 }
1748         }
1749 }
1750
1751 static void
1752 dissect_tlv_traffic(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1753 {
1754         proto_tree *ti = NULL, *val_tree = NULL;
1755         guint8  val_8;
1756         float   val_f;
1757         proto_item *pi;
1758
1759         if (tree != NULL) {
1760                 if(rem != 24) {
1761                         proto_tree_add_text(tree, tvb, offset, rem,
1762                             "Error processing Traffic Parameters TLV: length is %d, should be 24",
1763                             rem);
1764                         return;
1765                 }
1766                 ti = proto_tree_add_text(tree, tvb, offset, rem, "Traffic parameters");
1767                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1768
1769                 if(val_tree != NULL) {
1770                         /* flags */
1771                         proto_tree_add_item(val_tree, hf_ldp_tlv_flags_reserv, tvb, offset, 1, FALSE);
1772                         proto_tree_add_item(val_tree, hf_ldp_tlv_flags_weight, tvb, offset, 1, FALSE);
1773                         proto_tree_add_item(val_tree, hf_ldp_tlv_flags_ebs, tvb, offset, 1, FALSE);
1774                         proto_tree_add_item(val_tree, hf_ldp_tlv_flags_cbs, tvb, offset, 1, FALSE);
1775                         proto_tree_add_item(val_tree, hf_ldp_tlv_flags_cdr, tvb, offset, 1, FALSE);
1776                         proto_tree_add_item(val_tree, hf_ldp_tlv_flags_pbs, tvb, offset, 1, FALSE);
1777                         proto_tree_add_item(val_tree, hf_ldp_tlv_flags_pdr, tvb, offset, 1, FALSE);
1778
1779                         offset ++;
1780                         /* frequency */
1781                         proto_tree_add_item(val_tree, hf_ldp_tlv_frequency, tvb, offset, 1, FALSE);
1782                         offset ++;
1783
1784                         /* reserver byte */
1785                         offset ++;
1786
1787                         /* weight */
1788                         pi = proto_tree_add_item(val_tree, hf_ldp_tlv_weight, tvb, offset, 1, FALSE);
1789                         val_8 = tvb_get_guint8(tvb, offset);
1790                         if (val_8 == 0)
1791                                 proto_item_set_text(pi, "Weight: Not applicable");
1792                         offset ++;
1793
1794                         /* PDR */
1795                         val_f = tvb_get_ntohieee_float (tvb, offset);
1796                         proto_tree_add_double_format(val_tree, hf_ldp_tlv_pdr, tvb, offset,
1797                                                     4, val_f, "PDR: %.10g Bps", val_f);
1798                         offset += 4;
1799                         /* PBS */
1800                         val_f = tvb_get_ntohieee_float (tvb, offset);
1801                         proto_tree_add_double_format(val_tree, hf_ldp_tlv_pbs, tvb, offset,
1802                                                     4, val_f, "PBS: %.10g Bytes", val_f);
1803                         offset += 4;
1804
1805                         /* CDR */
1806                         val_f = tvb_get_ntohieee_float (tvb, offset);
1807                         proto_tree_add_double_format(val_tree, hf_ldp_tlv_cdr, tvb, offset,
1808                                                     4, val_f, "CDR: %.10g Bps", val_f);
1809                         offset += 4;
1810
1811                         /* CBS */
1812                         val_f = tvb_get_ntohieee_float (tvb, offset);
1813                         proto_tree_add_double_format(val_tree, hf_ldp_tlv_cbs, tvb, offset,
1814                                                     4, val_f, "CBS: %.10g Bytes", val_f);
1815                         offset += 4;
1816
1817                         /* EBS */
1818                         val_f = tvb_get_ntohieee_float (tvb, offset);
1819                         proto_tree_add_double_format(val_tree, hf_ldp_tlv_ebs, tvb, offset,
1820                                                     4, val_f, "EBS: %.10g Bytes", val_f);
1821
1822                 }
1823         }
1824 }
1825
1826 static void
1827 dissect_tlv_route_pinning(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1828 {
1829         proto_tree *ti = NULL, *val_tree = NULL;
1830
1831         if (tree != NULL) {
1832                 if(rem != 4) {
1833                         proto_tree_add_text(tree, tvb, offset, rem,
1834                             "Error processing Route Pinning TLV: length is %d, should be 4",
1835                             rem);
1836                         return;
1837                 }
1838                 ti = proto_tree_add_text(tree, tvb, offset, rem, "Route Pinning");
1839                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1840
1841                 if(val_tree != NULL) {
1842                         proto_tree_add_item(val_tree, hf_ldp_tlv_route_pinning,
1843                                            tvb, offset, 4, FALSE);
1844                 }
1845         }
1846 }
1847
1848
1849 static void
1850 dissect_tlv_resource_class(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1851 {
1852         proto_tree *ti = NULL, *val_tree = NULL;
1853
1854         if (tree != NULL) {
1855                 if(rem != 4) {
1856                         proto_tree_add_text(tree, tvb, offset, rem,
1857                             "Error processing Resource Class TLV: length is %d, should be 4",
1858                             rem);
1859                         return;
1860                 }
1861                 ti = proto_tree_add_text(tree, tvb, offset, rem, "Resource Class");
1862                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1863
1864                 if(val_tree != NULL) {
1865                         proto_tree_add_item(val_tree, hf_ldp_tlv_resource_class,
1866                                            tvb, offset, 4, FALSE);
1867                 }
1868         }
1869 }
1870
1871
1872 static void
1873 dissect_tlv_preemption(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1874 {
1875         proto_tree *ti = NULL, *val_tree = NULL;
1876
1877         if (tree != NULL) {
1878                 if(rem != 4) {
1879                         proto_tree_add_text(tree, tvb, offset, rem,
1880                             "Error processing Preemption TLV: length is %d, should be 4",
1881                             rem);
1882                         return;
1883                 }
1884                 ti = proto_tree_add_text(tree, tvb, offset, rem, "Preemption");
1885                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1886
1887                 if(val_tree != NULL) {
1888                         proto_tree_add_item(val_tree, hf_ldp_tlv_set_prio,
1889                                            tvb, offset, 1, FALSE);
1890                         offset += 1;
1891                         proto_tree_add_item(val_tree, hf_ldp_tlv_hold_prio,
1892                                            tvb, offset, 1, FALSE);
1893                 }
1894         }
1895 }
1896
1897
1898 static void
1899 dissect_tlv_diffserv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1900 {
1901     int type, mapnb, count;
1902     int *hfindexes[] = {
1903         &hf_ldp_tlv_diffserv_map,
1904         &hf_ldp_tlv_diffserv_map_exp,
1905         &hf_ldp_tlv_diffserv_phbid,
1906         &hf_ldp_tlv_diffserv_phbid_dscp,
1907         &hf_ldp_tlv_diffserv_phbid_code,
1908         &hf_ldp_tlv_diffserv_phbid_bit14,
1909         &hf_ldp_tlv_diffserv_phbid_bit15
1910     };
1911     gint *etts[] = {
1912         &ett_ldp_diffserv_map,
1913         &ett_ldp_diffserv_map_phbid
1914     };
1915
1916     if (rem < 4) {
1917         proto_tree_add_text(tree, tvb, offset, rem,
1918             "Error processing Diff-Serv TLV: length is %d, should be >= 4", rem);
1919         return;
1920     }
1921     proto_tree_add_uint(tree, hf_ldp_tlv_diffserv_type, tvb, offset, 1,
1922                         type = tvb_get_guint8(tvb, offset));
1923     type = (type >> 7) + 1;
1924     if (type == 1) {
1925         /* E-LSP */
1926         offset += 3;
1927         proto_tree_add_uint(tree, hf_ldp_tlv_diffserv_mapnb, tvb, offset,
1928                             1, mapnb = tvb_get_guint8(tvb, offset) & 15);
1929         offset += 1;
1930         for (count = 0; count < mapnb; count++) {
1931             dissect_diffserv_mpls_common(tvb, tree, type, offset, hfindexes, etts);
1932             offset += 4;
1933         }
1934     }
1935     else if (type == 2) {
1936         /* L-LSP */
1937         dissect_diffserv_mpls_common(tvb, tree, type, offset + 2, hfindexes, etts);
1938     }
1939 }
1940
1941
1942 static int
1943 dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem);
1944
1945 static void
1946 dissect_tlv_er(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1947 {
1948         proto_tree *ti = NULL, *val_tree = NULL;
1949         int len;
1950
1951         if (tree != NULL) {
1952                 ti = proto_tree_add_text(tree, tvb, offset, rem, "Explicit route");
1953                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1954
1955                 if(val_tree != NULL) {
1956                         len = 0;
1957                         while (rem > 0) {
1958                                 len = dissect_tlv (tvb, offset, val_tree, rem);
1959                                 offset += len;
1960                                 rem -= len;
1961                         }
1962                 }
1963         }
1964 }
1965
1966
1967 /* Dissect a TLV and return the number of bytes consumed ... */
1968
1969 static int
1970 dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1971 {
1972         guint16 type, typebak;
1973         int length;
1974         proto_tree *ti = NULL, *tlv_tree = NULL;
1975
1976         length=tvb_reported_length_remaining(tvb, offset);
1977         rem=MIN(rem, length);
1978
1979         if( rem < 4 ) {/*chk for minimum header*/
1980                 if(tree)
1981                         proto_tree_add_text(tree, tvb, offset, rem,
1982                             "Error processing TLV: length is %d, should be >= 4",
1983                             rem);
1984                 return rem;
1985         }
1986         type = tvb_get_ntohs(tvb, offset) & 0x3FFF;
1987
1988         length = tvb_get_ntohs(tvb, offset + 2),
1989         rem -= 4; /*do not count header*/
1990         length = MIN(length, rem);  /* Don't go haywire if a problem ... */
1991
1992         if (tree != NULL) {
1993                 /*chk for vendor-private*/
1994                 if(type>=TLV_VENDOR_PRIVATE_START && type<=TLV_VENDOR_PRIVATE_END){
1995                         typebak=type;           /*keep type*/
1996                         type=TLV_VENDOR_PRIVATE_START;
1997
1998                 /*chk for experimental*/
1999                 } else if(type>=TLV_EXPERIMENTAL_START && type<=TLV_EXPERIMENTAL_END){
2000                         typebak=type;           /*keep type*/
2001                         type=TLV_EXPERIMENTAL_START;
2002                 }
2003
2004                 ti = proto_tree_add_text(tree, tvb, offset, length + 4, "%s",
2005                         val_to_str(type, tlv_type_names, "Unknown TLV type (0x%04X)"));
2006                 tlv_tree = proto_item_add_subtree(ti, ett_ldp_tlv);
2007                 if(tlv_tree == NULL) return length+4;
2008
2009                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_unknown, tvb, offset, 1, FALSE);
2010
2011                 proto_tree_add_uint_format(tlv_tree, hf_ldp_tlv_type, tvb, offset, 2, type, "TLV Type: %s (0x%X)", val_to_str(type, tlv_type_names, "Unknown TLV type"), type );
2012
2013                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_len, tvb, offset + 2, 2, FALSE);
2014
2015                 switch (type) {
2016
2017                 case TLV_FEC:
2018                         dissect_tlv_fec(tvb, offset + 4, tlv_tree, length);
2019                         break;
2020
2021                 case TLV_ADDRESS_LIST:
2022                         dissect_tlv_address_list(tvb, offset + 4, tlv_tree, length);
2023                         break;
2024
2025                 case TLV_HOP_COUNT:
2026                         if( length != 1 ) /*error, only one byte*/
2027                                 proto_tree_add_text(tlv_tree, tvb, offset + 4,length,
2028                                     "Error processing Hop Count TLV: length is %d, should be 1",
2029                                     length);
2030                         else
2031                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_hc_value, tvb,offset + 4, length, FALSE);
2032                         break;
2033
2034                 case TLV_PATH_VECTOR:
2035                         dissect_tlv_path_vector(tvb, offset + 4, tlv_tree, length);
2036                         break;
2037
2038                 case TLV_GENERIC_LABEL:
2039                         if( length != 4 ) /*error, need only label*/
2040                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
2041                                     "Error processing Generic Label TLV: length is %d, should be 4",
2042                                     length);
2043                         else {
2044                                 guint32 label=tvb_get_ntohl(tvb, offset+4) & 0x000FFFFF;
2045
2046                                 proto_tree_add_uint_format(tlv_tree, hf_ldp_tlv_generic_label,
2047                                         tvb, offset+4, length, label, "Generic Label: %u", label);
2048                         }
2049                         break;
2050
2051                 case TLV_ATM_LABEL:
2052                         dissect_tlv_atm_label(tvb, offset + 4, tlv_tree, length);
2053                         break;
2054
2055                 case TLV_FRAME_LABEL:
2056                         dissect_tlv_frame_label(tvb, offset + 4, tlv_tree, length);
2057                         break;
2058
2059                 case TLV_FT_PROTECTION:
2060                         if( length != 4 ) /* Length must be 4 bytes */
2061                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
2062                                     "Error processing FT Protection TLV: length is %d, should be 4",
2063                                     length);
2064                         else
2065                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_ft_protect_sequence_num, tvb,
2066                                     offset + 4,length, FALSE);
2067                         break;
2068
2069                 case TLV_STATUS:
2070                         dissect_tlv_status(tvb, offset + 4, tlv_tree, length);
2071                         break;
2072
2073                 case TLV_EXTENDED_STATUS:
2074                         if( length != 4 ) /*error, need only status_code(guint32)*/
2075                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
2076                                     "Error processing Extended Status TLV: length is %d, should be 4",
2077                                     length);
2078                         else {
2079                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_extstatus_data, tvb, offset + 4, length, FALSE);
2080                         }
2081                         break;
2082
2083                 case TLV_RETURNED_PDU:
2084                         dissect_tlv_returned_pdu(tvb, offset + 4, tlv_tree, length);
2085                         break;
2086
2087                 case TLV_RETURNED_MESSAGE:
2088                         dissect_tlv_returned_message(tvb, offset + 4, tlv_tree, length);
2089                         break;
2090
2091                 case TLV_COMMON_HELLO_PARMS:
2092 #if 0
2093                         dissect_tlv_common_hello_parms(tvb, offset + 4, tlv_tree, length);
2094 #else
2095                         dissect_tlv_common_hello_parms(tvb, offset + 4, tlv_tree);
2096 #endif
2097                         break;
2098
2099                 case TLV_IPV4_TRANSPORT_ADDRESS:
2100                         if( length != 4 ) /*error, need only ipv4*/
2101                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
2102                                     "Error processing IPv4 Transport Address TLV: length is %d, should be 4",
2103                                     length);
2104                         else {
2105                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_ipv4_taddr, tvb, offset + 4, 4, FALSE);
2106                         }
2107                         break;
2108
2109                 case TLV_CONFIGURATION_SEQNO:
2110                         if( length != 4 ) /*error, need only seq_num(guint32)*/
2111                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
2112                                     "Error processing Configuration Sequence Number TLV: length is %d, should be 4",
2113                                     length);
2114                         else {
2115                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_config_seqno, tvb, offset + 4, 4, FALSE);
2116                         }
2117                         break;
2118
2119                 case TLV_IPV6_TRANSPORT_ADDRESS:
2120                         if( length != 16 ) /*error, need only ipv6*/
2121                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
2122                                     "Error processing IPv6 Transport Address TLV: length is %d, should be 16",
2123                                     length);
2124                         else {
2125                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_ipv6_taddr, tvb, offset + 4, 16, FALSE);
2126                         }
2127                         break;
2128
2129                 case TLV_MAC: /* draft-lasserre-vkompella-ppvpn-vpls-02.txt */
2130                         dissect_tlv_mac(tvb, offset + 4, tlv_tree, length);
2131                         break;
2132
2133                 case TLV_COMMON_SESSION_PARMS:
2134                         dissect_tlv_common_session_parms(tvb, offset + 4, tlv_tree, length);
2135                         break;
2136
2137                 case TLV_ATM_SESSION_PARMS:
2138                         dissect_tlv_atm_session_parms(tvb, offset + 4, tlv_tree, length);
2139                         break;
2140
2141                 case TLV_FRAME_RELAY_SESSION_PARMS:
2142                         dissect_tlv_frame_relay_session_parms(tvb, offset + 4, tlv_tree, length);
2143                         break;
2144
2145                 case TLV_FT_SESSION:
2146                         /* Used in RFC3478 LDP Graceful Restart */
2147                         dissect_tlv_ft_session(tvb, offset + 4, tlv_tree, length);
2148                         break;
2149
2150                 case TLV_FT_ACK:
2151                         if( length != 4 ) /* Length must be 4 bytes */
2152                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
2153                                     "Error processing FT ACK TLV: length is %d, should be 4",
2154                                     length);
2155                         else
2156                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_ft_ack_sequence_num, tvb,
2157                                     offset + 4,length, FALSE);
2158                         break;
2159
2160                 case TLV_FT_CORK:
2161                         if( length != 0 ) /* Length must be 0 bytes */
2162                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
2163                                     "Error processing FT Cork TLV: length is %d, should be 0",      
2164                                     length);
2165                         break;
2166
2167                 case TLV_LABEL_REQUEST_MESSAGE_ID:
2168                         if( length != 4 ) /*error, need only one msgid*/
2169                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
2170                                     "Error processing Label Request Message ID TLV: length is %d, should be 4",
2171                                     length);
2172                         else
2173                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_lbl_req_msg_id, tvb,offset + 4,length, FALSE);
2174                         break;
2175
2176                 case TLV_LSPID:
2177                         dissect_tlv_lspid(tvb, offset + 4, tlv_tree, length);
2178                         break;
2179
2180                 case TLV_ER:
2181                         dissect_tlv_er(tvb, offset + 4, tlv_tree, length);
2182                         break;
2183
2184                 case TLV_ER_HOP_IPV4:
2185                         dissect_tlv_er_hop_ipv4(tvb, offset + 4, tlv_tree, length);
2186                         break;
2187
2188                 case TLV_ER_HOP_IPV6:
2189                         dissect_tlv_er_hop_ipv6(tvb, offset +4, tlv_tree, length);
2190                         break;
2191
2192                 case TLV_ER_HOP_AS:
2193                         dissect_tlv_er_hop_as(tvb, offset + 4, tlv_tree, length);
2194                         break;
2195
2196                 case TLV_ER_HOP_LSPID:
2197                         dissect_tlv_er_hop_lspid(tvb, offset +4, tlv_tree, length);
2198                         break;
2199
2200                 case TLV_TRAFFIC_PARAM:
2201                         dissect_tlv_traffic(tvb, offset +4, tlv_tree, length);
2202                         break;
2203
2204                 case TLV_PREEMPTION:
2205                         dissect_tlv_preemption(tvb, offset +4, tlv_tree, length);
2206                         break;
2207
2208                 case TLV_RESOURCE_CLASS:
2209                         dissect_tlv_resource_class(tvb, offset +4, tlv_tree, length);
2210                         break;
2211
2212                 case TLV_ROUTE_PINNING:
2213                         dissect_tlv_route_pinning(tvb, offset +4, tlv_tree, length);
2214                         break;
2215
2216                 case TLV_DIFFSERV:
2217                         dissect_tlv_diffserv(tvb, offset +4, tlv_tree, length);
2218                         break;
2219
2220                 case TLV_VENDOR_PRIVATE_START:
2221                         if( length < 4 ) /*error, at least Vendor ID*/
2222                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
2223                                     "Error processing Vendor Private Start TLV: length is %d, should be >= 4",
2224                                     length);
2225                         else {
2226                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_vendor_id, tvb,offset + 4, 4, FALSE);
2227                                 if( length > 4 )  /*have data*/
2228                                         proto_tree_add_text(tlv_tree, tvb, offset + 8, length-4,"Data");
2229                         }
2230                         break;
2231
2232                 case TLV_EXPERIMENTAL_START:
2233                         if( length < 4 ) /*error, at least Experiment ID*/
2234                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
2235                                     "Error processing Experimental Start TLV: length is %d, should be >= 4",
2236                                     length);
2237                         else {
2238                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_experiment_id, tvb,offset + 4, 4, FALSE);
2239                                 if( length > 4 )  /*have data*/
2240                                         proto_tree_add_text(tlv_tree, tvb, offset + 8, length-4,"Data");
2241                         }
2242                         break;
2243
2244                 default:
2245                         proto_tree_add_item(tlv_tree, hf_ldp_tlv_value, tvb, offset + 4, length, FALSE);
2246                         break;
2247                 }
2248         }
2249
2250         return length + 4;  /* Length of the value field + header */
2251 }
2252
2253
2254 /* Dissect a Message and return the number of bytes consumed ... */
2255
2256 static int
2257 dissect_msg(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree)
2258 {
2259         guint16 type, typebak;
2260         guint8  extra=0;
2261         int length, rem, ao=0, co;
2262         proto_tree *ti = NULL, *msg_tree = NULL;
2263
2264         rem=tvb_reported_length_remaining(tvb, offset);
2265
2266         if( rem < 8 ) {/*chk for minimum header = type + length + msg_id*/
2267                 if( check_col(pinfo->cinfo, COL_INFO) )
2268                         col_append_fstr(pinfo->cinfo, COL_INFO, "Bad Message");
2269                 if(tree)
2270                         proto_tree_add_text(tree, tvb, offset, rem,
2271                             "Error processing Message: length is %d, should be >= 8",
2272                             rem);
2273                 return rem;
2274         }
2275         type = tvb_get_ntohs(tvb, offset) & 0x7FFF;
2276
2277         /*chk for vendor-private*/
2278         if(type>=LDP_VENDOR_PRIVATE_START && type<=LDP_VENDOR_PRIVATE_END){
2279                 typebak=type;           /*keep type*/
2280                 type=LDP_VENDOR_PRIVATE_START;
2281                 extra=4;
2282         /*chk for experimental*/
2283         } else if(type>=LDP_EXPERIMENTAL_MESSAGE_START && type<=LDP_EXPERIMENTAL_MESSAGE_END){
2284                 typebak=type;           /*keep type*/
2285                 type=LDP_EXPERIMENTAL_MESSAGE_START;
2286                 extra=4;
2287         }
2288
2289         if( (length = tvb_get_ntohs(tvb, offset + 2)) < (4+extra) ) {/*not enough data for type*/
2290                 if( check_col(pinfo->cinfo, COL_INFO) )
2291                         col_append_fstr(pinfo->cinfo, COL_INFO, "Bad Message Length ");
2292                 if(tree)
2293                         proto_tree_add_text(tree, tvb, offset, rem,
2294                             "Error processing Message Length: length is %d, should be >= %u",
2295                             length, 4+extra);
2296                 return rem;
2297         }
2298         rem -= 4;
2299         length = MIN(length, rem);  /* Don't go haywire if a problem ... */
2300
2301         if( check_col(pinfo->cinfo, COL_INFO) ){
2302                 col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(type, ldp_message_types, "Unknown Message (0x%04X)"));
2303         }
2304
2305         if( tree ){
2306                 ti = proto_tree_add_text(tree, tvb, offset, length + 4, "%s",
2307                         val_to_str(type, ldp_message_types, "Unknown Message type (0x%04X)"));
2308                 msg_tree = proto_item_add_subtree(ti, ett_ldp_message);
2309                 if(msg_tree == NULL) return length+4;
2310
2311                 proto_tree_add_item(msg_tree, hf_ldp_msg_ubit, tvb, offset, 1, FALSE);
2312
2313                 type=tvb_get_ntohs(tvb, offset)&0x7FFF;
2314                 proto_tree_add_uint_format(msg_tree, hf_ldp_msg_type, tvb, offset, 2, type, "Message Type: %s (0x%X)", val_to_str(type, ldp_message_types,"Unknown Message Type"), type);
2315
2316                 proto_tree_add_item(msg_tree, hf_ldp_msg_len, tvb, offset+2, 2, FALSE);
2317                 proto_tree_add_item(msg_tree, hf_ldp_msg_id, tvb, offset+4, 4, FALSE);
2318                 if(extra){
2319                         int hf_tmp=0;
2320
2321                         switch(type){
2322                                 case LDP_VENDOR_PRIVATE_START:
2323                                         hf_tmp=hf_ldp_msg_vendor_id;
2324                                         break;
2325                                 case LDP_EXPERIMENTAL_MESSAGE_START:
2326                                         hf_tmp=hf_ldp_msg_experiment_id;
2327                                         break;
2328                         }
2329                         proto_tree_add_item(msg_tree, hf_tmp, tvb, offset+8, extra, FALSE);
2330                 }
2331         }
2332
2333         offset += (8+extra);
2334         length -= (4+extra);
2335
2336         if( tree )
2337                 while( (length-ao) > 0 ) {
2338                         co=dissect_tlv(tvb, offset, msg_tree, length-ao);
2339                         offset += co;
2340                         ao += co;
2341                 }
2342
2343         return length+8+extra;
2344 }
2345
2346 /* Dissect a PDU */
2347 static void
2348 dissect_ldp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2349 {
2350         int offset = 0, co;
2351         int rem, length;
2352         proto_tree *ti=NULL, *pdu_tree = NULL;
2353
2354         if (check_col(pinfo->cinfo, COL_PROTOCOL))
2355                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "LDP");
2356
2357         if (check_col(pinfo->cinfo, COL_INFO))
2358                 col_clear(pinfo->cinfo, COL_INFO);
2359
2360         if( tree ){
2361                 ti=proto_tree_add_item(tree, proto_ldp, tvb, 0, -1, FALSE);
2362                 pdu_tree = proto_item_add_subtree(ti, ett_ldp);
2363
2364                 proto_tree_add_item(pdu_tree, hf_ldp_version, tvb, offset, 2, FALSE);
2365         }
2366
2367         length = tvb_get_ntohs(tvb, offset+2);
2368         if( tree )
2369                 proto_tree_add_uint(pdu_tree, hf_ldp_pdu_len, tvb, offset+2, 2, length);
2370
2371         length += 4;    /* add the version and type sizes */
2372         rem = tvb_reported_length_remaining(tvb, offset);
2373         if (length < rem)
2374                 tvb_set_reported_length(tvb, length);
2375
2376         if( tree ){
2377                 proto_tree_add_item(pdu_tree, hf_ldp_lsr, tvb, offset+4, 4, FALSE);
2378                 proto_tree_add_item(pdu_tree, hf_ldp_ls_id, tvb, offset+8, 2, FALSE);
2379         }
2380         offset += 10;
2381
2382         while( tvb_reported_length_remaining(tvb, offset) > 0 ) {
2383                 co=dissect_msg(tvb, offset, pinfo, pdu_tree);
2384                 offset += co;
2385         }
2386 }
2387
2388 static int
2389 dissect_ldp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2390 {
2391         /*
2392          * Make sure the first PDU has a version number of 1;
2393          * if not, reject this, so we don't get confused by
2394          * packets that happen to be going to or from the
2395          * LDP port but that aren't LDP packets.
2396          */
2397         if (!tvb_bytes_exist(tvb, 0, 2)) {
2398                 /*
2399                  * Not enough information to tell.
2400                  */
2401                 return 0;
2402         }
2403         if (tvb_get_ntohs(tvb, 0) != 1) {
2404                 /*
2405                  * Not version 1.
2406                  */
2407                 return 0;
2408         }
2409
2410         dissect_ldp_pdu(tvb, pinfo, tree);
2411
2412         /*
2413          * XXX - return minimum of this and the length of the PDU?
2414          */
2415         return tvb_length(tvb);
2416 }
2417
2418 static int
2419 dissect_ldp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2420 {
2421         volatile gboolean first = TRUE;
2422         volatile int offset = 0;
2423         int length_remaining;
2424         guint16 plen;
2425         int length;
2426         tvbuff_t *next_tvb;
2427
2428         while (tvb_reported_length_remaining(tvb, offset) != 0) {
2429                 length_remaining = tvb_length_remaining(tvb, offset);
2430
2431                 /*
2432                  * Make sure the first PDU has a version number of 1;
2433                  * if not, reject this, so we don't get confused by
2434                  * packets that happen to be going to or from the
2435                  * LDP port but that aren't LDP packets.
2436                  *
2437                  * XXX - this means we can't handle an LDP PDU of which
2438                  * only one byte appears in a TCP segment.  If that's
2439                  * a problem, we'll either have to completely punt on
2440                  * rejecting non-LDP packets, or will have to assume
2441                  * that if we have only one byte, it's an LDP packet.
2442                  */
2443                 if (first) {
2444                         if (length_remaining < 2) {
2445                                 /*
2446                                  * Not enough information to tell.
2447                                  */
2448                                 return 0;
2449                         }
2450                         if (tvb_get_ntohs(tvb, offset) != 1) {
2451                                 /*
2452                                  * Not version 1.
2453                                  */
2454                                 return 0;
2455                         }
2456                         first = FALSE;
2457                 }
2458
2459                 /*
2460                  * Can we do reassembly?
2461                  */
2462                 if (ldp_desegment && pinfo->can_desegment) {
2463                         /*
2464                          * Yes - is the LDP header split across segment
2465                          * boundaries?
2466                          */
2467                         if (length_remaining < 4) {
2468                                 /*
2469                                  * Yes.  Tell the TCP dissector where
2470                                  * the data for this message starts in
2471                                  * the data it handed us, and how many
2472                                  * more bytes we need, and return.
2473                                  */
2474                                 pinfo->desegment_offset = offset;
2475                                 pinfo->desegment_len = 4 - length_remaining;
2476                                 return -((gint32) pinfo->desegment_len);
2477                         }
2478                 }
2479
2480                 /*
2481                  * Get the length of the rest of the LDP packet.
2482                  * XXX - check for a version of 1 first?
2483                  */
2484                 plen = tvb_get_ntohs(tvb, offset + 2);
2485
2486                 /*
2487                  * Can we do reassembly?
2488                  */
2489                 if (ldp_desegment && pinfo->can_desegment) {
2490                         /*
2491                          * Yes - is the LDP packet split across segment
2492                          * boundaries?
2493                          */
2494                         if (length_remaining < plen + 4) {
2495                                 /*
2496                                  * Yes.  Tell the TCP dissector where the
2497                                  * data for this message starts in the data
2498                                  * it handed us, and how many more bytes we
2499                                  * need, and return.
2500                                  */
2501                                 pinfo->desegment_offset = offset;
2502                                 pinfo->desegment_len =
2503                                     (plen + 4) - length_remaining;
2504                                 return -((gint32) pinfo->desegment_len);
2505                         }
2506                 }
2507
2508                 /*
2509                  * Construct a tvbuff containing the amount of the payload
2510                  * we have available.  Make its reported length the
2511                  * amount of data in the DNS-over-TCP packet.
2512                  *
2513                  * XXX - if reassembly isn't enabled. the subdissector
2514                  * will throw a BoundsError exception, rather than a
2515                  * ReportedBoundsError exception.  We really want
2516                  * a tvbuff where the length is "length", the reported
2517                  * length is "plen + 4", and the "if the snapshot length
2518                  * were infinite" length is the minimum of the
2519                  * reported length of the tvbuff handed to us and "plen+4",
2520                  * with a new type of exception thrown if the offset is
2521                  * within the reported length but beyond that third length,
2522                  * with that exception getting the "Unreassembled Packet"
2523                  * error.
2524                  */
2525                 length = length_remaining;
2526                 if (length > plen + 4)
2527                         length = plen + 4;
2528                 next_tvb = tvb_new_subset(tvb, offset, length, plen + 4);
2529
2530                 /*
2531                  * Dissect the LDP packet.
2532                  *
2533                  * Catch the ReportedBoundsError exception; if this
2534                  * particular message happens to get a ReportedBoundsError
2535                  * exception, that doesn't mean that we should stop
2536                  * dissecting LDP messages within this frame or chunk of
2537                  * reassembled data.
2538                  *
2539                  * If it gets a BoundsError, we can stop, as there's nothing
2540                  * more to see, so we just re-throw it.
2541                  */
2542                 TRY {
2543                         dissect_ldp_pdu(next_tvb, pinfo, tree);
2544                 }
2545                 CATCH(BoundsError) {
2546                         RETHROW;
2547                 }
2548                 CATCH(ReportedBoundsError) {
2549                         show_reported_bounds_error(tvb, pinfo, tree);
2550                 }
2551                 ENDTRY;
2552
2553                 /*
2554                  * Skip the LDP header and the payload.
2555                  */
2556                 offset += plen + 4;
2557         }
2558         return tvb_length(tvb);
2559 }
2560
2561 /* Register all the bits needed with the filtering engine */
2562
2563 void
2564 proto_register_ldp(void)
2565 {
2566   static hf_register_info hf[] = {
2567     { &hf_ldp_req,
2568       /* Change the following to the type you need */
2569       { "Request", "ldp.req", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
2570
2571     { &hf_ldp_rsp,
2572       { "Response", "ldp.rsp", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
2573
2574     { &hf_ldp_version,
2575       { "Version", "ldp.hdr.version", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Version Number", HFILL }},
2576
2577     { &hf_ldp_pdu_len,
2578       { "PDU Length", "ldp.hdr.pdu_len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP PDU Length", HFILL }},
2579
2580     { &hf_ldp_lsr,
2581       { "LSR ID", "ldp.hdr.ldpid.lsr", FT_IPv4, BASE_HEX, NULL, 0x0, "LDP Label Space Router ID", HFILL }},
2582
2583     { &hf_ldp_ls_id,
2584       { "Label Space ID", "ldp.hdr.ldpid.lsid", FT_UINT16, BASE_DEC, NULL, 0, "LDP Label Space ID", HFILL }},
2585
2586     { &hf_ldp_msg_ubit,
2587       { "U bit", "ldp.msg.ubit", FT_BOOLEAN, 8, TFS(&ldp_message_ubit), 0x80, "Unknown Message Bit", HFILL }},
2588
2589     { &hf_ldp_msg_type,
2590       { "Message Type", "ldp.msg.type", FT_UINT16, BASE_HEX, VALS(ldp_message_types), 0x7FFF, "LDP message type", HFILL }},
2591
2592     { &hf_ldp_msg_len,
2593       { "Message Length", "ldp.msg.len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Message Length (excluding message type and len)", HFILL }},
2594
2595     { &hf_ldp_msg_id,
2596       { "Message ID", "ldp.msg.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Message ID", HFILL }},
2597
2598     { &hf_ldp_msg_vendor_id,
2599       { "Vendor ID", "ldp.msg.vendor.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Vendor-private Message ID", HFILL }},
2600
2601     { &hf_ldp_msg_experiment_id,
2602       { "Experiment ID", "ldp.msg.experiment.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Experimental Message ID", HFILL }},
2603
2604     { &hf_ldp_tlv_unknown,
2605       { "TLV Unknown bits", "ldp.msg.tlv.unknown", FT_UINT8, BASE_HEX, VALS(tlv_unknown_vals), 0xC0, "TLV Unknown bits Field", HFILL }},
2606
2607     { &hf_ldp_tlv_type,
2608       { "TLV Type", "ldp.msg.tlv.type", FT_UINT16, BASE_HEX, VALS(tlv_type_names), 0x3FFF, "TLV Type Field", HFILL }},
2609
2610     { &hf_ldp_tlv_len,
2611       {"TLV Length", "ldp.msg.tlv.len", FT_UINT16, BASE_DEC, NULL, 0x0, "TLV Length Field", HFILL }},
2612
2613     { &hf_ldp_tlv_value,
2614       { "TLV Value", "ldp.msg.tlv.value", FT_BYTES, BASE_NONE, NULL, 0x0, "TLV Value Bytes", HFILL }},
2615
2616     { &hf_ldp_tlv_val_hold,
2617       { "Hold Time", "ldp.msg.tlv.hello.hold", FT_UINT16, BASE_DEC, NULL, 0x0, "Hello Common Parameters Hold Time", HFILL }},
2618
2619     { &hf_ldp_tlv_val_target,
2620       { "Targeted Hello", "ldp.msg.tlv.hello.targeted", FT_BOOLEAN, 16, TFS(&hello_targeted_vals), 0x8000, "Hello Common Parameters Targeted Bit", HFILL }},
2621
2622     { &hf_ldp_tlv_val_request,
2623       { "Hello Requested", "ldp.msg.tlv.hello.requested", FT_BOOLEAN, 16, TFS(&hello_requested_vals), 0x4000, "Hello Common Parameters Hello Requested Bit", HFILL }},
2624
2625     { &hf_ldp_tlv_val_res,
2626       { "Reserved", "ldp.msg.tlv.hello.res", FT_UINT16, BASE_HEX, NULL, 0x3FFF, "Hello Common Parameters Reserved Field", HFILL }},
2627
2628     { &hf_ldp_tlv_ipv4_taddr,
2629       { "IPv4 Transport Address", "ldp.msg.tlv.ipv4.taddr", FT_IPv4, BASE_DEC, NULL, 0x0, "IPv4 Transport Address", HFILL }},
2630
2631     { &hf_ldp_tlv_config_seqno,
2632       { "Configuration Sequence Number", "ldp.msg.tlv.hello.cnf_seqno", FT_UINT32, BASE_DEC, NULL, 0x0, "Hello Configuration Sequence Number", HFILL }},
2633
2634     { &hf_ldp_tlv_ipv6_taddr,
2635       { "IPv6 Transport Address", "ldp.msg.tlv.ipv6.taddr", FT_IPv6, BASE_DEC, NULL, 0x0, "IPv6 Transport Address", HFILL }},
2636
2637     { &hf_ldp_tlv_fec_wc,
2638       { "FEC Element Type", "ldp.msg.tlv.fec.type", FT_UINT8, BASE_DEC, VALS(fec_types), 0x0, "Forwarding Equivalence Class Element Types", HFILL }},
2639
2640     { &hf_ldp_tlv_fec_af,
2641       { "FEC Element Address Type", "ldp.msg.tlv.fec.af", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, "Forwarding Equivalence Class Element Address Family", HFILL }},
2642
2643     { &hf_ldp_tlv_fec_len,
2644       { "FEC Element Length", "ldp.msg.tlv.fec.len", FT_UINT8, BASE_DEC, NULL, 0x0, "Forwarding Equivalence Class Element Length", HFILL }},
2645
2646     { &hf_ldp_tlv_fec_pfval,
2647       { "FEC Element Prefix Value", "ldp.msg.tlv.fec.pfval", FT_STRING, BASE_NONE, NULL, 0x0, "Forwarding Equivalence Class Element Prefix", HFILL }},
2648
2649     { &hf_ldp_tlv_fec_hoval,
2650       { "FEC Element Host Address Value", "ldp.msg.tlv.fec.hoval", FT_STRING, BASE_NONE, NULL, 0x0, "Forwarding Equivalence Class Element Address", HFILL }},
2651
2652     { &hf_ldp_tlv_addrl_addr_family,
2653       { "Address Family", "ldp.msg.tlv.addrl.addr_family", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, "Address Family List", HFILL }},
2654
2655     { &hf_ldp_tlv_addrl_addr,
2656       { "Address", "ldp.msg.tlv.addrl.addr", FT_STRING, BASE_NONE, NULL, 0x0, "Address", HFILL }},
2657
2658     { &hf_ldp_tlv_hc_value,
2659       { "Hop Count Value", "ldp.msg.tlv.hc.value", FT_UINT8, BASE_DEC, NULL, 0x0, "Hop Count", HFILL }},
2660
2661     { &hf_ldp_tlv_pv_lsrid,
2662       { "LSR Id", "ldp.msg.tlv.pv.lsrid", FT_IPv4, BASE_DEC, NULL, 0x0, "Path Vector LSR Id", HFILL }},
2663
2664     { &hf_ldp_tlv_sess_ver,
2665       { "Session Protocol Version", "ldp.msg.tlv.sess.ver", FT_UINT16, BASE_DEC, NULL, 0x0, "Common Session Parameters Protocol Version", HFILL }},
2666
2667     { &hf_ldp_tlv_sess_ka,
2668       { "Session KeepAlive Time", "ldp.msg.tlv.sess.ka", FT_UINT16, BASE_DEC, NULL, 0x0, "Common Session Parameters KeepAlive Time", HFILL }},
2669
2670     { &hf_ldp_tlv_sess_advbit,
2671       { "Session Label Advertisement Discipline", "ldp.msg.tlv.sess.advbit",
2672  FT_BOOLEAN, 8, TFS(&tlv_sess_advbit_vals), 0x80,
2673         "Common Session Parameters Label Advertisement Discipline", HFILL }},
2674
2675     { &hf_ldp_tlv_sess_ldetbit,
2676       { "Session Loop Detection", "ldp.msg.tlv.sess.ldetbit", FT_BOOLEAN, 8, TFS(&tlv_sess_ldetbit_vals), 0x40, "Common Session Parameters Loop Detection", HFILL }},
2677
2678     { &hf_ldp_tlv_sess_pvlim,
2679       { "Session Path Vector Limit", "ldp.msg.tlv.sess.pvlim", FT_UINT8, BASE_DEC, NULL, 0x0, "Common Session Parameters Path Vector Limit", HFILL }},
2680
2681     { &hf_ldp_tlv_sess_mxpdu,
2682       { "Session Max PDU Length", "ldp.msg.tlv.sess.mxpdu", FT_UINT16, BASE_DEC, NULL, 0x0, "Common Session Parameters Max PDU Length", HFILL }},
2683
2684     { &hf_ldp_tlv_sess_rxlsr,
2685       { "Session Receiver LSR Identifier", "ldp.msg.tlv.sess.rxlsr", FT_IPv4, BASE_DEC, NULL, 0x0, "Common Session Parameters LSR Identifier", HFILL }},
2686
2687     { &hf_ldp_tlv_sess_rxls,
2688       { "Session Receiver Label Space Identifier", "ldp.msg.tlv.sess.rxlsr", FT_UINT16, BASE_DEC, NULL, 0x0, "Common Session Parameters Receiver Label Space Identifier", HFILL }},
2689
2690     { &hf_ldp_tlv_sess_atm_merge,
2691       { "Session ATM Merge Parameter", "ldp.msg.tlv.sess.atm.merge", FT_UINT8, BASE_DEC, VALS(tlv_atm_merge_vals), 0xC0, "Merge ATM Session Parameters", HFILL }},
2692
2693     { &hf_ldp_tlv_sess_atm_lr,
2694       { "Number of ATM Label Ranges", "ldp.msg.tlv.sess.atm.lr", FT_UINT8, BASE_DEC, NULL, 0x3C, "Number of Label Ranges", HFILL }},
2695
2696     { &hf_ldp_tlv_sess_atm_dir,
2697       { "Directionality", "ldp.msg.tlv.sess.atm.dir", FT_BOOLEAN, 8, TFS(&tlv_atm_dirbit), 0x02, "Label Directionality", HFILL }},
2698
2699     { &hf_ldp_tlv_sess_atm_minvpi,
2700       { "Minimum VPI", "ldp.msg.tlv.sess.atm.minvpi", FT_UINT16, BASE_DEC, NULL, 0x0FFF, "Minimum VPI", HFILL }},
2701
2702     { &hf_ldp_tlv_sess_atm_minvci,
2703       { "Minimum VCI", "ldp.msg.tlv.sess.atm.minvci", FT_UINT16, BASE_DEC, NULL, 0x0, "Minimum VCI", HFILL }},
2704
2705     { &hf_ldp_tlv_sess_atm_maxvpi,
2706       { "Maximum VPI", "ldp.msg.tlv.sess.atm.maxvpi", FT_UINT16, BASE_DEC, NULL, 0x0FFF, "Maximum VPI", HFILL }},
2707
2708     { &hf_ldp_tlv_sess_atm_maxvci,
2709       { "Maximum VCI", "ldp.msg.tlv.sess.atm.maxvci", FT_UINT16, BASE_DEC, NULL, 0x0, "Maximum VCI", HFILL }},
2710
2711     { &hf_ldp_tlv_sess_fr_merge,
2712       { "Session Frame Relay Merge Parameter", "ldp.msg.tlv.sess.fr.merge", FT_UINT8, BASE_DEC, VALS(tlv_fr_merge_vals), 0xC0, "Merge Frame Relay Session Parameters", HFILL }},
2713
2714     { &hf_ldp_tlv_sess_fr_lr,
2715       { "Number of Frame Relay Label Ranges", "ldp.msg.tlv.sess.fr.lr", FT_UINT8, BASE_DEC, NULL, 0x3C, "Number of Label Ranges", HFILL }},
2716
2717     { &hf_ldp_tlv_sess_fr_dir,
2718       { "Directionality", "ldp.msg.tlv.sess.fr.dir", FT_BOOLEAN, 8, TFS(&tlv_atm_dirbit), 0x02, "Label Directionality", HFILL }},
2719
2720     { &hf_ldp_tlv_sess_fr_len,
2721       { "Number of DLCI bits", "ldp.msg.tlv.sess.fr.len", FT_UINT16, BASE_DEC, VALS(tlv_fr_len_vals), 0x0180, "DLCI Number of bits", HFILL }},
2722
2723     { &hf_ldp_tlv_sess_fr_mindlci,
2724       { "Minimum DLCI", "ldp.msg.tlv.sess.fr.mindlci", FT_UINT24, BASE_DEC, NULL, 0x7FFFFF, "Minimum DLCI", HFILL }},
2725
2726     { &hf_ldp_tlv_sess_fr_maxdlci,
2727       { "Maximum DLCI", "ldp.msg.tlv.sess.fr.maxdlci", FT_UINT24, BASE_DEC, NULL, 0x7FFFFF, "Maximum DLCI", HFILL }},
2728
2729     { &hf_ldp_tlv_ft_sess_flags,
2730       { "Flags", "ldp.msg.tlv.ft_sess.flags", FT_UINT16, BASE_HEX, NULL, 0x0, "FT Session Flags", HFILL }},
2731
2732     { &hf_ldp_tlv_ft_sess_flag_r,
2733       { "R bit", "ldp.msg.tlv.ft_sess.flag_r", FT_BOOLEAN, 16, TFS(&tlv_ft_r), 0x8000, "FT Reconnect Flag", HFILL }},
2734
2735     { &hf_ldp_tlv_ft_sess_flag_res,
2736       { "Reserved", "ldp.msg.tlv.ft_sess.flag_res", FT_UINT16, BASE_HEX, NULL, 0x7FF0, "Reserved bits", HFILL }},
2737
2738     { &hf_ldp_tlv_ft_sess_flag_s,
2739       { "S bit", "ldp.msg.tlv.ft_sess.flag_s", FT_BOOLEAN, 16, TFS(&tlv_ft_s), 0x8, "Save State Flag", HFILL }},
2740
2741     { &hf_ldp_tlv_ft_sess_flag_a,
2742       { "A bit", "ldp.msg.tlv.ft_sess.flag_a", FT_BOOLEAN, 16, TFS(&tlv_ft_a), 0x4, "All-Label protection Required", HFILL }},
2743
2744     { &hf_ldp_tlv_ft_sess_flag_c,
2745       { "C bit", "ldp.msg.tlv.ft_sess.flag_c", FT_BOOLEAN, 16, TFS(&tlv_ft_c), 0x2, "Check-Pointint Flag", HFILL }},
2746
2747     { &hf_ldp_tlv_ft_sess_flag_l,
2748       { "L bit", "ldp.msg.tlv.ft_sess.flag_l", FT_BOOLEAN, 16, TFS(&tlv_ft_l), 0x1, "Learn From network Flag", HFILL }},
2749
2750     { &hf_ldp_tlv_ft_sess_res,
2751       { "Reserved", "ldp.msg.tlv.ft_sess.res", FT_UINT16, BASE_HEX, NULL, 0x0, "Reserved", HFILL }},
2752
2753     { &hf_ldp_tlv_ft_sess_reconn_to,
2754       { "Reconnect Timeout", "ldp.msg.tlv.ft_sess.reconn_to", FT_UINT32, BASE_DEC, NULL, 0x0, "FT Reconnect Timeout", HFILL }},
2755
2756     { &hf_ldp_tlv_ft_sess_recovery_time,
2757       { "Recovery Time", "ldp.msg.tlv.ft_sess.recovery_time", FT_UINT32, BASE_DEC, NULL, 0x0, "Recovery Time", HFILL }},
2758
2759     { &hf_ldp_tlv_ft_ack_sequence_num,
2760       { "FT ACK Sequence Number", "ldp.msg.tlv.ft_ack.sequence_num", FT_UINT32, BASE_HEX, NULL, 0x0, "FT ACK Sequence Number", HFILL }},
2761
2762     { &hf_ldp_tlv_lbl_req_msg_id,
2763       { "Label Request Message ID", "ldp.tlv.lbl_req_msg_id", FT_UINT32, BASE_HEX, NULL, 0x0, "Label Request Message to be aborted", HFILL }},
2764
2765     { &hf_ldp_tlv_vendor_id,
2766       { "Vendor ID", "ldp.msg.tlv.vendor_id", FT_UINT32, BASE_HEX, NULL, 0, "IEEE 802 Assigned Vendor ID", HFILL }},
2767
2768     { &hf_ldp_tlv_experiment_id,
2769       { "Experiment ID", "ldp.msg.tlv.experiment_id", FT_UINT32, BASE_HEX, NULL, 0, "Experiment ID", HFILL }},
2770
2771     { &hf_ldp_tlv_generic_label,
2772       { "Generic Label", "ldp.msg.tlv.generic.label", FT_UINT32, BASE_HEX, NULL, 0x000FFFFF, "Generic Label", HFILL }},
2773
2774     { &hf_ldp_tlv_atm_label_vbits,
2775       { "V-bits", "ldp.msg.tlv.atm.label.vbits", FT_UINT8, BASE_HEX, VALS(tlv_atm_vbits_vals), 0x30, "ATM Label V Bits", HFILL }},
2776
2777     { &hf_ldp_tlv_atm_label_vpi,
2778       { "VPI", "ldp.msg.tlv.atm.label.vpi", FT_UINT16, BASE_DEC, NULL, 0x0FFF, "ATM Label VPI", HFILL }},
2779
2780     { &hf_ldp_tlv_atm_label_vci,
2781       { "VCI", "ldp.msg.tlv.atm.label.vci", FT_UINT16, BASE_DEC, NULL, 0, "ATM Label VCI", HFILL }},
2782
2783     { &hf_ldp_tlv_fr_label_len,
2784       { "Number of DLCI bits", "ldp.msg.tlv.fr.label.len", FT_UINT16, BASE_DEC, VALS(tlv_fr_len_vals), 0x0180, "DLCI Number of bits", HFILL }},
2785
2786     { &hf_ldp_tlv_fr_label_dlci,
2787       { "DLCI", "ldp.msg.tlv.fr.label.dlci", FT_UINT24, BASE_DEC, NULL, 0x7FFFFF, "FRAME RELAY Label DLCI", HFILL }},
2788
2789     { &hf_ldp_tlv_ft_protect_sequence_num,
2790       { "FT Sequence Number", "ldp.msg.tlv.ft_protect.sequence_num", FT_UINT32, BASE_HEX, NULL, 0x0, "FT Sequence Number", HFILL }},
2791
2792     { &hf_ldp_tlv_status_ebit,
2793       { "E Bit", "ldp.msg.tlv.status.ebit", FT_BOOLEAN, 8, TFS(&tlv_status_ebit), 0x80, "Fatal Error Bit", HFILL }},
2794
2795     { &hf_ldp_tlv_status_fbit,
2796       { "F Bit", "ldp.msg.tlv.status.fbit", FT_BOOLEAN, 8, TFS(&tlv_status_fbit), 0x40, "Forward Bit", HFILL }},
2797
2798     { &hf_ldp_tlv_status_data,
2799       { "Status Data", "ldp.msg.tlv.status.data", FT_UINT32, BASE_HEX, VALS(tlv_status_data), 0x3FFFFFFF, "Status Data", HFILL }},
2800
2801     { &hf_ldp_tlv_status_msg_id,
2802       { "Message ID", "ldp.msg.tlv.status.msg.id", FT_UINT32, BASE_HEX, NULL, 0x0, "Identifies peer message to which Status TLV refers", HFILL }},
2803
2804     { &hf_ldp_tlv_status_msg_type,
2805       { "Message Type", "ldp.msg.tlv.status.msg.type", FT_UINT16, BASE_HEX, VALS(ldp_message_types), 0x0, "Type of peer message to which Status TLV refers", HFILL }},
2806
2807     { &hf_ldp_tlv_extstatus_data,
2808       { "Extended Status Data", "ldp.msg.tlv.extstatus.data", FT_UINT32, BASE_HEX, NULL, 0x0, "Extended Status Data", HFILL }},
2809
2810     { &hf_ldp_tlv_returned_version,
2811       { "Returned PDU Version", "ldp.msg.tlv.returned.version", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Version Number", HFILL }},
2812
2813     { &hf_ldp_tlv_returned_pdu_len,
2814       { "Returned PDU Length", "ldp.msg.tlv.returned.pdu_len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP PDU Length", HFILL }},
2815
2816     { &hf_ldp_tlv_returned_lsr,
2817       { "Returned PDU LSR ID", "ldp.msg.tlv.returned.ldpid.lsr", FT_IPv4, BASE_DEC, NULL, 0x0, "LDP Label Space Router ID", HFILL }},
2818
2819     { &hf_ldp_tlv_returned_ls_id,
2820       { "Returned PDU Label Space ID", "ldp.msg.tlv.returned.ldpid.lsid", FT_UINT16, BASE_HEX, NULL, 0x0, "LDP Label Space ID", HFILL }},
2821
2822     { &hf_ldp_tlv_returned_msg_ubit,
2823       { "Returned Message Unknown bit", "ldp.msg.tlv.returned.msg.ubit", FT_BOOLEAN, BASE_HEX, TFS(&ldp_message_ubit), 0x80, "Message Unknown bit", HFILL }},
2824
2825     { &hf_ldp_tlv_returned_msg_type,
2826       { "Returned Message Type", "ldp.msg.tlv.returned.msg.type", FT_UINT16, BASE_HEX, VALS(ldp_message_types), 0x7FFF, "LDP message type", HFILL }},
2827
2828     { &hf_ldp_tlv_returned_msg_len,
2829       { "Returned Message Length", "ldp.msg.tlv.returned.msg.len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Message Length (excluding message type and len)", HFILL }},
2830
2831     { &hf_ldp_tlv_returned_msg_id,
2832       { "Returned Message ID", "ldp.msg.tlv.returned.msg.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Message ID", HFILL }},
2833
2834     { &hf_ldp_tlv_mac,
2835       { "MAC address", "ldp.msg.tlv.mac", FT_ETHER, BASE_NONE, NULL, 0x0, "MAC address", HFILL}},
2836
2837     {&hf_ldp_tlv_fec_vc_controlword,
2838      {"C-bit", "ldp.msg.tlv.fec.vc.controlword", FT_BOOLEAN, 8, TFS(&fec_vc_cbit), 0x80, "Control Word Present", HFILL }},
2839
2840     {&hf_ldp_tlv_fec_vc_vctype,
2841      {"VC Type", "ldp.msg.tlv.fec.vc.vctype", FT_UINT16, BASE_HEX, VALS(fec_vc_types_vals), 0x7FFF, "Virtual Circuit Type", HFILL }},
2842
2843     {&hf_ldp_tlv_fec_vc_infolength,
2844      {"VC Info Length", "ldp.msg.tlv.fec.vc.infolength", FT_UINT8, BASE_DEC, NULL, 0x0, "VC FEC Info Length", HFILL }},
2845
2846     {&hf_ldp_tlv_fec_vc_groupid,
2847      {"Group ID", "ldp.msg.tlv.fec.vc.groupid", FT_UINT32, BASE_DEC, NULL, 0x0, "VC FEC Group ID", HFILL }},
2848
2849     {&hf_ldp_tlv_fec_vc_vcid,
2850      {"VC ID", "ldp.msg.tlv.fec.vc.vcid", FT_UINT32, BASE_DEC, NULL, 0x0, "VC FEC VCID", HFILL }},
2851
2852     {&hf_ldp_tlv_fec_vc_intparam_length,
2853      {"Length", "ldp.msg.tlv.fec.vc.intparam.length", FT_UINT8, BASE_DEC, NULL, 0x0, "VC FEC Interface Paramater Length", HFILL }},
2854
2855     {&hf_ldp_tlv_fec_vc_intparam_mtu,
2856      {"MTU", "ldp.msg.tlv.fec.vc.intparam.mtu", FT_UINT16, BASE_DEC, NULL, 0x0, "VC FEC Interface Paramater MTU", HFILL }},
2857
2858     {&hf_ldp_tlv_fec_vc_intparam_tdmbps,
2859      {"BPS", "ldp.msg.tlv.fec.vc.intparam.tdmbps", FT_UINT32, BASE_DEC, NULL, 0x0, "VC FEC Interface Parameter CEP/TDM bit-rate", HFILL }},
2860
2861     {&hf_ldp_tlv_fec_vc_intparam_id,
2862      {"ID", "ldp.msg.tlv.fec.vc.intparam.id", FT_UINT8, BASE_HEX, VALS(fec_vc_interfaceparm), 0x0, "VC FEC Interface Paramater ID", HFILL }},
2863
2864     {&hf_ldp_tlv_fec_vc_intparam_maxcatmcells,
2865      {"Number of Cells", "ldp.msg.tlv.fec.vc.intparam.maxatm", FT_UINT16, BASE_DEC, NULL, 0x0, "VC FEC Interface Param Max ATM Concat Cells", HFILL }},
2866
2867     { &hf_ldp_tlv_fec_vc_intparam_desc,
2868       { "Description", "ldp.msg.tlv.fec.vc.intparam.desc", FT_STRING, BASE_DEC, NULL, 0, "VC FEC Interface Description", HFILL }},
2869
2870     { &hf_ldp_tlv_fec_vc_intparam_cepbytes,
2871      {"Payload Bytes", "ldp.msg.tlv.fec.vc.intparam.cepbytes", FT_UINT16, BASE_DEC, NULL, 0x0, "VC FEC Interface Param CEP/TDM Payload Bytes", HFILL }},
2872
2873     { &hf_ldp_tlv_fec_vc_intparam_cepopt_ais,
2874      {"AIS", "ldp.msg.tlv.fec.vc.intparam.cepopt_ais", FT_BOOLEAN, 16, NULL, 0x8000, "VC FEC Interface Param CEP Option AIS", HFILL }},
2875
2876     { &hf_ldp_tlv_fec_vc_intparam_cepopt_une,
2877      {"UNE", "ldp.msg.tlv.fec.vc.intparam.cepopt_une", FT_BOOLEAN, 16, NULL, 0x4000, "VC FEC Interface Param CEP Option Unequipped", HFILL }},
2878
2879     { &hf_ldp_tlv_fec_vc_intparam_cepopt_rtp,
2880      {"RTP", "ldp.msg.tlv.fec.vc.intparam.cepopt_rtp", FT_BOOLEAN, 16, NULL, 0x2000, "VC FEC Interface Param CEP Option RTP Header", HFILL }},
2881
2882     { &hf_ldp_tlv_fec_vc_intparam_cepopt_ebm,
2883      {"EBM", "ldp.msg.tlv.fec.vc.intparam.cepopt_ebm", FT_BOOLEAN, 16, NULL, 0x1000, "VC FEC Interface Param CEP Option EBM Header", HFILL }},
2884
2885     { &hf_ldp_tlv_fec_vc_intparam_cepopt_mah,
2886      {"MAH", "ldp.msg.tlv.fec.vc.intparam.cepopt_mah", FT_BOOLEAN, 16, NULL, 0x0800, "VC FEC Interface Param CEP Option MPLS Adaptation header", HFILL }},
2887
2888     { &hf_ldp_tlv_fec_vc_intparam_cepopt_res,
2889      {"Reserved", "ldp.msg.tlv.fec.vc.intparam.cepopt_res", FT_UINT16, BASE_HEX, NULL , 0x07E0, "VC FEC Interface Param CEP Option Reserved", HFILL }},
2890
2891     { &hf_ldp_tlv_fec_vc_intparam_cepopt_ceptype,
2892      {"CEP Type", "ldp.msg.tlv.fec.vc.intparam.cepopt_ceptype", FT_UINT16, BASE_HEX, VALS(fec_vc_ceptype_vals), 0x001C, "VC FEC Interface Param CEP Option CEP Type", HFILL }},
2893
2894     { &hf_ldp_tlv_fec_vc_intparam_cepopt_t3,
2895      {"Async T3", "ldp.msg.tlv.fec.vc.intparam.cepopt_t3", FT_BOOLEAN, 16, NULL, 0x0002, "VC FEC Interface Param CEP Option Async T3", HFILL }},
2896
2897     { &hf_ldp_tlv_fec_vc_intparam_cepopt_e3,
2898      {"Async E3", "ldp.msg.tlv.fec.vc.intparam.cepopt_e3", FT_BOOLEAN, 16, NULL, 0x0001, "VC FEC Interface Param CEP Option Async E3", HFILL }},
2899
2900     { &hf_ldp_tlv_fec_vc_intparam_vlanid,
2901       { "VLAN Id", "ldp.msg.tlv.fec.vc.intparam.vlanid", FT_UINT16, BASE_DEC, NULL, 0x0, "VC FEC Interface Param VLAN Id", HFILL }},
2902
2903     {&hf_ldp_tlv_fec_vc_intparam_dlcilen,
2904      {"DLCI Length", "ldp.msg.tlv.fec.vc.intparam.dlcilen", FT_UINT16, BASE_DEC, NULL, 0x0, "VC FEC Interface Parameter Frame-Relay DLCI Length", HFILL }},
2905
2906     {&hf_ldp_tlv_fec_vc_intparam_fcslen,
2907      {"FCS Length", "ldp.msg.tlv.fec.vc.intparam.fcslen", FT_UINT16, BASE_DEC, NULL, 0x0, "VC FEC Interface Paramater FCS Length", HFILL }},
2908
2909     {&hf_ldp_tlv_fec_vc_intparam_tdmopt_r,
2910      {"R Bit", "ldp.msg.tlv.fec.vc.intparam.tdmopt_r", FT_BOOLEAN, 16, TFS(&fec_vc_tdmopt_r), 0x8000, "VC FEC Interface Param TDM Options RTP Header", HFILL }},
2911
2912     {&hf_ldp_tlv_fec_vc_intparam_tdmopt_d,
2913      {"D Bit", "ldp.msg.tlv.fec.vc.intparam.tdmopt_d", FT_BOOLEAN, 16, TFS(&fec_vc_tdmopt_d), 0x4000, "VC FEC Interface Param TDM Options Dynamic Timestamp", HFILL }},
2914
2915     {&hf_ldp_tlv_fec_vc_intparam_tdmopt_f,
2916      {"F Bit", "ldp.msg.tlv.fec.vc.intparam.tdmopt_f", FT_BOOLEAN, 16, TFS(&fec_vc_tdmopt_f), 0x2000, "VC FEC Interface Param TDM Options Flavor bit", HFILL }},
2917
2918     {&hf_ldp_tlv_fec_vc_intparam_tdmopt_res1,
2919      {"RSVD-1", "ldp.msg.tlv.fec.vc.intparam.tdmopt_res1", FT_UINT16, BASE_HEX, NULL, 0x1FFF, "VC FEC Interface Param TDM Options Reserved", HFILL }},
2920
2921     {&hf_ldp_tlv_fec_vc_intparam_tdmopt_pt,
2922      {"PT", "ldp.msg.tlv.fec.vc.intparam.tdmopt_pt", FT_UINT8, BASE_DEC, NULL, 0x7F, "VC FEC Interface Param TDM Options Payload Type", HFILL }},
2923
2924     {&hf_ldp_tlv_fec_vc_intparam_tdmopt_res2,
2925      {"RSVD-2", "ldp.msg.tlv.fec.vc.intparam.tdmopt_res2", FT_UINT8, BASE_HEX, NULL, 0x00, "VC FEC Interface Param TDM Options Reserved", HFILL }},
2926
2927     {&hf_ldp_tlv_fec_vc_intparam_tdmopt_freq,
2928      {"FREQ", "ldp.msg.tlv.fec.vc.intparam.tdmopt_freq", FT_UINT16, BASE_DEC, NULL, 0x00, "VC FEC Interface Param TDM Options Frequency", HFILL }},
2929
2930     {&hf_ldp_tlv_fec_vc_intparam_tdmopt_ssrc,
2931      {"SSRC", "ldp.msg.tlv.fec.vc.intparam.tdmopt_ssrc", FT_UINT32, BASE_HEX, NULL, 0x00, "VC FEC Interface Param TDM Options SSRC", HFILL }},
2932
2933     {&hf_ldp_tlv_fec_vc_intparam_vccv_cctype_cw,
2934      {"PWE3 Control Word", "ldp.msg.tlv.fec.vc.intparam.vccv.cctype_cw", FT_BOOLEAN, 8, NULL, 0x01, "VC FEC Interface Param VCCV CC Type PWE3 CW", HFILL }},
2935
2936     {&hf_ldp_tlv_fec_vc_intparam_vccv_cctype_mplsra,
2937      {"MPLS Router Alert", "ldp.msg.tlv.fec.vc.intparam.vccv.cctype_mplsra", FT_BOOLEAN, 8, NULL, 0x02, "VC FEC Interface Param VCCV CC Type MPLS Router Alert", HFILL }},
2938
2939     {&hf_ldp_tlv_fec_vc_intparam_vccv_cctype_ttl1,
2940      {"MPLS Inner Label TTL = 1", "ldp.msg.tlv.fec.vc.intparam.vccv.cctype_ttl1", FT_BOOLEAN, 8, NULL, 0x04, "VC FEC Interface Param VCCV CC Type Inner Label TTL 1", HFILL }},
2941
2942     {&hf_ldp_tlv_fec_vc_intparam_vccv_cvtype_icmpping,
2943      {"ICMP Ping", "ldp.msg.tlv.fec.vc.intparam.vccv.cvtype_icmpping", FT_BOOLEAN, 8, NULL, 0x01, "VC FEC Interface Param VCCV CV Type ICMP Ping", HFILL }},
2944
2945     {&hf_ldp_tlv_fec_vc_intparam_vccv_cvtype_lspping,
2946      {"LSP Ping", "ldp.msg.tlv.fec.vc.intparam.vccv.cvtype_lspping", FT_BOOLEAN, 8, NULL, 0x02, "VC FEC Interface Param VCCV CV Type LSP Ping", HFILL }},
2947
2948     {&hf_ldp_tlv_fec_vc_intparam_vccv_cvtype_bfd,
2949      {"BFD", "ldp.msg.tlv.fec.vc.intparam.vccv.cvtype_bfd", FT_BOOLEAN, 8, NULL, 0x04, "VC FEC Interface Param VCCV CV Type BFD", HFILL }},
2950
2951
2952     { &hf_ldp_tlv_lspid_act_flg,
2953       { "Action Indicator Flag", "ldp.msg.tlv.lspid.actflg", FT_UINT16, BASE_HEX, VALS(ldp_act_flg_vals), 0x000F, "Action Indicator Flag", HFILL}},
2954
2955     { &hf_ldp_tlv_lspid_cr_lsp,
2956       { "Local CR-LSP ID", "ldp.msg.tlv.lspid.locallspid", FT_UINT16, BASE_HEX, NULL, 0x0, "Local CR-LSP ID", HFILL}},
2957
2958     { &hf_ldp_tlv_lspid_ldpid,
2959       { "Ingress LSR Router ID", "ldp.msg.tlv.lspid.lsrid", FT_IPv4, BASE_DEC, NULL, 0x0, "Ingress LSR Router ID", HFILL}},
2960
2961     { &hf_ldp_tlv_er_hop_loose,
2962       { "Loose route bit", "ldp.msg.tlv.er_hop.loose", FT_UINT24, BASE_HEX, VALS(ldp_loose_vals), 0x800000, "Loose route bit", HFILL}},
2963
2964     { &hf_ldp_tlv_er_hop_prelen,
2965       { "Prefix length", "ldp.msg.tlv.er_hop.prefixlen", FT_UINT8, BASE_DEC, NULL, 0x0, "Prefix len", HFILL}},
2966
2967     { &hf_ldp_tlv_er_hop_prefix4,
2968       { "IPv4 Address", "ldp.msg.tlv.er_hop.prefix4", FT_IPv4, BASE_DEC, NULL, 0x0, "IPv4 Address", HFILL}},
2969    { &hf_ldp_tlv_er_hop_prefix6,
2970      { "IPv6 Address", "ldp.msg.tlv.er_hop.prefix6", FT_IPv6, BASE_DEC, NULL, 0x0, "IPv6 Address", HFILL}},
2971
2972     { &hf_ldp_tlv_er_hop_as,
2973       { "AS Number", "ldp.msg.tlv.er_hop.as", FT_UINT16, BASE_DEC, NULL, 0x0, "AS Number", HFILL}},
2974
2975     { &hf_ldp_tlv_er_hop_cr_lsp,
2976       { "Local CR-LSP ID", "ldp.msg.tlv.er_hop.locallspid", FT_UINT16, BASE_DEC, NULL, 0x0, "Local CR-LSP ID", HFILL}},
2977
2978     { &hf_ldp_tlv_er_hop_ldpid,
2979       { "Local CR-LSP ID", "ldp.msg.tlv.er_hop.lsrid", FT_IPv4, BASE_DEC, NULL, 0x0, "Local CR-LSP ID", HFILL}},
2980
2981     { &hf_ldp_tlv_flags_reserv,
2982       { "Reserved", "ldp.msg.tlv.flags_reserv", FT_UINT8, BASE_HEX, NULL, 0xC0, "Reserved", HFILL}},
2983
2984     { &hf_ldp_tlv_flags_pdr,
2985       { "PDR", "ldp.msg.tlv.flags_pdr", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x1, "PDR negotiability flag", HFILL}},
2986
2987     { &hf_ldp_tlv_flags_pbs,
2988       { "PBS", "ldp.msg.tlv.flags_pbs", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x2, "PBS negotiability flag", HFILL}},
2989
2990     { &hf_ldp_tlv_flags_cdr,
2991       { "CDR", "ldp.msg.tlv.flags_cdr", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x4, "CDR negotiability flag", HFILL}},
2992
2993     { &hf_ldp_tlv_flags_cbs,
2994       { "CBS", "ldp.msg.tlv.flags_cbs", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x8, "CBS negotiability flag", HFILL}},
2995
2996     { &hf_ldp_tlv_flags_ebs,
2997       { "EBS", "ldp.msg.tlv.flags_ebs", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x10, "EBS negotiability flag", HFILL}},
2998
2999     { &hf_ldp_tlv_flags_weight,
3000       { "Weight", "ldp.msg.tlv.flags_weight", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x20, "Weight negotiability flag", HFILL}},
3001
3002     { &hf_ldp_tlv_frequency,
3003       { "Frequency", "ldp.msg.tlv.frequency", FT_UINT8, BASE_DEC, VALS(freq_values), 0, "Frequency", HFILL}},
3004
3005     { &hf_ldp_tlv_weight,
3006       { "Weight", "ldp.msg.tlv.weight", FT_UINT8, BASE_DEC, NULL, 0, "Weight of the CR-LSP", HFILL}},
3007
3008     { &hf_ldp_tlv_pdr,
3009       { "PDR", "ldp.msg.tlv.pdr", FT_DOUBLE, BASE_NONE, NULL, 0, "Peak Data Rate", HFILL}},
3010
3011     { &hf_ldp_tlv_pbs,
3012       { "PBS", "ldp.msg.tlv.pbs", FT_DOUBLE, BASE_NONE, NULL, 0, "Peak Burst Size", HFILL}},
3013
3014     { &hf_ldp_tlv_cdr,
3015       { "CDR", "ldp.msg.tlv.cdr", FT_DOUBLE, BASE_NONE, NULL, 0, "Committed Data Rate", HFILL}},
3016
3017     { &hf_ldp_tlv_cbs,
3018       { "CBS", "ldp.msg.tlv.cbs", FT_DOUBLE, BASE_NONE, NULL, 0, "Committed Burst Size", HFILL}},
3019
3020     { &hf_ldp_tlv_ebs,
3021       { "EBS", "ldp.msg.tlv.ebs", FT_DOUBLE, BASE_NONE, NULL, 0, "Excess Burst Size", HFILL}},
3022
3023     { &hf_ldp_tlv_set_prio,
3024       { "Set Prio", "ldp.msg.tlv.set_prio", FT_UINT8, BASE_DEC, NULL, 0, "LSP setup priority", HFILL}},
3025
3026     { &hf_ldp_tlv_hold_prio,
3027       { "Hold Prio", "ldp.msg.tlv.hold_prio", FT_UINT8, BASE_DEC, NULL, 0, "LSP hold priority", HFILL}},
3028
3029     { &hf_ldp_tlv_route_pinning,
3030       { "Route Pinning", "ldp.msg.tlv.route_pinning", FT_UINT32, BASE_DEC, VALS(route_pinning_vals), 0x80000000, "Route Pinning", HFILL}},
3031
3032     { &hf_ldp_tlv_resource_class,
3033       { "Resource Class", "ldp.msg.tlv.resource_class", FT_UINT32, BASE_HEX, NULL, 0, "Resource Class (Color)", HFILL}},
3034
3035     { &hf_ldp_tlv_diffserv,
3036       { "Diff-Serv TLV", "ldp.msg.tlv.diffserv", FT_NONE, BASE_NONE, NULL,
3037         0, "Diffserv TLV", HFILL}},
3038
3039     { &hf_ldp_tlv_diffserv_type,
3040       { "LSP Type", "ldp.msg.tlv.diffserv.type", FT_UINT8, BASE_DEC,
3041         VALS(diffserv_type_vals), 0x80, "LSP Type", HFILL}},
3042
3043     { &hf_ldp_tlv_diffserv_mapnb,
3044       { "MAPnb", "ldp.msg.tlv.diffserv.mapnb", FT_UINT8, BASE_DEC, NULL,
3045         0, MAPNB_DESCRIPTION, HFILL}},
3046
3047     { &hf_ldp_tlv_diffserv_map,
3048       { "MAP", "ldp.msg.tlv.diffserv.map", FT_NONE, BASE_NONE, NULL,
3049         0, MAP_DESCRIPTION, HFILL}},
3050
3051     { &hf_ldp_tlv_diffserv_map_exp,
3052       { "EXP", "ldp.msg.tlv.diffserv.map.exp", FT_UINT8, BASE_DEC, NULL,
3053         0, EXP_DESCRIPTION, HFILL}},
3054
3055     { &hf_ldp_tlv_diffserv_phbid,
3056       { "PHBID", "ldp.msg.tlv.diffserv.phbid", FT_NONE, BASE_NONE, NULL,
3057         0, PHBID_DESCRIPTION, HFILL}},
3058
3059     { &hf_ldp_tlv_diffserv_phbid_dscp,
3060       { "DSCP", "ldp.msg.tlv.diffserv.phbid.dscp", FT_UINT16, BASE_DEC,
3061         NULL, PHBID_DSCP_MASK, PHBID_DSCP_DESCRIPTION, HFILL}},
3062
3063     { &hf_ldp_tlv_diffserv_phbid_code,
3064       { "PHB id code", "ldp.msg.tlv.diffserv.phbid.code", FT_UINT16, BASE_DEC,
3065         NULL, PHBID_CODE_MASK, PHBID_CODE_DESCRIPTION, HFILL}},
3066
3067     { &hf_ldp_tlv_diffserv_phbid_bit14,
3068       { "Bit 14", "ldp.msg.tlv.diffserv.phbid.bit14", FT_UINT16, BASE_DEC,
3069         VALS(phbid_bit14_vals), PHBID_BIT14_MASK, PHBID_BIT14_DESCRIPTION, HFILL}},
3070
3071     { &hf_ldp_tlv_diffserv_phbid_bit15,
3072       { "Bit 15", "ldp.msg.tlv.diffserv.phbid.bit15", FT_UINT16, BASE_DEC,
3073         VALS(phbid_bit15_vals), PHBID_BIT15_MASK, PHBID_BIT15_DESCRIPTION, HFILL}}
3074
3075   };
3076
3077   static gint *ett[] = {
3078     &ett_ldp,
3079     &ett_ldp_header,
3080     &ett_ldp_ldpid,
3081     &ett_ldp_message,
3082     &ett_ldp_tlv,
3083     &ett_ldp_tlv_val,
3084     &ett_ldp_tlv_ft_flags,
3085     &ett_ldp_fec,
3086     &ett_ldp_fec_vc_interfaceparam,
3087     &ett_ldp_fec_vc_interfaceparam_cepopt,
3088     &ett_ldp_fec_vc_interfaceparam_vccvtype,
3089     &ett_ldp_diffserv_map,
3090     &ett_ldp_diffserv_map_phbid
3091   };
3092   module_t *ldp_module;
3093
3094   proto_ldp = proto_register_protocol("Label Distribution Protocol",
3095                                        "LDP", "ldp");
3096
3097   proto_register_field_array(proto_ldp, hf, array_length(hf));
3098   proto_register_subtree_array(ett, array_length(ett));
3099
3100   /* Register our configuration options for , particularly our port */
3101
3102   ldp_module = prefs_register_protocol(proto_ldp, proto_reg_handoff_ldp);
3103
3104   prefs_register_uint_preference(ldp_module, "tcp.port", "LDP TCP Port",
3105                                  "Set the TCP port for messages (if other"
3106                                  " than the default of 646)",
3107                                  10, &global_ldp_tcp_port);
3108
3109   prefs_register_uint_preference(ldp_module, "udp.port", "LDP UDP Port",
3110                                  "Set the UDP port for messages (if other"
3111                                  " than the default of 646)",
3112                                  10, &global_ldp_udp_port);
3113
3114   prefs_register_bool_preference(ldp_module, "desegment_ldp_messages",
3115     "Reassemble LDP messages spanning multiple TCP segments",
3116     "Whether the LDP dissector should reassemble messages spanning multiple TCP segments."
3117     " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
3118     &ldp_desegment);
3119 }
3120
3121 /* The registration hand-off routine */
3122 void
3123 proto_reg_handoff_ldp(void)
3124 {
3125   static gboolean ldp_prefs_initialized = FALSE;
3126   static dissector_handle_t ldp_tcp_handle, ldp_handle;
3127
3128   if (!ldp_prefs_initialized) {
3129
3130     ldp_tcp_handle = new_create_dissector_handle(dissect_ldp_tcp, proto_ldp);
3131     ldp_handle = new_create_dissector_handle(dissect_ldp, proto_ldp);
3132
3133     ldp_prefs_initialized = TRUE;
3134
3135   }
3136   else {
3137
3138     dissector_delete("tcp.port", tcp_port, ldp_tcp_handle);
3139     dissector_delete("udp.port", udp_port, ldp_handle);
3140
3141   }
3142
3143   /* Set our port number for future use */
3144
3145   tcp_port = global_ldp_tcp_port;
3146   udp_port = global_ldp_udp_port;
3147
3148   dissector_add("tcp.port", global_ldp_tcp_port, ldp_tcp_handle);
3149   dissector_add("udp.port", global_ldp_udp_port, ldp_handle);
3150
3151 }