2 * Routines for LDP (RFC 3036) packet disassembly
4 * $Id: packet-ldp.c,v 1.32 2002/04/08 20:30:52 gram Exp $
6 * Copyright (c) November 2000 by Richard Sharpe <rsharpe@ns.aus.com>
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@ethereal.com>
10 * Copyright 1999 Gerald Combs
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31 #ifdef HAVE_SYS_TYPES_H
32 # include <sys/types.h>
35 #ifdef HAVE_NETINET_IN_H
36 #include <netinet/in.h>
45 #include <epan/packet.h>
46 #include <epan/resolv.h>
50 #define TCP_PORT_LDP 646
51 #define UDP_PORT_LDP 646
53 void proto_reg_handoff_ldp(void);
55 static int proto_ldp = -1;
57 /* Delete the following if you do not use it, or add to it if you need */
58 static int hf_ldp_req = -1;
59 static int hf_ldp_rsp = -1;
60 static int hf_ldp_version = -1;
61 static int hf_ldp_pdu_len = -1;
62 static int hf_ldp_lsr = -1;
63 static int hf_ldp_ls_id = -1;
64 static int hf_ldp_msg_ubit = -1;
65 static int hf_ldp_msg_type = -1;
66 static int hf_ldp_msg_len = -1;
67 static int hf_ldp_msg_id = -1;
68 static int hf_ldp_msg_vendor_id = -1;
69 static int hf_ldp_msg_experiment_id = -1;
70 static int hf_ldp_tlv_value = -1;
71 static int hf_ldp_tlv_type = -1;
72 static int hf_ldp_tlv_unknown = -1;
73 static int hf_ldp_tlv_len = -1;
74 static int hf_ldp_tlv_val_hold = -1;
75 static int hf_ldp_tlv_val_target = -1;
76 static int hf_ldp_tlv_val_request = -1;
77 static int hf_ldp_tlv_val_res = -1;
78 static int hf_ldp_tlv_ipv4_taddr = -1;
79 static int hf_ldp_tlv_config_seqno = -1;
80 static int hf_ldp_tlv_ipv6_taddr = -1;
81 static int hf_ldp_tlv_fec_wc = -1;
82 static int hf_ldp_tlv_fec_af = -1;
83 static int hf_ldp_tlv_fec_len = -1;
84 static int hf_ldp_tlv_fec_pfval = -1;
85 static int hf_ldp_tlv_fec_hoval = -1;
86 static int hf_ldp_tlv_addrl_addr_family = -1;
87 static int hf_ldp_tlv_addrl_addr = -1;
88 static int hf_ldp_tlv_hc_value = -1;
89 static int hf_ldp_tlv_pv_lsrid = -1;
90 static int hf_ldp_tlv_generic_label = -1;
91 static int hf_ldp_tlv_atm_label_vbits = -1;
92 static int hf_ldp_tlv_atm_label_vpi = -1;
93 static int hf_ldp_tlv_atm_label_vci = -1;
94 static int hf_ldp_tlv_fr_label_len = -1;
95 static int hf_ldp_tlv_fr_label_dlci = -1;
96 static int hf_ldp_tlv_status_ebit = -1;
97 static int hf_ldp_tlv_status_fbit = -1;
98 static int hf_ldp_tlv_status_data = -1;
99 static int hf_ldp_tlv_status_msg_id = -1;
100 static int hf_ldp_tlv_status_msg_type = -1;
101 static int hf_ldp_tlv_extstatus_data = -1;
102 static int hf_ldp_tlv_returned_version = -1;
103 static int hf_ldp_tlv_returned_pdu_len = -1;
104 static int hf_ldp_tlv_returned_lsr = -1;
105 static int hf_ldp_tlv_returned_ls_id = -1;
106 static int hf_ldp_tlv_returned_msg_ubit = -1;
107 static int hf_ldp_tlv_returned_msg_type = -1;
108 static int hf_ldp_tlv_returned_msg_len = -1;
109 static int hf_ldp_tlv_returned_msg_id = -1;
110 static int hf_ldp_tlv_sess_ver = -1;
111 static int hf_ldp_tlv_sess_ka = -1;
112 static int hf_ldp_tlv_sess_advbit = -1;
113 static int hf_ldp_tlv_sess_ldetbit = -1;
114 static int hf_ldp_tlv_sess_pvlim = -1;
115 static int hf_ldp_tlv_sess_mxpdu = -1;
116 static int hf_ldp_tlv_sess_rxlsr = -1;
117 static int hf_ldp_tlv_sess_rxls = -1;
118 static int hf_ldp_tlv_sess_atm_merge = -1;
119 static int hf_ldp_tlv_sess_atm_lr = -1;
120 static int hf_ldp_tlv_sess_atm_dir = -1;
121 static int hf_ldp_tlv_sess_atm_minvpi = -1;
122 static int hf_ldp_tlv_sess_atm_maxvpi = -1;
123 static int hf_ldp_tlv_sess_atm_minvci = -1;
124 static int hf_ldp_tlv_sess_atm_maxvci = -1;
125 static int hf_ldp_tlv_sess_fr_merge = -1;
126 static int hf_ldp_tlv_sess_fr_lr = -1;
127 static int hf_ldp_tlv_sess_fr_dir = -1;
128 static int hf_ldp_tlv_sess_fr_len = -1;
129 static int hf_ldp_tlv_sess_fr_mindlci = -1;
130 static int hf_ldp_tlv_sess_fr_maxdlci = -1;
131 static int hf_ldp_tlv_lbl_req_msg_id = -1;
132 static int hf_ldp_tlv_vendor_id = -1;
133 static int hf_ldp_tlv_experiment_id = -1;
134 static int hf_ldp_tlv_fec_vc_controlword = -1;
135 static int hf_ldp_tlv_fec_vc_vctype = -1;
136 static int hf_ldp_tlv_fec_vc_infolength = -1;
137 static int hf_ldp_tlv_fec_vc_groupid = -1;
138 static int hf_ldp_tlv_fec_vc_vcid = -1;
139 static int hf_ldp_tlv_fec_vc_intparam_length = -1;
140 static int hf_ldp_tlv_fec_vc_intparam_mtu = -1;
141 static int hf_ldp_tlv_fec_vc_intparam_id = -1;
142 static int hf_ldp_tlv_fec_vc_intparam_maxcatmcells = -1;
143 static int hf_ldp_tlv_fec_vc_intparam_desc = -1;
144 static int hf_ldp_tlv_fec_vc_intparam_cembytes = -1;
145 static int ett_ldp = -1;
146 static int ett_ldp_header = -1;
147 static int ett_ldp_ldpid = -1;
148 static int ett_ldp_message = -1;
149 static int ett_ldp_tlv = -1;
150 static int ett_ldp_tlv_val = -1;
151 static int ett_ldp_fec = -1;
152 static int ett_ldp_fec_vc_interfaceparam = -1;
154 static int tcp_port = 0;
155 static int udp_port = 0;
157 /* desegmentation of LDP over TCP */
158 static gboolean ldp_desegment = FALSE;
160 /* Add your functions here */
162 static int global_ldp_tcp_port = TCP_PORT_LDP;
163 static int global_ldp_udp_port = UDP_PORT_LDP;
166 * The following define all the TLV types I know about
169 #define TLV_FEC 0x0100
170 #define TLV_ADDRESS_LIST 0x0101
171 #define TLV_HOP_COUNT 0x0103
172 #define TLV_PATH_VECTOR 0x0104
173 #define TLV_GENERIC_LABEL 0x0200
174 #define TLV_ATM_LABEL 0x0201
175 #define TLV_FRAME_LABEL 0x0202
176 #define TLV_STATUS 0x0300
177 #define TLV_EXTENDED_STATUS 0x0301
178 #define TLV_RETURNED_PDU 0x0302
179 #define TLV_RETURNED_MESSAGE 0x0303
180 #define TLV_COMMON_HELLO_PARMS 0x0400
181 #define TLV_IPV4_TRANSPORT_ADDRESS 0x0401
182 #define TLV_CONFIGURATION_SEQNO 0x0402
183 #define TLV_IPV6_TRANSPORT_ADDRESS 0x0403
184 #define TLV_COMMON_SESSION_PARMS 0x0500
185 #define TLV_ATM_SESSION_PARMS 0x0501
186 #define TLV_FRAME_RELAY_SESSION_PARMS 0x0502
187 #define TLV_LABEL_REQUEST_MESSAGE_ID 0x0600
189 #define TLV_VENDOR_PRIVATE_START 0x3E00
190 #define TLV_VENDOR_PRIVATE_END 0x3EFF
191 #define TLV_EXPERIMENTAL_START 0x3F00
192 #define TLV_EXPERIMENTAL_END 0x3FFF
194 static const value_string tlv_type_names[] = {
195 { TLV_FEC, "Forwarding Equivalence Classes TLV" },
196 { TLV_ADDRESS_LIST, "Address List TLV"},
197 { TLV_HOP_COUNT, "Hop Count TLV"},
198 { TLV_PATH_VECTOR, "Path Vector TLV"},
199 { TLV_GENERIC_LABEL, "Generic Label TLV"},
200 { TLV_ATM_LABEL, "ATM Label TLV"},
201 { TLV_FRAME_LABEL, "Frame Label TLV"},
202 { TLV_STATUS, "Status TLV"},
203 { TLV_EXTENDED_STATUS, "Extended Status TLV"},
204 { TLV_RETURNED_PDU, "Returned PDU TLV"},
205 { TLV_RETURNED_MESSAGE, "Returned Message TLV"},
206 { TLV_COMMON_HELLO_PARMS, "Common Hello Parameters TLV"},
207 { TLV_IPV4_TRANSPORT_ADDRESS, "IPv4 Transport Address TLV"},
208 { TLV_CONFIGURATION_SEQNO, "Configuration Sequence Number TLV"},
209 { TLV_IPV6_TRANSPORT_ADDRESS, "IPv6 Transport Address TLV"},
210 { TLV_COMMON_SESSION_PARMS, "Common Session Parameters TLV"},
211 { TLV_ATM_SESSION_PARMS, "ATM Session Parameters TLV"},
212 { TLV_FRAME_RELAY_SESSION_PARMS, "Frame Relay Session Parameters TLV"},
213 { TLV_LABEL_REQUEST_MESSAGE_ID, "Label Request Message ID TLV"},
214 { TLV_VENDOR_PRIVATE_START, "Vendor Private TLV"},
215 { TLV_EXPERIMENTAL_START, "Experimental TLV"},
220 * The following define all the message types I know about
223 #define LDP_NOTIFICATION 0x0001
224 #define LDP_HELLO 0x0100
225 #define LDP_INITIALIZATION 0x0200
226 #define LDP_KEEPALIVE 0x0201
227 #define LDP_ADDRESS 0x0300
228 #define LDP_ADDRESS_WITHDRAWAL 0x0301
229 #define LDP_LABEL_MAPPING 0x0400
230 #define LDP_LABEL_REQUEST 0x0401
231 #define LDP_LABEL_WITHDRAWAL 0x0402
232 #define LDP_LABEL_RELEASE 0x0403
233 #define LDP_LABEL_ABORT_REQUEST 0x0404
234 #define LDP_VENDOR_PRIVATE_START 0x3E00
235 #define LDP_VENDOR_PRIVATE_END 0x3EFF
236 #define LDP_EXPERIMENTAL_MESSAGE_START 0x3F00
237 #define LDP_EXPERIMENTAL_MESSAGE_END 0x3FFF
239 static const value_string ldp_message_types[] = {
240 {LDP_NOTIFICATION, "Notification Message"},
241 {LDP_HELLO, "Hello Message"},
242 {LDP_INITIALIZATION, "Initialization Message"},
243 {LDP_KEEPALIVE, "Keep Alive Message"},
244 {LDP_ADDRESS, "Address Message"},
245 {LDP_ADDRESS_WITHDRAWAL, "Address Withdrawal Message"},
246 {LDP_LABEL_MAPPING, "Label Mapping Message"},
247 {LDP_LABEL_REQUEST, "Label Request Message"},
248 {LDP_LABEL_WITHDRAWAL, "Label Withdrawal Message"},
249 {LDP_LABEL_RELEASE, "Label Release Message"},
250 {LDP_LABEL_ABORT_REQUEST, "Label Abort Request Message"},
251 {LDP_VENDOR_PRIVATE_START, "Vendor-Private Message"},
252 {LDP_EXPERIMENTAL_MESSAGE_START, "Experimental Message"},
256 static const true_false_string ldp_message_ubit = {
258 "Unknown bit not set"
261 static const true_false_string hello_targeted_vals = {
266 static const value_string tlv_unknown_vals[] = {
269 {2, "Unknown TLV, do not Forward"},
270 {3, "Unknown TLV, do Forward"},
274 #define WILDCARD_FEC 1
277 #define VC_FEC 0x80 /* draft-martini-l2circuit-trans-mpls */
279 static const value_string fec_types[] = {
280 {WILDCARD_FEC, "Wildcard FEC"},
281 {PREFIX_FEC, "Prefix FEC"},
282 {HOST_FEC, "Host Address FEC"},
283 {VC_FEC, "Virtual Circuit FEC"},
288 static const value_string fec_vc_types_vals[] = {
289 {0x0001, "Frame Relay DLCI"},
290 {0x0002, "ATM VCC transport"},
291 {0x0003, "ATM VPC transport"},
292 {0x0004, "Ethernet VLAN"},
293 {0x0005, "Ethernet"},
296 {0x0009, "ATM VCC cell transport"},
298 {0x000A, "ATM VPC cell transport"},
303 #define FEC_VC_INTERFACEPARAM_MTU 0x01
304 #define FEC_VC_INTERFACEPARAM_MAXCATMCELLS 0x02
305 #define FEC_VC_INTERFACEPARAM_DESCRIPTION 0x03
306 #define FEC_VC_INTERFACEPARAM_CEMBYTES 0x04
307 #define FEC_VC_INTERFACEPARAM_CEMOPTIONS 0x05
310 static const value_string fec_vc_interfaceparm[] = {
311 {FEC_VC_INTERFACEPARAM_MTU, "MTU"},
312 {FEC_VC_INTERFACEPARAM_MAXCATMCELLS, "Max Concatenated ATM cells"},
313 {FEC_VC_INTERFACEPARAM_DESCRIPTION, "Interface Description"},
314 {FEC_VC_INTERFACEPARAM_CEMBYTES, "CEM Payload Bytes"},
315 {FEC_VC_INTERFACEPARAM_CEMOPTIONS, "CEM options"}
318 static const true_false_string fec_vc_cbit = {
319 "Contorl Word Present",
320 "Control Word NOT Present"
325 static const value_string tlv_atm_merge_vals[] = {
326 {0, "Merge not supported"},
327 {1, "VP merge supported"},
328 {2, "VC merge supported"},
329 {3, "VP & VC merge supported"},
333 static const value_string tlv_atm_vbits_vals[] = {
334 {0, "VPI & VCI Significant"},
335 {1, "Only VPI Significant"},
336 {2, "Only VCI Significant"},
337 {3, "VPI & VCI not Significant, nonsense"},
341 static const value_string tlv_fr_merge_vals[] = {
342 {0, "Merge not supported"},
343 {1, "Merge supported"},
349 static const value_string tlv_fr_len_vals[] = {
357 static const true_false_string tlv_atm_dirbit = {
358 "Bidirectional capability",
359 "Unidirectional capability"
362 static const true_false_string hello_requested_vals = {
363 "Source requests periodic hellos",
364 "Source does not request periodic hellos"
367 static const true_false_string tlv_sess_advbit_vals = {
368 "Downstream On Demand proposed",
369 "Downstream Unsolicited proposed"
372 static const true_false_string tlv_sess_ldetbit_vals = {
373 "Loop Detection Enabled",
374 "Loop Detection Disabled"
377 static const true_false_string tlv_status_ebit = {
378 "Fatal Error Notification",
379 "Advisory Notification"
382 static const true_false_string tlv_status_fbit = {
383 "Notification should be Forwarded",
384 "Notification should NOT be Forwarded"
387 static const value_string tlv_status_data[] = {
389 {1, "Bad LDP Identifier"},
390 {2, "Bad Protocol Version"},
391 {3, "Bad PDU Length"},
392 {4, "Unknown Message Type"},
393 {5, "Bad Message Length"},
395 {7, "Bad TLV Length"},
396 {8, "Malformed TLV Value"},
397 {9, "Hold Timer Expired"},
399 {11, "Loop Detected"},
402 {14, "No Label Resources"},
403 {15, "Label Resources / Available"},
404 {16, "Session Rejected / No Hello"},
405 {17, "Session Rejected / Parameters Advertisement Mode"},
406 {18, "Session Rejected / Parameters Max PDU Length"},
407 {19, "Session Rejected / Parameters Label Range"},
408 {20, "KeepAlive Timer Expired"},
409 {21, "Label Request Aborted"},
410 {22, "Missing Message Parameters"},
411 {23, "Unsoported Address Family"},
412 {24, "Session Rejected / Bad KeepAlive Time"},
413 {25, "Internal Error"},
414 {0x01000001,"Unexpected Diff-Serv TLV"},
415 {0x01000002,"Unsupported PHB"},
416 {0x01000003,"Invalid EXP<->PHB Mapping"},
417 {0x01000004,"Unsupported PSC"},
418 {0x01000005,"Per-LSP context allocation failure"},
419 {0x04000001,"Bad Explicit Routing TLV Error"},
420 {0x04000002,"Bad Strict Node Error"},
421 {0x04000003,"Bad Strict Node Error"},
422 {0x04000004,"Bad Initial ER-Hop Error"},
423 {0x04000005,"Resource Unavailable"},
424 {0x04000006,"Traffic Parameters Unavailable"},
425 {0x04000007,"LSP Preempted"},
426 {0x04000008,"Modify Request Not Supported"},
427 {0x20000001,"Illegal C-Bit"},
428 {0x20000002,"Wrong C-Bit"},
432 /* Dissect FEC TLV */
435 dissect_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
437 proto_tree *ti=NULL, *val_tree=NULL, *fec_tree=NULL, *vcintparam_tree=NULL;
438 guint16 family, ix=1, ax;
439 guint8 addr_size=0, *addr, implemented, prefix_len_octets, prefix_len, host_len, vc_len;
441 void *str_handler=NULL;
447 proto_tree_add_text(tree, tvb, offset, rem, "Error processing TLV");
451 ti=proto_tree_add_text(tree, tvb, offset, rem, "FEC Elements");
452 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
453 if(val_tree == NULL) return;
456 switch (tvb_get_guint8(tvb, offset)) {
458 ti = proto_tree_add_text(val_tree, tvb, offset, 4, "FEC Element %u", ix);
459 fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
460 if(fec_tree == NULL) return;
461 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc,tvb, offset, 4, FALSE);
467 if( rem < 4 ){/*not enough*/
468 proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
471 family=tvb_get_ntohs(tvb, offset+1);
472 prefix_len=tvb_get_guint8(tvb, offset+3);
473 prefix_len_octets=(prefix_len+7)/8;
477 case AFNUM_INET: /*IPv4*/
479 str_handler=ip_to_str;
481 case AFNUM_INET6: /*IPv6*/
483 str_handler=ip6_to_str;
493 noctets= rem>4+prefix_len_octets?4+prefix_len_octets:rem;
494 proto_tree_add_text(val_tree, tvb, offset, noctets,"Support for Address Family not implemented");
500 if( rem < 4+MIN(addr_size, prefix_len_octets) ){
501 proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
505 /*Add a subtree for this*/
506 ti = proto_tree_add_text(val_tree, tvb, offset, 4+MIN(addr_size, prefix_len_octets), "FEC Element %u", ix);
507 fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
508 if(fec_tree == NULL) return;
509 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc, tvb, offset, 1, FALSE);
512 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_af, tvb, offset, 2, FALSE);
515 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_len, tvb, offset, 1, FALSE);
519 if( addr_size < prefix_len_octets) {
522 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"));
526 if( (addr=g_malloc0(addr_size)) == NULL ){
527 /*big big trouble, no mem or bad addr_size*/
528 fprintf(stderr, "packet-ldp: dissect_tlv_fec() malloc failed\n");
532 for(ax=0; ax+1 <= prefix_len_octets; ax++)
533 addr[ax]=tvb_get_guint8(tvb, offset+ax);
535 addr[ax-1] = addr[ax-1]&(0xFF<<(8-prefix_len%8));
537 str = (* (char* (*)(guint8 *))str_handler)(addr);
538 proto_tree_add_string_format(fec_tree, hf_ldp_tlv_fec_pfval, tvb, offset, prefix_len_octets, str, "Prefix: %s", str);
540 offset += prefix_len_octets;
541 rem -= 4+prefix_len_octets;
546 if( rem < 4 ){/*not enough*/
547 proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
550 family=tvb_get_ntohs(tvb, offset+1);
551 host_len=tvb_get_guint8(tvb, offset+3);
555 case AFNUM_INET: /*IPv4*/
557 str_handler=ip_to_str;
559 case AFNUM_INET6: /*IPv6*/
561 str_handler=ip6_to_str;
571 noctets= rem>4+host_len?4+host_len:rem;
572 proto_tree_add_text(val_tree, tvb, offset, noctets,"Support for Address Family not implemented");
578 if( rem < 4+addr_size ){
579 proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
583 /*Add a subtree for this*/
584 ti = proto_tree_add_text(val_tree, tvb, offset, 4+addr_size, "FEC Element %u", ix);
585 fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
586 if(fec_tree == NULL) return;
587 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc, tvb, offset, 1, FALSE);
590 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_af, tvb, offset, 2, FALSE);
593 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_len, tvb, offset, 1, FALSE);
597 if( addr_size != host_len) {
600 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"));
604 if( (addr=g_malloc0(addr_size)) == NULL ){
605 /*big big xtrouble, no mem or bad addr_size*/
606 fprintf(stderr, "packet-ldp: dissect_tlv_fec() malloc failed\n");
610 for(ax=0; ax+1 <= host_len; ax++)
611 addr[ax]=tvb_get_guint8(tvb, offset+ax);
613 str = (* (char* (*)(guint8 *))str_handler)(addr);
614 proto_tree_add_string_format(fec_tree, hf_ldp_tlv_fec_hoval, tvb, offset, host_len, str, "Address: %s", str);
622 if( rem < 8 ){/*not enough bytes for a minimal VC_FEC*/
623 proto_tree_add_text(val_tree, tvb, offset, rem, "Error in FEC Element %u", ix);
626 vc_len = tvb_get_guint8 (tvb, offset+3);
629 ti = proto_tree_add_text(val_tree, tvb, offset, 8+vc_len, "FEC Element %u", ix);
630 fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
631 if(fec_tree == NULL) return;
632 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc, tvb, offset, 1, FALSE);
633 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_controlword, tvb, offset+1, 1, FALSE);
634 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_vctype, tvb, offset+1, 2, FALSE);
635 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_infolength, tvb, offset+3,1,FALSE);
636 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_groupid,tvb, offset +4, 4, FALSE);
640 if ( (vc_len > 3) && ( rem > 3 ) ) { /* there is enough room for vcid */
641 proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_vcid,tvb, offset, 4, FALSE);
642 proto_item_append_text (ti," VCID: %u",tvb_get_ntohl(tvb,offset));
645 proto_tree_add_text(val_tree,tvb,offset +4, 8 +vc_len, "VC FEC size format error");
652 while ( (vc_len > 1) && (rem > 1) ) { /* enough to include id and length */
653 intparam_len = tvb_get_guint8(tvb, offset+1);
654 ti = proto_tree_add_text(fec_tree, tvb, offset, 4, "Interface Paramameter");
655 vcintparam_tree = proto_item_add_subtree(ti, ett_ldp_fec_vc_interfaceparam);
656 if(vcintparam_tree == NULL) return;
657 proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_id,tvb,offset,1,FALSE);
658 proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_length,tvb, offset+1, 1, FALSE);
659 if ( (vc_len -intparam_len) <0 && (rem -intparam_len) <0 ) { /* error condition */
660 proto_tree_add_text(vcintparam_tree, tvb, offset +2, MIN(vc_len,rem), "malformed data");
663 switch (tvb_get_guint8(tvb, offset)) {
664 case FEC_VC_INTERFACEPARAM_MTU:
665 proto_item_append_text(ti,": MTU %u", tvb_get_ntohs(tvb,offset+2));
666 proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_mtu,tvb, offset+2, 2, FALSE);
668 case FEC_VC_INTERFACEPARAM_MAXCATMCELLS:
669 proto_item_append_text(ti,": Max ATM Concat Cells %u", tvb_get_ntohs(tvb,offset+2));
670 proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_maxcatmcells,tvb, offset+2, 2, FALSE);
672 case FEC_VC_INTERFACEPARAM_DESCRIPTION:
673 proto_item_append_text(ti,": Description");
674 proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_desc,tvb, offset+2, (intparam_len -2), FALSE);
676 case FEC_VC_INTERFACEPARAM_CEMBYTES:
677 proto_item_append_text(ti,": CEM Payload Bytes %u", tvb_get_ntohs(tvb,offset+2));
678 proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_cembytes,tvb, offset+2, 2, FALSE);
680 case FEC_VC_INTERFACEPARAM_CEMOPTIONS:
681 /* draft-malis-sonet-ces-mpls CEM options still undefined */
682 default: /* unknown */
683 proto_item_append_text(ti," unknown");
684 proto_tree_add_text(vcintparam_tree,tvb, offset+2, (intparam_len -2), "Unknown data");
689 vc_len -= intparam_len;
690 offset += intparam_len;
694 default: /* Unknown */
695 /* XXX - do all FEC's have a length that's a multiple of 4? */
696 /* Hmmm, don't think so. Will check. RJS. */
697 /* If we don't know its structure, we have to exit */
698 ti = proto_tree_add_text(val_tree, tvb, offset, 4, "FEC Element %u", ix);
699 fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
700 if(fec_tree == NULL) return;
701 proto_tree_add_text(fec_tree, tvb, offset, rem, "Unknown FEC TLV type");
709 /* Dissect Address List TLV */
712 dissect_tlv_address_list(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
714 proto_tree *ti = NULL, *val_tree = NULL;
716 guint8 addr_size, *addr;
722 proto_tree_add_text(tree, tvb, offset, rem,
723 "Error processing TLV");
727 family=tvb_get_ntohs(tvb, offset);
728 proto_tree_add_item(tree, hf_ldp_tlv_addrl_addr_family, tvb,
731 case AFNUM_INET: /*IPv4*/
733 str_handler=ip_to_str;
735 case AFNUM_INET6: /*IPv6*/
737 str_handler=ip6_to_str;
740 proto_tree_add_text(tree, tvb, offset+2, rem-2,
741 "Support for Address Family not implemented");
746 ti=proto_tree_add_text(tree, tvb, offset, rem, "Addresses");
747 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
749 if(val_tree == NULL) return;
750 if( (addr=g_malloc(addr_size)) == NULL ){
752 fprintf(stderr, "packet-ldp: dissect_tlv_address_list() malloc failed\n");
756 for(ix=1; rem >= addr_size; ix++, offset += addr_size,
758 if( (tvb_memcpy(tvb, addr, offset, addr_size))
762 str = (* (char* (*)(guint8 *))str_handler)(addr);
763 proto_tree_add_string_format(val_tree,
764 hf_ldp_tlv_addrl_addr, tvb, offset, addr_size, str,
765 "Address %u: %s", ix, str);
768 proto_tree_add_text(val_tree, tvb, offset, rem,
769 "Error processing TLV");
774 /* Dissect Path Vector TLV */
777 dissect_tlv_path_vector(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
779 proto_tree *ti = NULL, *val_tree = NULL;
784 ti=proto_tree_add_text(tree, tvb, offset, rem, "LSR IDs");
785 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
787 if(val_tree == NULL) return;
789 for(ix=1; rem >= 4; ix++, offset += 4, rem -= 4) {
790 tvb_memcpy(tvb, (guint8 *)&addr, offset, 4);
791 proto_tree_add_ipv4_format(val_tree,
792 hf_ldp_tlv_pv_lsrid, tvb, offset, 4,
793 addr, "LSR Id %u: %s", ix,
794 ip_to_str((guint8 *)&addr));
797 proto_tree_add_text(val_tree, tvb, offset, rem,
798 "Error processing TLV");
802 /* Dissect ATM Label TLV */
805 dissect_tlv_atm_label(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
807 proto_tree *ti = NULL, *val_tree = NULL;
812 proto_tree_add_text(tree, tvb, offset, rem, "Error processing TLV");
815 ti=proto_tree_add_text(tree, tvb, offset, rem, "ATM Label");
816 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
817 if(val_tree == NULL) return;
819 proto_tree_add_item(val_tree, hf_ldp_tlv_atm_label_vbits, tvb, offset, 1, FALSE);
821 id=tvb_get_ntohs(tvb, offset)&0x0FFF;
822 proto_tree_add_uint_format(val_tree, hf_ldp_tlv_atm_label_vpi, tvb, offset, 2, id, "VPI: %u", id);
824 id=tvb_get_ntohs(tvb, offset+2);
825 proto_tree_add_uint_format(val_tree, hf_ldp_tlv_atm_label_vci, tvb, offset+2, 2, id, "VCI: %u", id);
829 /* Dissect FRAME RELAY Label TLV */
832 dissect_tlv_frame_label(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
834 proto_tree *ti = NULL, *val_tree = NULL;
840 proto_tree_add_text(tree, tvb, offset, rem,"Error processing TLV");
843 ti=proto_tree_add_text(tree, tvb, offset, rem, "Frame Relay Label");
844 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
845 if(val_tree == NULL) return;
847 len=(guint8)(tvb_get_ntohs(tvb, offset)>>7) & 0x03;
848 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);
850 id=tvb_get_ntoh24(tvb, offset+1)&0x7FFFFF;
851 proto_tree_add_uint_format(val_tree,
852 hf_ldp_tlv_fr_label_dlci, tvb, offset+1, 3, id, "DLCI: %u", id);
856 /* Dissect STATUS TLV */
859 dissect_tlv_status(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
861 proto_tree *ti = NULL, *val_tree = NULL;
866 proto_tree_add_text(tree, tvb, offset, rem,"Error processing TLV");
870 ti=proto_tree_add_text(tree, tvb, offset, rem, "Status");
871 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
872 if(val_tree == NULL) return;
874 proto_tree_add_item(val_tree, hf_ldp_tlv_status_ebit, tvb, offset, 1, FALSE);
875 proto_tree_add_item(val_tree, hf_ldp_tlv_status_fbit, tvb, offset, 1, FALSE);
877 data=tvb_get_ntohl(tvb, offset)&0x3FFFFFFF;
878 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);
880 proto_tree_add_item(val_tree, hf_ldp_tlv_status_msg_id, tvb, offset+4, 4, FALSE);
881 proto_tree_add_item(val_tree, hf_ldp_tlv_status_msg_type, tvb, offset+8, 2, FALSE);
885 /* Dissect Returned PDU TLV */
888 dissect_tlv_returned_pdu(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
890 proto_tree *ti = NULL, *val_tree = NULL;
894 proto_tree_add_text(tree, tvb, offset, rem,"Error processing TLV");
897 ti=proto_tree_add_text(tree, tvb, offset, rem, "Returned PDU");
898 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
899 if(val_tree == NULL) return;
901 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_version, tvb, offset, 2, FALSE);
902 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_pdu_len, tvb, offset+2, 2, FALSE);
903 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_lsr, tvb, offset+4, 4, FALSE);
904 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_ls_id, tvb, offset+8, 2, FALSE);
909 /*XXX - dissect returned pdu data*/
910 proto_tree_add_text(val_tree, tvb, offset, rem, "Returned PDU Data");
915 /* Dissect Returned MESSAGE TLV */
918 dissect_tlv_returned_message(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
920 proto_tree *ti = NULL, *val_tree = NULL;
925 proto_tree_add_text(tree, tvb, offset, rem,"Error processing TLV");
928 ti=proto_tree_add_text(tree, tvb, offset, rem, "Returned Message");
929 val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
930 if(val_tree == NULL) return;
932 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_ubit, tvb, offset, 1, FALSE);
934 type=tvb_get_ntohs(tvb, offset)&0x7FFF;
935 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);
937 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_len, tvb, offset+2, 2, FALSE);
941 if( rem >= 4 ) { /*have msg_id*/
942 proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_id, tvb, offset, 4, FALSE);
948 /*XXX - dissect returned msg parameters*/
949 proto_tree_add_text(val_tree, tvb, offset, rem, "Returned Message Parameters");
954 /* Dissect the common hello params */
957 dissect_tlv_common_hello_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
959 proto_tree *ti = NULL, *val_tree = NULL;
963 ti = proto_tree_add_item(tree, hf_ldp_tlv_value, tvb, offset, rem, FALSE);
964 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
965 if(val_tree == NULL) return;
969 proto_tree_add_item(val_tree, hf_ldp_tlv_val_hold, tvb, offset, 2, FALSE);
970 proto_tree_add_item(val_tree, hf_ldp_tlv_val_target, tvb, offset + 2, 1, FALSE);
971 proto_tree_add_item(val_tree, hf_ldp_tlv_val_request, tvb, offset + 2, 1, FALSE);
972 proto_tree_add_item(val_tree, hf_ldp_tlv_val_res, tvb, offset + 2, 2, FALSE);
976 /* Dissect the common session params */
979 dissect_tlv_common_session_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
981 proto_tree *ti = NULL, *val_tree = NULL;
984 ti = proto_tree_add_text(tree, tvb, offset, rem, "Parameters");
985 if( rem != 14) { /*length of Comm Sess Parms tlv*/
986 proto_tree_add_text(tree, tvb, offset, rem, "Error processing TLV");
989 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
991 if(val_tree != NULL) {
993 proto_tree_add_item(val_tree, hf_ldp_tlv_sess_ver, tvb,offset, 2, FALSE);
996 proto_tree_add_item(val_tree, hf_ldp_tlv_sess_ka, tvb,offset + 2, 2, FALSE);
999 proto_tree_add_item(val_tree, hf_ldp_tlv_sess_advbit,tvb, offset + 4, 1, FALSE);
1002 proto_tree_add_item(val_tree, hf_ldp_tlv_sess_ldetbit,tvb, offset + 4, 1, FALSE);
1004 /*Path Vector Limit*/
1005 proto_tree_add_item(val_tree, hf_ldp_tlv_sess_pvlim,tvb, offset + 5, 1, FALSE);
1008 proto_tree_add_item(val_tree, hf_ldp_tlv_sess_mxpdu,tvb, offset + 6, 2, FALSE);
1011 proto_tree_add_item(val_tree, hf_ldp_tlv_sess_rxlsr,tvb, offset + 8, 4, FALSE);
1014 proto_tree_add_item(val_tree, hf_ldp_tlv_sess_rxls,tvb, offset + 12, 2, FALSE);
1019 /* Dissect the atm session params */
1022 dissect_tlv_atm_session_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1024 proto_tree *ti = NULL, *val_tree = NULL, *lbl_tree = NULL;
1030 proto_tree_add_text(tree, tvb, offset, rem,
1031 "Error processing TLV");
1035 ti = proto_tree_add_text(tree, tvb, offset, rem,"ATM Parameters");
1036 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1038 if(val_tree != NULL) {
1039 proto_tree_add_item(val_tree, hf_ldp_tlv_sess_atm_merge,tvb, offset, 1, FALSE);
1041 /*get the number of label ranges*/
1042 numlr=(tvb_get_guint8(tvb, offset)>>2) & 0x0F;
1043 proto_tree_add_uint_format(val_tree, hf_ldp_tlv_sess_atm_lr,
1044 tvb, offset, 1, numlr, "Number of Label Range components: %u",
1047 proto_tree_add_item(val_tree, hf_ldp_tlv_sess_atm_dir,tvb, offset, 1, FALSE);
1049 /*move into range components*/
1052 ti = proto_tree_add_text(val_tree, tvb, offset, rem,"ATM Label Range Components");
1055 val_tree=proto_item_add_subtree(ti,ett_ldp_tlv_val);
1056 if( ! val_tree ) return;
1058 /*now dissect ranges*/
1059 for(ix=1; numlr > 0 && rem >= 8; ix++, rem-=8, numlr--) {
1060 ti=proto_tree_add_text(val_tree, tvb, offset, 8,
1061 "ATM Label Range Component %u", ix);
1062 lbl_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
1064 if( lbl_tree == NULL ) break;
1066 id=tvb_get_ntohs(tvb, offset)&0x0FFF;
1067 proto_tree_add_uint_format(lbl_tree,
1068 hf_ldp_tlv_sess_atm_minvpi,tvb, offset, 2, id, "Minimum VPI: %u", id);
1069 id=tvb_get_ntohs(tvb, offset+4)&0x0FFF;
1070 proto_tree_add_uint_format(lbl_tree,
1071 hf_ldp_tlv_sess_atm_maxvpi,tvb, (offset+4), 2, id, "Maximum VPI: %u", id);
1073 id=tvb_get_ntohs(tvb, offset+2);
1074 proto_tree_add_uint_format(lbl_tree,
1075 hf_ldp_tlv_sess_atm_minvci,tvb, offset+2, 2, id, "Minimum VCI: %u", id);
1076 id=tvb_get_ntohs(tvb, offset+6);
1077 proto_tree_add_uint_format(lbl_tree,
1078 hf_ldp_tlv_sess_atm_maxvci,tvb, offset+6, 2, id, "Maximum VCI: %u", id);
1083 proto_tree_add_text(val_tree, tvb, offset, rem,"Error processing TLV");
1088 /* Dissect the frame relay session params */
1091 dissect_tlv_frame_relay_session_parms(tvbuff_t *tvb, guint offset,proto_tree *tree, int rem)
1093 proto_tree *ti = NULL, *val_tree = NULL, *lbl_tree = NULL;
1094 guint8 numlr, ix, len;
1099 proto_tree_add_text(tree, tvb, offset, rem,
1100 "Error processing TLV");
1104 ti = proto_tree_add_text(tree, tvb, offset, rem,
1105 "Frame Relay Parameters");
1106 val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
1108 if(val_tree != NULL) {
1109 proto_tree_add_item(val_tree, hf_ldp_tlv_sess_fr_merge,
1110 tvb, offset, 1, FALSE);
1112 /*get the number of label ranges*/
1113 numlr=(tvb_get_guint8(tvb, offset)>>2) & 0x0F;
1114 proto_tree_add_uint_format(val_tree, hf_ldp_tlv_sess_fr_lr,
1115 tvb, offset, 1, numlr, "Number of Label Range components: %u",
1118 proto_tree_add_item(val_tree, hf_ldp_tlv_sess_fr_dir,
1119 tvb, offset, 1, FALSE);
1121 /*move into range components*/
1124 ti = proto_tree_add_text(val_tree, tvb, offset, rem,
1125 "Frame Relay Label Range Components");
1128 val_tree=proto_item_add_subtree(ti,
1130 if( ! val_tree ) return;
1133 /*now dissect ranges*/
1134 for(ix=1; numlr > 0 && rem >= 8; ix++, rem-=8, numlr--) {
1135 ti=proto_tree_add_text(val_tree, tvb, offset, 8,
1136 "Frame Relay Label Range Component %u", ix);
1137 lbl_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
1139 if( lbl_tree == NULL ) break;
1141 len=(guint8)(tvb_get_ntohs(tvb, offset)>>7) & 0x03;
1142 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);
1144 id=tvb_get_ntoh24(tvb, offset+1)&0x7FFFFF;
1145 proto_tree_add_uint_format(lbl_tree,
1146 hf_ldp_tlv_sess_fr_mindlci, tvb, offset+1, 3, id, "Minimum DLCI %u", id);
1147 id=tvb_get_ntoh24(tvb, offset+5)&0x7FFFFF;
1148 proto_tree_add_uint_format(lbl_tree,
1149 hf_ldp_tlv_sess_fr_maxdlci, tvb, offset+5, 3, id, "Maximum DLCI %u", id);
1155 proto_tree_add_text(val_tree, tvb, offset, rem,
1156 "Error processing TLV");
1162 /* Dissect a TLV and return the number of bytes consumed ... */
1165 dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
1167 guint16 type, typebak;
1169 proto_tree *ti = NULL, *tlv_tree = NULL;
1171 length=tvb_reported_length_remaining(tvb, offset);
1172 rem=MIN(rem, length);
1174 if( rem < 4 ) {/*chk for minimum header*/
1176 proto_tree_add_text(tree, tvb, offset, rem,"Error processing TLV");
1179 type = tvb_get_ntohs(tvb, offset) & 0x3FFF;
1181 length = tvb_get_ntohs(tvb, offset + 2),
1182 rem -= 4; /*do not count header*/
1183 length = MIN(length, rem); /* Don't go haywire if a problem ... */
1186 /*chk for vendor-private*/
1187 if(type>=TLV_VENDOR_PRIVATE_START && type<=TLV_VENDOR_PRIVATE_END){
1188 typebak=type; /*keep type*/
1189 type=TLV_VENDOR_PRIVATE_START;
1191 /*chk for experimental*/
1192 } else if(type>=TLV_EXPERIMENTAL_START && type<=TLV_EXPERIMENTAL_END){
1193 typebak=type; /*keep type*/
1194 type=TLV_EXPERIMENTAL_START;
1197 ti = proto_tree_add_text(tree, tvb, offset, length + 4, "%s",
1198 val_to_str(type, tlv_type_names, "Unknown TLV type (0x%04X)"));
1199 tlv_tree = proto_item_add_subtree(ti, ett_ldp_tlv);
1200 if(tlv_tree == NULL) return length+4;
1202 proto_tree_add_item(tlv_tree, hf_ldp_tlv_unknown, tvb, offset, 1, FALSE);
1204 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 );
1206 proto_tree_add_item(tlv_tree, hf_ldp_tlv_len, tvb, offset + 2, 2, FALSE);
1211 dissect_tlv_fec(tvb, offset + 4, tlv_tree, length);
1214 case TLV_ADDRESS_LIST:
1215 dissect_tlv_address_list(tvb, offset + 4, tlv_tree, length);
1219 if( length != 1 ) /*error, only one byte*/
1220 proto_tree_add_text(tlv_tree, tvb, offset + 4,length,"Error processing TLV");
1222 proto_tree_add_item(tlv_tree, hf_ldp_tlv_hc_value, tvb,offset + 4, length, FALSE);
1225 case TLV_PATH_VECTOR:
1226 dissect_tlv_path_vector(tvb, offset + 4, tlv_tree, length);
1229 case TLV_GENERIC_LABEL:
1230 if( length != 4 ) /*error, need only label*/
1231 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
1233 guint32 label=tvb_get_ntohl(tvb, offset+4) & 0x000FFFFF;
1235 proto_tree_add_uint_format(tlv_tree, hf_ldp_tlv_generic_label,
1236 tvb, offset+4, length, label, "Generic Label: %u", label);
1241 dissect_tlv_atm_label(tvb, offset + 4, tlv_tree, length);
1244 case TLV_FRAME_LABEL:
1245 dissect_tlv_frame_label(tvb, offset + 4, tlv_tree, length);
1249 dissect_tlv_status(tvb, offset + 4, tlv_tree, length);
1252 case TLV_EXTENDED_STATUS:
1253 if( length != 4 ) /*error, need only status_code(guint32)*/
1254 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
1256 proto_tree_add_item(tlv_tree, hf_ldp_tlv_extstatus_data, tvb, offset + 4, length, FALSE);
1260 case TLV_RETURNED_PDU:
1261 dissect_tlv_returned_pdu(tvb, offset + 4, tlv_tree, length);
1264 case TLV_RETURNED_MESSAGE:
1265 dissect_tlv_returned_message(tvb, offset + 4, tlv_tree, length);
1268 case TLV_COMMON_HELLO_PARMS:
1269 dissect_tlv_common_hello_parms(tvb, offset + 4, tlv_tree, length);
1272 case TLV_IPV4_TRANSPORT_ADDRESS:
1273 if( length != 4 ) /*error, need only ipv4*/
1274 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
1276 proto_tree_add_item(tlv_tree, hf_ldp_tlv_ipv4_taddr, tvb, offset + 4, 4, FALSE);
1280 case TLV_CONFIGURATION_SEQNO:
1281 if( length != 4 ) /*error, need only seq_num(guint32)*/
1282 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
1284 proto_tree_add_item(tlv_tree, hf_ldp_tlv_config_seqno, tvb, offset + 4, 4, FALSE);
1288 case TLV_IPV6_TRANSPORT_ADDRESS:
1289 if( length != 16 ) /*error, need only ipv6*/
1290 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
1292 proto_tree_add_item(tlv_tree, hf_ldp_tlv_ipv6_taddr, tvb, offset + 4, 16, FALSE);
1296 case TLV_COMMON_SESSION_PARMS:
1297 dissect_tlv_common_session_parms(tvb, offset + 4, tlv_tree, length);
1300 case TLV_ATM_SESSION_PARMS:
1301 dissect_tlv_atm_session_parms(tvb, offset + 4, tlv_tree, length);
1304 case TLV_FRAME_RELAY_SESSION_PARMS:
1305 dissect_tlv_frame_relay_session_parms(tvb, offset + 4, tlv_tree, length);
1308 case TLV_LABEL_REQUEST_MESSAGE_ID:
1309 if( length != 4 ) /*error, need only one msgid*/
1310 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
1312 proto_tree_add_item(tlv_tree, hf_ldp_tlv_lbl_req_msg_id, tvb,offset + 4,length, FALSE);
1315 case TLV_VENDOR_PRIVATE_START:
1316 if( length < 4 ) /*error, at least Vendor ID*/
1317 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
1319 proto_tree_add_item(tlv_tree, hf_ldp_tlv_vendor_id, tvb,offset + 4, 4, FALSE);
1320 if( length > 4 ) /*have data*/
1321 proto_tree_add_text(tlv_tree, tvb, offset + 8, length-4,"Data");
1325 case TLV_EXPERIMENTAL_START:
1326 if( length < 4 ) /*error, at least Experiment ID*/
1327 proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
1329 proto_tree_add_item(tlv_tree, hf_ldp_tlv_experiment_id, tvb,offset + 4, 4, FALSE);
1330 if( length > 4 ) /*have data*/
1331 proto_tree_add_text(tlv_tree, tvb, offset + 8, length-4,"Data");
1336 proto_tree_add_item(tlv_tree, hf_ldp_tlv_value, tvb, offset + 4, length, FALSE);
1341 return length + 4; /* Length of the value field + header */
1345 /* Dissect a Message and return the number of bytes consumed ... */
1348 dissect_msg(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, int rem)
1350 guint16 type, typebak;
1352 int length, ao=0, co;
1353 proto_tree *ti = NULL, *msg_tree = NULL;
1355 length=tvb_reported_length_remaining(tvb, offset);
1356 rem=MIN(rem, length);
1358 if( rem < 8 ) {/*chk for minimum header = type + length + msg_id*/
1359 if( check_col(pinfo->cinfo, COL_INFO) )
1360 col_append_fstr(pinfo->cinfo, COL_INFO, "Bad Message");
1362 proto_tree_add_text(tree, tvb, offset, rem,"Error processing Message");
1365 type = tvb_get_ntohs(tvb, offset) & 0x7FFF;
1367 /*chk for vendor-private*/
1368 if(type>=LDP_VENDOR_PRIVATE_START && type<=LDP_VENDOR_PRIVATE_END){
1369 typebak=type; /*keep type*/
1370 type=LDP_VENDOR_PRIVATE_START;
1372 /*chk for experimental*/
1373 } else if(type>=LDP_EXPERIMENTAL_MESSAGE_START && type<=LDP_EXPERIMENTAL_MESSAGE_END){
1374 typebak=type; /*keep type*/
1375 type=LDP_EXPERIMENTAL_MESSAGE_START;
1379 if( (length = tvb_get_ntohs(tvb, offset + 2)) < (4+extra) ) {/*not enough data for type*/
1380 if( check_col(pinfo->cinfo, COL_INFO) )
1381 col_append_fstr(pinfo->cinfo, COL_INFO, "Bad Message Length ");
1383 proto_tree_add_text(tree, tvb, offset, rem,"Error processing Message Length");
1387 length = MIN(length, rem); /* Don't go haywire if a problem ... */
1389 if( check_col(pinfo->cinfo, COL_INFO) ){
1390 col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", val_to_str(type, ldp_message_types, "Unknown Message (0x%04X)"));
1394 ti = proto_tree_add_text(tree, tvb, offset, length + 4, "%s",
1395 val_to_str(type, ldp_message_types, "Unknown Message type (0x%04X)"));
1396 msg_tree = proto_item_add_subtree(ti, ett_ldp_message);
1397 if(msg_tree == NULL) return length+4;
1399 proto_tree_add_item(msg_tree, hf_ldp_msg_ubit, tvb, offset, 1, FALSE);
1401 type=tvb_get_ntohs(tvb, offset)&0x7FFF;
1402 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);
1404 proto_tree_add_item(msg_tree, hf_ldp_msg_len, tvb, offset+2, 2, FALSE);
1405 proto_tree_add_item(msg_tree, hf_ldp_msg_id, tvb, offset+4, 4, FALSE);
1410 case LDP_VENDOR_PRIVATE_START:
1411 hf_tmp=hf_ldp_msg_vendor_id;
1413 case LDP_EXPERIMENTAL_MESSAGE_START:
1414 hf_tmp=hf_ldp_msg_experiment_id;
1417 proto_tree_add_item(msg_tree, hf_tmp, tvb, offset+8, extra, FALSE);
1421 offset += (8+extra);
1422 length -= (4+extra);
1425 while( (length-ao) > 0 ) {
1426 co=dissect_tlv(tvb, offset, msg_tree, length-ao);
1431 return length+8+extra;
1434 /* Dissect a PDU and return the number of bytes consumed ... */
1437 dissect_ldp_pdu(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, int rem, guint ix)
1439 int length, ao=0, co;
1440 proto_tree *ti=NULL, *pdu_tree = NULL;
1442 length=tvb_reported_length_remaining(tvb, offset);
1443 rem=MIN(rem, length);
1445 if( rem < 10 ){/*don't even have a PDU header*/
1446 /*XXX Need changes in desegment_tcp to handle multiple requests*/
1448 if( pinfo->can_desegment && (pinfo->ptype==PT_TCP) && ldp_desegment ){
1449 pinfo->desegment_offset=offset;
1450 pinfo->desegment_len=10-rem;
1454 proto_tree_add_text(tree, tvb, offset, rem,"Not enough bytes for PDU Hdr in TCP segment");
1459 if( (length = tvb_get_ntohs(tvb, offset + 2)) < 6 ) {/*not enough*/
1460 if( check_col(pinfo->cinfo, COL_INFO) && ix )
1461 col_append_fstr(pinfo->cinfo, COL_INFO, "PDU %u: ", ix);
1462 if( check_col(pinfo->cinfo, COL_INFO) ){
1463 col_append_fstr(pinfo->cinfo, COL_INFO, "Bad PDU Length ");
1466 proto_tree_add_text(tree, tvb, offset, rem,"Error processing PDU Length");
1472 if( pinfo->can_desegment && (pinfo->ptype==PT_TCP) && ldp_desegment ){/*ask for more*/
1473 pinfo->desegment_offset=offset;
1474 pinfo->desegment_len=length-rem;
1476 if( check_col(pinfo->cinfo, COL_INFO) && ix )
1477 col_append_fstr(pinfo->cinfo, COL_INFO, "PDU %u: ", ix);
1478 if( check_col(pinfo->cinfo, COL_INFO) )
1479 col_append_fstr(pinfo->cinfo, COL_INFO, "Bad PDU Length ");
1481 proto_tree_add_text(tree, tvb, offset, rem+4,"Error processing PDU Length");
1486 if( check_col(pinfo->cinfo, COL_INFO) && ix )
1487 col_append_fstr(pinfo->cinfo, COL_INFO, "PDU %u: ", ix);
1490 ti=proto_tree_add_protocol_format(tree, proto_ldp, tvb, offset,
1491 length+4, ix?"LDP PDU %u":"LDP PDU", ix);
1492 pdu_tree = proto_item_add_subtree(ti, ett_ldp);
1496 proto_tree_add_item(pdu_tree, hf_ldp_version, tvb, offset, 2, FALSE);
1497 proto_tree_add_item(pdu_tree, hf_ldp_pdu_len, tvb, offset+2, 2, FALSE);
1498 proto_tree_add_item(pdu_tree, hf_ldp_lsr, tvb, offset+4, 4, FALSE);
1499 proto_tree_add_item(pdu_tree, hf_ldp_ls_id, tvb, offset+8, 2, FALSE);
1504 while( (length-ao) > 0 ) {
1505 co=dissect_msg(tvb, offset, pinfo, pdu_tree, length-ao);
1514 dissect_ldp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1516 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1517 col_set_str(pinfo->cinfo, COL_PROTOCOL, "LDP");
1519 if (check_col(pinfo->cinfo, COL_INFO))
1520 col_clear(pinfo->cinfo, COL_INFO);
1522 dissect_ldp_pdu(tvb, 0, pinfo, tree, tvb_reported_length(tvb), 0);
1526 dissect_ldp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1528 int offset=0, length, rtn;
1532 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1533 col_set_str(pinfo->cinfo, COL_PROTOCOL, "LDP");
1535 if (check_col(pinfo->cinfo, COL_INFO))
1536 col_clear(pinfo->cinfo, COL_INFO);
1538 length=tvb_reported_length(tvb);
1540 rtn = dissect_ldp_pdu(tvb, offset, pinfo, tree, length, ix++);
1546 /* Register all the bits needed with the filtering engine */
1549 proto_register_ldp(void)
1551 static hf_register_info hf[] = {
1553 /* Change the following to the type you need */
1554 { "Request", "ldp.req", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
1557 { "Response", "ldp.rsp", FT_BOOLEAN, BASE_NONE, NULL, 0x0, "", HFILL }},
1560 { "Version", "ldp.hdr.version", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Version Number", HFILL }},
1563 { "PDU Length", "ldp.hdr.pdu_len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP PDU Length", HFILL }},
1566 { "LSR ID", "ldp.hdr.ldpid.lsr", FT_IPv4, BASE_HEX, NULL, 0x0, "LDP Label Space Router ID", HFILL }},
1569 { "Label Space ID", "ldp.hdr.ldpid.lsid", FT_UINT16, BASE_DEC, NULL, 0, "LDP Label Space ID", HFILL }},
1572 { "U bit", "ldp.msg.ubit", FT_BOOLEAN, 8, TFS(&ldp_message_ubit), 0x80, "Unknown Message Bit", HFILL }},
1575 { "Message Type", "ldp.msg.type", FT_UINT16, BASE_HEX, VALS(ldp_message_types), 0x7FFF, "LDP message type", HFILL }},
1578 { "Message Length", "ldp.msg.len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Message Length (excluding message type and len)", HFILL }},
1581 { "Message ID", "ldp.msg.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Message ID", HFILL }},
1583 { &hf_ldp_msg_vendor_id,
1584 { "Vendor ID", "ldp.msg.vendor.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Vendor-private Message ID", HFILL }},
1586 { &hf_ldp_msg_experiment_id,
1587 { "Experiment ID", "ldp.msg.experiment.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Experimental Message ID", HFILL }},
1589 { &hf_ldp_tlv_unknown,
1590 { "TLV Unknown bits", "ldp.msg.tlv.unknown", FT_UINT8, BASE_HEX, VALS(tlv_unknown_vals), 0xC0, "TLV Unknown bits Field", HFILL }},
1593 { "TLV Type", "ldp.msg.tlv.type", FT_UINT16, BASE_HEX, VALS(tlv_type_names), 0x3FFF, "TLV Type Field", HFILL }},
1596 {"TLV Length", "ldp.msg.tlv.len", FT_UINT16, BASE_DEC, NULL, 0x0, "TLV Length Field", HFILL }},
1598 { &hf_ldp_tlv_value,
1599 { "TLV Value", "ldp.msg.tlv.value", FT_BYTES, BASE_NONE, NULL, 0x0, "TLV Value Bytes", HFILL }},
1601 { &hf_ldp_tlv_val_hold,
1602 { "Hold Time", "ldp.msg.tlv.hello.hold", FT_UINT16, BASE_DEC, NULL, 0x0, "Hello Common Parameters Hold Time", HFILL }},
1604 { &hf_ldp_tlv_val_target,
1605 { "Targeted Hello", "ldp.msg.tlv.hello.targeted", FT_BOOLEAN, 8, TFS(&hello_targeted_vals), 0x80, "Hello Common Parameters Targeted Bit", HFILL }},
1607 { &hf_ldp_tlv_val_request,
1608 { "Hello Requested", "ldp,msg.tlv.hello.requested", FT_BOOLEAN, 8, TFS(&hello_requested_vals), 0x40, "Hello Common Parameters Hello Requested Bit", HFILL }},
1610 { &hf_ldp_tlv_val_res,
1611 { "Reserved", "ldp.msg.tlv.hello.res", FT_UINT16, BASE_HEX, NULL, 0x3FFF, "Hello Common Parameters Reserved Field", HFILL }},
1613 { &hf_ldp_tlv_ipv4_taddr,
1614 { "IPv4 Transport Address", "ldp.msg.tlv.ipv4.taddr", FT_IPv4, BASE_DEC, NULL, 0x0, "IPv4 Transport Address", HFILL }},
1616 { &hf_ldp_tlv_config_seqno,
1617 { "Configuration Sequence Number", "ldp.msg.tlv.hello.cnf_seqno", FT_UINT32, BASE_DEC, NULL, 0x0, "Hello Configuration Sequence Number", HFILL }},
1619 { &hf_ldp_tlv_ipv6_taddr,
1620 { "IPv6 Transport Address", "ldp.msg.tlv.ipv6.taddr", FT_IPv6, BASE_DEC, NULL, 0x0, "IPv6 Transport Address", HFILL }},
1622 { &hf_ldp_tlv_fec_wc,
1623 { "FEC Element Type", "ldp.msg.tlv.fec.type", FT_UINT8, BASE_DEC, VALS(fec_types), 0x0, "Forwarding Equivalence Class Element Types", HFILL }},
1625 { &hf_ldp_tlv_fec_af,
1626 { "FEC Element Address Type", "ldp.msg.tlv.fec.af", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, "Forwarding Equivalence Class Element Address Family", HFILL }},
1628 { &hf_ldp_tlv_fec_len,
1629 { "FEC Element Length", "ldp.msg.tlv.fec.len", FT_UINT8, BASE_DEC, NULL, 0x0, "Forwarding Equivalence Class Element Length", HFILL }},
1631 { &hf_ldp_tlv_fec_pfval,
1632 { "FEC Element Prefix Value", "ldp.msg.tlv.fec.pfval", FT_STRING, BASE_NONE, NULL, 0x0, "Forwarding Equivalence Class Element Prefix", HFILL }},
1634 { &hf_ldp_tlv_fec_hoval,
1635 { "FEC Element Host Address Value", "ldp.msg.tlv.fec.hoval", FT_STRING, BASE_NONE, NULL, 0x0, "Forwarding Equivalence Class Element Address", HFILL }},
1637 { &hf_ldp_tlv_addrl_addr_family,
1638 { "Address Family", "ldp.msg.tlv.addrl.addr_family", FT_UINT16, BASE_DEC, VALS(afn_vals), 0x0, "Address Family List", HFILL }},
1640 { &hf_ldp_tlv_addrl_addr,
1641 { "Address", "ldp.msg.tlv.addrl.addr", FT_STRING, BASE_NONE, NULL, 0x0, "Address", HFILL }},
1643 { &hf_ldp_tlv_hc_value,
1644 { "Hop Count Value", "ldp.msg.tlv.hc.value", FT_UINT8, BASE_DEC, NULL, 0x0, "Hop Count", HFILL }},
1646 { &hf_ldp_tlv_pv_lsrid,
1647 { "LSR Id", "ldp.msg.tlv.pv.lsrid", FT_IPv4, BASE_DEC, NULL, 0x0, "Path Vector LSR Id", HFILL }},
1649 { &hf_ldp_tlv_sess_ver,
1650 { "Session Protocol Version", "ldp.msg.tlv.sess.ver", FT_UINT16, BASE_DEC, NULL, 0x0, "Common Session Parameters Protocol Version", HFILL }},
1652 { &hf_ldp_tlv_sess_ka,
1653 { "Session KeepAlive Time", "ldp.msg.tlv.sess.ka", FT_UINT16, BASE_DEC, NULL, 0x0, "Common Session Parameters KeepAlive Time", HFILL }},
1655 { &hf_ldp_tlv_sess_advbit,
1656 { "Session Label Advertisement Discipline", "ldp.msg.tlv.sess.advbit",
1657 FT_BOOLEAN, 8, TFS(&tlv_sess_advbit_vals), 0x80,
1658 "Common Session Parameters Label Advertisement Discipline", HFILL }},
1660 { &hf_ldp_tlv_sess_ldetbit,
1661 { "Session Loop Detection", "ldp.msg.tlv.sess.ldetbit", FT_BOOLEAN, 8, TFS(&tlv_sess_ldetbit_vals), 0x40, "Common Session Parameters Loop Detection", HFILL }},
1663 { &hf_ldp_tlv_sess_pvlim,
1664 { "Session Path Vector Limit", "ldp.msg.tlv.sess.pvlim", FT_UINT8, BASE_DEC, NULL, 0x0, "Common Session Parameters Path Vector Limit", HFILL }},
1666 { &hf_ldp_tlv_sess_mxpdu,
1667 { "Session Max PDU Length", "ldp.msg.tlv.sess.mxpdu", FT_UINT16, BASE_DEC, NULL, 0x0, "Common Session Parameters Max PDU Length", HFILL }},
1669 { &hf_ldp_tlv_sess_rxlsr,
1670 { "Session Receiver LSR Identifier", "ldp.msg.tlv.sess.rxlsr", FT_IPv4, BASE_DEC, NULL, 0x0, "Common Session Parameters LSR Identifier", HFILL }},
1672 { &hf_ldp_tlv_sess_rxls,
1673 { "Session Receiver Label Space Identifier", "ldp.msg.tlv.sess.rxlsr", FT_UINT16, BASE_DEC, NULL, 0x0, "Common Session Parameters Receiver Label Space Identifier", HFILL }},
1675 { &hf_ldp_tlv_sess_atm_merge,
1676 { "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 }},
1678 { &hf_ldp_tlv_sess_atm_lr,
1679 { "Number of ATM Label Ranges", "ldp.msg.tlv.sess.atm.lr", FT_UINT8, BASE_DEC, NULL, 0x3C, "Number of Label Ranges", HFILL }},
1681 { &hf_ldp_tlv_sess_atm_dir,
1682 { "Directionality", "ldp.msg.tlv.sess.atm.dir", FT_BOOLEAN, 8, TFS(&tlv_atm_dirbit), 0x02, "Lablel Directionality", HFILL }},
1684 { &hf_ldp_tlv_sess_atm_minvpi,
1685 { "Minimum VPI", "ldp.msg.tlv.sess.atm.minvpi", FT_UINT16, BASE_DEC, NULL, 0x0FFF, "Minimum VPI", HFILL }},
1687 { &hf_ldp_tlv_sess_atm_minvci,
1688 { "Minimum VCI", "ldp.msg.tlv.sess.atm.minvci", FT_UINT16, BASE_DEC, NULL, 0x0, "Minimum VCI", HFILL }},
1690 { &hf_ldp_tlv_sess_atm_maxvpi,
1691 { "Maximum VPI", "ldp.msg.tlv.sess.atm.maxvpi", FT_UINT16, BASE_DEC, NULL, 0x0FFF, "Maximum VPI", HFILL }},
1693 { &hf_ldp_tlv_sess_atm_maxvci,
1694 { "Maximum VCI", "ldp.msg.tlv.sess.atm.maxvci", FT_UINT16, BASE_DEC, NULL, 0x0, "Maximum VCI", HFILL }},
1696 { &hf_ldp_tlv_sess_fr_merge,
1697 { "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 }},
1699 { &hf_ldp_tlv_sess_fr_lr,
1700 { "Number of Frame Relay Label Ranges", "ldp.msg.tlv.sess.fr.lr", FT_UINT8, BASE_DEC, NULL, 0x3C, "Number of Label Ranges", HFILL }},
1702 { &hf_ldp_tlv_sess_fr_dir,
1703 { "Directionality", "ldp.msg.tlv.sess.fr.dir", FT_BOOLEAN, 8, TFS(&tlv_atm_dirbit), 0x02, "Lablel Directionality", HFILL }},
1705 { &hf_ldp_tlv_sess_fr_len,
1706 { "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 }},
1708 { &hf_ldp_tlv_sess_fr_mindlci,
1709 { "Minimum DLCI", "ldp.msg.tlv.sess.fr.mindlci", FT_UINT24, BASE_DEC, NULL, 0x7FFFFF, "Minimum DLCI", HFILL }},
1711 { &hf_ldp_tlv_sess_fr_maxdlci,
1712 { "Maximum DLCI", "ldp.msg.tlv.sess.fr.maxdlci", FT_UINT24, BASE_DEC, NULL, 0x7FFFFF, "Maximum DLCI", HFILL }},
1714 { &hf_ldp_tlv_lbl_req_msg_id,
1715 { "Label Request Message ID", "ldp.tlv.lbl_req_msg_id", FT_UINT32, BASE_HEX, NULL, 0x0, "Label Request Message to be aborted", HFILL }},
1717 { &hf_ldp_tlv_vendor_id,
1718 { "Vendor ID", "ldp.msg.tlv.vendor_id", FT_UINT32, BASE_HEX, NULL, 0, "IEEE 802 Assigned Vendor ID", HFILL }},
1720 { &hf_ldp_tlv_experiment_id,
1721 { "Experiment ID", "ldp.msg.tlv.experiment_id", FT_UINT32, BASE_HEX, NULL, 0, "Experiment ID", HFILL }},
1723 { &hf_ldp_tlv_generic_label,
1724 { "Generic Label", "ldp.msg.tlv.generic.label", FT_UINT32, BASE_HEX, NULL, 0x000FFFFF, "Generic Label", HFILL }},
1726 { &hf_ldp_tlv_atm_label_vbits,
1727 { "V-bits", "ldp.msg.tlv.atm.label.vbits", FT_UINT8, BASE_HEX, VALS(tlv_atm_vbits_vals), 0x30, "ATM Label V Bits", HFILL }},
1729 { &hf_ldp_tlv_atm_label_vpi,
1730 { "VPI", "ldp.msg.tlv.atm.label.vpi", FT_UINT16, BASE_DEC, NULL, 0x0FFF, "ATM Label VPI", HFILL }},
1732 { &hf_ldp_tlv_atm_label_vci,
1733 { "VCI", "ldp.msg.tlv.atm.label.vci", FT_UINT16, BASE_DEC, NULL, 0, "ATM Label VCI", HFILL }},
1735 { &hf_ldp_tlv_fr_label_len,
1736 { "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 }},
1738 { &hf_ldp_tlv_fr_label_dlci,
1739 { "DLCI", "ldp.msg.tlv.fr.label.dlci", FT_UINT24, BASE_DEC, NULL, 0x7FFFFF, "FRAME RELAY Label DLCI", HFILL }},
1741 { &hf_ldp_tlv_status_ebit,
1742 { "E Bit", "ldp.msg.tlv.status.ebit", FT_BOOLEAN, 8, TFS(&tlv_status_ebit), 0x80, "Fatal Error Bit", HFILL }},
1744 { &hf_ldp_tlv_status_fbit,
1745 { "F Bit", "ldp.msg.tlv.status.fbit", FT_BOOLEAN, 8, TFS(&tlv_status_fbit), 0x40, "Forward Bit", HFILL }},
1747 { &hf_ldp_tlv_status_data,
1748 { "Status Data", "ldp.msg.tlv.status.data", FT_UINT32, BASE_HEX, VALS(tlv_status_data), 0x3FFFFFFF, "Status Data", HFILL }},
1750 { &hf_ldp_tlv_status_msg_id,
1751 { "Message ID", "ldp.msg.tlv.status.msg.id", FT_UINT32, BASE_HEX, NULL, 0x0, "Identifies peer message to which Status TLV refers", HFILL }},
1753 { &hf_ldp_tlv_status_msg_type,
1754 { "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 }},
1756 { &hf_ldp_tlv_extstatus_data,
1757 { "Extended Status Data", "ldp.msg.tlv.extstatus.data", FT_UINT32, BASE_HEX, NULL, 0x0, "Extended Status Data", HFILL }},
1759 { &hf_ldp_tlv_returned_version,
1760 { "Returned PDU Version", "ldp.msg.tlv.returned.version", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Version Number", HFILL }},
1762 { &hf_ldp_tlv_returned_pdu_len,
1763 { "Returned PDU Length", "ldp.msg.tlv.returned.pdu_len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP PDU Length", HFILL }},
1765 { &hf_ldp_tlv_returned_lsr,
1766 { "Returned PDU LSR ID", "ldp.msg.tlv.returned.ldpid.lsr", FT_IPv4, BASE_DEC, NULL, 0x0, "LDP Label Space Router ID", HFILL }},
1768 { &hf_ldp_tlv_returned_ls_id,
1769 { "Returned PDU Label Space ID", "ldp.msg.tlv.returned.ldpid.lsid", FT_UINT16, BASE_HEX, NULL, 0x0, "LDP Label Space ID", HFILL }},
1771 { &hf_ldp_tlv_returned_msg_ubit,
1772 { "Returned Message Unknown bit", "ldp.msg.tlv.returned.msg.ubit", FT_UINT8, BASE_HEX, TFS(&ldp_message_ubit), 0x80, "Message Unknown bit", HFILL }},
1774 { &hf_ldp_tlv_returned_msg_type,
1775 { "Returned Message Type", "ldp.msg.tlv.returned.msg.type", FT_UINT16, BASE_HEX, VALS(ldp_message_types), 0x7FFF, "LDP message type", HFILL }},
1777 { &hf_ldp_tlv_returned_msg_len,
1778 { "Returned Message Length", "ldp.msg.tlv.returned.msg.len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Message Length (excluding message type and len)", HFILL }},
1780 { &hf_ldp_tlv_returned_msg_id,
1781 { "Returned Message ID", "ldp.msg.tlv.returned.msg.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Message ID", HFILL }},
1783 {&hf_ldp_tlv_fec_vc_controlword,
1784 {"C-bit", "ldp.msg.tlv.fec.vc.controlword", FT_BOOLEAN, 8, TFS(&fec_vc_cbit), 0x80, "Control Word Present", HFILL }},
1786 {&hf_ldp_tlv_fec_vc_vctype,
1787 {"VC Type", "ldp.msg.tlv.fec.vc.vctype", FT_UINT16, BASE_HEX, VALS(fec_vc_types_vals), 0x7FFF, "Virtual Circuit Type", HFILL }},
1789 {&hf_ldp_tlv_fec_vc_infolength,
1790 {"VC Info Length", "ldp.msg.tlv.fec.vc.infolength", FT_UINT8, BASE_DEC, NULL, 0x0, "VC FEC Info Length", HFILL }},
1792 {&hf_ldp_tlv_fec_vc_groupid,
1793 {"Group ID", "ldp.msg.tlv.fec.vc.groupid", FT_UINT32, BASE_DEC, NULL, 0x0, "VC FEC Group ID", HFILL }},
1795 {&hf_ldp_tlv_fec_vc_vcid,
1796 {"VC ID", "ldp.msg.tlv.fec.vc.vcid", FT_UINT32, BASE_DEC, NULL, 0x0, "VC FEC VCID", HFILL }},
1798 {&hf_ldp_tlv_fec_vc_intparam_length,
1799 {"Length", "ldp.msg.tlv.fec.vc.intparam.length", FT_UINT8, BASE_DEC, NULL, 0x0, "VC FEC Interface Paramater Length", HFILL }},
1801 {&hf_ldp_tlv_fec_vc_intparam_mtu,
1802 {"MTU", "ldp.msg.tlv.fec.vc.intparam.mtu", FT_UINT16, BASE_DEC, NULL, 0x0, "VC FEC Interface Paramater MTU", HFILL }},
1804 {&hf_ldp_tlv_fec_vc_intparam_id,
1805 {"ID", "ldp.msg.tlv.fec.vc.intparam.id", FT_UINT8, BASE_HEX, VALS(fec_vc_interfaceparm), 0x0, "VC FEC Interface Paramater ID", HFILL }},
1807 {&hf_ldp_tlv_fec_vc_intparam_maxcatmcells,
1808 {"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 }},
1810 { &hf_ldp_tlv_fec_vc_intparam_desc,
1811 { "Description", "ldp.msg.tlv.fec.vc.intparam.desc", FT_STRING, BASE_DEC, NULL, 0, "VC FEC Interface Description", HFILL }},
1813 {&hf_ldp_tlv_fec_vc_intparam_cembytes,
1814 {"Payload Bytes", "ldp.msg.tlv.fec.vc.intparam.cembytes", FT_UINT16, BASE_DEC, NULL, 0x0, "VC FEC Interface Param CEM Payload Bytes", HFILL }},
1818 static gint *ett[] = {
1826 &ett_ldp_fec_vc_interfaceparam
1828 module_t *ldp_module;
1830 proto_ldp = proto_register_protocol("Label Distribution Protocol",
1833 proto_register_field_array(proto_ldp, hf, array_length(hf));
1834 proto_register_subtree_array(ett, array_length(ett));
1836 /* Register our configuration options for , particularly our port */
1838 ldp_module = prefs_register_protocol(proto_ldp, proto_reg_handoff_ldp);
1840 prefs_register_uint_preference(ldp_module, "tcp.port", "LDP TCP Port",
1841 "Set the TCP port for messages (if other"
1842 " than the default of 646)",
1843 10, &global_ldp_tcp_port);
1845 prefs_register_uint_preference(ldp_module, "udp.port", "LDP UDP Port",
1846 "Set the UDP port for messages (if other"
1847 " than the default of 646)",
1848 10, &global_ldp_udp_port);
1850 prefs_register_bool_preference(ldp_module, "desegment_ldp_messages",
1851 "Desegment all LDP messages spanning multiple TCP segments",
1852 "Whether the LDP dissector should desegment all messages spanning multiple TCP segments",
1856 /* The registration hand-off routine */
1858 proto_reg_handoff_ldp(void)
1860 static int ldp_prefs_initialized = FALSE;
1861 static dissector_handle_t ldp_tcp_handle, ldp_handle;
1863 if (!ldp_prefs_initialized) {
1865 ldp_tcp_handle = create_dissector_handle(dissect_ldp_tcp, proto_ldp);
1866 ldp_handle = create_dissector_handle(dissect_ldp, proto_ldp);
1868 ldp_prefs_initialized = TRUE;
1873 dissector_delete("tcp.port", tcp_port, ldp_tcp_handle);
1874 dissector_delete("udp.port", udp_port, ldp_handle);
1878 /* Set our port number for future use */
1880 tcp_port = global_ldp_tcp_port;
1881 udp_port = global_ldp_udp_port;
1883 dissector_add("tcp.port", global_ldp_tcp_port, ldp_tcp_handle);
1884 dissector_add("udp.port", global_ldp_udp_port, ldp_handle);