* Routines for OSPF packet disassembly
* (c) Copyright Hannes R. Boehm <hannes@boehm.org>
*
- * $Id: packet-ospf.c,v 1.43 2001/09/05 19:53:41 guy Exp $
+ * $Id: packet-ospf.c,v 1.59 2002/04/14 23:04:03 guy Exp $
*
* At this time, this module is able to analyze OSPF
* packets as specified in RFC2328. MOSPF (RFC1584) and other
#include <string.h>
#include <glib.h>
-#include "packet.h"
+#include <epan/packet.h>
#include "ipproto.h"
#include "in_cksum.h"
#include "ieee-float.h"
+#include "packet-rsvp.h"
#define OSPF_VERSION_2 2
#define OSPF_VERSION_3 3
#define OSPF_V2_OPTIONS_EA 0x10
#define OSPF_V2_OPTIONS_DC 0x20
#define OSPF_V2_OPTIONS_O 0x40
-#define OSPF_V2_OPTIONS_DN 0x01
+#define OSPF_V2_OPTIONS_DN 0x01
#define OSPF_V3_OPTIONS_V6 0x01
#define OSPF_V3_OPTIONS_E 0x02
#define OSPF_V3_OPTIONS_MC 0x04
static gint ett_ospf_lsa_mpls_link = -1;
static gint ett_ospf_lsa_mpls_link_stlv = -1;
+static dissector_handle_t data_handle;
+
static void dissect_ospf_hello(tvbuff_t*, int, proto_tree*, guint8);
static void dissect_ospf_db_desc(tvbuff_t*, int, proto_tree*, guint8);
static void dissect_ospf_ls_req(tvbuff_t*, int, proto_tree*, guint8);
guint8 version;
guint8 packet_type;
guint16 ospflen;
- vec_t cksum_vec[2];
+ vec_t cksum_vec[4];
int cksum_vec_len;
+ guint32 phdr[2];
guint16 cksum, computed_cksum;
guint length, reported_length;
guint16 auth_type;
unsigned int ospf_header_length;
guint8 instance_ID;
guint8 reserved;
+ guint32 areaid;
+
- if (check_col(pinfo->fd, COL_PROTOCOL))
- col_set_str(pinfo->fd, COL_PROTOCOL, "OSPF");
- if (check_col(pinfo->fd, COL_INFO))
- col_clear(pinfo->fd, COL_INFO);
+ if (check_col(pinfo->cinfo, COL_PROTOCOL))
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "OSPF");
+ if (check_col(pinfo->cinfo, COL_INFO))
+ col_clear(pinfo->cinfo, COL_INFO);
version = tvb_get_guint8(tvb, 0);
switch (version) {
}
packet_type = tvb_get_guint8(tvb, 1);
- if (check_col(pinfo->fd, COL_INFO)) {
- col_add_str(pinfo->fd, COL_INFO,
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
val_to_str(packet_type, pt_vals, "Unknown (%u)"));
}
ospflen);
proto_tree_add_text(ospf_header_tree, tvb, 4, 4, "Source OSPF Router ID: %s",
ip_to_str(tvb_get_ptr(tvb, 4, 4)));
- if (tvb_get_ntohl(tvb, 8) == 0) {
- proto_tree_add_text(ospf_header_tree, tvb, 8, 4, "Area ID: Backbone");
- } else {
- proto_tree_add_text(ospf_header_tree, tvb, 8, 4, "Area ID: %s",
- ip_to_str(tvb_get_ptr(tvb, 8, 4)));
- }
+ areaid=tvb_get_ntohl(tvb,8);
+ proto_tree_add_text(ospf_header_tree, tvb, 8, 4, "Area ID: %s%s",
+ ip_to_str(tvb_get_ptr(tvb, 8, 4)), areaid == 0 ? " (Backbone)" : "");
cksum = tvb_get_ntohs(tvb, 12);
length = tvb_length(tvb);
/* XXX - include only the length from the OSPF header? */
reported_length = tvb_reported_length(tvb);
- if (!pinfo->fragmented && length >= reported_length
- && length >= ospf_header_length) {
+ if (cksum == 0) {
+ /* No checksum supplied in the packet. */
+ proto_tree_add_text(ospf_header_tree, tvb, 12, 2,
+ "Packet Checksum: 0x%04x (none)", cksum);
+ } else if (!pinfo->fragmented && length >= reported_length
+ && length >= ospf_header_length
+ && (version == OSPF_VERSION_2 || version == OSPF_VERSION_3)) {
/* The packet isn't part of a fragmented datagram and isn't
- truncated, so we can checksum it. */
-
- /* Header, not including the authentication data (the OSPF
- checksum excludes the 64-bit authentication field (which is an OSPFv2-only field)). */
- cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, 16);
- cksum_vec[0].len = 16;
- if (length > ospf_header_length) {
- /* Rest of the packet, again not including the
- authentication data. */
- reported_length -= ospf_header_length;
- cksum_vec[1].ptr = tvb_get_ptr(tvb, ospf_header_length, reported_length);
- cksum_vec[1].len = reported_length;
- cksum_vec_len = 2;
- } else {
- /* There's nothing but a header. */
- cksum_vec_len = 1;
+ truncated, and we know how to checksum this version of
+ OSPF, so we can checksum it. */
+
+ switch (version) {
+
+ case OSPF_VERSION_2:
+ /* Header, not including the authentication data (the OSPFv2
+ checksum excludes the 64-bit authentication field). */
+ cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, 16);
+ cksum_vec[0].len = 16;
+ if (length > ospf_header_length) {
+ /* Rest of the packet, again not including the
+ authentication data. */
+ reported_length -= ospf_header_length;
+ cksum_vec[1].ptr = tvb_get_ptr(tvb, ospf_header_length, reported_length);
+ cksum_vec[1].len = reported_length;
+ cksum_vec_len = 2;
+ } else {
+ /* There's nothing but a header. */
+ cksum_vec_len = 1;
+ }
+ break;
+
+ case OSPF_VERSION_3:
+ /* IPv6-style checksum, covering the entire OSPF packet
+ and a prepended IPv6 pseudo-header. */
+
+ /* Set up the fields of the pseudo-header. */
+ cksum_vec[0].ptr = pinfo->src.data;
+ cksum_vec[0].len = pinfo->src.len;
+ cksum_vec[1].ptr = pinfo->dst.data;
+ cksum_vec[1].len = pinfo->dst.len;
+ cksum_vec[2].ptr = (const guint8 *)&phdr;
+ phdr[0] = htonl(ospflen);
+ phdr[1] = htonl(IP_PROTO_OSPF);
+ cksum_vec[2].len = 8;
+
+ cksum_vec[3].ptr = tvb_get_ptr(tvb, 0, reported_length);
+ cksum_vec[3].len = reported_length;
+ cksum_vec_len = 4;
+ break;
+
+ default:
+ g_assert_not_reached();
+ cksum_vec_len = 0;
}
computed_cksum = in_cksum(cksum_vec, cksum_vec_len);
if (computed_cksum == 0) {
break;
default:
- dissect_data(tvb, ospf_header_length, pinfo, tree);
+ call_dissector(data_handle,tvb_new_subset(tvb, ospf_header_length,-1,tvb_reported_length_remaining(tvb,ospf_header_length)), pinfo, tree);
break;
}
}
proto_tree *ospf_hello_tree;
proto_item *ti;
- ti = proto_tree_add_text(tree, tvb, offset,
- tvb_length_remaining(tvb, offset),
- "OSPF Hello Packet");
+ ti = proto_tree_add_text(tree, tvb, offset, -1, "OSPF Hello Packet");
ospf_hello_tree = proto_item_add_subtree(ti, ett_ospf_hello);
switch (version ) {
char flags_string[20] = "";
if (tree) {
- ti = proto_tree_add_text(tree, tvb, offset,
- tvb_length_remaining(tvb, offset),
- "OSPF DB Description");
+ ti = proto_tree_add_text(tree, tvb, offset, -1, "OSPF DB Description");
ospf_db_desc_tree = proto_item_add_subtree(ti, ett_ospf_desc);
switch (version ) {
tvb_get_ntohl(tvb, offset + 4));
offset += 8;
+ break;
case OSPF_VERSION_3:
- reserved = tvb_get_guint8(tvb, 16);
+ reserved = tvb_get_guint8(tvb, offset);
proto_tree_add_text(ospf_db_desc_tree, tvb, offset, 1, (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),
reserved);
proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 4, 2, "Interface MTU: %u",
tvb_get_ntohs(tvb, offset+4));
- reserved = tvb_get_guint8(tvb, 22);
+ reserved = tvb_get_guint8(tvb, offset + 6);
proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 6, 1, (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),
reserved);
tvb_get_ntohl(tvb, offset + 8));
offset += 12;
+ break;
- break;
-
-
- default:
- break;
- }
-
-
+ default:
+ break;
+ }
}
/* LS Headers will be processed here */
guint32 lsa_nr;
guint32 lsa_counter;
- ti = proto_tree_add_text(tree, tvb, offset,
- tvb_length_remaining(tvb, offset),
- "LS Update Packet");
+ ti = proto_tree_add_text(tree, tvb, offset, -1, "LS Update Packet");
ospf_lsa_upd_tree = proto_item_add_subtree(ti, ett_ospf_lsa_upd);
lsa_nr = tvb_get_ntohl(tvb, offset);
MPLS_LINK_MAX_RES_BW,
MPLS_LINK_UNRES_BW,
MPLS_LINK_COLOR,
+ MPLS_LINK_LOCAL_ID = 11,
+ MPLS_LINK_REMOTE_ID,
+ MPLS_LINK_PROTECTION = 14,
+ MPLS_LINK_IF_SWITCHING_DESC,
+ MPLS_LINK_SHARED_RISK_GROUP,
};
static const value_string mpls_link_stlv_str[] = {
{MPLS_LINK_MAX_RES_BW, "Maximum Reservable Bandwidth"},
{MPLS_LINK_UNRES_BW, "Unreserved Bandwidth"},
{MPLS_LINK_COLOR, "Resource Class/Color"},
+ {MPLS_LINK_LOCAL_ID, "Link Local Identifier"},
+ {MPLS_LINK_REMOTE_ID, "Link Remote Identifier"},
+ {MPLS_LINK_PROTECTION, "Link Protection Type"},
+ {MPLS_LINK_IF_SWITCHING_DESC, "Interface Switching Capability Descriptor"},
+ {MPLS_LINK_SHARED_RISK_GROUP, "Shared Risk Link Group"},
{0, NULL},
};
stlv_len);
for (i = 0; i < 8; i++) {
proto_tree_add_text(stlv_tree, tvb, stlv_offset+4+(i*4), 4,
- "Pri %d: %ld", i,
- tvb_ieee_to_long(tvb, stlv_offset + 4 + i*4));
+ "Pri %d: %ld bytes/s (%.0f bits/s)", i,
+ tvb_ieee_to_long(tvb, stlv_offset + 4 + i*4),
+ tvb_ieee_to_long(tvb, stlv_offset + 4 + i*4) * 8.0);
+ }
+ break;
+
+ case MPLS_LINK_LOCAL_ID:
+ case MPLS_LINK_REMOTE_ID:
+ ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
+ "%s: %d (0x%x)", stlv_name,
+ tvb_get_ntohl(tvb, stlv_offset + 4),
+ tvb_get_ntohl(tvb, stlv_offset + 4));
+ stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
+ "TLV Type: %u: %s", stlv_type, stlv_name);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
+ stlv_len);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 4, "%s: %d (0x%x)", stlv_name,
+ tvb_get_ntohl(tvb, stlv_offset + 4),
+ tvb_get_ntohl(tvb, stlv_offset + 4));
+ break;
+
+ case MPLS_LINK_IF_SWITCHING_DESC:
+ ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4,
+ "%s", stlv_name);
+ stlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link_stlv);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset, 2,
+ "TLV Type: %u: %s", stlv_type, stlv_name);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+2, 2, "TLV Length: %u",
+ stlv_len);
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+4, 1, "Switching Type: %s",
+ val_to_str(tvb_get_guint8(tvb,stlv_offset+4),
+ gmpls_switching_type_str, "Unknown (%d)"));
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+5, 1, "Encoding: %s",
+ val_to_str(tvb_get_guint8(tvb,stlv_offset+5),
+ gmpls_lsp_enc_str, "Unknown (%d)"));
+ for (i = 0; i < 8; i++) {
+ proto_tree_add_text(stlv_tree, tvb, stlv_offset+8+(i*4), 4,
+ "Pri %d: %ld bytes/s (%.0f bits/s)", i,
+ tvb_ieee_to_long(tvb, stlv_offset + 8 + i*4),
+ tvb_ieee_to_long(tvb, stlv_offset + 8 + i*4) * 8.0);
}
break;
/*
* Dissect opaque LSAs
*/
-void
+static void
dissect_ospf_lsa_opaque(tvbuff_t *tvb, int offset, proto_tree *tree,
guint8 ls_id_type, guint32 length)
{
guint16 ls_type;
guint16 ls_length;
int end_offset;
- guint8 nr_links;
- guint16 nr_tos;
guint8 reserved;
/* router LSA */
guint8 link_type;
- guint16 link_counter;
- guint8 tos_counter;
char *link_type_str;
guint32 metric;
guint8 router_lsa_flags;
char router_lsa_flags_string[5];
- /* AS-external LSA */
- guint8 options;
-
- /* opaque LSA */
- guint8 ls_id_type;
-
guint8 router_priority;
guint32 number_prefixes;
guint8 prefix_length;
guint16 reserved16;
guint16 referenced_ls_type;
- char *referenced_ls_type_str;
guint8 flags;
guint8 flags_string[4];
proto_tree_add_text(ospf_lsa_tree, tvb, offset + 2, 2, "LSA Type: 0x%04x (%s)",
ls_type, val_to_str(ls_type, v3_ls_type_vals,"Unkown"));
- ls_id_type = 0;
proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Link State ID: %s",
ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)));
proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 4, "Advertising Router: %s",
ip_to_str(tvb_get_ptr(tvb, offset + 8, 4)));
- proto_tree_add_text(ospf_lsa_tree, tvb, offset + 12, 4, "LS Sequence Number: 0x%04x",
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset + 12, 4, "LS Sequence Number: %d",
tvb_get_ntohl(tvb, offset + 12));
proto_tree_add_text(ospf_lsa_tree, tvb, offset + 16, 2, "LS Checksum: %04x",
tvb_get_ntohs(tvb, offset + 16));
offset+=8;
/* address_prefix */
- dissect_ospf_v3_address_prefix(tvb, offset+8, prefix_length, ospf_lsa_tree);
+ dissect_ospf_v3_address_prefix(tvb, offset, prefix_length, ospf_lsa_tree);
offset+=(prefix_length+31)/32*4;
proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 4, "Destination Router ID: %s",
ip_to_str(tvb_get_ptr(tvb, offset + 8, 4)));
- offset+=12 ;
+ offset+=12;
break;
else
flags_string[2] = '.';
- router_lsa_flags_string[3]=0;
+ flags_string[3]=0;
proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "Flags: 0x%02x (%s)",
flags, flags_string);
/* 24 bits metric */
- metric=tvb_get_ntohs(tvb, offset+1);
+ metric=tvb_get_ntoh24(tvb, offset+1);
proto_tree_add_text(ospf_lsa_tree, tvb, offset+1, 3,
"Metric: %u", metric);
/* referenced LS type */
referenced_ls_type=tvb_get_ntohs(tvb, offset+6);
- proto_tree_add_text(ospf_lsa_tree, tvb, offset+2, 2,"Referenced LS type 0x%04x (%s)",
- referenced_ls_type, val_to_str(referenced_ls_type, ls_type_vals, "Unknown"));
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset+6, 2,"Referenced LS type 0x%04x (%s)",
+ referenced_ls_type, val_to_str(referenced_ls_type, v3_ls_type_vals, "Unknown"));
offset+=8;
offset+=(prefix_length+31)/32*4;
/* Forwarding Address (optional - only if F-flag is on) */
- if ( (offset < end_offset) && (flags == OSPF_V3_AS_EXTERNAL_FLAG_F) ) {
+ if ( (offset < end_offset) && (flags & OSPF_V3_AS_EXTERNAL_FLAG_F) ) {
proto_tree_add_text(ospf_lsa_tree, tvb, offset, 16,"Forwarding Address: %s",
ip6_to_str((struct e_in6_addr *)tvb_get_ptr(tvb, offset, 16)));
}
/* External Route Tag (optional - only if T-flag is on) */
- if ( (offset < end_offset) && (flags == OSPF_V3_AS_EXTERNAL_FLAG_T) ) {
+ if ( (offset < end_offset) && (flags & OSPF_V3_AS_EXTERNAL_FLAG_T) ) {
external_route_tag=tvb_get_ntohl(tvb, offset);
proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4,"External Route Tag: 0x%04x",
external_route_tag);
/* referenced LS type */
referenced_ls_type=tvb_get_ntohs(tvb, offset+2);
- proto_tree_add_text(ospf_lsa_tree, tvb, offset+2, 2,"Referenced LS type 0x%04x (%s)",
- referenced_ls_type, val_to_str(referenced_ls_type, ls_type_vals, "Unknown"));
+ proto_tree_add_text(ospf_lsa_tree, tvb, offset+2, 2,"Referenced LS type 0x%04x (%s)",
+ referenced_ls_type, val_to_str(referenced_ls_type, v3_ls_type_vals, "Unknown"));
/* Referenced Link State ID */
proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Referenced Link State ID: %s",
void
proto_reg_handoff_ospf(void)
{
- dissector_add("ip.proto", IP_PROTO_OSPF, dissect_ospf, proto_ospf);
+ dissector_handle_t ospf_handle;
+
+ ospf_handle = create_dissector_handle(dissect_ospf, proto_ospf);
+ dissector_add("ip.proto", IP_PROTO_OSPF, ospf_handle);
+ data_handle = find_dissector("data");
}