/* packet-ldp.c
* Routines for LDP (RFC 3036) packet disassembly
*
- * $Id: packet-ldp.c,v 1.30 2002/03/16 23:15:45 guy Exp $
- *
+ * $Id: packet-ldp.c,v 1.43 2002/08/28 21:00:20 jmayer Exp $
+ *
* Copyright (c) November 2000 by Richard Sharpe <rsharpe@ns.aus.com>
*
+ * CRLDP (RFC3212) is now supported
+ * - (c) 2002 Michael Rozhavsky <mike[AT]tochna.technion.ac.il>
+ *
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* Copyright 1999 Gerald Combs
#include "config.h"
#endif
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "prefs.h"
#include "afn.h"
+#include "packet-frame.h"
+
#define TCP_PORT_LDP 646
#define UDP_PORT_LDP 646
static int hf_ldp_tlv_returned_msg_type = -1;
static int hf_ldp_tlv_returned_msg_len = -1;
static int hf_ldp_tlv_returned_msg_id = -1;
+static int hf_ldp_tlv_mac = -1;
static int hf_ldp_tlv_sess_ver = -1;
static int hf_ldp_tlv_sess_ka = -1;
static int hf_ldp_tlv_sess_advbit = -1;
static int hf_ldp_tlv_fec_vc_vctype = -1;
static int hf_ldp_tlv_fec_vc_infolength = -1;
static int hf_ldp_tlv_fec_vc_groupid = -1;
-static int hf_ldp_tlv_fec_vc_vcid = -1;
+static int hf_ldp_tlv_fec_vc_vcid = -1;
static int hf_ldp_tlv_fec_vc_intparam_length = -1;
static int hf_ldp_tlv_fec_vc_intparam_mtu = -1;
static int hf_ldp_tlv_fec_vc_intparam_id = -1;
static int hf_ldp_tlv_fec_vc_intparam_maxcatmcells = -1;
static int hf_ldp_tlv_fec_vc_intparam_desc = -1;
static int hf_ldp_tlv_fec_vc_intparam_cembytes = -1;
+static int hf_ldp_tlv_fec_vc_intparam_vpnid_oui = -1;
+static int hf_ldp_tlv_fec_vc_intparam_vpnid_index = -1;
+static int hf_ldp_tlv_lspid_act_flg = -1;
+static int hf_ldp_tlv_lspid_cr_lsp = -1;
+static int hf_ldp_tlv_lspid_ldpid = -1;
+static int hf_ldp_tlv_er_hop_loose = -1;
+static int hf_ldp_tlv_er_hop_prelen = -1;
+static int hf_ldp_tlv_er_hop_prefix4 = -1;
+static int hf_ldp_tlv_er_hop_prefix6 = -1;
+static int hf_ldp_tlv_er_hop_as = -1;
+static int hf_ldp_tlv_er_hop_cr_lsp = -1;
+static int hf_ldp_tlv_er_hop_ldpid = -1;
+static int hf_ldp_tlv_flags_reserv = -1;
+static int hf_ldp_tlv_flags_weight = -1;
+static int hf_ldp_tlv_flags_ebs = -1;
+static int hf_ldp_tlv_flags_cbs = -1;
+static int hf_ldp_tlv_flags_cdr = -1;
+static int hf_ldp_tlv_flags_pbs = -1;
+static int hf_ldp_tlv_flags_pdr = -1;
+static int hf_ldp_tlv_frequency = -1;
+static int hf_ldp_tlv_pdr = -1;
+static int hf_ldp_tlv_pbs = -1;
+static int hf_ldp_tlv_cdr = -1;
+static int hf_ldp_tlv_cbs = -1;
+static int hf_ldp_tlv_ebs = -1;
+static int hf_ldp_tlv_weight = -1;
+static int hf_ldp_tlv_set_prio = -1;
+static int hf_ldp_tlv_hold_prio = -1;
+static int hf_ldp_tlv_route_pinning = -1;
+static int hf_ldp_tlv_resource_class = -1;
static int ett_ldp = -1;
static int ett_ldp_header = -1;
static int ett_ldp_ldpid = -1;
#define TLV_IPV4_TRANSPORT_ADDRESS 0x0401
#define TLV_CONFIGURATION_SEQNO 0x0402
#define TLV_IPV6_TRANSPORT_ADDRESS 0x0403
+#define TLV_MAC 0x0404
#define TLV_COMMON_SESSION_PARMS 0x0500
#define TLV_ATM_SESSION_PARMS 0x0501
#define TLV_FRAME_RELAY_SESSION_PARMS 0x0502
#define TLV_LABEL_REQUEST_MESSAGE_ID 0x0600
+#define TLV_ER 0x0800
+#define TLV_ER_HOP_IPV4 0x0801
+#define TLV_ER_HOP_IPV6 0x0802
+#define TLV_ER_HOP_AS 0x0803
+#define TLV_ER_HOP_LSPID 0x0804
+#define TLV_TRAFFIC_PARAM 0x0810
+#define TLV_PREEMPTION 0x0820
+#define TLV_LSPID 0x0821
+#define TLV_RESOURCE_CLASS 0x0822
+#define TLV_ROUTE_PINNING 0x0823
#define TLV_VENDOR_PRIVATE_START 0x3E00
#define TLV_VENDOR_PRIVATE_END 0x3EFF
#define TLV_EXPERIMENTAL_START 0x3F00
#define TLV_EXPERIMENTAL_END 0x3FFF
-static const value_string tlv_type_names[] = {
+static const value_string tlv_type_names[] = {
{ TLV_FEC, "Forwarding Equivalence Classes TLV" },
{ TLV_ADDRESS_LIST, "Address List TLV"},
{ TLV_HOP_COUNT, "Hop Count TLV"},
{ TLV_IPV4_TRANSPORT_ADDRESS, "IPv4 Transport Address TLV"},
{ TLV_CONFIGURATION_SEQNO, "Configuration Sequence Number TLV"},
{ TLV_IPV6_TRANSPORT_ADDRESS, "IPv6 Transport Address TLV"},
+ { TLV_MAC, "MAC TLV"},
{ TLV_COMMON_SESSION_PARMS, "Common Session Parameters TLV"},
{ TLV_ATM_SESSION_PARMS, "ATM Session Parameters TLV"},
{ TLV_FRAME_RELAY_SESSION_PARMS, "Frame Relay Session Parameters TLV"},
{ TLV_LABEL_REQUEST_MESSAGE_ID, "Label Request Message ID TLV"},
+ { TLV_LSPID, "LSP ID TLV"},
+ { TLV_ER, "Explicit route TLV"},
+ { TLV_ER_HOP_IPV4, "ER hop IPv4 prefix TLV"},
+ { TLV_ER_HOP_IPV6, "ER hop IPv6 prefix TLV"},
+ { TLV_ER_HOP_AS, "ER hop Autonomous system number prefix TLV"},
+ { TLV_TRAFFIC_PARAM, "Traffic parameters TLV"},
+ { TLV_PREEMPTION, "Preemption TLV"},
+ { TLV_ER_HOP_LSPID, "ER hop LSPID prefix TLV"},
+ { TLV_RESOURCE_CLASS, "Resource Class (Color) TLV"},
+ { TLV_ROUTE_PINNING, "Route Pinning TLV"},
{ TLV_VENDOR_PRIVATE_START, "Vendor Private TLV"},
{ TLV_EXPERIMENTAL_START, "Experimental TLV"},
{ 0, NULL}
};
static const value_string tlv_unknown_vals[] = {
- {0, "Known TLV"},
- {1, "Known TLV"},
+ {0, "Known TLV, do not Forward"},
+ {1, "Known TLV, do Forward"},
{2, "Unknown TLV, do not Forward"},
{3, "Unknown TLV, do Forward"},
{0, NULL}
#define WILDCARD_FEC 1
#define PREFIX_FEC 2
#define HOST_FEC 3
+#define CRLSP_FEC 4
#define VC_FEC 0x80 /* draft-martini-l2circuit-trans-mpls */
static const value_string fec_types[] = {
{WILDCARD_FEC, "Wildcard FEC"},
{PREFIX_FEC, "Prefix FEC"},
{HOST_FEC, "Host Address FEC"},
+ {CRLSP_FEC, "CR LSP FEC"},
{VC_FEC, "Virtual Circuit FEC"},
{0, NULL}
};
{0x0009, "ATM VCC cell transport"},
{0x8008, "CEM"},
{0x000A, "ATM VPC cell transport"},
+ {0x000B, "Ethernet VPLS"},
{0, NULL}
};
#define FEC_VC_INTERFACEPARAM_DESCRIPTION 0x03
#define FEC_VC_INTERFACEPARAM_CEMBYTES 0x04
#define FEC_VC_INTERFACEPARAM_CEMOPTIONS 0x05
+#define FEC_VC_INTERFACEPARAM_VPNID 0x06
static const value_string fec_vc_interfaceparm[] = {
{FEC_VC_INTERFACEPARAM_MAXCATMCELLS, "Max Concatenated ATM cells"},
{FEC_VC_INTERFACEPARAM_DESCRIPTION, "Interface Description"},
{FEC_VC_INTERFACEPARAM_CEMBYTES, "CEM Payload Bytes"},
- {FEC_VC_INTERFACEPARAM_CEMOPTIONS, "CEM options"}
+ {FEC_VC_INTERFACEPARAM_CEMOPTIONS, "CEM options"},
+ {FEC_VC_INTERFACEPARAM_VPNID, "VPN Id"}
};
static const true_false_string fec_vc_cbit = {
{0, NULL}
};
+static const value_string ldp_act_flg_vals[] = {
+ {0, "indicates initial LSP setup"},
+ {1, "indicates modify LSP"},
+ {0, NULL}
+};
+
+static const value_string route_pinning_vals[] = {
+ {0, "route pinning is not requested"},
+ {1, "route pinning is requested"},
+ {0, NULL}
+};
+
+static const value_string ldp_loose_vals[] = {
+ {0, "strict hop"},
+ {1, "loose hop"},
+ {0, NULL}
+};
+
+static const true_false_string tlv_negotiable = {
+ "Negotiable",
+ "Not negotiable"
+};
+
+static const value_string freq_values[] = {
+ {0, "Unspecified"},
+ {1, "Frequent"},
+ {2, "VeryFrequent"},
+ {0, NULL}
+};
+
static const true_false_string tlv_atm_dirbit = {
"Bidirectional capability",
"Unidirectional capability"
/* Dissect FEC TLV */
-void
+static void
dissect_tlv_fec(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
{
proto_tree *ti=NULL, *val_tree=NULL, *fec_tree=NULL, *vcintparam_tree=NULL;
char *str;
if (tree) {
-
- if( rem < 4 ) {
- proto_tree_add_text(tree, tvb, offset, rem, "Error processing TLV");
- return;
- }
-
ti=proto_tree_add_text(tree, tvb, offset, rem, "FEC Elements");
val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
if(val_tree == NULL) return;
while (rem > 0){
switch (tvb_get_guint8(tvb, offset)) {
case WILDCARD_FEC:
- ti = proto_tree_add_text(val_tree, tvb, offset, 4, "FEC Element %u", ix);
+ case CRLSP_FEC:
+ ti = proto_tree_add_text(val_tree, tvb, offset, 1, "FEC Element %u", ix);
fec_tree = proto_item_add_subtree(ti, ett_ldp_fec);
if(fec_tree == NULL) return;
- proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc,tvb, offset, 4, FALSE);
+ proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_wc,tvb, offset, 1, FALSE);
rem -= 1;
offset += 1;
break;
family=tvb_get_ntohs(tvb, offset+1);
prefix_len=tvb_get_guint8(tvb, offset+3);
prefix_len_octets=(prefix_len+7)/8;
-
+
implemented=1;
switch(family) {
case AFNUM_INET: /*IPv4*/
if( !implemented ) {
guint16 noctets;
-
+
noctets= rem>4+prefix_len_octets?4+prefix_len_octets:rem;
proto_tree_add_text(val_tree, tvb, offset, noctets,"Support for Address Family not implemented");
offset+=noctets;
proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_len, tvb, offset, 1, FALSE);
offset += 1;
-
-
+
+
if( addr_size < prefix_len_octets) {
offset+=addr_size;
rem-=addr_size;
fprintf(stderr, "packet-ldp: dissect_tlv_fec() malloc failed\n");
return;
}
-
+
for(ax=0; ax+1 <= prefix_len_octets; ax++)
addr[ax]=tvb_get_guint8(tvb, offset+ax);
if( prefix_len % 8 )
str = (* (char* (*)(guint8 *))str_handler)(addr);
proto_tree_add_string_format(fec_tree, hf_ldp_tlv_fec_pfval, tvb, offset, prefix_len_octets, str, "Prefix: %s", str);
-
+
offset += prefix_len_octets;
rem -= 4+prefix_len_octets;
g_free(addr);
if( !implemented ) {
guint16 noctets;
-
+
noctets= rem>4+host_len?4+host_len:rem;
proto_tree_add_text(val_tree, tvb, offset, noctets,"Support for Address Family not implemented");
offset+=noctets;
proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_len, tvb, offset, 1, FALSE);
offset += 1;
-
-
+
+
if( addr_size != host_len) {
offset+=addr_size;
rem-=addr_size;
fprintf(stderr, "packet-ldp: dissect_tlv_fec() malloc failed\n");
return;
}
-
+
for(ax=0; ax+1 <= host_len; ax++)
addr[ax]=tvb_get_guint8(tvb, offset+ax);
str = (* (char* (*)(guint8 *))str_handler)(addr);
proto_tree_add_string_format(fec_tree, hf_ldp_tlv_fec_hoval, tvb, offset, host_len, str, "Address: %s", str);
-
+
offset += host_len;
rem -= 4+host_len;
g_free(addr);
proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_groupid,tvb, offset +4, 4, FALSE);
rem -=8;
offset +=8;
-
+
if ( (vc_len > 3) && ( rem > 3 ) ) { /* there is enough room for vcid */
proto_tree_add_item(fec_tree, hf_ldp_tlv_fec_vc_vcid,tvb, offset, 4, FALSE);
proto_item_append_text (ti," VCID: %u",tvb_get_ntohl(tvb,offset));
- } else {
+ } else {
proto_tree_add_text(val_tree,tvb,offset +4, 8 +vc_len, "VC FEC size format error");
return;
}
while ( (vc_len > 1) && (rem > 1) ) { /* enough to include id and length */
intparam_len = tvb_get_guint8(tvb, offset+1);
- ti = proto_tree_add_text(fec_tree, tvb, offset, 4, "Interface Paramameter");
+ ti = proto_tree_add_text(fec_tree, tvb, offset, intparam_len, "Interface Paramameter");
vcintparam_tree = proto_item_add_subtree(ti, ett_ldp_fec_vc_interfaceparam);
if(vcintparam_tree == NULL) return;
proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_id,tvb,offset,1,FALSE);
proto_item_append_text(ti,": CEM Payload Bytes %u", tvb_get_ntohs(tvb,offset+2));
proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_cembytes,tvb, offset+2, 2, FALSE);
break;
+ case FEC_VC_INTERFACEPARAM_VPNID:
+ /* draft-lasserre-tls-mpls-00.txt */
+ proto_item_append_text(ti,": VPN Id");
+ proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_vpnid_oui, tvb, offset+2, 3, FALSE);
+ proto_tree_add_item(vcintparam_tree,hf_ldp_tlv_fec_vc_intparam_vpnid_index, tvb, offset+5, 4, FALSE);
+ break;
case FEC_VC_INTERFACEPARAM_CEMOPTIONS:
/* draft-malis-sonet-ces-mpls CEM options still undefined */
default: /* unknown */
/* Dissect Address List TLV */
-void
+static void
dissect_tlv_address_list(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
{
proto_tree *ti = NULL, *val_tree = NULL;
if (tree) {
if( rem < 2 ) {
proto_tree_add_text(tree, tvb, offset, rem,
- "Error processing TLV");
+ "Error processing Address List TLV: length is %d, should be >= 2",
+ rem);
return;
}
str = (* (char* (*)(guint8 *))str_handler)(addr);
proto_tree_add_string_format(val_tree,
- hf_ldp_tlv_addrl_addr, tvb, offset, addr_size, str,
- "Address %u : %s", ix, str);
+ hf_ldp_tlv_addrl_addr, tvb, offset, addr_size, str,
+ "Address %u: %s", ix, str);
}
if(rem)
proto_tree_add_text(val_tree, tvb, offset, rem,
- "Error processing TLV");
+ "Error processing TLV: Extra data at end of address list");
g_free(addr);
}
}
/* Dissect Path Vector TLV */
-void
+static void
dissect_tlv_path_vector(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
{
proto_tree *ti = NULL, *val_tree = NULL;
- guint8 ix, *addr;
+ guint8 ix;
+ guint32 addr;
if (tree) {
ti=proto_tree_add_text(tree, tvb, offset, rem, "LSR IDs");
if(val_tree == NULL) return;
for(ix=1; rem >= 4; ix++, offset += 4, rem -= 4) {
- if( (addr=(guint8 *)tvb_get_ptr(tvb, offset, 4))
- == NULL)
- break;
- proto_tree_add_ipv4_format(val_tree, hf_ldp_tlv_pv_lsrid, tvb,
- offset, 4, tvb_get_ntohl(tvb, offset), "LSR Id %u : %s", ix,
- ip_to_str(addr));
+ tvb_memcpy(tvb, (guint8 *)&addr, offset, 4);
+ proto_tree_add_ipv4_format(val_tree,
+ hf_ldp_tlv_pv_lsrid, tvb, offset, 4,
+ addr, "LSR Id %u: %s", ix,
+ ip_to_str((guint8 *)&addr));
}
if(rem)
proto_tree_add_text(val_tree, tvb, offset, rem,
- "Error processing TLV");
+ "Error processing TLV: Extra data at end of path vector");
}
}
/* Dissect ATM Label TLV */
-void
+static void
dissect_tlv_atm_label(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
{
proto_tree *ti = NULL, *val_tree = NULL;
if(tree) {
if(rem != 4){
- proto_tree_add_text(tree, tvb, offset, rem, "Error processing TLV");
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing ATM Label TLV: length is %d, should be 4",
+ rem);
return;
}
ti=proto_tree_add_text(tree, tvb, offset, rem, "ATM Label");
proto_tree_add_item(val_tree, hf_ldp_tlv_atm_label_vbits, tvb, offset, 1, FALSE);
id=tvb_get_ntohs(tvb, offset)&0x0FFF;
- proto_tree_add_uint_format(val_tree, hf_ldp_tlv_atm_label_vpi, tvb, offset, 2, id, "VPI: %u", id);
-
+ proto_tree_add_uint_format(val_tree, hf_ldp_tlv_atm_label_vpi, tvb, offset, 2, id, "VPI: %u", id);
+
id=tvb_get_ntohs(tvb, offset+2);
- proto_tree_add_uint_format(val_tree, hf_ldp_tlv_atm_label_vci, tvb, offset+2, 2, id, "VCI: %u", id);
+ proto_tree_add_uint_format(val_tree, hf_ldp_tlv_atm_label_vci, tvb, offset+2, 2, id, "VCI: %u", id);
}
}
/* Dissect FRAME RELAY Label TLV */
-void
+static void
dissect_tlv_frame_label(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
{
proto_tree *ti = NULL, *val_tree = NULL;
if(tree) {
if(rem != 4){
- proto_tree_add_text(tree, tvb, offset, rem,"Error processing TLV");
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing Frame Relay Label TLV: length is %d, should be 4",
+ rem);
return;
}
ti=proto_tree_add_text(tree, tvb, offset, rem, "Frame Relay Label");
if(val_tree == NULL) return;
len=(guint8)(tvb_get_ntohs(tvb, offset)>>7) & 0x03;
- 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);
+ 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);
id=tvb_get_ntoh24(tvb, offset+1)&0x7FFFFF;
- proto_tree_add_uint_format(val_tree,
- hf_ldp_tlv_fr_label_dlci, tvb, offset+1, 3, id, "DLCI: %u", id);
+ proto_tree_add_uint_format(val_tree,
+ hf_ldp_tlv_fr_label_dlci, tvb, offset+1, 3, id, "DLCI: %u", id);
}
}
/* Dissect STATUS TLV */
-void
+static void
dissect_tlv_status(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
{
proto_tree *ti = NULL, *val_tree = NULL;
if(tree) {
if(rem != 10){
- proto_tree_add_text(tree, tvb, offset, rem,"Error processing TLV");
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing Status TLV: length is %d, should be 10",
+ rem);
return;
}
val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
if(val_tree == NULL) return;
- proto_tree_add_item(val_tree, hf_ldp_tlv_status_ebit, tvb, offset, 1, FALSE);
- proto_tree_add_item(val_tree, hf_ldp_tlv_status_fbit, tvb, offset, 1, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_status_ebit, tvb, offset, 1, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_status_fbit, tvb, offset, 1, FALSE);
data=tvb_get_ntohl(tvb, offset)&0x3FFFFFFF;
- 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);
+ 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);
- proto_tree_add_item(val_tree, hf_ldp_tlv_status_msg_id, tvb, offset+4, 4, FALSE);
- proto_tree_add_item(val_tree, hf_ldp_tlv_status_msg_type, tvb, offset+8, 2, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_status_msg_id, tvb, offset+4, 4, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_status_msg_type, tvb, offset+8, 2, FALSE);
}
}
/* Dissect Returned PDU TLV */
-void
+static void
dissect_tlv_returned_pdu(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
{
proto_tree *ti = NULL, *val_tree = NULL;
if(tree) {
if(rem < 10){
- proto_tree_add_text(tree, tvb, offset, rem,"Error processing TLV");
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing Returned PDU TLV: length is %d, should be >= 10",
+ rem);
return;
}
ti=proto_tree_add_text(tree, tvb, offset, rem, "Returned PDU");
val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
if(val_tree == NULL) return;
- proto_tree_add_item(val_tree, hf_ldp_tlv_returned_version, tvb, offset, 2, FALSE);
- proto_tree_add_item(val_tree, hf_ldp_tlv_returned_pdu_len, tvb, offset+2, 2, FALSE);
- proto_tree_add_item(val_tree, hf_ldp_tlv_returned_lsr, tvb, offset+4, 4, FALSE);
- proto_tree_add_item(val_tree, hf_ldp_tlv_returned_ls_id, tvb, offset+8, 2, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_returned_version, tvb, offset, 2, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_returned_pdu_len, tvb, offset+2, 2, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_returned_lsr, tvb, offset+4, 4, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_returned_ls_id, tvb, offset+8, 2, FALSE);
offset += 10;
rem -= 10;
/* Dissect Returned MESSAGE TLV */
-void
+static void
dissect_tlv_returned_message(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
{
proto_tree *ti = NULL, *val_tree = NULL;
if(tree) {
if(rem < 4){
- proto_tree_add_text(tree, tvb, offset, rem,"Error processing TLV");
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing Returned Message TLV: length is %d, should be >= 4",
+ rem);
return;
}
ti=proto_tree_add_text(tree, tvb, offset, rem, "Returned Message");
val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
if(val_tree == NULL) return;
- proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_ubit, tvb, offset, 1, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_ubit, tvb, offset, 1, FALSE);
type=tvb_get_ntohs(tvb, offset)&0x7FFF;
- 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);
+ 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);
- proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_len, tvb, offset+2, 2, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_len, tvb, offset+2, 2, FALSE);
offset += 4;
rem -= 4;
if( rem >= 4 ) { /*have msg_id*/
- proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_id, tvb, offset, 4, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_returned_msg_id, tvb, offset, 4, FALSE);
offset += 4;
rem -= 4;
}
/* Dissect the common hello params */
-void
+static void
+#if 0
dissect_tlv_common_hello_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+#else
+dissect_tlv_common_hello_parms(tvbuff_t *tvb, guint offset, proto_tree *tree)
+#endif
{
- proto_tree *ti = NULL, *val_tree = NULL;
+#if 0
+ proto_tree *ti = NULL;
+#endif
+ proto_tree *val_tree = NULL;
if (tree) {
#if 0
val_tree=tree;
#endif
proto_tree_add_item(val_tree, hf_ldp_tlv_val_hold, tvb, offset, 2, FALSE);
- proto_tree_add_item(val_tree, hf_ldp_tlv_val_target, tvb, offset + 2, 1, FALSE);
- proto_tree_add_item(val_tree, hf_ldp_tlv_val_request, tvb, offset + 2, 1, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_val_target, tvb, offset + 2, 2, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_val_request, tvb, offset + 2, 2, FALSE);
proto_tree_add_item(val_tree, hf_ldp_tlv_val_res, tvb, offset + 2, 2, FALSE);
}
}
+/* Dissect MAC TLV */
+
+static void
+dissect_tlv_mac(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+ guint8 ix;
+ const guint8 *mac;
+
+ if (tree) {
+ ti=proto_tree_add_text(tree, tvb, offset, rem, "MAC addresses");
+ val_tree=proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree == NULL) return;
+
+ for(ix=1; rem >= 6; ix++, offset += 6, rem -= 6) {
+ mac = tvb_get_ptr(tvb, offset, 6);
+ proto_tree_add_ether(val_tree,
+ hf_ldp_tlv_mac, tvb, offset, 6, mac);
+ }
+ if(rem)
+ proto_tree_add_text(val_tree, tvb, offset, rem,
+ "Error processing TLV: Extra data at end of path vector");
+ }
+}
+
+
+
/* Dissect the common session params */
-void
+static void
dissect_tlv_common_session_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
{
proto_tree *ti = NULL, *val_tree = NULL;
if (tree != NULL) {
- ti = proto_tree_add_text(tree, tvb, offset, rem, "Parameters");
if( rem != 14) { /*length of Comm Sess Parms tlv*/
- proto_tree_add_text(tree, tvb, offset, rem, "Error processing TLV");
- return ;
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing Common Session Parameters TLV: length is %d, should be 14",
+ rem);
+ return;
}
+ ti = proto_tree_add_text(tree, tvb, offset, rem, "Parameters");
val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
if(val_tree != NULL) {
/*Protocol Version*/
- proto_tree_add_item(val_tree, hf_ldp_tlv_sess_ver, tvb,offset, 2, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_sess_ver, tvb,offset, 2, FALSE);
/*KeepAlive Time*/
proto_tree_add_item(val_tree, hf_ldp_tlv_sess_ka, tvb,offset + 2, 2, FALSE);
/*A bit*/
proto_tree_add_item(val_tree, hf_ldp_tlv_sess_advbit,tvb, offset + 4, 1, FALSE);
-
+
/*D bit*/
proto_tree_add_item(val_tree, hf_ldp_tlv_sess_ldetbit,tvb, offset + 4, 1, FALSE);
-
+
/*Path Vector Limit*/
proto_tree_add_item(val_tree, hf_ldp_tlv_sess_pvlim,tvb, offset + 5, 1, FALSE);
-
+
/*Max PDU Length*/
proto_tree_add_item(val_tree, hf_ldp_tlv_sess_mxpdu,tvb, offset + 6, 2, FALSE);
-
+
/*Rx LSR*/
proto_tree_add_item(val_tree, hf_ldp_tlv_sess_rxlsr,tvb, offset + 8, 4, FALSE);
-
+
/*Rx LS*/
proto_tree_add_item(val_tree, hf_ldp_tlv_sess_rxls,tvb, offset + 12, 2, FALSE);
}
/* Dissect the atm session params */
-void
+static void
dissect_tlv_atm_session_parms(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
{
proto_tree *ti = NULL, *val_tree = NULL, *lbl_tree = NULL;
if (tree != NULL) {
if(rem < 4) {
proto_tree_add_text(tree, tvb, offset, rem,
- "Error processing TLV");
+ "Error processing ATM Parameters TLV: length is %d, should be >= 4",
+ rem);
return;
}
val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
if(val_tree != NULL) {
- proto_tree_add_item(val_tree, hf_ldp_tlv_sess_atm_merge,tvb, offset, 1, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_sess_atm_merge,tvb, offset, 1, FALSE);
- /*get the number of label ranges*/
+ /*get the number of label ranges*/
numlr=(tvb_get_guint8(tvb, offset)>>2) & 0x0F;
proto_tree_add_uint_format(val_tree, hf_ldp_tlv_sess_atm_lr,
tvb, offset, 1, numlr, "Number of Label Range components: %u",
- numlr);
+ numlr);
- proto_tree_add_item(val_tree, hf_ldp_tlv_sess_atm_dir,tvb, offset, 1, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_sess_atm_dir,tvb, offset, 1, FALSE);
/*move into range components*/
offset += 4;
rem -= 4;
ti = proto_tree_add_text(val_tree, tvb, offset, rem,"ATM Label Range Components");
-
+
if(numlr) {
val_tree=proto_item_add_subtree(ti,ett_ldp_tlv_val);
if( ! val_tree ) return;
if( lbl_tree == NULL ) break;
id=tvb_get_ntohs(tvb, offset)&0x0FFF;
- proto_tree_add_uint_format(lbl_tree,
- hf_ldp_tlv_sess_atm_minvpi,tvb, offset, 2, id, "Minimum VPI: %u", id);
+ proto_tree_add_uint_format(lbl_tree,
+ hf_ldp_tlv_sess_atm_minvpi,
+ tvb, offset, 2,
+ id, "Minimum VPI: %u", id);
id=tvb_get_ntohs(tvb, offset+4)&0x0FFF;
- proto_tree_add_uint_format(lbl_tree,
- hf_ldp_tlv_sess_atm_maxvpi,tvb, (offset+4), 2, id, "Maximum VPI: %u", id);
-
+ proto_tree_add_uint_format(lbl_tree,
+ hf_ldp_tlv_sess_atm_maxvpi,
+ tvb, (offset+4), 2, id,
+ "Maximum VPI: %u", id);
+
id=tvb_get_ntohs(tvb, offset+2);
- proto_tree_add_uint_format(lbl_tree,
- hf_ldp_tlv_sess_atm_minvci,tvb, offset+2, 2, id, "Minimum VCI: %u", id);
+ proto_tree_add_uint_format(lbl_tree,
+ hf_ldp_tlv_sess_atm_minvci,
+ tvb, offset+2, 2,
+ id, "Minimum VCI: %u", id);
id=tvb_get_ntohs(tvb, offset+6);
- proto_tree_add_uint_format(lbl_tree,
- hf_ldp_tlv_sess_atm_maxvci,tvb, offset+6, 2, id, "Maximum VCI: %u", id);
+ proto_tree_add_uint_format(lbl_tree,
+ hf_ldp_tlv_sess_atm_maxvci,
+ tvb, offset+6, 2,
+ id, "Maximum VCI: %u", id);
offset += 8;
}
if( rem || numlr)
- proto_tree_add_text(val_tree, tvb, offset, rem,"Error processing TLV");
+ proto_tree_add_text(val_tree, tvb, offset, rem,
+ "Error processing TLV: Extra data at end of TLV");
}
}
}
/* Dissect the frame relay session params */
-void
+static void
dissect_tlv_frame_relay_session_parms(tvbuff_t *tvb, guint offset,proto_tree *tree, int rem)
{
proto_tree *ti = NULL, *val_tree = NULL, *lbl_tree = NULL;
if (tree != NULL) {
if(rem < 4) {
proto_tree_add_text(tree, tvb, offset, rem,
- "Error processing TLV");
+ "Error processing Frame Relay Parameters TLV: length is %d, should be >= 4",
+ rem);
return;
}
if(val_tree != NULL) {
proto_tree_add_item(val_tree, hf_ldp_tlv_sess_fr_merge,
- tvb, offset, 1, FALSE);
+ tvb, offset, 1, FALSE);
- /*get the number of label ranges*/
+ /*get the number of label ranges*/
numlr=(tvb_get_guint8(tvb, offset)>>2) & 0x0F;
proto_tree_add_uint_format(val_tree, hf_ldp_tlv_sess_fr_lr,
tvb, offset, 1, numlr, "Number of Label Range components: %u",
- numlr);
+ numlr);
proto_tree_add_item(val_tree, hf_ldp_tlv_sess_fr_dir,
- tvb, offset, 1, FALSE);
+ tvb, offset, 1, FALSE);
/*move into range components*/
offset += 4;
if( lbl_tree == NULL ) break;
len=(guint8)(tvb_get_ntohs(tvb, offset)>>7) & 0x03;
- 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);
+ 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);
id=tvb_get_ntoh24(tvb, offset+1)&0x7FFFFF;
- proto_tree_add_uint_format(lbl_tree,
- hf_ldp_tlv_sess_fr_mindlci, tvb, offset+1, 3, id, "Minimum DLCI %u", id);
+ proto_tree_add_uint_format(lbl_tree,
+ hf_ldp_tlv_sess_fr_mindlci, tvb, offset+1, 3, id, "Minimum DLCI %u", id);
id=tvb_get_ntoh24(tvb, offset+5)&0x7FFFFF;
- proto_tree_add_uint_format(lbl_tree,
- hf_ldp_tlv_sess_fr_maxdlci, tvb, offset+5, 3, id, "Maximum DLCI %u", id);
+ proto_tree_add_uint_format(lbl_tree,
+ hf_ldp_tlv_sess_fr_maxdlci, tvb, offset+5, 3, id, "Maximum DLCI %u", id);
offset += 8;
}
if( rem || numlr)
proto_tree_add_text(val_tree, tvb, offset, rem,
- "Error processing TLV");
+ "Error processing TLV: Extra data at end of TLV");
+ }
+ }
+}
+
+
+static void
+dissect_tlv_lspid(tvbuff_t *tvb, guint offset,proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+
+ if (tree != NULL) {
+ if(rem != 8) {
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing LSP ID TLV: length is %d, should be 8",
+ rem);
+ return;
+ }
+
+ ti = proto_tree_add_text(tree, tvb, offset, rem,
+ "LSP ID");
+ val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree != NULL) {
+ proto_tree_add_item(val_tree, hf_ldp_tlv_lspid_act_flg,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_item(val_tree, hf_ldp_tlv_lspid_cr_lsp,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_item(val_tree, hf_ldp_tlv_lspid_ldpid,
+ tvb, offset, 4, FALSE);
+ }
+ }
+}
+
+static void
+dissect_tlv_er_hop_ipv4(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+
+
+ if (tree != NULL) {
+ if(rem != 8) {
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing ER HOP IPv4 TLV: length is %d, should be 8",
+ rem);
+ return;
+ }
+ ti = proto_tree_add_text(tree, tvb, offset, rem, "ER HOP IPv4");
+ val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree != NULL) {
+ proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_loose,
+ tvb, offset, 3, FALSE);
+ offset += 3;
+ proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_prelen,
+ tvb, offset, 1, FALSE);
+ offset ++;
+ proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_prefix4,
+ tvb, offset, 4, FALSE);
+ }
+ }
+}
+
+static void
+dissect_tlv_er_hop_ipv6(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+
+ if (tree != NULL) {
+ if(rem != 20) {
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing ER HOP IPv6 TLV: length is %d, should be 20",
+ rem);
+ return;
+ }
+ ti = proto_tree_add_text(tree, tvb, offset, rem, "ER HOP IPv6");
+ val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree != NULL) {
+ proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_loose,
+ tvb, offset, 3, FALSE);
+ offset += 3;
+ proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_prelen,
+ tvb, offset, 1, FALSE);
+ offset ++;
+ proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_prefix6,
+ tvb, offset, 16, FALSE);
+ }
+ }
+}
+
+static void
+dissect_tlv_er_hop_as(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+
+ if (tree != NULL) {
+ if(rem != 4) {
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing ER HOP AS TLV: length is %d, should be 4",
+ rem);
+ return;
+ }
+ ti = proto_tree_add_text(tree, tvb, offset, rem, "ER HOP AS");
+ val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree != NULL) {
+ proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_loose,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_as,
+ tvb, offset, 2, FALSE);
+ }
+ }
+}
+
+static void
+dissect_tlv_er_hop_lspid(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+
+ if (tree != NULL) {
+ if(rem != 8) {
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing ER HOP LSPID TLV: length is %d, should be 8",
+ rem);
+ return;
+ }
+ ti = proto_tree_add_text(tree, tvb, offset, rem, "ER HOP LSPID");
+ val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree != NULL) {
+ proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_loose,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_cr_lsp,
+ tvb, offset, 2, FALSE);
+ offset += 2;
+ proto_tree_add_item(val_tree, hf_ldp_tlv_er_hop_ldpid,
+ tvb, offset, 4, FALSE);
+ }
+ }
+}
+
+static void
+dissect_tlv_traffic(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+ guint8 val_8;
+ float val_f;
+ proto_item *pi;
+
+ if (tree != NULL) {
+ if(rem != 24) {
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing Traffic Parameters TLV: length is %d, should be 24",
+ rem);
+ return;
+ }
+ ti = proto_tree_add_text(tree, tvb, offset, rem, "Traffic parameters");
+ val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree != NULL) {
+ /* flags */
+ proto_tree_add_item(val_tree, hf_ldp_tlv_flags_reserv, tvb, offset, 1, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_flags_weight, tvb, offset, 1, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_flags_ebs, tvb, offset, 1, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_flags_cbs, tvb, offset, 1, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_flags_cdr, tvb, offset, 1, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_flags_pbs, tvb, offset, 1, FALSE);
+ proto_tree_add_item(val_tree, hf_ldp_tlv_flags_pdr, tvb, offset, 1, FALSE);
+
+ offset ++;
+ /* frequency */
+ proto_tree_add_item(val_tree, hf_ldp_tlv_frequency, tvb, offset, 1, FALSE);
+ offset ++;
+
+ /* reserver byte */
+ offset ++;
+
+ /* weight */
+ pi = proto_tree_add_item(val_tree, hf_ldp_tlv_weight, tvb, offset, 1, FALSE);
+ val_8 = tvb_get_guint8(tvb, offset);
+ if (val_8 == 0)
+ proto_item_set_text(pi, "Weight: Not applicable");
+ offset ++;
+
+ /* PDR */
+ val_f = tvb_get_ntohieee_float (tvb, offset);
+ proto_tree_add_double_format(val_tree, hf_ldp_tlv_pdr, tvb, offset,
+ 4, val_f, "PDR: %.10g Bps", val_f);
+ offset += 4;
+ /* PBS */
+ val_f = tvb_get_ntohieee_float (tvb, offset);
+ proto_tree_add_double_format(val_tree, hf_ldp_tlv_pbs, tvb, offset,
+ 4, val_f, "PBS: %.10g Bytes", val_f);
+ offset += 4;
+
+ /* CDR */
+ val_f = tvb_get_ntohieee_float (tvb, offset);
+ proto_tree_add_double_format(val_tree, hf_ldp_tlv_cdr, tvb, offset,
+ 4, val_f, "CDR: %.10g Bps", val_f);
+ offset += 4;
+
+ /* CBS */
+ val_f = tvb_get_ntohieee_float (tvb, offset);
+ proto_tree_add_double_format(val_tree, hf_ldp_tlv_cbs, tvb, offset,
+ 4, val_f, "CBS: %.10g Bytes", val_f);
+ offset += 4;
+
+ /* EBS */
+ val_f = tvb_get_ntohieee_float (tvb, offset);
+ proto_tree_add_double_format(val_tree, hf_ldp_tlv_ebs, tvb, offset,
+ 4, val_f, "EBS: %.10g Bytes", val_f);
+
+ }
+ }
+}
+
+static void
+dissect_tlv_route_pinning(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+
+ if (tree != NULL) {
+ if(rem != 4) {
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing Route Pinning TLV: length is %d, should be 4",
+ rem);
+ return;
+ }
+ ti = proto_tree_add_text(tree, tvb, offset, rem, "Route Pinning");
+ val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree != NULL) {
+ proto_tree_add_item(val_tree, hf_ldp_tlv_route_pinning,
+ tvb, offset, 4, FALSE);
+ }
+ }
+}
+
+
+static void
+dissect_tlv_resource_class(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+
+ if (tree != NULL) {
+ if(rem != 4) {
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing Resource Class TLV: length is %d, should be 4",
+ rem);
+ return;
+ }
+ ti = proto_tree_add_text(tree, tvb, offset, rem, "Resource Class");
+ val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree != NULL) {
+ proto_tree_add_item(val_tree, hf_ldp_tlv_resource_class,
+ tvb, offset, 4, FALSE);
+ }
+ }
+}
+
+
+static void
+dissect_tlv_preemption(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+
+ if (tree != NULL) {
+ if(rem != 4) {
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing Preemption TLV: length is %d, should be 4",
+ rem);
+ return;
+ }
+ ti = proto_tree_add_text(tree, tvb, offset, rem, "Preemption");
+ val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree != NULL) {
+ proto_tree_add_item(val_tree, hf_ldp_tlv_set_prio,
+ tvb, offset, 1, FALSE);
+ offset += 1;
+ proto_tree_add_item(val_tree, hf_ldp_tlv_hold_prio,
+ tvb, offset, 1, FALSE);
+ }
+ }
+}
+
+static int
+dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem);
+
+static void
+dissect_tlv_er(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
+{
+ proto_tree *ti = NULL, *val_tree = NULL;
+ int len;
+
+ if (tree != NULL) {
+ ti = proto_tree_add_text(tree, tvb, offset, rem, "Explicit route");
+ val_tree = proto_item_add_subtree(ti, ett_ldp_tlv_val);
+
+ if(val_tree != NULL) {
+ len = 0;
+ while (rem > 0) {
+ len = dissect_tlv (tvb, offset, val_tree, rem);
+ offset += len;
+ rem -= len;
+ }
}
}
}
/* Dissect a TLV and return the number of bytes consumed ... */
-int
+static int
dissect_tlv(tvbuff_t *tvb, guint offset, proto_tree *tree, int rem)
{
guint16 type, typebak;
if( rem < 4 ) {/*chk for minimum header*/
if(tree)
- proto_tree_add_text(tree, tvb, offset, rem,"Error processing TLV");
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing TLV: length is %d, should be >= 4",
+ rem);
return rem;
}
type = tvb_get_ntohs(tvb, offset) & 0x3FFF;
if (tree != NULL) {
/*chk for vendor-private*/
if(type>=TLV_VENDOR_PRIVATE_START && type<=TLV_VENDOR_PRIVATE_END){
- typebak=type; /*keep type*/
+ typebak=type; /*keep type*/
type=TLV_VENDOR_PRIVATE_START;
/*chk for experimental*/
} else if(type>=TLV_EXPERIMENTAL_START && type<=TLV_EXPERIMENTAL_END){
- typebak=type; /*keep type*/
+ typebak=type; /*keep type*/
type=TLV_EXPERIMENTAL_START;
}
proto_tree_add_item(tlv_tree, hf_ldp_tlv_unknown, tvb, offset, 1, FALSE);
- 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 );
+ 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 );
proto_tree_add_item(tlv_tree, hf_ldp_tlv_len, tvb, offset + 2, 2, FALSE);
case TLV_HOP_COUNT:
if( length != 1 ) /*error, only one byte*/
- proto_tree_add_text(tlv_tree, tvb, offset + 4,length,"Error processing TLV");
+ proto_tree_add_text(tlv_tree, tvb, offset + 4,length,
+ "Error processing Hop Count TLV: length is %d, should be 1",
+ length);
else
- proto_tree_add_item(tlv_tree, hf_ldp_tlv_hc_value, tvb,offset + 4, length, FALSE);
+ proto_tree_add_item(tlv_tree, hf_ldp_tlv_hc_value, tvb,offset + 4, length, FALSE);
break;
case TLV_PATH_VECTOR:
case TLV_GENERIC_LABEL:
if( length != 4 ) /*error, need only label*/
- proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
+ proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+ "Error processing Generic Label TLV: length is %d, should be 4",
+ length);
else {
guint32 label=tvb_get_ntohl(tvb, offset+4) & 0x000FFFFF;
proto_tree_add_uint_format(tlv_tree, hf_ldp_tlv_generic_label,
- tvb, offset+4, length, label, "Generic Label: %u", label);
+ tvb, offset+4, length, label, "Generic Label: %u", label);
}
break;
case TLV_EXTENDED_STATUS:
if( length != 4 ) /*error, need only status_code(guint32)*/
- proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
+ proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+ "Error processing Extended Status TLV: length is %d, should be 4",
+ length);
else {
- proto_tree_add_item(tlv_tree, hf_ldp_tlv_extstatus_data, tvb, offset + 4, length, FALSE);
+ proto_tree_add_item(tlv_tree, hf_ldp_tlv_extstatus_data, tvb, offset + 4, length, FALSE);
}
break;
break;
case TLV_COMMON_HELLO_PARMS:
+#if 0
dissect_tlv_common_hello_parms(tvb, offset + 4, tlv_tree, length);
+#else
+ dissect_tlv_common_hello_parms(tvb, offset + 4, tlv_tree);
+#endif
break;
case TLV_IPV4_TRANSPORT_ADDRESS:
if( length != 4 ) /*error, need only ipv4*/
- proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
+ proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+ "Error processing IPv4 Transport Address TLV: length is %d, should be 4",
+ length);
else {
proto_tree_add_item(tlv_tree, hf_ldp_tlv_ipv4_taddr, tvb, offset + 4, 4, FALSE);
}
case TLV_CONFIGURATION_SEQNO:
if( length != 4 ) /*error, need only seq_num(guint32)*/
- proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
+ proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+ "Error processing Configuration Sequence Number TLV: length is %d, should be 4",
+ length);
else {
proto_tree_add_item(tlv_tree, hf_ldp_tlv_config_seqno, tvb, offset + 4, 4, FALSE);
}
case TLV_IPV6_TRANSPORT_ADDRESS:
if( length != 16 ) /*error, need only ipv6*/
- proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
+ proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+ "Error processing IPv6 Transport Address TLV: length is %d, should be 16",
+ length);
else {
proto_tree_add_item(tlv_tree, hf_ldp_tlv_ipv6_taddr, tvb, offset + 4, 16, FALSE);
}
break;
+ case TLV_MAC: /* draft-lasserre-vkompella-ppvpn-vpls-02.txt */
+ dissect_tlv_mac(tvb, offset + 4, tlv_tree, length);
+ break;
+
case TLV_COMMON_SESSION_PARMS:
dissect_tlv_common_session_parms(tvb, offset + 4, tlv_tree, length);
break;
case TLV_LABEL_REQUEST_MESSAGE_ID:
if( length != 4 ) /*error, need only one msgid*/
- proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
+ proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+ "Error processing Label Request Message ID TLV: length is %d, should be 4",
+ length);
else
- proto_tree_add_item(tlv_tree, hf_ldp_tlv_lbl_req_msg_id, tvb,offset + 4,length, FALSE);
+ proto_tree_add_item(tlv_tree, hf_ldp_tlv_lbl_req_msg_id, tvb,offset + 4,length, FALSE);
+ break;
+
+ case TLV_LSPID:
+ dissect_tlv_lspid(tvb, offset + 4, tlv_tree, length);
+ break;
+
+ case TLV_ER:
+ dissect_tlv_er(tvb, offset + 4, tlv_tree, length);
+ break;
+
+ case TLV_ER_HOP_IPV4:
+ dissect_tlv_er_hop_ipv4(tvb, offset + 4, tlv_tree, length);
+ break;
+
+ case TLV_ER_HOP_IPV6:
+ dissect_tlv_er_hop_ipv6(tvb, offset +4, tlv_tree, length);
+ break;
+
+ case TLV_ER_HOP_AS:
+ dissect_tlv_er_hop_as(tvb, offset + 4, tlv_tree, length);
+ break;
+
+ case TLV_ER_HOP_LSPID:
+ dissect_tlv_er_hop_lspid(tvb, offset +4, tlv_tree, length);
+ break;
+
+ case TLV_TRAFFIC_PARAM:
+ dissect_tlv_traffic(tvb, offset +4, tlv_tree, length);
+ break;
+
+ case TLV_PREEMPTION:
+ dissect_tlv_preemption(tvb, offset +4, tlv_tree, length);
+ break;
+
+ case TLV_RESOURCE_CLASS:
+ dissect_tlv_resource_class(tvb, offset +4, tlv_tree, length);
+ break;
+
+ case TLV_ROUTE_PINNING:
+ dissect_tlv_route_pinning(tvb, offset +4, tlv_tree, length);
break;
case TLV_VENDOR_PRIVATE_START:
if( length < 4 ) /*error, at least Vendor ID*/
- proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
+ proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+ "Error processing Vendor Private Start TLV: length is %d, should be >= 4",
+ length);
else {
- proto_tree_add_item(tlv_tree, hf_ldp_tlv_vendor_id, tvb,offset + 4, 4, FALSE);
- if( length > 4 ) /*have data*/
+ proto_tree_add_item(tlv_tree, hf_ldp_tlv_vendor_id, tvb,offset + 4, 4, FALSE);
+ if( length > 4 ) /*have data*/
proto_tree_add_text(tlv_tree, tvb, offset + 8, length-4,"Data");
}
break;
case TLV_EXPERIMENTAL_START:
if( length < 4 ) /*error, at least Experiment ID*/
- proto_tree_add_text(tlv_tree, tvb, offset + 4, length,"Error processing TLV");
+ proto_tree_add_text(tlv_tree, tvb, offset + 4, length,
+ "Error processing Experimental Start TLV: length is %d, should be >= 4",
+ length);
else {
- proto_tree_add_item(tlv_tree, hf_ldp_tlv_experiment_id, tvb,offset + 4, 4, FALSE);
- if( length > 4 ) /*have data*/
+ proto_tree_add_item(tlv_tree, hf_ldp_tlv_experiment_id, tvb,offset + 4, 4, FALSE);
+ if( length > 4 ) /*have data*/
proto_tree_add_text(tlv_tree, tvb, offset + 8, length-4,"Data");
}
break;
/* Dissect a Message and return the number of bytes consumed ... */
-int
-dissect_msg(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, int rem)
+static int
+dissect_msg(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree)
{
guint16 type, typebak;
guint8 extra=0;
- int length, ao=0, co;
+ int length, rem, ao=0, co;
proto_tree *ti = NULL, *msg_tree = NULL;
- length=tvb_reported_length_remaining(tvb, offset);
- rem=MIN(rem, length);
+ rem=tvb_reported_length_remaining(tvb, offset);
if( rem < 8 ) {/*chk for minimum header = type + length + msg_id*/
if( check_col(pinfo->cinfo, COL_INFO) )
col_append_fstr(pinfo->cinfo, COL_INFO, "Bad Message");
if(tree)
- proto_tree_add_text(tree, tvb, offset, rem,"Error processing Message");
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing Message: length is %d, should be >= 8",
+ rem);
return rem;
}
type = tvb_get_ntohs(tvb, offset) & 0x7FFF;
/*chk for vendor-private*/
if(type>=LDP_VENDOR_PRIVATE_START && type<=LDP_VENDOR_PRIVATE_END){
- typebak=type; /*keep type*/
+ typebak=type; /*keep type*/
type=LDP_VENDOR_PRIVATE_START;
extra=4;
/*chk for experimental*/
} else if(type>=LDP_EXPERIMENTAL_MESSAGE_START && type<=LDP_EXPERIMENTAL_MESSAGE_END){
- typebak=type; /*keep type*/
+ typebak=type; /*keep type*/
type=LDP_EXPERIMENTAL_MESSAGE_START;
extra=4;
}
if( check_col(pinfo->cinfo, COL_INFO) )
col_append_fstr(pinfo->cinfo, COL_INFO, "Bad Message Length ");
if(tree)
- proto_tree_add_text(tree, tvb, offset, rem,"Error processing Message Length");
+ proto_tree_add_text(tree, tvb, offset, rem,
+ "Error processing Message Length: length is %d, should be >= %u",
+ length, 4+extra);
return rem;
}
- rem -= 4;
+ rem -= 4;
length = MIN(length, rem); /* Don't go haywire if a problem ... */
if( check_col(pinfo->cinfo, COL_INFO) ){
proto_tree_add_item(msg_tree, hf_ldp_msg_ubit, tvb, offset, 1, FALSE);
type=tvb_get_ntohs(tvb, offset)&0x7FFF;
- 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);
+ 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);
proto_tree_add_item(msg_tree, hf_ldp_msg_len, tvb, offset+2, 2, FALSE);
proto_tree_add_item(msg_tree, hf_ldp_msg_id, tvb, offset+4, 4, FALSE);
proto_tree_add_item(msg_tree, hf_tmp, tvb, offset+8, extra, FALSE);
}
}
-
+
offset += (8+extra);
length -= (4+extra);
-
- if( tree )
+
+ if( tree )
while( (length-ao) > 0 ) {
co=dissect_tlv(tvb, offset, msg_tree, length-ao);
offset += co;
ao += co;
}
-
+
return length+8+extra;
}
-/* Dissect a PDU and return the number of bytes consumed ... */
-
-int
-dissect_ldp_pdu(tvbuff_t *tvb, guint offset, packet_info *pinfo, proto_tree *tree, int rem, guint ix)
+/* Dissect a PDU */
+static void
+dissect_ldp_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- int length, ao=0, co;
+ int offset = 0, co;
+ int rem, length;
proto_tree *ti=NULL, *pdu_tree = NULL;
-
- length=tvb_reported_length_remaining(tvb, offset);
- rem=MIN(rem, length);
-
- if( rem < 10 ){/*don't even have a PDU header*/
-/*XXX Need changes in desegment_tcp to handle multiple requests*/
-#if 0
- if( pinfo->can_desegment && (pinfo->ptype==PT_TCP) && ldp_desegment ){
- pinfo->desegment_offset=offset;
- pinfo->desegment_len=10-rem;
- }
-#else
- if(tree)
- proto_tree_add_text(tree, tvb, offset, rem,"Not enough bytes for PDU Hdr in TCP segment");
-#endif
- return rem;
- }
- if( (length = tvb_get_ntohs(tvb, offset + 2)) < 6 ) {/*not enough*/
- if( check_col(pinfo->cinfo, COL_INFO) && ix )
- col_append_fstr(pinfo->cinfo, COL_INFO, "PDU %u: ", ix);
- if( check_col(pinfo->cinfo, COL_INFO) ){
- col_append_fstr(pinfo->cinfo, COL_INFO, "Bad PDU Length ");
- }
- if(tree)
- proto_tree_add_text(tree, tvb, offset, rem,"Error processing PDU Length");
- return rem;
- }
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "LDP");
- rem -=4;
- if( length>rem ){
- if( pinfo->can_desegment && (pinfo->ptype==PT_TCP) && ldp_desegment ){/*ask for more*/
- pinfo->desegment_offset=offset;
- pinfo->desegment_len=length-rem;
- }else {
- if( check_col(pinfo->cinfo, COL_INFO) && ix )
- col_append_fstr(pinfo->cinfo, COL_INFO, "PDU %u: ", ix);
- if( check_col(pinfo->cinfo, COL_INFO) )
- col_append_fstr(pinfo->cinfo, COL_INFO, "Bad PDU Length ");
- if(tree)
- proto_tree_add_text(tree, tvb, offset, rem+4,"Error processing PDU Length");
- }
- return rem+4;
- }
-
- if( check_col(pinfo->cinfo, COL_INFO) && ix )
- col_append_fstr(pinfo->cinfo, COL_INFO, "PDU %u: ", ix);
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
if( tree ){
- ti=proto_tree_add_protocol_format(tree, proto_ldp, tvb, offset,
- length+4, ix?"LDP PDU %u":"LDP PDU", ix);
+ ti=proto_tree_add_item(tree, proto_ldp, tvb, 0, -1, FALSE);
pdu_tree = proto_item_add_subtree(ti, ett_ldp);
- }
- if(pdu_tree){
proto_tree_add_item(pdu_tree, hf_ldp_version, tvb, offset, 2, FALSE);
- proto_tree_add_item(pdu_tree, hf_ldp_pdu_len, tvb, offset+2, 2, FALSE);
+ }
+
+ length = tvb_get_ntohs(tvb, offset+2);
+ if( tree )
+ proto_tree_add_uint(pdu_tree, hf_ldp_pdu_len, tvb, offset+2, 2, length);
+
+ length += 4; /* add the version and type sizes */
+ rem = tvb_reported_length_remaining(tvb, offset);
+ if (length < rem)
+ tvb_set_reported_length(tvb, length);
+
+ if( tree ){
proto_tree_add_item(pdu_tree, hf_ldp_lsr, tvb, offset+4, 4, FALSE);
proto_tree_add_item(pdu_tree, hf_ldp_ls_id, tvb, offset+8, 2, FALSE);
}
offset += 10;
- length -= 6;
- while( (length-ao) > 0 ) {
- co=dissect_msg(tvb, offset, pinfo, pdu_tree, length-ao);
+ while( tvb_reported_length_remaining(tvb, offset) > 0 ) {
+ co=dissect_msg(tvb, offset, pinfo, pdu_tree);
offset += co;
- ao += co;
}
-
- return length+10;
}
-static void
+static int
dissect_ldp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
- if (check_col(pinfo->cinfo, COL_PROTOCOL))
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "LDP");
+ /*
+ * Make sure the first PDU has a version number of 1;
+ * if not, reject this, so we don't get confused by
+ * packets that happen to be going to or from the
+ * LDP port but that aren't LDP packets.
+ */
+ if (!tvb_bytes_exist(tvb, 0, 2)) {
+ /*
+ * Not enough information to tell.
+ */
+ return 0;
+ }
+ if (tvb_get_ntohs(tvb, 0) != 1) {
+ /*
+ * Not version 1.
+ */
+ return 0;
+ }
- if (check_col(pinfo->cinfo, COL_INFO))
- col_clear(pinfo->cinfo, COL_INFO);
+ dissect_ldp_pdu(tvb, pinfo, tree);
- dissect_ldp_pdu(tvb, 0, pinfo, tree, tvb_reported_length(tvb), 0);
+ /*
+ * XXX - return minimum of this and the length of the PDU?
+ */
+ return tvb_length(tvb);
}
-static void
+static int
dissect_ldp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
-{
- int offset=0, length, rtn;
- guint ix=1;
-
+{
+ volatile gboolean first = TRUE;
+ volatile int offset = 0;
+ int length_remaining;
+ guint16 plen;
+ int length;
+ tvbuff_t *next_tvb;
+
+ while (tvb_reported_length_remaining(tvb, offset) != 0) {
+ length_remaining = tvb_length_remaining(tvb, offset);
+
+ /*
+ * Make sure the first PDU has a version number of 1;
+ * if not, reject this, so we don't get confused by
+ * packets that happen to be going to or from the
+ * LDP port but that aren't LDP packets.
+ *
+ * XXX - this means we can't handle an LDP PDU of which
+ * only one byte appears in a TCP segment. If that's
+ * a problem, we'll either have to completely punt on
+ * rejecting non-LDP packets, or will have to assume
+ * that if we have only one byte, it's an LDP packet.
+ */
+ if (first) {
+ if (length_remaining < 2) {
+ /*
+ * Not enough information to tell.
+ */
+ return 0;
+ }
+ if (tvb_get_ntohs(tvb, offset) != 1) {
+ /*
+ * Not version 1.
+ */
+ return 0;
+ }
+ first = FALSE;
+ }
- if (check_col(pinfo->cinfo, COL_PROTOCOL))
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "LDP");
+ /*
+ * Can we do reassembly?
+ */
+ if (ldp_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the LDP header split across segment
+ * boundaries?
+ */
+ if (length_remaining < 4) {
+ /*
+ * Yes. Tell the TCP dissector where
+ * the data for this message starts in
+ * the data it handed us, and how many
+ * more bytes we need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len = 4 - length_remaining;
+ return -pinfo->desegment_len;
+ }
+ }
- if (check_col(pinfo->cinfo, COL_INFO))
- col_clear(pinfo->cinfo, COL_INFO);
+ /*
+ * Get the length of the rest of the LDP packet.
+ * XXX - check for a version of 1 first?
+ */
+ plen = tvb_get_ntohs(tvb, offset + 2);
+
+ /*
+ * Can we do reassembly?
+ */
+ if (ldp_desegment && pinfo->can_desegment) {
+ /*
+ * Yes - is the LDP packet split across segment
+ * boundaries?
+ */
+ if (length_remaining < plen + 4) {
+ /*
+ * Yes. Tell the TCP dissector where the
+ * data for this message starts in the data
+ * it handed us, and how many more bytes we
+ * need, and return.
+ */
+ pinfo->desegment_offset = offset;
+ pinfo->desegment_len =
+ (plen + 4) - length_remaining;
+ return -pinfo->desegment_len;
+ }
+ }
+
+ /*
+ * Construct a tvbuff containing the amount of the payload
+ * we have available. Make its reported length the
+ * amount of data in the DNS-over-TCP packet.
+ *
+ * XXX - if reassembly isn't enabled. the subdissector
+ * will throw a BoundsError exception, rather than a
+ * ReportedBoundsError exception. We really want
+ * a tvbuff where the length is "length", the reported
+ * length is "plen + 4", and the "if the snapshot length
+ * were infinite" length is the minimum of the
+ * reported length of the tvbuff handed to us and "plen+4",
+ * with a new type of exception thrown if the offset is
+ * within the reported length but beyond that third length,
+ * with that exception getting the "Unreassembled Packet"
+ * error.
+ */
+ length = length_remaining;
+ if (length > plen + 4)
+ length = plen + 4;
+ next_tvb = tvb_new_subset(tvb, offset, length, plen + 4);
+
+ /*
+ * Dissect the LDP packet.
+ *
+ * Catch the ReportedBoundsError exception; if this
+ * particular message happens to get a ReportedBoundsError
+ * exception, that doesn't mean that we should stop
+ * dissecting LDP messages within this frame or chunk of
+ * reassembled data.
+ *
+ * If it gets a BoundsError, we can stop, as there's nothing
+ * more to see, so we just re-throw it.
+ */
+ TRY {
+ dissect_ldp_pdu(next_tvb, pinfo, tree);
+ }
+ CATCH(BoundsError) {
+ RETHROW;
+ }
+ CATCH(ReportedBoundsError) {
+ show_reported_bounds_error(tvb, pinfo, tree);
+ }
+ ENDTRY;
- length=tvb_reported_length(tvb);
- while (length > 0){
- rtn = dissect_ldp_pdu(tvb, offset, pinfo, tree, length, ix++);
- offset += rtn;
- length -= rtn;
+ /*
+ * Skip the LDP header and the payload.
+ */
+ offset += plen + 4;
}
+ return tvb_length(tvb);
}
/* Register all the bits needed with the filtering engine */
-void
+void
proto_register_ldp(void)
{
static hf_register_info hf[] = {
{ &hf_ldp_msg_len,
{ "Message Length", "ldp.msg.len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Message Length (excluding message type and len)", HFILL }},
- { &hf_ldp_msg_id,
+ { &hf_ldp_msg_id,
{ "Message ID", "ldp.msg.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Message ID", HFILL }},
- { &hf_ldp_msg_vendor_id,
+ { &hf_ldp_msg_vendor_id,
{ "Vendor ID", "ldp.msg.vendor.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Vendor-private Message ID", HFILL }},
- { &hf_ldp_msg_experiment_id,
+ { &hf_ldp_msg_experiment_id,
{ "Experiment ID", "ldp.msg.experiment.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Experimental Message ID", HFILL }},
- { &hf_ldp_tlv_unknown,
+ { &hf_ldp_tlv_unknown,
{ "TLV Unknown bits", "ldp.msg.tlv.unknown", FT_UINT8, BASE_HEX, VALS(tlv_unknown_vals), 0xC0, "TLV Unknown bits Field", HFILL }},
- { &hf_ldp_tlv_type,
+ { &hf_ldp_tlv_type,
{ "TLV Type", "ldp.msg.tlv.type", FT_UINT16, BASE_HEX, VALS(tlv_type_names), 0x3FFF, "TLV Type Field", HFILL }},
{ &hf_ldp_tlv_len,
{ "Hold Time", "ldp.msg.tlv.hello.hold", FT_UINT16, BASE_DEC, NULL, 0x0, "Hello Common Parameters Hold Time", HFILL }},
{ &hf_ldp_tlv_val_target,
- { "Targeted Hello", "ldp.msg.tlv.hello.targeted", FT_BOOLEAN, 8, TFS(&hello_targeted_vals), 0x80, "Hello Common Parameters Targeted Bit", HFILL }},
+ { "Targeted Hello", "ldp.msg.tlv.hello.targeted", FT_BOOLEAN, 16, TFS(&hello_targeted_vals), 0x8000, "Hello Common Parameters Targeted Bit", HFILL }},
{ &hf_ldp_tlv_val_request,
- { "Hello Requested", "ldp,msg.tlv.hello.requested", FT_BOOLEAN, 8, TFS(&hello_requested_vals), 0x40, "Hello Common Parameters Hello Requested Bit", HFILL }},
-
+ { "Hello Requested", "ldp,msg.tlv.hello.requested", FT_BOOLEAN, 16, TFS(&hello_requested_vals), 0x4000, "Hello Common Parameters Hello Requested Bit", HFILL }},
+
{ &hf_ldp_tlv_val_res,
{ "Reserved", "ldp.msg.tlv.hello.res", FT_UINT16, BASE_HEX, NULL, 0x3FFF, "Hello Common Parameters Reserved Field", HFILL }},
{ &hf_ldp_tlv_sess_advbit,
{ "Session Label Advertisement Discipline", "ldp.msg.tlv.sess.advbit",
- FT_BOOLEAN, 8, TFS(&tlv_sess_advbit_vals), 0x80,
+ FT_BOOLEAN, 8, TFS(&tlv_sess_advbit_vals), 0x80,
"Common Session Parameters Label Advertisement Discipline", HFILL }},
{ &hf_ldp_tlv_sess_ldetbit,
{ &hf_ldp_tlv_sess_fr_maxdlci,
{ "Maximum DLCI", "ldp.msg.tlv.sess.fr.maxdlci", FT_UINT24, BASE_DEC, NULL, 0x7FFFFF, "Maximum DLCI", HFILL }},
- { &hf_ldp_tlv_lbl_req_msg_id,
+ { &hf_ldp_tlv_lbl_req_msg_id,
{ "Label Request Message ID", "ldp.tlv.lbl_req_msg_id", FT_UINT32, BASE_HEX, NULL, 0x0, "Label Request Message to be aborted", HFILL }},
{ &hf_ldp_tlv_vendor_id,
{ &hf_ldp_tlv_status_data,
{ "Status Data", "ldp.msg.tlv.status.data", FT_UINT32, BASE_HEX, VALS(tlv_status_data), 0x3FFFFFFF, "Status Data", HFILL }},
- { &hf_ldp_tlv_status_msg_id,
+ { &hf_ldp_tlv_status_msg_id,
{ "Message ID", "ldp.msg.tlv.status.msg.id", FT_UINT32, BASE_HEX, NULL, 0x0, "Identifies peer message to which Status TLV refers", HFILL }},
{ &hf_ldp_tlv_status_msg_type,
{ &hf_ldp_tlv_returned_ls_id,
{ "Returned PDU Label Space ID", "ldp.msg.tlv.returned.ldpid.lsid", FT_UINT16, BASE_HEX, NULL, 0x0, "LDP Label Space ID", HFILL }},
- { &hf_ldp_tlv_returned_msg_ubit,
+ { &hf_ldp_tlv_returned_msg_ubit,
{ "Returned Message Unknown bit", "ldp.msg.tlv.returned.msg.ubit", FT_UINT8, BASE_HEX, TFS(&ldp_message_ubit), 0x80, "Message Unknown bit", HFILL }},
{ &hf_ldp_tlv_returned_msg_type,
{ &hf_ldp_tlv_returned_msg_len,
{ "Returned Message Length", "ldp.msg.tlv.returned.msg.len", FT_UINT16, BASE_DEC, NULL, 0x0, "LDP Message Length (excluding message type and len)", HFILL }},
- { &hf_ldp_tlv_returned_msg_id,
+ { &hf_ldp_tlv_returned_msg_id,
{ "Returned Message ID", "ldp.msg.tlv.returned.msg.id", FT_UINT32, BASE_HEX, NULL, 0x0, "LDP Message ID", HFILL }},
+ { &hf_ldp_tlv_mac,
+ { "MAC address", "ldp.msg.tlv.mac", FT_ETHER, BASE_NONE, NULL, 0x0, "MAC address", HFILL}},
+
{&hf_ldp_tlv_fec_vc_controlword,
{"C-bit", "ldp.msg.tlv.fec.vc.controlword", FT_BOOLEAN, 8, TFS(&fec_vc_cbit), 0x80, "Control Word Present", HFILL }},
{ &hf_ldp_tlv_fec_vc_intparam_desc,
{ "Description", "ldp.msg.tlv.fec.vc.intparam.desc", FT_STRING, BASE_DEC, NULL, 0, "VC FEC Interface Description", HFILL }},
- {&hf_ldp_tlv_fec_vc_intparam_cembytes,
+ { &hf_ldp_tlv_fec_vc_intparam_cembytes,
{"Payload Bytes", "ldp.msg.tlv.fec.vc.intparam.cembytes", FT_UINT16, BASE_DEC, NULL, 0x0, "VC FEC Interface Param CEM Payload Bytes", HFILL }},
+ { &hf_ldp_tlv_fec_vc_intparam_vpnid_oui,
+ { "VPN OUI", "ldp.msg.tlv.fec.vc.intparam.vpnid.oui", FT_UINT24, BASE_HEX, NULL, 0x0, "VC FEC Interface Param VPN OUI", HFILL }},
+
+ { &hf_ldp_tlv_fec_vc_intparam_vpnid_index,
+ { "VPN Index", "ldp.msg.tlv.fec.vc.intparam.vpnid.index", FT_UINT32, BASE_HEX, NULL, 0x0, "VC FEC Interface Param VPN Index", HFILL }},
+
+ { &hf_ldp_tlv_lspid_act_flg,
+ { "Action Indicator Flag", "ldp.msg.tlv.lspid.actflg", FT_UINT16, BASE_HEX, VALS(ldp_act_flg_vals), 0x000F, "Action Indicator Flag", HFILL}},
+
+ { &hf_ldp_tlv_lspid_cr_lsp,
+ { "Local CR-LSP ID", "ldp.msg.tlv.lspid.locallspid", FT_UINT16, BASE_HEX, NULL, 0x0, "Local CR-LSP ID", HFILL}},
+
+ { &hf_ldp_tlv_lspid_ldpid,
+ { "Ingress LSR Router ID", "ldp.msg.tlv.lspid.lsrid", FT_IPv4, BASE_DEC, NULL, 0x0, "Ingress LSR Router ID", HFILL}},
+
+ { &hf_ldp_tlv_er_hop_loose,
+ { "Loose route bit", "ldp.msg.tlv.er_hop.loose", FT_UINT24, BASE_HEX, VALS(ldp_loose_vals), 0x800000, "Loose route bit", HFILL}},
+
+ { &hf_ldp_tlv_er_hop_prelen,
+ { "Prefix length", "ldp.msg.tlv.er_hop.prefixlen", FT_UINT8, BASE_DEC, NULL, 0x0, "Prefix len", HFILL}},
+
+ { &hf_ldp_tlv_er_hop_prefix4,
+ { "IPv4 Address", "ldp.msg.tlv.er_hop.prefix4", FT_IPv4, BASE_DEC, NULL, 0x0, "IPv4 Address", HFILL}},
+ { &hf_ldp_tlv_er_hop_prefix6,
+ { "IPv6 Address", "ldp.msg.tlv.er_hop.prefix6", FT_IPv6, BASE_DEC, NULL, 0x0, "IPv6 Address", HFILL}},
+
+ { &hf_ldp_tlv_er_hop_as,
+ { "AS Number", "ldp.msg.tlv.er_hop.as", FT_UINT16, BASE_DEC, NULL, 0x0, "AS Number", HFILL}},
+
+ { &hf_ldp_tlv_er_hop_cr_lsp,
+ { "Local CR-LSP ID", "ldp.msg.tlv.er_hop.locallspid", FT_UINT16, BASE_DEC, NULL, 0x0, "Local CR-LSP ID", HFILL}},
+
+ { &hf_ldp_tlv_er_hop_ldpid,
+ { "Local CR-LSP ID", "ldp.msg.tlv.er_hop.lsrid", FT_IPv4, BASE_DEC, NULL, 0x0, "Local CR-LSP ID", HFILL}},
+
+ { &hf_ldp_tlv_flags_reserv,
+ { "Reserved", "ldp.msg.tlv.flags_reserv", FT_UINT8, BASE_HEX, NULL, 0xC0, "Reserved", HFILL}},
+
+ { &hf_ldp_tlv_flags_pdr,
+ { "PDR", "ldp.msg.tlv.flags_pdr", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x1, "PDR negotiability flag", HFILL}},
+
+ { &hf_ldp_tlv_flags_pbs,
+ { "PBS", "ldp.msg.tlv.flags_pbs", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x2, "PBS negotiability flag", HFILL}},
+
+ { &hf_ldp_tlv_flags_cdr,
+ { "CDR", "ldp.msg.tlv.flags_cdr", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x4, "CDR negotiability flag", HFILL}},
+
+ { &hf_ldp_tlv_flags_cbs,
+ { "CBS", "ldp.msg.tlv.flags_cbs", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x8, "CBS negotiability flag", HFILL}},
+
+ { &hf_ldp_tlv_flags_ebs,
+ { "EBS", "ldp.msg.tlv.flags_ebs", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x10, "EBS negotiability flag", HFILL}},
+
+ { &hf_ldp_tlv_flags_weight,
+ { "Weight", "ldp.msg.tlv.flags_weight", FT_BOOLEAN, 8, TFS(&tlv_negotiable), 0x20, "Weight negotiability flag", HFILL}},
+
+ { &hf_ldp_tlv_frequency,
+ { "Frequency", "ldp.msg.tlv.frequency", FT_UINT8, BASE_DEC, VALS(freq_values), 0, "Frequency", HFILL}},
+
+ { &hf_ldp_tlv_weight,
+ { "Weight", "ldp.msg.tlv.weight", FT_UINT8, BASE_DEC, NULL, 0, "Weight of the CR-LSP", HFILL}},
+
+ { &hf_ldp_tlv_pdr,
+ { "PDR", "ldp.msg.tlv.pdr", FT_DOUBLE, BASE_NONE, NULL, 0, "Peak Data Rate", HFILL}},
+
+ { &hf_ldp_tlv_pbs,
+ { "PBS", "ldp.msg.tlv.pbs", FT_DOUBLE, BASE_NONE, NULL, 0, "Peak Burst Size", HFILL}},
+
+ { &hf_ldp_tlv_cdr,
+ { "CDR", "ldp.msg.tlv.cdr", FT_DOUBLE, BASE_NONE, NULL, 0, "Committed Data Rate", HFILL}},
+
+ { &hf_ldp_tlv_cbs,
+ { "CBS", "ldp.msg.tlv.cbs", FT_DOUBLE, BASE_NONE, NULL, 0, "Committed Burst Size", HFILL}},
+
+ { &hf_ldp_tlv_ebs,
+ { "EBS", "ldp.msg.tlv.ebs", FT_DOUBLE, BASE_NONE, NULL, 0, "Excess Burst Size", HFILL}},
+
+ { &hf_ldp_tlv_set_prio,
+ { "Set Prio", "ldp.msg.tlv.set_prio", FT_UINT8, BASE_DEC, NULL, 0, "LSP setup priority", HFILL}},
+
+ { &hf_ldp_tlv_hold_prio,
+ { "Hold Prio", "ldp.msg.tlv.hold_prio", FT_UINT8, BASE_DEC, NULL, 0, "LSP hold priority", HFILL}},
+
+ { &hf_ldp_tlv_route_pinning,
+ { "Route Pinning", "ldp.msg.tlv.route_pinning", FT_UINT32, BASE_DEC, VALS(route_pinning_vals), 0x80000000, "Route Pinning", HFILL}},
+
+ { &hf_ldp_tlv_resource_class,
+ { "Resource Class", "ldp.msg.tlv.resource_class", FT_UINT32, BASE_HEX, NULL, 0, "Resource Class (Color)", HFILL}},
+
};
static gint *ett[] = {
&ett_ldp_fec,
&ett_ldp_fec_vc_interfaceparam
};
- module_t *ldp_module;
+ module_t *ldp_module;
proto_ldp = proto_register_protocol("Label Distribution Protocol",
"LDP", "ldp");
void
proto_reg_handoff_ldp(void)
{
- static int ldp_prefs_initialized = FALSE;
+ static gboolean ldp_prefs_initialized = FALSE;
static dissector_handle_t ldp_tcp_handle, ldp_handle;
if (!ldp_prefs_initialized) {
- ldp_tcp_handle = create_dissector_handle(dissect_ldp_tcp, proto_ldp);
- ldp_handle = create_dissector_handle(dissect_ldp, proto_ldp);
+ ldp_tcp_handle = new_create_dissector_handle(dissect_ldp_tcp, proto_ldp);
+ ldp_handle = new_create_dissector_handle(dissect_ldp, proto_ldp);
ldp_prefs_initialized = TRUE;