Replace the types from sys/types.h and netinet/in.h by their glib.h
[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.40 2002/08/02 23:35:53 jmayer 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
47 #define TCP_PORT_LDP 646
48 #define UDP_PORT_LDP 646
49
50 void proto_reg_handoff_ldp(void);
51
52 static int proto_ldp = -1;
53
54 /* Delete the following if you do not use it, or add to it if you need */
55 static int hf_ldp_req = -1;
56 static int hf_ldp_rsp = -1;
57 static int hf_ldp_version = -1;
58 static int hf_ldp_pdu_len = -1;
59 static int hf_ldp_lsr = -1;
60 static int hf_ldp_ls_id = -1;
61 static int hf_ldp_msg_ubit = -1;
62 static int hf_ldp_msg_type = -1;
63 static int hf_ldp_msg_len = -1;
64 static int hf_ldp_msg_id = -1;
65 static int hf_ldp_msg_vendor_id = -1;
66 static int hf_ldp_msg_experiment_id = -1;
67 static int hf_ldp_tlv_value = -1;
68 static int hf_ldp_tlv_type = -1;
69 static int hf_ldp_tlv_unknown = -1;
70 static int hf_ldp_tlv_len = -1;
71 static int hf_ldp_tlv_val_hold = -1;
72 static int hf_ldp_tlv_val_target = -1;
73 static int hf_ldp_tlv_val_request = -1;
74 static int hf_ldp_tlv_val_res = -1;
75 static int hf_ldp_tlv_ipv4_taddr = -1;
76 static int hf_ldp_tlv_config_seqno = -1;
77 static int hf_ldp_tlv_ipv6_taddr = -1;
78 static int hf_ldp_tlv_fec_wc = -1;
79 static int hf_ldp_tlv_fec_af = -1;
80 static int hf_ldp_tlv_fec_len = -1;
81 static int hf_ldp_tlv_fec_pfval = -1;
82 static int hf_ldp_tlv_fec_hoval = -1;
83 static int hf_ldp_tlv_addrl_addr_family = -1;
84 static int hf_ldp_tlv_addrl_addr = -1;
85 static int hf_ldp_tlv_hc_value = -1;
86 static int hf_ldp_tlv_pv_lsrid = -1;
87 static int hf_ldp_tlv_generic_label = -1;
88 static int hf_ldp_tlv_atm_label_vbits = -1;
89 static int hf_ldp_tlv_atm_label_vpi = -1;
90 static int hf_ldp_tlv_atm_label_vci = -1;
91 static int hf_ldp_tlv_fr_label_len = -1;
92 static int hf_ldp_tlv_fr_label_dlci = -1;
93 static int hf_ldp_tlv_status_ebit = -1;
94 static int hf_ldp_tlv_status_fbit = -1;
95 static int hf_ldp_tlv_status_data = -1;
96 static int hf_ldp_tlv_status_msg_id = -1;
97 static int hf_ldp_tlv_status_msg_type = -1;
98 static int hf_ldp_tlv_extstatus_data = -1;
99 static int hf_ldp_tlv_returned_version = -1;
100 static int hf_ldp_tlv_returned_pdu_len = -1;
101 static int hf_ldp_tlv_returned_lsr = -1;
102 static int hf_ldp_tlv_returned_ls_id = -1;
103 static int hf_ldp_tlv_returned_msg_ubit = -1;
104 static int hf_ldp_tlv_returned_msg_type = -1;
105 static int hf_ldp_tlv_returned_msg_len = -1;
106 static int hf_ldp_tlv_returned_msg_id = -1;
107 static int hf_ldp_tlv_sess_ver = -1;
108 static int hf_ldp_tlv_sess_ka = -1;
109 static int hf_ldp_tlv_sess_advbit = -1;
110 static int hf_ldp_tlv_sess_ldetbit = -1;
111 static int hf_ldp_tlv_sess_pvlim = -1;
112 static int hf_ldp_tlv_sess_mxpdu = -1;
113 static int hf_ldp_tlv_sess_rxlsr = -1;
114 static int hf_ldp_tlv_sess_rxls = -1;
115 static int hf_ldp_tlv_sess_atm_merge = -1;
116 static int hf_ldp_tlv_sess_atm_lr = -1;
117 static int hf_ldp_tlv_sess_atm_dir = -1;
118 static int hf_ldp_tlv_sess_atm_minvpi = -1;
119 static int hf_ldp_tlv_sess_atm_maxvpi = -1;
120 static int hf_ldp_tlv_sess_atm_minvci = -1;
121 static int hf_ldp_tlv_sess_atm_maxvci = -1;
122 static int hf_ldp_tlv_sess_fr_merge = -1;
123 static int hf_ldp_tlv_sess_fr_lr = -1;
124 static int hf_ldp_tlv_sess_fr_dir = -1;
125 static int hf_ldp_tlv_sess_fr_len = -1;
126 static int hf_ldp_tlv_sess_fr_mindlci = -1;
127 static int hf_ldp_tlv_sess_fr_maxdlci = -1;
128 static int hf_ldp_tlv_lbl_req_msg_id = -1;
129 static int hf_ldp_tlv_vendor_id = -1;
130 static int hf_ldp_tlv_experiment_id = -1;
131 static int hf_ldp_tlv_fec_vc_controlword = -1;
132 static int hf_ldp_tlv_fec_vc_vctype = -1;
133 static int hf_ldp_tlv_fec_vc_infolength = -1;
134 static int hf_ldp_tlv_fec_vc_groupid = -1;
135 static int hf_ldp_tlv_fec_vc_vcid = -1; 
136 static int hf_ldp_tlv_fec_vc_intparam_length = -1;
137 static int hf_ldp_tlv_fec_vc_intparam_mtu = -1;
138 static int hf_ldp_tlv_fec_vc_intparam_id = -1;
139 static int hf_ldp_tlv_fec_vc_intparam_maxcatmcells = -1;
140 static int hf_ldp_tlv_fec_vc_intparam_desc = -1;
141 static int hf_ldp_tlv_fec_vc_intparam_cembytes = -1;
142 static int hf_ldp_tlv_lspid_act_flg = -1;
143 static int hf_ldp_tlv_lspid_cr_lsp = -1;
144 static int hf_ldp_tlv_lspid_ldpid = -1;
145 static int hf_ldp_tlv_er_hop_loose = -1;
146 static int hf_ldp_tlv_er_hop_prelen = -1;
147 static int hf_ldp_tlv_er_hop_prefix4 = -1;
148 static int hf_ldp_tlv_er_hop_prefix6 = -1;
149 static int hf_ldp_tlv_er_hop_as = -1;
150 static int hf_ldp_tlv_er_hop_cr_lsp = -1;
151 static int hf_ldp_tlv_er_hop_ldpid = -1;
152 static int hf_ldp_tlv_flags_reserv = -1;
153 static int hf_ldp_tlv_flags_weight = -1;
154 static int hf_ldp_tlv_flags_ebs = -1;
155 static int hf_ldp_tlv_flags_cbs = -1;
156 static int hf_ldp_tlv_flags_cdr = -1;
157 static int hf_ldp_tlv_flags_pbs = -1;
158 static int hf_ldp_tlv_flags_pdr = -1;
159 static int hf_ldp_tlv_frequency = -1;
160 static int hf_ldp_tlv_pdr = -1;
161 static int hf_ldp_tlv_pbs = -1;
162 static int hf_ldp_tlv_cdr = -1;
163 static int hf_ldp_tlv_cbs = -1;
164 static int hf_ldp_tlv_ebs = -1;
165 static int hf_ldp_tlv_weight = -1;
166 static int hf_ldp_tlv_set_prio = -1;
167 static int hf_ldp_tlv_hold_prio = -1;
168 static int hf_ldp_tlv_route_pinning = -1;
169 static int hf_ldp_tlv_resource_class = -1;
170 static int ett_ldp = -1;
171 static int ett_ldp_header = -1;
172 static int ett_ldp_ldpid = -1;
173 static int ett_ldp_message = -1;
174 static int ett_ldp_tlv = -1;
175 static int ett_ldp_tlv_val = -1;
176 static int ett_ldp_fec = -1;
177 static int ett_ldp_fec_vc_interfaceparam = -1;
178
179 static int tcp_port = 0;
180 static int udp_port = 0;
181
182 /* desegmentation of LDP over TCP */
183 static gboolean ldp_desegment = FALSE;
184
185 /* Add your functions here */
186
187 static int global_ldp_tcp_port = TCP_PORT_LDP;
188 static int global_ldp_udp_port = UDP_PORT_LDP;
189
190 /*
191  * The following define all the TLV types I know about
192  */
193
194 #define TLV_FEC                    0x0100
195 #define TLV_ADDRESS_LIST           0x0101
196 #define TLV_HOP_COUNT              0x0103
197 #define TLV_PATH_VECTOR            0x0104
198 #define TLV_GENERIC_LABEL          0x0200
199 #define TLV_ATM_LABEL              0x0201
200 #define TLV_FRAME_LABEL            0x0202
201 #define TLV_STATUS                 0x0300
202 #define TLV_EXTENDED_STATUS        0x0301
203 #define TLV_RETURNED_PDU           0x0302
204 #define TLV_RETURNED_MESSAGE       0x0303
205 #define TLV_COMMON_HELLO_PARMS     0x0400
206 #define TLV_IPV4_TRANSPORT_ADDRESS 0x0401
207 #define TLV_CONFIGURATION_SEQNO    0x0402
208 #define TLV_IPV6_TRANSPORT_ADDRESS 0x0403
209 #define TLV_COMMON_SESSION_PARMS   0x0500
210 #define TLV_ATM_SESSION_PARMS      0x0501
211 #define TLV_FRAME_RELAY_SESSION_PARMS 0x0502
212 #define TLV_LABEL_REQUEST_MESSAGE_ID 0x0600
213 #define TLV_ER                     0x0800
214 #define TLV_ER_HOP_IPV4            0x0801
215 #define TLV_ER_HOP_IPV6            0x0802
216 #define TLV_ER_HOP_AS              0x0803
217 #define TLV_ER_HOP_LSPID           0x0804
218 #define TLV_TRAFFIC_PARAM          0x0810
219 #define TLV_PREEMPTION             0x0820
220 #define TLV_LSPID                  0x0821
221 #define TLV_RESOURCE_CLASS         0x0822
222 #define TLV_ROUTE_PINNING          0x0823
223
224 #define TLV_VENDOR_PRIVATE_START   0x3E00
225 #define TLV_VENDOR_PRIVATE_END     0x3EFF
226 #define TLV_EXPERIMENTAL_START     0x3F00
227 #define TLV_EXPERIMENTAL_END       0x3FFF
228
229 static const value_string tlv_type_names[] = { 
230   { TLV_FEC,                       "Forwarding Equivalence Classes TLV" },
231   { TLV_ADDRESS_LIST,              "Address List TLV"},
232   { TLV_HOP_COUNT,                 "Hop Count TLV"},
233   { TLV_PATH_VECTOR,               "Path Vector TLV"},
234   { TLV_GENERIC_LABEL,             "Generic Label TLV"},
235   { TLV_ATM_LABEL,                 "ATM Label TLV"},
236   { TLV_FRAME_LABEL,               "Frame Label TLV"},
237   { TLV_STATUS,                    "Status TLV"},
238   { TLV_EXTENDED_STATUS,           "Extended Status TLV"},
239   { TLV_RETURNED_PDU,              "Returned PDU TLV"},
240   { TLV_RETURNED_MESSAGE,          "Returned Message TLV"},
241   { TLV_COMMON_HELLO_PARMS,        "Common Hello Parameters TLV"},
242   { TLV_IPV4_TRANSPORT_ADDRESS,    "IPv4 Transport Address TLV"},
243   { TLV_CONFIGURATION_SEQNO,       "Configuration Sequence Number TLV"},
244   { TLV_IPV6_TRANSPORT_ADDRESS,    "IPv6 Transport Address TLV"},
245   { TLV_COMMON_SESSION_PARMS,      "Common Session Parameters TLV"},
246   { TLV_ATM_SESSION_PARMS,         "ATM Session Parameters TLV"},
247   { TLV_FRAME_RELAY_SESSION_PARMS, "Frame Relay Session Parameters TLV"},
248   { TLV_LABEL_REQUEST_MESSAGE_ID,  "Label Request Message ID TLV"},
249   { TLV_LSPID,                     "LSP ID TLV"},
250   { TLV_ER,                        "Explicit route TLV"},
251   { TLV_ER_HOP_IPV4,               "ER hop IPv4 prefix TLV"},
252   { TLV_ER_HOP_IPV6,               "ER hop IPv6 prefix TLV"},
253   { TLV_ER_HOP_AS,                 "ER hop Autonomous system number prefix TLV"},
254   { TLV_TRAFFIC_PARAM,             "Traffic parameters TLV"},
255   { TLV_PREEMPTION,                "Preemption TLV"},
256   { TLV_ER_HOP_LSPID,              "ER hop LSPID prefix TLV"},
257   { TLV_RESOURCE_CLASS,            "Resource Class (Color) TLV"},
258   { TLV_ROUTE_PINNING,             "Route Pinning TLV"},
259   { TLV_VENDOR_PRIVATE_START,   "Vendor Private TLV"},
260   { TLV_EXPERIMENTAL_START,     "Experimental TLV"},
261   { 0, NULL}
262 };
263
264 /*
265  * The following define all the message types I know about
266  */
267
268 #define LDP_NOTIFICATION       0x0001
269 #define LDP_HELLO              0x0100
270 #define LDP_INITIALIZATION     0x0200
271 #define LDP_KEEPALIVE          0x0201
272 #define LDP_ADDRESS            0x0300
273 #define LDP_ADDRESS_WITHDRAWAL 0x0301
274 #define LDP_LABEL_MAPPING      0x0400
275 #define LDP_LABEL_REQUEST      0x0401
276 #define LDP_LABEL_WITHDRAWAL   0x0402
277 #define LDP_LABEL_RELEASE      0x0403
278 #define LDP_LABEL_ABORT_REQUEST 0x0404
279 #define LDP_VENDOR_PRIVATE_START 0x3E00
280 #define LDP_VENDOR_PRIVATE_END   0x3EFF
281 #define LDP_EXPERIMENTAL_MESSAGE_START 0x3F00
282 #define LDP_EXPERIMENTAL_MESSAGE_END   0x3FFF
283
284 static const value_string ldp_message_types[] = {
285   {LDP_NOTIFICATION,             "Notification Message"},
286   {LDP_HELLO,                    "Hello Message"},
287   {LDP_INITIALIZATION,           "Initialization Message"},
288   {LDP_KEEPALIVE,                "Keep Alive Message"},
289   {LDP_ADDRESS,                  "Address Message"},
290   {LDP_ADDRESS_WITHDRAWAL,       "Address Withdrawal Message"},
291   {LDP_LABEL_MAPPING,            "Label Mapping Message"},
292   {LDP_LABEL_REQUEST,            "Label Request Message"},
293   {LDP_LABEL_WITHDRAWAL,         "Label Withdrawal Message"},
294   {LDP_LABEL_RELEASE,            "Label Release Message"},
295   {LDP_LABEL_ABORT_REQUEST,      "Label Abort Request Message"},
296   {LDP_VENDOR_PRIVATE_START,     "Vendor-Private Message"},
297   {LDP_EXPERIMENTAL_MESSAGE_START,     "Experimental Message"},
298   {0, NULL}
299 };
300
301 static const true_false_string ldp_message_ubit = {
302   "Unknown bit set",
303   "Unknown bit not set"
304 };
305
306 static const true_false_string hello_targeted_vals = {
307   "Targeted Hello",
308   "Link Hello"
309 };
310
311 static const value_string tlv_unknown_vals[] = {
312   {0, "Known TLV, do not Forward"},
313   {1, "Known TLV, do Forward"},
314   {2, "Unknown TLV, do not Forward"},
315   {3, "Unknown TLV, do Forward"},
316   {0, NULL}
317 };
318
319 #define WILDCARD_FEC    1
320 #define PREFIX_FEC      2
321 #define HOST_FEC        3
322 #define CRLSP_FEC       4
323 #define VC_FEC          0x80    /* draft-martini-l2circuit-trans-mpls */
324
325 static const value_string fec_types[] = {
326   {WILDCARD_FEC, "Wildcard FEC"},
327   {PREFIX_FEC, "Prefix FEC"},
328   {HOST_FEC, "Host Address FEC"},
329   {CRLSP_FEC, "CR LSP FEC"},
330   {VC_FEC, "Virtual Circuit FEC"},
331   {0, NULL}
332 };
333
334
335 static const value_string fec_vc_types_vals[] = {
336   {0x0001, "Frame Relay DLCI"},
337   {0x0002, "ATM VCC transport"},
338   {0x0003, "ATM VPC transport"},
339   {0x0004, "Ethernet VLAN"},
340   {0x0005, "Ethernet"},
341   {0x0006, "HDLC"},
342   {0x0007, "PPP"},
343   {0x0009, "ATM VCC cell transport"},
344   {0x8008, "CEM"},
345   {0x000A, "ATM VPC cell transport"},
346   {0, NULL}
347 };
348
349
350 #define FEC_VC_INTERFACEPARAM_MTU          0x01
351 #define FEC_VC_INTERFACEPARAM_MAXCATMCELLS 0x02
352 #define FEC_VC_INTERFACEPARAM_DESCRIPTION  0x03
353 #define FEC_VC_INTERFACEPARAM_CEMBYTES     0x04
354 #define FEC_VC_INTERFACEPARAM_CEMOPTIONS   0x05
355
356
357 static const value_string fec_vc_interfaceparm[] = {
358   {FEC_VC_INTERFACEPARAM_MTU, "MTU"},
359   {FEC_VC_INTERFACEPARAM_MAXCATMCELLS, "Max Concatenated ATM cells"},
360   {FEC_VC_INTERFACEPARAM_DESCRIPTION, "Interface Description"},
361   {FEC_VC_INTERFACEPARAM_CEMBYTES, "CEM Payload Bytes"},
362   {FEC_VC_INTERFACEPARAM_CEMOPTIONS, "CEM options"}
363 };
364
365 static const true_false_string fec_vc_cbit = {
366   "Contorl Word Present",
367   "Control Word NOT Present"
368 };
369
370
371
372 static const value_string tlv_atm_merge_vals[] = {
373   {0, "Merge not supported"},
374   {1, "VP merge supported"},
375   {2, "VC merge supported"},
376   {3, "VP & VC merge supported"},
377   {0, NULL}
378 };
379
380 static const value_string tlv_atm_vbits_vals[] = {
381   {0, "VPI & VCI Significant"},
382   {1, "Only VPI Significant"},
383   {2, "Only VCI Significant"},
384   {3, "VPI & VCI not Significant, nonsense"},
385   {0, NULL}
386 };
387
388 static const value_string tlv_fr_merge_vals[] = {
389   {0, "Merge not supported"},
390   {1, "Merge supported"},
391   {2, "Unspecified"},
392   {3, "Unspecified"},
393   {0, NULL}
394 };
395
396 static const value_string tlv_fr_len_vals[] = {
397   {0, "10 bits"},
398   {1, "Reserved"},
399   {2, "23 bits"},
400   {3, "Reserved"},
401   {0, NULL}
402 };
403
404 static const value_string ldp_act_flg_vals[] = {
405   {0, "indicates initial LSP setup"},
406   {1, "indicates modify LSP"},
407   {0, NULL}
408 };
409
410 static const value_string route_pinning_vals[] = {
411   {0, "route pinning is not requested"},
412   {1, "route pinning is requested"},
413   {0, NULL}
414 };
415
416 static const value_string ldp_loose_vals[] = {
417   {0, "strict hop"},
418   {1, "loose hop"},
419   {0, NULL}
420 };
421
422 static const true_false_string tlv_negotiable = {
423   "Negotiable",
424   "Not negotiable"
425 };
426
427 static const value_string freq_values[] = {
428   {0, "Unspecified"},
429   {1, "Frequent"},
430   {2, "VeryFrequent"},
431   {0, NULL}
432 };
433
434 static const true_false_string tlv_atm_dirbit = {
435   "Bidirectional capability",
436   "Unidirectional capability"
437 };
438
439 static const true_false_string hello_requested_vals = {
440   "Source requests periodic hellos",
441   "Source does not request periodic hellos"
442 };
443
444 static const true_false_string tlv_sess_advbit_vals = {
445   "Downstream On Demand proposed",
446   "Downstream Unsolicited proposed"
447 };
448
449 static const true_false_string tlv_sess_ldetbit_vals = {
450   "Loop Detection Enabled",
451   "Loop Detection Disabled"
452 };
453
454 static const true_false_string tlv_status_ebit = {
455   "Fatal Error Notification",
456   "Advisory Notification"
457 };
458
459 static const true_false_string tlv_status_fbit = {
460   "Notification should be Forwarded",
461   "Notification should NOT be Forwarded"
462 };
463
464 static const value_string tlv_status_data[] = {
465   {0, "Success"},
466   {1, "Bad LDP Identifier"},
467   {2, "Bad Protocol Version"},
468   {3, "Bad PDU Length"},
469   {4, "Unknown Message Type"},
470   {5, "Bad Message Length"},
471   {6, "Unknown TLV"},
472   {7, "Bad TLV Length"},
473   {8, "Malformed TLV Value"},
474   {9, "Hold Timer Expired"},
475   {10, "Shutdown"},
476   {11, "Loop Detected"},
477   {12, "Unknown FEC"},
478   {13, "No Route"},
479   {14, "No Label Resources"},
480   {15, "Label Resources / Available"},
481   {16, "Session Rejected / No Hello"},
482   {17, "Session Rejected / Parameters Advertisement Mode"},
483   {18, "Session Rejected / Parameters Max PDU Length"},
484   {19, "Session Rejected / Parameters Label Range"},
485   {20, "KeepAlive Timer Expired"},
486   {21, "Label Request Aborted"},
487   {22, "Missing Message Parameters"},
488   {23, "Unsoported Address Family"},
489   {24, "Session Rejected / Bad KeepAlive Time"},
490   {25, "Internal Error"},
491   {0x01000001,"Unexpected Diff-Serv TLV"},
492   {0x01000002,"Unsupported PHB"},
493   {0x01000003,"Invalid EXP<->PHB Mapping"},
494   {0x01000004,"Unsupported PSC"},
495   {0x01000005,"Per-LSP context allocation failure"},
496   {0x04000001,"Bad Explicit Routing TLV Error"},
497   {0x04000002,"Bad Strict Node Error"},
498   {0x04000003,"Bad Strict Node Error"},
499   {0x04000004,"Bad Initial ER-Hop Error"},
500   {0x04000005,"Resource Unavailable"},
501   {0x04000006,"Traffic Parameters Unavailable"},
502   {0x04000007,"LSP Preempted"},
503   {0x04000008,"Modify Request Not Supported"},
504   {0x20000001,"Illegal C-Bit"},
505   {0x20000002,"Wrong C-Bit"},
506   {0, NULL}
507 };
508
509 /* Dissect FEC TLV */
510
511 static void
512 dissect_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
513 {
514         proto_tree *ti=NULL, *val_tree=NULL, *fec_tree=NULL, *vcintparam_tree=NULL;
515         guint16 family, ix=1, ax;
516         guint8  addr_size=0, *addr, implemented, prefix_len_octets, prefix_len, host_len, vc_len;
517         guint8  intparam_len;
518         void *str_handler=NULL;
519         char *str;
520
521         if (tree) {
522                 ti=proto_tree_add_text(tree, tvb, offset, rem, "FEC Elements");
523                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
524                 if(val_tree == NULL) return;
525
526                 while (rem > 0){
527                         switch (tvb_get_guint8(tvb, offset)) {
528                         case WILDCARD_FEC:
529                         case CRLSP_FEC:
530                                 ti = proto_tree_add_text(val_tree, tvb, offset, 1, "FEC Element %u", ix);
531                                 fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
532                                 if(fec_tree == NULL) return;
533                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc,tvb, offset, 1, FALSE);
534                                 rem -= 1;
535                                 offset += 1;
536                                 break;
537
538                         case PREFIX_FEC:
539                                 if( rem < 4 ){/*not enough*/
540                                         proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
541                                         return;
542                                 }
543                                 family=tvb_get_ntohs(tvb, offset+1);
544                                 prefix_len=tvb_get_guint8(tvb, offset+3);
545                                 prefix_len_octets=(prefix_len+7)/8;
546                                 
547                                 implemented=1;
548                                 switch(family) {
549                                         case AFNUM_INET: /*IPv4*/
550                                                 addr_size=4;
551                                                 str_handler=ip_to_str;
552                                                 break;
553                                         case AFNUM_INET6: /*IPv6*/
554                                                 addr_size=16;
555                                                 str_handler=ip6_to_str;
556                                                 break;
557                                         default:
558                                                 implemented=0;
559                                                 break;
560                                 }
561
562                                 if( !implemented ) {
563                                         guint16 noctets;
564                                         
565                                         noctets= rem>4+prefix_len_octets?4+prefix_len_octets:rem;
566                                         proto_tree_add_text(val_tree, tvb, offset, noctets,"Support for Address Family not implemented");
567                                         offset+=noctets;
568                                         rem-=noctets;
569                                         break;
570                                 }
571
572                                 if( rem < 4+MIN(addr_size, prefix_len_octets) ){
573                                         proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
574                                         return;
575                                 }
576
577                                 /*Add a subtree for this*/
578                                 ti = proto_tree_add_text(val_tree, tvb, offset, 4+MIN(addr_size, prefix_len_octets), "FEC Element %u", ix);
579                                 fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
580                                 if(fec_tree == NULL) return;
581                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc, tvb, offset, 1, FALSE);
582                                 offset += 1;
583
584                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_af, tvb, offset, 2, FALSE);
585                                 offset += 2;
586
587                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_len, tvb, offset, 1, FALSE);
588                                 offset += 1;
589                                 
590                                 
591                                 if( addr_size < prefix_len_octets) {
592                                         offset+=addr_size;
593                                         rem-=addr_size;
594                                         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"));
595                                         break;
596                                 }
597
598                                 if( (addr=g_malloc0(addr_size)) == NULL ){
599                                         /*big big trouble, no mem or bad addr_size*/
600                                         fprintf(stderr, "packet-ldp: dissect_tlv_fec() malloc failed\n");
601                                         return;
602                                 }
603                                 
604                                 for(ax=0; ax+1 <= prefix_len_octets; ax++)
605                                         addr[ax]=tvb_get_guint8(tvb, offset+ax);
606                                 if( prefix_len % 8 )
607                                         addr[ax-1] = addr[ax-1]&(0xFF<<(8-prefix_len%8));
608
609                                 str = (* (char* (*)(guint8 *))str_handler)(addr);
610                                 proto_tree_add_string_format(fec_tree, hf_ldp_tlv_fec_pfval, tvb, offset, prefix_len_octets, str, "Prefix: %s", str);
611                                 
612                                 offset += prefix_len_octets;
613                                 rem -= 4+prefix_len_octets;
614                                 g_free(addr);
615                                 break;
616
617                         case HOST_FEC:
618                                 if( rem < 4 ){/*not enough*/
619                                         proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
620                                         return;
621                                 }
622                                 family=tvb_get_ntohs(tvb, offset+1);
623                                 host_len=tvb_get_guint8(tvb, offset+3);
624
625                                 implemented=1;
626                                 switch(family) {
627                                         case AFNUM_INET: /*IPv4*/
628                                                 addr_size=4;
629                                                 str_handler=ip_to_str;
630                                                 break;
631                                         case AFNUM_INET6: /*IPv6*/
632                                                 addr_size=16;
633                                                 str_handler=ip6_to_str;
634                                                 break;
635                                         default:
636                                                 implemented=0;
637                                                 break;
638                                 }
639
640                                 if( !implemented ) {
641                                         guint16 noctets;
642                                         
643                                         noctets= rem>4+host_len?4+host_len:rem;
644                                         proto_tree_add_text(val_tree, tvb, offset, noctets,"Support for Address Family not implemented");
645                                         offset+=noctets;
646                                         rem-=noctets;
647                                         break;
648                                 }
649
650                                 if( rem < 4+addr_size ){
651                                         proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
652                                         return;
653                                 }
654
655                                 /*Add a subtree for this*/
656                                 ti = proto_tree_add_text(val_tree, tvb, offset, 4+addr_size, "FEC Element %u", ix);
657                                 fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
658                                 if(fec_tree == NULL) return;
659                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc, tvb, offset, 1, FALSE);
660                                 offset += 1;
661
662                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_af, tvb, offset, 2, FALSE);
663                                 offset += 2;
664
665                                 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_len, tvb, offset, 1, FALSE);
666                                 offset += 1;
667                                 
668                                 
669                                 if( addr_size != host_len) {
670                                         offset+=addr_size;
671                                         rem-=addr_size;
672                                         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"));
673                                         break;
674                                 }
675
676                                 if( (addr=g_malloc0(addr_size)) == NULL ){
677                                         /*big big xtrouble, no mem or bad addr_size*/
678                                         fprintf(stderr, "packet-ldp: dissect_tlv_fec() malloc failed\n");
679                                         return;
680                                 }
681                                 
682                                 for(ax=0; ax+1 <= host_len; ax++)
683                                         addr[ax]=tvb_get_guint8(tvb, offset+ax);
684
685                                 str = (* (char* (*)(guint8 *))str_handler)(addr);
686                                 proto_tree_add_string_format(fec_tree, hf_ldp_tlv_fec_hoval, tvb, offset, host_len, str, "Address: %s", str);
687                                 
688                                 offset += host_len;
689                                 rem -= 4+host_len;
690                                 g_free(addr);
691                                 break;
692
693                         case VC_FEC:
694                           if( rem < 8 ){/*not enough bytes for a minimal VC_FEC*/
695                             proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
696                             return;
697                           }
698                           vc_len = tvb_get_guint8 (tvb, offset+3);
699
700
701                           ti = proto_tree_add_text(val_tree, tvb, offset, 8+vc_len, "FEC Element %u", ix);
702                           fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
703                           if(fec_tree == NULL) return;
704                           proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc, tvb, offset, 1, FALSE);
705                           proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_controlword, tvb, offset+1, 1, FALSE);
706                           proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_vctype, tvb, offset+1, 2, FALSE);
707                           proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_infolength, tvb, offset+3,1,FALSE);
708                           proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_groupid,tvb, offset +4, 4, FALSE);
709                           rem -=8;
710                           offset +=8;
711                           
712                           if ( (vc_len > 3) && ( rem > 3 ) ) { /* there is enough room for vcid */
713                             proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_vcid,tvb, offset, 4, FALSE);
714                             proto_item_append_text (ti," VCID: %u",tvb_get_ntohl(tvb,offset));
715
716                           } else {
717                             proto_tree_add_text(val_tree,tvb,offset +4, 8 +vc_len, "VC FEC size format error");
718                             return;
719                           }
720                           rem -= 4;
721                           vc_len -= 4;
722                           offset += 4;
723
724                           while ( (vc_len > 1) && (rem > 1) ) { /* enough to include id and length */
725                             intparam_len = tvb_get_guint8(tvb, offset+1);
726                             ti = proto_tree_add_text(fec_tree, tvb, offset, 4, "Interface Paramameter");
727                             vcintparam_tree = proto_item_add_subtree(ti, ett_ldp_fec_vc_interfaceparam);
728                             if(vcintparam_tree == NULL) return;
729                             proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_id,tvb,offset,1,FALSE);
730                             proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_length,tvb, offset+1, 1, FALSE);
731                             if ( (vc_len -intparam_len) <0 && (rem -intparam_len) <0 ) { /* error condition */
732                               proto_tree_add_text(vcintparam_tree, tvb, offset +2, MIN(vc_len,rem), "malformed data");
733                               return;
734                             }
735                             switch (tvb_get_guint8(tvb, offset)) {
736                             case FEC_VC_INTERFACEPARAM_MTU:
737                               proto_item_append_text(ti,": MTU %u", tvb_get_ntohs(tvb,offset+2));
738                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_mtu,tvb, offset+2, 2, FALSE);
739                               break;
740                             case FEC_VC_INTERFACEPARAM_MAXCATMCELLS:
741                               proto_item_append_text(ti,": Max ATM Concat Cells %u", tvb_get_ntohs(tvb,offset+2));
742                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_maxcatmcells,tvb, offset+2, 2, FALSE);
743                               break;
744                             case FEC_VC_INTERFACEPARAM_DESCRIPTION:
745                               proto_item_append_text(ti,": Description");
746                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_desc,tvb, offset+2, (intparam_len -2), FALSE);
747                               break;
748                             case FEC_VC_INTERFACEPARAM_CEMBYTES:
749                               proto_item_append_text(ti,": CEM Payload Bytes %u", tvb_get_ntohs(tvb,offset+2));
750                               proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_cembytes,tvb, offset+2, 2, FALSE);
751                               break;
752                             case FEC_VC_INTERFACEPARAM_CEMOPTIONS:
753                                 /* draft-malis-sonet-ces-mpls CEM options still undefined */
754                             default: /* unknown */
755                               proto_item_append_text(ti," unknown");
756                               proto_tree_add_text(vcintparam_tree,tvb, offset+2, (intparam_len -2), "Unknown data");
757
758                               return;
759                             }
760                             rem -= intparam_len;
761                             vc_len -= intparam_len;
762                             offset += intparam_len;
763                           }
764                           break;
765
766                         default:  /* Unknown */
767                         /* XXX - do all FEC's have a length that's a multiple of 4? */
768                         /* Hmmm, don't think so. Will check. RJS. */
769                         /* If we don't know its structure, we have to exit */
770                                 ti = proto_tree_add_text(val_tree, tvb, offset, 4, "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_text(fec_tree, tvb, offset, rem, "Unknown FEC TLV type");
774                                 return;
775                         }
776                         ix++;
777                 }
778         }
779 }
780
781 /* Dissect Address List TLV */
782
783 static void
784 dissect_tlv_address_list(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
785 {
786         proto_tree *ti = NULL, *val_tree = NULL;
787         guint16 family, ix;
788         guint8  addr_size, *addr;
789         void *str_handler;
790         char *str;
791
792         if (tree) {
793                 if( rem < 2 ) {
794                         proto_tree_add_text(tree, tvb, offset, rem,
795                             "Error processing Address List TLV: length is %d, should be >= 2",
796                             rem);
797                         return;
798                 }
799
800                 family=tvb_get_ntohs(tvb, offset);
801                 proto_tree_add_item(tree, hf_ldp_tlv_addrl_addr_family, tvb,
802                                          offset, 2, FALSE);
803                 switch(family) {
804                         case AFNUM_INET: /*IPv4*/
805                                 addr_size=4;
806                                 str_handler=ip_to_str;
807                                 break;
808                         case AFNUM_INET6: /*IPv6*/
809                                 addr_size=16;
810                                 str_handler=ip6_to_str;
811                                 break;
812                         default:
813                                 proto_tree_add_text(tree, tvb, offset+2, rem-2,
814                                  "Support for Address Family not implemented");
815                                 return;
816                 }
817
818                 offset+=2; rem-=2;
819                 ti=proto_tree_add_text(tree, tvb, offset, rem, "Addresses");
820                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
821
822                 if(val_tree == NULL) return;
823                 if( (addr=g_malloc(addr_size)) == NULL ){
824                         /*big big trouble*/
825                         fprintf(stderr, "packet-ldp: dissect_tlv_address_list() malloc failed\n");
826                         return;
827                 }
828
829                 for(ix=1; rem >= addr_size; ix++, offset += addr_size,
830                                                          rem -= addr_size) {
831                         if( (tvb_memcpy(tvb, addr, offset, addr_size))
832                                                          == NULL)
833                                 break;
834
835                         str = (* (char* (*)(guint8 *))str_handler)(addr);
836                         proto_tree_add_string_format(val_tree,
837                             hf_ldp_tlv_addrl_addr, tvb, offset, addr_size, str,
838                             "Address %u: %s", ix, str);
839                 }
840                 if(rem)
841                         proto_tree_add_text(val_tree, tvb, offset, rem,
842                             "Error processing TLV: Extra data at end of address list");
843                 g_free(addr);
844         }
845 }
846
847 /* Dissect Path Vector TLV */
848
849 static void
850 dissect_tlv_path_vector(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
851 {
852         proto_tree *ti = NULL, *val_tree = NULL;
853         guint8  ix;
854         guint32 addr;
855
856         if (tree) {
857                 ti=proto_tree_add_text(tree, tvb, offset, rem, "LSR IDs");
858                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
859
860                 if(val_tree == NULL) return;
861
862                 for(ix=1; rem >= 4; ix++, offset += 4, rem -= 4) {
863                         tvb_memcpy(tvb, (guint8 *)&addr, offset, 4);
864                         proto_tree_add_ipv4_format(val_tree,
865                             hf_ldp_tlv_pv_lsrid, tvb, offset, 4,
866                             addr, "LSR Id %u: %s", ix,
867                             ip_to_str((guint8 *)&addr));
868                 }
869                 if(rem)
870                         proto_tree_add_text(val_tree, tvb, offset, rem,
871                             "Error processing TLV: Extra data at end of path vector");
872         }
873 }
874
875 /* Dissect ATM Label TLV */
876
877 static void
878 dissect_tlv_atm_label(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
879 {
880         proto_tree *ti = NULL, *val_tree = NULL;
881         guint16 id;
882
883         if(tree) {
884                 if(rem != 4){
885                         proto_tree_add_text(tree, tvb, offset, rem,
886                             "Error processing ATM Label TLV: length is %d, should be 4",
887                             rem);
888                         return;
889                 }
890                 ti=proto_tree_add_text(tree, tvb, offset, rem, "ATM Label");
891                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
892                 if(val_tree == NULL) return;
893
894                 proto_tree_add_item(val_tree, hf_ldp_tlv_atm_label_vbits, tvb, offset, 1, FALSE);
895
896                 id=tvb_get_ntohs(tvb, offset)&0x0FFF;
897                 proto_tree_add_uint_format(val_tree, hf_ldp_tlv_atm_label_vpi, tvb, offset, 2, id, "VPI: %u", id); 
898                         
899                 id=tvb_get_ntohs(tvb, offset+2);
900                 proto_tree_add_uint_format(val_tree, hf_ldp_tlv_atm_label_vci, tvb, offset+2, 2, id, "VCI: %u", id); 
901         }
902 }
903
904 /* Dissect FRAME RELAY Label TLV */
905
906 static void
907 dissect_tlv_frame_label(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
908 {
909         proto_tree *ti = NULL, *val_tree = NULL;
910         guint8  len;
911         guint32 id;
912
913         if(tree) {
914                 if(rem != 4){
915                         proto_tree_add_text(tree, tvb, offset, rem,
916                             "Error processing Frame Relay Label TLV: length is %d, should be 4",
917                             rem);
918                         return;
919                 }
920                 ti=proto_tree_add_text(tree, tvb, offset, rem, "Frame Relay Label");
921                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
922                 if(val_tree == NULL) return;
923
924                 len=(guint8)(tvb_get_ntohs(tvb, offset)>>7) & 0x03;
925                 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); 
926
927                 id=tvb_get_ntoh24(tvb, offset+1)&0x7FFFFF;
928                 proto_tree_add_uint_format(val_tree, 
929                 hf_ldp_tlv_fr_label_dlci, tvb, offset+1, 3, id, "DLCI: %u", id); 
930         }
931 }
932
933 /* Dissect STATUS TLV */
934
935 static void
936 dissect_tlv_status(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
937 {
938         proto_tree *ti = NULL, *val_tree = NULL;
939         guint32 data;
940
941         if(tree) {
942                 if(rem != 10){
943                         proto_tree_add_text(tree, tvb, offset, rem,
944                             "Error processing Status TLV: length is %d, should be 10",
945                             rem);
946                         return;
947                 }
948
949                 ti=proto_tree_add_text(tree, tvb, offset, rem, "Status");
950                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
951                 if(val_tree == NULL) return;
952
953                 proto_tree_add_item(val_tree, hf_ldp_tlv_status_ebit, tvb, offset, 1, FALSE); 
954                 proto_tree_add_item(val_tree, hf_ldp_tlv_status_fbit, tvb, offset, 1, FALSE); 
955
956                 data=tvb_get_ntohl(tvb, offset)&0x3FFFFFFF;
957                 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); 
958
959                 proto_tree_add_item(val_tree, hf_ldp_tlv_status_msg_id, tvb, offset+4, 4, FALSE); 
960                 proto_tree_add_item(val_tree, hf_ldp_tlv_status_msg_type, tvb, offset+8, 2, FALSE); 
961         }
962 }
963
964 /* Dissect Returned PDU TLV */
965
966 static void
967 dissect_tlv_returned_pdu(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
968 {
969         proto_tree *ti = NULL, *val_tree = NULL;
970
971         if(tree) {
972                 if(rem < 10){
973                         proto_tree_add_text(tree, tvb, offset, rem,
974                             "Error processing Returned PDU TLV: length is %d, should be >= 10",
975                             rem);
976                         return;
977                 }
978                 ti=proto_tree_add_text(tree, tvb, offset, rem, "Returned PDU");
979                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
980                 if(val_tree == NULL) return;
981
982                 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_version, tvb, offset, 2, FALSE); 
983                 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_pdu_len, tvb, offset+2, 2, FALSE); 
984                 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_lsr, tvb, offset+4, 4, FALSE); 
985                 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_ls_id, tvb, offset+8, 2, FALSE); 
986                 offset += 10;
987                 rem -= 10;
988
989                 if( rem > 0 ) {
990                 /*XXX - dissect returned pdu data*/
991                         proto_tree_add_text(val_tree, tvb, offset, rem, "Returned PDU Data");
992                 }
993         }
994 }
995
996 /* Dissect Returned MESSAGE TLV */
997
998 static void
999 dissect_tlv_returned_message(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1000 {
1001         proto_tree *ti = NULL, *val_tree = NULL;
1002         guint16 type;
1003
1004         if(tree) {
1005                 if(rem < 4){
1006                         proto_tree_add_text(tree, tvb, offset, rem,
1007                             "Error processing Returned Message TLV: length is %d, should be >= 4",
1008                             rem);
1009                         return;
1010                 }
1011                 ti=proto_tree_add_text(tree, tvb, offset, rem, "Returned Message");
1012                 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
1013                 if(val_tree == NULL) return;
1014
1015                 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_ubit, tvb, offset, 1, FALSE); 
1016
1017                 type=tvb_get_ntohs(tvb, offset)&0x7FFF;
1018                 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); 
1019
1020                 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_len, tvb, offset+2, 2, FALSE); 
1021                 offset += 4;
1022                 rem -= 4;
1023
1024                 if( rem >= 4  ) { /*have msg_id*/
1025                         proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_id, tvb, offset, 4, FALSE); 
1026                         offset += 4;
1027                         rem -= 4;
1028                 }
1029
1030                 if( rem > 0 ) {
1031                 /*XXX - dissect returned msg parameters*/
1032                         proto_tree_add_text(val_tree, tvb, offset, rem, "Returned Message Parameters");
1033                 }
1034         }
1035 }
1036
1037 /* Dissect the common hello params */
1038
1039 static void 
1040 #if 0
1041 dissect_tlv_common_hello_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1042 #else
1043 dissect_tlv_common_hello_parms(tvbuff_t *tvb, guint offset, proto_tree *tree)
1044 #endif
1045 {
1046 #if 0
1047         proto_tree *ti = NULL;
1048 #endif
1049         proto_tree *val_tree = NULL;
1050
1051         if (tree) {
1052 #if 0
1053                 ti = proto_tree_add_item(tree, hf_ldp_tlv_value, tvb, offset, rem, FALSE);
1054                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1055                 if(val_tree == NULL) return;
1056 #else
1057                 val_tree=tree;
1058 #endif
1059                 proto_tree_add_item(val_tree, hf_ldp_tlv_val_hold, tvb, offset, 2, FALSE);
1060                 proto_tree_add_item(val_tree, hf_ldp_tlv_val_target, tvb, offset + 2, 2, FALSE);
1061                 proto_tree_add_item(val_tree, hf_ldp_tlv_val_request, tvb, offset + 2, 2, FALSE);
1062                 proto_tree_add_item(val_tree, hf_ldp_tlv_val_res, tvb, offset + 2, 2, FALSE);
1063         }
1064 }
1065
1066 /* Dissect the common session params */
1067
1068 static void 
1069 dissect_tlv_common_session_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1070 {
1071         proto_tree *ti = NULL, *val_tree = NULL;
1072
1073         if (tree != NULL) {
1074                 if( rem != 14) { /*length of Comm Sess Parms tlv*/
1075                         proto_tree_add_text(tree, tvb, offset, rem,
1076                             "Error processing Common Session Parameters TLV: length is %d, should be 14",
1077                             rem);
1078                         return;
1079                 }
1080                 ti = proto_tree_add_text(tree, tvb, offset, rem, "Parameters");
1081                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1082
1083                 if(val_tree != NULL) {
1084                         /*Protocol Version*/
1085                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_ver, tvb,offset, 2, FALSE); 
1086
1087                         /*KeepAlive Time*/
1088                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_ka, tvb,offset + 2, 2, FALSE);
1089
1090                         /*A bit*/
1091                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_advbit,tvb, offset + 4, 1, FALSE);
1092                                          
1093                         /*D bit*/
1094                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_ldetbit,tvb, offset + 4, 1, FALSE);
1095                                          
1096                         /*Path Vector Limit*/
1097                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_pvlim,tvb, offset + 5, 1, FALSE);
1098                                          
1099                         /*Max PDU Length*/
1100                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_mxpdu,tvb, offset + 6, 2, FALSE);
1101                                          
1102                         /*Rx LSR*/
1103                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_rxlsr,tvb, offset + 8, 4, FALSE);
1104                                          
1105                         /*Rx LS*/
1106                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_rxls,tvb, offset + 12, 2, FALSE);
1107                 }
1108         }
1109 }
1110
1111 /* Dissect the atm session params */
1112
1113 static void 
1114 dissect_tlv_atm_session_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1115 {
1116         proto_tree *ti = NULL, *val_tree = NULL, *lbl_tree = NULL;
1117         guint8 numlr, ix;
1118         guint16 id;
1119
1120         if (tree != NULL) {
1121                 if(rem < 4) {
1122                         proto_tree_add_text(tree, tvb, offset, rem,
1123                             "Error processing ATM Parameters TLV: length is %d, should be >= 4",
1124                             rem);
1125                         return;
1126                 }
1127
1128                 ti = proto_tree_add_text(tree, tvb, offset, rem,"ATM Parameters");
1129                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1130
1131                 if(val_tree != NULL) {
1132                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_atm_merge,tvb, offset, 1, FALSE); 
1133
1134                         /*get the number of label ranges*/      
1135                         numlr=(tvb_get_guint8(tvb, offset)>>2) & 0x0F;
1136                         proto_tree_add_uint_format(val_tree, hf_ldp_tlv_sess_atm_lr,
1137                         tvb, offset, 1, numlr, "Number of Label Range components: %u",
1138                         numlr); 
1139
1140                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_atm_dir,tvb, offset, 1, FALSE); 
1141
1142                         /*move into range components*/
1143                         offset += 4;
1144                         rem -= 4;
1145                         ti = proto_tree_add_text(val_tree, tvb, offset, rem,"ATM Label Range Components");
1146                                  
1147                         if(numlr) {
1148                                 val_tree=proto_item_add_subtree(ti,ett_ldp_tlv_val);
1149                                 if( ! val_tree ) return;
1150                         }
1151                         /*now dissect ranges*/
1152                         for(ix=1; numlr > 0 && rem >= 8; ix++, rem-=8, numlr--) {
1153                                 ti=proto_tree_add_text(val_tree, tvb, offset, 8,
1154                                  "ATM Label Range Component %u", ix);
1155                                 lbl_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
1156
1157                                 if( lbl_tree == NULL ) break;
1158
1159                                 id=tvb_get_ntohs(tvb, offset)&0x0FFF;
1160                                 proto_tree_add_uint_format(lbl_tree, 
1161                                     hf_ldp_tlv_sess_atm_minvpi,
1162                                     tvb, offset, 2,
1163                                     id, "Minimum VPI: %u", id); 
1164                                 id=tvb_get_ntohs(tvb, offset+4)&0x0FFF;
1165                                 proto_tree_add_uint_format(lbl_tree, 
1166                                     hf_ldp_tlv_sess_atm_maxvpi,
1167                                     tvb, (offset+4), 2, id,
1168                                     "Maximum VPI: %u", id); 
1169                                  
1170                                 id=tvb_get_ntohs(tvb, offset+2);
1171                                 proto_tree_add_uint_format(lbl_tree, 
1172                                     hf_ldp_tlv_sess_atm_minvci,
1173                                     tvb, offset+2, 2,
1174                                     id, "Minimum VCI: %u", id); 
1175                                 id=tvb_get_ntohs(tvb, offset+6);
1176                                 proto_tree_add_uint_format(lbl_tree, 
1177                                     hf_ldp_tlv_sess_atm_maxvci,
1178                                     tvb, offset+6, 2,
1179                                     id, "Maximum VCI: %u", id); 
1180
1181                                 offset += 8;
1182                         }
1183                         if( rem || numlr)
1184                                 proto_tree_add_text(val_tree, tvb, offset, rem,
1185                                     "Error processing TLV: Extra data at end of TLV");
1186                 }
1187         }
1188 }
1189
1190 /* Dissect the frame relay session params */
1191
1192 static void 
1193 dissect_tlv_frame_relay_session_parms(tvbuff_t *tvb, guint offset,proto_tree *tree, int rem)
1194 {
1195         proto_tree *ti = NULL, *val_tree = NULL, *lbl_tree = NULL;
1196         guint8 numlr, ix, len;
1197         guint32 id;
1198
1199         if (tree != NULL) {
1200                 if(rem < 4) {
1201                         proto_tree_add_text(tree, tvb, offset, rem,
1202                             "Error processing Frame Relay Parameters TLV: length is %d, should be >= 4",
1203                             rem);
1204                         return;
1205                 }
1206
1207                 ti = proto_tree_add_text(tree, tvb, offset, rem,
1208                                                  "Frame Relay Parameters");
1209                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1210
1211                 if(val_tree != NULL) {
1212                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_fr_merge,
1213                                 tvb, offset, 1, FALSE); 
1214
1215                         /*get the number of label ranges*/      
1216                         numlr=(tvb_get_guint8(tvb, offset)>>2) & 0x0F;
1217                         proto_tree_add_uint_format(val_tree, hf_ldp_tlv_sess_fr_lr,
1218                         tvb, offset, 1, numlr, "Number of Label Range components: %u",
1219                         numlr); 
1220
1221                         proto_tree_add_item(val_tree, hf_ldp_tlv_sess_fr_dir,
1222                                  tvb, offset, 1, FALSE); 
1223
1224                         /*move into range components*/
1225                         offset += 4;
1226                         rem -= 4;
1227                         ti = proto_tree_add_text(val_tree, tvb, offset, rem,
1228                                  "Frame Relay Label Range Components");
1229
1230                         if(numlr) {
1231                                 val_tree=proto_item_add_subtree(ti,
1232                                                          ett_ldp_tlv_val);
1233                                 if( ! val_tree ) return;
1234                         }
1235
1236                         /*now dissect ranges*/
1237                         for(ix=1; numlr > 0 && rem >= 8; ix++, rem-=8, numlr--) {
1238                                 ti=proto_tree_add_text(val_tree, tvb, offset, 8,
1239                                 "Frame Relay Label Range Component %u", ix);
1240                                 lbl_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
1241
1242                                 if( lbl_tree == NULL ) break;
1243
1244                                 len=(guint8)(tvb_get_ntohs(tvb, offset)>>7) & 0x03;
1245                                 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); 
1246
1247                                 id=tvb_get_ntoh24(tvb, offset+1)&0x7FFFFF;
1248                                 proto_tree_add_uint_format(lbl_tree, 
1249                         hf_ldp_tlv_sess_fr_mindlci, tvb, offset+1, 3, id, "Minimum DLCI %u", id); 
1250                                 id=tvb_get_ntoh24(tvb, offset+5)&0x7FFFFF;
1251                                 proto_tree_add_uint_format(lbl_tree, 
1252                         hf_ldp_tlv_sess_fr_maxdlci, tvb, offset+5, 3, id, "Maximum DLCI %u", id); 
1253
1254                                 offset += 8;
1255                         }
1256
1257                         if( rem || numlr)
1258                                 proto_tree_add_text(val_tree, tvb, offset, rem,
1259                                  "Error processing TLV: Extra data at end of TLV");
1260                 }
1261         }
1262 }
1263
1264
1265 static void
1266 dissect_tlv_lspid(tvbuff_t *tvb, guint offset,proto_tree *tree, int rem)
1267 {
1268         proto_tree *ti = NULL, *val_tree = NULL;
1269
1270         if (tree != NULL) {
1271                 if(rem != 8) {
1272                         proto_tree_add_text(tree, tvb, offset, rem,
1273                             "Error processing LSP ID TLV: length is %d, should be 8",
1274                             rem);
1275                         return;
1276                 }
1277
1278                 ti = proto_tree_add_text(tree, tvb, offset, rem,
1279                                                 "LSP ID");
1280                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1281
1282                 if(val_tree != NULL) {
1283                         proto_tree_add_item(val_tree, hf_ldp_tlv_lspid_act_flg,
1284                                            tvb, offset, 2, FALSE); 
1285                         offset += 2;
1286                         proto_tree_add_item(val_tree, hf_ldp_tlv_lspid_cr_lsp,
1287                                            tvb, offset, 2, FALSE);
1288                         offset += 2;
1289                         proto_tree_add_item(val_tree, hf_ldp_tlv_lspid_ldpid, 
1290                                            tvb, offset, 4, FALSE);
1291                 }
1292         }
1293 }
1294
1295 static void
1296 dissect_tlv_er_hop_ipv4(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1297 {
1298         proto_tree *ti = NULL, *val_tree = NULL;
1299
1300
1301         if (tree != NULL) {
1302                 if(rem != 8) {
1303                         proto_tree_add_text(tree, tvb, offset, rem,
1304                             "Error processing ER HOP IPv4 TLV: length is %d, should be 8",
1305                             rem);
1306                         return;
1307                 }
1308                 ti = proto_tree_add_text(tree, tvb, offset, rem, "ER HOP IPv4");
1309                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1310
1311                 if(val_tree != NULL) {
1312                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_loose,
1313                                            tvb, offset, 3, FALSE);
1314                         offset += 3;
1315                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_prelen,
1316                                            tvb, offset, 1, FALSE);
1317                         offset ++;
1318                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_prefix4,
1319                                            tvb, offset, 4, FALSE);
1320                 }
1321         }
1322 }
1323
1324 static void
1325 dissect_tlv_er_hop_ipv6(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1326 {
1327         proto_tree *ti = NULL, *val_tree = NULL;
1328
1329         if (tree != NULL) {
1330                 if(rem != 20) {
1331                         proto_tree_add_text(tree, tvb, offset, rem,
1332                             "Error processing ER HOP IPv6 TLV: length is %d, should be 20",
1333                             rem);
1334                         return;
1335                 }
1336                 ti = proto_tree_add_text(tree, tvb, offset, rem, "ER HOP IPv6");
1337                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1338
1339                 if(val_tree != NULL) {
1340                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_loose,
1341                                            tvb, offset, 3, FALSE);
1342                         offset += 3;
1343                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_prelen,
1344                                           tvb, offset, 1, FALSE);
1345                         offset ++;
1346                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_prefix6,
1347                                            tvb, offset, 16, FALSE);
1348                 }
1349         }
1350 }
1351
1352 static void
1353 dissect_tlv_er_hop_as(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1354 {
1355         proto_tree *ti = NULL, *val_tree = NULL;
1356
1357         if (tree != NULL) {
1358                 if(rem != 4) {
1359                         proto_tree_add_text(tree, tvb, offset, rem,
1360                             "Error processing ER HOP AS TLV: length is %d, should be 4",
1361                             rem);
1362                         return;
1363                 }
1364                 ti = proto_tree_add_text(tree, tvb, offset, rem, "ER HOP AS");
1365                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1366
1367                 if(val_tree != NULL) {
1368                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_loose,
1369                                            tvb, offset, 2, FALSE);
1370                         offset += 2;
1371                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_as,
1372                                            tvb, offset, 2, FALSE);
1373                 }
1374         }
1375 }
1376
1377 static void
1378 dissect_tlv_er_hop_lspid(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1379 {
1380         proto_tree *ti = NULL, *val_tree = NULL;
1381
1382         if (tree != NULL) {
1383                 if(rem != 8) {
1384                         proto_tree_add_text(tree, tvb, offset, rem,
1385                             "Error processing ER HOP LSPID TLV: length is %d, should be 8",
1386                             rem);
1387                         return;
1388                 }
1389                 ti = proto_tree_add_text(tree, tvb, offset, rem, "ER HOP LSPID");
1390                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1391
1392                 if(val_tree != NULL) {
1393                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_loose,
1394                                            tvb, offset, 2, FALSE);
1395                         offset += 2;
1396                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_cr_lsp,
1397                                            tvb, offset, 2, FALSE);
1398                         offset += 2;
1399                         proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_ldpid,
1400                                            tvb, offset, 4, FALSE);
1401                 }
1402         }
1403 }
1404
1405 static void
1406 dissect_tlv_traffic(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1407 {
1408         proto_tree *ti = NULL, *val_tree = NULL;
1409         guint8  val_8;
1410         float   val_f;
1411         proto_item *pi;
1412
1413         if (tree != NULL) {
1414                 if(rem != 24) {
1415                         proto_tree_add_text(tree, tvb, offset, rem,
1416                             "Error processing Traffic Parameters TLV: length is %d, should be 24",
1417                             rem);
1418                         return;
1419                 }
1420                 ti = proto_tree_add_text(tree, tvb, offset, rem, "Traffic parameters");
1421                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1422
1423                 if(val_tree != NULL) {
1424                         /* flags */
1425                         proto_tree_add_item(val_tree, hf_ldp_tlv_flags_reserv, tvb, offset, 1, FALSE);
1426                         proto_tree_add_item(val_tree, hf_ldp_tlv_flags_weight, tvb, offset, 1, FALSE);
1427                         proto_tree_add_item(val_tree, hf_ldp_tlv_flags_ebs, tvb, offset, 1, FALSE);
1428                         proto_tree_add_item(val_tree, hf_ldp_tlv_flags_cbs, tvb, offset, 1, FALSE);
1429                         proto_tree_add_item(val_tree, hf_ldp_tlv_flags_cdr, tvb, offset, 1, FALSE);
1430                         proto_tree_add_item(val_tree, hf_ldp_tlv_flags_pbs, tvb, offset, 1, FALSE);
1431                         proto_tree_add_item(val_tree, hf_ldp_tlv_flags_pdr, tvb, offset, 1, FALSE);
1432
1433                         offset ++;
1434                         /* frequency */
1435                         proto_tree_add_item(val_tree, hf_ldp_tlv_frequency, tvb, offset, 1, FALSE);
1436                         offset ++;
1437
1438                         /* reserver byte */
1439                         offset ++;
1440
1441                         /* weight */
1442                         pi = proto_tree_add_item(val_tree, hf_ldp_tlv_weight, tvb, offset, 1, FALSE);
1443                         val_8 = tvb_get_guint8(tvb, offset);
1444                         if (val_8 == 0)
1445                                 proto_item_set_text(pi, "Weight: Not applicable");
1446                         offset ++;
1447
1448                         /* PDR */
1449                         val_f = tvb_get_ntohieee_float (tvb, offset);
1450                         proto_tree_add_double_format(val_tree, hf_ldp_tlv_pdr, tvb, offset,
1451                                                     4, val_f, "PDR: %.10g Bps", val_f);
1452                         offset += 4;
1453                         /* PBS */
1454                         val_f = tvb_get_ntohieee_float (tvb, offset);
1455                         proto_tree_add_double_format(val_tree, hf_ldp_tlv_pbs, tvb, offset,
1456                                                     4, val_f, "PBS: %.10g Bytes", val_f);
1457                         offset += 4;
1458
1459                         /* CDR */
1460                         val_f = tvb_get_ntohieee_float (tvb, offset);
1461                         proto_tree_add_double_format(val_tree, hf_ldp_tlv_cdr, tvb, offset,
1462                                                     4, val_f, "CDR: %.10g Bps", val_f);
1463                         offset += 4;
1464
1465                         /* CBS */
1466                         val_f = tvb_get_ntohieee_float (tvb, offset);
1467                         proto_tree_add_double_format(val_tree, hf_ldp_tlv_cbs, tvb, offset,
1468                                                     4, val_f, "CBS: %.10g Bytes", val_f);
1469                         offset += 4;
1470
1471                         /* EBS */
1472                         val_f = tvb_get_ntohieee_float (tvb, offset);
1473                         proto_tree_add_double_format(val_tree, hf_ldp_tlv_ebs, tvb, offset,
1474                                                     4, val_f, "EBS: %.10g Bytes", val_f);
1475
1476                 }
1477         }
1478 }
1479
1480 static void
1481 dissect_tlv_route_pinning(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1482 {
1483         proto_tree *ti = NULL, *val_tree = NULL;
1484
1485         if (tree != NULL) {
1486                 if(rem != 4) {
1487                         proto_tree_add_text(tree, tvb, offset, rem,
1488                             "Error processing Route Pinning TLV: length is %d, should be 4",
1489                             rem);
1490                         return;
1491                 }
1492                 ti = proto_tree_add_text(tree, tvb, offset, rem, "Route Pinning");
1493                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1494
1495                 if(val_tree != NULL) {
1496                         proto_tree_add_item(val_tree, hf_ldp_tlv_route_pinning,
1497                                            tvb, offset, 4, FALSE);
1498                 }
1499         }
1500 }
1501
1502
1503 static void
1504 dissect_tlv_resource_class(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1505 {
1506         proto_tree *ti = NULL, *val_tree = NULL;
1507
1508         if (tree != NULL) {
1509                 if(rem != 4) {
1510                         proto_tree_add_text(tree, tvb, offset, rem,
1511                             "Error processing Resource Class TLV: length is %d, should be 4",
1512                             rem);
1513                         return;
1514                 }
1515                 ti = proto_tree_add_text(tree, tvb, offset, rem, "Resource Class");
1516                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1517
1518                 if(val_tree != NULL) {
1519                         proto_tree_add_item(val_tree, hf_ldp_tlv_resource_class,
1520                                            tvb, offset, 4, FALSE);
1521                 }
1522         }
1523 }
1524
1525
1526 static void
1527 dissect_tlv_preemption(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1528 {
1529         proto_tree *ti = NULL, *val_tree = NULL;
1530
1531         if (tree != NULL) {
1532                 if(rem != 4) {
1533                         proto_tree_add_text(tree, tvb, offset, rem,
1534                             "Error processing Preemption TLV: length is %d, should be 4",
1535                             rem);
1536                         return;
1537                 }
1538                 ti = proto_tree_add_text(tree, tvb, offset, rem, "Preemption");
1539                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1540
1541                 if(val_tree != NULL) {
1542                         proto_tree_add_item(val_tree, hf_ldp_tlv_set_prio,
1543                                            tvb, offset, 1, FALSE);
1544                         offset += 1;
1545                         proto_tree_add_item(val_tree, hf_ldp_tlv_hold_prio,
1546                                            tvb, offset, 1, FALSE);
1547                 }
1548         }
1549 }
1550
1551 static int
1552 dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem);
1553
1554 static void
1555 dissect_tlv_er(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1556 {
1557         proto_tree *ti = NULL, *val_tree = NULL;
1558         int len;
1559
1560         if (tree != NULL) {
1561                 ti = proto_tree_add_text(tree, tvb, offset, rem, "Explicit route");
1562                 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1563
1564                 if(val_tree != NULL) {
1565                         len = 0;
1566                         while (rem > 0) {
1567                                 len = dissect_tlv (tvb, offset, val_tree, rem);
1568                                 offset += len;
1569                                 rem -= len;
1570                         }
1571                 }
1572         }
1573 }
1574
1575
1576 /* Dissect a TLV and return the number of bytes consumed ... */
1577
1578 static int
1579 dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1580 {
1581         guint16 type, typebak;
1582         int length;
1583         proto_tree *ti = NULL, *tlv_tree = NULL;
1584
1585         length=tvb_reported_length_remaining(tvb, offset);
1586         rem=MIN(rem, length);
1587
1588         if( rem < 4 ) {/*chk for minimum header*/
1589                 if(tree)
1590                         proto_tree_add_text(tree, tvb, offset, rem,
1591                             "Error processing TLV: length is %d, should be >= 4",
1592                             rem);
1593                 return rem;
1594         }
1595         type = tvb_get_ntohs(tvb, offset) & 0x3FFF;
1596
1597         length = tvb_get_ntohs(tvb, offset + 2),
1598         rem -= 4; /*do not count header*/
1599         length = MIN(length, rem);  /* Don't go haywire if a problem ... */
1600
1601         if (tree != NULL) {
1602                 /*chk for vendor-private*/
1603                 if(type>=TLV_VENDOR_PRIVATE_START && type<=TLV_VENDOR_PRIVATE_END){
1604                         typebak=type;           /*keep type*/   
1605                         type=TLV_VENDOR_PRIVATE_START;
1606
1607                 /*chk for experimental*/
1608                 } else if(type>=TLV_EXPERIMENTAL_START && type<=TLV_EXPERIMENTAL_END){
1609                         typebak=type;           /*keep type*/   
1610                         type=TLV_EXPERIMENTAL_START;
1611                 }
1612
1613                 ti = proto_tree_add_text(tree, tvb, offset, length + 4, "%s",
1614                         val_to_str(type, tlv_type_names, "Unknown TLV type (0x%04X)"));
1615                 tlv_tree = proto_item_add_subtree(ti, ett_ldp_tlv);
1616                 if(tlv_tree == NULL) return length+4;
1617
1618                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_unknown, tvb, offset, 1, FALSE);
1619
1620                 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 ); 
1621
1622                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_len, tvb, offset + 2, 2, FALSE);
1623
1624                 switch (type) {
1625
1626                 case TLV_FEC:
1627                         dissect_tlv_fec(tvb, offset + 4, tlv_tree, length);
1628                         break;
1629
1630                 case TLV_ADDRESS_LIST:
1631                         dissect_tlv_address_list(tvb, offset + 4, tlv_tree, length);
1632                         break;
1633
1634                 case TLV_HOP_COUNT:
1635                         if( length != 1 ) /*error, only one byte*/
1636                                 proto_tree_add_text(tlv_tree, tvb, offset + 4,length,
1637                                     "Error processing Hop Count TLV: length is %d, should be 1",
1638                                     length);
1639                         else
1640                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_hc_value, tvb,offset + 4, length, FALSE); 
1641                         break;
1642
1643                 case TLV_PATH_VECTOR:
1644                         dissect_tlv_path_vector(tvb, offset + 4, tlv_tree, length);
1645                         break;
1646
1647                 case TLV_GENERIC_LABEL:
1648                         if( length != 4 ) /*error, need only label*/
1649                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
1650                                     "Error processing Generic Label TLV: length is %d, should be 4",
1651                                     length);
1652                         else {
1653                                 guint32 label=tvb_get_ntohl(tvb, offset+4) & 0x000FFFFF;
1654
1655                                 proto_tree_add_uint_format(tlv_tree, hf_ldp_tlv_generic_label,
1656                                         tvb, offset+4, length, label, "Generic Label: %u", label); 
1657                         }
1658                         break;
1659
1660                 case TLV_ATM_LABEL:
1661                         dissect_tlv_atm_label(tvb, offset + 4, tlv_tree, length);
1662                         break;
1663
1664                 case TLV_FRAME_LABEL:
1665                         dissect_tlv_frame_label(tvb, offset + 4, tlv_tree, length);
1666                         break;
1667
1668                 case TLV_STATUS:
1669                         dissect_tlv_status(tvb, offset + 4, tlv_tree, length);
1670                         break;
1671
1672                 case TLV_EXTENDED_STATUS:
1673                         if( length != 4 ) /*error, need only status_code(guint32)*/
1674                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
1675                                     "Error processing Extended Status TLV: length is %d, should be 4",
1676                                     length);
1677                         else {
1678                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_extstatus_data, tvb, offset + 4, length, FALSE); 
1679                         }
1680                         break;
1681
1682                 case TLV_RETURNED_PDU:
1683                         dissect_tlv_returned_pdu(tvb, offset + 4, tlv_tree, length);
1684                         break;
1685
1686                 case TLV_RETURNED_MESSAGE:
1687                         dissect_tlv_returned_message(tvb, offset + 4, tlv_tree, length);
1688                         break;
1689
1690                 case TLV_COMMON_HELLO_PARMS:
1691 #if 0
1692                         dissect_tlv_common_hello_parms(tvb, offset + 4, tlv_tree, length);
1693 #else
1694                         dissect_tlv_common_hello_parms(tvb, offset + 4, tlv_tree);
1695 #endif
1696                         break;
1697
1698                 case TLV_IPV4_TRANSPORT_ADDRESS:
1699                         if( length != 4 ) /*error, need only ipv4*/
1700                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
1701                                     "Error processing IPv4 Transport Address TLV: length is %d, should be 4",
1702                                     length);
1703                         else {
1704                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_ipv4_taddr, tvb, offset + 4, 4, FALSE);
1705                         }
1706                         break;
1707
1708                 case TLV_CONFIGURATION_SEQNO:
1709                         if( length != 4 ) /*error, need only seq_num(guint32)*/
1710                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
1711                                     "Error processing Configuration Sequence Number TLV: length is %d, should be 4",
1712                                     length);
1713                         else {
1714                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_config_seqno, tvb, offset + 4, 4, FALSE);
1715                         }
1716                         break;
1717
1718                 case TLV_IPV6_TRANSPORT_ADDRESS:
1719                         if( length != 16 ) /*error, need only ipv6*/
1720                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
1721                                     "Error processing IPv6 Transport Address TLV: length is %d, should be 16",
1722                                     length);
1723                         else {
1724                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_ipv6_taddr, tvb, offset + 4, 16, FALSE);
1725                         }
1726                         break;
1727
1728                 case TLV_COMMON_SESSION_PARMS:
1729                         dissect_tlv_common_session_parms(tvb, offset + 4, tlv_tree, length);
1730                         break;
1731
1732                 case TLV_ATM_SESSION_PARMS:
1733                         dissect_tlv_atm_session_parms(tvb, offset + 4, tlv_tree, length);
1734                         break;
1735
1736                 case TLV_FRAME_RELAY_SESSION_PARMS:
1737                         dissect_tlv_frame_relay_session_parms(tvb, offset + 4, tlv_tree, length);
1738                         break;
1739
1740                 case TLV_LABEL_REQUEST_MESSAGE_ID:
1741                         if( length != 4 ) /*error, need only one msgid*/
1742                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
1743                                     "Error processing Label Request Message ID TLV: length is %d, should be 4",
1744                                     length);
1745                         else
1746                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_lbl_req_msg_id, tvb,offset + 4,length, FALSE); 
1747                         break;
1748
1749                 case TLV_LSPID:
1750                         dissect_tlv_lspid(tvb, offset + 4, tlv_tree, length);
1751                         break;
1752                         
1753                 case TLV_ER:
1754                         dissect_tlv_er(tvb, offset + 4, tlv_tree, length);
1755                         break;
1756                         
1757                 case TLV_ER_HOP_IPV4:
1758                         dissect_tlv_er_hop_ipv4(tvb, offset + 4, tlv_tree, length);
1759                         break;
1760                         
1761                 case TLV_ER_HOP_IPV6:
1762                         dissect_tlv_er_hop_ipv6(tvb, offset +4, tlv_tree, length);
1763                         break;
1764                         
1765                 case TLV_ER_HOP_AS:
1766                         dissect_tlv_er_hop_as(tvb, offset + 4, tlv_tree, length);
1767                         break;
1768                         
1769                 case TLV_ER_HOP_LSPID:
1770                         dissect_tlv_er_hop_lspid(tvb, offset +4, tlv_tree, length);
1771                         break;
1772                         
1773                 case TLV_TRAFFIC_PARAM:
1774                         dissect_tlv_traffic(tvb, offset +4, tlv_tree, length);
1775                         break;
1776                         
1777                 case TLV_PREEMPTION:
1778                         dissect_tlv_preemption(tvb, offset +4, tlv_tree, length);
1779                         break;
1780                         
1781                 case TLV_RESOURCE_CLASS:
1782                         dissect_tlv_resource_class(tvb, offset +4, tlv_tree, length);
1783                         break;
1784                         
1785                 case TLV_ROUTE_PINNING:
1786                         dissect_tlv_route_pinning(tvb, offset +4, tlv_tree, length);
1787                         break;
1788                         
1789                 case TLV_VENDOR_PRIVATE_START:
1790                         if( length < 4 ) /*error, at least Vendor ID*/
1791                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
1792                                     "Error processing Vendor Private Start TLV: length is %d, should be >= 4",
1793                                     length);
1794                         else {
1795                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_vendor_id, tvb,offset + 4, 4, FALSE); 
1796                                 if( length > 4 )  /*have data*/ 
1797                                         proto_tree_add_text(tlv_tree, tvb, offset + 8, length-4,"Data");
1798                         }
1799                         break;
1800
1801                 case TLV_EXPERIMENTAL_START:
1802                         if( length < 4 ) /*error, at least Experiment ID*/
1803                                 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
1804                                     "Error processing Experimental Start TLV: length is %d, should be >= 4",
1805                                     length);
1806                         else {
1807                                 proto_tree_add_item(tlv_tree, hf_ldp_tlv_experiment_id, tvb,offset + 4, 4, FALSE); 
1808                                 if( length > 4 )  /*have data*/ 
1809                                         proto_tree_add_text(tlv_tree, tvb, offset + 8, length-4,"Data");
1810                         }
1811                         break;
1812
1813                 default:
1814                         proto_tree_add_item(tlv_tree, hf_ldp_tlv_value, tvb, offset + 4, length, FALSE);
1815                         break;
1816                 }
1817         }
1818
1819         return length + 4;  /* Length of the value field + header */
1820 }
1821
1822
1823 /* Dissect a Message and return the number of bytes consumed ... */
1824
1825 static int
1826 dissect_msg(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree)
1827 {
1828         guint16 type, typebak;
1829         guint8  extra=0;
1830         int length, rem, ao=0, co;
1831         proto_tree *ti = NULL, *msg_tree = NULL;
1832
1833         rem=tvb_reported_length_remaining(tvb, offset);
1834
1835         if( rem < 8 ) {/*chk for minimum header = type + length + msg_id*/
1836                 if( check_col(pinfo->cinfo, COL_INFO) )
1837                         col_append_fstr(pinfo->cinfo, COL_INFO, "Bad Message");
1838                 if(tree)
1839                         proto_tree_add_text(tree, tvb, offset, rem,
1840                             "Error processing Message: length is %d, should be >= 8",
1841                             rem);
1842                 return rem;
1843         }
1844         type = tvb_get_ntohs(tvb, offset) & 0x7FFF;
1845
1846         /*chk for vendor-private*/
1847         if(type>=LDP_VENDOR_PRIVATE_START && type<=LDP_VENDOR_PRIVATE_END){
1848                 typebak=type;           /*keep type*/   
1849                 type=LDP_VENDOR_PRIVATE_START;
1850                 extra=4;
1851         /*chk for experimental*/
1852         } else if(type>=LDP_EXPERIMENTAL_MESSAGE_START && type<=LDP_EXPERIMENTAL_MESSAGE_END){
1853                 typebak=type;           /*keep type*/   
1854                 type=LDP_EXPERIMENTAL_MESSAGE_START;
1855                 extra=4;
1856         }
1857
1858         if( (length = tvb_get_ntohs(tvb, offset + 2)) < (4+extra) ) {/*not enough data for type*/
1859                 if( check_col(pinfo->cinfo, COL_INFO) )
1860                         col_append_fstr(pinfo->cinfo, COL_INFO, "Bad Message Length ");
1861                 if(tree)
1862                         proto_tree_add_text(tree, tvb, offset, rem,
1863                             "Error processing Message Length: length is %d, should be >= %u",
1864                             length, 4+extra);
1865                 return rem;
1866         }
1867         rem -= 4; 
1868         length = MIN(length, rem);  /* Don't go haywire if a problem ... */
1869
1870         if( check_col(pinfo->cinfo, COL_INFO) ){
1871                 col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(type, ldp_message_types, "Unknown Message (0x%04X)"));
1872         }
1873
1874         if( tree ){
1875                 ti = proto_tree_add_text(tree, tvb, offset, length + 4, "%s",
1876                         val_to_str(type, ldp_message_types, "Unknown Message type (0x%04X)"));
1877                 msg_tree = proto_item_add_subtree(ti, ett_ldp_message);
1878                 if(msg_tree == NULL) return length+4;
1879
1880                 proto_tree_add_item(msg_tree, hf_ldp_msg_ubit, tvb, offset, 1, FALSE);
1881
1882                 type=tvb_get_ntohs(tvb, offset)&0x7FFF;
1883                 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); 
1884
1885                 proto_tree_add_item(msg_tree, hf_ldp_msg_len, tvb, offset+2, 2, FALSE);
1886                 proto_tree_add_item(msg_tree, hf_ldp_msg_id, tvb, offset+4, 4, FALSE);
1887                 if(extra){
1888                         int hf_tmp=0;
1889
1890                         switch(type){
1891                                 case LDP_VENDOR_PRIVATE_START:
1892                                         hf_tmp=hf_ldp_msg_vendor_id;
1893                                         break;
1894                                 case LDP_EXPERIMENTAL_MESSAGE_START:
1895                                         hf_tmp=hf_ldp_msg_experiment_id;
1896                                         break;
1897                         }
1898                         proto_tree_add_item(msg_tree, hf_tmp, tvb, offset+8, extra, FALSE);
1899                 }
1900         }
1901                 
1902         offset += (8+extra);
1903         length -= (4+extra);
1904         
1905         if( tree )      
1906                 while( (length-ao) > 0 ) {
1907                         co=dissect_tlv(tvb, offset, msg_tree, length-ao);
1908                         offset += co;
1909                         ao += co;
1910                 }
1911         
1912         return length+8+extra;
1913 }
1914
1915 /* Dissect a PDU */
1916 static void
1917 dissect_ldp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1918 {
1919         int offset = 0, co;
1920         int rem, length;
1921         proto_tree *ti=NULL, *pdu_tree = NULL;
1922         
1923         if (check_col(pinfo->cinfo, COL_PROTOCOL))
1924                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "LDP");
1925
1926         if (check_col(pinfo->cinfo, COL_INFO))
1927                 col_clear(pinfo->cinfo, COL_INFO);
1928
1929         if( tree ){
1930                 ti=proto_tree_add_item(tree, proto_ldp, tvb, 0, -1, FALSE);
1931                 pdu_tree = proto_item_add_subtree(ti, ett_ldp);
1932
1933                 proto_tree_add_item(pdu_tree, hf_ldp_version, tvb, offset, 2, FALSE);
1934         }
1935
1936         length = tvb_get_ntohs(tvb, offset+2);
1937         if( tree )
1938                 proto_tree_add_uint(pdu_tree, hf_ldp_pdu_len, tvb, offset+2, 2, length);
1939
1940         length += 4;    /* add the version and type sizes */
1941         rem = tvb_reported_length_remaining(tvb, offset);
1942         if (length < rem)
1943                 tvb_set_reported_length(tvb, length);
1944
1945         if( tree ){
1946                 proto_tree_add_item(pdu_tree, hf_ldp_lsr, tvb, offset+4, 4, FALSE);
1947                 proto_tree_add_item(pdu_tree, hf_ldp_ls_id, tvb, offset+8, 2, FALSE);
1948         }
1949         offset += 10;
1950
1951         while( tvb_reported_length_remaining(tvb, offset) > 0 ) {
1952                 co=dissect_msg(tvb, offset, pinfo, pdu_tree);
1953                 offset += co;
1954         }
1955 }
1956
1957 static int
1958 dissect_ldp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1959 {
1960         /*
1961          * Make sure the first PDU has a version number of 1;
1962          * if not, reject this, so we don't get confused by
1963          * packets that happen to be going to or from the
1964          * LDP port but that aren't LDP packets.
1965          */
1966         if (!tvb_bytes_exist(tvb, 0, 2)) {
1967                 /*
1968                  * Not enough information to tell.
1969                  */
1970                 return 0;
1971         }
1972         if (tvb_get_ntohs(tvb, 0) != 1) {
1973                 /*
1974                  * Not version 1.
1975                  */
1976                 return 0;
1977         }
1978
1979         dissect_ldp_pdu(tvb, pinfo, tree);
1980
1981         /*
1982          * XXX - return minimum of this and the length of the PDU?
1983          */
1984         return tvb_length(tvb);
1985 }
1986
1987 static int
1988 dissect_ldp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1989
1990         volatile gboolean first = TRUE;
1991         volatile int offset = 0;
1992         int length_remaining;
1993         guint16 plen;
1994         int length;
1995         tvbuff_t *next_tvb;
1996   
1997         while (tvb_reported_length_remaining(tvb, offset) != 0) {
1998                 length_remaining = tvb_length_remaining(tvb, offset);
1999
2000                 /*
2001                  * Make sure the first PDU has a version number of 1;
2002                  * if not, reject this, so we don't get confused by
2003                  * packets that happen to be going to or from the
2004                  * LDP port but that aren't LDP packets.
2005                  *
2006                  * XXX - this means we can't handle an LDP PDU of which
2007                  * only one byte appears in a TCP segment.  If that's
2008                  * a problem, we'll either have to completely punt on
2009                  * rejecting non-LDP packets, or will have to assume
2010                  * that if we have only one byte, it's an LDP packet.
2011                  */
2012                 if (first) {
2013                         if (length_remaining < 2) {
2014                                 /*
2015                                  * Not enough information to tell.
2016                                  */
2017                                 return 0;
2018                         }
2019                         if (tvb_get_ntohs(tvb, offset) != 1) {
2020                                 /*
2021                                  * Not version 1.
2022                                  */
2023                                 return 0;
2024                         }
2025                         first = FALSE;
2026                 }
2027
2028                 /*
2029                  * Can we do reassembly?
2030                  */
2031                 if (ldp_desegment && pinfo->can_desegment) {
2032                         /*
2033                          * Yes - is the LDP header split across segment
2034                          * boundaries?
2035                          */
2036                         if (length_remaining < 4) {
2037                                 /*
2038                                  * Yes.  Tell the TCP dissector where
2039                                  * the data for this message starts in
2040                                  * the data it handed us, and how many
2041                                  * more bytes we need, and return.
2042                                  */
2043                                 pinfo->desegment_offset = offset;
2044                                 pinfo->desegment_len = 4 - length_remaining;
2045                                 return -pinfo->desegment_len;
2046                         }
2047                 }
2048
2049                 /*
2050                  * Get the length of the rest of the LDP packet.
2051                  * XXX - check for a version of 1 first?
2052                  */
2053                 plen = tvb_get_ntohs(tvb, offset + 2);
2054
2055                 /*
2056                  * Can we do reassembly?
2057                  */
2058                 if (ldp_desegment && pinfo->can_desegment) {
2059                         /*
2060                          * Yes - is the LDP packet split across segment
2061                          * boundaries?
2062                          */
2063                         if (length_remaining < plen + 4) {
2064                                 /*
2065                                  * Yes.  Tell the TCP dissector where the
2066                                  * data for this message starts in the data
2067                                  * it handed us, and how many more bytes we
2068                                  * need, and return.
2069                                  */
2070                                 pinfo->desegment_offset = offset;
2071                                 pinfo->desegment_len =
2072                                     (plen + 4) - length_remaining;
2073                                 return -pinfo->desegment_len;
2074                         }
2075                 }
2076
2077                 /*
2078                  * Construct a tvbuff containing the amount of the payload
2079                  * we have available.  Make its reported length the
2080                  * amount of data in the DNS-over-TCP packet.
2081                  *
2082                  * XXX - if reassembly isn't enabled. the subdissector
2083                  * will throw a BoundsError exception, rather than a
2084                  * ReportedBoundsError exception.  We really want
2085                  * a tvbuff where the length is "length", the reported
2086                  * length is "plen + 4", and the "if the snapshot length
2087                  * were infinite" length is the minimum of the
2088                  * reported length of the tvbuff handed to us and "plen+4",
2089                  * with a new type of exception thrown if the offset is
2090                  * within the reported length but beyond that third length,
2091                  * with that exception getting the "Unreassembled Packet"
2092                  * error.
2093                  */
2094                 length = length_remaining;
2095                 if (length > plen + 4)
2096                         length = plen + 4;
2097                 next_tvb = tvb_new_subset(tvb, offset, length, plen + 4);
2098
2099                 /*
2100                  * Dissect the LDP packet.
2101                  *
2102                  * Catch the ReportedBoundsError exception; if this
2103                  * particular message happens to get a ReportedBoundsError
2104                  * exception, that doesn't mean that we should stop
2105                  * dissecting LDP messages within this frame or chunk of
2106                  * reassembled data.
2107                  *
2108                  * If it gets a BoundsError, we can stop, as there's nothing
2109                  * more to see, so we just re-throw it.
2110                  */
2111                 TRY {
2112                         dissect_ldp_pdu(next_tvb, pinfo, tree);
2113                 }
2114                 CATCH(BoundsError) {
2115                         RETHROW;
2116                 }
2117                 CATCH(ReportedBoundsError) {
2118                         show_reported_bounds_error(tvb, pinfo, tree);
2119                 }
2120                 ENDTRY;
2121
2122                 /*
2123                  * Skip the LDP header and the payload.
2124                  */
2125                 offset += plen + 4;
2126         }
2127         return tvb_length(tvb);
2128 }
2129
2130 /* Register all the bits needed with the filtering engine */
2131
2132 void 
2133 proto_register_ldp(void)
2134 {
2135   static hf_register_info hf[] = {
2136     { &hf_ldp_req,
2137       /* Change the following to the type you need */
2138       { "Request", "ldp.req", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
2139
2140     { &hf_ldp_rsp,
2141       { "Response", "ldp.rsp", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
2142
2143     { &hf_ldp_version,
2144       { "Version", "ldp.hdr.version", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Version Number", HFILL }},
2145
2146     { &hf_ldp_pdu_len,
2147       { "PDU Length", "ldp.hdr.pdu_len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP PDU Length", HFILL }},
2148
2149     { &hf_ldp_lsr,
2150       { "LSR ID", "ldp.hdr.ldpid.lsr", FT_IPv4, BASE_HEX, NULL, 0x0, "LDP Label Space Router ID", HFILL }},
2151
2152     { &hf_ldp_ls_id,
2153       { "Label Space ID", "ldp.hdr.ldpid.lsid", FT_UINT16, BASE_DEC, NULL, 0, "LDP Label Space ID", HFILL }},
2154
2155     { &hf_ldp_msg_ubit,
2156       { "U bit", "ldp.msg.ubit", FT_BOOLEAN, 8, TFS(&ldp_message_ubit), 0x80, "Unknown Message Bit", HFILL }},
2157
2158     { &hf_ldp_msg_type,
2159       { "Message Type", "ldp.msg.type", FT_UINT16, BASE_HEX, VALS(ldp_message_types), 0x7FFF, "LDP message type", HFILL }},
2160
2161     { &hf_ldp_msg_len,
2162       { "Message Length", "ldp.msg.len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Message Length (excluding message type and len)", HFILL }},
2163
2164     { &hf_ldp_msg_id, 
2165       { "Message ID", "ldp.msg.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Message ID", HFILL }},
2166
2167     { &hf_ldp_msg_vendor_id, 
2168       { "Vendor ID", "ldp.msg.vendor.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Vendor-private Message ID", HFILL }},
2169
2170     { &hf_ldp_msg_experiment_id, 
2171       { "Experiment ID", "ldp.msg.experiment.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Experimental Message ID", HFILL }},
2172
2173     { &hf_ldp_tlv_unknown, 
2174       { "TLV Unknown bits", "ldp.msg.tlv.unknown", FT_UINT8, BASE_HEX, VALS(tlv_unknown_vals), 0xC0, "TLV Unknown bits Field", HFILL }},
2175
2176     { &hf_ldp_tlv_type, 
2177       { "TLV Type", "ldp.msg.tlv.type", FT_UINT16, BASE_HEX, VALS(tlv_type_names), 0x3FFF, "TLV Type Field", HFILL }},
2178
2179     { &hf_ldp_tlv_len,
2180       {"TLV Length", "ldp.msg.tlv.len", FT_UINT16, BASE_DEC, NULL, 0x0, "TLV Length Field", HFILL }},
2181
2182     { &hf_ldp_tlv_value,
2183       { "TLV Value", "ldp.msg.tlv.value", FT_BYTES, BASE_NONE, NULL, 0x0, "TLV Value Bytes", HFILL }},
2184
2185     { &hf_ldp_tlv_val_hold,
2186       { "Hold Time", "ldp.msg.tlv.hello.hold", FT_UINT16, BASE_DEC, NULL, 0x0, "Hello Common Parameters Hold Time", HFILL }},
2187
2188     { &hf_ldp_tlv_val_target,
2189       { "Targeted Hello", "ldp.msg.tlv.hello.targeted", FT_BOOLEAN, 16, TFS(&hello_targeted_vals), 0x8000, "Hello Common Parameters Targeted Bit", HFILL }},
2190
2191     { &hf_ldp_tlv_val_request,
2192       { "Hello Requested", "ldp,msg.tlv.hello.requested", FT_BOOLEAN, 16, TFS(&hello_requested_vals), 0x4000, "Hello Common Parameters Hello Requested Bit", HFILL }},
2193  
2194     { &hf_ldp_tlv_val_res,
2195       { "Reserved", "ldp.msg.tlv.hello.res", FT_UINT16, BASE_HEX, NULL, 0x3FFF, "Hello Common Parameters Reserved Field", HFILL }},
2196
2197     { &hf_ldp_tlv_ipv4_taddr,
2198       { "IPv4 Transport Address", "ldp.msg.tlv.ipv4.taddr", FT_IPv4, BASE_DEC, NULL, 0x0, "IPv4 Transport Address", HFILL }},
2199
2200     { &hf_ldp_tlv_config_seqno,
2201       { "Configuration Sequence Number", "ldp.msg.tlv.hello.cnf_seqno", FT_UINT32, BASE_DEC, NULL, 0x0, "Hello Configuration Sequence Number", HFILL }},
2202
2203     { &hf_ldp_tlv_ipv6_taddr,
2204       { "IPv6 Transport Address", "ldp.msg.tlv.ipv6.taddr", FT_IPv6, BASE_DEC, NULL, 0x0, "IPv6 Transport Address", HFILL }},
2205
2206     { &hf_ldp_tlv_fec_wc,
2207       { "FEC Element Type", "ldp.msg.tlv.fec.type", FT_UINT8, BASE_DEC, VALS(fec_types), 0x0, "Forwarding Equivalence Class Element Types", HFILL }},
2208
2209     { &hf_ldp_tlv_fec_af,
2210       { "FEC Element Address Type", "ldp.msg.tlv.fec.af", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, "Forwarding Equivalence Class Element Address Family", HFILL }},
2211
2212     { &hf_ldp_tlv_fec_len,
2213       { "FEC Element Length", "ldp.msg.tlv.fec.len", FT_UINT8, BASE_DEC, NULL, 0x0, "Forwarding Equivalence Class Element Length", HFILL }},
2214
2215     { &hf_ldp_tlv_fec_pfval,
2216       { "FEC Element Prefix Value", "ldp.msg.tlv.fec.pfval", FT_STRING, BASE_NONE, NULL, 0x0, "Forwarding Equivalence Class Element Prefix", HFILL }},
2217
2218     { &hf_ldp_tlv_fec_hoval,
2219       { "FEC Element Host Address Value", "ldp.msg.tlv.fec.hoval", FT_STRING, BASE_NONE, NULL, 0x0, "Forwarding Equivalence Class Element Address", HFILL }},
2220
2221     { &hf_ldp_tlv_addrl_addr_family,
2222       { "Address Family", "ldp.msg.tlv.addrl.addr_family", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, "Address Family List", HFILL }},
2223
2224     { &hf_ldp_tlv_addrl_addr,
2225       { "Address", "ldp.msg.tlv.addrl.addr", FT_STRING, BASE_NONE, NULL, 0x0, "Address", HFILL }},
2226
2227     { &hf_ldp_tlv_hc_value,
2228       { "Hop Count Value", "ldp.msg.tlv.hc.value", FT_UINT8, BASE_DEC, NULL, 0x0, "Hop Count", HFILL }},
2229
2230     { &hf_ldp_tlv_pv_lsrid,
2231       { "LSR Id", "ldp.msg.tlv.pv.lsrid", FT_IPv4, BASE_DEC, NULL, 0x0, "Path Vector LSR Id", HFILL }},
2232
2233     { &hf_ldp_tlv_sess_ver,
2234       { "Session Protocol Version", "ldp.msg.tlv.sess.ver", FT_UINT16, BASE_DEC, NULL, 0x0, "Common Session Parameters Protocol Version", HFILL }},
2235
2236     { &hf_ldp_tlv_sess_ka,
2237       { "Session KeepAlive Time", "ldp.msg.tlv.sess.ka", FT_UINT16, BASE_DEC, NULL, 0x0, "Common Session Parameters KeepAlive Time", HFILL }},
2238
2239     { &hf_ldp_tlv_sess_advbit,
2240       { "Session Label Advertisement Discipline", "ldp.msg.tlv.sess.advbit",
2241  FT_BOOLEAN, 8, TFS(&tlv_sess_advbit_vals), 0x80, 
2242         "Common Session Parameters Label Advertisement Discipline", HFILL }},
2243
2244     { &hf_ldp_tlv_sess_ldetbit,
2245       { "Session Loop Detection", "ldp.msg.tlv.sess.ldetbit", FT_BOOLEAN, 8, TFS(&tlv_sess_ldetbit_vals), 0x40, "Common Session Parameters Loop Detection", HFILL }},
2246
2247     { &hf_ldp_tlv_sess_pvlim,
2248       { "Session Path Vector Limit", "ldp.msg.tlv.sess.pvlim", FT_UINT8, BASE_DEC, NULL, 0x0, "Common Session Parameters Path Vector Limit", HFILL }},
2249
2250     { &hf_ldp_tlv_sess_mxpdu,
2251       { "Session Max PDU Length", "ldp.msg.tlv.sess.mxpdu", FT_UINT16, BASE_DEC, NULL, 0x0, "Common Session Parameters Max PDU Length", HFILL }},
2252
2253     { &hf_ldp_tlv_sess_rxlsr,
2254       { "Session Receiver LSR Identifier", "ldp.msg.tlv.sess.rxlsr", FT_IPv4, BASE_DEC, NULL, 0x0, "Common Session Parameters LSR Identifier", HFILL }},
2255
2256     { &hf_ldp_tlv_sess_rxls,
2257       { "Session Receiver Label Space Identifier", "ldp.msg.tlv.sess.rxlsr", FT_UINT16, BASE_DEC, NULL, 0x0, "Common Session Parameters Receiver Label Space Identifier", HFILL }},
2258
2259     { &hf_ldp_tlv_sess_atm_merge,
2260       { "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 }},
2261
2262     { &hf_ldp_tlv_sess_atm_lr,
2263       { "Number of ATM Label Ranges", "ldp.msg.tlv.sess.atm.lr", FT_UINT8, BASE_DEC, NULL, 0x3C, "Number of Label Ranges", HFILL }},
2264
2265     { &hf_ldp_tlv_sess_atm_dir,
2266       { "Directionality", "ldp.msg.tlv.sess.atm.dir", FT_BOOLEAN, 8, TFS(&tlv_atm_dirbit), 0x02, "Lablel Directionality", HFILL }},
2267
2268     { &hf_ldp_tlv_sess_atm_minvpi,
2269       { "Minimum VPI", "ldp.msg.tlv.sess.atm.minvpi", FT_UINT16, BASE_DEC, NULL, 0x0FFF, "Minimum VPI", HFILL }},
2270
2271     { &hf_ldp_tlv_sess_atm_minvci,
2272       { "Minimum VCI", "ldp.msg.tlv.sess.atm.minvci", FT_UINT16, BASE_DEC, NULL, 0x0, "Minimum VCI", HFILL }},
2273
2274     { &hf_ldp_tlv_sess_atm_maxvpi,
2275       { "Maximum VPI", "ldp.msg.tlv.sess.atm.maxvpi", FT_UINT16, BASE_DEC, NULL, 0x0FFF, "Maximum VPI", HFILL }},
2276
2277     { &hf_ldp_tlv_sess_atm_maxvci,
2278       { "Maximum VCI", "ldp.msg.tlv.sess.atm.maxvci", FT_UINT16, BASE_DEC, NULL, 0x0, "Maximum VCI", HFILL }},
2279
2280     { &hf_ldp_tlv_sess_fr_merge,
2281       { "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 }},
2282
2283     { &hf_ldp_tlv_sess_fr_lr,
2284       { "Number of Frame Relay Label Ranges", "ldp.msg.tlv.sess.fr.lr", FT_UINT8, BASE_DEC, NULL, 0x3C, "Number of Label Ranges", HFILL }},
2285
2286     { &hf_ldp_tlv_sess_fr_dir,
2287       { "Directionality", "ldp.msg.tlv.sess.fr.dir", FT_BOOLEAN, 8, TFS(&tlv_atm_dirbit), 0x02, "Lablel Directionality", HFILL }},
2288
2289     { &hf_ldp_tlv_sess_fr_len,
2290       { "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 }},
2291
2292     { &hf_ldp_tlv_sess_fr_mindlci,
2293       { "Minimum DLCI", "ldp.msg.tlv.sess.fr.mindlci", FT_UINT24, BASE_DEC, NULL, 0x7FFFFF, "Minimum DLCI", HFILL }},
2294
2295     { &hf_ldp_tlv_sess_fr_maxdlci,
2296       { "Maximum DLCI", "ldp.msg.tlv.sess.fr.maxdlci", FT_UINT24, BASE_DEC, NULL, 0x7FFFFF, "Maximum DLCI", HFILL }},
2297
2298     { &hf_ldp_tlv_lbl_req_msg_id, 
2299       { "Label Request Message ID", "ldp.tlv.lbl_req_msg_id", FT_UINT32, BASE_HEX, NULL, 0x0, "Label Request Message to be aborted", HFILL }},
2300
2301     { &hf_ldp_tlv_vendor_id,
2302       { "Vendor ID", "ldp.msg.tlv.vendor_id", FT_UINT32, BASE_HEX, NULL, 0, "IEEE 802 Assigned Vendor ID", HFILL }},
2303
2304     { &hf_ldp_tlv_experiment_id,
2305       { "Experiment ID", "ldp.msg.tlv.experiment_id", FT_UINT32, BASE_HEX, NULL, 0, "Experiment ID", HFILL }},
2306
2307     { &hf_ldp_tlv_generic_label,
2308       { "Generic Label", "ldp.msg.tlv.generic.label", FT_UINT32, BASE_HEX, NULL, 0x000FFFFF, "Generic Label", HFILL }},
2309
2310     { &hf_ldp_tlv_atm_label_vbits,
2311       { "V-bits", "ldp.msg.tlv.atm.label.vbits", FT_UINT8, BASE_HEX, VALS(tlv_atm_vbits_vals), 0x30, "ATM Label V Bits", HFILL }},
2312
2313     { &hf_ldp_tlv_atm_label_vpi,
2314       { "VPI", "ldp.msg.tlv.atm.label.vpi", FT_UINT16, BASE_DEC, NULL, 0x0FFF, "ATM Label VPI", HFILL }},
2315
2316     { &hf_ldp_tlv_atm_label_vci,
2317       { "VCI", "ldp.msg.tlv.atm.label.vci", FT_UINT16, BASE_DEC, NULL, 0, "ATM Label VCI", HFILL }},
2318
2319     { &hf_ldp_tlv_fr_label_len,
2320       { "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 }},
2321
2322     { &hf_ldp_tlv_fr_label_dlci,
2323       { "DLCI", "ldp.msg.tlv.fr.label.dlci", FT_UINT24, BASE_DEC, NULL, 0x7FFFFF, "FRAME RELAY Label DLCI", HFILL }},
2324
2325     { &hf_ldp_tlv_status_ebit,
2326       { "E Bit", "ldp.msg.tlv.status.ebit", FT_BOOLEAN, 8, TFS(&tlv_status_ebit), 0x80, "Fatal Error Bit", HFILL }},
2327
2328     { &hf_ldp_tlv_status_fbit,
2329       { "F Bit", "ldp.msg.tlv.status.fbit", FT_BOOLEAN, 8, TFS(&tlv_status_fbit), 0x40, "Forward Bit", HFILL }},
2330
2331     { &hf_ldp_tlv_status_data,
2332       { "Status Data", "ldp.msg.tlv.status.data", FT_UINT32, BASE_HEX, VALS(tlv_status_data), 0x3FFFFFFF, "Status Data", HFILL }},
2333
2334     { &hf_ldp_tlv_status_msg_id, 
2335       { "Message ID", "ldp.msg.tlv.status.msg.id", FT_UINT32, BASE_HEX, NULL, 0x0, "Identifies peer message to which Status TLV refers", HFILL }},
2336
2337     { &hf_ldp_tlv_status_msg_type,
2338       { "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 }},
2339
2340     { &hf_ldp_tlv_extstatus_data,
2341       { "Extended Status Data", "ldp.msg.tlv.extstatus.data", FT_UINT32, BASE_HEX, NULL, 0x0, "Extended Status Data", HFILL }},
2342
2343     { &hf_ldp_tlv_returned_version,
2344       { "Returned PDU Version", "ldp.msg.tlv.returned.version", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Version Number", HFILL }},
2345
2346     { &hf_ldp_tlv_returned_pdu_len,
2347       { "Returned PDU Length", "ldp.msg.tlv.returned.pdu_len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP PDU Length", HFILL }},
2348
2349     { &hf_ldp_tlv_returned_lsr,
2350       { "Returned PDU LSR ID", "ldp.msg.tlv.returned.ldpid.lsr", FT_IPv4, BASE_DEC, NULL, 0x0, "LDP Label Space Router ID", HFILL }},
2351
2352     { &hf_ldp_tlv_returned_ls_id,
2353       { "Returned PDU Label Space ID", "ldp.msg.tlv.returned.ldpid.lsid", FT_UINT16, BASE_HEX, NULL, 0x0, "LDP Label Space ID", HFILL }},
2354
2355     { &hf_ldp_tlv_returned_msg_ubit, 
2356       { "Returned Message Unknown bit", "ldp.msg.tlv.returned.msg.ubit", FT_UINT8, BASE_HEX, TFS(&ldp_message_ubit), 0x80, "Message Unknown bit", HFILL }},
2357
2358     { &hf_ldp_tlv_returned_msg_type,
2359       { "Returned Message Type", "ldp.msg.tlv.returned.msg.type", FT_UINT16, BASE_HEX, VALS(ldp_message_types), 0x7FFF, "LDP message type", HFILL }},
2360
2361     { &hf_ldp_tlv_returned_msg_len,
2362       { "Returned Message Length", "ldp.msg.tlv.returned.msg.len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Message Length (excluding message type and len)", HFILL }},
2363
2364     { &hf_ldp_tlv_returned_msg_id, 
2365       { "Returned Message ID", "ldp.msg.tlv.returned.msg.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Message ID", HFILL }},
2366
2367     {&hf_ldp_tlv_fec_vc_controlword,
2368      {"C-bit", "ldp.msg.tlv.fec.vc.controlword", FT_BOOLEAN, 8, TFS(&fec_vc_cbit), 0x80, "Control Word Present", HFILL }},
2369
2370     {&hf_ldp_tlv_fec_vc_vctype,
2371      {"VC Type", "ldp.msg.tlv.fec.vc.vctype", FT_UINT16, BASE_HEX, VALS(fec_vc_types_vals), 0x7FFF, "Virtual Circuit Type", HFILL }},
2372
2373     {&hf_ldp_tlv_fec_vc_infolength,
2374      {"VC Info Length", "ldp.msg.tlv.fec.vc.infolength", FT_UINT8, BASE_DEC, NULL, 0x0, "VC FEC Info Length", HFILL }},
2375
2376     {&hf_ldp_tlv_fec_vc_groupid,
2377      {"Group ID", "ldp.msg.tlv.fec.vc.groupid", FT_UINT32, BASE_DEC, NULL, 0x0, "VC FEC Group ID", HFILL }},
2378
2379     {&hf_ldp_tlv_fec_vc_vcid,
2380      {"VC ID", "ldp.msg.tlv.fec.vc.vcid", FT_UINT32, BASE_DEC, NULL, 0x0, "VC FEC VCID", HFILL }},
2381
2382     {&hf_ldp_tlv_fec_vc_intparam_length,
2383      {"Length", "ldp.msg.tlv.fec.vc.intparam.length", FT_UINT8, BASE_DEC, NULL, 0x0, "VC FEC Interface Paramater Length", HFILL }},
2384
2385     {&hf_ldp_tlv_fec_vc_intparam_mtu,
2386      {"MTU", "ldp.msg.tlv.fec.vc.intparam.mtu", FT_UINT16, BASE_DEC, NULL, 0x0, "VC FEC Interface Paramater MTU", HFILL }},
2387
2388     {&hf_ldp_tlv_fec_vc_intparam_id,
2389      {"ID", "ldp.msg.tlv.fec.vc.intparam.id", FT_UINT8, BASE_HEX, VALS(fec_vc_interfaceparm), 0x0, "VC FEC Interface Paramater ID", HFILL }},
2390
2391     {&hf_ldp_tlv_fec_vc_intparam_maxcatmcells,
2392      {"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 }},
2393
2394     { &hf_ldp_tlv_fec_vc_intparam_desc,
2395       { "Description", "ldp.msg.tlv.fec.vc.intparam.desc", FT_STRING, BASE_DEC, NULL, 0, "VC FEC Interface Description", HFILL }},
2396
2397     {&hf_ldp_tlv_fec_vc_intparam_cembytes,
2398      {"Payload Bytes", "ldp.msg.tlv.fec.vc.intparam.cembytes", FT_UINT16, BASE_DEC, NULL, 0x0, "VC FEC Interface Param CEM Payload Bytes", HFILL }},
2399
2400     { &hf_ldp_tlv_lspid_act_flg,
2401       { "Action Indicator Flag", "ldp.msg.tlv.lspid.actflg", FT_UINT16, BASE_HEX, VALS(ldp_act_flg_vals), 0x000F, "Action Indicator Flag", HFILL}},
2402
2403     { &hf_ldp_tlv_lspid_cr_lsp,
2404       { "Local CR-LSP ID", "ldp.msg.tlv.lspid.locallspid", FT_UINT16, BASE_HEX, NULL, 0x0, "Local CR-LSP ID", HFILL}},
2405
2406     { &hf_ldp_tlv_lspid_ldpid,
2407       { "Ingress LSR Router ID", "ldp.msg.tlv.lspid.lsrid", FT_IPv4, BASE_DEC, NULL, 0x0, "Ingress LSR Router ID", HFILL}},
2408
2409     { &hf_ldp_tlv_er_hop_loose,
2410       { "Loose route bit", "ldp.msg.tlv.er_hop.loose", FT_UINT24, BASE_HEX, VALS(ldp_loose_vals), 0x800000, "Loose route bit", HFILL}},
2411
2412     { &hf_ldp_tlv_er_hop_prelen,
2413       { "Prefix length", "ldp.msg.tlv.er_hop.prefixlen", FT_UINT8, BASE_DEC, NULL, 0x0, "Prefix len", HFILL}},
2414
2415     { &hf_ldp_tlv_er_hop_prefix4,
2416       { "IPv4 Address", "ldp.msg.tlv.er_hop.prefix4", FT_IPv4, BASE_DEC, NULL, 0x0, "IPv4 Address", HFILL}},
2417    { &hf_ldp_tlv_er_hop_prefix6,
2418      { "IPv6 Address", "ldp.msg.tlv.er_hop.prefix6", FT_IPv6, BASE_DEC, NULL, 0x0, "IPv6 Address", HFILL}},
2419     
2420     { &hf_ldp_tlv_er_hop_as,
2421       { "AS Number", "ldp.msg.tlv.er_hop.as", FT_UINT16, BASE_DEC, NULL, 0x0, "AS Number", HFILL}},
2422     
2423     { &hf_ldp_tlv_er_hop_cr_lsp,
2424       { "Local CR-LSP ID", "ldp.msg.tlv.er_hop.locallspid", FT_UINT16, BASE_DEC, NULL, 0x0, "Local CR-LSP ID", HFILL}},
2425     
2426     { &hf_ldp_tlv_er_hop_ldpid,
2427       { "Local CR-LSP ID", "ldp.msg.tlv.er_hop.lsrid", FT_IPv4, BASE_DEC, NULL, 0x0, "Local CR-LSP ID", HFILL}},
2428
2429     { &hf_ldp_tlv_flags_reserv,
2430       { "Reserved", "ldp.msg.tlv.flags_reserv", FT_UINT8, BASE_HEX, NULL, 0xC0, "Reserved", HFILL}},
2431     
2432     { &hf_ldp_tlv_flags_pdr,
2433       { "PDR", "ldp.msg.tlv.flags_pdr", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x1, "PDR negotiability flag", HFILL}},
2434     
2435     { &hf_ldp_tlv_flags_pbs,
2436       { "PBS", "ldp.msg.tlv.flags_pbs", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x2, "PBS negotiability flag", HFILL}},
2437     
2438     { &hf_ldp_tlv_flags_cdr,
2439       { "CDR", "ldp.msg.tlv.flags_cdr", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x4, "CDR negotiability flag", HFILL}},
2440     
2441     { &hf_ldp_tlv_flags_cbs,
2442       { "CBS", "ldp.msg.tlv.flags_cbs", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x8, "CBS negotiability flag", HFILL}},
2443     
2444     { &hf_ldp_tlv_flags_ebs,
2445       { "EBS", "ldp.msg.tlv.flags_ebs", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x10, "EBS negotiability flag", HFILL}},
2446     
2447     { &hf_ldp_tlv_flags_weight,
2448       { "Weight", "ldp.msg.tlv.flags_weight", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x20, "Weight negotiability flag", HFILL}},
2449     
2450     { &hf_ldp_tlv_frequency,
2451       { "Frequency", "ldp.msg.tlv.frequency", FT_UINT8, BASE_DEC, VALS(freq_values), 0, "Frequency", HFILL}},
2452     
2453     { &hf_ldp_tlv_weight,
2454       { "Weight", "ldp.msg.tlv.weight", FT_UINT8, BASE_DEC, NULL, 0, "Weight of the CR-LSP", HFILL}},
2455     
2456     { &hf_ldp_tlv_pdr,
2457       { "PDR", "ldp.msg.tlv.pdr", FT_DOUBLE, BASE_NONE, NULL, 0, "Peak Data Rate", HFILL}},
2458     
2459     { &hf_ldp_tlv_pbs,
2460       { "PBS", "ldp.msg.tlv.pbs", FT_DOUBLE, BASE_NONE, NULL, 0, "Peak Burst Size", HFILL}},
2461     
2462     { &hf_ldp_tlv_cdr,
2463       { "CDR", "ldp.msg.tlv.cdr", FT_DOUBLE, BASE_NONE, NULL, 0, "Committed Data Rate", HFILL}},
2464     
2465     { &hf_ldp_tlv_cbs,
2466       { "CBS", "ldp.msg.tlv.cbs", FT_DOUBLE, BASE_NONE, NULL, 0, "Committed Burst Size", HFILL}},
2467     
2468     { &hf_ldp_tlv_ebs,
2469       { "EBS", "ldp.msg.tlv.ebs", FT_DOUBLE, BASE_NONE, NULL, 0, "Excess Burst Size", HFILL}},
2470     
2471     { &hf_ldp_tlv_set_prio,
2472       { "Set Prio", "ldp.msg.tlv.set_prio", FT_UINT8, BASE_DEC, NULL, 0, "LSP setup priority", HFILL}},
2473     
2474     { &hf_ldp_tlv_hold_prio,
2475       { "Hold Prio", "ldp.msg.tlv.hold_prio", FT_UINT8, BASE_DEC, NULL, 0, "LSP hold priority", HFILL}},
2476
2477     { &hf_ldp_tlv_route_pinning,
2478       { "Route Pinning", "ldp.msg.tlv.route_pinning", FT_UINT32, BASE_DEC, VALS(route_pinning_vals), 0x80000000, "Route Pinning", HFILL}},
2479     
2480     { &hf_ldp_tlv_resource_class,
2481       { "Resource Class", "ldp.msg.tlv.resource_class", FT_UINT32, BASE_HEX, NULL, 0, "Resource Class (Color)", HFILL}},
2482
2483   };
2484
2485   static gint *ett[] = {
2486     &ett_ldp,
2487     &ett_ldp_header,
2488     &ett_ldp_ldpid,
2489     &ett_ldp_message,
2490     &ett_ldp_tlv,
2491     &ett_ldp_tlv_val,
2492     &ett_ldp_fec,
2493     &ett_ldp_fec_vc_interfaceparam
2494   };
2495   module_t *ldp_module; 
2496
2497   proto_ldp = proto_register_protocol("Label Distribution Protocol",
2498                                        "LDP", "ldp");
2499
2500   proto_register_field_array(proto_ldp, hf, array_length(hf));
2501   proto_register_subtree_array(ett, array_length(ett));
2502
2503   /* Register our configuration options for , particularly our port */
2504
2505   ldp_module = prefs_register_protocol(proto_ldp, proto_reg_handoff_ldp);
2506
2507   prefs_register_uint_preference(ldp_module, "tcp.port", "LDP TCP Port",
2508                                  "Set the TCP port for messages (if other"
2509                                  " than the default of 646)",
2510                                  10, &global_ldp_tcp_port);
2511
2512   prefs_register_uint_preference(ldp_module, "udp.port", "LDP UDP Port",
2513                                  "Set the UDP port for messages (if other"
2514                                  " than the default of 646)",
2515                                  10, &global_ldp_udp_port);
2516
2517   prefs_register_bool_preference(ldp_module, "desegment_ldp_messages",
2518     "Desegment all LDP messages spanning multiple TCP segments",
2519     "Whether the LDP dissector should desegment all messages spanning multiple TCP segments",
2520     &ldp_desegment);
2521 }
2522
2523 /* The registration hand-off routine */
2524 void
2525 proto_reg_handoff_ldp(void)
2526 {
2527   static gboolean ldp_prefs_initialized = FALSE;
2528   static dissector_handle_t ldp_tcp_handle, ldp_handle;
2529
2530   if (!ldp_prefs_initialized) {
2531
2532     ldp_tcp_handle = new_create_dissector_handle(dissect_ldp_tcp, proto_ldp);
2533     ldp_handle = new_create_dissector_handle(dissect_ldp, proto_ldp);
2534
2535     ldp_prefs_initialized = TRUE;
2536
2537   }
2538   else {
2539
2540     dissector_delete("tcp.port", tcp_port, ldp_tcp_handle);
2541     dissector_delete("udp.port", udp_port, ldp_handle);
2542
2543   }
2544
2545   /* Set our port number for future use */
2546
2547   tcp_port = global_ldp_tcp_port;
2548   udp_port = global_ldp_udp_port;
2549
2550   dissector_add("tcp.port", global_ldp_tcp_port, ldp_tcp_handle);
2551   dissector_add("udp.port", global_ldp_udp_port, ldp_handle);
2552
2553 }