aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnish Bhatt <anish@chelsio.com>2014-06-10 18:27:53 -0400
committerMichael Mann <mmann78@netscape.net>2014-06-11 00:58:10 +0000
commit3fcd016029672b5683406ceeb75faa0533ce63c1 (patch)
tree2c17928946d0d7514b1f41abeffc4ec0fe5be1ad
parentb6f8aea069daffd888d06e020414c10da6e61cee (diff)
downloadwireshark-3fcd016029672b5683406ceeb75faa0533ce63c1.tar.gz
wireshark-3fcd016029672b5683406ceeb75faa0533ce63c1.tar.bz2
wireshark-3fcd016029672b5683406ceeb75faa0533ce63c1.zip
Fix bug in dissect_lldp_port_id, support all port id subtypes
Change-Id: I8b44e0d55701ba5d583e3e734e19d4d2aa024b25 Reviewed-on: https://code.wireshark.org/review/2049 Reviewed-by: Michael Mann <mmann78@netscape.net>
-rw-r--r--epan/dissectors/packet-lldp.c90
1 files changed, 78 insertions, 12 deletions
diff --git a/epan/dissectors/packet-lldp.c b/epan/dissectors/packet-lldp.c
index d4db577992..4a9dc3883c 100644
--- a/epan/dissectors/packet-lldp.c
+++ b/epan/dissectors/packet-lldp.c
@@ -1131,17 +1131,18 @@ dissect_lldp_chassis_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
/* Dissect Port Id TLV (Mandatory) */
static gint32
-dissect_lldp_port_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, guint32 offset)
+dissect_lldp_port_id(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 offset)
{
guint8 tempType;
guint16 tempShort;
guint32 tempLen = 0;
+ const char *strPtr=NULL;
guint32 ip_addr = 0;
struct e_in6_addr ip6_addr;
guint8 addr_family = 0;
proto_tree *port_tree = NULL;
- proto_item *tf = NULL;
+ proto_item *tf = NULL, *lf = NULL;
/* Get tlv type */
tempShort = tvb_get_ntohs(tvb, offset);
@@ -1155,46 +1156,111 @@ dissect_lldp_port_id(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gu
/* Set port tree */
tf = proto_tree_add_text(tree, tvb, offset, (tempLen + 2), "Port Subtype = %s",
- val_to_str_const(tempType, port_id_subtypes, "Unknown" ));
- port_tree = proto_item_add_subtree(tf, ett_port_id);
+ val_to_str_const(tempType, port_id_subtypes, "Unknown" ));
+ port_tree = proto_item_add_subtree(tf, ett_port_id);
proto_tree_add_item(port_tree, hf_lldp_tlv_type, tvb, offset, 2, ENC_BIG_ENDIAN);
- proto_tree_add_item(port_tree, hf_lldp_tlv_len, tvb, offset, 2, ENC_BIG_ENDIAN);
+ lf = proto_tree_add_item(port_tree, hf_lldp_tlv_len, tvb, offset, 2, ENC_BIG_ENDIAN);
+
+ if (tempLen < 2) {
+ expert_add_info_format(pinfo, lf, &ei_lldp_bad_length,
+ "Invalid Port ID Length (%u), expected > (2)", tempLen);
+
+ return -1;
+ }
/* Get port id subtype */
proto_tree_add_item(port_tree, hf_port_id_subtype, tvb, (offset+2), 1, ENC_BIG_ENDIAN);
- /* Get port id */
- /*proto_tree_add_text(port_tree, tvb, (offset+3), (tempLen-1), "Port Id: %s", strPtr);*/
switch (tempType)
{
case 3: /* MAC address */
+ if (tempLen != 7)
+ {
+ expert_add_info_format(pinfo, lf, &ei_lldp_bad_length,
+ "Invalid Port ID Length (%u) for Type (%s), expected (7)", tempLen, val_to_str_const(tempType, port_id_subtypes, ""));
+ return -1;
+ }
+
+ strPtr = tvb_ether_to_str(tvb, offset+3);
proto_tree_add_item(port_tree, hf_port_id_mac, tvb, (offset+3), 6, ENC_NA);
+
break;
case 4: /* Network address */
- /* Network address
- * networkAddress is an octet string that identifies a particular network address family
- * and an associated network address that are encoded in network octet order.
- */
- /* Network address family */
+ /* Get network address family */
+ addr_family = tvb_get_guint8(tvb,offset+3);
proto_tree_add_item(port_tree, hf_lldp_network_address_family, tvb, offset+3, 1, ENC_BIG_ENDIAN);
+ /* Check for IPv4 or IPv6 */
switch(addr_family){
case AFNUM_INET:
+ if (tempLen == 6){
+ ip_addr = tvb_get_ipv4(tvb, (offset+4));
+ strPtr = ip_to_str((guint8 *)&ip_addr);
+ }else{
+ expert_add_info_format(pinfo, lf, &ei_lldp_bad_length,
+ "Invalid Port ID Length (%u) for Type (%s, %s), expected (6)", tempLen, val_to_str_const(tempType, port_id_subtypes, ""), val_to_str_const(addr_family, afn_vals, ""));
+ return -1;
+ }
+
proto_tree_add_ipv4(port_tree, hf_port_id_ip4, tvb, (offset+4), 4, ip_addr);
+
break;
case AFNUM_INET6:
+ if (tempLen == 18){
+ tvb_get_ipv6(tvb, (offset+4), &ip6_addr);
+ strPtr = ip6_to_str(&ip6_addr);
+ }else{
+ expert_add_info_format(pinfo, lf, &ei_lldp_bad_length,
+ "Invalid Port ID Length (%u) for Type (%s, %s), expected (18)", tempLen, val_to_str_const(tempType, port_id_subtypes, ""), val_to_str_const(addr_family, afn_vals, ""));
+ return -1;
+ }
+
proto_tree_add_ipv6(port_tree, hf_port_id_ip6, tvb, (offset+4), 16, ip6_addr.bytes);
+
break;
default:
+ strPtr = tvb_bytes_to_ep_str(tvb, (offset+4), (tempLen-2));
proto_tree_add_item(port_tree, hf_port_id, tvb, (offset+4), (tempLen-2), ENC_ASCII|ENC_NA);
+
break;
}
+
break;
+ case 1: /* Interface alias */
+ case 2: /* Port Component */
+ case 5: /* Interface name */
+ case 6: /* Agent circuit ID */
+ case 7: /* Locally assigned */
default:
+ if (tempLen > 256)
+ {
+ expert_add_info_format(pinfo, lf, &ei_lldp_bad_length_excess,
+ "Invalid Port ID Length (%u) for Type (%s), expected < (256)", tempLen, val_to_str_const(tempType, port_id_subtypes, ""));
+ return -1;
+ }
+
+ switch (tempType)
+ {
+ case 2: /* Port component */
+ strPtr = tvb_bytes_to_ep_str(tvb, (offset+3), (tempLen-1));
+ break;
+ case 1: /* Interface alias */
+ case 5: /* Interface name */
+ case 6: /* Agent circuit ID */
+ case 7: /* Locally assigned */
+ strPtr = tvb_format_stringzpad(tvb, (offset+3), (tempLen-1));
+ break;
+ default:
+ strPtr = "Reserved";
+ break;
+ }
+
proto_tree_add_item(port_tree, hf_port_id, tvb, (offset+3), (tempLen-1), ENC_ASCII|ENC_NA);
break;
}
+ proto_item_append_text(tf, ", Id: %s", strPtr);
+
return (tempLen + 2);
}