diff options
Diffstat (limited to 'packet-ospf.c')
-rw-r--r-- | packet-ospf.c | 2145 |
1 files changed, 0 insertions, 2145 deletions
diff --git a/packet-ospf.c b/packet-ospf.c deleted file mode 100644 index 02ac9e64fd..0000000000 --- a/packet-ospf.c +++ /dev/null @@ -1,2145 +0,0 @@ -/* packet-ospf.c - * Routines for OSPF packet disassembly - * (c) Copyright Hannes R. Boehm <hannes@boehm.org> - * - * $Id$ - * - * At this time, this module is able to analyze OSPF - * packets as specified in RFC2328. MOSPF (RFC1584) and other - * OSPF Extensions which introduce new Packet types - * (e.g the External Atributes LSA) are not supported. - * Furthermore RFC2740 (OSPFv3 - OSPF for IPv6) is now supported - * - (c) 2001 Palle Lyckegaard <palle[AT]lyckegaard.dk> - * - * TOS - support is not fully implemented - * - * Ethereal - Network traffic analyzer - * By Gerald Combs <gerald@ethereal.com> - * Copyright 1998 Gerald Combs - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <stdio.h> -#include <string.h> - -#include <glib.h> -#include <epan/packet.h> -#include "ipproto.h" -#include "in_cksum.h" -#include "packet-rsvp.h" - -#define OSPF_VERSION_2 2 -#define OSPF_VERSION_3 3 -#define OSPF_VERSION_2_HEADER_LENGTH 24 -#define OSPF_VERSION_3_HEADER_LENGTH 16 - - -#define OSPF_HELLO 1 -#define OSPF_DB_DESC 2 -#define OSPF_LS_REQ 3 -#define OSPF_LS_UPD 4 -#define OSPF_LS_ACK 5 - -static const value_string pt_vals[] = { - {OSPF_HELLO, "Hello Packet" }, - {OSPF_DB_DESC, "DB Descr." }, - {OSPF_LS_REQ, "LS Request" }, - {OSPF_LS_UPD, "LS Update" }, - {OSPF_LS_ACK, "LS Acknowledge" }, - {0, NULL } -}; - -#define OSPF_AUTH_NONE 0 -#define OSPF_AUTH_SIMPLE 1 -#define OSPF_AUTH_CRYPT 2 - -static const value_string auth_vals[] = { - {OSPF_AUTH_NONE, "Null" }, - {OSPF_AUTH_SIMPLE, "Simple password" }, - {OSPF_AUTH_CRYPT, "Cryptographic" }, - {0, NULL } -}; - -#define OSPF_V2_OPTIONS_DN 0x01 -#define OSPF_V2_OPTIONS_E 0x02 -#define OSPF_V2_OPTIONS_MC 0x04 -#define OSPF_V2_OPTIONS_NP 0x08 -#define OSPF_V2_OPTIONS_EA 0x10 -#define OSPF_V2_OPTIONS_DC 0x20 -#define OSPF_V2_OPTIONS_O 0x40 -#define OSPF_V3_OPTIONS_V6 0x01 -#define OSPF_V3_OPTIONS_E 0x02 -#define OSPF_V3_OPTIONS_MC 0x04 -#define OSPF_V3_OPTIONS_N 0x08 -#define OSPF_V3_OPTIONS_R 0x10 -#define OSPF_V3_OPTIONS_DC 0x20 - - -#define OSPF_DBD_FLAG_MS 1 -#define OSPF_DBD_FLAG_M 2 -#define OSPF_DBD_FLAG_I 4 - -#define OSPF_LS_REQ_LENGTH 12 - -#define OSPF_LSTYPE_ROUTER 1 -#define OSPF_LSTYPE_NETWORK 2 -#define OSPF_LSTYPE_SUMMERY 3 -#define OSPF_LSTYPE_ASBR 4 -#define OSPF_LSTYPE_ASEXT 5 -#define OSPF_LSTYPE_GRPMEMBER 6 -#define OSPF_LSTYPE_ASEXT7 7 -#define OSPF_LSTYPE_EXTATTR 8 -#define OSPF_V3_LSTYPE_ROUTER 0x2001 -#define OSPF_V3_LSTYPE_NETWORK 0x2002 -#define OSPF_V3_LSTYPE_INTER_AREA_PREFIX 0x2003 -#define OSPF_V3_LSTYPE_INTER_AREA_ROUTER 0x2004 -#define OSPF_V3_LSTYPE_AS_EXTERNAL 0x4005 -#define OSPF_V3_LSTYPE_GROUP_MEMBERSHIP 0x2006 -#define OSPF_V3_LSTYPE_TYPE_7 0x2007 -#define OSPF_V3_LSTYPE_LINK 0x0008 -#define OSPF_V3_LSTYPE_INTRA_AREA_PREFIX 0x2009 - -/* Opaque LSA types */ -#define OSPF_LSTYPE_OP_LINKLOCAL 9 -#define OSPF_LSTYPE_OP_AREALOCAL 10 -#define OSPF_LSTYPE_OP_ASWIDE 11 - -#define OSPF_LINK_PTP 1 -#define OSPF_LINK_TRANSIT 2 -#define OSPF_LINK_STUB 3 -#define OSPF_LINK_VIRTUAL 4 - -#define OSPF_V3_LINK_PTP 1 -#define OSPF_V3_LINK_TRANSIT 2 -#define OSPF_V3_LINK_RESERVED 3 -#define OSPF_V3_LINK_VIRTUAL 4 - -#define OSPF_LSA_HEADER_LENGTH 20 - -/* Known opaque LSAs */ -#define OSPF_LSA_MPLS_TE 1 - - -static const value_string ls_type_vals[] = { - {OSPF_LSTYPE_ROUTER, "Router-LSA" }, - {OSPF_LSTYPE_NETWORK, "Network-LSA" }, - {OSPF_LSTYPE_SUMMERY, "Summary-LSA (IP network)" }, - {OSPF_LSTYPE_ASBR, "Summary-LSA (ASBR)" }, - {OSPF_LSTYPE_ASEXT, "AS-External-LSA (ASBR)" }, - {OSPF_LSTYPE_GRPMEMBER, "Group Membership LSA" }, - {OSPF_LSTYPE_ASEXT7, "NSSA AS-External-LSA" }, - {OSPF_LSTYPE_EXTATTR, "External Attributes LSA" }, - {OSPF_LSTYPE_OP_LINKLOCAL, "Opaque LSA, Link-local scope" }, - {OSPF_LSTYPE_OP_AREALOCAL, "Opaque LSA, Area-local scope" }, - {0, NULL } - -}; - -static const value_string ls_opaque_type_vals[] = { - {OSPF_LSA_MPLS_TE, "Traffic Engineering LSA" }, - {2, "Sycamore Optical Topology Descriptions" }, - {3, "grace-LSA" }, - {0, NULL } -}; - -static const value_string v3_ls_type_vals[] = { - {OSPF_V3_LSTYPE_ROUTER, "Router-LSA" }, - {OSPF_V3_LSTYPE_NETWORK, "Network-LSA" }, - {OSPF_V3_LSTYPE_INTER_AREA_PREFIX, "Inter-Area-Prefix-LSA" }, - {OSPF_V3_LSTYPE_INTER_AREA_ROUTER, "Inter-Area-Router-LSA" }, - {OSPF_V3_LSTYPE_AS_EXTERNAL, "AS-External-LSA" }, - {OSPF_V3_LSTYPE_GROUP_MEMBERSHIP, "Group-Membership-LSA" }, - {OSPF_V3_LSTYPE_TYPE_7, "Type-LSA" }, - {OSPF_V3_LSTYPE_LINK, "Link-LSA" }, - {OSPF_V3_LSTYPE_INTRA_AREA_PREFIX, "Intra-Area-Prefix-LSA" }, - {0, NULL } - -}; - - -#define OSPF_V3_ROUTER_LSA_FLAG_B 0x01 -#define OSPF_V3_ROUTER_LSA_FLAG_E 0x02 -#define OSPF_V3_ROUTER_LSA_FLAG_V 0x04 -#define OSPF_V3_ROUTER_LSA_FLAG_W 0x08 - -#define OSPF_V3_PREFIX_OPTION_NU 0x01 -#define OSPF_V3_PREFIX_OPTION_LA 0x02 -#define OSPF_V3_PREFIX_OPTION_MC 0x04 -#define OSPF_V3_PREFIX_OPTION_P 0x08 - -#define OSPF_V3_AS_EXTERNAL_FLAG_T 0x01 -#define OSPF_V3_AS_EXTERNAL_FLAG_F 0x02 -#define OSPF_V3_AS_EXTERNAL_FLAG_E 0x04 - - -static int proto_ospf = -1; - -static gint ett_ospf = -1; -static gint ett_ospf_hdr = -1; -static gint ett_ospf_hello = -1; -static gint ett_ospf_desc = -1; -static gint ett_ospf_lsr = -1; -static gint ett_ospf_lsa = -1; -static gint ett_ospf_lsa_router_link = -1; -static gint ett_ospf_lsa_upd = -1; - -/* Trees for opaque LSAs */ -static gint ett_ospf_lsa_mpls = -1; -static gint ett_ospf_lsa_mpls_router = -1; -static gint ett_ospf_lsa_mpls_link = -1; -static gint ett_ospf_lsa_mpls_link_stlv = -1; - -/*----------------------------------------------------------------------- - * OSPF Filtering - *-----------------------------------------------------------------------*/ - -/* The OSPF filtering keys */ -enum { - - OSPFF_MSG_TYPE, - - OSPFF_MSG_MIN, - OSPFF_MSG_HELLO, - OSPFF_MSG_DB_DESC, - OSPFF_MSG_LS_REQ, - OSPFF_MSG_LS_UPD, - OSPFF_MSG_LS_ACK, - - OSPFF_LS_TYPE, - OSPFF_LS_OPAQUE_TYPE, - - OSPFF_LS_MPLS_TE_INSTANCE, - - OSPFF_LS_MIN, - OSPFF_LS_ROUTER, - OSPFF_LS_NETWORK, - OSPFF_LS_SUMMARY, - OSPFF_LS_ASBR, - OSPFF_LS_ASEXT, - OSPFF_LS_GRPMEMBER, - OSPFF_LS_ASEXT7, - OSPFF_LS_EXTATTR, - OSPFF_LS_OPAQUE, - - OSPFF_SRC_ROUTER, - OSPFF_ADV_ROUTER, - OSPFF_LS_MPLS, - OSPFF_LS_MPLS_ROUTERID, - - OSPFF_LS_MPLS_LINKID, - OSPFF_LS_MPLS_LOCAL_ADDR, - OSPFF_LS_MPLS_REMOTE_ADDR, - OSPFF_LS_MPLS_LOCAL_IFID, - OSPFF_LS_MPLS_REMOTE_IFID, - - OSPFF_MAX -}; - -static int ospf_filter[OSPFF_MAX]; - -static hf_register_info ospff_info[] = { - - /* Message type number */ - {&ospf_filter[OSPFF_MSG_TYPE], - { "Message Type", "ospf.msg", FT_UINT8, BASE_DEC, VALS(pt_vals), 0x0, - "", HFILL }}, - - /* Message types */ - {&ospf_filter[OSPFF_MSG_HELLO], - { "Hello", "ospf.msg.hello", FT_BOOLEAN, BASE_NONE, NULL, 0x0, - "", HFILL }}, - {&ospf_filter[OSPFF_MSG_DB_DESC], - { "Database Description", "ospf.msg.dbdesc", FT_BOOLEAN, BASE_NONE, NULL, 0x0, - "", HFILL }}, - {&ospf_filter[OSPFF_MSG_LS_REQ], - { "Link State Adv Request", "ospf.msg.lsreq", FT_BOOLEAN, BASE_NONE, NULL, 0x0, - "", HFILL }}, - {&ospf_filter[OSPFF_MSG_LS_UPD], - { "Link State Adv Update", "ospf.msg.lsupdate", FT_BOOLEAN, BASE_NONE, NULL, 0x0, - "", HFILL }}, - {&ospf_filter[OSPFF_MSG_LS_ACK], - { "Link State Adv Acknowledgement", "ospf.msg.lsack", FT_BOOLEAN, - BASE_NONE, NULL, 0x0, "", HFILL }}, - - - - /* LS Types */ - {&ospf_filter[OSPFF_LS_TYPE], - { "Link-State Advertisement Type", "ospf.lsa", FT_UINT8, BASE_DEC, - VALS(ls_type_vals), 0x0, "", HFILL }}, - {&ospf_filter[OSPFF_LS_OPAQUE_TYPE], - { "Link State ID Opaque Type", "ospf.lsid_opaque_type", FT_UINT8, BASE_DEC, - VALS(ls_opaque_type_vals), 0x0, "", HFILL }}, - - {&ospf_filter[OSPFF_LS_MPLS_TE_INSTANCE], - { "Link State ID TE-LSA Instance", "ospf.lsid_te_lsa.instance", FT_UINT16, BASE_DEC, - NULL, 0x0, "", HFILL }}, - - {&ospf_filter[OSPFF_LS_ROUTER], - { "Router LSA", "ospf.lsa.router", FT_BOOLEAN, BASE_NONE, NULL, 0x0, - "", HFILL }}, - {&ospf_filter[OSPFF_LS_NETWORK], - { "Network LSA", "ospf.lsa.network", FT_BOOLEAN, BASE_NONE, NULL, 0x0, - "", HFILL }}, - {&ospf_filter[OSPFF_LS_SUMMARY], - { "Summary LSA (IP Network)", "ospf.lsa.summary", FT_BOOLEAN, BASE_NONE, - NULL, 0x0, "", HFILL }}, - {&ospf_filter[OSPFF_LS_ASBR], - { "Summary LSA (ASBR)", "ospf.lsa.asbr", FT_BOOLEAN, BASE_NONE, NULL, 0x0, - "", HFILL }}, - {&ospf_filter[OSPFF_LS_ASEXT], - { "AS-External LSA (ASBR)", "ospf.lsa.asext", FT_BOOLEAN, BASE_NONE, NULL, 0x0, - "", HFILL }}, - {&ospf_filter[OSPFF_LS_GRPMEMBER], - { "Group Membership LSA", "ospf.lsa.member", FT_BOOLEAN, BASE_NONE, NULL, 0x0, - "", HFILL }}, - {&ospf_filter[OSPFF_LS_ASEXT7], - { "NSSA AS-External LSA", "ospf.lsa.nssa", FT_BOOLEAN, BASE_NONE, NULL, 0x0, - "", HFILL }}, - {&ospf_filter[OSPFF_LS_EXTATTR], - { "External Attributes LSA", "ospf.lsa.attr", FT_BOOLEAN, BASE_NONE, NULL, 0x0, - "", HFILL }}, - {&ospf_filter[OSPFF_LS_OPAQUE], - { "Opaque LSA", "ospf.lsa.opaque", FT_BOOLEAN, BASE_NONE, NULL, 0x0, - "", HFILL }}, - - /* Other interesting OSPF values */ - - {&ospf_filter[OSPFF_SRC_ROUTER], - { "Source OSPF Router", "ospf.srcrouter", FT_IPv4, BASE_NONE, NULL, 0x0, - "", HFILL }}, - - {&ospf_filter[OSPFF_ADV_ROUTER], - { "Advertising Router", "ospf.advrouter", FT_IPv4, BASE_NONE, NULL, 0x0, - "", HFILL }}, - - {&ospf_filter[OSPFF_LS_MPLS], - { "MPLS Traffic Engineering LSA", "ospf.lsa.mpls", FT_BOOLEAN, - BASE_NONE, NULL, 0x0, "", HFILL }}, - - {&ospf_filter[OSPFF_LS_MPLS_ROUTERID], - { "MPLS/TE Router ID", "ospf.mpls.routerid", FT_IPv4, BASE_NONE, NULL, 0x0, - "", HFILL }}, - - {&ospf_filter[OSPFF_LS_MPLS_LINKID], - { "MPLS/TE Link ID", "ospf.mpls.linkid", FT_IPv4, BASE_NONE, NULL, 0x0, - "", HFILL }}, - {&ospf_filter[OSPFF_LS_MPLS_LOCAL_ADDR], - { "MPLS/TE Local Interface Address", "ospf.mpls.local_addr", FT_IPv4, - BASE_NONE, NULL, 0x0, "", HFILL }}, - {&ospf_filter[OSPFF_LS_MPLS_REMOTE_ADDR], - { "MPLS/TE Remote Interface Address", "ospf.mpls.remote_addr", FT_IPv4, - BASE_NONE, NULL, 0x0, "", HFILL }}, - {&ospf_filter[OSPFF_LS_MPLS_LOCAL_IFID], - { "MPLS/TE Local Interface Index", "ospf.mpls.local_id", FT_UINT32, - BASE_DEC, NULL, 0x0, "", HFILL }}, - {&ospf_filter[OSPFF_LS_MPLS_REMOTE_IFID], - { "MPLS/TE Remote Interface Index", "ospf.mpls.remote_id", FT_UINT32, - BASE_DEC, NULL, 0x0, "", HFILL }}, - - - -}; - -static guint8 ospf_msg_type_to_filter (guint8 msg_type) -{ - if (msg_type >= OSPF_HELLO && - msg_type <= OSPF_LS_ACK) - return msg_type + OSPFF_MSG_MIN; - return -1; -} - -static guint8 ospf_ls_type_to_filter (guint8 ls_type) -{ - if (ls_type >= OSPF_LSTYPE_ROUTER && - ls_type <= OSPF_LSTYPE_EXTATTR) - return OSPFF_LS_MIN + ls_type; - else if (ls_type >= OSPF_LSTYPE_OP_LINKLOCAL && - ls_type <= OSPF_LSTYPE_OP_ASWIDE) - return OSPFF_LS_OPAQUE; - else - return -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); -static void dissect_ospf_ls_upd(tvbuff_t*, int, proto_tree*, guint8); -static void dissect_ospf_ls_ack(tvbuff_t*, int, proto_tree*, guint8); - -/* dissect_ospf_v[23]lsa returns the offset of the next LSA - * if disassemble_body is set to FALSE (e.g. in LSA ACK - * packets), the offset is set to the offset of the next - * LSA header - */ -static int dissect_ospf_v2_lsa(tvbuff_t*, int, proto_tree*, gboolean disassemble_body); -static int dissect_ospf_v3_lsa(tvbuff_t*, int, proto_tree*, gboolean disassemble_body); - -static void dissect_ospf_options(tvbuff_t *, int, proto_tree *, guint8); - -static void dissect_ospf_v3_prefix_options(tvbuff_t *, int, proto_tree *); - -static void dissect_ospf_v3_address_prefix(tvbuff_t *, int, int, proto_tree *); - -static void -dissect_ospf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) -{ - proto_tree *ospf_tree = NULL; - proto_item *ti; - proto_tree *ospf_header_tree; - guint8 version; - guint8 packet_type; - guint16 ospflen; - vec_t cksum_vec[4]; - int cksum_vec_len; - guint32 phdr[2]; - guint16 cksum, computed_cksum; - guint length, reported_length; - guint16 auth_type; - char auth_data[8+1]; - int crypto_len; - unsigned int ospf_header_length; - guint8 instance_ID; - guint8 reserved; - guint32 areaid; - - - 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) { - case OSPF_VERSION_2: - ospf_header_length = OSPF_VERSION_2_HEADER_LENGTH; - break; - case OSPF_VERSION_3: - ospf_header_length = OSPF_VERSION_3_HEADER_LENGTH; - break; - default: - ospf_header_length = 0; - break; - } - - packet_type = tvb_get_guint8(tvb, 1); - if (check_col(pinfo->cinfo, COL_INFO)) { - col_add_str(pinfo->cinfo, COL_INFO, - val_to_str(packet_type, pt_vals, "Unknown (%u)")); - } - - if (tree) { - ospflen = tvb_get_ntohs(tvb, 2); - - ti = proto_tree_add_item(tree, proto_ospf, tvb, 0, ospflen, FALSE); - ospf_tree = proto_item_add_subtree(ti, ett_ospf); - - ti = proto_tree_add_text(ospf_tree, tvb, 0, ospf_header_length, - "OSPF Header"); - ospf_header_tree = proto_item_add_subtree(ti, ett_ospf_hdr); - - proto_tree_add_text(ospf_header_tree, tvb, 0, 1, "OSPF Version: %u", - version); - proto_tree_add_item(ospf_header_tree, ospf_filter[OSPFF_MSG_TYPE], - tvb, 1, 1, FALSE); - proto_tree_add_item_hidden(ospf_header_tree, - ospf_filter[ospf_msg_type_to_filter(packet_type)], - tvb, 1, 1, FALSE); - proto_tree_add_text(ospf_header_tree, tvb, 2, 2, "Packet Length: %u", - ospflen); - proto_tree_add_item(ospf_header_tree, ospf_filter[OSPFF_SRC_ROUTER], - tvb, 4, 4, FALSE); - 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 (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, 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] = g_htonl(ospflen); - phdr[1] = g_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) { - proto_tree_add_text(ospf_header_tree, tvb, 12, 2, - "Packet Checksum: 0x%04x (correct)", cksum); - } else { - proto_tree_add_text(ospf_header_tree, tvb, 12, 2, - "Packet Checksum: 0x%04x (incorrect, should be 0x%04x)", - cksum, in_cksum_shouldbe(cksum, computed_cksum)); - } - } else { - proto_tree_add_text(ospf_header_tree, tvb, 12, 2, - "Packet Checksum: 0x%04x", cksum); - } - - - /* Authentication is only valid for OSPFv2 */ - if ( version == OSPF_VERSION_2 ) { - auth_type = tvb_get_ntohs(tvb, 14); - proto_tree_add_text(ospf_header_tree, tvb, 14, 2, "Auth Type: %s", - val_to_str(auth_type, auth_vals, "Unknown (%u)")); - switch (auth_type) { - - case OSPF_AUTH_NONE: - proto_tree_add_text(ospf_header_tree, tvb, 16, 8, "Auth Data (none)"); - break; - - case OSPF_AUTH_SIMPLE: - tvb_get_nstringz0(tvb, 16, 8+1, auth_data); - proto_tree_add_text(ospf_header_tree, tvb, 16, 8, "Auth Data: %s", auth_data); - break; - - case OSPF_AUTH_CRYPT: - proto_tree_add_text(ospf_header_tree, tvb, 18, 1, "Auth Key ID: %u", - tvb_get_guint8(tvb, 18)); - crypto_len = tvb_get_guint8(tvb, 19); - proto_tree_add_text(ospf_header_tree, tvb, 19, 1, "Auth Data Length: %u", - crypto_len); - proto_tree_add_text(ospf_header_tree, tvb, 20, 4, "Auth Crypto Sequence Number: 0x%x", - tvb_get_ntohl(tvb, 20)); - - /* Show the message digest that was appended to the end of the - OSPF message - but only if it's present (we don't want - to get an exception before we've tried dissecting OSPF - message). */ - if (tvb_bytes_exist(tvb, ospflen, crypto_len)) { - proto_tree_add_text(ospf_header_tree, tvb, ospflen, crypto_len, - "Auth Data: %s", - tvb_bytes_to_str(tvb, ospflen, crypto_len)); - } - break; - - default: - proto_tree_add_text(ospf_header_tree, tvb, 16, 8, "Auth Data (unknown)"); - break; - } - - } - - /* Instance ID and "reserved" is OSPFv3-only */ - if ( version == OSPF_VERSION_3 ) { - instance_ID = tvb_get_guint8(tvb, 14); - proto_tree_add_text(ospf_header_tree, tvb, 14, 1, "Instance ID: %u", - instance_ID); - reserved = tvb_get_guint8(tvb, 15); - proto_tree_add_text(ospf_header_tree, tvb, 15, 1, (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"), - reserved); - - } - - /* Adjust the length of the tvbuff to match the size of the OSPF - * packet (since the dissect routines use it to work out where the - * end of the OSPF packet is). - */ - tvb_set_reported_length(tvb, ospflen); - - switch (packet_type){ - - case OSPF_HELLO: - dissect_ospf_hello(tvb, ospf_header_length, ospf_tree, version); - break; - - case OSPF_DB_DESC: - dissect_ospf_db_desc(tvb, ospf_header_length, ospf_tree, version); - break; - - case OSPF_LS_REQ: - dissect_ospf_ls_req(tvb, ospf_header_length, ospf_tree, version); - break; - - case OSPF_LS_UPD: - dissect_ospf_ls_upd(tvb, ospf_header_length, ospf_tree, version); - break; - - case OSPF_LS_ACK: - dissect_ospf_ls_ack(tvb, ospf_header_length, ospf_tree, version); - break; - - default: - call_dissector(data_handle, - tvb_new_subset(tvb, ospf_header_length, -1, -1), pinfo, tree); - break; - } - } -} - -static void -dissect_ospf_hello(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version) -{ - proto_tree *ospf_hello_tree; - proto_item *ti; - - 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 ) { - case OSPF_VERSION_2: - proto_tree_add_text(ospf_hello_tree, tvb, offset, 4, "Network Mask: %s", - ip_to_str(tvb_get_ptr(tvb, offset, 4))); - proto_tree_add_text(ospf_hello_tree, tvb, offset + 4, 2, - "Hello Interval: %u seconds", - tvb_get_ntohs(tvb, offset + 4)); - - dissect_ospf_options(tvb, offset + 6, ospf_hello_tree, version); - proto_tree_add_text(ospf_hello_tree, tvb, offset + 7, 1, "Router Priority: %u", - tvb_get_guint8(tvb, offset + 7)); - proto_tree_add_text(ospf_hello_tree, tvb, offset + 8, 4, "Router Dead Interval: %u seconds", - tvb_get_ntohl(tvb, offset + 8)); - proto_tree_add_text(ospf_hello_tree, tvb, offset + 12, 4, "Designated Router: %s", - ip_to_str(tvb_get_ptr(tvb, offset + 12, 4))); - proto_tree_add_text(ospf_hello_tree, tvb, offset + 16, 4, "Backup Designated Router: %s", - ip_to_str(tvb_get_ptr(tvb, offset + 16, 4))); - - offset += 20; - while (tvb_reported_length_remaining(tvb, offset) != 0) { - proto_tree_add_text(ospf_hello_tree, tvb, offset, 4, - "Active Neighbor: %s", - ip_to_str(tvb_get_ptr(tvb, offset, 4))); - offset += 4; - } - break; - case OSPF_VERSION_3: - proto_tree_add_text(ospf_hello_tree, tvb, offset + 0, 4, "Interface ID: %u", - tvb_get_ntohl(tvb, offset + 0)); - proto_tree_add_text(ospf_hello_tree, tvb, offset + 4, 1, "Router Priority: %u", - tvb_get_guint8(tvb, offset + 4)); - dissect_ospf_options(tvb, offset + 5, ospf_hello_tree, version); - proto_tree_add_text(ospf_hello_tree, tvb, offset + 8, 2, - "Hello Interval: %u seconds", - tvb_get_ntohs(tvb, offset + 8)); - proto_tree_add_text(ospf_hello_tree, tvb, offset + 10, 2, "Router Dead Interval: %u seconds", - tvb_get_ntohs(tvb, offset + 10)); - proto_tree_add_text(ospf_hello_tree, tvb, offset + 12, 4, "Designated Router: %s", - ip_to_str(tvb_get_ptr(tvb, offset + 12, 4))); - proto_tree_add_text(ospf_hello_tree, tvb, offset + 16, 4, "Backup Designated Router: %s", - ip_to_str(tvb_get_ptr(tvb, offset + 16, 4))); - offset += 20; - while (tvb_reported_length_remaining(tvb, offset) != 0) { - proto_tree_add_text(ospf_hello_tree, tvb, offset, 4, - "Active Neighbor: %s", - ip_to_str(tvb_get_ptr(tvb, offset, 4))); - offset += 4; - } - - break; - - default: - break; - } -} - -static void -dissect_ospf_db_desc(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version) -{ - proto_tree *ospf_db_desc_tree=NULL; - proto_item *ti; - guint8 flags; - guint8 reserved; - char flags_string[20] = ""; - - if (tree) { - 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 ) { - - case OSPF_VERSION_2: - - proto_tree_add_text(ospf_db_desc_tree, tvb, offset, 2, "Interface MTU: %u", - tvb_get_ntohs(tvb, offset)); - - dissect_ospf_options(tvb, offset + 2, ospf_db_desc_tree, version); - - flags = tvb_get_guint8(tvb, offset + 3); - if (flags & OSPF_DBD_FLAG_MS) - strcat(flags_string, "MS"); - if (flags & OSPF_DBD_FLAG_M) { - if (flags_string[0] != '\0') - strcat(flags_string, "/"); - strcat(flags_string, "M"); - } - if (flags & OSPF_DBD_FLAG_I) { - if (flags_string[0] != '\0') - strcat(flags_string, "/"); - strcat(flags_string, "I"); - } - proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 3, 1, "Flags: 0x%x (%s)", - flags, flags_string); - proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 4, 4, "DD Sequence: %u", - tvb_get_ntohl(tvb, offset + 4)); - - offset += 8; - break; - - case OSPF_VERSION_3: - - 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); - - dissect_ospf_options(tvb, offset + 1, ospf_db_desc_tree, version); - - 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, 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); - - flags = tvb_get_guint8(tvb, offset + 7); - if (flags & OSPF_DBD_FLAG_MS) - strcat(flags_string, "MS"); - if (flags & OSPF_DBD_FLAG_M) { - if (flags_string[0] != '\0') - strcat(flags_string, "/"); - strcat(flags_string, "M"); - } - if (flags & OSPF_DBD_FLAG_I) { - if (flags_string[0] != '\0') - strcat(flags_string, "/"); - strcat(flags_string, "I"); - } - proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 7, 1, "Flags: 0x%x (%s)", - flags, flags_string); - - proto_tree_add_text(ospf_db_desc_tree, tvb, offset + 8, 4, "DD Sequence: %u", - tvb_get_ntohl(tvb, offset + 8)); - - offset += 12; - break; - - default: - break; - } - } - - /* LS Headers will be processed here */ - /* skip to the end of DB-Desc header */ - while (tvb_reported_length_remaining(tvb, offset) != 0) { - if ( version == OSPF_VERSION_2) - offset = dissect_ospf_v2_lsa(tvb, offset, tree, FALSE); - else - if ( version == OSPF_VERSION_3) - offset = dissect_ospf_v3_lsa(tvb, offset, tree, FALSE); - } - -} - -static void -dissect_ospf_ls_req(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version) -{ - proto_tree *ospf_lsr_tree; - proto_item *ti; - guint32 ls_type; - guint16 reserved; - - /* zero or more LS requests may be within a LS Request */ - /* we place every request for a LSA in a single subtree */ - while (tvb_reported_length_remaining(tvb, offset) != 0) { - ti = proto_tree_add_text(tree, tvb, offset, OSPF_LS_REQ_LENGTH, - "Link State Request"); - ospf_lsr_tree = proto_item_add_subtree(ti, ett_ospf_lsr); - - switch ( version ) { - - case OSPF_VERSION_2: - ls_type = tvb_get_ntohl(tvb, offset); - proto_tree_add_item(ospf_lsr_tree, ospf_filter[OSPFF_LS_TYPE], - tvb, offset, 4, FALSE); - break; - case OSPF_VERSION_3: - reserved = tvb_get_ntohs(tvb, offset); - proto_tree_add_text(ospf_lsr_tree, tvb, offset, 2, - (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"), reserved); - ls_type = tvb_get_ntohs(tvb, offset+2); - proto_tree_add_text(ospf_lsr_tree, tvb, offset+2, 2, "LS Type: %s (0x%04x)", - val_to_str(ls_type, v3_ls_type_vals, "Unknown"), - ls_type); - break; - default: - ls_type=0; - break; - } - - - proto_tree_add_text(ospf_lsr_tree, tvb, offset + 4, 4, "Link State ID: %s", - ip_to_str(tvb_get_ptr(tvb, offset + 4, 4))); - proto_tree_add_item(ospf_lsr_tree, ospf_filter[OSPFF_ADV_ROUTER], - tvb, offset + 8, 4, FALSE); - - offset += 12; - } -} - -static void -dissect_ospf_ls_upd(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version) -{ - proto_tree *ospf_lsa_upd_tree=NULL; - proto_item *ti; - guint32 lsa_nr; - guint32 lsa_counter; - - 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); - proto_tree_add_text(ospf_lsa_upd_tree, tvb, offset, 4, "Number of LSAs: %u", - lsa_nr); - /* skip to the beginning of the first LSA */ - offset += 4; /* the LS Upd Packet contains only a 32 bit #LSAs field */ - - lsa_counter = 0; - while (lsa_counter < lsa_nr) { - if ( version == OSPF_VERSION_2) - offset = dissect_ospf_v2_lsa(tvb, offset, ospf_lsa_upd_tree, TRUE); - else - if ( version == OSPF_VERSION_3) - offset = dissect_ospf_v3_lsa(tvb, offset, ospf_lsa_upd_tree, TRUE); - lsa_counter += 1; - } -} - -static void -dissect_ospf_ls_ack(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version) -{ - /* the body of a LS Ack packet simply contains zero or more LSA Headers */ - while (tvb_reported_length_remaining(tvb, offset) != 0) { - if ( version == OSPF_VERSION_2) - offset = dissect_ospf_v2_lsa(tvb, offset, tree, FALSE); - else - if ( version == OSPF_VERSION_3) - offset = dissect_ospf_v3_lsa(tvb, offset, tree, FALSE); - } -} - -/* - * Returns if an LSA is opaque, i.e. requires special treatment - */ -static int -is_opaque(int lsa_type) -{ - return (lsa_type >= OSPF_LSTYPE_OP_LINKLOCAL && - lsa_type <= OSPF_LSTYPE_OP_ASWIDE); -} - -/* MPLS/TE TLV types */ -#define MPLS_TLV_ROUTER 1 -#define MPLS_TLV_LINK 2 - -/* MPLS/TE Link STLV types */ -enum { - MPLS_LINK_TYPE = 1, - MPLS_LINK_ID, - MPLS_LINK_LOCAL_IF, - MPLS_LINK_REMOTE_IF, - MPLS_LINK_TE_METRIC, - MPLS_LINK_MAX_BW, - 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_TYPE, "Link Type"}, - {MPLS_LINK_ID, "Link ID"}, - {MPLS_LINK_LOCAL_IF, "Local Interface IP Address"}, - {MPLS_LINK_REMOTE_IF, "Remote Interface IP Address"}, - {MPLS_LINK_TE_METRIC, "Traffic Engineering Metric"}, - {MPLS_LINK_MAX_BW, "Maximum Bandwidth"}, - {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}, -}; - -/* - * Dissect MPLS/TE opaque LSA - */ -static void -dissect_ospf_lsa_mpls(tvbuff_t *tvb, int offset, proto_tree *tree, - guint32 length) -{ - proto_item *ti; - proto_tree *mpls_tree; - proto_tree *tlv_tree; - proto_tree *stlv_tree; - - int tlv_type; - int tlv_length; - int tlv_end_offset; - - int stlv_type, stlv_len, stlv_offset; - char *stlv_name; - int i; - - ti = proto_tree_add_text(tree, tvb, offset, length, - "MPLS Traffic Engineering LSA"); - proto_tree_add_item_hidden(tree, ospf_filter[OSPFF_LS_MPLS], - tvb, offset, 2, FALSE); - mpls_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls); - - while (length != 0) { - tlv_type = tvb_get_ntohs(tvb, offset); - tlv_length = tvb_get_ntohs(tvb, offset + 2); - tlv_end_offset = offset + tlv_length + 4; - - switch (tlv_type) { - - case MPLS_TLV_ROUTER: - ti = proto_tree_add_text(mpls_tree, tvb, offset, tlv_length+4, - "Router Address: %s", - ip_to_str(tvb_get_ptr(tvb, offset+4, 4))); - tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_router); - proto_tree_add_text(tlv_tree, tvb, offset, 2, "TLV Type: 1 - Router Address"); - proto_tree_add_text(tlv_tree, tvb, offset+2, 2, "TLV Length: %u", - tlv_length); - proto_tree_add_item(tlv_tree, ospf_filter[OSPFF_LS_MPLS_ROUTERID], - tvb, offset+4, 4, FALSE); - break; - - case MPLS_TLV_LINK: - ti = proto_tree_add_text(mpls_tree, tvb, offset, tlv_length+4, - "Link Information"); - tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link); - proto_tree_add_text(tlv_tree, tvb, offset, 2, "TLV Type: 2 - Link Information"); - proto_tree_add_text(tlv_tree, tvb, offset+2, 2, "TLV Length: %u", - tlv_length); - stlv_offset = offset + 4; - - /* Walk down the sub-TLVs for link information */ - while (stlv_offset < tlv_end_offset) { - stlv_type = tvb_get_ntohs(tvb, stlv_offset); - stlv_len = tvb_get_ntohs(tvb, stlv_offset + 2); - stlv_name = val_to_str(stlv_type, mpls_link_stlv_str, "Unknown sub-TLV"); - switch (stlv_type) { - - case MPLS_LINK_TYPE: - ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4, - "%s: %u", stlv_name, - tvb_get_guint8(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, 1, "%s: %u", stlv_name, - tvb_get_guint8(tvb, stlv_offset + 4)); - break; - - case MPLS_LINK_ID: - ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4, - "%s: %s (%x)", stlv_name, - ip_to_str(tvb_get_ptr(tvb, stlv_offset + 4, 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_item(stlv_tree, ospf_filter[OSPFF_LS_MPLS_LINKID], - tvb, stlv_offset+4, 4, FALSE); - break; - - case MPLS_LINK_LOCAL_IF: - case MPLS_LINK_REMOTE_IF: - 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); - /* The Local/Remote Interface IP Address sub-TLV is TLV type 3/4, and is 4N - octets in length, where N is the number of neighbor addresses. */ - for (i=0; i < stlv_len; i+=4) - proto_tree_add_item(stlv_tree, - stlv_type==MPLS_LINK_LOCAL_IF ? - ospf_filter[OSPFF_LS_MPLS_LOCAL_ADDR] : - ospf_filter[OSPFF_LS_MPLS_REMOTE_ADDR], - tvb, stlv_offset+4+i, 4, FALSE); - break; - - case MPLS_LINK_TE_METRIC: - case MPLS_LINK_COLOR: - ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4, - "%s: %u", stlv_name, - 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: %u", stlv_name, - tvb_get_ntohl(tvb, stlv_offset + 4)); - break; - - case MPLS_LINK_MAX_BW: - case MPLS_LINK_MAX_RES_BW: - ti = proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4, - "%s: %.10g", stlv_name, - tvb_get_ntohieee_float(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: %.10g", stlv_name, - tvb_get_ntohieee_float(tvb, stlv_offset + 4)); - break; - - case MPLS_LINK_UNRES_BW: - 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); - for (i = 0; i < 8; i++) { - proto_tree_add_text(stlv_tree, tvb, stlv_offset+4+(i*4), 4, - "Pri %d: %.10g bytes/s (%.0f bits/s)", i, - tvb_get_ntohieee_float(tvb, stlv_offset + 4 + i*4), - tvb_get_ntohieee_float(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, - "Link Local/Remote Identifier"); - 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, "Local ID: %s", - ip_to_str(tvb_get_ptr(tvb, stlv_offset + 4, 4))); - proto_tree_add_text(stlv_tree, tvb, stlv_offset+8, 4, "Remote ID: %s", - ip_to_str(tvb_get_ptr(tvb, stlv_offset + 8, 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: %.10g bytes/s (%.0f bits/s)", i, - tvb_get_ntohieee_float(tvb, stlv_offset + 8 + i*4), - tvb_get_ntohieee_float(tvb, stlv_offset + 8 + i*4) * 8.0); - } - break; - case MPLS_LINK_PROTECTION: - 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, "Protection Capability: %s (0x%x)", - val_to_str(tvb_get_guint8(tvb,stlv_offset+4), gmpls_protection_cap_str, "Unknown (%d)"),tvb_get_guint8(tvb,stlv_offset+4)); - break; - - case MPLS_LINK_SHARED_RISK_GROUP: - 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); - for (i=0; i < stlv_len; i+=4) - proto_tree_add_text(stlv_tree, tvb, stlv_offset+4+i, 4, "Shared Risk Link Group: %u", - tvb_get_ntohl(tvb,stlv_offset+4+i)); - break; - - default: - proto_tree_add_text(tlv_tree, tvb, stlv_offset, stlv_len+4, - "Unknown Link sub-TLV: %u", stlv_type); - break; - } - stlv_offset += ((stlv_len+4+3)/4)*4; - } - break; - - default: - ti = proto_tree_add_text(mpls_tree, tvb, offset, tlv_length+4, - "Unknown LSA: %u", tlv_type); - tlv_tree = proto_item_add_subtree(ti, ett_ospf_lsa_mpls_link); - proto_tree_add_text(tlv_tree, tvb, offset, 2, "TLV Type: %u - Unknown", - tlv_type); - proto_tree_add_text(tlv_tree, tvb, offset+2, 2, "TLV Length: %u", - tlv_length); - proto_tree_add_text(tlv_tree, tvb, offset+4, tlv_length, "TLV Data"); - break; - } - - offset += tlv_length + 4; - length -= tlv_length + 4; - } -} - -/* - * Dissect opaque LSAs - */ -static void -dissect_ospf_lsa_opaque(tvbuff_t *tvb, int offset, proto_tree *tree, - guint8 ls_id_type, guint32 length) -{ - switch (ls_id_type) { - - case OSPF_LSA_MPLS_TE: - dissect_ospf_lsa_mpls(tvb, offset, tree, length); - break; - - default: - proto_tree_add_text(tree, tvb, offset, length, - "Unknown LSA Type %u", ls_id_type); - break; - } /* switch on opaque LSA id */ -} - -static int -dissect_ospf_v2_lsa(tvbuff_t *tvb, int offset, proto_tree *tree, - gboolean disassemble_body) -{ - proto_tree *ospf_lsa_tree; - proto_item *ti; - - guint8 ls_type; - guint16 ls_length; - int end_offset; - guint16 nr_links; - guint16 nr_tos; - - /* router LSA */ - guint8 link_type; - guint16 link_counter; - guint8 tos_counter; - char *link_type_str; - char *link_type_short_str; - char *link_id; - - /* AS-external LSA */ - guint8 options; - - /* opaque LSA */ - guint8 ls_id_type; - - ls_type = tvb_get_guint8(tvb, offset + 3); - ls_length = tvb_get_ntohs(tvb, offset + 18); - end_offset = offset + ls_length; - - if (disassemble_body) { - ti = proto_tree_add_text(tree, tvb, offset, ls_length, - "LS Type: %s", - val_to_str(ls_type, ls_type_vals, "Unknown (%d)")); - } else { - ti = proto_tree_add_text(tree, tvb, offset, OSPF_LSA_HEADER_LENGTH, - "LSA Header"); - } - ospf_lsa_tree = proto_item_add_subtree(ti, ett_ospf_lsa); - - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 2, "LS Age: %u seconds", - tvb_get_ntohs(tvb, offset)); - dissect_ospf_options(tvb, offset + 2, ospf_lsa_tree, OSPF_VERSION_2); - proto_tree_add_item(ospf_lsa_tree, ospf_filter[OSPFF_LS_TYPE], tvb, - offset + 3, 1, FALSE); - proto_tree_add_item_hidden(ospf_lsa_tree, - ospf_filter[ospf_ls_type_to_filter(ls_type)], tvb, - offset + 3, 1, FALSE); - - if (is_opaque(ls_type)) { - ls_id_type = tvb_get_guint8(tvb, offset + 4); - proto_tree_add_uint(ospf_lsa_tree, ospf_filter[OSPFF_LS_OPAQUE_TYPE], - tvb, offset + 4, 1, ls_id_type); - - switch (ls_id_type) { - - case OSPF_LSA_MPLS_TE: - proto_tree_add_text(ospf_lsa_tree, tvb, offset + 5, 1, "Link State ID TE-LSA Reserved: %u", - tvb_get_guint8(tvb, offset + 5)); - proto_tree_add_item(ospf_lsa_tree, ospf_filter[OSPFF_LS_MPLS_TE_INSTANCE], - tvb, offset + 6, 2, FALSE); - break; - - default: - proto_tree_add_text(ospf_lsa_tree, tvb, offset + 5, 3, "Link State ID Opaque ID: %u", - tvb_get_ntoh24(tvb, offset + 5)); - break; - } - } else { - 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_item(ospf_lsa_tree, ospf_filter[OSPFF_ADV_ROUTER], - tvb, offset + 8, 4, FALSE); - proto_tree_add_text(ospf_lsa_tree, tvb, offset + 12, 4, "LS Sequence Number: 0x%08x", - 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)); - - proto_tree_add_text(ospf_lsa_tree, tvb, offset + 18, 2, "Length: %u", - ls_length); - - /* skip past the LSA header to the body */ - offset += OSPF_LSA_HEADER_LENGTH; - if (ls_length <= OSPF_LSA_HEADER_LENGTH) - return offset; /* no data, or bogus length */ - ls_length -= OSPF_LSA_HEADER_LENGTH; - - if (!disassemble_body) - return offset; - - switch (ls_type){ - - case OSPF_LSTYPE_ROUTER: - /* again: flags should be secified in detail */ - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "Flags: 0x%02x", - tvb_get_guint8(tvb, offset)); - nr_links = tvb_get_ntohs(tvb, offset + 2); - proto_tree_add_text(ospf_lsa_tree, tvb, offset + 2, 2, "Number of Links: %u", - nr_links); - offset += 4; - /* nr_links links follow - * maybe we should put each of the links into its own subtree ??? - */ - for (link_counter = 1; link_counter <= nr_links; link_counter++) { - proto_tree *ospf_lsa_router_link_tree; - proto_item *ti_local; - - - /* check the Link Type and ID */ - link_type = tvb_get_guint8(tvb, offset + 8); - switch (link_type) { - - case OSPF_LINK_PTP: - link_type_str="Point-to-point connection to another router"; - link_type_short_str="PTP"; - link_id="Neighboring router's Router ID"; - break; - - case OSPF_LINK_TRANSIT: - link_type_str="Connection to a transit network"; - link_type_short_str="Transit"; - link_id="IP address of Designated Router"; - break; - - case OSPF_LINK_STUB: - link_type_str="Connection to a stub network"; - link_type_short_str="Stub"; - link_id="IP network/subnet number"; - break; - - case OSPF_LINK_VIRTUAL: - link_type_str="Virtual link"; - link_type_short_str="Virtual"; - link_id="Neighboring router's Router ID"; - break; - - default: - link_type_str="Unknown link type"; - link_type_short_str="Unknown"; - link_id="Unknown link ID"; - break; - } - - nr_tos = tvb_get_guint8(tvb, offset + 9); - - - ti_local = proto_tree_add_text(ospf_lsa_tree, tvb, offset, 12 + 4 * nr_tos, - "Type: %-8s ID: %-15s Data: %-15s Metric: %d", - link_type_short_str, - ip_to_str(tvb_get_ptr(tvb, offset, 4)), - ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)), - tvb_get_ntohs(tvb, offset + 10)); - - ospf_lsa_router_link_tree = proto_item_add_subtree(ti_local, ett_ospf_lsa_router_link); - - proto_tree_add_text(ospf_lsa_router_link_tree, tvb, offset, 4, "%s: %s", link_id, - ip_to_str(tvb_get_ptr(tvb, offset, 4))); - - /* link_data should be specified in detail (e.g. network mask) (depends on link type)*/ - proto_tree_add_text(ospf_lsa_router_link_tree, tvb, offset + 4, 4, "Link Data: %s", - ip_to_str(tvb_get_ptr(tvb, offset + 4, 4))); - - proto_tree_add_text(ospf_lsa_router_link_tree, tvb, offset + 8, 1, "Link Type: %u - %s", - link_type, link_type_str); - proto_tree_add_text(ospf_lsa_router_link_tree, tvb, offset + 9, 1, "Number of TOS metrics: %u", - nr_tos); - proto_tree_add_text(ospf_lsa_router_link_tree, tvb, offset + 10, 2, "TOS 0 metric: %u", - tvb_get_ntohs(tvb, offset + 10)); - - offset += 12; - - /* nr_tos metrics may follow each link - * ATTENTION: TOS metrics are not tested (I don't have TOS - * based routing) - * please send me a mail if it is/isn't working - */ - for (tos_counter = 1; tos_counter <= nr_tos; tos_counter++) { - proto_tree_add_text(ospf_lsa_router_link_tree, tvb, offset, 4, "TOS: %u, Metric: %u", - tvb_get_guint8(tvb, offset), - tvb_get_ntohs(tvb, offset + 2)); - offset += 4; - } - } - break; - - case OSPF_LSTYPE_NETWORK: - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Netmask: %s", - ip_to_str(tvb_get_ptr(tvb, offset, 4))); - offset += 4; - - while (offset < end_offset) { - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Attached Router: %s", - ip_to_str(tvb_get_ptr(tvb, offset, 4))); - offset += 4; - } - break; - - case OSPF_LSTYPE_SUMMERY: - /* Type 3 and 4 LSAs have the same format */ - case OSPF_LSTYPE_ASBR: - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Netmask: %s", - ip_to_str(tvb_get_ptr(tvb, offset, 4))); - offset += 4; - - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Metric: %u", - tvb_get_ntoh24(tvb, offset + 1)); - offset += 4; - - /* TOS-specific information, if any */ - while (offset < end_offset) { - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "TOS: %u, Metric: %u", - tvb_get_guint8(tvb, offset), - tvb_get_ntoh24(tvb, offset + 1)); - offset += 4; - } - break; - - case OSPF_LSTYPE_ASEXT: - case OSPF_LSTYPE_ASEXT7: - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Netmask: %s", - ip_to_str(tvb_get_ptr(tvb, offset, 4))); - offset += 4; - - options = tvb_get_guint8(tvb, offset); - if (options & 0x80) { /* check wether or not E bit is set */ - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, - "External Type: Type 2 (metric is larger than any other link state path)"); - } else { - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, - "External Type: Type 1 (metric is specified in the same units as interface cost)"); - } - /* the metric field of a AS-external LAS is specified in 3 bytes */ - proto_tree_add_text(ospf_lsa_tree, tvb, offset + 1, 3, "Metric: %u", - tvb_get_ntoh24(tvb, offset + 1)); - offset += 4; - - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Forwarding Address: %s", - ip_to_str(tvb_get_ptr(tvb, offset, 4))); - offset += 4; - - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "External Route Tag: %u", - tvb_get_ntohl(tvb, offset)); - offset += 4; - - /* TOS-specific information, if any */ - while (offset < end_offset) { - options = tvb_get_guint8(tvb, offset); - if (options & 0x80) { /* check wether or not E bit is set */ - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, - "External Type: Type 2 (metric is larger than any other link state path)"); - } else { - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, - "External Type: Type 1 (metric is specified in the same units as interface cost)"); - } - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "TOS: %u, Metric: %u", - options & 0x7F, - tvb_get_ntoh24(tvb, offset + 1)); - offset += 4; - - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Forwarding Address: %s", - ip_to_str(tvb_get_ptr(tvb, offset, 4))); - offset += 4; - - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "External Route Tag: %u", - tvb_get_ntohl(tvb, offset)); - offset += 4; - } - break; - - case OSPF_LSTYPE_OP_LINKLOCAL: - case OSPF_LSTYPE_OP_AREALOCAL: - case OSPF_LSTYPE_OP_ASWIDE: - /* - * RFC 2370 opaque LSAs. - */ - dissect_ospf_lsa_opaque(tvb, offset, ospf_lsa_tree, ls_id_type, - ls_length); - offset += ls_length; - break; - - default: - /* unknown LSA type */ - proto_tree_add_text(ospf_lsa_tree, tvb, offset, ls_length, - "Unknown LSA Type"); - offset += ls_length; - break; - } - /* return the offset of the next LSA */ - return offset; -} - -static int -dissect_ospf_v3_lsa(tvbuff_t *tvb, int offset, proto_tree *tree, - gboolean disassemble_body) -{ - proto_tree *ospf_lsa_tree; - proto_item *ti; - - guint16 ls_type; - guint16 ls_length; - int end_offset; - guint8 reserved; - - /* router LSA */ - guint8 link_type; - char *link_type_str; - guint32 metric; - - guint8 router_lsa_flags; - char router_lsa_flags_string[5]; - - guint8 router_priority; - guint32 number_prefixes; - guint8 prefix_length; - guint16 reserved16; - - guint16 referenced_ls_type; - - guint8 flags; - guint8 flags_string[4]; - guint32 external_route_tag; - - - ls_type = tvb_get_ntohs(tvb, offset + 2); - ls_length = tvb_get_ntohs(tvb, offset + 18); - end_offset = offset + ls_length; - - if (disassemble_body) { - ti = proto_tree_add_text(tree, tvb, offset, ls_length, - "%s (Type: 0x%04x)", val_to_str(ls_type, v3_ls_type_vals,"Unknown"), ls_type); - } else { - ti = proto_tree_add_text(tree, tvb, offset, OSPF_LSA_HEADER_LENGTH, - "LSA Header"); - } - ospf_lsa_tree = proto_item_add_subtree(ti, ett_ospf_lsa); - - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 2, "LS Age: %u seconds", - tvb_get_ntohs(tvb, offset)); - - 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")); - - 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_item(ospf_lsa_tree, ospf_filter[OSPFF_ADV_ROUTER], - tvb, offset + 8, 4, FALSE); - proto_tree_add_text(ospf_lsa_tree, tvb, offset + 12, 4, "LS Sequence Number: 0x%08x", - 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)); - - proto_tree_add_text(ospf_lsa_tree, tvb, offset + 18, 2, "Length: %u", - ls_length); - - /* skip past the LSA header to the body */ - offset += OSPF_LSA_HEADER_LENGTH; - ls_length -= OSPF_LSA_HEADER_LENGTH; - - if (!disassemble_body) - return offset; - - switch (ls_type){ - - - case OSPF_V3_LSTYPE_ROUTER: - - /* flags field in an router-lsa */ - router_lsa_flags=tvb_get_guint8(tvb,offset); - if (router_lsa_flags & OSPF_V3_ROUTER_LSA_FLAG_B) - router_lsa_flags_string[3] = 'B'; - else - router_lsa_flags_string[3] = '.'; - if (router_lsa_flags & OSPF_V3_ROUTER_LSA_FLAG_E) - router_lsa_flags_string[2] = 'E'; - else - router_lsa_flags_string[2] = '.'; - if (router_lsa_flags & OSPF_V3_ROUTER_LSA_FLAG_V) - router_lsa_flags_string[1] = 'V'; - else - router_lsa_flags_string[1] = '.'; - if (router_lsa_flags & OSPF_V3_ROUTER_LSA_FLAG_W) - router_lsa_flags_string[0] = 'W'; - else - router_lsa_flags_string[0] = '.'; - - router_lsa_flags_string[4]=0; - - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "Flags: 0x%02x (%s)", - router_lsa_flags, router_lsa_flags_string); - - /* options field in an router-lsa */ - dissect_ospf_options(tvb, offset + 1, ospf_lsa_tree, OSPF_VERSION_3); - - /* skip the router-lsa flags and options */ - offset+=4; - ls_length-=4; - - if (ls_length > 0) - proto_tree_add_text(ospf_lsa_tree, tvb, offset, ls_length, - "Router Interfaces:"); - - /* scan all router-lsa router interfaces */ - /* maybe we should put each of the links into its own subtree ??? */ - while (ls_length > 0 ) { - - /* check the type */ - link_type = tvb_get_guint8(tvb, offset); - switch (link_type) { - - case OSPF_V3_LINK_PTP: - link_type_str="Point-to-point connection to another router"; - break; - - case OSPF_V3_LINK_TRANSIT: - link_type_str="Connection to a transit network"; - break; - - case OSPF_V3_LINK_RESERVED: - link_type_str="Connection to a stub network"; - break; - - case OSPF_V3_LINK_VIRTUAL: - link_type_str="Virtual link"; - break; - - default: - link_type_str="Unknown link type"; - break; - } - - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "Type: %u (%s)", link_type,link_type_str); - - /* reserved field */ - reserved = tvb_get_guint8(tvb, offset+1); - proto_tree_add_text(ospf_lsa_tree, tvb, offset+1, 1, - (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved); - - /* metric */ - metric=tvb_get_ntohs(tvb, offset+2); - proto_tree_add_text(ospf_lsa_tree, tvb, offset + 2, 2,"Metric: %u",metric); - - /* Interface ID */ - proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 4, "Interface ID: %u", - tvb_get_ntohl(tvb, offset + 4)); - - /* Neighbor Interface ID */ - proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 4, "Neighbor Interface ID: %u", - tvb_get_ntohl(tvb, offset + 8)); - - /* Neighbor Router ID */ - proto_tree_add_text(ospf_lsa_tree, tvb, offset + 12, 4, "Neighbor Router ID: %s", - ip_to_str(tvb_get_ptr(tvb, offset + 12, 4))); - - /* skip to the (possible) next entry */ - offset+=16; - ls_length-=16; - - } - break; - - case OSPF_V3_LSTYPE_NETWORK: - - /* reserved field */ - reserved = tvb_get_guint8(tvb, offset); - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, - (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved); - - /* options field in an network-lsa */ - dissect_ospf_options(tvb, offset + 1, ospf_lsa_tree, OSPF_VERSION_3); - - offset += 4; - ls_length-=4; - - while (ls_length > 0 ) { - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Attached Router: %s", - ip_to_str(tvb_get_ptr(tvb, offset, 4))); - ls_length-=4; - offset += 4; - } - break; - - - case OSPF_V3_LSTYPE_INTER_AREA_PREFIX: - - /* reserved field */ - reserved = tvb_get_guint8(tvb, offset); - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, - (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved); - - /* metric */ - metric=tvb_get_ntoh24(tvb, offset+1); - proto_tree_add_text(ospf_lsa_tree, tvb, offset + 1, 3,"Metric: %u",metric); - - /* prefix length */ - prefix_length=tvb_get_guint8(tvb, offset+4); - proto_tree_add_text(ospf_lsa_tree, tvb, offset+4, 1, "PrefixLength: %u",prefix_length); - - /* prefix options */ - dissect_ospf_v3_prefix_options(tvb, offset+5, ospf_lsa_tree); - - /* 16 bits reserved */ - reserved16=tvb_get_ntohs(tvb, offset+6); - proto_tree_add_text(ospf_lsa_tree, tvb, offset+6, 2, - (reserved16 == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved16); - - offset+=8; - - /* address_prefix */ - dissect_ospf_v3_address_prefix(tvb, offset, prefix_length, ospf_lsa_tree); - - offset+=(prefix_length+31)/32*4; - - break; - - - case OSPF_V3_LSTYPE_INTER_AREA_ROUTER: - - /* reserved field */ - reserved = tvb_get_guint8(tvb, offset); - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, - (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved); - - /* options field in an inter-area-router-lsa */ - dissect_ospf_options(tvb, offset + 1, ospf_lsa_tree, OSPF_VERSION_3); - - /* reserved field */ - reserved = tvb_get_guint8(tvb, offset+4); - proto_tree_add_text(ospf_lsa_tree, tvb, offset+4, 1, - (reserved == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved); - - /* metric */ - metric=tvb_get_ntoh24(tvb, offset+5); - proto_tree_add_text(ospf_lsa_tree, tvb, offset + 5, 3,"Metric: %u",metric); - - /* Destination Router ID */ - 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; - break; - - - case OSPF_V3_LSTYPE_AS_EXTERNAL: - - /* flags */ - flags=tvb_get_guint8(tvb, offset); - if (flags & OSPF_V3_AS_EXTERNAL_FLAG_E) - flags_string[0] = 'E'; - else - flags_string[0] = '.'; - if (flags & OSPF_V3_AS_EXTERNAL_FLAG_F) - flags_string[1] = 'F'; - else - flags_string[1] = '.'; - if (flags & OSPF_V3_AS_EXTERNAL_FLAG_T) - flags_string[2] = 'T'; - else - flags_string[2] = '.'; - - 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_ntoh24(tvb, offset+1); - proto_tree_add_text(ospf_lsa_tree, tvb, offset+1, 3, - "Metric: %u", metric); - - /* prefix length */ - prefix_length=tvb_get_guint8(tvb, offset+4); - proto_tree_add_text(ospf_lsa_tree, tvb, offset+4, 1, "PrefixLength: %u",prefix_length); - - /* prefix options */ - dissect_ospf_v3_prefix_options(tvb, offset+5, ospf_lsa_tree); - - /* referenced LS type */ - referenced_ls_type=tvb_get_ntohs(tvb, offset+6); - 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; - - /* address_prefix */ - dissect_ospf_v3_address_prefix(tvb, offset, prefix_length, ospf_lsa_tree); - - 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) ) { - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 16,"Forwarding Address: %s", - ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset, 16))); - - offset+=16; - } - - /* External Route Tag (optional - only if T-flag is on) */ - 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: %u", - external_route_tag); - - offset+=4; - } - - /* Referenced Link State ID (optional - only if Referenced LS type is non-zero */ - if ( (offset < end_offset) && (referenced_ls_type != 0) ) { - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 4, "Referenced Link State ID: %s", - ip_to_str(tvb_get_ptr(tvb, offset, 4))); - offset+=4; - } - - break; - - case OSPF_V3_LSTYPE_LINK: - - /* router priority */ - router_priority=tvb_get_guint8(tvb, offset); - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "Router Priority: %u", router_priority); - - /* options field in an link-lsa */ - dissect_ospf_options(tvb, offset + 1, ospf_lsa_tree, OSPF_VERSION_3); - - /* Link-local Interface Address */ - proto_tree_add_text(ospf_lsa_tree, tvb, offset + 4, 16, "Link-local Interface Address: %s", - ip6_to_str((const struct e_in6_addr *)tvb_get_ptr(tvb, offset + 4, 16))); - - /* Number prefixes */ - number_prefixes=tvb_get_ntohl(tvb, offset + 20); - proto_tree_add_text(ospf_lsa_tree, tvb, offset+20, 4, "# prefixes: %d",number_prefixes); - - offset+=24; - - while (number_prefixes > 0) { - - /* prefix length */ - prefix_length=tvb_get_guint8(tvb, offset); - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "PrefixLength: %u",prefix_length); - - /* prefix options */ - dissect_ospf_v3_prefix_options(tvb, offset+1, ospf_lsa_tree); - - /* 16 bits reserved */ - reserved16=tvb_get_ntohs(tvb, offset+2); - proto_tree_add_text(ospf_lsa_tree, tvb, offset+2, 2, - (reserved16 == 0 ? "Reserved: %u" : "Reserved: %u (incorrect, should be 0)"),reserved16); - - offset+=4; - - /* address_prefix */ - dissect_ospf_v3_address_prefix(tvb, offset, prefix_length, ospf_lsa_tree); - - offset+=(prefix_length+31)/32*4; - - number_prefixes--; - - } - break; - - case OSPF_V3_LSTYPE_INTRA_AREA_PREFIX: - - /* # prefixes */ - number_prefixes=tvb_get_ntohs(tvb, offset); - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 2,"# prefixes: %u",number_prefixes); - - /* 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, 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", - ip_to_str(tvb_get_ptr(tvb, offset + 4, 4))); - - /* Referenced Advertising Router */ - proto_tree_add_text(ospf_lsa_tree, tvb, offset + 8, 4, "Referenced Advertising Router: %s", - ip_to_str(tvb_get_ptr(tvb, offset + 8, 4))); - - offset+=12; - - while (number_prefixes > 0) { - - /* prefix length */ - prefix_length=tvb_get_guint8(tvb, offset); - proto_tree_add_text(ospf_lsa_tree, tvb, offset, 1, "PrefixLength: %u",prefix_length); - - /* prefix options */ - dissect_ospf_v3_prefix_options(tvb, offset+1, ospf_lsa_tree); - - /* 16 bits metric */ - metric=tvb_get_ntohs(tvb, offset+2); - proto_tree_add_text(ospf_lsa_tree, tvb, offset+2, 2, - "Metric: %u", metric); - - offset+=4; - - /* address_prefix */ - dissect_ospf_v3_address_prefix(tvb, offset, prefix_length, ospf_lsa_tree); - - offset+=(prefix_length+31)/32*4; - - number_prefixes--; - } - break; - - default: - /* unknown LSA type */ - proto_tree_add_text(ospf_lsa_tree, tvb, offset, ls_length, - "Unknown LSA Type 0x%04x",ls_type); - offset += ls_length; - break; - } - /* return the offset of the next LSA */ - return offset; -} - - -static void -dissect_ospf_options(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 version) -{ - guint8 options_ospfv2; - guint32 options_ospfv3; - char options_string[20] = ""; - - /* ATTENTION !!! no check for length of options string - with OSPFv3 maximum length is 14 characters */ - - switch ( version ) { - - case OSPF_VERSION_2: - - options_ospfv2 = tvb_get_guint8(tvb, offset); - - if (options_ospfv2 & OSPF_V2_OPTIONS_E) - strcat(options_string, "E"); - - if (options_ospfv2 & OSPF_V2_OPTIONS_MC) { - if (options_string[0] != '\0') - strcat(options_string, "/"); - strcat(options_string, "MC"); - } - - if (options_ospfv2 & OSPF_V2_OPTIONS_NP) { - if (options_string[0] != '\0') - strcat(options_string, "/"); - strcat(options_string, "NP"); - } - - if (options_ospfv2 & OSPF_V2_OPTIONS_EA) { - if (options_string[0] != '\0') - strcat(options_string, "/"); - strcat(options_string, "EA"); - } - - if (options_ospfv2 & OSPF_V2_OPTIONS_DC) { - if (options_string[0] != '\0') - strcat(options_string, "/"); - strcat(options_string, "DC"); - } - - if (options_ospfv2 & OSPF_V2_OPTIONS_O) { - if (options_string[0] != '\0') - strcat(options_string, "/"); - strcat(options_string, "O"); - } - - if (options_ospfv2 & OSPF_V2_OPTIONS_DN) { - if (options_string[0] != '\0') - strcat(options_string, "/"); - strcat(options_string, "DN"); - } - - proto_tree_add_text(tree, tvb, offset, 1, "Options: 0x%x (%s)", - options_ospfv2, options_string); - break; - - - case OSPF_VERSION_3: - - options_ospfv3 = tvb_get_ntoh24(tvb, offset); - - if (options_ospfv3 & OSPF_V3_OPTIONS_V6) - strcat(options_string, "V6"); - - if (options_ospfv3 & OSPF_V3_OPTIONS_E) { - if (options_string[0] != '\0') - strcat(options_string, "/"); - strcat(options_string, "E"); - } - - if (options_ospfv3 & OSPF_V3_OPTIONS_MC) { - if (options_string[0] != '\0') - strcat(options_string, "/"); - strcat(options_string, "MC"); - } - - if (options_ospfv3 & OSPF_V3_OPTIONS_N) { - if (options_string[0] != '\0') - strcat(options_string, "/"); - strcat(options_string, "N"); - } - - if (options_ospfv3 & OSPF_V3_OPTIONS_R) { - if (options_string[0] != '\0') - strcat(options_string, "/"); - strcat(options_string, "R"); - } - - if (options_ospfv3 & OSPF_V3_OPTIONS_DC) { - if (options_string[0] != '\0') - strcat(options_string, "/"); - strcat(options_string, "DC"); - } - - proto_tree_add_text(tree, tvb, offset, 3, "Options: 0x%x (%s)", - options_ospfv3, options_string); - break; - - default: - break; - } - -} - - -static void dissect_ospf_v3_prefix_options(tvbuff_t *tvb, int offset, proto_tree *tree) -{ - - guint8 prefix_options; - char prefix_options_string[11]; - guint8 position; - - position=0; - - prefix_options=tvb_get_guint8(tvb, offset); - - strcpy(prefix_options_string,""); - - if (prefix_options & OSPF_V3_PREFIX_OPTION_P) { - strcat(prefix_options_string, "P"); - position++; - } - - if (prefix_options & OSPF_V3_PREFIX_OPTION_MC) { - if ( (position > 0) && (prefix_options_string[position-1] != '/') ) { - strcat(prefix_options_string, "/"); - position++; - } - strcat(prefix_options_string, "MC"); - position+=2; - } - - if (prefix_options & OSPF_V3_PREFIX_OPTION_LA) { - if ( (position > 0) && (prefix_options_string[position-1] != '/') ) { - strcat(prefix_options_string, "/"); - position++; - } - strcat(prefix_options_string, "LA"); - position+=2; - } - - if (prefix_options & OSPF_V3_PREFIX_OPTION_NU) { - if ( (position > 0) && (prefix_options_string[position-1] != '/') ) { - strcat(prefix_options_string, "/"); - position++; - } - strcat(prefix_options_string, "NU"); - } - - prefix_options_string[10]=0; - - proto_tree_add_text(tree, tvb, offset, 1, "PrefixOptions: 0x%02x (%s)",prefix_options, prefix_options_string); - -} - - -static void dissect_ospf_v3_address_prefix(tvbuff_t *tvb, int offset, int prefix_length, proto_tree *tree) -{ - - guint8 value; - guint8 position; - guint8 bufpos; - gchar buffer[32+7]; - gchar bytebuf[3]; - guint8 bytes_to_process; - int start_offset; - - start_offset=offset; - position=0; - bufpos=0; - bytes_to_process=((prefix_length+31)/32)*4; - - while (bytes_to_process > 0 ) { - - value=tvb_get_guint8(tvb, offset); - - if ( (position > 0) && ( (position%2) == 0 ) ) - buffer[bufpos++]=':'; - - sprintf(bytebuf,"%02x",value); - buffer[bufpos++]=bytebuf[0]; - buffer[bufpos++]=bytebuf[1]; - - position++; - offset++; - bytes_to_process--; - } - - buffer[bufpos]=0; - proto_tree_add_text(tree, tvb, start_offset, ((prefix_length+31)/32)*4, "Address Prefix: %s",buffer); - -} - - -void -proto_register_ospf(void) -{ - static gint *ett[] = { - &ett_ospf, - &ett_ospf_hdr, - &ett_ospf_hello, - &ett_ospf_desc, - &ett_ospf_lsr, - &ett_ospf_lsa, - &ett_ospf_lsa_router_link, - &ett_ospf_lsa_upd, - &ett_ospf_lsa_mpls, - &ett_ospf_lsa_mpls_router, - &ett_ospf_lsa_mpls_link, - &ett_ospf_lsa_mpls_link_stlv - }; - - proto_ospf = proto_register_protocol("Open Shortest Path First", - "OSPF", "ospf"); - proto_register_field_array(proto_ospf, ospff_info, array_length(ospff_info)); - proto_register_subtree_array(ett, array_length(ett)); -} - -void -proto_reg_handoff_ospf(void) -{ - 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"); -} |