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