diff options
author | Anders Broman <anders.broman@ericsson.com> | 2011-10-10 18:11:18 +0000 |
---|---|---|
committer | Anders Broman <anders.broman@ericsson.com> | 2011-10-10 18:11:18 +0000 |
commit | 29d57edb56a6181029512cbd8ec32dcfe36bd465 (patch) | |
tree | a8eb60a3a5a01686130c5e7912001e704bbe82bb /epan/dissectors/packet-eigrp.c | |
parent | b79dfbe40592a8ecab18bffe5f95bae56d2b0f31 (diff) |
From Donnie Savage:
Re-write of the EIGRP dissector to support Multi-Protocol (TLV 2.0) and
Multi-Topology (TLV 3.0). This version also support Service Advertisement
Framework(SAF) extensions to EIGRP
Dissector includes:
- Dissection of all EIGRP Opcodes and TLVs
- Decode of EIGRP Flags and bitfields
- Decode of EIGRP Communities
- Decode of latest EIGRP "wide metric" formats
- Decode of EIGRP Extended Metrics
- Decode of SAF packets with XML client data handed off to XML dissector
From me:
Fix checkapi errors/warnings use G_GINT64_CONSTANT and G_GINT64_MODIFIER
svn path=/trunk/; revision=39339
Diffstat (limited to 'epan/dissectors/packet-eigrp.c')
-rw-r--r-- | epan/dissectors/packet-eigrp.c | 4931 |
1 files changed, 3310 insertions, 1621 deletions
diff --git a/epan/dissectors/packet-eigrp.c b/epan/dissectors/packet-eigrp.c index 8f97ecfe62..37bffef55e 100644 --- a/epan/dissectors/packet-eigrp.c +++ b/epan/dissectors/packet-eigrp.c @@ -1,10 +1,10 @@ /* packet-eigrp.c - * Routines for EIGRP Stub Routing, Authentication and IPv6 TLV dissection - * - * Copyright 2009, Jochen Bartl <jochen.bartl@gmail.com> - * * Routines for EIGRP dissection - * Copyright 2000, Paul Ionescu <paul@acorp.ro> + * Copyright 2011, Donnie V Savage <dsavage@cisco.com> + * + * Complete re-write and replaces previous file of same name authored by: + * Copyright 2009, Jochen Bartl <jochen.bartl@gmail.co + * Copyright 2000, Paul Ionescu <paul@acorp.ro> * * $Id$ * @@ -26,119 +26,382 @@ * 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 <glib.h> #include <epan/packet.h> +#include <epan/prefs.h> +#include <epan/guid-utils.h> #include <epan/addr_resolv.h> - #include <epan/atalk-utils.h> #include <epan/addr_and_mask.h> #include <epan/ipproto.h> -#include "packet-ipx.h" +#include <epan/tfs.h> #include <epan/expert.h> +#include <epan/reassemble.h> + +#include "packet-ipx.h" +#include "packet-osi.h" + +/** + * EIGRP Header size in bytes + */ +#define EIGRP_HEADER_LENGTH 20 + +/** + * EIGRP Packet Opcodes + */ +#define EIGRP_OPC_UPDATE 1 /*!< packet containing routing information */ +#define EIGRP_OPC_REQUEST 2 /*!< sent to request one or more routes */ +#define EIGRP_OPC_QUERY 3 /*!< sent when a routing is in active start */ +#define EIGRP_OPC_REPLY 4 /*!< sent in response to a query */ +#define EIGRP_OPC_HELLO 5 /*!< sent to maintain a peering session */ +#define EIGRP_OPC_IPXSAP 6 /*!< IPX SAP information */ +#define EIGRP_OPC_PROBE 7 /*!< for test purposes */ +#define EIGRP_OPC_ACK 8 /*!< acknowledge */ +#define EIGRP_OPC_STUB 9 /*!< peering operating in restricted mode */ +#define EIGRP_OPC_SIAQUERY 10 /*!< QUERY - with relaxed restrictions */ +#define EIGRP_OPC_SIAREPLY 11 /*!< REPLY - may contain old routing information */ + +/** + * EIGRP TLV Range definitions + * PDM TLV Range + * General 0x0000 + * IPv4 0x0100 ** TLVs for one and all + * ATALK 0x0200 ** legacy + * IPX 0x0300 ** discontinued + * IPv6 0x0400 ** legacy + * Multiprotocol 0x0600 ** wide metrics + * MultiTopology 0x00f0 ** deprecated + */ +#define EIGRP_TLV_RANGEMASK 0xfff0 /*!< should be 0xff00 - opps */ +#define EIGRP_TLV_GENERAL 0x0000 + +/** + * 1.2 TLV Definitions ** legacy + * These have been deprecated and should not be used for future packets + */ +#define EIGRP_TLV_IPv4 0x0100 /*!< Classic IPv4 TLV encoding */ +#define EIGRP_TLV_ATALK 0x0200 /*!< Classic Appletalk TLV encoding*/ +#define EIGRP_TLV_IPX 0x0300 /*!< Classic IPX TLV encoding */ +#define EIGRP_TLV_IPv6 0x0400 /*!< Classic IPv6 TLV encoding */ + +/** + * 2.0 Multi-Protocol TLV Definitions + * These have been deprecated and should not be used for future packets + */ +#define EIGRP_TLV_MP 0x0600 /*!< Non-PDM specific encoding */ + +/** + * 3.0 TLV Definitions ** deprecated + * These have been deprecated and should not be used for future packets + */ +#define EIGRP_TLV_MTR 0x00f0 /*!< MTR TLV encoding */ + +/** + * TLV type definitions. Generic (protocol-independent) TLV types are + * defined here. Protocol-specific ones are defined elsewhere. + */ +#define EIGRP_TLV_PARAMETER (EIGRP_TLV_GENERAL | 0x0001) /*!< eigrp parameters */ +#define EIGRP_TLV_AUTH (EIGRP_TLV_GENERAL | 0x0002) /*!< authentication */ +#define EIGRP_TLV_SEQ (EIGRP_TLV_GENERAL | 0x0003) /*!< sequenced packet */ +#define EIGRP_TLV_SW_VERSION (EIGRP_TLV_GENERAL | 0x0004) /*!< software version */ +#define EIGRP_TLV_NEXT_MCAST_SEQ (EIGRP_TLV_GENERAL | 0x0005) /*!< */ +#define EIGRP_TLV_PEER_STUBINFO (EIGRP_TLV_GENERAL | 0x0006) /*!< stub information */ +#define EIGRP_TLV_PEER_TERMINATION (EIGRP_TLV_GENERAL | 0x0007) /*!< peer termination */ +#define EIGRP_TLV_PEER_TIDLIST (EIGRP_TLV_GENERAL | 0x0008) /*!< peer sub-topology list */ + +/** + * Route Based TLVs + */ +#define EIGRP_TLV_TYPEMASK 0x000f +#define EIGRP_TLV_REQUEST 0x0001 +#define EIGRP_TLV_INTERNAL 0x0002 +#define EIGRP_TLV_EXTERNAL 0x0003 +#define EIGRP_TLV_COMMUNITY 0x0004 + +/* Legacy TLV formats */ +#define EIGRP_TLV_IPv4_REQ (EIGRP_TLV_IPv4 | EIGRP_TLV_REQUEST) +#define EIGRP_TLV_IPv4_INT (EIGRP_TLV_IPv4 | EIGRP_TLV_INTERNAL) +#define EIGRP_TLV_IPv4_EXT (EIGRP_TLV_IPv4 | EIGRP_TLV_EXTERNAL) +#define EIGRP_TLV_IPv4_COM (EIGRP_TLV_IPv4 | EIGRP_TLV_COMMUNITY) +#define EIGRP_TLV_IPX_INT (EIGRP_TLV_IPX | EIGRP_TLV_INTERNAL) +#define EIGRP_TLV_IPX_EXT (EIGRP_TLV_IPX | EIGRP_TLV_EXTERNAL) +#define EIGRP_TLV_IPX_COM (EIGRP_TLV_IPX | EIGRP_TLV_COMMUNITY) +#define EIGRP_TLV_IPv6_INT (EIGRP_TLV_IPv6 | EIGRP_TLV_INTERNAL) +#define EIGRP_TLV_IPv6_EXT (EIGRP_TLV_IPv6 | EIGRP_TLV_EXTERNAL) +#define EIGRP_TLV_IPv6_COM (EIGRP_TLV_IPv6 | EIGRP_TLV_COMMUNITY) + +/* Deprecated TLV formats */ +#define EIGRP_TLV_AT_INT (EIGRP_TLV_ATALK | EIGRP_TLV_INTERNAL) +#define EIGRP_TLV_AT_EXT (EIGRP_TLV_ATALK | EIGRP_TLV_EXTERNAL) +#define EIGRP_TLV_AT_CBL (EIGRP_TLV_ATALK | 0x04) +#define EIGRP_TLV_MTR_REQ (EIGRP_TLV_MTR | EIGRP_TLV_REQUEST) +#define EIGRP_TLV_MTR_INT (EIGRP_TLV_MTR | EIGRP_TLV_INTERNAL) +#define EIGRP_TLV_MTR_EXT (EIGRP_TLV_MTR | EIGRP_TLV_EXTERNAL) +#define EIGRP_TLV_MTR_COM (EIGRP_TLV_MTR | EIGRP_TLV_COMMUNITY) +#define EIGRP_TLV_MTR_TIDLIST (EIGRP_TLV_MTR | 0x0005) + +/* Current "Wide Metric" TLV formats */ +#define EIGRP_TLV_MP_REQ (EIGRP_TLV_MP | EIGRP_TLV_REQUEST) +#define EIGRP_TLV_MP_INT (EIGRP_TLV_MP | EIGRP_TLV_INTERNAL) +#define EIGRP_TLV_MP_EXT (EIGRP_TLV_MP | EIGRP_TLV_EXTERNAL) +#define EIGRP_TLV_MP_COM (EIGRP_TLV_MP | EIGRP_TLV_COMMUNITY) + +/** + * External routes originate from some other protocol - these are them + */ +#define NULL_PROTID 0 /*!< unknown protocol */ +#define IGRP1_PROTID 1 /*!< IGRP.. whos your daddy! */ +#define IGRP2_PROTID 2 /*!< EIGRP - Just flat out the best */ +#define STATIC_PROTID 3 /*!< Staticly configured source */ +#define RIP_PROTID 4 /*!< Routing Information Protocol */ +#define HELLO_PROTID 5 /*!< Hello? RFC-891 you there? */ +#define OSPF_PROTID 6 /*!< OSPF - Open Shortest Path First */ +#define ISIS_PROTID 7 /*!< Intermediate System To Intermediate System */ +#define EGP_PROTID 8 /*!< Exterior Gateway Protocol */ +#define BGP_PROTID 9 /*!< Border Gateway Protocol */ +#define IDRP_PROTID 10 /*!< InterDomain Routing Protocol */ +#define CONN_PROTID 11 /*!< Connected source */ + +/** + * + * extdata flag field definitions + */ +#define EIGRP_OPAQUE_EXT 0x01 /*!< Route is external */ +#define EIGRP_OPAQUE_CD 0x02 /*!< Candidate default route */ + +/** + * Address-Family types are taken from: + * http://www.iana.org/assignments/address-family-numbers + * to provide a standards based exchange of AFI information between + * EIGRP routers. + */ +#define EIGRP_AF_IPv4 1 /*!< IPv4 (IP version 4) */ +#define EIGRP_AF_IPv6 2 /*!< IPv6 (IP version 6) */ +#define EIGRP_AF_IPX 11 /*!< IPX */ +#define EIGRP_AF_ATALK 12 /*!< Appletalk */ +#define EIGRP_SF_COMMON 16384 /*!< Cisco Service Family */ +#define EIGRP_SF_IPv4 16385 /*!< Cisco IPv4 Service Family */ +#define EIGRP_SF_IPv6 16386 /*!< Cisco IPv6 Service Family */ + +/** + * Authentication types supported by EIGRP + */ +#define EIGRP_AUTH_TYPE_NONE 0 +#define EIGRP_AUTH_TYPE_TEXT 1 +#define EIGRP_AUTH_TYPE_MD5 2 +#define EIGRP_AUTH_TYPE_MD5_LEN 16 +#define EIGRP_AUTH_TYPE_SHA256 3 +#define EIGRP_AUTH_TYPE_SHA256_LEN 32 + +/** + * opaque flag field definitions + */ +#define EIGRP_OPAQUE_SRCWD 0x01 /*!< Route Source Withdraw */ +#define EIGRP_OPAQUE_ACTIVE 0x04 /*!< Route is currently in active state */ +#define EIGRP_OPAQUE_REPL 0x08 /*!< Route is replicated from different tableid */ + +/** + * pak flag bit field definitions - 0 (none)-7 source priority + */ +#define EIGRP_PRIV_DEFAULT 0x00 /* 0 (none)-7 source priority */ +#define EIGRP_PRIV_LOW 0x01 +#define EIGRP_PRIV_MEDIUM 0x04 +#define EIGRP_PRIV_HIGH 0x07 + +/** + * stub bit definitions + */ +#define EIGRP_PEER_ALLOWS_CONNECTED 0x0001 +#define EIGRP_PEER_ALLOWS_STATIC 0x0002 +#define EIGRP_PEER_ALLOWS_SUMMARY 0x0004 +#define EIGRP_PEER_ALLOWS_REDIST 0x0008 +#define EIGRP_PEER_ALLOWS_LEAKING 0x0010 +#define EIGRP_PEER_ALLOWS_RCVONLY 0x0020 + +/* + * Init bit definition. First unicast transmitted Update has this + * bit set in the flags field of the fixed header. It tells the neighbor + * to down-load his topology table. + */ +#define EIGRP_INIT_FLAG 0x01 + +/* + * CR bit (Conditionally Received) definition in flags field on header. Any + * packets with the CR-bit set can be accepted by an EIGRP speaker if and + * only if a previous Hello was received with the SEQUENCE_TYPE TLV present. + * + * This allows multicasts to be transmitted in order and reliably at the + * same time as unicasts are transmitted. + */ +#define EIGRP_CR_FLAG 0x02 + +/* + * RS bit. The Restart flag is set in the hello and the init + * update packets during the nsf signaling period. A nsf-aware + * router looks at the RS flag to detect if a peer is restarting + * and maintain the adjacency. A restarting router looks at + * this flag to determine if the peer is helping out with the restart. + */ +#define EIGRP_RS_FLAG 0x04 + +/* + * EOT bit. The End-of-Table flag marks the end of the start-up updates + * sent to a new peer. A nsf restarting router looks at this flag to + * determine if it has finished receiving the start-up updates from all + * peers. A nsf-aware router waits for this flag before cleaning up + * the stale routes from the restarting peer. + */ +#define EIGRP_EOT_FLAG 0x08 + +/** + * EIGRP Virtual Router ID + * + * Define values to deal with EIGRP virtual router ids. Virtual + * router IDs are stored in the upper short of the EIGRP fixed packet + * header. The lower short of the packet header continues to be used + * as asystem number. + * + * Virtual Router IDs are PDM-independent. All PDMs will use + * VRID_BASE to indicate the 'base' or 'legacy' EIGRP instance. + * All PDMs need to initialize their vrid to VRID_BASE for compatibility + * with legacy routers. + * Once IPv6 supports 'MTR Multicast', it will use the same VRID as + * IPv4. No current plans to support VRIDs on IPX. :) + * Initial usage of VRID is to signal usage of Multicast topology for + * MTR. + * + * VRID_MCAST is a well known constant, other VRIDs will be determined + * programmatic... + * + * With the addition of SAF the VRID space has been divided into two + * segments 0x0000-0x7fff is for EIGRP and vNets, 0x8000-0xffff is + * for saf and it's associated vNets. + */ +#define EIGRP_VRID_MASK 0x8001 +#define EIGRP_VRID_AF_BASE 0x0000 +#define EIGRP_VRID_MCAST_BASE 0x0001 +#define EIGRP_VRID_SF_BASE 0x8000 + +/* Extended Attributes for a destination */ +#define EIGRP_ATTR_HDRLEN (2) +#define EIGRP_ATTR_MAXDATA (512) + +#define EIGRP_ATTR_NOOP 0 /*!< No-Op used as offset padding */ +#define EIGRP_ATTR_SCALED 1 /*!< Scaled metric values */ +#define EIGRP_ATTR_TAG 2 /*!< Tag assigned by Admin for dest */ +#define EIGRP_ATTR_COMM 3 /*!< Community attribute for dest */ +#define EIGRP_ATTR_JITTER 4 /*!< Variation in path delay */ +#define EIGRP_ATTR_QENERGY 5 /*!< Non-Active energy usage along path */ +#define EIGRP_ATTR_ENERGY 6 /*!< Active energy usage along path */ /* - * See - * - * http://www.rhyshaden.com/eigrp.htm - */ - -#define EIGRP_UPDATE 0x01 -#define EIGRP_REQUEST 0x02 -#define EIGRP_QUERY 0x03 -#define EIGRP_REPLY 0x04 -#define EIGRP_HELLO 0x05 -#define EIGRP_SAP 0x06 -#define EIGRP_SIA_QUERY 0x0a -#define EIGRP_SIA_REPLY 0x0b -#define EIGRP_HI 0x20 /* This value is for my own need to make a difference between Hello and Ack */ -#define EIGRP_ACK 0x40 /* This value is for my own need to make a difference between Hello and Ack */ - -#define TLV_PAR 0x0001 -#define TLV_AUTH 0x0002 -#define TLV_SEQ 0x0003 -#define TLV_SV 0x0004 -#define TLV_NMS 0x0005 -#define TLV_STUB 0x0006 -#define TLV_IP_INT 0x0102 -#define TLV_IP_EXT 0x0103 -#define TLV_AT_INT 0x0202 -#define TLV_AT_EXT 0x0203 -#define TLV_AT_CBL 0x0204 -#define TLV_IPX_INT 0x0302 -#define TLV_IPX_EXT 0x0303 -#define TLV_IP6_INT 0x0402 -#define TLV_IP6_EXT 0x0403 - -#define EIGRP_FLAGS_INIT 0x00000001 -#define EIGRP_FLAGS_CONDRECV 0x00000002 -#define EIGRP_FLAGS_RESTART 0x00000004 -#define EIGRP_FLAGS_ENDOFTABLE 0x00000008 - -#define EIGRP_STUB_FLAGS_CONNECTED 0x0001 -#define EIGRP_STUB_FLAGS_STATIC 0x0002 -#define EIGRP_STUB_FLAGS_SUMMARY 0x0004 -#define EIGRP_STUB_FLAGS_RECVONLY 0x0008 -#define EIGRP_STUB_FLAGS_REDIST 0x0010 -#define EIGRP_STUB_FLAGS_LEAKMAP 0x0020 - -#define EIGRP_IP_EXT_FLAGS_EXT 0x01 -#define EIGRP_IP_EXT_FLAGS_DEFAULT 0x02 - -#define EIGRP_HEADER_LENGTH 20 - -static gint proto_eigrp = -1; + * Begin EIGRP-BGP interoperability communities + */ +#define EIGRP_EXTCOMM_SOO_ASFMT 0x0003 /* Site-of-Origin, BGP AS format */ +#define EIGRP_EXTCOMM_SOO_ADRFMT 0x0103 /* Site-of-Origin, BGP/EIGRP addr format */ +/* + * EIGRP Specific communities + */ +#define EIGRP_EXTCOMM_EIGRP 0x8800 /* EIGRP route information appended*/ +#define EIGRP_EXTCOMM_DAD 0x8801 /* EIGRP AS + Delay */ +#define EIGRP_EXTCOMM_VRHB 0x8802 /* EIGRP Vector: Reliability + Hop + BW */ +#define EIGRP_EXTCOMM_SRLM 0x8803 /* EIGRP System: Reserve +Load + MTU */ +#define EIGRP_EXTCOMM_SAR 0x8804 /* EIGRP System: Remote AS + Remote ID */ +#define EIGRP_EXTCOMM_RPM 0x8805 /* EIGRP Remote: Protocol + Metric */ +#define EIGRP_EXTCOMM_VRR 0x8806 /* EIGRP Vecmet: Rsvd + (internal) Routerid */ + +/* SAF types */ +#define EIGRP_SVCDATA_COMPLETE 0x01 /*!< Data is attached */ +#define EIGRP_SVCDATA_TRIMMED 0x02 /*!< Data was trimmed from service */ + +/* SAF Defined Numbers */ +#define SAF_SERVICE_ID_CAPMAN 100 /*!< Capabilities Manager */ +#define SAF_SERVICE_ID_UC 101 /*!< Unified Communications */ +#define SAF_SERVICE_ID_PFR 102 /*!< Performance Routing */ + +/* Forward declaration we need below (if using proto_reg_handoff... + as a prefs callback) */ +void proto_reg_handoff_eigrp(void); + +/* Initialize the protocol and registered fields */ +static int proto_eigrp = -1; + +/* header */ static gint hf_eigrp_version = -1; static gint hf_eigrp_opcode = -1; static gint hf_eigrp_checksum = -1; +static gint hf_eigrp_flags = -1; +static gint hf_eigrp_sequence = -1; +static gint hf_eigrp_acknowledge = -1; +static gint hf_eigrp_vrid = -1; +static gint hf_eigrp_as = -1; +static gint ett_eigrp = -1; -static gint hf_eigrp_flags = -1; /* Flags Tree */ +/* packet header flags */ static gint hf_eigrp_flags_init = -1; -static gint hf_eigrp_flags_condrecv = -1; static gint hf_eigrp_flags_restart = -1; static gint hf_eigrp_flags_eot = -1; +static gint hf_eigrp_flags_condrecv = -1; -static gint hf_eigrp_sequence = -1; -static gint hf_eigrp_acknowledge = -1; -static gint hf_eigrp_as = -1; -static gint hf_eigrp_tlv = -1; -static gint hf_eigrp_tlv_size = -1; +static gint ett_eigrp_flags = -1; +static const int *eigrp_flag_fields[] = { + &hf_eigrp_flags_init, + &hf_eigrp_flags_condrecv, + &hf_eigrp_flags_restart, + &hf_eigrp_flags_eot, + NULL +}; + +/* tlv */ +static gint hf_eigrp_tlv_type = -1; +static gint hf_eigrp_tlv_len = -1; +static gint hf_eigrp_tid = -1; +static gint hf_eigrp_afi = -1; +static gint hf_eigrp_nullpad = -1; + +static gint ett_eigrp_tlv = -1; +static gint ett_eigrp_tlv_metric = -1; +static gint ett_eigrp_tlv_attr = -1; +static gint ett_eigrp_tlv_extdata = -1; -/* EIGRP Parameters TLV */ +/* param */ static gint hf_eigrp_par_k1 = -1; static gint hf_eigrp_par_k2 = -1; static gint hf_eigrp_par_k3 = -1; static gint hf_eigrp_par_k4 = -1; static gint hf_eigrp_par_k5 = -1; -static gint hf_eigrp_par_reserved = -1; +static gint hf_eigrp_par_k6 = -1; static gint hf_eigrp_par_holdtime = -1; -/* Authentication TLV */ +/* auth */ static gint hf_eigrp_auth_type = -1; -static gint hf_eigrp_auth_keysize = -1; +static gint hf_eigrp_auth_len = -1; static gint hf_eigrp_auth_keyid = -1; -static gint hf_eigrp_auth_nullpad = -1; -static gint hf_eigrp_auth_data = -1; +static gint hf_eigrp_auth_keyseq = -1; +static gint hf_eigrp_auth_digest = -1; -/* Sequence TLV */ +/* seq */ static gint hf_eigrp_seq_addrlen = -1; -static gint hf_eigrp_seq_ipaddr = -1; -static gint hf_eigrp_seq_ip6addr = -1; +static gint hf_eigrp_seq_ipv4addr = -1; +static gint hf_eigrp_seq_ipv6addr = -1; -/* Software Version TLV */ -static gint hf_eigrp_sv_ios = -1; -static gint hf_eigrp_sv_eigrp = -1; +/* sw version */ +static gint hf_eigrp_sw_version = -1; +static gint hf_eigrp_sw_version_os_majorver = -1; +static gint hf_eigrp_sw_version_os_minorver = -1; +static gint hf_eigrp_sw_version_tlv_majorrev = -1; +static gint hf_eigrp_sw_version_tlv_minorrev = -1; -/* Next multicast sequence TLV */ -static gint hf_eigrp_nms = -1; +/* multicast seq */ +static gint hf_eigrp_next_mcast_seq = -1; -/* Stub routing TLV */ -static gint hf_eigrp_stub_flags = -1; /* Stub Flags Tree */ +/* stub flags */ +static gint hf_eigrp_stub_flags = -1; static gint hf_eigrp_stub_flags_connected = -1; static gint hf_eigrp_stub_flags_static = -1; static gint hf_eigrp_stub_flags_summary = -1; @@ -146,1649 +409,3075 @@ static gint hf_eigrp_stub_flags_recvonly = -1; static gint hf_eigrp_stub_flags_redist = -1; static gint hf_eigrp_stub_flags_leakmap = -1; -/* IP internal route TLV */ -static gint hf_eigrp_ip_int_nexthop = -1; -static gint hf_eigrp_ip_int_delay = -1; -static gint hf_eigrp_ip_int_bandwidth = -1; -static gint hf_eigrp_ip_int_mtu = -1; -static gint hf_eigrp_ip_int_hopcount = -1; -static gint hf_eigrp_ip_int_reliability = -1; -static gint hf_eigrp_ip_int_load = -1; -static gint hf_eigrp_ip_int_reserved = -1; -static gint hf_eigrp_ip_int_prefixlen = -1; -static gint hf_eigrp_ip_int_dst = -1; - -/* IP external route TLV */ -static gint hf_eigrp_ip_ext_nexthop = -1; -static gint hf_eigrp_ip_ext_origrouter = -1; -static gint hf_eigrp_ip_ext_as = -1; -static gint hf_eigrp_ip_ext_tag = -1; -static gint hf_eigrp_ip_ext_metric = -1; -static gint hf_eigrp_ip_ext_reserved = -1; -static gint hf_eigrp_ip_ext_proto = -1; - -static gint hf_eigrp_ip_ext_flags = -1; /* IP external route Flags Tree */ -static gint hf_eigrp_ip_ext_flags_ext = -1; -static gint hf_eigrp_ip_ext_flags_default = -1; - -static gint hf_eigrp_ip_ext_delay = -1; -static gint hf_eigrp_ip_ext_bandwidth = -1; -static gint hf_eigrp_ip_ext_mtu = -1; -static gint hf_eigrp_ip_ext_hopcount = -1; -static gint hf_eigrp_ip_ext_reliability = -1; -static gint hf_eigrp_ip_ext_load = -1; -static gint hf_eigrp_ip_ext_reserved2 = -1; -static gint hf_eigrp_ip_ext_prefixlen = -1; - -/* IPX internal route TLV */ -static gint hf_eigrp_ipx_int_nexthop_addr = -1; -static gint hf_eigrp_ipx_int_nexthop_id = -1; -static gint hf_eigrp_ipx_int_delay = -1; -static gint hf_eigrp_ipx_int_bandwidth = -1; -static gint hf_eigrp_ipx_int_mtu = -1; -static gint hf_eigrp_ipx_int_hopcount = -1; -static gint hf_eigrp_ipx_int_reliability = -1; -static gint hf_eigrp_ipx_int_load = -1; -static gint hf_eigrp_ipx_int_reserved = -1; -static gint hf_eigrp_ipx_int_dst = -1; - -/* IPX external route TLV */ -static gint hf_eigrp_ipx_ext_nexthop_addr = -1; -static gint hf_eigrp_ipx_ext_nexthop_id = -1; -static gint hf_eigrp_ipx_ext_origrouter = -1; -static gint hf_eigrp_ipx_ext_as = -1; -static gint hf_eigrp_ipx_ext_tag = -1; -static gint hf_eigrp_ipx_ext_proto = -1; -static gint hf_eigrp_ipx_ext_reserved = -1; -static gint hf_eigrp_ipx_ext_metric = -1; -static gint hf_eigrp_ipx_ext_extdelay = -1; -static gint hf_eigrp_ipx_ext_delay = -1; -static gint hf_eigrp_ipx_ext_bandwidth = -1; -static gint hf_eigrp_ipx_ext_mtu = -1; -static gint hf_eigrp_ipx_ext_hopcount = -1; -static gint hf_eigrp_ipx_ext_reliability = -1; -static gint hf_eigrp_ipx_ext_load = -1; -static gint hf_eigrp_ipx_ext_reserved2 = -1; -static gint hf_eigrp_ipx_ext_dst = -1; - -/* AppleTalk cable configuration TLV */ -static gint hf_eigrp_at_cbl_routerid = -1; - -/* AppleTalk internal route TLV */ -static gint hf_eigrp_at_int_delay = -1; -static gint hf_eigrp_at_int_bandwidth = -1; -static gint hf_eigrp_at_int_mtu = -1; -static gint hf_eigrp_at_int_hopcount = -1; -static gint hf_eigrp_at_int_reliability = -1; -static gint hf_eigrp_at_int_load = -1; -static gint hf_eigrp_at_int_reserved = -1; - -/* AppleTalk external route TLV */ -static gint hf_eigrp_at_ext_origrouter = -1; -static gint hf_eigrp_at_ext_as = -1; -static gint hf_eigrp_at_ext_tag = -1; -static gint hf_eigrp_at_ext_proto = -1; - -static gint hf_eigrp_at_ext_flags = -1; /* AppleTalk external route Flags Tree */ -static gint hf_eigrp_at_ext_flags_ext = -1; -static gint hf_eigrp_at_ext_flags_default = -1; - -static gint hf_eigrp_at_ext_metric = -1; - -static gint hf_eigrp_at_ext_delay = -1; -static gint hf_eigrp_at_ext_bandwidth = -1; -static gint hf_eigrp_at_ext_mtu = -1; -static gint hf_eigrp_at_ext_hopcount = -1; -static gint hf_eigrp_at_ext_reliability = -1; -static gint hf_eigrp_at_ext_load = -1; -static gint hf_eigrp_at_ext_reserved = -1; - -/* IPv6 internal route TLV */ -static gint hf_eigrp_ip6_int_nexthop = -1; -static gint hf_eigrp_ip6_int_delay = -1; -static gint hf_eigrp_ip6_int_bandwidth = -1; -static gint hf_eigrp_ip6_int_mtu = -1; -static gint hf_eigrp_ip6_int_hopcount = -1; -static gint hf_eigrp_ip6_int_reliability = -1; -static gint hf_eigrp_ip6_int_load = -1; -static gint hf_eigrp_ip6_int_reserved = -1; -static gint hf_eigrp_ip6_int_prefixlen = -1; - -/* IPv6 external route TLV */ -static gint hf_eigrp_ip6_ext_nexthop = -1; -static gint hf_eigrp_ip6_ext_origrouter = -1; -static gint hf_eigrp_ip6_ext_as = -1; -static gint hf_eigrp_ip6_ext_tag = -1; -static gint hf_eigrp_ip6_ext_metric = -1; -static gint hf_eigrp_ip6_ext_reserved = -1; -static gint hf_eigrp_ip6_ext_proto = -1; - -static gint hf_eigrp_ip6_ext_flags = -1; /* IPv6 external route Flags Tree */ -static gint hf_eigrp_ip6_ext_flags_ext = -1; -static gint hf_eigrp_ip6_ext_flags_default = -1; - -static gint hf_eigrp_ip6_ext_delay = -1; -static gint hf_eigrp_ip6_ext_bandwidth = -1; -static gint hf_eigrp_ip6_ext_mtu = -1; -static gint hf_eigrp_ip6_ext_hopcount = -1; -static gint hf_eigrp_ip6_ext_reliability = -1; -static gint hf_eigrp_ip6_ext_load = -1; -static gint hf_eigrp_ip6_ext_reserved2 = -1; -static gint hf_eigrp_ip6_ext_prefixlen = -1; - -static gint ett_eigrp = -1; -static gint ett_eigrp_flags = -1; -static gint ett_tlv = -1; static gint ett_eigrp_stub_flags = -1; -static gint ett_eigrp_ip_ext_flags = -1; -static gint ett_eigrp_ip6_ext_flags = -1; -static gint ett_eigrp_at_ext_flags = -1; - -static dissector_handle_t ipxsap_handle; - - -static const value_string eigrp_opcode_vals[] = { - { EIGRP_HELLO, "Hello/Ack" }, - { EIGRP_UPDATE, "Update" }, - { EIGRP_REPLY, "Reply" }, - { EIGRP_QUERY, "Query" }, - { EIGRP_REQUEST, "Request" }, - { EIGRP_SAP, "IPX/SAP Update" }, - { EIGRP_SIA_QUERY, "SIA-Query" }, - { EIGRP_SIA_REPLY, "SIA-Reply" }, - { EIGRP_HI, "Hello" }, - { EIGRP_ACK, "Acknowledge" }, - { 0, NULL } +static const int *eigrp_stub_flag_fields[] = { + &hf_eigrp_stub_flags_connected, + &hf_eigrp_stub_flags_static, + &hf_eigrp_stub_flags_summary, + &hf_eigrp_stub_flags_redist, + &hf_eigrp_stub_flags_leakmap, + &hf_eigrp_stub_flags_recvonly, + NULL }; -static const value_string eigrp_tlv_vals[] = { - { TLV_PAR, "EIGRP Parameters"}, - { TLV_AUTH, "Authentication data"}, - { TLV_SEQ , "Sequence"}, - { TLV_SV, "Software Version"}, - { TLV_NMS , "Next multicast sequence"}, - { TLV_STUB , "Stub routing"}, - { TLV_IP_INT, "IP internal route"}, - { TLV_IP_EXT, "IP external route"}, - { TLV_AT_INT, "AppleTalk internal route"}, - { TLV_AT_EXT, "AppleTalk external route"}, - { TLV_AT_CBL, "AppleTalk cable configuration"}, - { TLV_IPX_INT, "IPX internal route"}, - { TLV_IPX_EXT, "IPX external route"}, - { TLV_IP6_INT, "IPv6 internal route"}, - { TLV_IP6_EXT, "IPv6 external route"}, - { 0, NULL} +/* tid */ +static gint hf_eigrp_tidlist = -1; +static gint hf_eigrp_tidlist_flags = -1; +static gint hf_eigrp_tidlist_len = -1; +static gint ett_eigrp_tidlist_flags = -1; + +/* 1.2 and 3.0 metric */ +static gint hf_eigrp_legacy_metric_delay = -1; +static gint hf_eigrp_legacy_metric_bw = -1; +static gint hf_eigrp_legacy_metric_mtu = -1; +static gint hf_eigrp_legacy_metric_hopcount = -1; +static gint hf_eigrp_legacy_metric_rel = -1; +static gint hf_eigrp_legacy_metric_load = -1; +static gint hf_eigrp_legacy_metric_intag = -1; + +/* 3.0 metric */ +static gint hf_eigrp_legacy_metric_tag = -1; + +/* 2.0 metric */ +static gint hf_eigrp_metric_offset = -1; +static gint hf_eigrp_metric_priority = -1; +static gint hf_eigrp_metric_rel = -1; +static gint hf_eigrp_metric_load = -1; +static gint hf_eigrp_metric_mtu = -1; +static gint hf_eigrp_metric_hopcount = -1; +static gint hf_eigrp_metric_delay = -1; +static gint hf_eigrp_metric_bw = -1; +static gint hf_eigrp_metric_reserved = -1; + +/* router id*/ +static gint hf_eigrp_routerid = -1; + +/* protocol dependent module route flags */ +static gint hf_eigrp_metric_flags_srcwd = -1; +static gint hf_eigrp_metric_flags_active = -1; +static gint hf_eigrp_metric_flags_repl = -1; +static gint ett_eigrp_metric_flags = -1; + +/* extended metrics */ +static gint hf_eigrp_attr_opcode = -1; +static gint hf_eigrp_attr_offset = -1; +static gint hf_eigrp_attr_scaled = -1; +static gint hf_eigrp_attr_tag = -1; +static gint hf_eigrp_attr_jitter = -1; +static gint hf_eigrp_attr_qenergy = -1; +static gint hf_eigrp_attr_energy = -1; + +/* route external data */ +static gint hf_eigrp_extdata_origrid = -1; +static gint hf_eigrp_extdata_as = -1; +static gint hf_eigrp_extdata_tag = -1; +static gint hf_eigrp_extdata_metric = -1; +static gint hf_eigrp_extdata_reserved = -1; +static gint hf_eigrp_extdata_proto = -1; + +static gint hf_eigrp_extdata_flag_ext = -1; +static gint hf_eigrp_extdata_flag_cd = -1; +static gint ett_eigrp_extdata_flags = -1; + +/* ipv4 address */ +static gint hf_eigrp_ipv4_nexthop = -1; +static gint hf_eigrp_ipv4_prefixlen = -1; +static gint hf_eigrp_ipv4_dest = -1; + +/* ipv6 address */ +static gint hf_eigrp_ipv6_nexthop = -1; +static gint hf_eigrp_ipv6_prefixlen = -1; + +/* ipx address */ +static gint hf_eigrp_ipx_nexthop_net = -1; +static gint hf_eigrp_ipx_nexthop_host = -1; +static gint hf_eigrp_ipx_extdata_routerid = -1; +static gint hf_eigrp_ipx_extdata_delay = -1; +static gint hf_eigrp_ipx_extdata_metric = -1; +static gint hf_eigrp_ipx_dest = -1; + +/* appletalk address */ +static gint hf_eigrp_atalk_routerid = -1; + +/* SAF services */ +static gint hf_eigrp_saf_service = -1; +static gint hf_eigrp_saf_subservice = -1; +static gint hf_eigrp_saf_guid = -1; + +static gint hf_eigrp_saf_reachability_afi = -1; +static gint hf_eigrp_saf_reachability_port = -1; +static gint hf_eigrp_saf_reachability_protocol = -1; +static gint hf_eigrp_saf_reachability_addr_ipv4 = -1; +static gint hf_eigrp_saf_reachability_addr_ipv6 = -1; +static gint hf_eigrp_saf_reachability_addr_hex = -1; +static gint ett_eigrp_saf_reachability = -1; + +static gint hf_eigrp_saf_data_length = -1; +static gint hf_eigrp_saf_data_sequence = -1; +static gint hf_eigrp_saf_data_type = -1; + +/* some extra handle that might be needed */ +static dissector_handle_t ipxsap_handle = NULL; +static dissector_table_t media_type_table = NULL; + +static const value_string eigrp_opcode2string[] = { + { EIGRP_OPC_UPDATE, "Update" }, + { EIGRP_OPC_REQUEST, "Request" }, + { EIGRP_OPC_QUERY, "Query" }, + { EIGRP_OPC_REPLY, "Reply" }, + { EIGRP_OPC_HELLO, "Hello" }, + { EIGRP_OPC_IPXSAP, "IPX/SAP Update" }, + { EIGRP_OPC_PROBE, "Route Probe" }, + { EIGRP_OPC_ACK, "Hello (Ack)" }, + { EIGRP_OPC_STUB, "Stub-Info" }, + { EIGRP_OPC_SIAQUERY, "SIA-Query" }, + { EIGRP_OPC_SIAREPLY, "SIA-Reply" }, + { 0, NULL } }; -static const value_string eigrp_pid_vals[] = { - { 1, "IGRP"}, - { 2, "EIGRP"}, - { 3, "Static Route"}, - { 4, "RIP"}, - { 5, "Hello"}, - { 6, "OSPF"}, - { 7, "IS-IS"}, - { 8, "EGP"}, - { 9, "BGP"}, - { 10, "IDRP"}, - { 11, "Connected link"}, - { 0, NULL} +static const value_string eigrp_tlv2string[] = { + /* General TLV formats */ + { EIGRP_TLV_PARAMETER, "Parameters"}, + { EIGRP_TLV_AUTH, "Authentication"}, + { EIGRP_TLV_SEQ, "Sequence"}, + { EIGRP_TLV_SW_VERSION, "Software Version"}, + { EIGRP_TLV_NEXT_MCAST_SEQ, "Next multicast sequence"}, + { EIGRP_TLV_PEER_STUBINFO, "Peer Stub Information"}, + { EIGRP_TLV_PEER_TERMINATION, "Peer Termination"}, + { EIGRP_TLV_PEER_TIDLIST, "Peer Topology ID List"}, + + /* Legacy TLV formats */ + { EIGRP_TLV_IPv4_INT, "Internal Route(IPv4)"}, + { EIGRP_TLV_IPv4_EXT, "External Route(IPv4)"}, + { EIGRP_TLV_IPv4_COM, "Ext-Community(IPv4)"}, + { EIGRP_TLV_IPv6_INT, "Internal Route(IPv6)"}, + { EIGRP_TLV_IPv6_EXT, "External Route(IPv6)"}, + { EIGRP_TLV_IPv6_COM, "Ext-Community(IPv6)"}, + { EIGRP_TLV_IPX_INT, "IPX Internal Route(IPX)"}, + { EIGRP_TLV_IPX_EXT, "IPX External Route(IPX)"}, + + /* Deprecated TLV formats */ + { EIGRP_TLV_AT_INT, "Internal Route(ATALK)"}, + { EIGRP_TLV_AT_EXT, "External Route(ATALK)"}, + { EIGRP_TLV_AT_CBL, "Cable Configuration(ATALK)"}, + { EIGRP_TLV_MTR_REQ, "Request(MTR)"}, + { EIGRP_TLV_MTR_INT, "Internal Route(MTR)"}, + { EIGRP_TLV_MTR_EXT, "External Route(MTR)"}, + { EIGRP_TLV_MTR_COM, "Ext-Community(MTR)"}, + { EIGRP_TLV_MTR_TIDLIST, "TopologyID List"}, + + /* Current "Wide Metric" TLV formats */ + { EIGRP_TLV_MP_REQ, "Request"}, + { EIGRP_TLV_MP_INT, "Internal Route"}, + { EIGRP_TLV_MP_EXT, "External Route"}, + { EIGRP_TLV_MP_COM, "Ext-Community"}, + + { 0, NULL} }; -static const value_string eigrp_auth_type_vals[] = { - { 2, "MD5"}, - { 0, NULL} +static const value_string eigrp_proto2string[] = { + { IGRP1_PROTID, "IGRP"}, + { IGRP2_PROTID, "EIGRP"}, + { STATIC_PROTID, "Static Route"}, + { RIP_PROTID, "RIP"}, + { HELLO_PROTID, "Hello"}, + { OSPF_PROTID, "OSPF"}, + { ISIS_PROTID, "IS-IS"}, + { EGP_PROTID, "EGP"}, + { BGP_PROTID, "BGP"}, + { IDRP_PROTID, "IDRP"}, + { CONN_PROTID, "Connected Route"}, + { 0, NULL} }; -static void dissect_eigrp_par(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti); -static void dissect_eigrp_auth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); -static void dissect_eigrp_seq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); -static void dissect_eigrp_sv(tvbuff_t *tvb, proto_tree *tree, proto_item *ti); -static void dissect_eigrp_nms(tvbuff_t *tvb, proto_tree *tree, proto_item *ti); -static void dissect_eigrp_stub(tvbuff_t *tvb, proto_tree *tree); - -static void dissect_eigrp_ip_int(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti); -static void dissect_eigrp_ip_ext(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti); - -static void dissect_eigrp_ipx_int(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti); -static void dissect_eigrp_ipx_ext(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti); - -static void dissect_eigrp_at_cbl(tvbuff_t *tvb, proto_tree *tree, proto_item *ti); -static void dissect_eigrp_at_int(tvbuff_t *tvb, proto_tree *tree, proto_item *ti); -static void dissect_eigrp_at_ext(tvbuff_t *tvb, proto_tree *tree, proto_item *ti); - -static void dissect_eigrp_ip6_int(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti); -static void dissect_eigrp_ip6_ext(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti); - - -static void dissect_eigrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { - - proto_tree *eigrp_tree = NULL, *tlv_tree, *eigrp_flags_tree; - proto_item *ti; - - guint opcode, opcode_tmp; - guint16 tlv; - guint32 ack, size, offset = EIGRP_HEADER_LENGTH; - - col_set_str(pinfo->cinfo, COL_PROTOCOL, "EIGRP"); - col_clear(pinfo->cinfo, COL_INFO); - - opcode_tmp = opcode = tvb_get_guint8(tvb, 1); - ack = tvb_get_ntohl(tvb, 12); - if (opcode == EIGRP_HELLO) { if (ack == 0) opcode_tmp = EIGRP_HI; else opcode_tmp = EIGRP_ACK; } - - col_add_str(pinfo->cinfo, COL_INFO, - val_to_str(opcode_tmp, eigrp_opcode_vals, "Unknown (0x%04x)")); - - if (tree) { +static const value_string eigrp_auth2string[] = { + { EIGRP_AUTH_TYPE_TEXT, "TEXT"}, + { EIGRP_AUTH_TYPE_MD5, "MD5"}, + { EIGRP_AUTH_TYPE_SHA256, "SHA256"}, + { 0, NULL}, +}; - ti = proto_tree_add_protocol_format(tree, proto_eigrp, tvb, 0, -1, "Cisco EIGRP"); +static const value_string eigrp_vrid2string[] = { + { EIGRP_VRID_AF_BASE, "(Address-Family)"}, + { EIGRP_VRID_SF_BASE, "(Service-Family)"}, + { EIGRP_VRID_MCAST_BASE, "(Multi-Cast)"}, + { -1, NULL} +}; - eigrp_tree = proto_item_add_subtree(ti, ett_eigrp); +static const value_string eigrp_afi2string[] = { + { EIGRP_AF_IPv4, "IPv4"}, + { EIGRP_AF_IPv6, "IPv6"}, + { EIGRP_AF_IPX, "IPX"}, + { EIGRP_AF_ATALK, "Appletalk"}, + { EIGRP_SF_COMMON, "Service Family"}, + { EIGRP_SF_IPv4, "IPv4 Service Family"}, + { EIGRP_SF_IPv6, "IPv6 Service Family"}, + { -1, NULL} +}; - proto_tree_add_item(eigrp_tree, hf_eigrp_version, tvb, 0, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(eigrp_tree, hf_eigrp_opcode, tvb, 1, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(eigrp_tree, hf_eigrp_checksum, tvb, 2, 2, ENC_BIG_ENDIAN); -/* Decode the EIGRP Flags Field */ +static const value_string eigrp_attr_opcode2string[] = { + { EIGRP_ATTR_NOOP, "NO-OP for padding"}, + { EIGRP_ATTR_SCALED, "Scaled Metric"}, + { EIGRP_ATTR_TAG, "Admin Tag"}, + { EIGRP_ATTR_COMM, "Community"}, + { EIGRP_ATTR_JITTER, "Jitter"}, + { EIGRP_ATTR_QENERGY, "Non-Active energy"}, + { EIGRP_ATTR_ENERGY, "Active energy"}, + { 0, NULL} +}; - ti = proto_tree_add_item(eigrp_tree, hf_eigrp_flags, tvb, 4, 4, ENC_BIG_ENDIAN); - eigrp_flags_tree = proto_item_add_subtree(ti, ett_eigrp_flags); +static const value_string eigrp_saf_type2string[] = { + { EIGRP_SVCDATA_COMPLETE, "Attached Service Data"}, + { EIGRP_SVCDATA_TRIMMED, "Trimmed Service Data"}, + { 0, NULL} +}; - proto_tree_add_item(eigrp_flags_tree, hf_eigrp_flags_init, tvb, 4, 4, ENC_BIG_ENDIAN); - proto_tree_add_item(eigrp_flags_tree, hf_eigrp_flags_condrecv, tvb, 4, 4, ENC_BIG_ENDIAN); - proto_tree_add_item(eigrp_flags_tree, hf_eigrp_flags_restart, tvb, 4, 4, ENC_BIG_ENDIAN); - proto_tree_add_item(eigrp_flags_tree, hf_eigrp_flags_eot, tvb, 4, 4, ENC_BIG_ENDIAN); +static const value_string eigrp_saf_srv2string[] = { + { SAF_SERVICE_ID_CAPMAN, "Capabilities Manager"}, + { SAF_SERVICE_ID_UC, "Unified Communications"}, + { SAF_SERVICE_ID_PFR, "Performance Routing"}, + { 0, NULL} +}; -/* End Decode the EIGRP Flags Field */ +/** + *@fn void dissect_eigrp_parameter (proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, + * + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * @param[in] pinfo general data about the protocol + * @param[in] ti protocol item + * + * @return void + * + * @par + * Dissect the Parameter TLV, which is used to convey metric weights and the + * hold time. + * + * @usage + * Note the addition of K6 for the new extended metrics, and does not apply to + * older TLV packet formats. + */ +static void +dissect_eigrp_parameter (proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, + proto_item *ti) +{ + int offset = 0; + guint8 k1, k2, k3, k4, k5, k6; + + k1 = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tree, hf_eigrp_par_k1, tvb, offset, 1, ENC_BIG_ENDIAN); + + offset += 1; + k2 = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tree, hf_eigrp_par_k2, tvb, offset, 1, ENC_BIG_ENDIAN); + + offset += 1; + k3 = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tree, hf_eigrp_par_k3, tvb, offset, 1, ENC_BIG_ENDIAN); + + offset += 1; + k4 = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tree, hf_eigrp_par_k4, tvb, offset, 1, ENC_BIG_ENDIAN); + + offset += 1; + k5 = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tree, hf_eigrp_par_k5, tvb, offset, 1, ENC_BIG_ENDIAN); + + offset += 1; + k6 = tvb_get_guint8(tvb, offset); + proto_tree_add_item(tree, hf_eigrp_par_k6, tvb, offset, 1, ENC_BIG_ENDIAN); + + offset += 1; + proto_tree_add_item(tree, hf_eigrp_par_holdtime, tvb, offset, 2, ENC_BIG_ENDIAN); + + if (k1 == 255 && k2 == 255 && k3 == 255 && k4 == 255 && k5 == 255) { + proto_item_append_text(ti, ": Peer Termination"); + expert_add_info_format(pinfo, ti, PI_RESPONSE_CODE, PI_NOTE, + "Peer Termination"); + } +} - proto_tree_add_item(eigrp_tree, hf_eigrp_sequence, tvb, 8, 4, ENC_BIG_ENDIAN); - proto_tree_add_item(eigrp_tree, hf_eigrp_acknowledge, tvb, 12, 4, ENC_BIG_ENDIAN); - proto_tree_add_item(eigrp_tree, hf_eigrp_as, tvb, 16, 4, ENC_BIG_ENDIAN); +/** + *@fn void dissect_eigrp_auth_tlv (proto_tree *tree, tvbuff_t *tvb, + * packet_info *pinfo, proto_item *ti) + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * @param[in] pinfo general data about the protocol + * @param[in] ti protocol item + * + * @return void + * + * @par + * Dissect the Authentication TLV and display digest. Currently MD5 and SHA256 + * HMAC is supported. For SHA256, a "secret key" with the HMAC-SHA-256 + * password, the source address from which the packet is sent. This combined + * string is used as the key for hash calculation. + */ +static void +dissect_eigrp_auth_tlv (proto_tree *tree, tvbuff_t *tvb, + packet_info *pinfo, proto_item *ti) +{ + proto_item *ti_auth_type, *ti_auth_len; + int offset = 0; + guint16 auth_type, auth_len; + + /* print out what family we dealing with... */ + + auth_type = tvb_get_ntohs(tvb, 0); + auth_len = tvb_get_ntohs(tvb, 2); + + proto_item_append_text(ti, " %s", val_to_str(auth_type, eigrp_auth2string, "")); + + ti_auth_type = proto_tree_add_item(tree, hf_eigrp_auth_type, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + ti_auth_len = proto_tree_add_item(tree, hf_eigrp_auth_len, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + proto_tree_add_item(tree, hf_eigrp_auth_keyid, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + proto_tree_add_item(tree, hf_eigrp_auth_keyseq, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + proto_tree_add_item(tree, hf_eigrp_nullpad, tvb, offset, 8, ENC_BIG_ENDIAN); + offset += 8; + + switch (auth_type) { + case EIGRP_AUTH_TYPE_MD5: + if (EIGRP_AUTH_TYPE_MD5_LEN != auth_len) { + expert_add_info_format(pinfo, ti_auth_len, PI_UNDECODED, PI_WARN, + "Invalid auth len %u:", auth_len); + } else { + proto_tree_add_item(tree, hf_eigrp_auth_digest, tvb, offset, + EIGRP_AUTH_TYPE_MD5_LEN, ENC_BIG_ENDIAN); } + break; - if (opcode == EIGRP_SAP) { - call_dissector(ipxsap_handle, tvb_new_subset(tvb, EIGRP_HEADER_LENGTH, -1, -1), pinfo, eigrp_tree); - return; - } + case EIGRP_AUTH_TYPE_SHA256: + if (EIGRP_AUTH_TYPE_SHA256_LEN != auth_len) { + expert_add_info_format(pinfo, ti_auth_len, PI_UNDECODED, PI_WARN, + "Invalid auth len %u:", auth_len); - if (tree) { - while (tvb_reported_length_remaining(tvb, offset) > 0) { - - tlv = tvb_get_ntohs(tvb, offset); - size = tvb_get_ntohs(tvb, offset + 2); - - if (size == 0) { - ti = proto_tree_add_text(eigrp_tree, tvb, offset, -1, "Unknown data (maybe authentication)"); - expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR, "Unknown data (maybe authentication)"); - return; - } - - ti = proto_tree_add_text(eigrp_tree, tvb, offset,size, - "%s", val_to_str(tlv, eigrp_tlv_vals, "Unknown (0x%04x)")); - - tlv_tree = proto_item_add_subtree(ti, ett_tlv); - proto_tree_add_item(tlv_tree, hf_eigrp_tlv, tvb, offset, 2, ENC_BIG_ENDIAN); - proto_tree_add_item(tlv_tree, hf_eigrp_tlv_size, tvb, offset + 2, 2, ENC_BIG_ENDIAN); - - - switch (tlv) { - case TLV_PAR: - dissect_eigrp_par(tvb_new_subset(tvb, offset + 4, size - 4, -1), pinfo, tlv_tree, ti); - break; - case TLV_AUTH: - dissect_eigrp_auth(tvb_new_subset(tvb, offset + 4, size - 4, -1), pinfo, tlv_tree); - break; - case TLV_SEQ: - dissect_eigrp_seq(tvb_new_subset(tvb, offset + 4, size - 4, -1), pinfo, tlv_tree); - break; - case TLV_SV: - dissect_eigrp_sv(tvb_new_subset(tvb, offset + 4, size - 4, -1), tlv_tree, ti); - break; - case TLV_NMS: - dissect_eigrp_nms(tvb_new_subset(tvb, offset + 4, size - 4, -1), tlv_tree, ti); - break; - case TLV_STUB: - dissect_eigrp_stub(tvb_new_subset(tvb, offset + 4, size - 4, -1), tlv_tree); - break; - - case TLV_IP_INT: - dissect_eigrp_ip_int(tvb_new_subset(tvb, offset + 4, size - 4, -1), pinfo, tlv_tree, ti); - break; - case TLV_IP_EXT: - dissect_eigrp_ip_ext(tvb_new_subset(tvb, offset + 4, size - 4, -1), pinfo, tlv_tree, ti); - break; - - case TLV_IPX_INT: - dissect_eigrp_ipx_int(tvb_new_subset(tvb, offset + 4, size - 4, -1), pinfo, tlv_tree, ti); - break; - case TLV_IPX_EXT: - dissect_eigrp_ipx_ext(tvb_new_subset(tvb, offset + 4, size - 4, -1), pinfo, tlv_tree, ti); - break; - - case TLV_AT_CBL: - dissect_eigrp_at_cbl(tvb_new_subset(tvb, offset + 4, size - 4, -1), tlv_tree, ti); - break; - case TLV_AT_INT: - dissect_eigrp_at_int(tvb_new_subset(tvb, offset + 4, size - 4, -1), tlv_tree, ti); - break; - case TLV_AT_EXT: - dissect_eigrp_at_ext(tvb_new_subset(tvb, offset + 4, size - 4, -1), tlv_tree, ti); - break; - - case TLV_IP6_INT: - dissect_eigrp_ip6_int(tvb_new_subset(tvb, offset + 4, size - 4, -1), pinfo, tlv_tree, ti); - break; - case TLV_IP6_EXT: - dissect_eigrp_ip6_ext(tvb_new_subset(tvb, offset + 4, size - 4, -1), pinfo, tlv_tree, ti); - break; - default: - expert_add_info_format(pinfo, ti, PI_UNDECODED, PI_WARN, "Unknown TLV (0x%04x)", tlv); - } - - offset += size; - } + } else { + proto_tree_add_item(tree, hf_eigrp_auth_digest, tvb, offset, + EIGRP_AUTH_TYPE_SHA256_LEN, ENC_BIG_ENDIAN); } + break; + + case EIGRP_AUTH_TYPE_NONE: + case EIGRP_AUTH_TYPE_TEXT: + default: + expert_add_info_format(pinfo, ti_auth_type, PI_UNDECODED, PI_WARN, + "Invalid auth type %u:", auth_type); + break; + } } - - -static void dissect_eigrp_par(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti) { - - int offset = 0; - guint8 k1, k2, k3, k4, k5; - - k1 = tvb_get_guint8(tvb, 1); - proto_tree_add_item(tree, hf_eigrp_par_k1, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - k2 = tvb_get_guint8(tvb, 1); - proto_tree_add_item(tree, hf_eigrp_par_k2, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - k3 = tvb_get_guint8(tvb, 1); - proto_tree_add_item(tree, hf_eigrp_par_k3, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - k4 = tvb_get_guint8(tvb, 1); - proto_tree_add_item(tree, hf_eigrp_par_k4, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - k5 = tvb_get_guint8(tvb, 1); - proto_tree_add_item(tree, hf_eigrp_par_k5, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_par_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_par_holdtime, tvb, offset, 2, ENC_BIG_ENDIAN); - - if (k1 == 255 && k2 == 255 && k3 == 255 && k4 == 255 && k5 == 255) { - proto_item_append_text(ti, ": Goodbye Message"); - expert_add_info_format(pinfo, ti, PI_RESPONSE_CODE, PI_NOTE, "Goodbye Message (Graceful Shutdown)"); - } +/** + *@fn void dissect_eigrp_seq_tlv (proto_tree *tree, tvbuff_t *tvb, + * packet_info *pinfo) + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * @param[in] pinfo general data about the protocol + * + * @return void + * + * @par + * Dissect the Sequence TLV which consist of the address of peers that must + * not receive the next multicast packet transmitted. + */ +static void +dissect_eigrp_seq_tlv (proto_tree *tree, tvbuff_t *tvb, + packet_info *pinfo) +{ + proto_item *ti_addrlen; + int offset = 0; + guint8 addr_len; + + addr_len = tvb_get_guint8(tvb, 0); + ti_addrlen = proto_tree_add_item(tree, hf_eigrp_seq_addrlen, tvb, offset, 1, ENC_BIG_ENDIAN); + offset += 1; + + switch (addr_len) { + case 4: + /* IPv4 */ + proto_tree_add_item(tree, hf_eigrp_seq_ipv4addr, tvb, offset, addr_len, ENC_BIG_ENDIAN); + break; + case 10: + /* IPX */ + proto_tree_add_text(tree, tvb, offset, addr_len, + "IPX Address = %08x.%04x.%04x.%04x", + tvb_get_ntohl(tvb, 1), tvb_get_ntohs(tvb, 5), + tvb_get_ntohs(tvb, 7), tvb_get_ntohs(tvb, 9)); + break; + case 16: + /* IPv6 */ + proto_tree_add_item(tree, hf_eigrp_seq_ipv6addr, tvb, offset, addr_len, + ENC_BIG_ENDIAN); + break; + default: + expert_add_info_format(pinfo, ti_addrlen, PI_MALFORMED, PI_ERROR, + "Invalid address length"); + } } -static void dissect_eigrp_auth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { - - proto_item *ti_keysize; - int offset = 0; - guint16 keysize; - - keysize = tvb_get_ntohs(tvb, 2); - - proto_tree_add_item(tree, hf_eigrp_auth_type, tvb, offset, 2, ENC_BIG_ENDIAN); - offset += 2; - ti_keysize = proto_tree_add_item(tree, hf_eigrp_auth_keysize, tvb, offset, 2, ENC_BIG_ENDIAN); - offset += 2; - proto_tree_add_item(tree, hf_eigrp_auth_keyid, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_auth_nullpad, tvb, offset, 12, FALSE); - offset += 12; - - switch (keysize) { - /* MD5 */ - case 16: - proto_tree_add_item(tree, hf_eigrp_auth_data, tvb, offset, keysize, FALSE); - break; - default: - expert_add_info_format(pinfo, ti_keysize, PI_UNDECODED, PI_WARN, - "Invalid key size %u: Only a value of 16 for MD5 is supported", keysize); - } +/** + *@fn void dissect_eigrp_sw_version (tvbuff_t *tvb, proto_tree *tree, + * proto_item *ti) + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * @param[in] ti protocol item + * + * @return void + * + * @par + * Dissect Software Version TLV. The older versions of EIGRP sent the IOS + * version along with the TLV Version. When EIGRP "plugins" were created, + * this as change to send the "Release" of EIGRP to better identify where fixes + * are present(missing) + */ +static void +dissect_eigrp_sw_version (tvbuff_t *tvb, proto_tree *tree, + proto_item *ti) +{ + int offset = 0; + guint8 ios_rel_major, ios_rel_minor; + guint8 eigrp_rel_major, eigrp_rel_minor; + + ios_rel_major = tvb_get_guint8(tvb, 0); + ios_rel_minor = tvb_get_guint8(tvb, 1); + proto_tree_add_text(tree, tvb, offset, 2, "EIGRP Release: %u.%u", + ios_rel_major, ios_rel_minor); + offset += 2; + proto_item_append_text(ti, ": EIGRP=%u.%u", ios_rel_major, ios_rel_minor); + + eigrp_rel_major = tvb_get_guint8(tvb, 2); + eigrp_rel_minor = tvb_get_guint8(tvb, 3); + proto_tree_add_text(tree,tvb,offset, 2, "EIGRP TLV version: %u.%u", + eigrp_rel_major, eigrp_rel_minor); + proto_item_append_text(ti, ", TLV=%u.%u", + eigrp_rel_major, eigrp_rel_minor); } -static void dissect_eigrp_seq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { - - proto_item *ti_addrlen; - int offset = 0; - guint8 addr_len; - - addr_len = tvb_get_guint8(tvb, 0); - - ti_addrlen = proto_tree_add_item(tree, hf_eigrp_seq_addrlen, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - - switch (addr_len) { - /* IPv4 */ - case 4: - proto_tree_add_item(tree, hf_eigrp_seq_ipaddr, tvb, offset, addr_len, ENC_BIG_ENDIAN); - break; - /* IPX */ - case 10: - proto_tree_add_text(tree, tvb, offset, addr_len, "IPX Address = %08x.%04x.%04x.%04x", - tvb_get_ntohl(tvb, 1), tvb_get_ntohs(tvb, 5), - tvb_get_ntohs(tvb, 7), tvb_get_ntohs(tvb, 9)); - break; - /* IPv6 */ - case 16: - proto_tree_add_item(tree, hf_eigrp_seq_ip6addr, tvb, offset, addr_len, ENC_NA); - break; - default: - expert_add_info_format(pinfo, ti_addrlen, PI_MALFORMED, PI_ERROR, "Invalid address length"); - } +/** + *@fn void dissect_eigrp_next_mcast_seq (tvbuff_t *tvb, proto_tree *tree, + * proto_item *ti) + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * @param[in] ti protocol item + * + * @return void + * + * @par + * Dissect Next Multicast Sequence TLV, which is part of the Hello with a + * Sequence TLV; this gives a two-way binding between the packets and plugs a + * hole where a multicast could be received by the wrong peers (due to a + * string of lost packets). + */ +static void +dissect_eigrp_next_mcast_seq (tvbuff_t *tvb, proto_tree *tree, + proto_item *ti) +{ + proto_tree_add_item(tree, hf_eigrp_next_mcast_seq, tvb, 0, 4, + ENC_BIG_ENDIAN); + proto_item_append_text(ti, ": %u", tvb_get_ntohl(tvb, 0)); } -static void dissect_eigrp_sv(tvbuff_t *tvb, proto_tree *tree, proto_item *ti) { +/** + *@fn void dissect_eigrp_peer_stubinfo (tvbuff_t *tvb, proto_tree *tree) + * + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * @param[in] pinfo general data about the protocol + * @param[in] ti protocol item + * @param[out] None + * + * @return void + * + * @par + * Dissect the PEER STUB TLV which contains the route types which the Peer will + * advertise. This is used to suppress QUERYs from being sent to the Peer + */ +static void +dissect_eigrp_peer_stubinfo (tvbuff_t *tvb, proto_tree *tree) +{ + proto_tree_add_bitmask(tree, tvb, 0, hf_eigrp_stub_flags, ett_eigrp_stub_flags, + eigrp_stub_flag_fields, FALSE); +} - int offset = 0; - guint8 ios_rel_major, ios_rel_minor; - guint8 eigrp_rel_major, eigrp_rel_minor; +/** + *@fn void dissect_eigrp_peer_termination (packet_info *pinfo, proto_item *ti) + * + * @param[in] pinfo general data about the protocol + * @param[in] ti protocol item + * @param[out] None + * + * @return void + * + * @par + * Dissect Peer Termination TLV. This TLV has no parameters and is used to + * signal an adjacency should be tore down + */ +static void +dissect_eigrp_peer_termination (packet_info *pinfo, proto_item *ti) +{ + expert_add_info_format(pinfo, ti, PI_RESPONSE_CODE, PI_NOTE, "Peer Termination (Graceful Shutdown)"); +} - ios_rel_major = tvb_get_guint8(tvb, 0); - ios_rel_minor = tvb_get_guint8(tvb, 1); - proto_tree_add_text(tree, tvb, offset, 2, "IOS release version: %u.%u", - ios_rel_major, ios_rel_minor); +/** + *@fn void dissect_eigrp_peer_tidlist (proto_tree *tree, tvbuff_t *tvb) + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * + * @return void + * + * @par + * Dissect the Topology Identifier List TLV. This TLV was introduced as part + * of the "MTR (Multi-Topology Routing) Project to support sub topologies + * within a given Autonomous System. The following represents the format of + * the TID list + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Flags | Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Variable Length TID (two bytes) list | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +static void +dissect_eigrp_peer_tidlist (proto_tree *tree, tvbuff_t *tvb) +{ + proto_item *sub_ti; + int offset = 0; + guint16 size, tid ; + + proto_tree_add_item(tree, hf_eigrp_tidlist_flags, tvb, offset, 2, + ENC_BIG_ENDIAN); + offset += 2; + + size = tvb_get_ntohs(tvb, offset) / 2; + proto_tree_add_item(tree, hf_eigrp_tidlist_len, tvb, offset, 2, + ENC_BIG_ENDIAN); + offset += 2; + + sub_ti = proto_tree_add_item(tree, hf_eigrp_tidlist, tvb, offset, + (size * 2), ENC_BIG_ENDIAN); + for (; size ; size--) { + tid = tvb_get_ntohs(tvb, offset); + proto_item_append_text(sub_ti, " %u", tid); offset += 2; - proto_item_append_text(ti, ": IOS=%u.%u", ios_rel_major, ios_rel_minor); - - eigrp_rel_major = tvb_get_guint8(tvb, 2); - eigrp_rel_minor = tvb_get_guint8(tvb, 3); - proto_tree_add_text(tree,tvb,offset, 2, "EIGRP release version: %u.%u", - eigrp_rel_major, eigrp_rel_minor); - proto_item_append_text(ti, ", EIGRP=%u.%u", - eigrp_rel_major, eigrp_rel_minor); + } } -static void dissect_eigrp_nms(tvbuff_t *tvb, proto_tree *tree, proto_item *ti) { - - proto_tree_add_item(tree, hf_eigrp_nms, tvb, 0, 4, ENC_BIG_ENDIAN); - proto_item_append_text(ti, ": %u", tvb_get_ntohl(tvb, 0)); +/** + *@fn int dissect_eigrp_extdata_flags (proto_tree *tree, tvbuff_t *tvb, int offset) + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * @param[in] offset current byte offset in packet being processed + * + * @return int number of bytes process + * + * @par + * Dissect the Flags field in the external data section of an external + * route.The following represents the format of the bit field + * + * 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+ + * | Flags | + * +-+-+-+-+-+-+-+-+ + * | | + * | +- Route is External *not used* + * +--- Route is Candidate Default + */ +static int +dissect_eigrp_extdata_flags (proto_tree *tree, tvbuff_t *tvb, int offset) +{ + proto_item *sub_ti; + proto_tree *sub_tree; + tvbuff_t *sub_tvb; + + /* Decode the route flags field */ + sub_ti = proto_tree_add_text(tree, tvb, offset, 1, "External Flags"); + sub_tree = proto_item_add_subtree(sub_ti, ett_eigrp_extdata_flags); + sub_tvb = tvb_new_subset(tvb, offset, 1, -1); + + proto_tree_add_item(sub_tree, hf_eigrp_extdata_flag_ext, sub_tvb, 0, 1, + ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_eigrp_extdata_flag_cd, sub_tvb, 0, 1, + ENC_BIG_ENDIAN); + + offset += 1; + return(offset); } -static void dissect_eigrp_stub(tvbuff_t *tvb, proto_tree *tree) { - - proto_tree *eigrp_stub_flags_tree; - proto_item *ti; - - ti = proto_tree_add_item(tree, hf_eigrp_stub_flags, tvb, 0, 2, ENC_BIG_ENDIAN); - eigrp_stub_flags_tree = proto_item_add_subtree(ti, ett_eigrp_stub_flags); - - proto_tree_add_item(eigrp_stub_flags_tree, hf_eigrp_stub_flags_connected, tvb, 0, 2, ENC_BIG_ENDIAN); - proto_tree_add_item(eigrp_stub_flags_tree, hf_eigrp_stub_flags_static, tvb, 0, 2, ENC_BIG_ENDIAN); - proto_tree_add_item(eigrp_stub_flags_tree, hf_eigrp_stub_flags_summary, tvb, 0, 2, ENC_BIG_ENDIAN); - proto_tree_add_item(eigrp_stub_flags_tree, hf_eigrp_stub_flags_recvonly, tvb, 0, 2, ENC_BIG_ENDIAN); - proto_tree_add_item(eigrp_stub_flags_tree, hf_eigrp_stub_flags_redist, tvb, 0, 2, ENC_BIG_ENDIAN); - proto_tree_add_item(eigrp_stub_flags_tree, hf_eigrp_stub_flags_leakmap, tvb, 0, 2, ENC_BIG_ENDIAN); +/** + *@fn int dissect_eigrp_metric_flags (proto_tree *tree, tvbuff_t *tvb, int offset, int limit) + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * @param[in] offset current byte offset in packet being processed + * @param[in] limit maximum number of bytes which can be process + * + * @return int number of bytes process + * + * @par + * Dissect Protocol Dependent Module (PDM) Flags field in the route metric + * section of an internal and external route. The following represents the + * format of the bit field + * + * MSB LSB + * 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Flags | MP Flags | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | | + * | | +- Route is Replicated + * | +--- Route is Active + * +----- Source Withdraw + */ +static int +dissect_eigrp_metric_flags (proto_tree *tree, tvbuff_t *tvb, int offset, int limit) +{ + proto_item *sub_ti; + proto_tree *sub_tree; + tvbuff_t *sub_tvb; + + /* Decode the route flags field */ + sub_ti = proto_tree_add_text(tree, tvb, offset, limit, "Flags"); + sub_tree = proto_item_add_subtree(sub_ti, ett_eigrp_metric_flags); + sub_tvb = tvb_new_subset(tvb, offset, limit, -1); + + /* just care about 'flags' byte, there are no MP flags for now */ + proto_tree_add_item(sub_tree, hf_eigrp_metric_flags_srcwd, sub_tvb, 0, 1, + ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_eigrp_metric_flags_active, sub_tvb, 0, 1, + ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_eigrp_metric_flags_repl, sub_tvb, 0, 1, + ENC_BIG_ENDIAN); + + offset += limit; + return(offset); } -static void dissect_eigrp_ip_int(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti) { - - guint8 ip_addr[4], length; - int addr_len, offset = 0; - proto_item *ti_prefixlen, *ti_dst; - - tvb_memcpy(tvb, ip_addr, 0, 4); - - proto_tree_add_item(tree, hf_eigrp_ip_int_nexthop, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_ip_int_delay, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_ip_int_bandwidth, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_ip_int_mtu, tvb, offset, 3, ENC_BIG_ENDIAN); - offset += 3; - proto_tree_add_item(tree, hf_eigrp_ip_int_hopcount, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_ip_int_reliability, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_ip_int_load, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_ip_int_reserved, tvb, offset, 2, ENC_BIG_ENDIAN); - offset += 2; +/** + *@fn int dissect_eigrp_ipv4_addr (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, + * packet_info *pinfo, int offset, int unreachable) + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * @param[in] pinfo general data about the protocol + * @param[in] offset current byte offset in packet being processed + * + * @return int number of bytes process + * + * @par + * Dissect all IPv4 address from offset though the end of the packet + */ +static int +dissect_eigrp_ipv4_addr (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, + packet_info *pinfo, int offset, int unreachable) +{ + guint8 ip_addr[4], length; + int addr_len; + proto_item *ti_prefixlen, *ti_dst; + int first = TRUE; + + for (; tvb_length_remaining(tvb, offset) > 0; offset += (1 + addr_len)) { + length = tvb_get_guint8(tvb, offset); + addr_len = ipv4_addr_and_mask(tvb, offset + 1, ip_addr, length); + + if (addr_len < 0) { + ti_prefixlen = proto_tree_add_item(tree, hf_eigrp_ipv4_prefixlen, + tvb, offset, 1, ENC_BIG_ENDIAN); + expert_add_info_format(pinfo, ti_prefixlen, PI_UNDECODED, PI_WARN, + "Invalid prefix length %u, must be <= 32", + length); + addr_len = 4; /* assure we can exit the loop */ + + } else { + proto_tree_add_item(tree, hf_eigrp_ipv4_prefixlen, tvb, offset, 1, + ENC_BIG_ENDIAN); + offset += 1; + ti_dst = proto_tree_add_text(tree, tvb, offset, addr_len, + "Destination: %s", ip_to_str(ip_addr)); + + /* add it to the top level line */ + proto_item_append_text(ti," %c %s/%u", first ? '=':',', + ip_to_str(ip_addr), length); + + if (unreachable) { + expert_add_info_format(pinfo, ti_dst, PI_RESPONSE_CODE, PI_NOTE, "Unreachable"); + } + } + first = FALSE; + } + return (offset); +} - for (offset = 20; tvb_length_remaining(tvb, offset) > 0; offset += (1 + addr_len)) { - length = tvb_get_guint8(tvb, offset); - addr_len = ipv4_addr_and_mask(tvb, offset + 1, ip_addr, length); - - if (addr_len < 0) { - ti_prefixlen = proto_tree_add_item(tree, hf_eigrp_ip_int_prefixlen, tvb, offset, 1, ENC_BIG_ENDIAN); - expert_add_info_format(pinfo, ti_prefixlen, PI_UNDECODED, PI_WARN, - "Invalid prefix length %u, must be <= 32", length); - addr_len = 4; /* assure we can exit the loop */ - } else { - proto_tree_add_item(tree, hf_eigrp_ip_int_prefixlen, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - ti_dst = proto_tree_add_text(tree, tvb, offset, addr_len, "Destination: %s", ip_to_str(ip_addr)); - proto_item_append_text (ti," %c %s/%u%s", offset == 21 ? '=':',', - ip_to_str(ip_addr), length, ((tvb_get_ntohl(tvb, 4 )== 0xffffffff) ? " - Destination unreachable":"")); - if (tvb_get_ntohl(tvb, 4) == 0xffffffff) { - expert_add_info_format(pinfo, ti_dst, PI_RESPONSE_CODE, PI_NOTE, "Destination unreachable"); - } - } +/** + *@fn int dissect_eigrp_ipv6_addr (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, + * packet_info *pinfo, int offset, int unreachable) + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * @param[in] pinfo general data about the protocol + * @param[in] offset current byte offset in packet being processed + * + * @return int number of bytes process + * + * @par + * Dissect all IPv6 address from offset though the end of the packet + */ +static int +dissect_eigrp_ipv6_addr (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, + packet_info *pinfo, int offset, int unreachable) +{ + guint8 length; + int addr_len; + struct e_in6_addr addr; + proto_item *ti_prefixlen, *ti_dst; + int first = TRUE; + + for (; tvb_length_remaining(tvb, offset) > 0; offset += (1 + addr_len)) { + length = tvb_get_guint8(tvb, offset); + addr_len = ipv6_addr_and_mask(tvb, offset + 1, &addr, length); + + if (addr_len < 0) { + ti_prefixlen = proto_tree_add_item(tree, hf_eigrp_ipv6_prefixlen, + tvb, offset, 1, ENC_BIG_ENDIAN); + expert_add_info_format(pinfo, ti_prefixlen, PI_UNDECODED, PI_WARN, + "Invalid prefix length %u, must be <= 128", + length); + addr_len = 16; /* assure we can exit the loop */ + } else { + proto_tree_add_item(tree, hf_eigrp_ipv6_prefixlen, tvb, offset, 1, + ENC_BIG_ENDIAN); + offset += 1; + + if ((length < 128) && (length % 8 == 0)) { + addr_len++; + } + + ti_dst = proto_tree_add_text(tree, tvb, offset, addr_len, + "Destination: %s", ip6_to_str(&addr)); + + /* add it to the top level line */ + proto_item_append_text(ti," %c %s/%u", first ? '=':',', + ip6_to_str(&addr), length); + + if (unreachable) { + expert_add_info_format(pinfo, ti_dst, PI_RESPONSE_CODE, PI_NOTE, "Unreachable"); + } } + first = FALSE; + } + return(offset); } -static void dissect_eigrp_ip_ext(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti) { +/** + *@fn int dissect_eigrp_ipx_addr (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, + * packet_info *pinfo, int offset, int unreachable) + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * @param[in] pinfo general data about the protocol + * @param[in] offset current byte offset in packet being processed + * + * @return int number of bytes process + * + * @par + * Dissect all IPX address from offset though the end of the packet + */ +static int +dissect_eigrp_ipx_addr (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, + packet_info *pinfo, int offset, int unreachable) +{ + proto_item *ti_dst; + + ti_dst = proto_tree_add_item(tree, hf_eigrp_ipx_dest, tvb, offset, 4, + ENC_BIG_ENDIAN); + + /* add it to the top level line */ + proto_item_append_text(ti," = %s", + ipxnet_to_string(tvb_get_ptr(tvb, offset, 4))); + + if (unreachable) { + expert_add_info_format(pinfo, ti_dst, PI_RESPONSE_CODE, PI_NOTE, + "Unreachable"); + } + + offset +=4; + return(offset); +} - guint8 ip_addr[4], length; - int addr_len, offset = 0; - proto_tree *eigrp_ip_ext_flags_tree; - proto_item *eigrp_ip_ext_ti, *ti_prefixlen, *ti_dst; +/** + *@fn int dissect_eigrp_service (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, + * packet_info *pinfo, int offset) + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * @param[in] pinfo general data about the protocol + * @param[in] ti protocol item + * @param[in] offset current byte offset in packet being processed + * + * @return int number of bytes process + * + * @par + * Dissect all SAF Services from offset though the end of the packet. The + * following represents the format of a SAF Service: + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Service | SubService | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | GUID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | GUID(cont) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | GUID(cont) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | GUID(cont) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Type | Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reachability AFI | Reachability Port | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reachability Protocol | Reachability Addr | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reachability Addr(cont) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reachability Addr(cont) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reachability Addr(cont) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reachability Addr(cont) | Sequence | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Sequence(cont) |\/\/\/ Service Data \/\/\/| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + */ +static int +dissect_eigrp_service (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, + packet_info *pinfo, int offset) +{ + int afi, length, remaining; + int sub_offset; + proto_item *sub_ti, *reach_ti; + proto_tree *sub_tree, *reach_tree; + tvbuff_t *sub_tvb, *reach_tvb; + guint16 service, sub_service; + + remaining = tvb_length_remaining(tvb, offset); + sub_ti = proto_tree_add_text(tree, tvb, offset, remaining, "SAF Service "); + sub_tree = proto_item_add_subtree(sub_ti, ett_eigrp_tlv_metric); + sub_tvb = tvb_new_subset(tvb, offset, remaining, -1); + sub_offset = 0; + + for (; tvb_length_remaining(sub_tvb, sub_offset) > 0; ) { + service = tvb_get_ntohs(sub_tvb, sub_offset); + proto_item_append_text(sub_ti, "%c %s", (sub_offset == 0 ? '=':','), + val_to_str(service, eigrp_saf_srv2string, "")); + + sub_service = tvb_get_ntohs(sub_tvb, sub_offset+2); + proto_item_append_text(ti, "%c %u:%u", (sub_offset == 0 ? '=':','), + service, sub_service); + + proto_tree_add_item(sub_tree, hf_eigrp_saf_service, sub_tvb, + sub_offset, 2, ENC_BIG_ENDIAN); + sub_offset += 2; + proto_tree_add_item(sub_tree, hf_eigrp_saf_subservice, sub_tvb, + sub_offset, 2, ENC_BIG_ENDIAN); + sub_offset += 2; + proto_tree_add_item(sub_tree, hf_eigrp_saf_guid, sub_tvb, + sub_offset, GUID_LEN, ENC_BIG_ENDIAN); + sub_offset += GUID_LEN; + + proto_tree_add_item(sub_tree, hf_eigrp_saf_data_type, sub_tvb, + sub_offset, 2, ENC_BIG_ENDIAN); + sub_offset += 2; + length = tvb_get_ntohs(sub_tvb, sub_offset); + proto_tree_add_item(sub_tree, hf_eigrp_saf_data_length, sub_tvb, + sub_offset, 2, ENC_BIG_ENDIAN); + sub_offset += 2; + + /* + * Reachability information + */ + reach_ti = proto_tree_add_text(sub_tree, sub_tvb, sub_offset, 22, + "Reachability"); + reach_tree = proto_item_add_subtree(reach_ti, ett_eigrp_saf_reachability); + reach_tvb = tvb_new_subset(sub_tvb, sub_offset, 22, -1); + + afi = tvb_get_ntohs(reach_tvb, 0); + proto_tree_add_item(reach_tree, hf_eigrp_saf_reachability_afi, + reach_tvb, 0, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(reach_tree, hf_eigrp_saf_reachability_port, + reach_tvb, 2, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(reach_tree, hf_eigrp_saf_reachability_protocol, + reach_tvb, 4, 2, ENC_BIG_ENDIAN); + + switch (afi) { + case EIGRP_AF_IPv4: + proto_tree_add_item(reach_tree, hf_eigrp_saf_reachability_addr_ipv4, + reach_tvb, 6, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(reach_tree, hf_eigrp_nullpad, reach_tvb, 10, 12, + ENC_BIG_ENDIAN); + break; + + case EIGRP_AF_IPv6: + proto_tree_add_item(reach_tree, hf_eigrp_saf_reachability_addr_ipv6, + reach_tvb, 6, 16, ENC_BIG_ENDIAN); + break; + default: + /* just print zeros... */ + proto_tree_add_item(reach_tree, hf_eigrp_saf_reachability_addr_hex, + reach_tvb, 6, 16, ENC_BIG_ENDIAN); + break; + } + sub_offset += 22; + + proto_tree_add_item(sub_tree, hf_eigrp_saf_data_sequence, sub_tvb, + sub_offset, 4, ENC_BIG_ENDIAN); + sub_offset += 4; + + if (length > 0) { + tvbuff_t *xml_tvb; + guint8 *test_string, *tok; + + /* + * Service-Data is usually (but not always) plain text, specifically + * XML. If it "looks like" XML (begins with optional white-space + * followed by a '<'), try XML. Otherwise, try plain-text. + */ + xml_tvb = tvb_new_subset(sub_tvb, sub_offset, length, length); + test_string = tvb_get_ephemeral_string(xml_tvb, 0, (length < 32 ? + length : 32)); + tok = strtok(test_string, " \t\r\n"); + + if (tok && tok[0] == '<') { + /* Looks like XML */ + dissector_try_string(media_type_table, "application/xml", + xml_tvb, pinfo, sub_tree); + } else { + /* Try plain text */ + dissector_try_string(media_type_table, "text/plain", + xml_tvb, pinfo, sub_tree); + } + } + sub_offset += length; + } - eigrp_ip_ext_ti = ti; + offset += sub_offset; + return(offset); +} - tvb_memcpy(tvb, ip_addr, 0, 4); - proto_tree_add_item(tree, hf_eigrp_ip_ext_nexthop, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - tvb_memcpy(tvb,ip_addr, 4, 4); - proto_tree_add_item(tree, hf_eigrp_ip_ext_origrouter, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_ip_ext_as, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_ip_ext_tag, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_ip_ext_metric, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_ip_ext_reserved, tvb, offset, 2, ENC_BIG_ENDIAN); - offset += 2; - proto_tree_add_item(tree, hf_eigrp_ip_ext_proto, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; +/** + *@fn int dissect_eigrp_legacy_metric (proto_tree *tree, tvbuff_t *tvb, int offset) + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * @param[in] offset current byte offset in packet being processed + * + * @return int number of bytes process + * + * @par + * Dissect the TLV Versions 1.2 (legacy) and 3.0 (deprecated) metric + * sections. The following represents the format + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Scaled Delay | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Scaled Bandwidth | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | MTU | Hopcount | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reliability | Load | Internal Tag | Flag | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + */ +static int +dissect_eigrp_legacy_metric (proto_tree *tree, tvbuff_t *tvb, int offset) +{ + proto_item *sub_ti; + proto_tree *sub_tree; + tvbuff_t *sub_tvb; + + sub_ti = proto_tree_add_text(tree, tvb, offset, 16, "Legacy Metric"); + sub_tree = proto_item_add_subtree(sub_ti, ett_eigrp_tlv_metric); + sub_tvb = tvb_new_subset(tvb, offset, 16, -1); + + proto_tree_add_item(sub_tree, hf_eigrp_legacy_metric_delay, sub_tvb, + 0, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_eigrp_legacy_metric_bw, sub_tvb, + 4, 4, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_eigrp_legacy_metric_mtu, sub_tvb, + 8, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_eigrp_legacy_metric_hopcount, sub_tvb, + 11, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_eigrp_legacy_metric_rel, sub_tvb, + 12, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_eigrp_legacy_metric_load, sub_tvb, + 13, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_eigrp_legacy_metric_intag, sub_tvb, + 14, 1, ENC_BIG_ENDIAN); + + /* Decode the route flags field */ + dissect_eigrp_metric_flags(sub_tree, sub_tvb, 15, 1); + + offset += 16; + return(offset); +} -/* Decode the IP external route Flags Field */ - ti = proto_tree_add_item(tree, hf_eigrp_ip_ext_flags, tvb, offset, 1, ENC_BIG_ENDIAN); - eigrp_ip_ext_flags_tree = proto_item_add_subtree(ti, ett_eigrp_ip_ext_flags); +/** + *@fn int dissect_eigrp_ipx_extdata (proto_tree *tree, tvbuff_t *tvb, int offset) + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * @param[in] offset current byte offset in packet being processed + * + * @return int number of bytes process + * + * @par + * Dissect the IPX External data for the TLV versions 1.2 and 3.0. + * The following represents the format + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ext RouterID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ext Router ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ext Autonomous System Number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Route Tag | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ext Protocol | Ext Flags | External Metric | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | External Delay | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +static int +dissect_eigrp_ipx_extdata (proto_tree *tree, tvbuff_t *tvb, int offset) +{ + proto_item *sub_ti; + proto_tree *sub_tree; + tvbuff_t *sub_tvb; + int sub_offset = 0; + + sub_ti = proto_tree_add_text(tree, tvb, offset, 20, "External Data"); + sub_tree = proto_item_add_subtree(sub_ti, ett_eigrp_tlv_extdata); + sub_tvb = tvb_new_subset(tvb, offset, 20, -1); + + /* Decode the external route source info */ + proto_tree_add_item(sub_tree, hf_eigrp_ipx_extdata_routerid, sub_tvb, + sub_offset, 6, ENC_BIG_ENDIAN); + sub_offset += 6; + proto_tree_add_item(sub_tree, hf_eigrp_extdata_as, sub_tvb, + sub_offset, 4, ENC_BIG_ENDIAN); + sub_offset += 4; + proto_tree_add_item(sub_tree, hf_eigrp_extdata_tag, sub_tvb, + sub_offset, 4, ENC_BIG_ENDIAN); + sub_offset += 4; + proto_tree_add_item(sub_tree, hf_eigrp_extdata_proto, sub_tvb, + sub_offset, 1, ENC_BIG_ENDIAN); + sub_offset += 1; + + /* Decode the external route flags */ + dissect_eigrp_extdata_flags(sub_tree, sub_tvb, sub_offset); + sub_offset += 1; + + /* and the rest of it... */ + proto_tree_add_item(sub_tree, hf_eigrp_ipx_extdata_metric, + sub_tvb, sub_offset, 2, ENC_BIG_ENDIAN); + sub_offset += 2; + proto_tree_add_item(sub_tree, hf_eigrp_ipx_extdata_delay, + sub_tvb, sub_offset, 2, ENC_BIG_ENDIAN); + sub_offset += 2; + + offset += sub_offset; + return(offset); +} - proto_tree_add_item(eigrp_ip_ext_flags_tree, hf_eigrp_ip_ext_flags_ext, tvb, offset, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(eigrp_ip_ext_flags_tree, hf_eigrp_ip_ext_flags_default, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; -/* End Decode the IP external route Flags Field */ +/** + *@fn int dissect_eigrp_extdata (proto_tree *tree, tvbuff_t *tvb, int offset) + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * @param[in] offset current byte offset in packet being processed + * + * @return int number of bytes process + * + * @par + * Dissect the external route data for TLV versions 1.2 and 3.0 for all + * protocols except IPX. The following represents the format + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ext Router ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ext Autonomous System Number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Route Tag | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | External Metric | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reserved | Ext Protocol | Ext Flags | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +static int +dissect_eigrp_extdata (proto_tree *tree, tvbuff_t *tvb, int offset) +{ + proto_item *sub_ti; + proto_tree *sub_tree; + tvbuff_t *sub_tvb; + int sub_offset = 0; + + sub_ti = proto_tree_add_text(tree, tvb, offset, 20, "External Data"); + sub_tree = proto_item_add_subtree(sub_ti, ett_eigrp_tlv_extdata); + sub_tvb = tvb_new_subset(tvb, offset, 20, -1); + + /* Decode the external route source info */ + proto_tree_add_item(sub_tree, hf_eigrp_extdata_origrid, sub_tvb, + sub_offset, 4, ENC_BIG_ENDIAN); + sub_offset += 4; + proto_tree_add_item(sub_tree, hf_eigrp_extdata_as, sub_tvb, + sub_offset, 4, ENC_BIG_ENDIAN); + sub_offset += 4; + proto_tree_add_item(sub_tree, hf_eigrp_extdata_tag, sub_tvb, + sub_offset, 4, ENC_BIG_ENDIAN); + sub_offset += 4; + proto_tree_add_item(sub_tree, hf_eigrp_extdata_metric, sub_tvb, + sub_offset, 4, ENC_BIG_ENDIAN); + sub_offset += 4; + proto_tree_add_item(sub_tree, hf_eigrp_extdata_reserved, sub_tvb, + sub_offset, 2, ENC_BIG_ENDIAN); + sub_offset += 2; + proto_tree_add_item(sub_tree, hf_eigrp_extdata_proto, sub_tvb, + sub_offset, 1, ENC_BIG_ENDIAN); + sub_offset += 1; + + /* Decode the external route flags */ + dissect_eigrp_extdata_flags(sub_tree, sub_tvb, sub_offset); + sub_offset += 1; + + offset += sub_offset; + return(offset); +} - proto_tree_add_item(tree, hf_eigrp_ip_ext_delay, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_ip_ext_bandwidth, tvb, offset, 4, ENC_BIG_ENDIAN); +/** + *@fn int dissect_eigrp_nexthop (proto_tree *tree, tvbuff_t *tvb, guint16 afi, int offset) + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * @param[in] afi IANA address family indicator + * @param[in] offset current byte offset in packet being processed + * + * @return int number of bytes process + * + * @par + * Dissect the next hop field which is in the "route TLVs". This function will + * handle all the various protocol AFIs and return the appropriate number of + * bytes processed + */ +static int +dissect_eigrp_nexthop (proto_tree *tree, tvbuff_t *tvb, guint16 afi, int offset) +{ + /* dissect dest information */ + switch (afi) { + case EIGRP_SF_IPv4: + case EIGRP_AF_IPv4: + proto_tree_add_item(tree, hf_eigrp_ipv4_nexthop, tvb, offset, 4, + ENC_BIG_ENDIAN); offset += 4; - proto_tree_add_item(tree, hf_eigrp_ip_ext_mtu, tvb, offset, 3, ENC_BIG_ENDIAN); - offset += 3; - proto_tree_add_item(tree, hf_eigrp_ip_ext_hopcount, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_ip_ext_reliability, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_ip_ext_load, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_ip_ext_reserved2, tvb, offset, 2, ENC_BIG_ENDIAN); - offset += 2; - - for (offset = 40; tvb_length_remaining(tvb, offset) > 0; offset += (1 + addr_len)) { - length = tvb_get_guint8(tvb, offset); - addr_len = ipv4_addr_and_mask(tvb, offset + 1, ip_addr, length); - - if (addr_len < 0) { - ti_prefixlen = proto_tree_add_item(tree, hf_eigrp_ip_ext_prefixlen, tvb, offset, 1, ENC_BIG_ENDIAN); - expert_add_info_format(pinfo, ti_prefixlen, PI_UNDECODED, PI_WARN, - "Invalid prefix length %u, must be <= 32", length); - addr_len = 4; /* assure we can exit the loop */ - } else { - proto_tree_add_item(tree, hf_eigrp_ip_ext_prefixlen, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - ti_dst = proto_tree_add_text(tree, tvb, offset, addr_len, "Destination = %s", ip_to_str(ip_addr)); - proto_item_append_text(eigrp_ip_ext_ti, " %c %s/%u%s", offset == 41 ? '=':',', - ip_to_str(ip_addr), length, ((tvb_get_ntohl(tvb, 24) == 0xffffffff) ? " - Destination unreachable":"")); - if (tvb_get_ntohl(tvb, 24) == 0xffffffff) { - expert_add_info_format(pinfo, ti_dst, PI_RESPONSE_CODE, PI_NOTE, "Destination unreachable"); - } - } - } -} + break; + case EIGRP_SF_IPv6: + case EIGRP_AF_IPv6: + proto_tree_add_item(tree, hf_eigrp_ipv6_nexthop, tvb, offset, 16, + ENC_BIG_ENDIAN); + offset += 16; + break; + case EIGRP_AF_IPX: + proto_tree_add_item(tree, hf_eigrp_ipx_nexthop_net, tvb, offset, 4, + ENC_BIG_ENDIAN); + offset += 4; + proto_tree_add_item(tree, hf_eigrp_ipx_nexthop_host, tvb, offset, 6, + ENC_BIG_ENDIAN); + offset += 6; + break; -static void dissect_eigrp_ipx_int(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti) { + case EIGRP_SF_COMMON: + break; - int offset = 0; - proto_item *ti_dst; + default: + break; + } - proto_tree_add_item(tree, hf_eigrp_ipx_int_nexthop_addr, tvb, offset, 4, ENC_NA); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_ipx_int_nexthop_id, tvb, offset, 6, FALSE); - offset += 6; - proto_tree_add_item(tree, hf_eigrp_ipx_int_delay, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_ipx_int_bandwidth, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_ipx_int_mtu, tvb, offset, 3, ENC_BIG_ENDIAN); - offset += 3; - proto_tree_add_item(tree, hf_eigrp_ipx_int_hopcount, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_ipx_int_reliability, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_ipx_int_load, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_ipx_int_reserved, tvb, offset, 2, ENC_BIG_ENDIAN); - offset += 2; - ti_dst = proto_tree_add_item(tree, hf_eigrp_ipx_int_dst, tvb, offset, 4, ENC_NA); - proto_item_append_text(ti, " = %08x%s", tvb_get_ntohl(tvb, 26), ((tvb_get_ntohl(tvb, 10) == 0xffffffff) ? " - Destination unreachable":"")); - if (tvb_get_ntohl(tvb, 10) == 0xffffffff) { - expert_add_info_format(pinfo, ti_dst, PI_RESPONSE_CODE, PI_NOTE, "Destination unreachable"); - } + return(offset); } -static void dissect_eigrp_ipx_ext(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti) { +/** + *@fn void dissect_eigrp_general_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, + * packet_info *pinfo, guint16 tlv) + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * @param[in] pinfo general data about the protocol + * @param[in] ti protocol item + * @param[in] tlv Specific TLV in to be dissected + * @param[out] None + * + * @return void + * + * @par + * General EIGRP parameters carry EIGRP management information and are not + * specific to any one routed protocol. + * + */ +static void +dissect_eigrp_general_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, + packet_info *pinfo, guint16 tlv) +{ + switch (tlv) { + case EIGRP_TLV_PARAMETER: + dissect_eigrp_parameter(tree, tvb, pinfo, ti); + break; + case EIGRP_TLV_AUTH: + dissect_eigrp_auth_tlv(tree, tvb, pinfo, ti); + break; + case EIGRP_TLV_SEQ: + dissect_eigrp_seq_tlv(tree, tvb, pinfo); + break; + case EIGRP_TLV_SW_VERSION: + dissect_eigrp_sw_version(tvb, tree, ti); + break; + case EIGRP_TLV_NEXT_MCAST_SEQ: + dissect_eigrp_next_mcast_seq(tvb, tree, ti); + break; + case EIGRP_TLV_PEER_STUBINFO: + dissect_eigrp_peer_stubinfo(tvb, tree); + break; + case EIGRP_TLV_PEER_TERMINATION: + dissect_eigrp_peer_termination(pinfo, ti); + break; + case EIGRP_TLV_PEER_TIDLIST: + dissect_eigrp_peer_tidlist(tree, tvb); + break; + default: + expert_add_info_format(pinfo, ti, PI_UNDECODED, PI_WARN, + "Unknown Generic TLV (0x%04x)", tlv); + break; + } +} - int offset = 0; - proto_item *ti_dst; +/** + *@fn void dissect_eigrp_ipv4_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, + * packet_info *pinfo, guint16 tlv) + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * @param[in] pinfo general data about the protocol + * @param[in] tlv Specific TLV in to be dissected + * + * @return void + * + * @par + * Dissect the Legacy IPv4 route TLV; handles both the internal and external + * TLV types; This packet format is being deprecated and replaced with the + * Multi-Protocol packet formats as of EIGRP Release-8. This TLV format is used + * to maintain backward compatibility between older version so EIGRP, "MTR" + * EIGRP, and current shipping code. + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | IPv4 Nexthop | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Scaled Delay | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Scaled Bandwidth | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | MTU | Hopcount | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reliability | Load | Internal Tag | Flag | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +static void +dissect_eigrp_ipv4_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, + packet_info *pinfo, guint16 tlv) +{ + int offset = 0; + int unreachable = FALSE; + + proto_tree_add_item(tree, hf_eigrp_ipv4_nexthop, tvb, offset, 4, + ENC_BIG_ENDIAN); + offset += 4; + + /* dissect external data if needed */ + if ((tlv & EIGRP_TLV_TYPEMASK) == EIGRP_TLV_EXTERNAL) { + offset = dissect_eigrp_extdata(tree, tvb, offset); + } + + /* dissect the metric */ + offset = dissect_eigrp_legacy_metric(tree, tvb, offset); + + /* dissect addresses */ + offset = dissect_eigrp_ipv4_addr(ti, tree, tvb, pinfo, offset, unreachable); +} - proto_tree_add_item(tree, hf_eigrp_ipx_ext_nexthop_addr, tvb, offset, 4, ENC_NA); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_ipx_ext_nexthop_id, tvb, offset, 6, FALSE); - offset += 6; - proto_tree_add_item(tree, hf_eigrp_ipx_ext_origrouter, tvb, offset, 6, FALSE); - offset += 6; - proto_tree_add_item(tree, hf_eigrp_ipx_ext_as, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_ipx_ext_tag, tvb, offset, 4, ENC_BIG_ENDIAN); +/** + *@fn void dissect_eigrp_atalk_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, + * proto_item *ti, guint16 tlv) + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * @param[in] pinfo general data about the protocol + * @param[in] tlv Specific TLV in to be dissected + * + * @return void + * + * @par + * Dissect the legacy AppleTalk route TLV; handles both the internal and external + * TLV type. The following represents the format + */ +static void +dissect_eigrp_atalk_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, + guint16 tlv) +{ + int offset = 0; + + /* cable tlv? */ + if ((tlv & EIGRP_TLV_TYPEMASK) == EIGRP_TLV_AT_CBL) { + proto_tree_add_text(tree, tvb, 0, 4, "AppleTalk Cable Range = %u-%u", + tvb_get_ntohs(tvb, 0), tvb_get_ntohs(tvb, 2)); + proto_tree_add_item(tree, hf_eigrp_atalk_routerid, tvb, 4, 4, + ENC_BIG_ENDIAN); + proto_item_append_text(ti, ": Cable range= %u-%u, Router ID= %u", + tvb_get_ntohs(tvb, 0), tvb_get_ntohs(tvb, 2), + tvb_get_ntohl(tvb, 4)); + + } else { + proto_tree_add_text(tree, tvb, offset, 4, "NextHop Address = %u.%u", + tvb_get_ntohs(tvb, 0), tvb_get_ntohs(tvb, 2)); offset += 4; - proto_tree_add_item(tree, hf_eigrp_ipx_ext_proto, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_ipx_ext_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_ipx_ext_metric, tvb, offset, 2, ENC_BIG_ENDIAN); - offset += 2; - proto_tree_add_item(tree, hf_eigrp_ipx_ext_extdelay, tvb, offset, 2, ENC_BIG_ENDIAN); - offset += 2; - proto_tree_add_item(tree, hf_eigrp_ipx_ext_delay, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_ipx_ext_bandwidth, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_ipx_ext_mtu, tvb, offset, 3, ENC_BIG_ENDIAN); - offset += 3; - proto_tree_add_item(tree, hf_eigrp_ipx_ext_hopcount, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_ipx_ext_reliability, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_ipx_ext_load, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_ipx_ext_reserved2, tvb, offset, 2, ENC_BIG_ENDIAN); - offset += 2; - ti_dst = proto_tree_add_item(tree, hf_eigrp_ipx_ext_dst, tvb, offset, 4, ENC_NA); - proto_item_append_text(ti, " = %08x%s", tvb_get_ntohl(tvb, 46), ((tvb_get_ntohl(tvb, 30) == 0xffffffff) ? " - Destination unreachable":"")); - if (tvb_get_ntohl(tvb, 30) == 0xffffffff) { - expert_add_info_format(pinfo, ti_dst, PI_RESPONSE_CODE, PI_NOTE, "Destination unreachable"); + /* dissect external data if needed */ + if ((tlv & EIGRP_TLV_TYPEMASK) == EIGRP_TLV_EXTERNAL) { + offset = dissect_eigrp_extdata(tree, tvb,offset); } -} + /* dissect the metric */ + offset = dissect_eigrp_legacy_metric(tree, tvb, offset); + /* dissect cable range */ + proto_tree_add_text(tree, tvb, offset, 4, "Cable range = %u-%u", + tvb_get_ntohs(tvb, 36), tvb_get_ntohs(tvb, 38)); + proto_item_append_text(ti, ": %u-%u", + tvb_get_ntohs(tvb, 36), tvb_get_ntohs(tvb, 38)); + } + return; +} -static void dissect_eigrp_at_cbl(tvbuff_t *tvb, proto_tree *tree, proto_item *ti) { +/** + *@fn void dissect_eigrp_ipv6_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, + * packet_info *pinfo, guint16 tlv) + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * @param[in] pinfo general data about the protocol + * @param[in] tlv Specific TLV in to be dissected + * + * @return void + * + * @par + * Dissect the Legacy IPv6 route TLV; handles both the internal and external + * TLV types; This packet format is being deprecated and replaced with the + * Multi-Protocol packet formats as of EIGRP Release-8. This TLV format is used + * to maintain backward compatibility between older version so EIGRP, "MTR" + * EIGRP, and current shipping code. + */ +static void +dissect_eigrp_ipv6_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, + packet_info *pinfo, guint16 tlv) +{ + int offset = 0; + int unreachable = FALSE; + + proto_tree_add_item(tree, hf_eigrp_ipv6_nexthop, tvb, offset, 16, + ENC_BIG_ENDIAN); + offset += 16; + + /* dissect external data if needed */ + if ((tlv & EIGRP_TLV_TYPEMASK) == EIGRP_TLV_EXTERNAL) { + offset = dissect_eigrp_extdata(tree, tvb, offset); + } + + /* dissect the metric */ + offset = dissect_eigrp_legacy_metric(tree, tvb, offset); + + /* dissect addresses */ + dissect_eigrp_ipv6_addr(ti, tree, tvb, pinfo, offset, unreachable); + return; +} - proto_tree_add_text(tree, tvb, 0, 4, "AppleTalk Cable Range = %u-%u", tvb_get_ntohs(tvb, 0), tvb_get_ntohs(tvb, 2)); - proto_tree_add_item(tree, hf_eigrp_at_cbl_routerid, tvb, 4, 4, ENC_BIG_ENDIAN); - proto_item_append_text(ti, ": Cable range= %u-%u, Router ID= %u", tvb_get_ntohs(tvb, 0), tvb_get_ntohs(tvb, 2), tvb_get_ntohl(tvb, 4)); +/** + *@fn void dissect_eigrp_ipx_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, + * packet_info *pinfo, guint16 tlv) + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * @param[in] pinfo general data about the protocol + * @param[in] tlv Specific TLV in to be dissected + * + * @return void + * + * @par + * Dissect the legacy IPX route TLV; handles both the internal and external + * TLV type. The following represents the format + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Nexthop Net | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Nexthop Host | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Nexthop Host(cont) | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Optional External Data: + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ext RouterID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ext Router ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ext Autonomous System Number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Route Tag | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ext Protocol | Ext Flags | External Metric | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | External Delay | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Scaled Delay | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Scaled Delay | Scaled Bandwidth | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Scaled Bandwidth | MTU | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | MTU(cont) | Hopcount | Reliability | Load | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Internal Tag | Flag | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * + */ +static void +dissect_eigrp_ipx_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, + packet_info *pinfo, guint16 tlv) +{ + int offset = 0; + int unreachable = FALSE; + + /* nexthop for route... */ + offset = dissect_eigrp_nexthop(tree, tvb, EIGRP_AF_IPX, offset); + + /* dissect external data if needed */ + if ((tlv & EIGRP_TLV_TYPEMASK) == EIGRP_TLV_EXTERNAL) { + offset = dissect_eigrp_ipx_extdata(tree, tvb, offset); + } + + /* dissect the metric */ + offset = dissect_eigrp_legacy_metric(tree, tvb, offset); + + /* dissect addresses */ + offset = dissect_eigrp_ipx_addr(ti, tree, tvb, pinfo, offset, unreachable); +} +/** + *@fn void dissect_eigrp_ipv4_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, + * packet_info *pinfo, proto_item *ti, guint16 tlv) + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * @param[in] pinfo general data about the protocol + * @param[in] ti protocol item + * @param[in] tlv Specific TLV in to be dissected + * + * @return void + * + * @par + * Dissect the Multi-Topology route TLV; This packet format has been deprecated + * and replaced with the Multi-Protocol packet formats as of EIGRP Release-8. Of + * course this means it will be around for a long long while. The following + * represents the format + * + * 1 2 3 0 1 1 + * 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Topology Identifier | Family Identifier | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Router ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Route Tag | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Scaled Delay | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Scaled Bandwidth | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | MTU | Hopcount | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reliability | Load | Internal Tag | Flag | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |\/\/\/ NextHop (Family Specific Length) \/\/\/| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |\/\/\/ External Route Data (Optional) \/\/\/| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |\/\/\/ Destination (Family Specific Length) \/\/\/| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + */ +static void +dissect_eigrp_multi_topology_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, + packet_info *pinfo, guint16 tlv) +{ + proto_item *sub_ti; + guint16 afi; + int offset = 2; + int unreachable = FALSE; + + /* tid for you */ + proto_tree_add_item(tree, hf_eigrp_tid, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + /* now its all about the family */ + afi = tvb_get_ntohs(tvb, offset); + proto_tree_add_item(tree, hf_eigrp_afi, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + /* gota have an id... */ + proto_tree_add_item(tree, hf_eigrp_routerid, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + + /* tag.. your it! */ + proto_tree_add_item(tree, hf_eigrp_legacy_metric_tag, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + + /* dissect the metric */ + offset = dissect_eigrp_legacy_metric(tree, tvb, offset); + + /* dissect nexthop */ + offset = dissect_eigrp_nexthop(tree, tvb, afi, offset); + + /* dissect external data if needed */ + if ((tlv & EIGRP_TLV_TYPEMASK) == EIGRP_TLV_EXTERNAL) { + if (afi == EIGRP_AF_IPX) { + offset = dissect_eigrp_ipx_extdata(tree, tvb, offset); + } else { + offset = dissect_eigrp_extdata(tree, tvb, offset); + } + } + + /* dissect dest information */ + switch (afi) { + case EIGRP_AF_IPv4: + offset = dissect_eigrp_ipv4_addr(ti, tree, tvb, pinfo, offset, unreachable); + break; + case EIGRP_AF_IPv6: + offset = dissect_eigrp_ipv6_addr(ti, tree, tvb, pinfo, offset, unreachable); + break; + case EIGRP_AF_IPX: + offset = dissect_eigrp_ipx_addr(ti, tree, tvb, pinfo, offset, unreachable); + break; + + case EIGRP_SF_COMMON: + case EIGRP_SF_IPv4: + case EIGRP_SF_IPv6: + offset = dissect_eigrp_service(ti, tree, tvb, pinfo, offset); + break; + + default: + sub_ti = proto_tree_add_text(tree, tvb, offset, -1, "Unknown AFI"); + expert_add_info_format(pinfo, sub_ti, PI_MALFORMED, PI_ERROR, "Unknown AFI"); + } + + return; } -static void dissect_eigrp_at_int(tvbuff_t *tvb, proto_tree *tree, proto_item *ti) { +/** + *@fn int dissect_eigrp_metric_comm (proto_tree *tree, tvbuff_t *tvb, int offset, int limit) + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * @param[in] offset current byte offset in packet being processed + * @param[in] limit maximum number of bytes which can be process + * + * @return int number of bytes process + * + * @par + * Dissect extended community attached to metric TLVs to support VPNv4 + * deployments, The following represents the format + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Type high | Type low(*) | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Value | + * | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +static int +dissect_eigrp_metric_comm (proto_tree *tree, tvbuff_t *tvb, int offset, int limit) +{ + int comm_type; + + while (limit > 0) { + comm_type = tvb_get_ntohs(tvb, offset); + offset++; + + switch (comm_type) { + /* + * Tag for this route. It is present for all EIGRP VPNv4 + * routes, internal and external + */ + case EIGRP_EXTCOMM_EIGRP: + proto_tree_add_text(tree, tvb, offset, 8, + "Type(EIGRP_EXTCOMM_EIGRP): Flag(0x%02x) Tag(%u)", + tvb_get_ntohs(tvb, 0), + tvb_get_ntohl(tvb, 2)); + break; + case EIGRP_EXTCOMM_VRR: + proto_tree_add_text(tree, tvb, offset, 8, + "Type(EIGRP_EXTCOMM_VRR)): RES(0x%02x) RID(0x%04x)", + tvb_get_ntohs(tvb, 0), + tvb_get_ntohl(tvb, 2)); + break; + + /* + * Vecmetric information for given EIGRP VPNv4 route, + * applies to both internal and external + */ + case EIGRP_EXTCOMM_DAD: + proto_tree_add_text(tree, tvb, offset, 8, + "Type(EIGRP_EXTCOMM_DAD): AS(%u):SDLY(%u)", + tvb_get_ntohs(tvb, 0), + tvb_get_ntohl(tvb, 2)); + break; + case EIGRP_EXTCOMM_VRHB: + proto_tree_add_text(tree, tvb, offset, 8, + "Type(EIGRP_EXTCOMM_VRHB): REL(%u) HOP(%u) SBW(%u)", + tvb_get_guint8(tvb, 0), + tvb_get_guint8(tvb, 1), + tvb_get_ntohl(tvb, 2)); + break; + case EIGRP_EXTCOMM_SRLM: + proto_tree_add_text(tree, tvb, offset, 8, + "Type(EIGRP_EXTCOMM_SRLM): RES(%u) LOAD(%u) MTU(%u)", + tvb_get_guint8(tvb, 0), + tvb_get_guint8(tvb, 1), + tvb_get_ntohl(tvb, 2)); + break; + + /* + * External information for given EIGRP VPNv4 route, + * applies to only to external routes + */ + case EIGRP_EXTCOMM_SAR: + proto_tree_add_text(tree, tvb, offset, 8, + "Type(EIGRP_EXTCOMM_SAR): xAS(%u) xRID(%u)", + tvb_get_ntohs(tvb, 0), + tvb_get_ntohl(tvb, 2)); + break; + case EIGRP_EXTCOMM_RPM: + proto_tree_add_text(tree, tvb, offset, 8, + "Type(EIGRP_EXTCOMM_RPM): xProto(%u) xMETRIC(%u)", + tvb_get_ntohs(tvb, 0), + tvb_get_ntohl(tvb, 2)); + break; + + case EIGRP_EXTCOMM_SOO_ASFMT: + case EIGRP_EXTCOMM_SOO_ADRFMT: + proto_tree_add_text(tree, tvb, offset, 8, + "Type(EIGRP_EXTCOMM_SOO): AS(%u) TAG(%u)", + tvb_get_ntohs(tvb, 0), + tvb_get_ntohl(tvb, 2)); + break; + } - int offset = 0; + /*on to the next */ + offset += 8; + limit -= 8; - proto_tree_add_text(tree, tvb, offset, 4, "Next Hop Address = %u.%u", tvb_get_ntohs(tvb, 0), tvb_get_ntohs(tvb, 2)); - offset += 4; + if (0 != limit%8) { + break; + } - proto_tree_add_item(tree, hf_eigrp_at_int_delay, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_at_int_bandwidth, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_at_int_mtu, tvb, offset, 3, ENC_BIG_ENDIAN); - offset += 3; - proto_tree_add_item(tree, hf_eigrp_at_int_hopcount, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_at_int_reliability, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_at_int_load, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_at_int_reserved, tvb, offset, 2, ENC_BIG_ENDIAN); - offset += 2; - proto_tree_add_text(tree,tvb,offset,4,"Cable range = %u-%u",tvb_get_ntohs(tvb,20),tvb_get_ntohs(tvb,22)); + } - proto_item_append_text(ti, ": %u-%u", tvb_get_ntohs(tvb, 20), tvb_get_ntohs(tvb, 22)); + return(offset); } -static void dissect_eigrp_at_ext(tvbuff_t *tvb, proto_tree *tree, proto_item *ti) { +/** + *@fn int dissect_eigrp_wide_metric_attr (proto_tree *tree, tvbuff_t *tvb, + * int offset, int limit) + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * @param[in] offset current byte offset in packet being processed + * @param[in] limit maximum number of words which should be process + * + * @return int number of bytes process + * + * @par + * Dissect the Metric Attributes which (optionally) are part of the wide-metric + * route TLV. Some of the attributes which effect the metric is controlled by + * K6 which is now part of the Parameter TLV. Also, eh extended community TLV is + * no longer used, as its now append to the route + */ +static int +dissect_eigrp_wide_metric_attr (proto_tree *tree, tvbuff_t *tvb, + int offset, int limit) +{ + proto_item *sub_ti; + proto_tree *sub_tree; + tvbuff_t *sub_tvb; + int sub_offset; + + gint8 attr_offset = 0; + gint8 attr_opcode = 0; + + limit *= 2; /* words to bytes */ + + sub_ti = proto_tree_add_text(tree, tvb, offset, limit, "Attributes"); + sub_tree = proto_item_add_subtree(sub_ti, ett_eigrp_tlv_attr); + sub_tvb = tvb_new_subset(tvb, offset, limit, -1); + sub_offset = 0; + + while (limit > 0) { + attr_opcode = tvb_get_guint8(sub_tvb, sub_offset); + proto_tree_add_item(sub_tree, hf_eigrp_attr_opcode, sub_tvb, + sub_offset, 1, ENC_BIG_ENDIAN); + sub_offset += 1; + + attr_offset = tvb_get_guint8(sub_tvb, sub_offset) * 2; + proto_tree_add_item(sub_tree, hf_eigrp_attr_offset, sub_tvb, + sub_offset, 1, ENC_BIG_ENDIAN); + sub_offset += 1; + + switch (attr_opcode) { + case EIGRP_ATTR_NOOP: + break; + + case EIGRP_ATTR_SCALED: + proto_tree_add_item(sub_tree, hf_eigrp_attr_scaled, sub_tvb, + sub_offset, 4, ENC_BIG_ENDIAN); + break; + + case EIGRP_ATTR_TAG: + proto_tree_add_item(sub_tree, hf_eigrp_attr_tag, sub_tvb, + sub_offset, 4, ENC_BIG_ENDIAN); + break; + + case EIGRP_ATTR_COMM: + dissect_eigrp_metric_comm(sub_tree, + tvb_new_subset(sub_tvb, sub_offset, 8, -1), + sub_offset, limit); + break; + + case EIGRP_ATTR_JITTER: + proto_tree_add_item(sub_tree, hf_eigrp_attr_jitter, sub_tvb, + sub_offset, 4, ENC_BIG_ENDIAN); + break; + + case EIGRP_ATTR_QENERGY: + proto_tree_add_item(sub_tree, hf_eigrp_attr_qenergy, sub_tvb, + sub_offset, 4, ENC_BIG_ENDIAN); + break; + + case EIGRP_ATTR_ENERGY: + proto_tree_add_item(sub_tree, hf_eigrp_attr_energy, sub_tvb, + sub_offset, 4, ENC_BIG_ENDIAN); + break; + + default: + break; + } + sub_offset += attr_offset; + limit -= (EIGRP_ATTR_HDRLEN + attr_offset); + } - int offset = 0; - proto_tree *eigrp_at_ext_flags_tree; + offset += sub_offset; + return(offset); +} - proto_tree_add_text(tree, tvb, offset, 4, "Next Hop Address = %u.%u", tvb_get_ntohs(tvb, 0), tvb_get_ntohs(tvb, 2)); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_at_ext_origrouter, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_at_ext_as, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_at_ext_tag, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_at_ext_proto, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; +/** + *@fn int dissect_eigrp_wide_metric (proto_tree *tree, tvbuff_t *tvb, int offset) + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * @param[in] offset current byte offset in packet being processed + * + * @return int number of bytes process + * + * @par + * Dissect the latest-n-greatest "Wide"Metric" definition for EIGRP. This + * definition was created to address the higher speed links and should handle + * things until we break the speed of light *wink* + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Offset | Priority | Reliability | Load | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | MTU | Hopcount | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Delay | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Delay | Bandwidth | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Bandwidth | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reserved | Flags | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |\/\/\/ Extended Metrics (Variable Length) \/\/\/| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + */ +static int +dissect_eigrp_wide_metric (proto_tree *tree, tvbuff_t *tvb, int offset) +{ + proto_item *sub_ti; + proto_tree *sub_tree; + tvbuff_t *sub_tvb; + gint8 attr_size = 0; + unsigned long long big_num; + + sub_ti = proto_tree_add_text(tree, tvb, offset, 24, "Wide Metric"); + sub_tree = proto_item_add_subtree(sub_ti, ett_eigrp_tlv_metric); + sub_tvb = tvb_new_subset(tvb, offset, 24, -1); + + attr_size = tvb_get_guint8(sub_tvb, 0); + + proto_tree_add_item(sub_tree, hf_eigrp_metric_offset, + sub_tvb, 0, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_eigrp_metric_priority, + sub_tvb, 1, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_eigrp_metric_rel, + sub_tvb, 2, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_eigrp_metric_load, + sub_tvb, 3, 1, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_eigrp_metric_mtu, + sub_tvb, 4, 3, ENC_BIG_ENDIAN); + proto_tree_add_item(sub_tree, hf_eigrp_metric_hopcount, + sub_tvb, 7, 1, ENC_BIG_ENDIAN); + + big_num = tvb_get_ntoh64(sub_tvb, 8); + big_num >>= 16; + if (big_num == G_GINT64_CONSTANT(0x0000ffffffffffffU)) { + proto_tree_add_text(sub_tree, sub_tvb, 8, 6, "Delay: Infinity"); + } else { + proto_tree_add_text(sub_tree, sub_tvb, 8, 6, "Delay: %" G_GINT64_MODIFIER "u", big_num); + } + + big_num = tvb_get_ntoh64(sub_tvb, 14); + big_num >>= 16; + if (big_num == G_GINT64_CONSTANT(0x0000ffffffffffffU)) { + proto_tree_add_text(sub_tree, sub_tvb, 14, 6, "Bandwidth: Infinity"); + } else { + proto_tree_add_text(sub_tree, sub_tvb, 14, 6, "Bandwidth: %" G_GINT64_MODIFIER "u", big_num); + } + proto_tree_add_item(sub_tree, hf_eigrp_metric_reserved, sub_tvb, 20, 2, + ENC_BIG_ENDIAN); + + /* Decode the route flags field */ + dissect_eigrp_metric_flags(sub_tree, sub_tvb, 22, 2); + offset += 24; + + /* any extended metric attributes? */ + if (attr_size > 0) { + offset = dissect_eigrp_wide_metric_attr(tree, tvb, offset, attr_size); + } + + return(offset); +} -/* Decode the AppleTalk external route Flags Field */ - ti = proto_tree_add_item(tree, hf_eigrp_at_ext_flags, tvb, offset, 1, ENC_BIG_ENDIAN); - eigrp_at_ext_flags_tree = proto_item_add_subtree(ti, ett_eigrp_at_ext_flags); +/** + *@fn void dissect_eigrp_multi_protocol_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, + * packet_info *pinfo, guint16 tlv) - proto_tree_add_item(eigrp_at_ext_flags_tree, hf_eigrp_at_ext_flags_ext, tvb, offset, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(eigrp_at_ext_flags_tree, hf_eigrp_at_ext_flags_default, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; -/* End Decode the AppleTalk external route Flags Field */ + * + * @param[in|out] tree detail dissection result + * @param[in] tvb packet data + * @param[in] ti protocol item + * @param[in] pinfo general data about the protocol + * + * @return void + * + * @par + * Dissect the Multi-Protocol (TLV Version 2.0) TLV format definition. The following + * represents the format + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Topology Identifier | Family Identifier | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Router ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Wide Metric | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |\/\/\/ Extended Metrics (Variable Length) \/\/\/| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |\/\/\/ NextHop (Family Specific Length) \/\/\/| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |\/\/\/ External Route Data (Optional) \/\/\/| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |\/\/\/ Destination (Family Specific Length) \/\/\/| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +static void +dissect_eigrp_multi_protocol_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, + packet_info *pinfo, guint16 tlv) +{ + proto_item *sub_ti; + int offset = 0; + guint16 afi; + int unreachable = FALSE; + + /* tid for you */ + proto_tree_add_item(tree, hf_eigrp_tid, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + /* now its all about the family */ + afi = tvb_get_ntohs(tvb, offset); + proto_tree_add_item(tree, hf_eigrp_afi, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + /* gota have an id... */ + proto_tree_add_item(tree, hf_eigrp_routerid, tvb, offset, 4, ENC_BIG_ENDIAN); + offset += 4; + + /* decode the wide metric */ + offset = dissect_eigrp_wide_metric(tree, tvb, offset); + + /* dissect nexthop */ + offset = dissect_eigrp_nexthop(tree, tvb, afi, offset); + + /* dissect external data if needed */ + if ((tlv & EIGRP_TLV_TYPEMASK) == EIGRP_TLV_EXTERNAL) { + if (afi == EIGRP_AF_IPX) { + offset = dissect_eigrp_ipx_extdata(tree, tvb, offset); + } else { + offset = dissect_eigrp_extdata(tree, tvb, offset); + } + } + + /* dissect dest information */ + switch (afi) { + case EIGRP_AF_IPv4: + offset = dissect_eigrp_ipv4_addr(ti, tree, tvb, pinfo, offset, unreachable); + break; + + case EIGRP_AF_IPv6: + offset = dissect_eigrp_ipv6_addr(ti, tree, tvb, pinfo, offset, unreachable); + break; + + case EIGRP_AF_IPX: + offset = dissect_eigrp_ipx_addr(ti, tree, tvb, pinfo, offset, unreachable); + break; + + case EIGRP_SF_COMMON: + case EIGRP_SF_IPv4: + case EIGRP_SF_IPv6: + offset = dissect_eigrp_service(ti, tree, tvb, pinfo, offset); + break; + + default: + sub_ti = proto_tree_add_text(tree, tvb, offset, -1, "Unknown AFI"); + expert_add_info_format(pinfo, sub_ti, PI_MALFORMED, PI_ERROR, "Unknown AFI"); + } + + return; +} - proto_tree_add_item(tree, hf_eigrp_at_ext_metric, tvb, offset, 2, ENC_BIG_ENDIAN); - offset += 2; +/** + *@fn int dissect_eigrp (proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo) + * + * @param[in] tvb packet data + * @param[in] pinfo general data about the protocol + * @param[in|out] tree detail dissection result + * @param[out] None + * + * @return int 0 if packet is not for this decoder + * + * @par + * This function is called to dissect the packets presented to it. The packet + * data is held in a special buffer referenced here as tvb. The packet info + * structure contains general data about the protocol, and can update + * information here. The tree parameter is where the detail dissection takes + * place. + */ +#include <epan/in_cksum.h> - proto_tree_add_item(tree, hf_eigrp_at_ext_delay, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_at_ext_bandwidth, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_at_ext_mtu, tvb, offset, 3, ENC_BIG_ENDIAN); - offset += 3; - proto_tree_add_item(tree, hf_eigrp_at_ext_hopcount, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_at_ext_reliability, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_at_ext_load, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_at_ext_reserved, tvb, offset, 2, ENC_BIG_ENDIAN); - offset += 2; - proto_tree_add_text(tree, tvb, offset, 4, "Cable range = %u-%u", tvb_get_ntohs(tvb, 36), tvb_get_ntohs(tvb, 38)); +static guint16 ip_checksum(const guint8 *ptr, int len) +{ + vec_t cksum_vec[1]; - proto_item_append_text(ti, ": %u-%u", tvb_get_ntohs(tvb, 36), tvb_get_ntohs(tvb, 38)); + cksum_vec[0].ptr = ptr; + cksum_vec[0].len = len; + return in_cksum(&cksum_vec[0], 1); } +static int +dissect_eigrp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + proto_item *ti; + proto_tree *eigrp_tree = NULL, *tlv_tree; + guint opcode, vrid; + guint16 tlv, checksum, cacl_checksum; + guint32 ack, size, offset = EIGRP_HEADER_LENGTH; + + /* Make entries in Protocol column and Info column on summary display */ + col_set_str(pinfo->cinfo, COL_PROTOCOL, "EIGRP"); + + /* This field shows up as the "Info" column in the display; you should use + * it, if possible, to summarize what's in the packet, so that a user + * looking at the list of packets can tell what type of packet it is. See + * section 1.5 for more information. + */ + col_clear(pinfo->cinfo, COL_INFO); + + opcode = tvb_get_guint8(tvb, 1); + ack = tvb_get_ntohl(tvb, 12); + if ((opcode == EIGRP_OPC_HELLO) && (0 != ack)) { + opcode = EIGRP_OPC_ACK; + } + + col_add_str(pinfo->cinfo, COL_INFO, + val_to_str(opcode, eigrp_opcode2string, "Unknown OpCode (0x%04x)")); + + /* A protocol dissector may be called in 2 different ways - with, or + * without a non-null "tree" argument. + * Note also that there is no guarantee, the first time the dissector is + * called, whether "tree" will be null or not; your dissector must work + * correctly, building or updating whatever state information is necessary, + * in either case. + */ + if (tree) { + /* NOTE: The offset and length values in the call to + * "proto_tree_add_item()" define what data bytes to highlight in the + * hex display window when the line in the protocol tree display + * corresponding to that item is selected. + */ + + /* create display subtree for the protocol */ + ti = proto_tree_add_protocol_format(tree, proto_eigrp, tvb, 0, -1, + "Cisco EIGRP"); + eigrp_tree = proto_item_add_subtree(ti, ett_eigrp); + proto_tree_add_item(eigrp_tree, hf_eigrp_version, tvb, 0, 1, + ENC_BIG_ENDIAN); + proto_tree_add_item(eigrp_tree, hf_eigrp_opcode, tvb, 1, 1, + ENC_BIG_ENDIAN); + + size = tvb_length(tvb); + checksum = tvb_get_ntohs(tvb, 2); + cacl_checksum = ip_checksum(tvb_get_ptr(tvb, 0, size), size); + + if (cacl_checksum == checksum) { + proto_tree_add_text(eigrp_tree, tvb, 2, 2, + "Checksum: 0x%02x [incorrect]", + checksum); + expert_add_info_format(pinfo, ti, PI_RESPONSE_CODE, PI_NOTE, + "Checksum: 0x%02x [incorrect, should be 0x%02x]", + checksum, cacl_checksum); + } else { + proto_tree_add_text(eigrp_tree, tvb, 2, 2, + "Checksum: 0x%02x [correct]", checksum); + } -static void dissect_eigrp_ip6_int(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti) { + /* Decode the EIGRP Flags Field */ + proto_tree_add_bitmask(eigrp_tree, tvb, 4, hf_eigrp_flags, ett_eigrp_flags, + eigrp_flag_fields, FALSE); + + proto_tree_add_item(eigrp_tree, hf_eigrp_sequence, tvb, 8, 4, + ENC_BIG_ENDIAN); + proto_tree_add_item(eigrp_tree, hf_eigrp_acknowledge, tvb, 12, 4, + ENC_BIG_ENDIAN); + + /* print out what family we dealing with... */ + ti = proto_tree_add_item(eigrp_tree, hf_eigrp_vrid, tvb, 16, 2, + ENC_BIG_ENDIAN); + vrid = (tvb_get_ntohs(tvb, 16) & EIGRP_VRID_MASK); + proto_item_append_text(ti, " %s", val_to_str(vrid, eigrp_vrid2string, + "")); + + /* print autonomous-system */ + proto_tree_add_item(eigrp_tree, hf_eigrp_as, tvb, 18, 2, + ENC_BIG_ENDIAN); + + switch (opcode) { + case EIGRP_OPC_IPXSAP: + call_dissector(ipxsap_handle, + tvb_new_subset(tvb, EIGRP_HEADER_LENGTH, -1, -1), pinfo, + eigrp_tree); + break; + + default: + while (tvb_reported_length_remaining(tvb, offset) > 0) { + tlv = tvb_get_ntohs(tvb, offset); + + /* its a rose by the wrong name... */ + if (tlv == EIGRP_TLV_MTR_TIDLIST) { + tlv = EIGRP_TLV_PEER_TIDLIST; + } - guint8 length; - int addr_len, offset = 0; - struct e_in6_addr addr; - proto_item *ti_prefixlen, *ti_dst; + size = tvb_get_ntohs(tvb, offset + 2); + if (size == 0) { + ti = proto_tree_add_text(eigrp_tree, tvb, offset, -1, + "Corrupt TLV (Zero Size)"); + expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR, + "Corrupt TLV (Zero Size)"); + return(tvb_length(tvb)); + } - proto_tree_add_item(tree, hf_eigrp_ip6_int_nexthop, tvb, offset, 16, ENC_NA); - offset += 16; - proto_tree_add_item(tree, hf_eigrp_ip6_int_delay, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_ip6_int_bandwidth, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_ip6_int_mtu, tvb, offset, 3, ENC_BIG_ENDIAN); - offset += 3; - proto_tree_add_item(tree, hf_eigrp_ip6_int_hopcount, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_ip6_int_reliability, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_ip6_int_load, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_ip6_int_reserved, tvb, offset, 2, ENC_BIG_ENDIAN); - offset += 2; + ti = proto_tree_add_text(eigrp_tree, tvb, offset, size, "%s", + val_to_str(tlv, eigrp_tlv2string, "Unknown TLV (0x%04x)")); - for (offset = 32; tvb_length_remaining(tvb, offset) > 0; offset += (1 + addr_len)) { - length = tvb_get_guint8(tvb, offset); - addr_len = ipv6_addr_and_mask(tvb, offset + 1, &addr, length); - - if (addr_len < 0) { - ti_prefixlen = proto_tree_add_item(tree, hf_eigrp_ip6_int_prefixlen, tvb, offset, 1, ENC_BIG_ENDIAN); - expert_add_info_format(pinfo, ti_prefixlen, PI_UNDECODED, PI_WARN, - "Invalid prefix length %u, must be <= 128", length); - addr_len = 16; /* assure we can exit the loop */ - } else { - proto_tree_add_item(tree, hf_eigrp_ip6_int_prefixlen, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - - if ((length < 128) && (length % 8 == 0)) { - addr_len++; - } - - ti_dst = proto_tree_add_text(tree, tvb, offset, addr_len, "Destination: %s", ip6_to_str(&addr)); - proto_item_append_text(ti, " %c %s/%u%s", offset == 33 ? '=':',', - ip6_to_str(&addr), length, ((tvb_get_ntohl(tvb, 16) == 0xffffffff) ? " - Destination unreachable":"")); - if (tvb_get_ntohl(tvb, 16) == 0xffffffff) { - expert_add_info_format(pinfo, ti_dst, PI_RESPONSE_CODE, PI_NOTE, "Destination unreachable"); - } - } - } -} + tlv_tree = proto_item_add_subtree(ti, ett_eigrp_tlv); + proto_tree_add_item(tlv_tree, hf_eigrp_tlv_type, tvb, + offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(tlv_tree, hf_eigrp_tlv_len, tvb, + (offset + 2), 2, ENC_BIG_ENDIAN); -static void dissect_eigrp_ip6_ext(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti) { + switch (tlv & EIGRP_TLV_RANGEMASK) { + case EIGRP_TLV_GENERAL: + dissect_eigrp_general_tlv(ti, tlv_tree, tvb_new_subset(tvb, (offset + 4), (size - 4), -1), pinfo, tlv); + break; - guint8 length; - int addr_len, offset = 0; - struct e_in6_addr addr; - proto_tree *eigrp_ip6_ext_flags_tree; - proto_item *eigrp_ip6_ext_ti, *ti_prefixlen, *ti_dst; + case EIGRP_TLV_IPv4: + dissect_eigrp_ipv4_tlv(ti, tlv_tree, tvb_new_subset(tvb, (offset + 4), (size - 4), -1), pinfo, tlv); + break; - eigrp_ip6_ext_ti = ti; + case EIGRP_TLV_ATALK: + dissect_eigrp_atalk_tlv(ti, tlv_tree, tvb_new_subset(tvb, (offset + 4), (size - 4), -1), tlv); + break; - proto_tree_add_item(tree, hf_eigrp_ip6_ext_nexthop, tvb, offset, 16, ENC_NA); - offset += 16; - proto_tree_add_item(tree, hf_eigrp_ip6_ext_origrouter, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_ip6_ext_as, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_ip6_ext_tag, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_ip6_ext_metric, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_ip6_ext_reserved, tvb, offset, 2, ENC_BIG_ENDIAN); - offset += 2; - proto_tree_add_item(tree, hf_eigrp_ip6_ext_proto, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; + case EIGRP_TLV_IPX: + dissect_eigrp_ipx_tlv(ti, tlv_tree, tvb_new_subset(tvb, (offset + 4), (size - 4), -1), pinfo, tlv); + break; -/* Decode the IPv6 external route Flags Field */ - ti = proto_tree_add_item(tree, hf_eigrp_ip6_ext_flags, tvb, offset, 1, ENC_BIG_ENDIAN); - eigrp_ip6_ext_flags_tree = proto_item_add_subtree(ti, ett_eigrp_ip6_ext_flags); + case EIGRP_TLV_IPv6: + dissect_eigrp_ipv6_tlv(ti, tlv_tree, tvb_new_subset(tvb, (offset + 4), (size - 4), -1), pinfo, tlv); + break; - proto_tree_add_item(eigrp_ip6_ext_flags_tree, hf_eigrp_ip6_ext_flags_ext, tvb, offset, 1, ENC_BIG_ENDIAN); - proto_tree_add_item(eigrp_ip6_ext_flags_tree, hf_eigrp_ip6_ext_flags_default, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; -/* End Decode the IPv6 external route Flags Field */ + case EIGRP_TLV_MP: + dissect_eigrp_multi_protocol_tlv(ti, tlv_tree, tvb_new_subset(tvb, (offset + 4), (size - 4), -1), + pinfo, tlv); + break; - proto_tree_add_item(tree, hf_eigrp_ip6_ext_delay, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_ip6_ext_bandwidth, tvb, offset, 4, ENC_BIG_ENDIAN); - offset += 4; - proto_tree_add_item(tree, hf_eigrp_ip6_ext_mtu, tvb, offset, 3, ENC_BIG_ENDIAN); - offset += 3; - proto_tree_add_item(tree, hf_eigrp_ip6_ext_hopcount, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_ip6_ext_reliability, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_ip6_ext_load, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - proto_tree_add_item(tree, hf_eigrp_ip6_ext_reserved2, tvb, offset, 2, ENC_BIG_ENDIAN); - offset += 2; + case EIGRP_TLV_MTR: + dissect_eigrp_multi_topology_tlv(ti, tlv_tree, tvb_new_subset(tvb, (offset + 4), (size - 4), -1), + pinfo, tlv); + break; - for (offset = 52; tvb_length_remaining(tvb, offset) > 0; offset += (1 + addr_len)) - { - length = tvb_get_guint8(tvb, offset); - addr_len = ipv6_addr_and_mask(tvb, offset + 1, &addr, length); - - if (addr_len < 0) { - ti_prefixlen = proto_tree_add_item(tree, hf_eigrp_ip6_ext_prefixlen, tvb, offset, 1, ENC_BIG_ENDIAN); - expert_add_info_format(pinfo, ti_prefixlen, PI_UNDECODED, PI_WARN, - "Invalid prefix length %u, must be <= 128", length); - addr_len = 16; /* assure we can exit the loop */ - } else { - proto_tree_add_item(tree, hf_eigrp_ip6_ext_prefixlen, tvb, offset, 1, ENC_BIG_ENDIAN); - offset += 1; - - if ((length < 128) && (length % 8 == 0)) { - addr_len++; - } - - ti_dst = proto_tree_add_text(tree, tvb, offset, addr_len, "Destination: %s", ip6_to_str(&addr)); - proto_item_append_text(eigrp_ip6_ext_ti, " %c %s/%u%s", offset == 53 ? '=':',', - ip6_to_str(&addr), length, ((tvb_get_ntohl(tvb, 36) == 0xffffffff) ? " - Destination unreachable":"")); - if (tvb_get_ntohl(tvb, 36) == 0xffffffff) { - expert_add_info_format(pinfo, ti_dst, PI_RESPONSE_CODE, PI_NOTE, "Destination unreachable"); - } + default: + expert_add_info_format(pinfo, ti, PI_UNDECODED, PI_WARN, + "Unknown TLV Group (0x%04x)", tlv); } + + offset += size; + } + break; } + } + + /* Return the amount of data this dissector was able to dissect */ + return(tvb_length(tvb)); } +/** + *@fn void proto _ register _ eigrp (void) + * + * @param[in] void + * @param[out] None + * + * @return void + * + * @usage + * you can not have the function name inside a comment or else Wireshark + * will fail with "duplicate protocol" error. Dont you hate it when tools + * try to be to smart :( + * + * @par + * Register the protocol with Wireshark + * this format is require because a script is used to build the C function + * that calls all the protocol registration. + */ +void +proto_register_eigrp(void) +{ + module_t *eigrp_module; + + /* Setup list of header fields See Section 1.6.1 for details + */ + static hf_register_info hf[] = { + /* + * + * EIGRP Packet Header definitions + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |Ver | Opcode | Checksum | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Flags | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Sequence number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Acknowledgement number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Virtual Router ID | Autonomous system number | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + { &hf_eigrp_version, + { "Version", "eigrp.version", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Version - Version of EIGRP packet format", HFILL } + }, + { &hf_eigrp_opcode, + { "Opcode", "eigrp.opcode", + FT_UINT8, BASE_DEC, VALS(eigrp_opcode2string), 0x0, + "Opcode - Operation code indicating the message type", HFILL } + }, + { &hf_eigrp_checksum, + { "Checksum", "eigrp.checksum", + FT_UINT16, BASE_HEX, NULL, 0x0, + "Checksum - computed using the same checksum algorithm as a UDP" + "checksum", HFILL } + }, + { &hf_eigrp_flags, + { "Flags", "eigrp.flags", + FT_UINT32, BASE_HEX, NULL, 0x0, + "Flag - Initialization bit and is used in establishing " + "a new neighbor relationship", HFILL } + }, + { &hf_eigrp_sequence, + { "Sequence", "eigrp.seq", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Sequence number -- used to send messages reliably", HFILL } + }, + { &hf_eigrp_acknowledge, + { "Acknowledge", "eigrp.ack", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Acknowledge number -- used to send messages reliably", HFILL } + }, + { &hf_eigrp_vrid, + { "Virtual Router ID", "eigrp.vrid", + FT_UINT16, BASE_DEC, NULL, 0, + "Virtual Router ID - For each Virtual Router, there is a separate topology " + "table and routing/service table; even for matching AS. " + "This field allows the gateway to select which set router to use.", HFILL } + }, + { &hf_eigrp_as, + { "Autonomous System", "eigrp.as", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Autonomous system number - Each AS has a separate topology table " + "which for a give routing/service table. A gateway can participate " + "in more than one AS. This field allows the gateway to" + "select which set of topology tables to use.", HFILL } + }, + + /* + * Define eigrp_flags bits here + * + * Init bit definition. First unicast transmitted Update has this + * bit set in the flags field of the fixed header. It tells the neighbor + * to send its full topology table. + */ + { &hf_eigrp_flags_init, + { "Init", "eigrp.flags.init", + FT_BOOLEAN, 32, TFS(&tfs_set_notset), EIGRP_INIT_FLAG, + "Init - tells the neighbor to send its full topology table", HFILL } + }, + + /* + * Conditionally Received - Any packet with the CR-bit set can + * be accepted by an EIGRP speaker if and only if a previous Hello was + * received with the SEQUENCE_TYPE TLV present. + * This allows multicasts to be transmitted in order and reliably at the + * same time as unicasts are transmitted. + */ + { &hf_eigrp_flags_condrecv, + { "Conditional Receive", "eigrp.flags.condrecv", + FT_BOOLEAN, 32, TFS(&tfs_set_notset), EIGRP_CR_FLAG, + "Conditionally Received the next packet if address was in listed " + "in the previous HELLO", HFILL } + }, + + /* + * Restart flag is set in the hello and the init update + * packets during the nsf signaling period. A nsf-aware + * router looks at the RS flag to detect if a peer is restarting + * and maintain the adjacency. A restarting router looks at + * this flag to determine if the peer is helping out with the restart. + */ + { &hf_eigrp_flags_restart, + { "Restart", "eigrp.flags.restart", + FT_BOOLEAN, 32, TFS(&tfs_set_notset), EIGRP_RS_FLAG, + "Restart flag - Set in the HELLO and the initial " + "UPDATE packets during the nsf signaling period.", HFILL }, + }, + + /* + * EOT bit. The End-of-Table flag marks the end of the start-up updates + * sent to a new peer. A nsf restarting router looks at this flag to + * determine if it has finished receiving the start-up updates from all + * peers. A nsf-aware router waits for this flag before cleaning up + * the stale routes from the restarting peer. + */ + { &hf_eigrp_flags_eot, + { "End Of Table", "eigrp.flags.eot", + FT_BOOLEAN, 32, TFS(&tfs_set_notset), EIGRP_EOT_FLAG, + "End-of-Table - Marks the end of the start-up UPDATES indicating the " + "complete topology database has been sent to a new peer", HFILL } + }, + + /** + * TLV type definitions. Generic (protocol-independent) TLV types are + * defined here. Protocol-specific ones are defined later + * + * +-----+------------------+ + * | | | | + * | Type| Len | Vector | + * | | | | + * +-----+------------------+ + * + * TLV type definitions. Generic (protocol-independent) TLV types are + * defined here. Protocol-specific ones are defined elsewhere. + * + * EIGRP_PARAMETER 0x0001 parameter + * EIGRP_AUTH 0x0002 authentication + * EIGRP_SEQUENCE 0x0003 sequenced packet + * EIGRP_SW_VERSION 0x0004 software version + * EIGRP_NEXT_MCAST_SEQ 0x0005 multicast sequence + * EIGRP_PEER_STUBINFO 0x0006 stub information + * EIGRP_PEER_TERMINATION 0x0007 peer termination + */ + { &hf_eigrp_tlv_type, + { "Type", "eigrp.tlv_type", + FT_UINT16, BASE_HEX, VALS(eigrp_tlv2string), 0x0, + "TLV Type", HFILL } + }, + { &hf_eigrp_tlv_len, + { "Length", "eigrp.tlv.len", + FT_UINT16, BASE_DEC, NULL, 0x0, + "TLV Length", HFILL } + }, + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Parameters TLV + */ + { &hf_eigrp_par_k1, { "K1", "eigrp.par.k1", FT_UINT8, BASE_DEC, NULL, 0x0, + "Bandwidth/Throughput Coefficient", HFILL }}, + { &hf_eigrp_par_k2, { "K2", "eigrp.par.k2", FT_UINT8, BASE_DEC, NULL, 0x0, + "Load Coefficient", HFILL }}, + { &hf_eigrp_par_k3, { "K3", "eigrp.par.k3", FT_UINT8, BASE_DEC, NULL, 0x0, + "Delay/Latency Coefficient", HFILL }}, + { &hf_eigrp_par_k4, { "K4", "eigrp.par.k4", FT_UINT8, BASE_DEC, NULL, 0x0, + "Reliability Coefficient", HFILL }}, + { &hf_eigrp_par_k5, { "K5", "eigrp.par.k5", FT_UINT8, BASE_DEC, NULL, 0x0, + "Reliability Coefficient", HFILL }}, + { &hf_eigrp_par_k6, { "K6", "eigrp.par.k6", FT_UINT8, BASE_DEC, NULL, 0x0, + "Extended Metric Coefficient", HFILL }}, + { &hf_eigrp_par_holdtime, + { "Hold Time", "eigrp.par.holdtime", FT_UINT16, BASE_DEC, NULL, 0x0, + "How long to ignore lost HELLO's", HFILL } + }, + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Authentication TLV + */ + { &hf_eigrp_auth_type, + { "Type", "eigrp.auth.type", + FT_UINT16, BASE_DEC, VALS(eigrp_auth2string), 0x0, + NULL, HFILL } + }, + { &hf_eigrp_auth_len, + { "Length", "eigrp.auth.length", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_eigrp_auth_keyid, + { "Key ID", "eigrp.auth.keyid", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_eigrp_auth_keyseq, + { "Key Sequence", "eigrp.auth.keyseq", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_eigrp_auth_digest, + { "Digest", "eigrp.auth.digest", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Sequence TLV + */ + { &hf_eigrp_seq_addrlen, + { "Address length", "eigrp.seq.addrlen", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_eigrp_seq_ipv4addr, + { "IP Address", "eigrp.seq.ipv4addr", + FT_IPv4, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_eigrp_seq_ipv6addr, + { "IPv6 Address", "eigrp.seq.ipv6addr", + FT_IPv6, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Software Version + */ + /* + * The revision level is used to track upward compatible changes in the + * protocol, so that newer code can know whether or not it may exploit these + * changes. Non-upward compatible changes should be signaled by changing + * the "version" field in the EIGRP header (and woe be unto you). + */ + { &hf_eigrp_sw_version, + { "Software Version", "eigrp.sw_version", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_eigrp_sw_version_os_majorver, + { "IOS Release Major", "eigrp.sw_version.os_majorver", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_eigrp_sw_version_os_minorver, + { "IOS Release Minor", "eigrp.sw_version.os_minorver", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_eigrp_sw_version_tlv_majorrev, + { "EIGRP Release Major", "eigrp.sw_version.tlv_majorrev", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_eigrp_sw_version_tlv_minorrev, + { "EIGRP Release Minor", "eigrp.sw_version.tlv_minorrev", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Next Multicast Sequence + */ + /* + * This was added to the hello containing the sequence TLV so that the + * hello packet could be more tightly bound to the multicast packet bearing + * the CR bit that follows it. The sequence number of the impending multicast + * is carried herein. + */ + { &hf_eigrp_next_mcast_seq, + { "Multicast Sequence", "eigrp.next_mcast_seq", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Peer Stub Information TLV + */ + { &hf_eigrp_stub_flags, + { "Stub Options", "eigrp.stub_options", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + + /* + * Define eigrp_stub_flags bits here + */ + { &hf_eigrp_stub_flags_connected, + { "Connected", "eigrp.stub_options.connected", + FT_BOOLEAN, 16, TFS(&tfs_set_notset), EIGRP_PEER_ALLOWS_CONNECTED, + NULL, HFILL } + }, + { &hf_eigrp_stub_flags_static, + { "Static", "eigrp.stub_options.static", + FT_BOOLEAN, 16, TFS(&tfs_set_notset), EIGRP_PEER_ALLOWS_STATIC, + NULL, HFILL } + }, + { &hf_eigrp_stub_flags_summary, + { "Summary", "eigrp.stub_options.summary", + FT_BOOLEAN, 16, TFS(&tfs_set_notset), EIGRP_PEER_ALLOWS_SUMMARY, + NULL, HFILL } + }, + { &hf_eigrp_stub_flags_redist, + { "Redistributed", "eigrp.stub_options.redist", + FT_BOOLEAN, 16, TFS(&tfs_set_notset), EIGRP_PEER_ALLOWS_REDIST, + NULL, HFILL } + }, + { &hf_eigrp_stub_flags_leakmap, + { "Leak-Map", "eigrp.stub_options.leakmap", + FT_BOOLEAN, 16, TFS(&tfs_set_notset), EIGRP_PEER_ALLOWS_LEAKING, + NULL, HFILL } + }, + { &hf_eigrp_stub_flags_recvonly, + { "Receive-Only", "eigrp.stub_options.recvonly", + FT_BOOLEAN, 16, TFS(&tfs_set_notset), EIGRP_PEER_ALLOWS_RCVONLY, + NULL, HFILL } + }, + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Peer Termination TLV + */ + /* Place holder - this TLV has no options */ -void proto_register_eigrp(void) { - - static hf_register_info hf[] = { - { &hf_eigrp_version, - { "Version", "eigrp.version", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_opcode, - { "Opcode", "eigrp.opcode", - FT_UINT8, BASE_DEC, VALS(eigrp_opcode_vals), 0x0, - "Opcode number", HFILL } - }, - { &hf_eigrp_checksum, - { "Checksum", "eigrp.checksum", - FT_UINT16, BASE_HEX, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_flags, - { "Flags", "eigrp.flags", - FT_UINT32, BASE_HEX, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_flags_init, - { "Init", "eigrp.flags.init", - FT_BOOLEAN, 32, NULL, EIGRP_FLAGS_INIT, - NULL, HFILL } - }, - { &hf_eigrp_flags_condrecv, - { "Conditional Receive", "eigrp.flags.condrecv", - FT_BOOLEAN, 32, NULL, EIGRP_FLAGS_CONDRECV, - NULL, HFILL } - }, - { &hf_eigrp_flags_restart, - { "Restart", "eigrp.flags.restart", - FT_BOOLEAN, 32, NULL, EIGRP_FLAGS_RESTART, - NULL, HFILL }, - }, - { &hf_eigrp_flags_eot, - { "End Of Table", "eigrp.flags.eot", - FT_BOOLEAN, 32, NULL, EIGRP_FLAGS_ENDOFTABLE, - NULL, HFILL } - }, - { &hf_eigrp_sequence, - { "Sequence", "eigrp.seq", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_acknowledge, - { "Acknowledge", "eigrp.ack", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_as, - { "Autonomous System", "eigrp.as", - FT_UINT16, BASE_DEC, NULL, 0x0, - "Autonomous System number", HFILL } - }, - { &hf_eigrp_tlv, - { "Type", "eigrp.tlv", - FT_UINT16, BASE_DEC, VALS(eigrp_tlv_vals), 0x0, - "Type/Length/Value", HFILL } - }, - { &hf_eigrp_tlv_size, - { "Size", "eigrp.tlv.size", - FT_UINT16, BASE_DEC, NULL, 0x0, - "TLV size", HFILL } - }, -/* EIGRP Parameters TLV */ - { &hf_eigrp_par_k1, - { "K1", "eigrp.par.k1", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_par_k2, - { "K2", "eigrp.par.k2", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_par_k3, - { "K3", "eigrp.par.k3", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_par_k4, - { "K4", "eigrp.par.k4", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_par_k5, - { "K5", "eigrp.par.k5", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_par_reserved, - { "Reserved", "eigrp.par.reserved", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_par_holdtime, - { "Hold Time", "eigrp.par.holdtime", - FT_UINT16, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, -/* Authentication TLV */ - { &hf_eigrp_auth_type, - { "Authentication Type", "eigrp.auth.type", - FT_UINT16, BASE_DEC, VALS(eigrp_auth_type_vals), 0x0, - NULL, HFILL } - }, - { &hf_eigrp_auth_keysize, - { "Key size", "eigrp.auth.keysize", - FT_UINT16, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_auth_keyid, - { "Key ID", "eigrp.auth.keyid", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_auth_nullpad, - { "Nullpad", "eigrp.auth.nullapd", - FT_STRING, BASE_NONE, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_auth_data, - { "Data", "eigrp.auth.data", - FT_STRING, BASE_NONE, NULL, 0x0, - NULL, HFILL } - }, -/* Sequence TLV */ - { &hf_eigrp_seq_addrlen, - { "Address length", "eigrp.seq.addrlen", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_seq_ipaddr, - { "IP Address", "eigrp.seq.ipaddr", - FT_IPv4, BASE_NONE, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_seq_ip6addr, - { "IPv6 Address", "eigrp.seq.ip6addr", - FT_IPv6, BASE_NONE, NULL, 0x0, - NULL, HFILL } - }, -/* Software Version TLV */ - { &hf_eigrp_sv_ios, - { "IOS release version", "eigrp.sv.ios", - FT_STRING, BASE_NONE, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_sv_eigrp, - { "EIGRP release version", "eigrp.sv.eigrp", - FT_STRING, BASE_NONE, NULL, 0x0, - NULL, HFILL } - }, -/* Next multicast sequence TLV */ - { &hf_eigrp_nms, - { "Next Multicast Sequence", "eigrp.nms", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, -/* Stub routing TLV */ - { &hf_eigrp_stub_flags, - { "Stub Flags", "eigrp.stub_flags", - FT_UINT16, BASE_HEX, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_stub_flags_connected, - { "Connected", "eigrp.stub_flags.connected", - FT_BOOLEAN, 16, NULL, EIGRP_STUB_FLAGS_CONNECTED, - NULL, HFILL } - }, - { &hf_eigrp_stub_flags_static, - { "Static", "eigrp.stub_flags.static", - FT_BOOLEAN, 16, NULL, EIGRP_STUB_FLAGS_STATIC, - NULL, HFILL } - }, - { &hf_eigrp_stub_flags_summary, - { "Summary", "eigrp.stub_flags.summary", - FT_BOOLEAN, 16, NULL, EIGRP_STUB_FLAGS_SUMMARY, - NULL, HFILL } - }, - { &hf_eigrp_stub_flags_recvonly, - { "Receive-Only", "eigrp.stub_flags.recvonly", - FT_BOOLEAN, 16, NULL, EIGRP_STUB_FLAGS_RECVONLY, - NULL, HFILL } - }, - { &hf_eigrp_stub_flags_redist, - { "Redistributed", "eigrp.stub_flags.redist", - FT_BOOLEAN, 16, NULL, EIGRP_STUB_FLAGS_REDIST, - NULL, HFILL } - }, - { &hf_eigrp_stub_flags_leakmap, - { "Leak-Map", "eigrp.stub_flags.leakmap", - FT_BOOLEAN, 16, NULL, EIGRP_STUB_FLAGS_LEAKMAP, - NULL, HFILL } - }, -/* IP internal route TLV */ - { &hf_eigrp_ip_int_nexthop, - { "Next Hop", "eigrp.ip_int.nexthop", - FT_IPv4, BASE_NONE, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip_int_delay, - { "Delay", "eigrp.ip_int.delay", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip_int_bandwidth, - { "Bandwidth", "eigrp.ip_int.bandwidth", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip_int_mtu, - { "MTU", "eigrp.ip_int.mtu", - FT_UINT24, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip_int_hopcount, - { "Hop Count", "eigrp.ip_int.hopcount", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip_int_reliability, - { "Reliability", "eigrp.ip_int.reliability", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip_int_load, - { "Load", "eigrp.ip_int.load", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip_int_reserved, - { "Reserved", "eigrp.ip_int.reserved", - FT_UINT16, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip_int_prefixlen, - { "Prefix Length", "eigrp.ip_int.prefixlen", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip_int_dst, - { "Destination", "eigrp.ip_int.dst", - FT_STRING, BASE_NONE, NULL, 0x0, - NULL, HFILL } - }, -/* IP external route TLV */ - { &hf_eigrp_ip_ext_nexthop, - { "Next Hop", "eigrp.ip_ext.nexthop", - FT_IPv4, BASE_NONE, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip_ext_origrouter, - { "Originating router", "eigrp.ip_ext.origrouter", - FT_IPv4, BASE_NONE, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip_ext_as, - { "Originating A.S.", "eigrp.ip_ext.as", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip_ext_tag, - { "Arbitrary tag", "eigrp.ip_ext.tag", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip_ext_metric, - { "External protocol metric", "eigrp.ip_ext.metric", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip_ext_reserved, - { "Reserved", "eigrp.ip_ext.reserved", - FT_UINT16, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip_ext_proto, - { "External protocol ID", "eigrp.ip_ext.proto", - FT_UINT8, BASE_DEC, VALS(eigrp_pid_vals), 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip_ext_flags, - { "Flags", "eigrp.ip_ext.flags", - FT_UINT8, BASE_HEX, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip_ext_flags_ext, - { "External Route", "eigrp.ip_ext.flags.ext", - FT_BOOLEAN, 8, NULL, EIGRP_IP_EXT_FLAGS_EXT, - NULL, HFILL } - }, - { &hf_eigrp_ip_ext_flags_default, - { "Candidate Default Route", "eigrp.ip_ext.flags.default", - FT_BOOLEAN, 8, NULL, EIGRP_IP_EXT_FLAGS_DEFAULT, - NULL, HFILL } - }, - { &hf_eigrp_ip_ext_delay, - { "Delay", "eigrp.ip_ext.delay", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip_ext_bandwidth, - { "Bandwidth", "eigrp.ip_ext.bandwidth", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip_ext_mtu, - { "MTU", "eigrp.ip_ext.mtu", - FT_UINT24, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip_ext_hopcount, - { "Hop Count", "eigrp.ip_ext.hopcount", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip_ext_reliability, - { "Reliability", "eigrp.ip_ext.reliability", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip_ext_load, - { "Load", "eigrp.ip_ext.load", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip_ext_reserved2, - { "Reserved", "eigrp.ip_ext.reserved2", - FT_UINT16, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip_ext_prefixlen, - { "Prefix Length", "eigrp.ip_ext.prefixlen", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, -/* IPX internal route TLV */ - { &hf_eigrp_ipx_int_nexthop_addr, - { "Next Hop Address", "eigrp.ipx_int.nexthop_addr", - FT_IPXNET, BASE_NONE, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ipx_int_nexthop_id, - { "Next Hop ID", "eigrp.ipx_int.nexthop_id", - FT_ETHER, BASE_NONE, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ipx_int_delay, - { "Delay", "eigrp.ipx_int.delay", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ipx_int_bandwidth, - { "Bandwidth", "eigrp.ipx_int.bandwidth", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ipx_int_mtu, - { "MTU", "eigrp.ipx_int.mtu", - FT_UINT24, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ipx_int_hopcount, - { "Hop Count", "eigrp.ipx_int.hopcount", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ipx_int_reliability, - { "Reliability", "eigrp.ipx_int.reliability", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ipx_int_load, - { "Load", "eigrp.ipx_int.load", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ipx_int_reserved, - { "Reserved", "eigrp.ipx_int.reserved", - FT_UINT16, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ipx_int_dst, - { "Destination", "eigrp.ipx_int.dst", - FT_IPXNET, BASE_NONE, NULL, 0x0, - NULL, HFILL } - }, -/* IPX external route TLV */ - { &hf_eigrp_ipx_ext_nexthop_addr, - { "Next Hop Address", "eigrp.ipx_ext.nexthop_addr", - FT_IPXNET, BASE_NONE, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ipx_ext_nexthop_id, - { "Next Hop ID", "eigrp.ipx_ext.nexthop_id", - FT_ETHER, BASE_NONE, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ipx_ext_origrouter, - { "Originating router", "eigrp.ipx_ext.origrouter", - FT_ETHER, BASE_NONE, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ipx_ext_as, - { "Originating A.S.", "eigrp.ipx_ext.as", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ipx_ext_tag, - { "Arbitrary tag", "eigrp.ipx_ext.tag", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ipx_ext_proto, - { "External protocol ID", "eigrp.ipx_ext.proto", - FT_UINT8, BASE_DEC, VALS(eigrp_pid_vals), 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ipx_ext_reserved, - { "Reserved", "eigrp.ipx_ext.reserved", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ipx_ext_metric, - { "External protocol metric", "eigrp.ipx_ext.metric", - FT_UINT16, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ipx_ext_extdelay, - { "External protocol delay", "eigrp.ipx_ext.extdelay", - FT_UINT16, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ipx_ext_delay, - { "Delay", "eigrp.ipx_ext.delay", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ipx_ext_bandwidth, - { "Bandwidth", "eigrp.ipx_ext.bandwidth", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ipx_ext_mtu, - { "MTU", "eigrp.ipx_ext.mtu", - FT_UINT24, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ipx_ext_hopcount, - { "Hop Count", "eigrp.ipx_ext.hopcount", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ipx_ext_reliability, - { "Reliability", "eigrp.ipx_ext.reliability", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ipx_ext_load, - { "Load", "eigrp.ipx_ext.load", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ipx_ext_reserved2, - { "Reserved", "eigrp.ipx_ext.reserved2", - FT_UINT16, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ipx_ext_dst, - { "Destination", "eigrp.ipx_ext.dst", - FT_IPXNET, BASE_NONE, NULL, 0x0, - NULL, HFILL } - }, -/* AppleTalk cable configuration TLV */ - { &hf_eigrp_at_cbl_routerid, - { "AppleTalk Router ID", "eigrp.at_cbl.routerid", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, -/* AppleTalk internal route TLV */ - { &hf_eigrp_at_int_delay, - { "Delay", "eigrp.at_int.delay", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_at_int_bandwidth, - { "Bandwidth", "eigrp.at_int.bandwidth", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_at_int_mtu, - { "MTU", "eigrp.at_int.mtu", - FT_UINT24, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_at_int_hopcount, - { "Hop Count", "eigrp.at_int.hopcount", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_at_int_reliability, - { "Reliability", "eigrp.at_int.reliability", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_at_int_load, - { "Load", "eigrp.at_int.load", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_at_int_reserved, - { "Reserved", "eigrp.at_int.reserved", - FT_UINT16, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, -/* AppleTalk external route TLV */ - { &hf_eigrp_at_ext_origrouter, - { "Originating router", "eigrp.at_ext.origrouter", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_at_ext_as, - { "Originating A.S.", "eigrp.at_ext.as", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_at_ext_tag, - { "Arbitrary tag", "eigrp.at_ext.tag", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_at_ext_proto, - { "External protocol ID", "eigrp.at_ext.proto", - FT_UINT8, BASE_DEC, VALS(eigrp_pid_vals), 0x0, - NULL, HFILL } - }, - { &hf_eigrp_at_ext_flags, - { "Flags", "eigrp.at_ext.flags", - FT_UINT8, BASE_HEX, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_at_ext_flags_ext, - { "External Route", "eigrp.at_ext.flags.ext", - FT_BOOLEAN, 8, NULL, EIGRP_IP_EXT_FLAGS_EXT, - NULL, HFILL } - }, - { &hf_eigrp_at_ext_flags_default, - { "Candidate Default Route", "eigrp.at_ext.flags.default", - FT_BOOLEAN, 8, NULL, EIGRP_IP_EXT_FLAGS_DEFAULT, - NULL, HFILL } - }, - { &hf_eigrp_at_ext_metric, - { "External protocol metric", "eigrp.at_ext.metric", - FT_UINT16, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_at_ext_delay, - { "Delay", "eigrp.at_ext.delay", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_at_ext_bandwidth, - { "Bandwidth", "eigrp.at_ext.bandwidth", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_at_ext_mtu, - { "MTU", "eigrp.at_ext.mtu", - FT_UINT24, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_at_ext_hopcount, - { "Hop Count", "eigrp.at_ext.hopcount", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_at_ext_reliability, - { "Reliability", "eigrp.at_ext.reliability", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_at_ext_load, - { "Load", "eigrp.at_ext.load", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_at_ext_reserved, - { "Reserved", "eigrp.at_ext.reserved", - FT_UINT16, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, -/* IPv6 internal route TLV */ - { &hf_eigrp_ip6_int_nexthop, - { "Next Hop", "eigrp.ip6_int.nexthop", - FT_IPv6, BASE_NONE, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip6_int_delay, - { "Delay", "eigrp.ip6_int.delay", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip6_int_bandwidth, - { "Bandwidth", "eigrp.ip6_int.bandwidth", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip6_int_mtu, - { "MTU", "eigrp.ip6_int.mtu", - FT_UINT24, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip6_int_hopcount, - { "Hop Count", "eigrp.ip6_int.hopcount", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip6_int_reliability, - { "Reliability", "eigrp.ip6_int.reliability", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip6_int_load, - { "Load", "eigrp.ip6_int.load", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip6_int_reserved, - { "Reserved", "eigrp.ip6_int.reserved", - FT_UINT16, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip6_int_prefixlen, - { "Prefix Length", "eigrp.ip6_int.prefixlen", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, -/* IPv6 external route TLV */ - { &hf_eigrp_ip6_ext_nexthop, - { "Next Hop", "eigrp.ip6_ext.nexthop", - FT_IPv6, BASE_NONE, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip6_ext_origrouter, - { "Originating router", "eigrp.ip6_ext.origrouter", - FT_IPv4, BASE_NONE, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip6_ext_as, - { "Originating A.S.", "eigrp.ip6_ext.as", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip6_ext_tag, - { "Arbitrary tag", "eigrp.ip6_ext.tag", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip6_ext_metric, - { "External protocol metric", "eigrp.ip6_ext.metric", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip6_ext_reserved, - { "Reserved", "eigrp.ip6_ext.reserved", - FT_UINT16, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip6_ext_proto, - { "External protocol ID", "eigrp.ip6_ext.proto", - FT_UINT8, BASE_DEC, VALS(eigrp_pid_vals), 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip6_ext_flags, - { "Flags", "eigrp.ip6_ext.flags", - FT_UINT8, BASE_HEX, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip6_ext_flags_ext, - { "External Route", "eigrp.ip6_ext.flags.ext", - FT_BOOLEAN, 8, NULL, EIGRP_IP_EXT_FLAGS_EXT, - NULL, HFILL } - }, - { &hf_eigrp_ip6_ext_flags_default, - { "Candidate Default Route", "eigrp.ip6_ext.flags.default", - FT_BOOLEAN, 8, NULL, EIGRP_IP_EXT_FLAGS_DEFAULT, - NULL, HFILL } - }, - { &hf_eigrp_ip6_ext_delay, - { "Delay", "eigrp.ip6_ext.delay", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip6_ext_bandwidth, - { "Bandwidth", "eigrp.ip6_ext.bandwidth", - FT_UINT32, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip6_ext_mtu, - { "MTU", "eigrp.ip6_ext.mtu", - FT_UINT24, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip6_ext_hopcount, - { "Hop Count", "eigrp.ip6_ext.hopcount", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip6_ext_reliability, - { "Reliability", "eigrp.ip6_ext.reliability", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip6_ext_load, - { "Load", "eigrp.ip6_ext.load", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip6_ext_reserved2, - { "Reserved", "eigrp.ip6_ext.reserved2", - FT_UINT16, BASE_DEC, NULL, 0x0, - NULL, HFILL } - }, - { &hf_eigrp_ip6_ext_prefixlen, - { "Prefix Length", "eigrp.ip6_ext.prefixlen", - FT_UINT8, BASE_DEC, NULL, 0x0, - NULL, HFILL } - } - }; - - static gint *ett[] = { - &ett_eigrp, - &ett_eigrp_flags, - &ett_tlv, - &ett_eigrp_stub_flags, - &ett_eigrp_ip_ext_flags, - &ett_eigrp_ip6_ext_flags, - &ett_eigrp_at_ext_flags - }; - - proto_eigrp = proto_register_protocol("Enhanced Interior Gateway Routing Protocol", "EIGRP", "eigrp"); - proto_register_field_array(proto_eigrp, hf, array_length(hf)); - proto_register_subtree_array(ett, array_length(ett)); +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * EIGRP 3.0 Vector Header (deprecated) + */ + /* + * common header for all version 3 tlvs + */ + { &hf_eigrp_tid, + { "Topology", "eigrp.tid", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_eigrp_afi, + { "AFI", "eigrp.afi", + FT_UINT16, BASE_DEC, VALS(eigrp_afi2string), 0x0, + NULL, HFILL } + }, + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * EIGRP TLV 1.2 (legacy) and TLV 3.0 Metric (deprecated) definition + */ + { &hf_eigrp_legacy_metric_delay, + { "Scaled Delay", "eigrp.old_metric.delay", + FT_UINT32, BASE_DEC, NULL, 0x0, + "delay, in 39.1 nanosec interments", HFILL } + }, + { &hf_eigrp_legacy_metric_bw, + { "Scaled BW", "eigrp.old_metric.bw", + FT_UINT32, BASE_DEC, NULL, 0x0, + "bandwidth, in units of 1 Kbit/sec", HFILL } + }, + { &hf_eigrp_legacy_metric_mtu, + { "MTU", "eigrp.old_metric.mtu", + FT_UINT24, BASE_DEC, NULL, 0x0, + "MTU, in octets", HFILL } + }, + { &hf_eigrp_legacy_metric_hopcount, + { "Hop Count", "eigrp.old_metric.hopcount", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Number of hops to destination", HFILL } + }, + { &hf_eigrp_legacy_metric_rel, + { "Reliability", "eigrp.old_metric.rel", + FT_UINT8, BASE_DEC, NULL, 0x0, + "percent packets successfully tx/rx", HFILL } + }, + { &hf_eigrp_legacy_metric_load, + { "Load", "eigrp.old_metric.load", + FT_UINT8, BASE_DEC, NULL, 0x0, + "percent of channel occupied", HFILL } + }, + { &hf_eigrp_legacy_metric_intag, + { "Route Tag", "eigrp.old_metric.intag", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Internal Route Tag", HFILL } + }, + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * EIGRP 3.0 TIDLIST TLV (only survivor in MTR) + */ + { &hf_eigrp_tidlist, + { "TID List", "eigrp.tidlist", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_eigrp_tidlist_flags, + { "TID List Flags", "eigrp.tidlist.flags", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + { &hf_eigrp_tidlist_len, + { "TID List Size", "eigrp.tidlist.len", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_eigrp_routerid, + { "RouterID", "eigrp.routerid", + FT_IPv4, BASE_NONE, NULL, 0x0, + "Router ID of injecting router", HFILL } + }, + { &hf_eigrp_legacy_metric_tag, + { "Tag", "eigrp.old_metric.tag", + FT_UINT32, BASE_DEC, NULL, 0x0, + "route tag", HFILL } + }, + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * PDM opaque flag field definitions + */ + { &hf_eigrp_metric_flags_srcwd, + { "Source Withdraw", "eigrp.metric.flags.srcwd", + FT_BOOLEAN, 8, TFS(&tfs_true_false), EIGRP_OPAQUE_SRCWD, + "Route Source Withdraw", HFILL } + }, + { &hf_eigrp_metric_flags_active, + { "Route is Active", "eigrp.metric.flags.active", + FT_BOOLEAN, 8, TFS(&tfs_true_false), EIGRP_OPAQUE_ACTIVE, + "Route is currently in active state", HFILL } + }, + { &hf_eigrp_metric_flags_repl, + { "Route is Replicated", "eigrp.metric.flags.repl", + FT_BOOLEAN, 8, TFS(&tfs_true_false), EIGRP_OPAQUE_REPL, + "Route is replicated from different tableid", HFILL } + }, + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * EIGRP TLV 1.2/3.0 ExtData Definitions + */ + { &hf_eigrp_extdata_origrid, + { "Originating RouterID", "eigrp.extdata.origrid", + FT_IPv4, BASE_NONE, NULL, 0x0, + "Router ID of redistributing router", HFILL } + }, + + { &hf_eigrp_extdata_as, + { "Originating A.S.", "eigrp.extdata.as", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Autonomous System of redistributing protocol", HFILL } + }, + + { &hf_eigrp_extdata_tag, + { "Administrative Tag", "eigrp.extdata.tag", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Administrative Route Tag", HFILL } + }, + { &hf_eigrp_extdata_metric, + { "External Metric", "eigrp.extdata.metric", + FT_UINT32, BASE_DEC, NULL, 0x0, + "Metric reported by redistributing protocol", HFILL } + }, + { &hf_eigrp_extdata_reserved, + { "Reserved", "eigrp.extdata.reserved", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + + /* IPX ExtData Definitions */ + { &hf_eigrp_ipx_extdata_delay, + { "External Delay", "eigrp.extdata.ipx_delay", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Delay reported by redistributing protocol", HFILL } + }, + { &hf_eigrp_ipx_extdata_metric, + { "External Metric", "eigrp.extdata.ipx_metric", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Delay reported by redistributing protocol", HFILL } + }, + + { &hf_eigrp_extdata_proto, + { "External Protocol ID", "eigrp.extdata.proto", + FT_UINT8, BASE_DEC, VALS(eigrp_proto2string), 0x0, + NULL, HFILL } + }, + + { &hf_eigrp_extdata_flag_ext, + { "Route is External", "eigrp.opaque.flag.ext", + FT_BOOLEAN, 8, TFS(&tfs_true_false), EIGRP_OPAQUE_EXT, + "External route", HFILL } + }, + { &hf_eigrp_extdata_flag_cd, + { "Route is Candidate Default", "eigrp.opaque.flag.cd", + FT_BOOLEAN, 8, TFS(&tfs_true_false), EIGRP_OPAQUE_CD, + "Candidate-Default route", HFILL } + }, + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * EIGRP TLV 2.0 "Wide" Metric format definition + */ + /* Number of 16bit words in the metric section, used to determine the + * start of the destination/attribute information. + */ + { &hf_eigrp_metric_offset, + { "Offset", "eigrp.metric.offset", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Number of 16bit words to reach the start of the" + "destination/attribute information", HFILL } + }, + + /* Priority of the prefix when transmitting a group of destination + * addresses to neighboring routers. A priority of zero indicates no + * priority is set. + */ + { &hf_eigrp_metric_priority, + { "Priority", "eigrp.metric.priority", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Priority of the prefix for ordering transmission", HFILL } + }, + + /** The current error rate for the path. Measured as an error + * percentage. A value of 255 indicates 100% reliability + */ + { &hf_eigrp_metric_rel, + { "Reliability", "eigrp.metric.reliability", + FT_UINT8, BASE_DEC, NULL, 0x0, + "percent packets successfully tx/rx", HFILL } + }, + + /** The load utilization of the path to the destination. Measured as a + * percentage of load. A value of 255 indicates 100% load. + */ + { &hf_eigrp_metric_load, + { "Load", "eigrp.metric.load", + FT_UINT8, BASE_DEC, NULL, 0x0, + "percent of channel occupied", HFILL } + }, + + /** The minimum maximum transmission unit size for the path to the + * destination. Not used in metric calculation, but available to + * underlying protocols + */ + { &hf_eigrp_metric_mtu, + { "MTU", "eigrp.metric.mtu", + FT_UINT24, BASE_DEC, NULL, 0x0, + "MTU, in octets", HFILL } + }, + + /** number of router traversals to the destination */ + { &hf_eigrp_metric_hopcount, + { "Hop Count", "eigrp.metric.hopcount", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Number of hops to destination", HFILL } + }, + + /** The one-way latency along an unloaded path to the destination + * expressed in units of nanoseconds per kilobyte. This number is not + * scaled, as is the case with scaled delay. A delay of 0xFFFFFFFFFFFF + * indicates an unreachable route. */ + { &hf_eigrp_metric_delay, + { "Delay", "eigrp.metric.delay", + FT_BYTES, BASE_NONE, NULL, 0x0, + "delay, nanoseconds per kilobyte", HFILL } + }, + + /** The path bandwidth measured in kilobyte per second as presented by + * the interface. This number is not scaled, as is the case with scaled + * bandwidth. A bandwidth of 0xFFFFFFFFFFFF indicates an unreachable + * route. + */ + { &hf_eigrp_metric_bw, + { "Bandwidth", "eigrp.metric.bw", + FT_BYTES, BASE_NONE, NULL, 0x0, + "bandwidth, Kilobyte per second", HFILL } + }, + /* Reserved - Transmitted as 0x0000 */ + { &hf_eigrp_metric_reserved, + { "Reserved", "eigrp.metric.reserved", + FT_UINT16, BASE_HEX, NULL, 0x0, + NULL, HFILL } + }, + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * EIGRP TLV 2.0 Extended Metric Attributes + */ + { &hf_eigrp_attr_opcode, + { "Opcode", "eigrp.attr.opcode", + FT_UINT8, BASE_DEC, VALS(eigrp_attr_opcode2string), 0x0, + "Opcode - Operation code indicating the attribute type", HFILL } + }, + { &hf_eigrp_attr_offset, + { "Offset", "eigrp.attr.offset", + FT_UINT8, BASE_DEC, NULL, 0x0, + "Number of 2 byte words of data", HFILL } + }, + { &hf_eigrp_attr_scaled, + { "Legacy Metric", "eigrp.attr.scaled", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Metric calculated from legacy TLVs", HFILL } + }, + { &hf_eigrp_attr_tag, + { "Tag", "eigrp.attr.tag", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Tag assigned by admin for dest", HFILL } + }, + { &hf_eigrp_attr_jitter, + { "Jitter", "eigrp.attr.jitter", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Variation in path delay", HFILL } + }, + { &hf_eigrp_attr_qenergy, + { "Q-Energy", "eigrp.attr.qenergy", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Non-Active energy usage along path", HFILL } + }, + { &hf_eigrp_attr_energy, + { "Energy", "eigrp.attr.energy", + FT_UINT16, BASE_DEC, NULL, 0x0, + "Active energy usage along path", HFILL } + }, + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * IPv4 specific address definitions + */ + { &hf_eigrp_ipv4_nexthop, + { "NextHop", "eigrp.ipv4.nexthop", + FT_IPv4, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_eigrp_ipv4_prefixlen, + { "Prefix Length", "eigrp.ipv4.prefixlen", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_eigrp_ipv4_dest, + { "Destination", "eigrp.ipv4.dest", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * IPv6 specific address definitions + */ + { &hf_eigrp_ipv6_nexthop, + { "NextHop", "eigrp.ipv6.nexthop", + FT_IPv6, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + + { &hf_eigrp_ipv6_prefixlen, + { "Prefix Length", "eigrp.ipv6.prefixlen", + FT_UINT8, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * IPX specific address definitions + */ + { &hf_eigrp_ipx_nexthop_net, + { "NextHop Net", "eigrp.ipx.nexthop_net", + FT_IPXNET, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_eigrp_ipx_nexthop_host, + { "NextHop Host", "eigrp.ipx.nexthop_host", + FT_ETHER, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_eigrp_ipx_extdata_routerid, + { "External RouterID", "eigrp.ipx.routerid", + FT_ETHER, BASE_NONE, NULL, 0x0, + "Router ID of redistributing router", HFILL } + }, + { &hf_eigrp_ipx_dest, + { "Destination", "eigrp.ipx.dest", + FT_IPXNET, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * AppleTalk specific address definitions + */ + { &hf_eigrp_atalk_routerid, + { "AppleTalk Router ID", "eigrp.atalk.routerid", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Service Advertisement Framework definitions + */ + { &hf_eigrp_saf_service, + { "Service", "eigrp.saf.service", + FT_UINT16, BASE_DEC, VALS(eigrp_saf_srv2string), 0x0, + NULL, HFILL } + }, + { &hf_eigrp_saf_subservice, + { "Sub-Service", "eigrp.saf.subservice", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_eigrp_saf_guid, + { "GUID", "eigrp.saf.guid", + FT_GUID, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_eigrp_saf_data_type, + { "Type", "eigrp.saf.data.type", + FT_UINT16, BASE_HEX, VALS(eigrp_saf_type2string), 0x0, + "SAF Message Data Type", HFILL } + }, + { &hf_eigrp_saf_data_length, + { "Length", "eigrp.saf.data.length", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_eigrp_saf_data_sequence, + { "Sequence", "eigrp.saf.data.sequence", + FT_UINT32, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_eigrp_saf_reachability_afi, + { "AFI", "eigrp.saf.data.reachability.afi", + FT_UINT16, BASE_DEC, VALS(eigrp_afi2string), 0x0, + NULL, HFILL } + }, + { &hf_eigrp_saf_reachability_port, + { "Port", "eigrp.saf.data.reachability.port", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_eigrp_saf_reachability_protocol, + { "Protocol", "eigrp.saf.data.reachability.protocol", + FT_UINT16, BASE_DEC, NULL, 0x0, + NULL, HFILL } + }, + { &hf_eigrp_saf_reachability_addr_ipv4, + { "IPv4 Addr", "eigrp.saf.data.reachability.addr_ipv4", + FT_IPv4, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_eigrp_saf_reachability_addr_ipv6, + { "IPv6 Addr", "eigrp.saf.data.reachability.addr_ipv6", + FT_IPv6, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + { &hf_eigrp_saf_reachability_addr_hex, + { "Addr", "eigrp.saf.data.reachability.addr_hex", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + + /* misc field used in a couple places */ + { &hf_eigrp_nullpad, + { "Nullpad", "eigrp.nullpad", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL } + }, + }; + + /* Setup protocol subtree array */ + static gint *ett[] = { + /* header flag */ + &ett_eigrp, + &ett_eigrp_flags, + + /* tlv specific */ + &ett_eigrp_tlv, + &ett_eigrp_tlv_metric, + &ett_eigrp_tlv_attr, + &ett_eigrp_tlv_extdata, + + &ett_eigrp_tidlist_flags, + &ett_eigrp_stub_flags, + &ett_eigrp_saf_reachability, + + /* metric tlv specific */ + &ett_eigrp_metric_flags, + &ett_eigrp_extdata_flags, + }; + + /* Register the protocol name and description */ + proto_eigrp = proto_register_protocol( + "Enhanced Interior Gateway Routing Protocol", /* name */ + "EIGRP", /* short name */ + "eigrp" /* abbrev */ + ); + + /* Required function calls to register the header fields and subtrees used */ + proto_register_field_array(proto_eigrp, hf, array_length(hf)); + proto_register_subtree_array(ett, array_length(ett)); + + /* Register preferences module (See Section 2.6 for more on preferences) */ + eigrp_module = prefs_register_protocol(proto_eigrp, + proto_reg_handoff_eigrp); } -void proto_reg_handoff_eigrp(void) { +/** + *@fn void proto_reg_handoff_eigrp(void) + * + * @param[in] void + * @param[out] None + * + * @return void + * + * @usage + * This exact format is required because a script is used to find these + * routines and create the code that calls these routines. + * + * @par + * If this dissector uses sub-dissector registration add a registration routine. + * + * This form of the reg_handoff function is used if if you perform registration + * functions which are dependent upon prefs. If this function is registered as + * a prefs callback (see prefs_register_protocol above) this function is also + * called by preferences whenever "Apply" is pressed; + * + * In that case, it should accommodate being called more than once. + */ +void +proto_reg_handoff_eigrp(void) +{ + static gboolean initialized = FALSE; + static dissector_handle_t eigrp_handle; + + if (!initialized) { + /* Use new_create_dissector_handle() to indicate that dissect_eigrp() + * returns the number of bytes it dissected (or 0 if it thinks the packet + * does not belong to EIGRP). + */ + eigrp_handle = new_create_dissector_handle(dissect_eigrp, proto_eigrp); + initialized = TRUE; + + } else { + /* + If you perform registration functions which are dependent upon + prefs the you should de-register everything which was associated + with the previous settings and re-register using the new prefs + settings here. In general this means you need to keep track of + the eigrp_handle and the value the preference had at the time + you registered. The eigrp_handle value and the value of the + preference can be saved using local statics in this + function (proto_reg_handoff). + */ + ipxsap_handle = find_dissector("ipxsap"); + media_type_table = find_dissector_table("media_type"); - dissector_handle_t eigrp_handle; + eigrp_handle = new_create_dissector_handle(dissect_eigrp, proto_eigrp); - ipxsap_handle = find_dissector("ipxsap"); - eigrp_handle = create_dissector_handle(dissect_eigrp, proto_eigrp); dissector_add_uint("ip.proto", IP_PROTO_EIGRP, eigrp_handle); dissector_add_uint("ddp.type", DDP_EIGRP, eigrp_handle); dissector_add_uint("ipx.socket", IPX_SOCKET_EIGRP, eigrp_handle); + } } |