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