/* packet-eigrp.c * Routines for EIGRP dissection * Copyright 2011, Donnie V Savage * * Complete re-write and replaces previous file of same name authored by: * Copyright 2009, Jochen Bartl * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "config.h" #include #include #include #include #include #include "packet-eigrp.h" #include "packet-ipx.h" #include "packet-atalk.h" /* * Originally Cisco proprietary; now the subject of RFC 7868. */ /** * 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.. who's your daddy! */ #define IGRP2_PROTID 2 /*!< EIGRP - Just flat out the best */ #define STATIC_PROTID 3 /*!< Statically 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_CD 0x02 /*!< Candidate Default */ #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 0x00000001 /* * 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 0x00000002 /* * 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 0x00000004 /* * 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 0x00000008 /** * 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 its 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 */ /* * 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); void proto_register_eigrp(void); /* Initialize the protocol and registered fields */ static int proto_eigrp; /* header */ static int hf_eigrp_version; static int hf_eigrp_opcode; static int hf_eigrp_flags; static int hf_eigrp_sequence; static int hf_eigrp_acknowledge; static int hf_eigrp_vrid; static int hf_eigrp_as; static int ett_eigrp; /* packet header flags */ static int hf_eigrp_flags_init; static int hf_eigrp_flags_restart; static int hf_eigrp_flags_eot; static int hf_eigrp_flags_condrecv; static int ett_eigrp_flags; static int * const eigrp_flag_fields[] = { &hf_eigrp_flags_init, &hf_eigrp_flags_condrecv, &hf_eigrp_flags_restart, &hf_eigrp_flags_eot, NULL }; /* tlv */ static int hf_eigrp_tlv_type; static int hf_eigrp_tlv_len; static int hf_eigrp_tid; static int hf_eigrp_afi; static int hf_eigrp_nullpad; static int ett_eigrp_tlv; static int ett_eigrp_tlv_metric; static int ett_eigrp_tlv_attr; static int ett_eigrp_tlv_extdata; /* param */ static int hf_eigrp_par_k1; static int hf_eigrp_par_k2; static int hf_eigrp_par_k3; static int hf_eigrp_par_k4; static int hf_eigrp_par_k5; static int hf_eigrp_par_k6; static int hf_eigrp_par_holdtime; /* auth */ static int hf_eigrp_auth_type; static int hf_eigrp_auth_len; static int hf_eigrp_auth_keyid; static int hf_eigrp_auth_keyseq; static int hf_eigrp_auth_digest; /* seq */ static int hf_eigrp_seq_addrlen; static int hf_eigrp_seq_ipv4addr; static int hf_eigrp_seq_ipv6addr; /* multicast seq */ static int hf_eigrp_next_mcast_seq; /* stub flags */ static int hf_eigrp_stub_flags; static int hf_eigrp_stub_flags_connected; static int hf_eigrp_stub_flags_static; static int hf_eigrp_stub_flags_summary; static int hf_eigrp_stub_flags_recvonly; static int hf_eigrp_stub_flags_redist; static int hf_eigrp_stub_flags_leakmap; static int ett_eigrp_stub_flags; static int * const 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 }; /* tid */ static int hf_eigrp_tidlist_tid; static int hf_eigrp_tidlist_flags; static int hf_eigrp_tidlist_len; static int ett_eigrp_tidlist; /* 1.2 and 3.0 metric */ static int hf_eigrp_legacy_metric_delay; static int hf_eigrp_legacy_metric_bw; static int hf_eigrp_legacy_metric_mtu; static int hf_eigrp_legacy_metric_hopcount; static int hf_eigrp_legacy_metric_rel; static int hf_eigrp_legacy_metric_load; static int hf_eigrp_legacy_metric_intag; /* 3.0 metric */ static int hf_eigrp_legacy_metric_tag; /* 2.0 metric */ static int hf_eigrp_metric_offset; static int hf_eigrp_metric_priority; static int hf_eigrp_metric_rel; static int hf_eigrp_metric_load; static int hf_eigrp_metric_mtu; static int hf_eigrp_metric_hopcount; static int hf_eigrp_metric_reserved; /* router id*/ static int hf_eigrp_routerid; /* protocol dependent module route flags */ static int hf_eigrp_metric_flags_srcwd; static int hf_eigrp_metric_flags_cd; static int hf_eigrp_metric_flags_active; static int hf_eigrp_metric_flags_repl; static int ett_eigrp_metric_flags; /* extended metrics */ static int hf_eigrp_attr_opcode; static int hf_eigrp_attr_offset; static int hf_eigrp_attr_scaled; static int hf_eigrp_attr_tag; static int hf_eigrp_attr_jitter; static int hf_eigrp_attr_qenergy; static int hf_eigrp_attr_energy; /* route external data */ static int hf_eigrp_extdata_origrid; static int hf_eigrp_extdata_as; static int hf_eigrp_extdata_tag; static int hf_eigrp_extdata_metric; static int hf_eigrp_extdata_reserved; static int hf_eigrp_extdata_proto; static int hf_eigrp_extdata_flag_ext; static int hf_eigrp_extdata_flag_cd; static int ett_eigrp_extdata_flags; /* ipv4 address */ static int hf_eigrp_ipv4_nexthop; static int hf_eigrp_ipv4_prefixlen; /* ipv6 address */ static int hf_eigrp_ipv6_nexthop; static int hf_eigrp_ipv6_prefixlen; /* ipx address */ static int hf_eigrp_ipx_nexthop_net; static int hf_eigrp_ipx_nexthop_host; static int hf_eigrp_ipx_extdata_routerid; static int hf_eigrp_ipx_extdata_delay; static int hf_eigrp_ipx_extdata_metric; static int hf_eigrp_ipx_dest; /* appletalk address */ static int hf_eigrp_atalk_routerid; /* SAF services */ static int hf_eigrp_saf_service; static int hf_eigrp_saf_subservice; static int hf_eigrp_saf_guid; static int hf_eigrp_saf_reachability_afi; static int hf_eigrp_saf_reachability_port; static int hf_eigrp_saf_reachability_protocol; static int hf_eigrp_saf_reachability_addr_ipv4; static int hf_eigrp_saf_reachability_addr_ipv6; static int hf_eigrp_saf_reachability_addr_hex; static int ett_eigrp_saf_reachability; static int hf_eigrp_saf_data_length; static int hf_eigrp_saf_data_sequence; static int hf_eigrp_saf_data_type; /* Generated from convert_proto_tree_add_text.pl */ static int hf_eigrp_ipx_address; static int hf_eigrp_release; static int hf_eigrp_tlv_version; static int hf_eigrp_ipv4_destination; static int hf_eigrp_ipv6_destination; static int hf_eigrp_appletalk_cable_range; static int hf_eigrp_nexthop_address; static int hf_eigrp_cable_range; static int hf_eigrp_metric_delay; static int hf_eigrp_metric_bandwidth; static int hf_eigrp_checksum; static int hf_eigrp_checksum_status; static int hf_eigrp_metric_comm_type; static int ett_metric_comm_type; static int hf_eigrp_extcomm_eigrp_flag; static int hf_eigrp_extcomm_eigrp_tag; static int hf_eigrp_extcomm_eigrp_res; static int hf_eigrp_extcomm_eigrp_rid; static int hf_eigrp_extcomm_eigrp_as; static int hf_eigrp_extcomm_eigrp_sdly; static int hf_eigrp_extcomm_eigrp_rel; static int hf_eigrp_extcomm_eigrp_hop; static int hf_eigrp_extcomm_eigrp_sbw; static int hf_eigrp_extcomm_eigrp_load; static int hf_eigrp_extcomm_eigrp_mtu; static int hf_eigrp_extcomm_eigrp_xas; static int hf_eigrp_extcomm_eigrp_xrid; static int hf_eigrp_extcomm_eigrp_xproto; static int hf_eigrp_extcomm_eigrp_xmetric; static expert_field ei_eigrp_checksum_bad; static expert_field ei_eigrp_unreachable; static expert_field ei_eigrp_seq_addrlen; static expert_field ei_eigrp_peer_termination; static expert_field ei_eigrp_tlv_type; static expert_field ei_eigrp_auth_type; static expert_field ei_eigrp_peer_termination_graceful; static expert_field ei_eigrp_auth_len; static expert_field ei_eigrp_tlv_len; static expert_field ei_eigrp_afi; static expert_field ei_eigrp_prefixlen; static expert_field ei_eigrp_tlv_trunc; /* some extra handle that might be needed */ static dissector_handle_t ipxsap_handle; static dissector_table_t media_type_table; 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_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} }; 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 const value_string eigrp_auth2string[] = { { EIGRP_AUTH_TYPE_TEXT, "TEXT"}, { EIGRP_AUTH_TYPE_MD5, "MD5"}, { EIGRP_AUTH_TYPE_SHA256, "SHA256"}, { 0, NULL}, }; static const value_string eigrp_vrid2string[] = { { EIGRP_VRID_AF_BASE, "(Address-Family)"}, { EIGRP_VRID_SF_BASE, "(Service-Family)"}, { EIGRP_VRID_MCAST_BASE, "(Multi-Cast)"}, { 0, NULL} }; 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"}, { 0, NULL} }; 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} }; static const value_string eigrp_saf_type2string[] = { { EIGRP_SVCDATA_COMPLETE, "Attached Service Data"}, { EIGRP_SVCDATA_TRIMMED, "Trimmed Service Data"}, { 0, NULL} }; 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} }; static const value_string eigrp_metric_comm_type_vals[] = { { EIGRP_EXTCOMM_EIGRP, "EIGRP_EXTCOMM_EIGRP"}, { EIGRP_EXTCOMM_VRR, "EIGRP_EXTCOMM_VRR"}, { EIGRP_EXTCOMM_DAD, "EIGRP_EXTCOMM_DAD"}, { EIGRP_EXTCOMM_VRHB, "EIGRP_EXTCOMM_VRHB"}, { EIGRP_EXTCOMM_SRLM, "EIGRP_EXTCOMM_SRLM"}, { EIGRP_EXTCOMM_SAR, "EIGRP_EXTCOMM_SAR"}, { EIGRP_EXTCOMM_RPM, "EIGRP_EXTCOMM_RPM"}, { EIGRP_EXTCOMM_SOO_ASFMT, "EIGRP_EXTCOMM_SOO_ASFMT"}, { EIGRP_EXTCOMM_SOO_ADRFMT, "EIGRP_EXTCOMM_SOO_ADRFMT"}, { 0, NULL} }; /** *@fn void dissect_eigrp_parameter (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 * * @par * Dissect the Parameter TLV, which is used to convey metric weights and the * hold time. * * @brief * 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; uint8_t k1, k2, k3, k4, k5; k1 = tvb_get_uint8(tvb, offset); proto_tree_add_item(tree, hf_eigrp_par_k1, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; k2 = tvb_get_uint8(tvb, offset); proto_tree_add_item(tree, hf_eigrp_par_k2, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; k3 = tvb_get_uint8(tvb, offset); proto_tree_add_item(tree, hf_eigrp_par_k3, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; k4 = tvb_get_uint8(tvb, offset); proto_tree_add_item(tree, hf_eigrp_par_k4, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; k5 = tvb_get_uint8(tvb, offset); 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_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(pinfo, ti, &ei_eigrp_peer_termination); } } /** *@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 * * @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; uint16_t 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_const(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_NA); 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, &ei_eigrp_auth_len, "Invalid auth len %u", auth_len); } else { proto_tree_add_item(tree, hf_eigrp_auth_digest, tvb, offset, EIGRP_AUTH_TYPE_MD5_LEN, ENC_NA); } break; case EIGRP_AUTH_TYPE_SHA256: if (EIGRP_AUTH_TYPE_SHA256_LEN != auth_len) { expert_add_info_format(pinfo, ti_auth_len, &ei_eigrp_auth_len, "Invalid auth len %u", auth_len); } else { proto_tree_add_item(tree, hf_eigrp_auth_digest, tvb, offset, EIGRP_AUTH_TYPE_SHA256_LEN, ENC_NA); } break; case EIGRP_AUTH_TYPE_NONE: case EIGRP_AUTH_TYPE_TEXT: default: expert_add_info_format(pinfo, ti_auth_type, &ei_eigrp_auth_type, "Invalid auth type %u", auth_type); break; } } /** *@fn void dissect_eigrp_seq_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 * * @par * Dissect the Sequence TLV which consists of the addresses 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) { proto_item *ti_addrlen; int offset = 0; uint8_t addr_len; while (tvb_reported_length_remaining(tvb, offset) > 0) { addr_len = tvb_get_uint8(tvb, offset); ti_addrlen = proto_tree_add_item(tree, hf_eigrp_seq_addrlen, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; if (tvb_reported_length_remaining(tvb, offset) < addr_len) { /* The remaining part of the TLV is shorter than the address it should contain */ expert_add_info(pinfo, ti, &ei_eigrp_tlv_trunc); break; } 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_bytes_format_value(tree, hf_eigrp_ipx_address, tvb, offset, addr_len, NULL, "IPX Address: %s", tvb_address_to_str(pinfo->pool, tvb, AT_IPX, 1)); break; case 16: /* IPv6 */ proto_tree_add_item(tree, hf_eigrp_seq_ipv6addr, tvb, offset, addr_len, ENC_NA); break; default: expert_add_info(pinfo, ti_addrlen, &ei_eigrp_seq_addrlen); } offset += addr_len; } } /** *@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 * * @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; uint8_t ios_rel_major, ios_rel_minor; uint8_t eigrp_rel_major, eigrp_rel_minor; ios_rel_major = tvb_get_uint8(tvb, 0); ios_rel_minor = tvb_get_uint8(tvb, 1); proto_tree_add_item(tree, hf_eigrp_release, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; proto_item_append_text(ti, ": EIGRP=%u.%u", ios_rel_major, ios_rel_minor); eigrp_rel_major = tvb_get_uint8(tvb, 2); eigrp_rel_minor = tvb_get_uint8(tvb, 3); proto_tree_add_item(tree, hf_eigrp_tlv_version, tvb, offset, 2, ENC_BIG_ENDIAN); proto_item_append_text(ti, ", TLV=%u.%u", eigrp_rel_major, eigrp_rel_minor); } /** *@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 * * @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)); } /** *@fn void dissect_eigrp_peer_stubinfo (tvbuff_t *tvb, proto_tree *tree) * * * @param[in,out] tree detail dissection result * @param[in] tvb packet data * * @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, ENC_BIG_ENDIAN); } /** *@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 * * @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(pinfo, ti, &ei_eigrp_peer_termination_graceful); } /** *@fn void dissect_eigrp_peer_tidlist (proto_tree *tree, tvbuff_t *tvb) * * @param[in,out] tree detail dissection result * @param[in] tvb packet data * * @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_tree *sub_tree; int offset = 0; uint16_t size; 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_tree = proto_tree_add_subtree_format(tree, tvb, offset, (size*2), ett_eigrp_tidlist, NULL, "%d TIDs", size); for (; size ; size--) { proto_tree_add_item(sub_tree, hf_eigrp_tidlist_tid, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; } } /** *@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_tree *sub_tree; tvbuff_t *sub_tvb; /* Decode the route flags field */ sub_tree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_eigrp_extdata_flags, NULL, "External Flags"); sub_tvb = tvb_new_subset_remaining(tvb, offset); 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; } /** *@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_tree *sub_tree; tvbuff_t *sub_tvb; /* Decode the route flags field */ sub_tree = proto_tree_add_subtree(tree, tvb, offset, limit, ett_eigrp_metric_flags, NULL, "Flags"); sub_tvb = tvb_new_subset_length_caplen(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_cd, 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; } /** *@fn void dissect_eigrp_ipv4_addrs (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 * * @par * Dissect all IPv4 address from offset though the end of the packet */ static void dissect_eigrp_ipv4_addrs (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int offset, int unreachable) { uint8_t length; ws_in4_addr ip_addr; int addr_len; proto_item *ti_prefixlen, *ti_dst; bool first = true; for (; tvb_reported_length_remaining(tvb, offset) > 0; offset += (1 + addr_len)) { length = tvb_get_uint8(tvb, offset); addr_len = tvb_get_ipv4_addr_with_prefix_len(tvb, offset + 1, &ip_addr, length); if (addr_len < 0) { /* Invalid prefix length, more than 32 bits */ ti_prefixlen = proto_tree_add_item(tree, hf_eigrp_ipv4_prefixlen, tvb, offset, 1, ENC_BIG_ENDIAN); expert_add_info_format(pinfo, ti_prefixlen, &ei_eigrp_prefixlen, "Invalid prefix length %u, must be <= 32", length); break; /* We don't know how long this address is */ } else { address addr; proto_tree_add_item(tree, hf_eigrp_ipv4_prefixlen, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; set_address(&addr, AT_IPv4, 4, &ip_addr); ti_dst = proto_tree_add_ipv4(tree, hf_eigrp_ipv4_destination, tvb, offset, addr_len, ip_addr); /* add it to the top level line */ proto_item_append_text(ti," %c %s/%u", first ? '=':',', address_to_str(pinfo->pool, &addr), length); if (unreachable) { expert_add_info(pinfo, ti_dst, &ei_eigrp_unreachable); } } first = false; } } /** *@fn void dissect_eigrp_ipv6_addrs (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 * * @par * Dissect all IPv6 address from offset though the end of the packet */ static void dissect_eigrp_ipv6_addrs (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int offset, int unreachable) { uint8_t length; int addr_len; ws_in6_addr addr; address addr_str; proto_item *ti_prefixlen, *ti_dst; bool first = true; for (; tvb_reported_length_remaining(tvb, offset) > 0; offset += (1 + addr_len)) { length = tvb_get_uint8(tvb, offset); addr_len = tvb_get_ipv6_addr_with_prefix_len(tvb, offset + 1, &addr, length); if (addr_len < 0) { /* Invalid prefix length, more than 128 bits */ ti_prefixlen = proto_tree_add_item(tree, hf_eigrp_ipv6_prefixlen, tvb, offset, 1, ENC_BIG_ENDIAN); expert_add_info_format(pinfo, ti_prefixlen, &ei_eigrp_prefixlen, "Invalid prefix length %u, must be <= 128", length); break; /* We don't know how long this address is */ } 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++; } set_address(&addr_str, AT_IPv6, 16, addr.bytes); ti_dst = proto_tree_add_ipv6(tree, hf_eigrp_ipv6_destination, tvb, offset, addr_len, &addr); /* add it to the top level line */ proto_item_append_text(ti," %c %s/%u", first ? '=':',', address_to_str(pinfo->pool, &addr_str), length); if (unreachable) { expert_add_info(pinfo, ti_dst, &ei_eigrp_unreachable); } } first = false; } } /** *@fn int dissect_eigrp_ipx_addrs (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_addrs (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_NA); /* add it to the top level line */ proto_item_append_text(ti," = %s", ipxnet_to_str_punct(pinfo->pool, tvb_get_ntohl(tvb, offset), ' ')); if (unreachable) { expert_add_info(pinfo, ti_dst, &ei_eigrp_unreachable); } offset +=4; return offset; } /** *@fn void dissect_eigrp_services (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 * * @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 void dissect_eigrp_services (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; proto_tree *sub_tree, *reach_tree; tvbuff_t *sub_tvb, *reach_tvb; uint16_t service, sub_service; remaining = tvb_captured_length_remaining(tvb, offset); sub_tree = proto_tree_add_subtree(tree, tvb, offset, remaining, ett_eigrp_tlv_metric, &sub_ti, "SAF Service "); sub_tvb = tvb_new_subset_length_caplen(tvb, offset, remaining, -1); sub_offset = 0; for (; tvb_reported_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_const(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_tree = proto_tree_add_subtree(sub_tree, sub_tvb, sub_offset, 22, ett_eigrp_saf_reachability, NULL, "Reachability"); reach_tvb = tvb_new_subset_length_caplen(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_NA); break; case EIGRP_AF_IPv6: proto_tree_add_item(reach_tree, hf_eigrp_saf_reachability_addr_ipv6, reach_tvb, 6, 16, ENC_NA); break; default: /* just print zeros... */ proto_tree_add_item(reach_tree, hf_eigrp_saf_reachability_addr_hex, reach_tvb, 6, 16, ENC_NA); 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; uint8_t *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_length(sub_tvb, sub_offset, length); test_string = tvb_get_string_enc(pinfo->pool, xml_tvb, 0, (length < 32 ? length : 32), ENC_ASCII); 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, NULL); } else { /* Try plain text */ dissector_try_string(media_type_table, "text/plain", xml_tvb, pinfo, sub_tree, NULL); } } sub_offset += length; } } /** *@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_tree *sub_tree; tvbuff_t *sub_tvb; sub_tree = proto_tree_add_subtree(tree, tvb, offset, 16, ett_eigrp_tlv_metric, NULL, "Legacy Metric"); sub_tvb = tvb_new_subset_length_caplen(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; } /** *@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_tree *sub_tree; tvbuff_t *sub_tvb; int sub_offset = 0; sub_tree = proto_tree_add_subtree(tree, tvb, offset, 20, ett_eigrp_tlv_extdata, NULL, "External Data"); sub_tvb = tvb_new_subset_length_caplen(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_NA); 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; } /** *@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_tree *sub_tree; tvbuff_t *sub_tvb; int sub_offset = 0; sub_tree = proto_tree_add_subtree(tree, tvb, offset, 20, ett_eigrp_tlv_extdata, NULL, "External Data"); sub_tvb = tvb_new_subset_length_caplen(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; } /** *@fn int dissect_eigrp_nexthop (proto_tree *tree, tvbuff_t *tvb, uint16_t 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, uint16_t 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; break; case EIGRP_SF_IPv6: case EIGRP_AF_IPv6: proto_tree_add_item(tree, hf_eigrp_ipv6_nexthop, tvb, offset, 16, ENC_NA); offset += 16; break; case EIGRP_AF_IPX: proto_tree_add_item(tree, hf_eigrp_ipx_nexthop_net, tvb, offset, 4, ENC_NA); offset += 4; proto_tree_add_item(tree, hf_eigrp_ipx_nexthop_host, tvb, offset, 6, ENC_NA); offset += 6; break; case EIGRP_SF_COMMON: break; default: break; } return offset; } /** *@fn void dissect_eigrp_general_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, * packet_info *pinfo, uint16_t 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 * * @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, uint16_t 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, ti); 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, &ei_eigrp_tlv_type, "Unknown Generic TLV (0x%04x)", tlv); break; } } /** *@fn void dissect_eigrp_ipv4_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, * packet_info *pinfo, uint16_t 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 * * @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, uint16_t tlv) { int offset = 0; bool 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 */ dissect_eigrp_ipv4_addrs(ti, tree, tvb, pinfo, offset, unreachable); } /** *@fn void dissect_eigrp_atalk_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, * proto_item *ti, uint16_t tlv) * * @param[in,out] tree detail dissection result * @param[in] tvb packet data * @param[in] tlv Specific TLV in to be dissected * * @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, uint16_t tlv) { int offset = 0; /* cable tlv? */ if (EIGRP_TLV_AT_CBL == tlv) { proto_tree_add_item(tree, hf_eigrp_appletalk_cable_range, tvb, 0, 4, ENC_BIG_ENDIAN); 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_item(tree, hf_eigrp_nexthop_address, 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 cable range */ proto_tree_add_item(tree, hf_eigrp_cable_range, tvb, offset, 4, ENC_BIG_ENDIAN); proto_item_append_text(ti, ": %u-%u", tvb_get_ntohs(tvb, 36), tvb_get_ntohs(tvb, 38)); } } /** *@fn void dissect_eigrp_ipv6_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, * packet_info *pinfo, uint16_t 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 * * @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, uint16_t tlv) { int offset = 0; bool unreachable = false; proto_tree_add_item(tree, hf_eigrp_ipv6_nexthop, tvb, offset, 16, ENC_NA); 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_addrs(ti, tree, tvb, pinfo, offset, unreachable); } /** *@fn void dissect_eigrp_ipx_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, * packet_info *pinfo, uint16_t 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 * * @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, uint16_t tlv) { int offset = 0; bool 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 */ dissect_eigrp_ipx_addrs(ti, tree, tvb, pinfo, offset, unreachable); } /** *@fn void dissect_eigrp_multi_topology_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, * packet_info *pinfo, proto_item *ti, uint16_t 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 * * @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, uint16_t tlv) { uint16_t afi; int offset = 2; bool unreachable = false; /* tid for you */ proto_tree_add_item(tree, hf_eigrp_tid, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* now it's 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: dissect_eigrp_ipv4_addrs(ti, tree, tvb, pinfo, offset, unreachable); break; case EIGRP_AF_IPv6: dissect_eigrp_ipv6_addrs(ti, tree, tvb, pinfo, offset, unreachable); break; case EIGRP_AF_IPX: dissect_eigrp_ipx_addrs(ti, tree, tvb, pinfo, offset, unreachable); break; case EIGRP_SF_COMMON: case EIGRP_SF_IPv4: case EIGRP_SF_IPv6: dissect_eigrp_services(ti, tree, tvb, pinfo, offset); break; default: proto_tree_add_expert(tree, pinfo, &ei_eigrp_afi, tvb, offset, -1); } } /** *@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; proto_item* ti; proto_tree* type_tree; while (limit > 0) { comm_type = tvb_get_ntohs(tvb, offset); ti = proto_tree_add_uint(tree, hf_eigrp_metric_comm_type, tvb, offset, 2, comm_type); type_tree = proto_item_add_subtree(ti, ett_metric_comm_type); offset += 2; 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_item(type_tree, hf_eigrp_extcomm_eigrp_flag, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_tag, tvb, offset+2, 4, ENC_BIG_ENDIAN); break; case EIGRP_EXTCOMM_VRR: proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_res, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_rid, tvb, offset+2, 4, ENC_BIG_ENDIAN); break; /* * Vecmetric information for given EIGRP VPNv4 route, * applies to both internal and external */ case EIGRP_EXTCOMM_DAD: proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_as, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_sdly, tvb, offset+2, 4, ENC_BIG_ENDIAN); break; case EIGRP_EXTCOMM_VRHB: proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_rel, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_hop, tvb, offset+1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_sbw, tvb, offset+2, 4, ENC_BIG_ENDIAN); break; case EIGRP_EXTCOMM_SRLM: proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_res, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_load, tvb, offset+1, 1, ENC_BIG_ENDIAN); proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_mtu, tvb, offset+2, 4, ENC_BIG_ENDIAN); break; /* * External information for given EIGRP VPNv4 route, * applies to only to external routes */ case EIGRP_EXTCOMM_SAR: proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_xas, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_xrid, tvb, offset+2, 4, ENC_BIG_ENDIAN); break; case EIGRP_EXTCOMM_RPM: proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_xproto, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_xmetric, tvb, offset+2, 4, ENC_BIG_ENDIAN); break; case EIGRP_EXTCOMM_SOO_ASFMT: case EIGRP_EXTCOMM_SOO_ADRFMT: proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_as, tvb, offset, 2, ENC_BIG_ENDIAN); proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_tag, tvb, offset+2, 4, ENC_BIG_ENDIAN); break; } proto_item_set_len(ti, 8); /*on to the next */ offset += 6; limit -= 8; if (0 != limit%8) { break; } } return offset; } /** *@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 are controlled by * K6 which is now part of the Parameter TLV. Also, eh extended community TLV is * no longer used, as it's now appended to the route */ static int dissect_eigrp_wide_metric_attr (proto_tree *tree, tvbuff_t *tvb, int offset, int limit) { proto_tree *sub_tree; tvbuff_t *sub_tvb; int sub_offset; uint16_t attr_offset = 0; uint8_t attr_opcode = 0; limit *= 2; /* words to bytes */ sub_tree = proto_tree_add_subtree(tree, tvb, offset, limit, ett_eigrp_tlv_attr, NULL, "Attributes"); sub_tvb = tvb_new_subset_length_caplen(tvb, offset, limit, -1); sub_offset = 0; while (limit > 0) { attr_opcode = tvb_get_uint8(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_uint8(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: /* TODO: if this corresponds to RFC 7868, 6.9.3.2, should be scaled bandwidth followed by scaled delay (both 32 bits) ? */ 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_length_caplen(sub_tvb, sub_offset, 8, -1), sub_offset, limit); break; case EIGRP_ATTR_JITTER: /* TODO: RFC 7868 6.9.3.5 suggests this value should be 6 bytes */ proto_tree_add_item(sub_tree, hf_eigrp_attr_jitter, sub_tvb, sub_offset, 4, ENC_BIG_ENDIAN); break; case EIGRP_ATTR_QENERGY: /* TODO: RFC 7868 6.9.3.6 splits this into separate high and low 16-bit values */ proto_tree_add_item(sub_tree, hf_eigrp_attr_qenergy, sub_tvb, sub_offset, 4, ENC_BIG_ENDIAN); break; case EIGRP_ATTR_ENERGY: /* TODO: RFC 7868 6.9.3.7 splits this into separate high and low 16-bit values */ 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); } offset += sub_offset; return offset; } /** *@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_tree *sub_tree; tvbuff_t *sub_tvb; int8_t attr_size = 0; uint64_t big_num; sub_tree = proto_tree_add_subtree(tree, tvb, offset, 24, ett_eigrp_tlv_metric, NULL, "Wide Metric"); sub_tvb = tvb_new_subset_length_caplen(tvb, offset, 24, -1); attr_size = tvb_get_uint8(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); /* 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. */ big_num = tvb_get_ntoh64(sub_tvb, 8); big_num >>= 16; if (big_num == UINT64_C(0x0000ffffffffffff)) { proto_tree_add_uint64_format_value(sub_tree, hf_eigrp_metric_delay, sub_tvb, 8, 6, big_num, "Infinity"); } else { proto_tree_add_uint64(sub_tree, hf_eigrp_metric_delay, sub_tvb, 8, 6, big_num); } /* 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. */ big_num = tvb_get_ntoh64(sub_tvb, 14); big_num >>= 16; if (big_num == UINT64_C(0x0000ffffffffffff)) { proto_tree_add_uint64_format_value(sub_tree, hf_eigrp_metric_bandwidth, sub_tvb, 14, 6, big_num, "Infinity"); } else { proto_tree_add_uint64(sub_tree, hf_eigrp_metric_bandwidth, sub_tvb, 14, 6, 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; } /** *@fn void dissect_eigrp_multi_protocol_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb, * packet_info *pinfo, uint16_t tlv) * * @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 * * @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, uint16_t tlv) { int offset = 0; uint16_t afi; bool unreachable = false; /* tid for you */ proto_tree_add_item(tree, hf_eigrp_tid, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; /* now it's 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: dissect_eigrp_ipv4_addrs(ti, tree, tvb, pinfo, offset, unreachable); break; case EIGRP_AF_IPv6: dissect_eigrp_ipv6_addrs(ti, tree, tvb, pinfo, offset, unreachable); break; case EIGRP_AF_IPX: dissect_eigrp_ipx_addrs(ti, tree, tvb, pinfo, offset, unreachable); break; case EIGRP_SF_COMMON: case EIGRP_SF_IPv4: case EIGRP_SF_IPv6: dissect_eigrp_services(ti, tree, tvb, pinfo, offset); break; default: proto_tree_add_expert(tree, pinfo, &ei_eigrp_afi, tvb, offset, -1); } } /** *@fn int dissect_eigrp (proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, void *data) * * @param[in] tvb packet data * @param[in] pinfo general data about the protocol * @param[in,out] tree detail dissection result * * @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 static int dissect_eigrp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { proto_item *ti; proto_tree *eigrp_tree, *tlv_tree; unsigned opcode, vrid; uint16_t tlv; uint32_t 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_uint8(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. */ /* 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_captured_length(tvb); proto_tree_add_checksum(eigrp_tree, tvb, 2, hf_eigrp_checksum, hf_eigrp_checksum_status, &ei_eigrp_checksum_bad, pinfo, ip_checksum_tvb(tvb, 0, size), ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_IN_CKSUM); /* Decode the EIGRP Flags Field */ proto_tree_add_bitmask(eigrp_tree, tvb, 4, hf_eigrp_flags, ett_eigrp_flags, eigrp_flag_fields, ENC_BIG_ENDIAN); 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_const(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_remaining(tvb, EIGRP_HEADER_LENGTH), pinfo, eigrp_tree); break; default: while (tvb_reported_length_remaining(tvb, offset) > 0) { tlv = tvb_get_ntohs(tvb, offset); /* it's a rose by the wrong name... */ if (tlv == EIGRP_TLV_MTR_TIDLIST) { tlv = EIGRP_TLV_PEER_TIDLIST; } size = tvb_get_ntohs(tvb, offset + 2); if (size < 4) { /* * As the draft says, in section 6.6.2 "Length Field Encoding", * "The value does includes[sic] the Type and Length fields". * * Therefore, it must be at least 4. */ proto_tree_add_expert(eigrp_tree, pinfo, &ei_eigrp_tlv_len, tvb, offset, -1); return tvb_captured_length(tvb); } tlv_tree = proto_tree_add_subtree(eigrp_tree, tvb, offset, size, ett_eigrp_tlv, &ti, val_to_str(tlv, eigrp_tlv2string, "Unknown TLV (0x%04x)")); 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); switch (tlv & EIGRP_TLV_RANGEMASK) { case EIGRP_TLV_GENERAL: dissect_eigrp_general_tlv(ti, tlv_tree, tvb_new_subset_length(tvb, (offset + 4), (size - 4)), pinfo, tlv); break; case EIGRP_TLV_IPv4: dissect_eigrp_ipv4_tlv(ti, tlv_tree, tvb_new_subset_length(tvb, (offset + 4), (size - 4)), pinfo, tlv); break; case EIGRP_TLV_ATALK: dissect_eigrp_atalk_tlv(ti, tlv_tree, tvb_new_subset_length(tvb, (offset + 4), (size - 4)), tlv); break; case EIGRP_TLV_IPX: dissect_eigrp_ipx_tlv(ti, tlv_tree, tvb_new_subset_length(tvb, (offset + 4), (size - 4)), pinfo, tlv); break; case EIGRP_TLV_IPv6: dissect_eigrp_ipv6_tlv(ti, tlv_tree, tvb_new_subset_length(tvb, (offset + 4), (size - 4)), pinfo, tlv); break; case EIGRP_TLV_MP: dissect_eigrp_multi_protocol_tlv(ti, tlv_tree, tvb_new_subset_length(tvb, (offset + 4), (size - 4)), pinfo, tlv); break; case EIGRP_TLV_MTR: dissect_eigrp_multi_topology_tlv(ti, tlv_tree, tvb_new_subset_length(tvb, (offset + 4), (size - 4)), pinfo, tlv); break; default: expert_add_info_format(pinfo, ti, &ei_eigrp_tlv_type, "Unknown TLV Group (0x%04x)", tlv); } offset += size; } break; } /* Return the amount of data this dissector was able to dissect */ return tvb_captured_length(tvb); } static void eigrp_fmt_cable_range(char *result, uint32_t revision ) { snprintf( result, ITEM_LABEL_LENGTH, "%u-%u", (uint16_t)(( revision & 0xFFFF0000 ) >> 16), (uint16_t)(revision & 0xFFFF) ); } static void eigrp_fmt_nexthop_address(char *result, uint32_t revision ) { snprintf( result, ITEM_LABEL_LENGTH, "%u.%u", (uint16_t)(( revision & 0xFFFF0000 ) >> 16), (uint16_t)(revision & 0xFFFF) ); } static void eigrp_fmt_version(char *result, uint32_t revision ) { snprintf( result, ITEM_LABEL_LENGTH, "%d.%02d", (uint8_t)(( revision & 0xFF00 ) >> 8), (uint8_t)(revision & 0xFF) ); } /** *@fn void proto_register_eigrp (void) * * @usage * you can not have the function name inside a comment or else Wireshark * will fail with "duplicate protocol" error. Don't 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) { /* 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_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 } }, /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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, { "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, NULL, EIGRP_OPAQUE_SRCWD, "Route Source Withdraw", HFILL } }, { &hf_eigrp_metric_flags_cd, { "Candidate Default", "eigrp.metric.flags.cd", FT_BOOLEAN, 8, NULL, EIGRP_OPAQUE_CD, NULL, HFILL } }, { &hf_eigrp_metric_flags_active, { "Route is Active", "eigrp.metric.flags.active", FT_BOOLEAN, 8, NULL, 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, NULL, 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, NULL, EIGRP_OPAQUE_EXT, NULL, HFILL } }, { &hf_eigrp_extdata_flag_cd, { "Route is Candidate Default", "eigrp.opaque.flag.cd", FT_BOOLEAN, 8, NULL, EIGRP_OPAQUE_CD, NULL, 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 } }, /* 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_UINT32, BASE_DEC, NULL, 0x0, "Metric calculated from legacy TLVs", HFILL } }, { &hf_eigrp_attr_tag, { "Tag", "eigrp.attr.tag", FT_UINT32, BASE_DEC, NULL, 0x0, "Tag assigned by admin for dest", HFILL } }, { &hf_eigrp_attr_jitter, { "Jitter", "eigrp.attr.jitter", FT_UINT32, BASE_DEC, NULL, 0x0, "Variation in path delay", HFILL } }, { &hf_eigrp_attr_qenergy, { "Q-Energy", "eigrp.attr.qenergy", FT_UINT32, BASE_DEC, NULL, 0x0, "Non-Active energy usage along path", HFILL } }, { &hf_eigrp_attr_energy, { "Energy", "eigrp.attr.energy", FT_UINT32, 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 } }, /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 } }, /* Generated from convert_proto_tree_add_text.pl */ { &hf_eigrp_ipx_address, { "IPX Address", "eigrp.ipx_address", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_eigrp_release, { "EIGRP Release", "eigrp.release_version", FT_UINT16, BASE_CUSTOM, CF_FUNC(eigrp_fmt_version), 0x0, NULL, HFILL }}, { &hf_eigrp_tlv_version, { "EIGRP TLV version", "eigrp.tlv_version", FT_UINT16, BASE_CUSTOM, CF_FUNC(eigrp_fmt_version), 0x0, NULL, HFILL }}, { &hf_eigrp_ipv4_destination, { "Destination", "eigrp.ipv4.destination", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_eigrp_ipv6_destination, { "Destination", "eigrp.ipv6.destination", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }}, { &hf_eigrp_appletalk_cable_range, { "AppleTalk Cable Range", "eigrp.appletalk_cable_range", FT_UINT32, BASE_CUSTOM, CF_FUNC(eigrp_fmt_cable_range), 0x0, NULL, HFILL }}, { &hf_eigrp_nexthop_address, { "NextHop Address", "eigrp.nexthop_address", FT_UINT32, BASE_CUSTOM, CF_FUNC(eigrp_fmt_nexthop_address), 0x0, NULL, HFILL }}, { &hf_eigrp_cable_range, { "Cable range", "eigrp.cable_range", FT_UINT32, BASE_CUSTOM, CF_FUNC(eigrp_fmt_cable_range), 0x0, NULL, HFILL }}, { &hf_eigrp_metric_delay, { "Delay", "eigrp.metric.delay", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_eigrp_metric_bandwidth, { "Bandwidth", "eigrp.metric.bandwidth", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_eigrp_checksum, { "Checksum", "eigrp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_eigrp_checksum_status, { "Checksum Status", "eigrp.checksum.status", FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0, NULL, HFILL }}, { &hf_eigrp_metric_comm_type, { "Type", "eigrp.metric.comm_type", FT_UINT16, BASE_DEC, VALS(eigrp_metric_comm_type_vals), 0x0, NULL, HFILL }}, { &hf_eigrp_extcomm_eigrp_flag, { "FLAG", "eigrp.extcomm.flag", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_eigrp_extcomm_eigrp_tag, { "TAG", "eigrp.extcomm.tag", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_eigrp_extcomm_eigrp_res, { "RES", "eigrp.extcomm.res", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_eigrp_extcomm_eigrp_rid, { "RID", "eigrp.extcomm.rid", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_eigrp_extcomm_eigrp_as, { "AS", "eigrp.extcomm.as", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_eigrp_extcomm_eigrp_sdly, { "SDLY", "eigrp.extcomm.sdly", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_eigrp_extcomm_eigrp_rel, { "RID", "eigrp.extcomm.rel", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_eigrp_extcomm_eigrp_hop, { "AS", "eigrp.extcomm.hop", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_eigrp_extcomm_eigrp_sbw, { "SDLY", "eigrp.extcomm.sbw", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_eigrp_extcomm_eigrp_load, { "LOAD", "eigrp.extcomm.load", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_eigrp_extcomm_eigrp_mtu, { "MTU", "eigrp.extcomm.mtu", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_eigrp_extcomm_eigrp_xas, { "xAS", "eigrp.extcomm.xas", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_eigrp_extcomm_eigrp_xrid, { "xRID", "eigrp.extcomm.xrid", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, { &hf_eigrp_extcomm_eigrp_xproto, { "xProto", "eigrp.extcomm.xproto", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }}, { &hf_eigrp_extcomm_eigrp_xmetric, { "xMETRIC", "eigrp.extcomm.xmetric", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }}, }; /* Setup protocol subtree array */ static int *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, &ett_eigrp_stub_flags, &ett_eigrp_saf_reachability, /* metric tlv specific */ &ett_eigrp_metric_flags, &ett_eigrp_extdata_flags, &ett_metric_comm_type }; static ei_register_info ei[] = { { &ei_eigrp_peer_termination, { "eigrp.peer_termination", PI_RESPONSE_CODE, PI_NOTE, "Peer Termination", EXPFILL }}, { &ei_eigrp_auth_len, { "eigrp.auth.length.invalid", PI_MALFORMED, PI_WARN, "Invalid auth len", EXPFILL }}, { &ei_eigrp_auth_type, { "eigrp.auth.type.invalid", PI_PROTOCOL, PI_WARN, "Invalid auth type", EXPFILL }}, { &ei_eigrp_seq_addrlen, { "eigrp.seq.addrlen.invalid", PI_MALFORMED, PI_ERROR, "Invalid address length", EXPFILL }}, { &ei_eigrp_peer_termination_graceful, { "eigrp.peer_termination_graceful", PI_RESPONSE_CODE, PI_NOTE, "Peer Termination (Graceful Shutdown)", EXPFILL }}, { &ei_eigrp_prefixlen, { "eigrp.prefixlen.invalid", PI_MALFORMED, PI_WARN, "Invalid prefix length", EXPFILL }}, { &ei_eigrp_unreachable, { "eigrp.unreachable", PI_RESPONSE_CODE, PI_NOTE, "Unreachable", EXPFILL }}, { &ei_eigrp_tlv_type, { "eigrp.tlv_type.unknown", PI_PROTOCOL, PI_WARN, "Unknown TLV", EXPFILL }}, { &ei_eigrp_afi, { "eigrp.afi.unknown", PI_PROTOCOL, PI_WARN, "Unknown AFI", EXPFILL }}, { &ei_eigrp_checksum_bad, { "eigrp.checksum.bad", PI_CHECKSUM, PI_WARN, "Bad Checksum", EXPFILL }}, { &ei_eigrp_tlv_len, { "eigrp.tlv.len.invalid", PI_MALFORMED, PI_ERROR, "Corrupt TLV (Length field less than 4)", EXPFILL }}, { &ei_eigrp_tlv_trunc, { "eigrp.tlv.truncated", PI_MALFORMED, PI_ERROR, "Corrupt TLV (Truncated prematurely)", EXPFILL }}, }; expert_module_t* expert_eigrp; /* Register the protocol name and description */ proto_eigrp = proto_register_protocol("Enhanced Interior Gateway Routing Protocol", "EIGRP", "eigrp"); register_dissector("eigrp", dissect_eigrp, proto_eigrp); /* 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)); expert_eigrp = expert_register_protocol(proto_eigrp); expert_register_field_array(expert_eigrp, ei, array_length(ei)); } /** *@fn void proto_reg_handoff_eigrp(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 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) { dissector_handle_t eigrp_handle = find_dissector("eigrp"); ipxsap_handle = find_dissector_add_dependency("ipxsap", proto_eigrp); media_type_table = find_dissector_table("media_type"); 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); } /* * Editor modelines - https://www.wireshark.org/tools/modelines.html * * Local variables: * c-basic-offset: 4 * tab-width: 8 * indent-tabs-mode: nil * End: * * vi: set shiftwidth=4 tabstop=8 expandtab: * :indentSize=4:tabSize=8:noTabs=true: */