From Donnie Savage:
authoretxrab <etxrab@f5534014-38df-0310-8fa8-9805f1628bb7>
Mon, 10 Oct 2011 18:11:18 +0000 (18:11 +0000)
committeretxrab <etxrab@f5534014-38df-0310-8fa8-9805f1628bb7>
Mon, 10 Oct 2011 18:11:18 +0000 (18:11 +0000)
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

git-svn-id: http://anonsvn.wireshark.org/wireshark/trunk@39339 f5534014-38df-0310-8fa8-9805f1628bb7

AUTHORS
epan/dissectors/packet-eigrp.c

diff --git a/AUTHORS b/AUTHORS
index b701d5fb45e29ef24adba1f08b0de69d9894fc03..14a11f03e6bc4a1152a0508b1a7d51d0e86a42d9 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -3307,18 +3307,22 @@ Kurnia Hendrawan        <kurnia.hendrawan [AT] consistec.de> {
         Saving User Specified Decodes into profile
 }
 
-Leonard Tracy          <letracy [at] cisco.com> {
+Leonard Tracy          <letracy [AT] cisco.com> {
         Cisco FabricPath protocol dissector
 }
 
-Elliott Aldrich                <elliott [at] aldrichart.com> {
+Elliott Aldrich                <elliott [AT] aldrichart.com> {
         Various icons
 }
 
-Glenn Matthews         <glenn.matthews@cisco.com> {
+Glenn Matthews         <glenn.matthews [AT] cisco.com> {
        XMCP dissector
 }
 
+Donnie Savage           <dsavage [AT] cisco.com> {
+       EIGRP TLV 2.0 and 3.0 support
+       SAF support
+}
 
 and by:
 
index 8f97ecfe62981cb09648488574721fd9e23e0b85..37bffef55e2f1906c2308cdd649109322d7ab9f5 100644 (file)
@@ -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$
  *
  * 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);
+    }
 }