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