1 /* packet-eigrp.c
2  * Routines for EIGRP dissection
3  * Copyright 2011, Donnie V Savage <dsavage@cisco.com>
4  *
5  * Complete re-write and replaces previous file of same name authored by:
6  *    Copyright 2009, Jochen Bartl <jochen.bartl@gmail.co
7  *    Copyright 2000, Paul Ionescu <paul@acorp.ro>
8  *
9  * Wireshark - Network traffic analyzer
10  * By Gerald Combs <gerald@wireshark.org>
11  * Copyright 1998 Gerald Combs
12  *
13  * SPDX-License-Identifier: GPL-2.0-or-later
14  */
15 #include "config.h"
16 
17 #include <epan/packet.h>
18 #include <epan/addr_resolv.h>
19 #include <epan/addr_and_mask.h>
20 #include <epan/ipproto.h>
21 #include <epan/expert.h>
22 
23 #include "packet-eigrp.h"
24 #include "packet-ipx.h"
25 #include "packet-atalk.h"
26 
27 /*
28  * Originally Cisco proprietary; now the subject of RFC 7868.
29  */
30 
31 /**
32  * EIGRP Header size in bytes
33  */
34 #define EIGRP_HEADER_LENGTH     20
35 
36 /**
37  * EIGRP Packet Opcodes
38  */
39 #define EIGRP_OPC_UPDATE        1       /*!< packet containing routing information */
40 #define EIGRP_OPC_REQUEST       2       /*!< sent to request one or more routes */
41 #define EIGRP_OPC_QUERY         3       /*!< sent when a routing is in active start */
42 #define EIGRP_OPC_REPLY         4       /*!< sent in response to a query */
43 #define EIGRP_OPC_HELLO         5       /*!< sent to maintain a peering session */
44 #define EIGRP_OPC_IPXSAP        6       /*!< IPX SAP information */
45 #define EIGRP_OPC_PROBE         7       /*!< for test purposes   */
46 #define EIGRP_OPC_ACK           8       /*!< acknowledge         */
47 #define EIGRP_OPC_STUB          9       /*!< peering operating in restricted mode */
48 #define EIGRP_OPC_SIAQUERY      10      /*!< QUERY - with relaxed restrictions */
49 #define EIGRP_OPC_SIAREPLY      11      /*!< REPLY - may contain old routing information */
50 
51 /**
52  * EIGRP TLV Range definitions
53  *      PDM             TLV Range
54  *      General         0x0000
55  *      IPv4            0x0100          ** TLVs for one and all
56  *      ATALK           0x0200          ** legacy
57  *      IPX             0x0300          ** discontinued
58  *      IPv6            0x0400          ** legacy
59  *      Multiprotocol   0x0600          ** wide metrics
60  *      MultiTopology   0x00f0          ** deprecated
61  */
62 #define EIGRP_TLV_RANGEMASK     0xfff0  /*!< should be 0xff00 - opps     */
63 #define EIGRP_TLV_GENERAL       0x0000
64 
65 /**
66  * 1.2 TLV Definitions  ** legacy
67  * These have been deprecated and should not be used for future packets
68  */
69 #define EIGRP_TLV_IPv4          0x0100          /*!< Classic IPv4 TLV encoding */
70 #define EIGRP_TLV_ATALK         0x0200          /*!< Classic Appletalk TLV encoding*/
71 #define EIGRP_TLV_IPX           0x0300          /*!< Classic IPX TLV encoding */
72 #define EIGRP_TLV_IPv6          0x0400          /*!< Classic IPv6 TLV encoding */
73 
74 /**
75  * 2.0 Multi-Protocol TLV Definitions
76  * These have been deprecated and should not be used for future packets
77  */
78 #define EIGRP_TLV_MP            0x0600  /*!< Non-PDM specific encoding */
79 
80 /**
81  * 3.0 TLV Definitions  ** deprecated
82  * These have been deprecated and should not be used for future packets
83  */
84 #define EIGRP_TLV_MTR           0x00f0          /*!< MTR TLV encoding */
85 
86 /**
87  * TLV type definitions.  Generic (protocol-independent) TLV types are
88  * defined here.  Protocol-specific ones are defined elsewhere.
89  */
90 #define EIGRP_TLV_PARAMETER             (EIGRP_TLV_GENERAL | 0x0001)    /*!< eigrp parameters */
91 #define EIGRP_TLV_AUTH                  (EIGRP_TLV_GENERAL | 0x0002)    /*!< authentication */
92 #define EIGRP_TLV_SEQ                   (EIGRP_TLV_GENERAL | 0x0003)    /*!< sequenced packet */
93 #define EIGRP_TLV_SW_VERSION            (EIGRP_TLV_GENERAL | 0x0004)    /*!< software version */
94 #define EIGRP_TLV_NEXT_MCAST_SEQ        (EIGRP_TLV_GENERAL | 0x0005)    /*!< */
95 #define EIGRP_TLV_PEER_STUBINFO         (EIGRP_TLV_GENERAL | 0x0006)    /*!< stub information */
96 #define EIGRP_TLV_PEER_TERMINATION      (EIGRP_TLV_GENERAL | 0x0007)    /*!< peer termination */
97 #define EIGRP_TLV_PEER_TIDLIST          (EIGRP_TLV_GENERAL | 0x0008)    /*!< peer sub-topology list */
98 
99 /**
100  * Route Based TLVs
101  */
102 #define EIGRP_TLV_TYPEMASK      0x000f
103 #define EIGRP_TLV_REQUEST       0x0001
104 #define EIGRP_TLV_INTERNAL      0x0002
105 #define EIGRP_TLV_EXTERNAL      0x0003
106 #define EIGRP_TLV_COMMUNITY     0x0004
107 
108 /* Legacy TLV formats */
109 #define EIGRP_TLV_IPv4_REQ      (EIGRP_TLV_IPv4 | EIGRP_TLV_REQUEST)
110 #define EIGRP_TLV_IPv4_INT      (EIGRP_TLV_IPv4 | EIGRP_TLV_INTERNAL)
111 #define EIGRP_TLV_IPv4_EXT      (EIGRP_TLV_IPv4 | EIGRP_TLV_EXTERNAL)
112 #define EIGRP_TLV_IPv4_COM      (EIGRP_TLV_IPv4 | EIGRP_TLV_COMMUNITY)
113 #define EIGRP_TLV_IPX_INT       (EIGRP_TLV_IPX | EIGRP_TLV_INTERNAL)
114 #define EIGRP_TLV_IPX_EXT       (EIGRP_TLV_IPX | EIGRP_TLV_EXTERNAL)
115 #define EIGRP_TLV_IPX_COM       (EIGRP_TLV_IPX | EIGRP_TLV_COMMUNITY)
116 #define EIGRP_TLV_IPv6_INT      (EIGRP_TLV_IPv6 | EIGRP_TLV_INTERNAL)
117 #define EIGRP_TLV_IPv6_EXT      (EIGRP_TLV_IPv6 | EIGRP_TLV_EXTERNAL)
118 #define EIGRP_TLV_IPv6_COM      (EIGRP_TLV_IPv6 | EIGRP_TLV_COMMUNITY)
119 
120 /* Deprecated TLV formats */
121 #define EIGRP_TLV_AT_INT        (EIGRP_TLV_ATALK | EIGRP_TLV_INTERNAL)
122 #define EIGRP_TLV_AT_EXT        (EIGRP_TLV_ATALK | EIGRP_TLV_EXTERNAL)
123 #define EIGRP_TLV_AT_CBL        (EIGRP_TLV_ATALK | 0x04)
124 #define EIGRP_TLV_MTR_REQ       (EIGRP_TLV_MTR | EIGRP_TLV_REQUEST)
125 #define EIGRP_TLV_MTR_INT       (EIGRP_TLV_MTR | EIGRP_TLV_INTERNAL)
126 #define EIGRP_TLV_MTR_EXT       (EIGRP_TLV_MTR | EIGRP_TLV_EXTERNAL)
127 #define EIGRP_TLV_MTR_COM       (EIGRP_TLV_MTR | EIGRP_TLV_COMMUNITY)
128 #define EIGRP_TLV_MTR_TIDLIST   (EIGRP_TLV_MTR | 0x0005)
129 
130 /* Current "Wide Metric" TLV formats */
131 #define EIGRP_TLV_MP_REQ        (EIGRP_TLV_MP | EIGRP_TLV_REQUEST)
132 #define EIGRP_TLV_MP_INT        (EIGRP_TLV_MP | EIGRP_TLV_INTERNAL)
133 #define EIGRP_TLV_MP_EXT        (EIGRP_TLV_MP | EIGRP_TLV_EXTERNAL)
134 #define EIGRP_TLV_MP_COM        (EIGRP_TLV_MP | EIGRP_TLV_COMMUNITY)
135 
136 /**
137  * External routes originate from some other protocol - these are them
138  */
139 #define NULL_PROTID     0       /*!< unknown protocol */
140 #define IGRP1_PROTID    1       /*!< IGRP.. who's your daddy! */
141 #define IGRP2_PROTID    2       /*!< EIGRP - Just flat out the best */
142 #define STATIC_PROTID   3       /*!< Staticly configured source */
143 #define RIP_PROTID      4       /*!< Routing Information Protocol */
144 #define HELLO_PROTID    5       /*!< Hello? RFC-891 you there? */
145 #define OSPF_PROTID     6       /*!< OSPF - Open Shortest Path First */
146 #define ISIS_PROTID     7       /*!< Intermediate System To Intermediate System */
147 #define EGP_PROTID      8       /*!< Exterior Gateway Protocol */
148 #define BGP_PROTID      9       /*!< Border Gateway Protocol */
149 #define IDRP_PROTID     10      /*!< InterDomain Routing Protocol */
150 #define CONN_PROTID     11      /*!< Connected source */
151 
152 /**
153  *
154  * extdata flag field definitions
155  */
156 #define EIGRP_OPAQUE_EXT      0x01   /*!< Route is external */
157 #define EIGRP_OPAQUE_CD       0x02   /*!< Candidate default route */
158 
159 /**
160  * Address-Family types are taken from:
161  *       http://www.iana.org/assignments/address-family-numbers
162  * to provide a standards based exchange of AFI information between
163  * EIGRP routers.
164  */
165 #define EIGRP_AF_IPv4           1       /*!< IPv4 (IP version 4) */
166 #define EIGRP_AF_IPv6           2       /*!< IPv6 (IP version 6) */
167 #define EIGRP_AF_IPX            11      /*!< IPX */
168 #define EIGRP_AF_ATALK          12      /*!< Appletalk */
169 #define EIGRP_SF_COMMON         16384   /*!< Cisco Service Family */
170 #define EIGRP_SF_IPv4           16385   /*!< Cisco IPv4 Service Family */
171 #define EIGRP_SF_IPv6           16386   /*!< Cisco IPv6 Service Family */
172 
173 /**
174  * Authentication types supported by EIGRP
175  */
176 #define EIGRP_AUTH_TYPE_NONE            0
177 #define EIGRP_AUTH_TYPE_TEXT            1
178 #define EIGRP_AUTH_TYPE_MD5             2
179 #define EIGRP_AUTH_TYPE_MD5_LEN         16
180 #define EIGRP_AUTH_TYPE_SHA256          3
181 #define EIGRP_AUTH_TYPE_SHA256_LEN      32
182 
183 /**
184  * opaque flag field definitions
185  */
186 #define EIGRP_OPAQUE_SRCWD    0x01   /*!< Route Source Withdraw */
187 #define EIGRP_OPAQUE_CD       0x02   /*!< Candidate Default */
188 #define EIGRP_OPAQUE_ACTIVE   0x04   /*!< Route is currently in active state */
189 #define EIGRP_OPAQUE_REPL     0x08   /*!< Route is replicated from different tableid */
190 
191 /**
192  * pak flag bit field definitions - 0 (none)-7 source priority
193  */
194 #define EIGRP_PRIV_DEFAULT      0x00   /* 0 (none)-7 source priority */
195 #define EIGRP_PRIV_LOW          0x01
196 #define EIGRP_PRIV_MEDIUM       0x04
197 #define EIGRP_PRIV_HIGH         0x07
198 
199 /**
200  * stub bit definitions
201  */
202 #define EIGRP_PEER_ALLOWS_CONNECTED     0x0001
203 #define EIGRP_PEER_ALLOWS_STATIC        0x0002
204 #define EIGRP_PEER_ALLOWS_SUMMARY       0x0004
205 #define EIGRP_PEER_ALLOWS_REDIST        0x0008
206 #define EIGRP_PEER_ALLOWS_LEAKING       0x0010
207 #define EIGRP_PEER_ALLOWS_RCVONLY       0x0020
208 
209 /*
210  * Init bit definition. First unicast transmitted Update has this
211  * bit set in the flags field of the fixed header. It tells the neighbor
212  * to down-load his topology table.
213  */
214 #define EIGRP_INIT_FLAG 0x01
215 
216 /*
217  * CR bit (Conditionally Received) definition in flags field on header. Any
218  * packets with the CR-bit set can be accepted by an EIGRP speaker if and
219  * only if a previous Hello was received with the SEQUENCE_TYPE TLV present.
220  *
221  * This allows multicasts to be transmitted in order and reliably at the
222  * same time as unicasts are transmitted.
223  */
224 #define EIGRP_CR_FLAG 0x02
225 
226 /*
227  * RS bit.  The Restart flag is set in the hello and the init
228  * update packets during the nsf signaling period.  A nsf-aware
229  * router looks at the RS flag to detect if a peer is restarting
230  * and maintain the adjacency. A restarting router looks at
231  * this flag to determine if the peer is helping out with the restart.
232  */
233 #define EIGRP_RS_FLAG 0x04
234 
235 /*
236  * EOT bit.  The End-of-Table flag marks the end of the start-up updates
237  * sent to a new peer.  A nsf restarting router looks at this flag to
238  * determine if it has finished receiving the start-up updates from all
239  * peers.  A nsf-aware router waits for this flag before cleaning up
240  * the stale routes from the restarting peer.
241  */
242 #define EIGRP_EOT_FLAG 0x08
243 
244 /**
245  * EIGRP Virtual Router ID
246  *
247  * Define values to deal with EIGRP virtual router ids.  Virtual
248  * router IDs are stored in the upper short of the EIGRP fixed packet
249  * header.  The lower short of the packet header continues to be used
250  * as asystem number.
251  *
252  * Virtual Router IDs are PDM-independent.  All PDMs will use
253  * VRID_BASE to indicate the 'base' or 'legacy' EIGRP instance.
254  * All PDMs need to initialize their vrid to VRID_BASE for compatibility
255  * with legacy routers.
256  * Once IPv6 supports 'MTR Multicast', it will use the same VRID as
257  * IPv4.  No current plans to support VRIDs on IPX. :)
258  * Initial usage of VRID is to signal usage of Multicast topology for
259  * MTR.
260  *
261  * VRID_MCAST is a well known constant, other VRIDs will be determined
262  * programmatic...
263  *
264  * With the addition of SAF the VRID space has been divided into two
265  * segments 0x0000-0x7fff is for EIGRP and vNets, 0x8000-0xffff is
266  * for saf and its associated vNets.
267  */
268 #define EIGRP_VRID_MASK         0x8001
269 #define EIGRP_VRID_AF_BASE      0x0000
270 #define EIGRP_VRID_MCAST_BASE   0x0001
271 #define EIGRP_VRID_SF_BASE      0x8000
272 
273 /* Extended Attributes for a destination */
274 #define EIGRP_ATTR_HDRLEN (2)
275 #define EIGRP_ATTR_MAXDATA (512)
276 
277 #define EIGRP_ATTR_NOOP         0       /*!< No-Op used as offset padding */
278 #define EIGRP_ATTR_SCALED       1       /*!< Scaled metric values */
279 #define EIGRP_ATTR_TAG          2       /*!< Tag assigned by Admin for dest */
280 #define EIGRP_ATTR_COMM         3       /*!< Community attribute for dest */
281 #define EIGRP_ATTR_JITTER       4       /*!< Variation in path delay */
282 #define EIGRP_ATTR_QENERGY      5       /*!< Non-Active energy usage along path */
283 #define EIGRP_ATTR_ENERGY       6       /*!< Active energy usage along path */
284 
285 /*
286  * Begin EIGRP-BGP interoperability communities
287  */
288 #define EIGRP_EXTCOMM_SOO_ASFMT         0x0003 /* Site-of-Origin, BGP AS format */
289 #define EIGRP_EXTCOMM_SOO_ADRFMT        0x0103 /* Site-of-Origin, BGP/EIGRP addr format */
290 
291 /*
292  * EIGRP Specific communities
293  */
294 #define EIGRP_EXTCOMM_EIGRP             0x8800 /* EIGRP route information appended*/
295 #define EIGRP_EXTCOMM_DAD               0x8801 /* EIGRP AS + Delay           */
296 #define EIGRP_EXTCOMM_VRHB              0x8802 /* EIGRP Vector: Reliability + Hop + BW */
297 #define EIGRP_EXTCOMM_SRLM              0x8803 /* EIGRP System: Reserve +Load + MTU   */
298 #define EIGRP_EXTCOMM_SAR               0x8804 /* EIGRP System: Remote AS + Remote ID  */
299 #define EIGRP_EXTCOMM_RPM               0x8805 /* EIGRP Remote: Protocol + Metric    */
300 #define EIGRP_EXTCOMM_VRR               0x8806 /* EIGRP Vecmet: Rsvd + (internal) Routerid */
301 
302 /* SAF types */
303 #define EIGRP_SVCDATA_COMPLETE          0x01    /*!< Data is attached */
304 #define EIGRP_SVCDATA_TRIMMED           0x02    /*!< Data was trimmed from service */
305 
306 /* SAF Defined Numbers */
307 #define SAF_SERVICE_ID_CAPMAN   100             /*!< Capabilities Manager */
308 #define SAF_SERVICE_ID_UC       101             /*!< Unified Communications */
309 #define SAF_SERVICE_ID_PFR      102             /*!< Performance Routing */
310 
311 /* Forward declaration we need below (if using proto_reg_handoff...
312    as a prefs callback)       */
313 void proto_reg_handoff_eigrp(void);
314 void proto_register_eigrp(void);
315 
316 /* Initialize the protocol and registered fields */
317 static int proto_eigrp = -1;
318 
319 /* header */
320 static gint hf_eigrp_version = -1;
321 static gint hf_eigrp_opcode = -1;
322 static gint hf_eigrp_flags = -1;
323 static gint hf_eigrp_sequence = -1;
324 static gint hf_eigrp_acknowledge = -1;
325 static gint hf_eigrp_vrid = -1;
326 static gint hf_eigrp_as = -1;
327 static gint ett_eigrp = -1;
328 
329 /* packet header flags */
330 static gint hf_eigrp_flags_init = -1;
331 static gint hf_eigrp_flags_restart = -1;
332 static gint hf_eigrp_flags_eot = -1;
333 static gint hf_eigrp_flags_condrecv = -1;
334 
335 static gint ett_eigrp_flags = -1;
336 static int * const eigrp_flag_fields[] = {
337     &hf_eigrp_flags_init,
338     &hf_eigrp_flags_condrecv,
339     &hf_eigrp_flags_restart,
340     &hf_eigrp_flags_eot,
341     NULL
342 };
343 
344 /* tlv */
345 static gint hf_eigrp_tlv_type = -1;
346 static gint hf_eigrp_tlv_len = -1;
347 static gint hf_eigrp_tid = -1;
348 static gint hf_eigrp_afi = -1;
349 static gint hf_eigrp_nullpad = -1;
350 
351 static gint ett_eigrp_tlv = -1;
352 static gint ett_eigrp_tlv_metric = -1;
353 static gint ett_eigrp_tlv_attr = -1;
354 static gint ett_eigrp_tlv_extdata = -1;
355 
356 /* param */
357 static gint hf_eigrp_par_k1 = -1;
358 static gint hf_eigrp_par_k2 = -1;
359 static gint hf_eigrp_par_k3 = -1;
360 static gint hf_eigrp_par_k4 = -1;
361 static gint hf_eigrp_par_k5 = -1;
362 static gint hf_eigrp_par_k6 = -1;
363 static gint hf_eigrp_par_holdtime = -1;
364 
365 /* auth */
366 static gint hf_eigrp_auth_type = -1;
367 static gint hf_eigrp_auth_len = -1;
368 static gint hf_eigrp_auth_keyid = -1;
369 static gint hf_eigrp_auth_keyseq = -1;
370 static gint hf_eigrp_auth_digest = -1;
371 
372 /* seq */
373 static gint hf_eigrp_seq_addrlen = -1;
374 static gint hf_eigrp_seq_ipv4addr = -1;
375 static gint hf_eigrp_seq_ipv6addr = -1;
376 
377 /* multicast seq */
378 static gint hf_eigrp_next_mcast_seq = -1;
379 
380 /* stub flags */
381 static gint hf_eigrp_stub_flags = -1;
382 static gint hf_eigrp_stub_flags_connected = -1;
383 static gint hf_eigrp_stub_flags_static = -1;
384 static gint hf_eigrp_stub_flags_summary = -1;
385 static gint hf_eigrp_stub_flags_recvonly = -1;
386 static gint hf_eigrp_stub_flags_redist = -1;
387 static gint hf_eigrp_stub_flags_leakmap = -1;
388 
389 static gint ett_eigrp_stub_flags = -1;
390 static int * const eigrp_stub_flag_fields[] = {
391     &hf_eigrp_stub_flags_connected,
392     &hf_eigrp_stub_flags_static,
393     &hf_eigrp_stub_flags_summary,
394     &hf_eigrp_stub_flags_redist,
395     &hf_eigrp_stub_flags_leakmap,
396     &hf_eigrp_stub_flags_recvonly,
397     NULL
398 };
399 
400 /* tid */
401 static gint hf_eigrp_tidlist_tid = -1;
402 static gint hf_eigrp_tidlist_flags = -1;
403 static gint hf_eigrp_tidlist_len = -1;
404 static gint ett_eigrp_tidlist = -1;
405 
406 /* 1.2 and 3.0 metric */
407 static gint hf_eigrp_legacy_metric_delay = -1;
408 static gint hf_eigrp_legacy_metric_bw = -1;
409 static gint hf_eigrp_legacy_metric_mtu = -1;
410 static gint hf_eigrp_legacy_metric_hopcount = -1;
411 static gint hf_eigrp_legacy_metric_rel = -1;
412 static gint hf_eigrp_legacy_metric_load = -1;
413 static gint hf_eigrp_legacy_metric_intag = -1;
414 
415 /* 3.0 metric */
416 static gint hf_eigrp_legacy_metric_tag = -1;
417 
418 /* 2.0 metric */
419 static gint hf_eigrp_metric_offset = -1;
420 static gint hf_eigrp_metric_priority = -1;
421 static gint hf_eigrp_metric_rel = -1;
422 static gint hf_eigrp_metric_load = -1;
423 static gint hf_eigrp_metric_mtu = -1;
424 static gint hf_eigrp_metric_hopcount = -1;
425 static gint hf_eigrp_metric_reserved = -1;
426 
427 /* router id*/
428 static gint hf_eigrp_routerid = -1;
429 
430 /* protocol dependent module route flags */
431 static gint hf_eigrp_metric_flags_srcwd = -1;
432 static gint hf_eigrp_metric_flags_cd = -1;
433 static gint hf_eigrp_metric_flags_active = -1;
434 static gint hf_eigrp_metric_flags_repl = -1;
435 static gint ett_eigrp_metric_flags = -1;
436 
437 /* extended metrics */
438 static gint hf_eigrp_attr_opcode = -1;
439 static gint hf_eigrp_attr_offset = -1;
440 static gint hf_eigrp_attr_scaled = -1;
441 static gint hf_eigrp_attr_tag = -1;
442 static gint hf_eigrp_attr_jitter = -1;
443 static gint hf_eigrp_attr_qenergy = -1;
444 static gint hf_eigrp_attr_energy = -1;
445 
446 /* route external data */
447 static gint hf_eigrp_extdata_origrid = -1;
448 static gint hf_eigrp_extdata_as = -1;
449 static gint hf_eigrp_extdata_tag = -1;
450 static gint hf_eigrp_extdata_metric = -1;
451 static gint hf_eigrp_extdata_reserved = -1;
452 static gint hf_eigrp_extdata_proto = -1;
453 
454 static gint hf_eigrp_extdata_flag_ext = -1;
455 static gint hf_eigrp_extdata_flag_cd = -1;
456 static gint ett_eigrp_extdata_flags = -1;
457 
458 /* ipv4 address */
459 static gint hf_eigrp_ipv4_nexthop = -1;
460 static gint hf_eigrp_ipv4_prefixlen = -1;
461 
462 /* ipv6 address */
463 static gint hf_eigrp_ipv6_nexthop = -1;
464 static gint hf_eigrp_ipv6_prefixlen = -1;
465 
466 /* ipx address */
467 static gint hf_eigrp_ipx_nexthop_net = -1;
468 static gint hf_eigrp_ipx_nexthop_host = -1;
469 static gint hf_eigrp_ipx_extdata_routerid = -1;
470 static gint hf_eigrp_ipx_extdata_delay = -1;
471 static gint hf_eigrp_ipx_extdata_metric = -1;
472 static gint hf_eigrp_ipx_dest = -1;
473 
474 /* appletalk address */
475 static gint hf_eigrp_atalk_routerid = -1;
476 
477 /* SAF services */
478 static gint hf_eigrp_saf_service = -1;
479 static gint hf_eigrp_saf_subservice = -1;
480 static gint hf_eigrp_saf_guid = -1;
481 
482 static gint hf_eigrp_saf_reachability_afi = -1;
483 static gint hf_eigrp_saf_reachability_port = -1;
484 static gint hf_eigrp_saf_reachability_protocol = -1;
485 static gint hf_eigrp_saf_reachability_addr_ipv4 = -1;
486 static gint hf_eigrp_saf_reachability_addr_ipv6 = -1;
487 static gint hf_eigrp_saf_reachability_addr_hex = -1;
488 static gint ett_eigrp_saf_reachability = -1;
489 
490 static gint hf_eigrp_saf_data_length = -1;
491 static gint hf_eigrp_saf_data_sequence = -1;
492 static gint hf_eigrp_saf_data_type = -1;
493 
494 /* Generated from convert_proto_tree_add_text.pl */
495 static int hf_eigrp_ipx_address = -1;
496 static int hf_eigrp_release = -1;
497 static int hf_eigrp_tlv_version = -1;
498 static int hf_eigrp_ipv4_destination = -1;
499 static int hf_eigrp_ipv6_destination = -1;
500 static int hf_eigrp_appletalk_cable_range = -1;
501 static int hf_eigrp_nexthop_address = -1;
502 static int hf_eigrp_cable_range = -1;
503 static int hf_eigrp_metric_delay = -1;
504 static int hf_eigrp_metric_bandwidth = -1;
505 static int hf_eigrp_checksum = -1;
506 static int hf_eigrp_checksum_status = -1;
507 static int hf_eigrp_metric_comm_type = -1;
508 static int ett_metric_comm_type = -1;
509 static int hf_eigrp_extcomm_eigrp_flag = -1;
510 static int hf_eigrp_extcomm_eigrp_tag = -1;
511 static int hf_eigrp_extcomm_eigrp_res = -1;
512 static int hf_eigrp_extcomm_eigrp_rid = -1;
513 static int hf_eigrp_extcomm_eigrp_as = -1;
514 static int hf_eigrp_extcomm_eigrp_sdly = -1;
515 static int hf_eigrp_extcomm_eigrp_rel = -1;
516 static int hf_eigrp_extcomm_eigrp_hop = -1;
517 static int hf_eigrp_extcomm_eigrp_sbw = -1;
518 static int hf_eigrp_extcomm_eigrp_load = -1;
519 static int hf_eigrp_extcomm_eigrp_mtu = -1;
520 static int hf_eigrp_extcomm_eigrp_xas = -1;
521 static int hf_eigrp_extcomm_eigrp_xrid = -1;
522 static int hf_eigrp_extcomm_eigrp_xproto = -1;
523 static int hf_eigrp_extcomm_eigrp_xmetric = -1;
524 
525 
526 
527 static expert_field ei_eigrp_checksum_bad = EI_INIT;
528 static expert_field ei_eigrp_unreachable = EI_INIT;
529 static expert_field ei_eigrp_seq_addrlen = EI_INIT;
530 static expert_field ei_eigrp_peer_termination = EI_INIT;
531 static expert_field ei_eigrp_tlv_type = EI_INIT;
532 static expert_field ei_eigrp_auth_type = EI_INIT;
533 static expert_field ei_eigrp_peer_termination_graceful = EI_INIT;
534 static expert_field ei_eigrp_auth_len = EI_INIT;
535 static expert_field ei_eigrp_tlv_len = EI_INIT;
536 static expert_field ei_eigrp_afi = EI_INIT;
537 static expert_field ei_eigrp_prefixlen = EI_INIT;
538 static expert_field ei_eigrp_tlv_trunc = EI_INIT;
539 
540 /* some extra handle that might be needed */
541 static dissector_handle_t ipxsap_handle = NULL;
542 static dissector_table_t media_type_table = NULL;
543 
544 static const value_string eigrp_opcode2string[] = {
545     { EIGRP_OPC_UPDATE,         "Update" },
546     { EIGRP_OPC_REQUEST,        "Request" },
547     { EIGRP_OPC_QUERY,          "Query" },
548     { EIGRP_OPC_REPLY,          "Reply" },
549     { EIGRP_OPC_HELLO,          "Hello" },
550     { EIGRP_OPC_IPXSAP,         "IPX/SAP Update" },
551     { EIGRP_OPC_PROBE,          "Route Probe" },
552     { EIGRP_OPC_ACK,            "Hello (Ack)" },
553     { EIGRP_OPC_STUB,           "Stub-Info" },
554     { EIGRP_OPC_SIAQUERY,       "SIA-Query" },
555     { EIGRP_OPC_SIAREPLY,       "SIA-Reply" },
556     { 0, NULL }
557 };
558 
559 static const value_string eigrp_tlv2string[] = {
560     /* General TLV formats */
561     { EIGRP_TLV_PARAMETER,              "Parameters"},
562     { EIGRP_TLV_AUTH,                   "Authentication"},
563     { EIGRP_TLV_SEQ,                    "Sequence"},
564     { EIGRP_TLV_SW_VERSION,             "Software Version"},
565     { EIGRP_TLV_NEXT_MCAST_SEQ,         "Next multicast sequence"},
566     { EIGRP_TLV_PEER_STUBINFO,          "Peer Stub Information"},
567     { EIGRP_TLV_PEER_TERMINATION,       "Peer Termination"},
568     { EIGRP_TLV_PEER_TIDLIST,           "Peer Topology ID List"},
569 
570     /* Legacy TLV formats */
571     { EIGRP_TLV_IPv4_INT,               "Internal Route(IPv4)"},
572     { EIGRP_TLV_IPv4_EXT,               "External Route(IPv4)"},
573     { EIGRP_TLV_IPv4_COM,               "Ext-Community(IPv4)"},
574     { EIGRP_TLV_IPv6_INT,               "Internal Route(IPv6)"},
575     { EIGRP_TLV_IPv6_EXT,               "External Route(IPv6)"},
576     { EIGRP_TLV_IPv6_COM,               "Ext-Community(IPv6)"},
577     { EIGRP_TLV_IPX_INT,                "IPX Internal Route(IPX)"},
578     { EIGRP_TLV_IPX_EXT,                "IPX External Route(IPX)"},
579 
580     /* Deprecated TLV formats */
581     { EIGRP_TLV_AT_INT,                 "Internal Route(ATALK)"},
582     { EIGRP_TLV_AT_EXT,                 "External Route(ATALK)"},
583     { EIGRP_TLV_AT_CBL,                 "Cable Configuration(ATALK)"},
584     { EIGRP_TLV_MTR_REQ,                "Request(MTR)"},
585     { EIGRP_TLV_MTR_INT,                "Internal Route(MTR)"},
586     { EIGRP_TLV_MTR_EXT,                "External Route(MTR)"},
587     { EIGRP_TLV_MTR_COM,                "Ext-Community(MTR)"},
588     { EIGRP_TLV_MTR_TIDLIST,            "TopologyID List"},
589 
590     /* Current "Wide Metric" TLV formats */
591     { EIGRP_TLV_MP_REQ,                 "Request"},
592     { EIGRP_TLV_MP_INT,                 "Internal Route"},
593     { EIGRP_TLV_MP_EXT,                 "External Route"},
594     { EIGRP_TLV_MP_COM,                 "Ext-Community"},
595 
596     { 0, NULL}
597 };
598 
599 const value_string eigrp_proto2string[] = {
600     { IGRP1_PROTID,             "IGRP"},
601     { IGRP2_PROTID,             "EIGRP"},
602     { STATIC_PROTID,            "Static Route"},
603     { RIP_PROTID,               "RIP"},
604     { HELLO_PROTID,             "Hello"},
605     { OSPF_PROTID,              "OSPF"},
606     { ISIS_PROTID,              "IS-IS"},
607     { EGP_PROTID,               "EGP"},
608     { BGP_PROTID,               "BGP"},
609     { IDRP_PROTID,              "IDRP"},
610     { CONN_PROTID,              "Connected Route"},
611     { 0, NULL}
612 };
613 
614 static const value_string eigrp_auth2string[] = {
615     { EIGRP_AUTH_TYPE_TEXT,     "TEXT"},
616     { EIGRP_AUTH_TYPE_MD5,      "MD5"},
617     { EIGRP_AUTH_TYPE_SHA256,   "SHA256"},
618     { 0, NULL},
619 };
620 
621 static const value_string eigrp_vrid2string[] = {
622     { EIGRP_VRID_AF_BASE,       "(Address-Family)"},
623     { EIGRP_VRID_SF_BASE,       "(Service-Family)"},
624     { EIGRP_VRID_MCAST_BASE,    "(Multi-Cast)"},
625     { 0, NULL}
626 };
627 
628 static const value_string eigrp_afi2string[] = {
629     { EIGRP_AF_IPv4,            "IPv4"},
630     { EIGRP_AF_IPv6,            "IPv6"},
631     { EIGRP_AF_IPX,             "IPX"},
632     { EIGRP_AF_ATALK,           "Appletalk"},
633     { EIGRP_SF_COMMON,          "Service Family"},
634     { EIGRP_SF_IPv4,            "IPv4 Service Family"},
635     { EIGRP_SF_IPv6,            "IPv6 Service Family"},
636     { 0, NULL}
637 };
638 
639 static const value_string eigrp_attr_opcode2string[] = {
640     { EIGRP_ATTR_NOOP,          "NO-OP for padding"},
641     { EIGRP_ATTR_SCALED,        "Scaled Metric"},
642     { EIGRP_ATTR_TAG,           "Admin Tag"},
643     { EIGRP_ATTR_COMM,          "Community"},
644     { EIGRP_ATTR_JITTER,        "Jitter"},
645     { EIGRP_ATTR_QENERGY,       "Non-Active energy"},
646     { EIGRP_ATTR_ENERGY,        "Active energy"},
647     { 0, NULL}
648 };
649 
650 static const value_string eigrp_saf_type2string[] = {
651     { EIGRP_SVCDATA_COMPLETE,   "Attached Service Data"},
652     { EIGRP_SVCDATA_TRIMMED,    "Trimmed Service Data"},
653     { 0, NULL}
654 };
655 
656 static const value_string eigrp_saf_srv2string[] = {
657     { SAF_SERVICE_ID_CAPMAN,    "Capabilities Manager"},
658     { SAF_SERVICE_ID_UC,        "Unified Communications"},
659     { SAF_SERVICE_ID_PFR,       "Performance Routing"},
660     { 0, NULL}
661 };
662 
663 static const value_string eigrp_metric_comm_type_vals[] = {
664     { EIGRP_EXTCOMM_EIGRP,    "EIGRP_EXTCOMM_EIGRP"},
665     { EIGRP_EXTCOMM_VRR,      "EIGRP_EXTCOMM_VRR"},
666     { EIGRP_EXTCOMM_DAD,      "EIGRP_EXTCOMM_DAD"},
667     { EIGRP_EXTCOMM_VRHB,     "EIGRP_EXTCOMM_VRHB"},
668     { EIGRP_EXTCOMM_SRLM,     "EIGRP_EXTCOMM_SRLM"},
669     { EIGRP_EXTCOMM_SAR,      "EIGRP_EXTCOMM_SAR"},
670     { EIGRP_EXTCOMM_RPM,      "EIGRP_EXTCOMM_RPM"},
671     { EIGRP_EXTCOMM_SOO_ASFMT,  "EIGRP_EXTCOMM_SOO"},
672     { EIGRP_EXTCOMM_SOO_ADRFMT, "EIGRP_EXTCOMM_SOO"},
673     { 0, NULL}
674 };
675 
676 
677 /**
678  *@fn void dissect_eigrp_parameter (proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo,  proto_item *ti)
679  *
680  *
681  * @param[in,out] tree  detail dissection result
682  * @param[in] tvb       packet data
683  * @param[in] pinfo     general data about the protocol
684  * @param[in] ti        protocol item
685  *
686  * @par
687  * Dissect the Parameter TLV, which is used to convey metric weights and the
688  * hold time.
689  *
690  * @brief
691  * Note the addition of K6 for the new extended metrics, and does not apply to
692  * older TLV packet formats.
693  */
694 static void
dissect_eigrp_parameter(proto_tree * tree,tvbuff_t * tvb,packet_info * pinfo,proto_item * ti)695 dissect_eigrp_parameter (proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo,
696                          proto_item *ti)
697 {
698     int    offset = 0;
699     guint8 k1, k2, k3, k4, k5;
700 
701     k1 = tvb_get_guint8(tvb, offset);
702     proto_tree_add_item(tree, hf_eigrp_par_k1, tvb, offset, 1, ENC_BIG_ENDIAN);
703 
704     offset += 1;
705     k2 = tvb_get_guint8(tvb, offset);
706     proto_tree_add_item(tree, hf_eigrp_par_k2, tvb, offset, 1, ENC_BIG_ENDIAN);
707 
708     offset += 1;
709     k3 = tvb_get_guint8(tvb, offset);
710     proto_tree_add_item(tree, hf_eigrp_par_k3, tvb, offset, 1, ENC_BIG_ENDIAN);
711 
712     offset += 1;
713     k4 = tvb_get_guint8(tvb, offset);
714     proto_tree_add_item(tree, hf_eigrp_par_k4, tvb, offset, 1, ENC_BIG_ENDIAN);
715 
716     offset += 1;
717     k5 = tvb_get_guint8(tvb, offset);
718     proto_tree_add_item(tree, hf_eigrp_par_k5, tvb, offset, 1, ENC_BIG_ENDIAN);
719 
720     offset += 1;
721     proto_tree_add_item(tree, hf_eigrp_par_k6, tvb, offset, 1, ENC_BIG_ENDIAN);
722 
723     offset += 1;
724     proto_tree_add_item(tree, hf_eigrp_par_holdtime, tvb, offset, 2, ENC_BIG_ENDIAN);
725 
726     if (k1 == 255 && k2 == 255 && k3 == 255 && k4 == 255 && k5 == 255) {
727         proto_item_append_text(ti, ": Peer Termination");
728         expert_add_info(pinfo, ti, &ei_eigrp_peer_termination);
729     }
730 }
731 
732 /**
733  *@fn void dissect_eigrp_auth_tlv (proto_tree *tree, tvbuff_t *tvb,
734  *                                 packet_info *pinfo, proto_item *ti)
735  *
736  * @param[in,out] tree  detail dissection result
737  * @param[in] tvb       packet data
738  * @param[in] pinfo     general data about the protocol
739  * @param[in] ti        protocol item
740  *
741  * @par
742  * Dissect the Authentication TLV and display digest. Currently MD5 and SHA256
743  * HMAC is supported.  For SHA256, a "secret key" with the HMAC-SHA-256
744  * password, the source address from which the packet is sent. This combined
745  * string is used as the key for hash calculation.
746  */
747 static void
dissect_eigrp_auth_tlv(proto_tree * tree,tvbuff_t * tvb,packet_info * pinfo,proto_item * ti)748 dissect_eigrp_auth_tlv (proto_tree *tree, tvbuff_t *tvb,
749                         packet_info *pinfo, proto_item *ti)
750 {
751     proto_item *ti_auth_type, *ti_auth_len;
752     int         offset = 0;
753     guint16     auth_type, auth_len;
754 
755     /* print out what family we dealing with... */
756 
757     auth_type = tvb_get_ntohs(tvb, 0);
758     auth_len = tvb_get_ntohs(tvb, 2);
759 
760     proto_item_append_text(ti, " %s", val_to_str_const(auth_type, eigrp_auth2string, ""));
761 
762     ti_auth_type = proto_tree_add_item(tree, hf_eigrp_auth_type, tvb, offset, 2, ENC_BIG_ENDIAN);
763     offset += 2;
764     ti_auth_len = proto_tree_add_item(tree, hf_eigrp_auth_len, tvb, offset, 2, ENC_BIG_ENDIAN);
765     offset += 2;
766     proto_tree_add_item(tree, hf_eigrp_auth_keyid, tvb, offset, 4, ENC_BIG_ENDIAN);
767     offset += 4;
768     proto_tree_add_item(tree, hf_eigrp_auth_keyseq, tvb, offset, 4, ENC_BIG_ENDIAN);
769     offset += 4;
770     proto_tree_add_item(tree, hf_eigrp_nullpad, tvb, offset, 8, ENC_NA);
771     offset += 8;
772 
773     switch (auth_type) {
774     case EIGRP_AUTH_TYPE_MD5:
775         if (EIGRP_AUTH_TYPE_MD5_LEN != auth_len) {
776             expert_add_info_format(pinfo, ti_auth_len, &ei_eigrp_auth_len, "Invalid auth len %u", auth_len);
777         } else {
778             proto_tree_add_item(tree, hf_eigrp_auth_digest, tvb, offset,
779                                 EIGRP_AUTH_TYPE_MD5_LEN, ENC_NA);
780         }
781         break;
782 
783     case EIGRP_AUTH_TYPE_SHA256:
784         if (EIGRP_AUTH_TYPE_SHA256_LEN != auth_len) {
785             expert_add_info_format(pinfo, ti_auth_len, &ei_eigrp_auth_len, "Invalid auth len %u", auth_len);
786 
787         } else {
788             proto_tree_add_item(tree, hf_eigrp_auth_digest, tvb, offset,
789                                 EIGRP_AUTH_TYPE_SHA256_LEN, ENC_NA);
790         }
791         break;
792 
793     case EIGRP_AUTH_TYPE_NONE:
794     case EIGRP_AUTH_TYPE_TEXT:
795     default:
796         expert_add_info_format(pinfo, ti_auth_type, &ei_eigrp_auth_type, "Invalid auth type %u", auth_type);
797         break;
798     }
799 }
800 
801 /**
802  *@fn void dissect_eigrp_seq_tlv (proto_tree *tree, tvbuff_t *tvb,
803  *                                packet_info *pinfo, proto_item *ti)
804  *
805  * @param[in,out] tree  detail dissection result
806  * @param[in] tvb       packet data
807  * @param[in] pinfo     general data about the protocol
808  * @param[in] ti        protocol item
809  *
810  * @par
811  * Dissect the Sequence TLV which consists of the addresses of peers that must
812  * not receive the next multicast packet transmitted.
813  */
814 static void
dissect_eigrp_seq_tlv(proto_tree * tree,tvbuff_t * tvb,packet_info * pinfo,proto_item * ti)815 dissect_eigrp_seq_tlv (proto_tree *tree, tvbuff_t *tvb,
816                        packet_info *pinfo, proto_item *ti)
817 {
818     proto_item *ti_addrlen;
819     int         offset = 0;
820     guint8      addr_len;
821 
822     while (tvb_reported_length_remaining(tvb, offset) > 0) {
823         addr_len = tvb_get_guint8(tvb, offset);
824         ti_addrlen = proto_tree_add_item(tree, hf_eigrp_seq_addrlen, tvb, offset, 1, ENC_BIG_ENDIAN);
825         offset += 1;
826 
827         if (tvb_reported_length_remaining(tvb, offset) < addr_len) {
828             /* The remaining part of the TLV is shorter than the address it should contain */
829             expert_add_info(pinfo, ti, &ei_eigrp_tlv_trunc);
830             break;
831         }
832 
833         switch (addr_len) {
834         case 4:
835             /* IPv4 */
836             proto_tree_add_item(tree, hf_eigrp_seq_ipv4addr, tvb, offset, addr_len, ENC_BIG_ENDIAN);
837             break;
838         case 10:
839             /* IPX */
840             proto_tree_add_bytes_format_value(tree, hf_eigrp_ipx_address, tvb, offset, addr_len, NULL,
841                                 "IPX Address: %s", tvb_address_to_str(pinfo->pool, tvb, AT_IPX, 1));
842             break;
843         case 16:
844             /* IPv6 */
845             proto_tree_add_item(tree, hf_eigrp_seq_ipv6addr, tvb, offset, addr_len,
846                                 ENC_NA);
847             break;
848         default:
849             expert_add_info(pinfo, ti_addrlen, &ei_eigrp_seq_addrlen);
850         }
851 
852         offset += addr_len;
853     }
854 }
855 
856 /**
857  *@fn void dissect_eigrp_sw_version (tvbuff_t *tvb, proto_tree *tree,
858  *                                   proto_item *ti)
859  *
860  * @param[in,out] tree  detail dissection result
861  * @param[in] tvb       packet data
862  * @param[in] ti        protocol item
863  *
864  * @par
865  * Dissect Software Version TLV.  The older versions of EIGRP sent the IOS
866  * version along with the TLV Version.   When EIGRP "plugins" were created,
867  * this as change to send the "Release" of EIGRP to better identify where fixes
868  * are present(missing)
869  */
870 static void
dissect_eigrp_sw_version(tvbuff_t * tvb,proto_tree * tree,proto_item * ti)871 dissect_eigrp_sw_version (tvbuff_t *tvb, proto_tree *tree,
872                           proto_item *ti)
873 {
874     int    offset = 0;
875     guint8 ios_rel_major, ios_rel_minor;
876     guint8 eigrp_rel_major, eigrp_rel_minor;
877 
878     ios_rel_major = tvb_get_guint8(tvb, 0);
879     ios_rel_minor = tvb_get_guint8(tvb, 1);
880     proto_tree_add_item(tree, hf_eigrp_release, tvb, offset, 2, ENC_BIG_ENDIAN);
881     offset += 2;
882     proto_item_append_text(ti, ": EIGRP=%u.%u", ios_rel_major, ios_rel_minor);
883 
884     eigrp_rel_major = tvb_get_guint8(tvb, 2);
885     eigrp_rel_minor = tvb_get_guint8(tvb, 3);
886     proto_tree_add_item(tree, hf_eigrp_tlv_version, tvb, offset, 2, ENC_BIG_ENDIAN);
887     proto_item_append_text(ti, ", TLV=%u.%u",
888                            eigrp_rel_major, eigrp_rel_minor);
889 }
890 
891 /**
892  *@fn void dissect_eigrp_next_mcast_seq (tvbuff_t *tvb, proto_tree *tree,
893  *                                      proto_item *ti)
894  *
895  * @param[in,out] tree  detail dissection result
896  * @param[in] tvb       packet data
897  * @param[in] ti        protocol item
898  *
899  * @par
900  * Dissect Next Multicast Sequence TLV, which is part of the Hello with a
901  * Sequence TLV;  this gives a two-way binding between the packets and plugs a
902  * hole where a multicast could be received  by the wrong peers (due to a
903  * string of lost packets).
904  */
905 static void
dissect_eigrp_next_mcast_seq(tvbuff_t * tvb,proto_tree * tree,proto_item * ti)906 dissect_eigrp_next_mcast_seq (tvbuff_t *tvb, proto_tree *tree,
907                               proto_item *ti)
908 {
909     proto_tree_add_item(tree, hf_eigrp_next_mcast_seq, tvb, 0, 4,
910                         ENC_BIG_ENDIAN);
911     proto_item_append_text(ti, ": %u", tvb_get_ntohl(tvb, 0));
912 }
913 
914 /**
915  *@fn void dissect_eigrp_peer_stubinfo (tvbuff_t *tvb, proto_tree *tree)
916  *
917  *
918  * @param[in,out] tree  detail dissection result
919  * @param[in] tvb       packet data
920  *
921  * @par
922  * Dissect the PEER STUB TLV which contains the route types which the Peer will
923  * advertise. This is used to suppress QUERYs from being sent to the Peer
924  */
925 static void
dissect_eigrp_peer_stubinfo(tvbuff_t * tvb,proto_tree * tree)926 dissect_eigrp_peer_stubinfo (tvbuff_t *tvb, proto_tree *tree)
927 {
928     proto_tree_add_bitmask(tree, tvb, 0, hf_eigrp_stub_flags, ett_eigrp_stub_flags,
929                            eigrp_stub_flag_fields, ENC_BIG_ENDIAN);
930 }
931 
932 /**
933  *@fn void dissect_eigrp_peer_termination (packet_info *pinfo, proto_item *ti)
934  *
935  * @param[in] pinfo     general data about the protocol
936  * @param[in] ti        protocol item
937  *
938  * @par
939  * Dissect Peer Termination TLV.  This TLV has no parameters and is used to
940  * signal an adjacency should be tore down
941  */
942 static void
dissect_eigrp_peer_termination(packet_info * pinfo,proto_item * ti)943 dissect_eigrp_peer_termination (packet_info *pinfo, proto_item *ti)
944 {
945     expert_add_info(pinfo, ti, &ei_eigrp_peer_termination_graceful);
946 }
947 
948 /**
949  *@fn void dissect_eigrp_peer_tidlist (proto_tree *tree, tvbuff_t *tvb)
950  *
951  * @param[in,out] tree  detail dissection result
952  * @param[in] tvb       packet data
953  *
954  * @par
955  *  Dissect the Topology Identifier List TLV.  This TLV was introduced as part
956  *  of the "MTR (Multi-Topology Routing) Project to support sub topologies
957  *  within a given Autonomous System. The following represents the format of
958  *  the TID list
959  *
960  *    0                   1                   2                   3
961  *    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
962  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
963  *   |            Flags             |         Length                 |
964  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
965  *   |        Variable Length TID (two bytes) list                   |
966  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
967  */
968 static void
dissect_eigrp_peer_tidlist(proto_tree * tree,tvbuff_t * tvb)969 dissect_eigrp_peer_tidlist (proto_tree *tree, tvbuff_t *tvb)
970 {
971     proto_tree *sub_tree;
972     int         offset = 0;
973     guint16     size;
974 
975     proto_tree_add_item(tree, hf_eigrp_tidlist_flags, tvb, offset, 2,
976                         ENC_BIG_ENDIAN);
977     offset += 2;
978 
979     size = tvb_get_ntohs(tvb, offset) / 2;
980     proto_tree_add_item(tree, hf_eigrp_tidlist_len, tvb, offset, 2,
981                         ENC_BIG_ENDIAN);
982     offset += 2;
983 
984     sub_tree = proto_tree_add_subtree_format(tree, tvb, offset, (size*2), ett_eigrp_tidlist, NULL, "%d TIDs", size);
985     for (; size ; size--) {
986         proto_tree_add_item(sub_tree, hf_eigrp_tidlist_tid, tvb, offset, 2,
987                             ENC_BIG_ENDIAN);
988         offset += 2;
989     }
990 }
991 
992 /**
993  *@fn int dissect_eigrp_extdata_flags (proto_tree *tree, tvbuff_t *tvb, int offset)
994  *
995  * @param[in,out] tree  detail dissection result
996  * @param[in] tvb       packet data
997  * @param[in] offset    current byte offset in packet being processed
998  *
999  * @return int          number of bytes process
1000  *
1001  * @par
1002  * Dissect the Flags field in the external data section of an external
1003  * route.The following represents the format of the bit field
1004  *
1005  *    7 6 5 4 3 2 1 0
1006  *   +-+-+-+-+-+-+-+-+
1007  *   |   Flags       |
1008  *   +-+-+-+-+-+-+-+-+
1009  *                | |
1010  *                | +- Route is External *not used*
1011  *                +--- Route is Candidate Default
1012  */
1013 static int
dissect_eigrp_extdata_flags(proto_tree * tree,tvbuff_t * tvb,int offset)1014 dissect_eigrp_extdata_flags (proto_tree *tree, tvbuff_t *tvb, int offset)
1015 {
1016     proto_tree *sub_tree;
1017     tvbuff_t   *sub_tvb;
1018 
1019     /* Decode the route flags field */
1020     sub_tree = proto_tree_add_subtree(tree, tvb, offset, 1, ett_eigrp_extdata_flags, NULL, "External Flags");
1021     sub_tvb = tvb_new_subset_remaining(tvb, offset);
1022 
1023     proto_tree_add_item(sub_tree, hf_eigrp_extdata_flag_ext, sub_tvb, 0, 1,
1024                         ENC_BIG_ENDIAN);
1025     proto_tree_add_item(sub_tree, hf_eigrp_extdata_flag_cd, sub_tvb, 0, 1,
1026                         ENC_BIG_ENDIAN);
1027 
1028     offset += 1;
1029     return(offset);
1030 }
1031 
1032 /**
1033  *@fn int dissect_eigrp_metric_flags (proto_tree *tree, tvbuff_t *tvb, int offset, int limit)
1034  *
1035  * @param[in,out] tree  detail dissection result
1036  * @param[in] tvb       packet data
1037  * @param[in] offset    current byte offset in packet being processed
1038  * @param[in] limit     maximum number of bytes which can be process
1039  *
1040  * @return int          number of bytes process
1041  *
1042  * @par
1043  * Dissect Protocol Dependent Module (PDM) Flags field in the route metric
1044  * section of an internal and external route. The following represents the
1045  * format of the bit field
1046  *
1047  *       MSB             LSB
1048  *    7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
1049  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1050  *   |   Flags       |    MP Flags   |
1051  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1052  *              | | |
1053  *              | | +- Route is Replicated
1054  *              | +--- Route is Active
1055  *              +----- Source Withdraw
1056  */
1057 static int
dissect_eigrp_metric_flags(proto_tree * tree,tvbuff_t * tvb,int offset,int limit)1058 dissect_eigrp_metric_flags (proto_tree *tree, tvbuff_t *tvb, int offset, int limit)
1059 {
1060     proto_tree *sub_tree;
1061     tvbuff_t   *sub_tvb;
1062 
1063     /* Decode the route flags field */
1064     sub_tree = proto_tree_add_subtree(tree, tvb, offset, limit, ett_eigrp_metric_flags, NULL, "Flags");
1065     sub_tvb = tvb_new_subset_length_caplen(tvb, offset, limit, -1);
1066 
1067     /* just care about 'flags' byte, there are no MP flags for now */
1068     proto_tree_add_item(sub_tree, hf_eigrp_metric_flags_srcwd, sub_tvb, 0, 1,
1069                         ENC_BIG_ENDIAN);
1070     proto_tree_add_item(sub_tree, hf_eigrp_metric_flags_cd, sub_tvb, 0, 1,
1071                         ENC_BIG_ENDIAN);
1072     proto_tree_add_item(sub_tree, hf_eigrp_metric_flags_active, sub_tvb, 0, 1,
1073                         ENC_BIG_ENDIAN);
1074     proto_tree_add_item(sub_tree, hf_eigrp_metric_flags_repl, sub_tvb, 0, 1,
1075                         ENC_BIG_ENDIAN);
1076 
1077     offset += limit;
1078     return(offset);
1079 }
1080 
1081 /**
1082  *@fn void dissect_eigrp_ipv4_addrs (proto_item *ti, proto_tree *tree, tvbuff_t *tvb,
1083  *                                   packet_info *pinfo, int offset, int unreachable)
1084  *
1085  * @param[in,out] tree  detail dissection result
1086  * @param[in] tvb       packet data
1087  * @param[in] pinfo     general data about the protocol
1088  * @param[in] offset    current byte offset in packet being processed
1089  *
1090  * @par
1091  * Dissect all IPv4 address from offset though the end of the packet
1092  */
1093 static void
dissect_eigrp_ipv4_addrs(proto_item * ti,proto_tree * tree,tvbuff_t * tvb,packet_info * pinfo,int offset,int unreachable)1094 dissect_eigrp_ipv4_addrs (proto_item *ti, proto_tree *tree, tvbuff_t *tvb,
1095                          packet_info *pinfo, int offset, int unreachable)
1096 {
1097     guint8 length;
1098     ws_in4_addr ip_addr;
1099     int         addr_len;
1100     proto_item *ti_prefixlen, *ti_dst;
1101     int         first = TRUE;
1102 
1103     for (; tvb_reported_length_remaining(tvb, offset) > 0; offset += (1 + addr_len)) {
1104         length = tvb_get_guint8(tvb, offset);
1105         addr_len = tvb_get_ipv4_addr_with_prefix_len(tvb, offset + 1, &ip_addr, length);
1106 
1107         if (addr_len < 0) {
1108             /* Invalid prefix length, more than 32 bits */
1109             ti_prefixlen = proto_tree_add_item(tree, hf_eigrp_ipv4_prefixlen,
1110                                                tvb, offset, 1, ENC_BIG_ENDIAN);
1111             expert_add_info_format(pinfo, ti_prefixlen, &ei_eigrp_prefixlen, "Invalid prefix length %u, must be <= 32", length);
1112             break;  /* We don't know how long this address is */
1113         } else {
1114             address addr;
1115 
1116             proto_tree_add_item(tree, hf_eigrp_ipv4_prefixlen, tvb, offset, 1,
1117                                 ENC_BIG_ENDIAN);
1118             offset += 1;
1119             set_address(&addr, AT_IPv4, 4, &ip_addr);
1120             ti_dst = proto_tree_add_ipv4(tree, hf_eigrp_ipv4_destination, tvb, offset, addr_len, ip_addr);
1121 
1122             /* add it to the top level line */
1123             proto_item_append_text(ti,"  %c   %s/%u", first ? '=':',',
1124                                    address_to_str(pinfo->pool, &addr), length);
1125 
1126             if (unreachable) {
1127                 expert_add_info(pinfo, ti_dst, &ei_eigrp_unreachable);
1128             }
1129         }
1130         first = FALSE;
1131     }
1132 }
1133 
1134 /**
1135  *@fn void dissect_eigrp_ipv6_addrs (proto_item *ti, proto_tree *tree, tvbuff_t *tvb,
1136  *                                   packet_info *pinfo, int offset, int unreachable)
1137  *
1138  * @param[in,out] tree  detail dissection result
1139  * @param[in] tvb       packet data
1140  * @param[in] pinfo     general data about the protocol
1141  * @param[in] offset    current byte offset in packet being processed
1142  *
1143  * @par
1144  * Dissect all IPv6 address from offset though the end of the packet
1145  */
1146 static void
dissect_eigrp_ipv6_addrs(proto_item * ti,proto_tree * tree,tvbuff_t * tvb,packet_info * pinfo,int offset,int unreachable)1147 dissect_eigrp_ipv6_addrs (proto_item *ti, proto_tree *tree, tvbuff_t *tvb,
1148                           packet_info *pinfo, int offset, int unreachable)
1149 {
1150     guint8             length;
1151     int                addr_len;
1152     ws_in6_addr  addr;
1153     address            addr_str;
1154     proto_item        *ti_prefixlen, *ti_dst;
1155     int                first = TRUE;
1156 
1157     for (; tvb_reported_length_remaining(tvb, offset) > 0; offset += (1 + addr_len)) {
1158         length = tvb_get_guint8(tvb, offset);
1159         addr_len = tvb_get_ipv6_addr_with_prefix_len(tvb, offset + 1, &addr, length);
1160 
1161         if (addr_len < 0) {
1162             /* Invalid prefix length, more than 128 bits */
1163             ti_prefixlen = proto_tree_add_item(tree, hf_eigrp_ipv6_prefixlen,
1164                                                tvb, offset, 1, ENC_BIG_ENDIAN);
1165             expert_add_info_format(pinfo, ti_prefixlen, &ei_eigrp_prefixlen, "Invalid prefix length %u, must be <= 128", length);
1166             break;  /* We don't know how long this address is */
1167         } else {
1168             proto_tree_add_item(tree, hf_eigrp_ipv6_prefixlen, tvb, offset, 1,
1169                                 ENC_BIG_ENDIAN);
1170             offset += 1;
1171 
1172             if ((length < 128) && (length % 8 == 0)) {
1173                 addr_len++;
1174             }
1175 
1176             set_address(&addr_str, AT_IPv6, 16, addr.bytes);
1177             ti_dst = proto_tree_add_ipv6(tree, hf_eigrp_ipv6_destination, tvb, offset, addr_len, &addr);
1178 
1179             /* add it to the top level line */
1180             proto_item_append_text(ti,"  %c   %s/%u", first ? '=':',',
1181                                    address_to_str(pinfo->pool, &addr_str), length);
1182 
1183             if (unreachable) {
1184                 expert_add_info(pinfo, ti_dst, &ei_eigrp_unreachable);
1185             }
1186         }
1187         first = FALSE;
1188     }
1189 }
1190 
1191 /**
1192  *@fn int dissect_eigrp_ipx_addrs (proto_item *ti, proto_tree *tree, tvbuff_t *tvb,
1193  *                                 packet_info *pinfo, int offset, int unreachable)
1194  *
1195  * @param[in,out] tree  detail dissection result
1196  * @param[in] tvb       packet data
1197  * @param[in] pinfo     general data about the protocol
1198  * @param[in] offset    current byte offset in packet being processed
1199  *
1200  * @return int          number of bytes process
1201  *
1202  * @par
1203  * Dissect all IPX address from offset though the end of the packet
1204  */
1205 static int
dissect_eigrp_ipx_addrs(proto_item * ti,proto_tree * tree,tvbuff_t * tvb,packet_info * pinfo,int offset,int unreachable)1206 dissect_eigrp_ipx_addrs (proto_item *ti, proto_tree *tree, tvbuff_t *tvb,
1207                          packet_info *pinfo, int offset, int unreachable)
1208 {
1209     proto_item *ti_dst;
1210 
1211     ti_dst = proto_tree_add_item(tree, hf_eigrp_ipx_dest, tvb, offset, 4,
1212                                  ENC_NA);
1213 
1214     /* add it to the top level line */
1215     proto_item_append_text(ti,"  =   %s", ipxnet_to_str_punct(pinfo->pool, tvb_get_ntohl(tvb, offset), ' '));
1216 
1217     if (unreachable) {
1218         expert_add_info(pinfo, ti_dst, &ei_eigrp_unreachable);
1219     }
1220 
1221     offset +=4;
1222     return(offset);
1223 }
1224 
1225 /**
1226  *@fn void dissect_eigrp_services (proto_item *ti, proto_tree *tree, tvbuff_t *tvb,
1227  *                                 packet_info *pinfo, int offset)
1228  *
1229  * @param[in,out] tree  detail dissection result
1230  * @param[in] tvb       packet data
1231  * @param[in] pinfo     general data about the protocol
1232  * @param[in] ti        protocol item
1233  * @param[in] offset    current byte offset in packet being processed
1234  *
1235  * @par
1236  * Dissect all SAF Services from offset though the end of the packet. The
1237  * following represents the format of  a SAF Service:
1238  *
1239  *    0                   1                   2                   3
1240  *    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
1241  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1242  *   |            Service            |         SubService            |
1243  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1244  *   |                             GUID                              |
1245  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1246  *   |                             GUID(cont)                        |
1247  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1248  *   |                             GUID(cont)                        |
1249  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1250  *   |                             GUID(cont)                        |
1251  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1252  *   |            Type               |           Length              |
1253  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1254  *   |        Reachability AFI       |    Reachability Port          |
1255  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1256  *   |     Reachability Protocol     |    Reachability Addr          |
1257  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1258  *   |                      Reachability Addr(cont)                  |
1259  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1260  *   |                      Reachability Addr(cont)                  |
1261  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1262  *   |                      Reachability Addr(cont)                  |
1263  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1264  *   |    Reachability Addr(cont)    |           Sequence            |
1265  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1266  *   |           Sequence(cont)      |\/\/\/    Service Data   \/\/\/|
1267  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1268  *
1269  */
1270 static void
dissect_eigrp_services(proto_item * ti,proto_tree * tree,tvbuff_t * tvb,packet_info * pinfo,int offset)1271 dissect_eigrp_services (proto_item *ti, proto_tree *tree, tvbuff_t *tvb,
1272                        packet_info *pinfo, int offset)
1273 {
1274     int         afi, length, remaining;
1275     int         sub_offset;
1276     proto_item *sub_ti;
1277     proto_tree *sub_tree, *reach_tree;
1278     tvbuff_t   *sub_tvb, *reach_tvb;
1279     guint16     service, sub_service;
1280 
1281     remaining = tvb_captured_length_remaining(tvb, offset);
1282     sub_tree = proto_tree_add_subtree(tree, tvb, offset, remaining, ett_eigrp_tlv_metric, &sub_ti, "SAF Service ");
1283     sub_tvb = tvb_new_subset_length_caplen(tvb, offset, remaining, -1);
1284     sub_offset = 0;
1285 
1286     for (; tvb_reported_length_remaining(sub_tvb, sub_offset) > 0; ) {
1287         service = tvb_get_ntohs(sub_tvb, sub_offset);
1288         proto_item_append_text(sub_ti, "%c %s", (sub_offset == 0 ? '=':','),
1289                                val_to_str_const(service, eigrp_saf_srv2string, ""));
1290 
1291         sub_service = tvb_get_ntohs(sub_tvb, sub_offset+2);
1292         proto_item_append_text(ti, "%c %u:%u", (sub_offset == 0 ? '=':','),
1293                                service, sub_service);
1294 
1295         proto_tree_add_item(sub_tree, hf_eigrp_saf_service, sub_tvb,
1296                             sub_offset, 2, ENC_BIG_ENDIAN);
1297         sub_offset += 2;
1298         proto_tree_add_item(sub_tree, hf_eigrp_saf_subservice, sub_tvb,
1299                             sub_offset, 2, ENC_BIG_ENDIAN);
1300         sub_offset += 2;
1301         proto_tree_add_item(sub_tree, hf_eigrp_saf_guid, sub_tvb,
1302                             sub_offset, GUID_LEN, ENC_BIG_ENDIAN);
1303         sub_offset += GUID_LEN;
1304 
1305         proto_tree_add_item(sub_tree, hf_eigrp_saf_data_type, sub_tvb,
1306                             sub_offset, 2, ENC_BIG_ENDIAN);
1307         sub_offset += 2;
1308         length = tvb_get_ntohs(sub_tvb, sub_offset);
1309         proto_tree_add_item(sub_tree, hf_eigrp_saf_data_length, sub_tvb,
1310                             sub_offset, 2, ENC_BIG_ENDIAN);
1311         sub_offset += 2;
1312 
1313         /*
1314          * Reachability information
1315          */
1316         reach_tree = proto_tree_add_subtree(sub_tree, sub_tvb, sub_offset, 22,
1317                                        ett_eigrp_saf_reachability, NULL, "Reachability");
1318         reach_tvb = tvb_new_subset_length_caplen(sub_tvb, sub_offset, 22, -1);
1319 
1320         afi = tvb_get_ntohs(reach_tvb, 0);
1321         proto_tree_add_item(reach_tree, hf_eigrp_saf_reachability_afi,
1322                             reach_tvb, 0, 2, ENC_BIG_ENDIAN);
1323         proto_tree_add_item(reach_tree, hf_eigrp_saf_reachability_port,
1324                             reach_tvb, 2, 2, ENC_BIG_ENDIAN);
1325         proto_tree_add_item(reach_tree, hf_eigrp_saf_reachability_protocol,
1326                             reach_tvb, 4, 2, ENC_BIG_ENDIAN);
1327 
1328         switch (afi) {
1329         case EIGRP_AF_IPv4:
1330             proto_tree_add_item(reach_tree, hf_eigrp_saf_reachability_addr_ipv4,
1331                                 reach_tvb, 6, 4, ENC_BIG_ENDIAN);
1332             proto_tree_add_item(reach_tree, hf_eigrp_nullpad, reach_tvb, 10, 12,
1333                                 ENC_NA);
1334             break;
1335 
1336         case EIGRP_AF_IPv6:
1337             proto_tree_add_item(reach_tree, hf_eigrp_saf_reachability_addr_ipv6,
1338                                 reach_tvb, 6, 16, ENC_NA);
1339             break;
1340         default:
1341             /* just print zeros... */
1342             proto_tree_add_item(reach_tree, hf_eigrp_saf_reachability_addr_hex,
1343                                 reach_tvb, 6, 16, ENC_NA);
1344             break;
1345         }
1346         sub_offset += 22;
1347 
1348         proto_tree_add_item(sub_tree, hf_eigrp_saf_data_sequence, sub_tvb,
1349                             sub_offset, 4, ENC_BIG_ENDIAN);
1350         sub_offset += 4;
1351 
1352         if (length > 0) {
1353             tvbuff_t *xml_tvb;
1354             guint8 *test_string, *tok;
1355 
1356             /*
1357              * Service-Data is usually (but not always) plain text, specifically
1358              * XML. If it "looks like" XML (begins with optional white-space
1359              * followed by a '<'), try XML. Otherwise, try plain-text.
1360              */
1361             xml_tvb = tvb_new_subset_length(sub_tvb, sub_offset, length);
1362             test_string = tvb_get_string_enc(pinfo->pool, xml_tvb, 0, (length < 32 ?
1363                                                                 length : 32), ENC_ASCII);
1364             tok = strtok(test_string, " \t\r\n");
1365 
1366             if (tok && tok[0] == '<') {
1367                 /* Looks like XML */
1368                 dissector_try_string(media_type_table, "application/xml",
1369                                      xml_tvb, pinfo, sub_tree, NULL);
1370             } else {
1371                 /* Try plain text */
1372                 dissector_try_string(media_type_table, "text/plain",
1373                                      xml_tvb, pinfo, sub_tree, NULL);
1374             }
1375         }
1376         sub_offset += length;
1377     }
1378 }
1379 
1380 /**
1381  *@fn int dissect_eigrp_legacy_metric (proto_tree *tree, tvbuff_t *tvb, int offset)
1382  *
1383  * @param[in,out] tree  detail dissection result
1384  * @param[in] tvb       packet data
1385  * @param[in] offset    current byte offset in packet being processed
1386  *
1387  * @return int          number of bytes process
1388  *
1389  * @par
1390  * Dissect the TLV Versions 1.2 (legacy) and 3.0 (deprecated) metric
1391  * sections. The following represents the format
1392  *
1393  *    0                   1                   2                   3
1394  *    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
1395  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1396  *   |                       Scaled Delay                            |
1397  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1398  *   |                    Scaled Bandwidth                           |
1399  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1400  *   |         MTU                                    |   Hopcount   |
1401  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1402  *   | Reliability  |      Load     |  Internal Tag   |    Flag      |
1403  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1404  *
1405  */
1406 static int
dissect_eigrp_legacy_metric(proto_tree * tree,tvbuff_t * tvb,int offset)1407 dissect_eigrp_legacy_metric (proto_tree *tree, tvbuff_t *tvb, int offset)
1408 {
1409     proto_tree *sub_tree;
1410     tvbuff_t   *sub_tvb;
1411 
1412     sub_tree = proto_tree_add_subtree(tree, tvb, offset, 16, ett_eigrp_tlv_metric, NULL, "Legacy Metric");
1413     sub_tvb = tvb_new_subset_length_caplen(tvb, offset, 16, -1);
1414 
1415     proto_tree_add_item(sub_tree, hf_eigrp_legacy_metric_delay, sub_tvb,
1416                         0, 4, ENC_BIG_ENDIAN);
1417     proto_tree_add_item(sub_tree, hf_eigrp_legacy_metric_bw, sub_tvb,
1418                         4, 4, ENC_BIG_ENDIAN);
1419     proto_tree_add_item(sub_tree, hf_eigrp_legacy_metric_mtu, sub_tvb,
1420                         8, 3, ENC_BIG_ENDIAN);
1421     proto_tree_add_item(sub_tree, hf_eigrp_legacy_metric_hopcount, sub_tvb,
1422                         11, 1, ENC_BIG_ENDIAN);
1423     proto_tree_add_item(sub_tree, hf_eigrp_legacy_metric_rel, sub_tvb,
1424                         12, 1, ENC_BIG_ENDIAN);
1425     proto_tree_add_item(sub_tree, hf_eigrp_legacy_metric_load, sub_tvb,
1426                         13, 1, ENC_BIG_ENDIAN);
1427     proto_tree_add_item(sub_tree, hf_eigrp_legacy_metric_intag, sub_tvb,
1428                         14, 1, ENC_BIG_ENDIAN);
1429 
1430     /* Decode the route flags field */
1431     dissect_eigrp_metric_flags(sub_tree, sub_tvb, 15, 1);
1432 
1433     offset += 16;
1434     return(offset);
1435 }
1436 
1437 /**
1438  *@fn int dissect_eigrp_ipx_extdata (proto_tree *tree, tvbuff_t *tvb, int offset)
1439  *
1440  * @param[in,out] tree  detail dissection result
1441  * @param[in] tvb       packet data
1442  * @param[in] offset    current byte offset in packet being processed
1443  *
1444  * @return int          number of bytes process
1445  *
1446  * @par
1447  * Dissect the IPX External data for the TLV versions 1.2 and 3.0.
1448  * The following represents the format
1449  *
1450  *    0                   1                   2                   3
1451  *    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
1452  *                                   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1453  *                                   |          Ext RouterID         |
1454  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1455  *   |                       Ext Router ID                           |
1456  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1457  *   |                Ext Autonomous System Number                   |
1458  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1459  *   |                        Route Tag                              |
1460  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1461  *   |  Ext Protocol  | Ext Flags    |     External Metric           |
1462  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1463  *   |      External Delay           |
1464  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1465  */
1466 static int
dissect_eigrp_ipx_extdata(proto_tree * tree,tvbuff_t * tvb,int offset)1467 dissect_eigrp_ipx_extdata (proto_tree *tree, tvbuff_t *tvb, int offset)
1468 {
1469     proto_tree *sub_tree;
1470     tvbuff_t   *sub_tvb;
1471     int         sub_offset = 0;
1472 
1473     sub_tree = proto_tree_add_subtree(tree, tvb, offset, 20, ett_eigrp_tlv_extdata, NULL, "External Data");
1474     sub_tvb = tvb_new_subset_length_caplen(tvb, offset, 20, -1);
1475 
1476     /* Decode the external route source info */
1477     proto_tree_add_item(sub_tree, hf_eigrp_ipx_extdata_routerid, sub_tvb,
1478                         sub_offset, 6, ENC_NA);
1479     sub_offset += 6;
1480     proto_tree_add_item(sub_tree, hf_eigrp_extdata_as, sub_tvb,
1481                         sub_offset, 4, ENC_BIG_ENDIAN);
1482     sub_offset += 4;
1483     proto_tree_add_item(sub_tree, hf_eigrp_extdata_tag, sub_tvb,
1484                         sub_offset, 4, ENC_BIG_ENDIAN);
1485     sub_offset += 4;
1486     proto_tree_add_item(sub_tree, hf_eigrp_extdata_proto, sub_tvb,
1487                         sub_offset, 1, ENC_BIG_ENDIAN);
1488     sub_offset += 1;
1489 
1490     /* Decode the external route flags */
1491     dissect_eigrp_extdata_flags(sub_tree, sub_tvb, sub_offset);
1492     sub_offset += 1;
1493 
1494     /* and the rest of it... */
1495     proto_tree_add_item(sub_tree, hf_eigrp_ipx_extdata_metric,
1496                         sub_tvb, sub_offset, 2, ENC_BIG_ENDIAN);
1497     sub_offset += 2;
1498     proto_tree_add_item(sub_tree, hf_eigrp_ipx_extdata_delay,
1499                         sub_tvb, sub_offset, 2, ENC_BIG_ENDIAN);
1500     sub_offset += 2;
1501 
1502     offset += sub_offset;
1503     return(offset);
1504 }
1505 
1506 /**
1507  *@fn int dissect_eigrp_extdata (proto_tree *tree, tvbuff_t *tvb, int offset)
1508  *
1509  * @param[in,out] tree  detail dissection result
1510  * @param[in] tvb       packet data
1511  * @param[in] offset    current byte offset in packet being processed
1512  *
1513  * @return int          number of bytes process
1514  *
1515  * @par
1516  * Dissect the external route data for TLV versions 1.2 and 3.0 for all
1517  * protocols except IPX. The following represents the format
1518  *
1519  *    0                   1                   2                   3
1520  *    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
1521  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1522  *   |                       Ext Router ID                           |
1523  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1524  *   |                Ext Autonomous System Number                   |
1525  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1526  *   |                        Route Tag                              |
1527  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1528  *   |                    External Metric                            |
1529  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1530  *   |         Reserved             |   Ext Protocol  | Ext Flags    |
1531  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1532  */
1533 static int
dissect_eigrp_extdata(proto_tree * tree,tvbuff_t * tvb,int offset)1534 dissect_eigrp_extdata (proto_tree *tree, tvbuff_t *tvb, int offset)
1535 {
1536     proto_tree *sub_tree;
1537     tvbuff_t   *sub_tvb;
1538     int         sub_offset = 0;
1539 
1540     sub_tree = proto_tree_add_subtree(tree, tvb, offset, 20, ett_eigrp_tlv_extdata, NULL, "External Data");
1541     sub_tvb = tvb_new_subset_length_caplen(tvb, offset, 20, -1);
1542 
1543     /* Decode the external route source info */
1544     proto_tree_add_item(sub_tree, hf_eigrp_extdata_origrid, sub_tvb,
1545                         sub_offset, 4, ENC_BIG_ENDIAN);
1546     sub_offset += 4;
1547     proto_tree_add_item(sub_tree, hf_eigrp_extdata_as, sub_tvb,
1548                         sub_offset, 4, ENC_BIG_ENDIAN);
1549     sub_offset += 4;
1550     proto_tree_add_item(sub_tree, hf_eigrp_extdata_tag, sub_tvb,
1551                         sub_offset, 4, ENC_BIG_ENDIAN);
1552     sub_offset += 4;
1553     proto_tree_add_item(sub_tree, hf_eigrp_extdata_metric, sub_tvb,
1554                         sub_offset, 4, ENC_BIG_ENDIAN);
1555     sub_offset += 4;
1556     proto_tree_add_item(sub_tree, hf_eigrp_extdata_reserved, sub_tvb,
1557                         sub_offset, 2, ENC_BIG_ENDIAN);
1558     sub_offset += 2;
1559     proto_tree_add_item(sub_tree, hf_eigrp_extdata_proto, sub_tvb,
1560                         sub_offset, 1, ENC_BIG_ENDIAN);
1561     sub_offset += 1;
1562 
1563     /* Decode the external route flags */
1564     dissect_eigrp_extdata_flags(sub_tree, sub_tvb, sub_offset);
1565     sub_offset += 1;
1566 
1567     offset += sub_offset;
1568     return(offset);
1569 }
1570 
1571 /**
1572  *@fn int dissect_eigrp_nexthop (proto_tree *tree, tvbuff_t *tvb, guint16 afi, int offset)
1573  *
1574  * @param[in,out] tree  detail dissection result
1575  * @param[in] tvb       packet data
1576  * @param[in] afi       IANA address family indicator
1577  * @param[in] offset    current byte offset in packet being processed
1578  *
1579  * @return int          number of bytes process
1580  *
1581  * @par
1582  * Dissect the next hop field which is in the "route TLVs".  This function will
1583  * handle all the various protocol AFIs and return the appropriate number of
1584  * bytes processed
1585  */
1586 static int
dissect_eigrp_nexthop(proto_tree * tree,tvbuff_t * tvb,guint16 afi,int offset)1587 dissect_eigrp_nexthop (proto_tree *tree, tvbuff_t *tvb, guint16 afi, int offset)
1588 {
1589     /* dissect dest information */
1590     switch (afi) {
1591     case EIGRP_SF_IPv4:
1592     case EIGRP_AF_IPv4:
1593         proto_tree_add_item(tree, hf_eigrp_ipv4_nexthop, tvb, offset, 4,
1594                             ENC_BIG_ENDIAN);
1595         offset += 4;
1596         break;
1597 
1598     case EIGRP_SF_IPv6:
1599     case EIGRP_AF_IPv6:
1600         proto_tree_add_item(tree, hf_eigrp_ipv6_nexthop, tvb, offset, 16,
1601                             ENC_NA);
1602         offset += 16;
1603         break;
1604 
1605     case EIGRP_AF_IPX:
1606         proto_tree_add_item(tree, hf_eigrp_ipx_nexthop_net, tvb, offset, 4,
1607                             ENC_NA);
1608         offset += 4;
1609         proto_tree_add_item(tree, hf_eigrp_ipx_nexthop_host, tvb, offset, 6,
1610                             ENC_NA);
1611         offset += 6;
1612         break;
1613 
1614     case EIGRP_SF_COMMON:
1615         break;
1616 
1617     default:
1618         break;
1619     }
1620 
1621     return(offset);
1622 }
1623 
1624 /**
1625  *@fn void dissect_eigrp_general_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb,
1626  *                                    packet_info *pinfo, guint16 tlv)
1627  *
1628  * @param[in,out] tree  detail dissection result
1629  * @param[in] tvb       packet data
1630  * @param[in] pinfo     general data about the protocol
1631  * @param[in] ti        protocol item
1632  * @param[in] tlv       Specific TLV in to be dissected
1633  *
1634  * @par
1635  * General EIGRP parameters carry EIGRP management information and are not
1636  * specific to any one routed protocol.
1637  *
1638  */
1639 static void
dissect_eigrp_general_tlv(proto_item * ti,proto_tree * tree,tvbuff_t * tvb,packet_info * pinfo,guint16 tlv)1640 dissect_eigrp_general_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb,
1641                            packet_info *pinfo, guint16 tlv)
1642 {
1643     switch (tlv) {
1644     case EIGRP_TLV_PARAMETER:
1645         dissect_eigrp_parameter(tree, tvb, pinfo, ti);
1646         break;
1647     case EIGRP_TLV_AUTH:
1648         dissect_eigrp_auth_tlv(tree, tvb, pinfo, ti);
1649         break;
1650     case EIGRP_TLV_SEQ:
1651         dissect_eigrp_seq_tlv(tree, tvb, pinfo, ti);
1652         break;
1653     case EIGRP_TLV_SW_VERSION:
1654         dissect_eigrp_sw_version(tvb, tree, ti);
1655         break;
1656     case EIGRP_TLV_NEXT_MCAST_SEQ:
1657         dissect_eigrp_next_mcast_seq(tvb, tree, ti);
1658         break;
1659     case EIGRP_TLV_PEER_STUBINFO:
1660         dissect_eigrp_peer_stubinfo(tvb, tree);
1661         break;
1662     case EIGRP_TLV_PEER_TERMINATION:
1663         dissect_eigrp_peer_termination(pinfo, ti);
1664         break;
1665     case EIGRP_TLV_PEER_TIDLIST:
1666         dissect_eigrp_peer_tidlist(tree, tvb);
1667         break;
1668     default:
1669         expert_add_info_format(pinfo, ti, &ei_eigrp_tlv_type, "Unknown Generic TLV (0x%04x)", tlv);
1670         break;
1671     }
1672 }
1673 
1674 /**
1675  *@fn void dissect_eigrp_ipv4_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb,
1676  *                                 packet_info *pinfo, guint16 tlv)
1677  *
1678  * @param[in,out] tree  detail dissection result
1679  * @param[in] tvb       packet data
1680  * @param[in] pinfo     general data about the protocol
1681  * @param[in] tlv       Specific TLV in to be dissected
1682  *
1683  * @par
1684  * Dissect the Legacy IPv4 route TLV; handles both the internal and external
1685  * TLV types; This packet format is being deprecated and replaced with the
1686  * Multi-Protocol packet formats as of EIGRP Release-8.  This TLV format is used
1687  * to maintain backward compatibility between older version so EIGRP, "MTR"
1688  * EIGRP, and current shipping code.
1689  *
1690  *    0                   1                   2                   3
1691  *    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
1692  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1693  *   |                      IPv4 Nexthop                             |
1694  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1695  *   |                       Scaled Delay                            |
1696  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1697  *   |                    Scaled Bandwidth                           |
1698  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1699  *   |         MTU                                    |   Hopcount   |
1700  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1701  *   | Reliability  |      Load     |  Internal Tag   |   Flag       |
1702  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1703  */
1704 static void
dissect_eigrp_ipv4_tlv(proto_item * ti,proto_tree * tree,tvbuff_t * tvb,packet_info * pinfo,guint16 tlv)1705 dissect_eigrp_ipv4_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb,
1706                         packet_info *pinfo, guint16 tlv)
1707 {
1708     int offset      = 0;
1709     int unreachable = FALSE;
1710 
1711     proto_tree_add_item(tree, hf_eigrp_ipv4_nexthop, tvb, offset, 4,
1712                         ENC_BIG_ENDIAN);
1713     offset += 4;
1714 
1715     /* dissect external data if needed */
1716     if ((tlv & EIGRP_TLV_TYPEMASK) == EIGRP_TLV_EXTERNAL) {
1717         offset = dissect_eigrp_extdata(tree, tvb, offset);
1718     }
1719 
1720     /* dissect the metric */
1721     offset = dissect_eigrp_legacy_metric(tree, tvb, offset);
1722 
1723     /* dissect addresses */
1724     dissect_eigrp_ipv4_addrs(ti, tree, tvb, pinfo, offset, unreachable);
1725 }
1726 
1727 /**
1728  *@fn void dissect_eigrp_atalk_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb,
1729  *                                  proto_item *ti, guint16 tlv)
1730  *
1731  * @param[in,out] tree  detail dissection result
1732  * @param[in] tvb       packet data
1733  * @param[in] tlv       Specific TLV in to be dissected
1734  *
1735  * @par
1736  * Dissect the legacy AppleTalk route TLV; handles both the internal and external
1737  * TLV type.  The following represents the format
1738  */
1739 static void
dissect_eigrp_atalk_tlv(proto_item * ti,proto_tree * tree,tvbuff_t * tvb,guint16 tlv)1740 dissect_eigrp_atalk_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb,
1741                          guint16 tlv)
1742 {
1743     int offset = 0;
1744 
1745     /* cable tlv? */
1746     if (EIGRP_TLV_AT_CBL == tlv) {
1747         proto_tree_add_item(tree, hf_eigrp_appletalk_cable_range, tvb, 0, 4, ENC_BIG_ENDIAN);
1748         proto_tree_add_item(tree, hf_eigrp_atalk_routerid, tvb, 4, 4,
1749                             ENC_BIG_ENDIAN);
1750         proto_item_append_text(ti, ": Cable range= %u-%u, Router ID= %u",
1751                                tvb_get_ntohs(tvb, 0), tvb_get_ntohs(tvb, 2),
1752                                tvb_get_ntohl(tvb, 4));
1753 
1754     } else {
1755         proto_tree_add_item(tree, hf_eigrp_nexthop_address, tvb, offset, 4, ENC_BIG_ENDIAN);
1756         offset += 4;
1757 
1758         /* dissect external data if needed */
1759         if ((tlv & EIGRP_TLV_TYPEMASK) == EIGRP_TLV_EXTERNAL) {
1760             offset = dissect_eigrp_extdata(tree, tvb,offset);
1761         }
1762 
1763         /* dissect the metric */
1764         offset = dissect_eigrp_legacy_metric(tree, tvb, offset);
1765 
1766         /* dissect cable range */
1767         proto_tree_add_item(tree, hf_eigrp_cable_range, tvb, offset, 4, ENC_BIG_ENDIAN);
1768         proto_item_append_text(ti, ": %u-%u",
1769                                tvb_get_ntohs(tvb, 36), tvb_get_ntohs(tvb, 38));
1770     }
1771 }
1772 
1773 /**
1774  *@fn void dissect_eigrp_ipv6_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb,
1775  *                                 packet_info *pinfo, guint16 tlv)
1776  *
1777  * @param[in,out] tree  detail dissection result
1778  * @param[in] tvb       packet data
1779  * @param[in] pinfo     general data about the protocol
1780  * @param[in] tlv       Specific TLV in to be dissected
1781  *
1782  * @par
1783  * Dissect the Legacy IPv6 route TLV; handles both the internal and external
1784  * TLV types; This packet format is being deprecated and replaced with the
1785  * Multi-Protocol packet formats as of EIGRP Release-8.  This TLV format is used
1786  * to maintain backward compatibility between older version so EIGRP, "MTR"
1787  * EIGRP, and current shipping code.
1788  */
1789 static void
dissect_eigrp_ipv6_tlv(proto_item * ti,proto_tree * tree,tvbuff_t * tvb,packet_info * pinfo,guint16 tlv)1790 dissect_eigrp_ipv6_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb,
1791                         packet_info *pinfo, guint16 tlv)
1792 {
1793     int offset      = 0;
1794     int unreachable = FALSE;
1795 
1796     proto_tree_add_item(tree, hf_eigrp_ipv6_nexthop, tvb, offset, 16,
1797                         ENC_NA);
1798     offset += 16;
1799 
1800     /* dissect external data if needed */
1801     if ((tlv & EIGRP_TLV_TYPEMASK) == EIGRP_TLV_EXTERNAL) {
1802         offset = dissect_eigrp_extdata(tree, tvb, offset);
1803     }
1804 
1805     /* dissect the metric */
1806     offset = dissect_eigrp_legacy_metric(tree, tvb, offset);
1807 
1808     /* dissect addresses */
1809     dissect_eigrp_ipv6_addrs(ti, tree, tvb, pinfo, offset, unreachable);
1810 }
1811 
1812 /**
1813  *@fn void dissect_eigrp_ipx_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb,
1814  *                                packet_info *pinfo, guint16 tlv)
1815  *
1816  * @param[in,out] tree  detail dissection result
1817  * @param[in] tvb       packet data
1818  * @param[in] pinfo     general data about the protocol
1819  * @param[in] tlv       Specific TLV in to be dissected
1820  *
1821  * @par
1822  * Dissect the legacy IPX route TLV; handles both the internal and external
1823  * TLV type.  The following represents the format
1824  *
1825  *    0                   1                   2                   3
1826  *    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
1827  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1828  *   |                         Nexthop Net                           |
1829  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1830  *   |                        Nexthop Host                           |
1831  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1832  *   |  Nexthop Host(cont)           |
1833  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1834  *
1835  * Optional External Data:
1836  *                                   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1837  *                                   |          Ext RouterID         |
1838  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1839  *   |                       Ext Router ID                           |
1840  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1841  *   |                Ext Autonomous System Number                   |
1842  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1843  *   |                        Route Tag                              |
1844  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1845  *   |  Ext Protocol  | Ext Flags    |    External Metric            |
1846  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1847  *   |     External Delay            |
1848  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1849  *
1850  *                                   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1851  *                                   |           Scaled Delay        |
1852  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1853  *   |           Scaled Delay        |      Scaled Bandwidth         |
1854  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1855  *   |         Scaled Bandwidth      |             MTU               |
1856  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1857  *   |   MTU(cont)   |    Hopcount   | Reliability   |     Load      |
1858  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1859  *   | Internal Tag |      Flag      |
1860  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1861  *
1862  *
1863  */
1864 static void
dissect_eigrp_ipx_tlv(proto_item * ti,proto_tree * tree,tvbuff_t * tvb,packet_info * pinfo,guint16 tlv)1865 dissect_eigrp_ipx_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb,
1866                        packet_info *pinfo, guint16 tlv)
1867 {
1868     int offset      = 0;
1869     int unreachable = FALSE;
1870 
1871     /* nexthop for route... */
1872     offset = dissect_eigrp_nexthop(tree, tvb, EIGRP_AF_IPX, offset);
1873 
1874     /* dissect external data if needed */
1875     if ((tlv & EIGRP_TLV_TYPEMASK) == EIGRP_TLV_EXTERNAL) {
1876         offset = dissect_eigrp_ipx_extdata(tree, tvb, offset);
1877     }
1878 
1879     /* dissect the metric */
1880     offset = dissect_eigrp_legacy_metric(tree, tvb, offset);
1881 
1882     /* dissect addresses */
1883     dissect_eigrp_ipx_addrs(ti, tree, tvb, pinfo, offset, unreachable);
1884 }
1885 
1886 /**
1887  *@fn void dissect_eigrp_multi_topology_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb,
1888  *                                           packet_info *pinfo, proto_item *ti, guint16 tlv)
1889  *
1890  * @param[in,out] tree  detail dissection result
1891  * @param[in] tvb       packet data
1892  * @param[in] pinfo     general data about the protocol
1893  * @param[in] ti        protocol item
1894  * @param[in] tlv       Specific TLV in to be dissected
1895  *
1896  * @par
1897  * Dissect the Multi-Topology route TLV; This packet format has been deprecated
1898  * and replaced with the Multi-Protocol packet formats as of EIGRP Release-8. Of
1899  * course this means it will be around for a long long while. The following
1900  * represents the format
1901  *
1902  *    1       2                   3   0                   1         1
1903  *    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
1904  *                                   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1905  *                                   |           Reserved            |
1906  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1907  *   |   Topology Identifier         |       Family Identifier       |
1908  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1909  *   |                       Router ID                               |
1910  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1911  *   |                       Route Tag                               |
1912  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1913  *   |                       Scaled Delay                            |
1914  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1915  *   |                    Scaled Bandwidth                           |
1916  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1917  *   |         MTU                                    |   Hopcount   |
1918  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1919  *   | Reliability  |      Load      |  Internal Tag   |    Flag     |
1920  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1921  *   |\/\/\/         NextHop (Family Specific Length)          \/\/\/|
1922  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1923  *   |\/\/\/          External Route Data (Optional)           \/\/\/|
1924  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1925  *   |\/\/\/       Destination (Family Specific Length)        \/\/\/|
1926  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1927  *
1928  */
1929 static void
dissect_eigrp_multi_topology_tlv(proto_item * ti,proto_tree * tree,tvbuff_t * tvb,packet_info * pinfo,guint16 tlv)1930 dissect_eigrp_multi_topology_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb,
1931                                   packet_info *pinfo, guint16 tlv)
1932 {
1933     guint16     afi;
1934     int         offset      = 2;
1935     int         unreachable = FALSE;
1936 
1937     /* tid for you */
1938     proto_tree_add_item(tree, hf_eigrp_tid, tvb, offset, 2, ENC_BIG_ENDIAN);
1939     offset += 2;
1940 
1941     /* now it's all about the family */
1942     afi = tvb_get_ntohs(tvb, offset);
1943     proto_tree_add_item(tree, hf_eigrp_afi, tvb, offset, 2, ENC_BIG_ENDIAN);
1944     offset += 2;
1945 
1946     /* gota have an id... */
1947     proto_tree_add_item(tree, hf_eigrp_routerid, tvb, offset, 4, ENC_BIG_ENDIAN);
1948     offset += 4;
1949 
1950     /* tag.. your it! */
1951     proto_tree_add_item(tree, hf_eigrp_legacy_metric_tag, tvb, offset, 4, ENC_BIG_ENDIAN);
1952     offset += 4;
1953 
1954     /* dissect the metric */
1955     offset = dissect_eigrp_legacy_metric(tree, tvb, offset);
1956 
1957     /* dissect nexthop */
1958     offset = dissect_eigrp_nexthop(tree, tvb, afi, offset);
1959 
1960     /* dissect external data if needed */
1961     if ((tlv & EIGRP_TLV_TYPEMASK) == EIGRP_TLV_EXTERNAL) {
1962         if (afi == EIGRP_AF_IPX) {
1963             offset = dissect_eigrp_ipx_extdata(tree, tvb, offset);
1964         } else {
1965             offset = dissect_eigrp_extdata(tree, tvb, offset);
1966         }
1967     }
1968 
1969     /* dissect dest information */
1970     switch (afi) {
1971     case EIGRP_AF_IPv4:
1972         dissect_eigrp_ipv4_addrs(ti, tree, tvb, pinfo, offset, unreachable);
1973         break;
1974     case EIGRP_AF_IPv6:
1975         dissect_eigrp_ipv6_addrs(ti, tree, tvb, pinfo, offset, unreachable);
1976         break;
1977     case EIGRP_AF_IPX:
1978         dissect_eigrp_ipx_addrs(ti, tree, tvb, pinfo, offset, unreachable);
1979         break;
1980 
1981     case EIGRP_SF_COMMON:
1982     case EIGRP_SF_IPv4:
1983     case EIGRP_SF_IPv6:
1984         dissect_eigrp_services(ti, tree, tvb, pinfo, offset);
1985         break;
1986 
1987     default:
1988         proto_tree_add_expert(tree, pinfo, &ei_eigrp_afi, tvb, offset, -1);
1989     }
1990 }
1991 
1992 /**
1993  *@fn int dissect_eigrp_metric_comm (proto_tree *tree, tvbuff_t *tvb, int offset, int limit)
1994  *
1995  * @param[in,out] tree  detail dissection result
1996  * @param[in] tvb       packet data
1997  * @param[in] offset    current byte offset in packet being processed
1998  * @param[in] limit     maximum number of bytes which can be process
1999  *
2000  * @return int          number of bytes process
2001  *
2002  * @par
2003  * Dissect extended community attached to metric TLVs to support VPNv4
2004  * deployments, The following represents the format
2005  *
2006  *   0                   1                   2                   3
2007  *   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
2008  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2009  *  |  Type high    |  Type low(*)  |                               |
2010  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+          Value                |
2011  *  |                                                               |
2012  *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2013  */
2014 static int
dissect_eigrp_metric_comm(proto_tree * tree,tvbuff_t * tvb,int offset,int limit)2015 dissect_eigrp_metric_comm (proto_tree *tree, tvbuff_t *tvb, int offset, int limit)
2016 {
2017     int comm_type;
2018     proto_item* ti;
2019     proto_tree* type_tree;
2020 
2021     while (limit > 0) {
2022         comm_type = tvb_get_ntohs(tvb, offset);
2023         ti = proto_tree_add_uint(tree, hf_eigrp_metric_comm_type, tvb, offset, 2, comm_type);
2024         type_tree = proto_item_add_subtree(ti, ett_metric_comm_type);
2025 
2026         offset += 2;
2027 
2028         switch (comm_type) {
2029             /*
2030              * Tag for this route. It is present for all EIGRP VPNv4
2031              * routes, internal and external
2032              */
2033         case EIGRP_EXTCOMM_EIGRP:
2034             proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_flag, tvb, offset, 2, ENC_BIG_ENDIAN);
2035             proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_tag, tvb, offset+2, 4, ENC_BIG_ENDIAN);
2036             break;
2037 
2038         case EIGRP_EXTCOMM_VRR:
2039             proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_res, tvb, offset, 2, ENC_BIG_ENDIAN);
2040             proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_rid, tvb, offset+2, 4, ENC_BIG_ENDIAN);
2041             break;
2042 
2043             /*
2044              * Vecmetric information for given EIGRP VPNv4 route,
2045              * applies to both internal and external
2046              */
2047         case EIGRP_EXTCOMM_DAD:
2048             proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_as, tvb, offset, 2, ENC_BIG_ENDIAN);
2049             proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_sdly, tvb, offset+2, 4, ENC_BIG_ENDIAN);
2050             break;
2051 
2052         case EIGRP_EXTCOMM_VRHB:
2053             proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_rel, tvb, offset, 1, ENC_BIG_ENDIAN);
2054             proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_hop, tvb, offset+1, 1, ENC_BIG_ENDIAN);
2055             proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_sbw, tvb, offset+2, 4, ENC_BIG_ENDIAN);
2056             break;
2057 
2058         case EIGRP_EXTCOMM_SRLM:
2059             proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_res, tvb, offset, 1, ENC_BIG_ENDIAN);
2060             proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_load, tvb, offset+1, 1, ENC_BIG_ENDIAN);
2061             proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_mtu, tvb, offset+2, 4, ENC_BIG_ENDIAN);
2062             break;
2063 
2064             /*
2065              * External information for given EIGRP VPNv4 route,
2066              * applies to only to external routes
2067              */
2068         case EIGRP_EXTCOMM_SAR:
2069             proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_xas, tvb, offset, 2, ENC_BIG_ENDIAN);
2070             proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_xrid, tvb, offset+2, 4, ENC_BIG_ENDIAN);
2071             break;
2072 
2073         case EIGRP_EXTCOMM_RPM:
2074             proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_xproto, tvb, offset, 2, ENC_BIG_ENDIAN);
2075             proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_xmetric, tvb, offset+2, 4, ENC_BIG_ENDIAN);
2076             break;
2077 
2078         case EIGRP_EXTCOMM_SOO_ASFMT:
2079         case EIGRP_EXTCOMM_SOO_ADRFMT:
2080             proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_as, tvb, offset, 2, ENC_BIG_ENDIAN);
2081             proto_tree_add_item(type_tree, hf_eigrp_extcomm_eigrp_tag, tvb, offset+2, 4, ENC_BIG_ENDIAN);
2082             break;
2083         }
2084 
2085         proto_item_set_len(ti, 8);
2086 
2087         /*on to the next */
2088         offset += 6;
2089         limit -= 8;
2090 
2091         if (0 != limit%8) {
2092             break;
2093         }
2094 
2095     }
2096 
2097     return(offset);
2098 }
2099 
2100 /**
2101  *@fn int dissect_eigrp_wide_metric_attr (proto_tree *tree, tvbuff_t *tvb,
2102  *                                        int offset, int limit)
2103  *
2104  * @param[in,out] tree  detail dissection result
2105  * @param[in] tvb       packet data
2106  * @param[in] offset    current byte offset in packet being processed
2107  * @param[in] limit     maximum number of words which should be process
2108  *
2109  * @return int          number of bytes process
2110  *
2111  * @par
2112  * Dissect the Metric Attributes which (optionally) are part of the wide-metric
2113  * route TLV.  Some of the attributes which effect the metric are controlled by
2114  * K6 which is now part of the Parameter TLV.  Also, eh extended community TLV is
2115  * no longer used, as it's now appended to the route
2116  */
2117 static int
dissect_eigrp_wide_metric_attr(proto_tree * tree,tvbuff_t * tvb,int offset,int limit)2118 dissect_eigrp_wide_metric_attr (proto_tree *tree, tvbuff_t *tvb,
2119                                 int offset, int limit)
2120 {
2121     proto_tree *sub_tree;
2122     tvbuff_t   *sub_tvb;
2123     int         sub_offset;
2124 
2125     guint16 attr_offset = 0;
2126     guint8  attr_opcode = 0;
2127 
2128     limit *= 2;   /* words to bytes */
2129 
2130     sub_tree = proto_tree_add_subtree(tree, tvb, offset, limit, ett_eigrp_tlv_attr, NULL, "Attributes");
2131     sub_tvb    = tvb_new_subset_length_caplen(tvb, offset, limit, -1);
2132     sub_offset = 0;
2133 
2134     while (limit > 0) {
2135         attr_opcode = tvb_get_guint8(sub_tvb, sub_offset);
2136         proto_tree_add_item(sub_tree, hf_eigrp_attr_opcode, sub_tvb,
2137                             sub_offset, 1, ENC_BIG_ENDIAN);
2138         sub_offset += 1;
2139 
2140         attr_offset = tvb_get_guint8(sub_tvb, sub_offset) * 2;
2141         proto_tree_add_item(sub_tree, hf_eigrp_attr_offset, sub_tvb,
2142                             sub_offset, 1, ENC_BIG_ENDIAN);
2143         sub_offset += 1;
2144 
2145         switch (attr_opcode) {
2146         case EIGRP_ATTR_NOOP:
2147             break;
2148 
2149         case EIGRP_ATTR_SCALED:
2150             proto_tree_add_item(sub_tree, hf_eigrp_attr_scaled, sub_tvb,
2151                                 sub_offset, 4, ENC_BIG_ENDIAN);
2152             break;
2153 
2154         case EIGRP_ATTR_TAG:
2155             proto_tree_add_item(sub_tree, hf_eigrp_attr_tag, sub_tvb,
2156                                 sub_offset, 4, ENC_BIG_ENDIAN);
2157             break;
2158 
2159         case EIGRP_ATTR_COMM:
2160             dissect_eigrp_metric_comm(sub_tree,
2161                                       tvb_new_subset_length_caplen(sub_tvb, sub_offset, 8, -1),
2162                                       sub_offset, limit);
2163             break;
2164 
2165         case EIGRP_ATTR_JITTER:
2166             proto_tree_add_item(sub_tree, hf_eigrp_attr_jitter, sub_tvb,
2167                                 sub_offset, 4, ENC_BIG_ENDIAN);
2168             break;
2169 
2170         case EIGRP_ATTR_QENERGY:
2171             proto_tree_add_item(sub_tree, hf_eigrp_attr_qenergy, sub_tvb,
2172                                 sub_offset, 4, ENC_BIG_ENDIAN);
2173             break;
2174 
2175         case EIGRP_ATTR_ENERGY:
2176             proto_tree_add_item(sub_tree, hf_eigrp_attr_energy, sub_tvb,
2177                                 sub_offset, 4, ENC_BIG_ENDIAN);
2178             break;
2179 
2180         default:
2181             break;
2182         }
2183         sub_offset += attr_offset;
2184         limit -= (EIGRP_ATTR_HDRLEN + attr_offset);
2185     }
2186 
2187     offset += sub_offset;
2188     return(offset);
2189 }
2190 
2191 /**
2192  *@fn int dissect_eigrp_wide_metric (proto_tree *tree, tvbuff_t *tvb, int offset)
2193  *
2194  * @param[in,out] tree  detail dissection result
2195  * @param[in] tvb       packet data
2196  * @param[in] offset    current byte offset in packet being processed
2197  *
2198  * @return int          number of bytes process
2199  *
2200  * @par
2201  * Dissect the latest-n-greatest "Wide"Metric" definition for EIGRP. This
2202  * definition was created to address the higher speed links and should handle
2203  * things until we break the speed of light *wink*
2204  *
2205  *    0                   1                   2                   3
2206  *    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
2207  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2208  *   |    Offset    |   Priority     |  Reliability  |     Load      |
2209  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2210  *   |         MTU                                    |   Hopcount   |
2211  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2212  *   |                            Delay                              |
2213  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2214  *   |         Delay                 |         Bandwidth             |
2215  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2216  *   |                        Bandwidth                              |
2217  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2218  *   |         Reserved              |           Flags               |
2219  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2220  *   |\/\/\/        Extended Metrics (Variable Length)         \/\/\/|
2221  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2222  *
2223  */
2224 static int
dissect_eigrp_wide_metric(proto_tree * tree,tvbuff_t * tvb,int offset)2225 dissect_eigrp_wide_metric (proto_tree *tree, tvbuff_t *tvb, int offset)
2226 {
2227     proto_tree *sub_tree;
2228     tvbuff_t   *sub_tvb;
2229     gint8       attr_size = 0;
2230     guint64     big_num;
2231 
2232     sub_tree = proto_tree_add_subtree(tree, tvb, offset, 24, ett_eigrp_tlv_metric, NULL, "Wide Metric");
2233     sub_tvb = tvb_new_subset_length_caplen(tvb, offset, 24, -1);
2234 
2235     attr_size = tvb_get_guint8(sub_tvb, 0);
2236 
2237     proto_tree_add_item(sub_tree, hf_eigrp_metric_offset,
2238                         sub_tvb, 0,  1, ENC_BIG_ENDIAN);
2239     proto_tree_add_item(sub_tree, hf_eigrp_metric_priority,
2240                         sub_tvb, 1,  1, ENC_BIG_ENDIAN);
2241     proto_tree_add_item(sub_tree, hf_eigrp_metric_rel,
2242                         sub_tvb, 2,  1, ENC_BIG_ENDIAN);
2243     proto_tree_add_item(sub_tree, hf_eigrp_metric_load,
2244                         sub_tvb, 3,  1, ENC_BIG_ENDIAN);
2245     proto_tree_add_item(sub_tree, hf_eigrp_metric_mtu,
2246                         sub_tvb, 4,  3, ENC_BIG_ENDIAN);
2247     proto_tree_add_item(sub_tree, hf_eigrp_metric_hopcount,
2248                         sub_tvb, 7,  1, ENC_BIG_ENDIAN);
2249 
2250     /* The one-way latency along an unloaded path to the destination
2251      * expressed in units of nanoseconds per kilobyte. This number is not
2252      * scaled, as is the case with scaled delay. A delay of 0xFFFFFFFFFFFF
2253      * indicates an unreachable route. */
2254     big_num = tvb_get_ntoh64(sub_tvb, 8);
2255     big_num >>= 16;
2256     if (big_num == G_GUINT64_CONSTANT(0x0000ffffffffffff)) {
2257         proto_tree_add_uint64_format_value(sub_tree, hf_eigrp_metric_delay, sub_tvb, 8, 6, big_num, "Infinity");
2258     } else {
2259         proto_tree_add_uint64(sub_tree, hf_eigrp_metric_delay, sub_tvb, 8, 6, big_num);
2260     }
2261 
2262     /* The path bandwidth measured in kilobyte per second as presented by
2263      * the interface.  This number is not scaled, as is the case with scaled
2264      * bandwidth. A bandwidth of 0xFFFFFFFFFFFF indicates an unreachable
2265      * route.
2266      */
2267     big_num = tvb_get_ntoh64(sub_tvb, 14);
2268     big_num >>= 16;
2269     if (big_num == G_GUINT64_CONSTANT(0x0000ffffffffffff)) {
2270         proto_tree_add_uint64_format_value(sub_tree, hf_eigrp_metric_bandwidth, sub_tvb, 14, 6, big_num, "Infinity");
2271     } else {
2272         proto_tree_add_uint64(sub_tree, hf_eigrp_metric_bandwidth, sub_tvb, 14, 6, big_num);
2273     }
2274     proto_tree_add_item(sub_tree, hf_eigrp_metric_reserved, sub_tvb, 20, 2,
2275                         ENC_BIG_ENDIAN);
2276 
2277     /* Decode the route flags field */
2278     dissect_eigrp_metric_flags(sub_tree, sub_tvb, 22, 2);
2279     offset += 24;
2280 
2281     /* any extended metric attributes? */
2282     if (attr_size > 0) {
2283         offset = dissect_eigrp_wide_metric_attr(tree, tvb, offset, attr_size);
2284     }
2285 
2286     return(offset);
2287 }
2288 
2289 /**
2290  *@fn void dissect_eigrp_multi_protocol_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb,
2291  *                                           packet_info *pinfo, guint16 tlv)
2292 
2293  *
2294  * @param[in,out] tree  detail dissection result
2295  * @param[in] tvb       packet data
2296  * @param[in] ti        protocol item
2297  * @param[in] pinfo     general data about the protocol
2298  *
2299  * @par
2300  * Dissect the Multi-Protocol (TLV Version 2.0) TLV format definition. The following
2301  * represents the format
2302  *
2303  *    0                   1                   2                   3
2304  *    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
2305  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2306  *   |   Topology Identifier         |         Family Identifier     |
2307  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2308  *   |                       Router ID                               |
2309  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2310  *   |                      Wide Metric                              |
2311  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2312  *   |\/\/\/        Extended Metrics (Variable Length)         \/\/\/|
2313  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2314  *   |\/\/\/         NextHop (Family Specific Length)          \/\/\/|
2315  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2316  *   |\/\/\/          External Route Data (Optional)           \/\/\/|
2317  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2318  *   |\/\/\/       Destination (Family Specific Length)        \/\/\/|
2319  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2320  */
2321 static void
dissect_eigrp_multi_protocol_tlv(proto_item * ti,proto_tree * tree,tvbuff_t * tvb,packet_info * pinfo,guint16 tlv)2322 dissect_eigrp_multi_protocol_tlv (proto_item *ti, proto_tree *tree, tvbuff_t *tvb,
2323                                   packet_info *pinfo, guint16 tlv)
2324 {
2325     int         offset      = 0;
2326     guint16     afi;
2327     int         unreachable = FALSE;
2328 
2329     /* tid for you */
2330     proto_tree_add_item(tree, hf_eigrp_tid, tvb, offset, 2, ENC_BIG_ENDIAN);
2331     offset += 2;
2332 
2333     /* now it's all about the family */
2334     afi = tvb_get_ntohs(tvb, offset);
2335     proto_tree_add_item(tree, hf_eigrp_afi, tvb, offset, 2, ENC_BIG_ENDIAN);
2336     offset += 2;
2337 
2338     /* gota have an id... */
2339     proto_tree_add_item(tree, hf_eigrp_routerid, tvb, offset, 4, ENC_BIG_ENDIAN);
2340     offset += 4;
2341 
2342     /* decode the wide metric */
2343     offset = dissect_eigrp_wide_metric(tree, tvb, offset);
2344 
2345     /* dissect nexthop */
2346     offset = dissect_eigrp_nexthop(tree, tvb, afi, offset);
2347 
2348     /* dissect external data if needed */
2349     if ((tlv & EIGRP_TLV_TYPEMASK) == EIGRP_TLV_EXTERNAL) {
2350         if (afi == EIGRP_AF_IPX) {
2351             offset = dissect_eigrp_ipx_extdata(tree, tvb, offset);
2352         } else {
2353             offset = dissect_eigrp_extdata(tree, tvb, offset);
2354         }
2355     }
2356 
2357     /* dissect dest information */
2358     switch (afi) {
2359     case EIGRP_AF_IPv4:
2360         dissect_eigrp_ipv4_addrs(ti, tree, tvb, pinfo, offset, unreachable);
2361         break;
2362 
2363     case EIGRP_AF_IPv6:
2364         dissect_eigrp_ipv6_addrs(ti, tree, tvb, pinfo, offset, unreachable);
2365         break;
2366 
2367     case EIGRP_AF_IPX:
2368         dissect_eigrp_ipx_addrs(ti, tree, tvb, pinfo, offset, unreachable);
2369         break;
2370 
2371     case EIGRP_SF_COMMON:
2372     case EIGRP_SF_IPv4:
2373     case EIGRP_SF_IPv6:
2374         dissect_eigrp_services(ti, tree, tvb, pinfo, offset);
2375         break;
2376 
2377     default:
2378         proto_tree_add_expert(tree, pinfo, &ei_eigrp_afi, tvb, offset, -1);
2379     }
2380 }
2381 
2382 /**
2383  *@fn int dissect_eigrp (proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, void *data)
2384  *
2385  * @param[in] tvb       packet data
2386  * @param[in] pinfo     general data about the protocol
2387  * @param[in,out] tree  detail dissection result
2388  *
2389  * @return int          0 if packet is not for this decoder
2390  *
2391  * @par
2392  * This function is called to dissect the packets presented to it. The packet
2393  * data is held in a special buffer referenced here as tvb. The packet info
2394  * structure contains general data about the protocol, and can update
2395  * information here. The tree parameter is where the detail dissection takes
2396  * place.
2397  */
2398 #include <epan/in_cksum.h>
2399 
2400 static int
dissect_eigrp(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)2401 dissect_eigrp (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
2402 {
2403     proto_item *ti;
2404     proto_tree *eigrp_tree, *tlv_tree;
2405     guint       opcode, vrid;
2406     guint16     tlv;
2407     guint32     ack, size, offset = EIGRP_HEADER_LENGTH;
2408 
2409     /* Make entries in Protocol column and Info column on summary display */
2410     col_set_str(pinfo->cinfo, COL_PROTOCOL, "EIGRP");
2411 
2412     /* This field shows up as the "Info" column in the display; you should use
2413      * it, if possible, to summarize what's in the packet, so that a user
2414      * looking at the list of packets can tell what type of packet it is. See
2415      * section 1.5 for more information.
2416      */
2417     col_clear(pinfo->cinfo, COL_INFO);
2418 
2419     opcode = tvb_get_guint8(tvb, 1);
2420     ack    = tvb_get_ntohl(tvb, 12);
2421     if ((opcode == EIGRP_OPC_HELLO) && (0 != ack)) {
2422         opcode = EIGRP_OPC_ACK;
2423     }
2424 
2425     col_add_str(pinfo->cinfo, COL_INFO,
2426                 val_to_str(opcode, eigrp_opcode2string, "Unknown OpCode (0x%04x)"));
2427 
2428     /* A protocol dissector may be called in 2 different ways - with, or
2429      * without a non-null "tree" argument.
2430      * Note also that there is no guarantee, the first time the dissector is
2431      * called, whether "tree" will be null or not; your dissector must work
2432      * correctly, building or updating whatever state information is necessary,
2433      * in either case.
2434      */
2435     /* NOTE: The offset and length values in the call to
2436      * "proto_tree_add_item()" define what data bytes to highlight in the
2437      * hex display window when the line in the protocol tree display
2438      * corresponding to that item is selected.
2439      */
2440 
2441     /* create display subtree for the protocol */
2442     ti = proto_tree_add_protocol_format(tree, proto_eigrp, tvb, 0, -1,
2443                                         "Cisco EIGRP");
2444     eigrp_tree = proto_item_add_subtree(ti, ett_eigrp);
2445     proto_tree_add_item(eigrp_tree, hf_eigrp_version, tvb, 0, 1,
2446                         ENC_BIG_ENDIAN);
2447     proto_tree_add_item(eigrp_tree, hf_eigrp_opcode, tvb, 1, 1,
2448                         ENC_BIG_ENDIAN);
2449 
2450     size          = tvb_captured_length(tvb);
2451     proto_tree_add_checksum(eigrp_tree, tvb, 2, hf_eigrp_checksum, hf_eigrp_checksum_status, &ei_eigrp_checksum_bad,
2452                             pinfo, ip_checksum_tvb(tvb, 0, size), ENC_BIG_ENDIAN, PROTO_CHECKSUM_VERIFY|PROTO_CHECKSUM_IN_CKSUM);
2453 
2454     /* Decode the EIGRP Flags Field */
2455     proto_tree_add_bitmask(eigrp_tree, tvb, 4, hf_eigrp_flags, ett_eigrp_flags,
2456                            eigrp_flag_fields, ENC_BIG_ENDIAN);
2457 
2458     proto_tree_add_item(eigrp_tree, hf_eigrp_sequence, tvb, 8, 4,
2459                         ENC_BIG_ENDIAN);
2460     proto_tree_add_item(eigrp_tree, hf_eigrp_acknowledge, tvb, 12, 4,
2461                         ENC_BIG_ENDIAN);
2462 
2463     /* print out what family we dealing with... */
2464     ti = proto_tree_add_item(eigrp_tree, hf_eigrp_vrid, tvb, 16, 2,
2465                              ENC_BIG_ENDIAN);
2466     vrid = (tvb_get_ntohs(tvb, 16) & EIGRP_VRID_MASK);
2467     proto_item_append_text(ti, " %s", val_to_str_const(vrid, eigrp_vrid2string, ""));
2468 
2469     /* print autonomous-system */
2470     proto_tree_add_item(eigrp_tree, hf_eigrp_as, tvb, 18, 2,
2471                         ENC_BIG_ENDIAN);
2472 
2473     switch (opcode) {
2474     case EIGRP_OPC_IPXSAP:
2475         call_dissector(ipxsap_handle,
2476                        tvb_new_subset_remaining(tvb, EIGRP_HEADER_LENGTH), pinfo,
2477                        eigrp_tree);
2478         break;
2479 
2480     default:
2481         while (tvb_reported_length_remaining(tvb, offset) > 0) {
2482             tlv = tvb_get_ntohs(tvb, offset);
2483 
2484             /* it's a rose by the wrong name... */
2485             if (tlv == EIGRP_TLV_MTR_TIDLIST) {
2486                 tlv = EIGRP_TLV_PEER_TIDLIST;
2487             }
2488 
2489             size =  tvb_get_ntohs(tvb, offset + 2);
2490             if (size < 4) {
2491                 /*
2492                  * As the draft says, in section 6.6.2 "Length Field Encoding",
2493                  * "The value does includes[sic] the Type and Length fields".
2494                  *
2495                  * Therefore, it must be at least 4.
2496                  */
2497                 proto_tree_add_expert(eigrp_tree, pinfo, &ei_eigrp_tlv_len, tvb, offset, -1);
2498                 return(tvb_captured_length(tvb));
2499             }
2500 
2501             tlv_tree = proto_tree_add_subtree(eigrp_tree, tvb, offset, size, ett_eigrp_tlv, &ti,
2502                                      val_to_str(tlv, eigrp_tlv2string, "Unknown TLV (0x%04x)"));
2503 
2504             proto_tree_add_item(tlv_tree, hf_eigrp_tlv_type, tvb,
2505                                 offset, 2, ENC_BIG_ENDIAN);
2506             proto_tree_add_item(tlv_tree, hf_eigrp_tlv_len, tvb,
2507                                 (offset + 2), 2, ENC_BIG_ENDIAN);
2508 
2509             switch (tlv & EIGRP_TLV_RANGEMASK) {
2510             case EIGRP_TLV_GENERAL:
2511                 dissect_eigrp_general_tlv(ti, tlv_tree, tvb_new_subset_length(tvb, (offset + 4), (size - 4)), pinfo, tlv);
2512                 break;
2513 
2514             case EIGRP_TLV_IPv4:
2515                 dissect_eigrp_ipv4_tlv(ti, tlv_tree, tvb_new_subset_length(tvb, (offset + 4), (size - 4)), pinfo, tlv);
2516                 break;
2517 
2518             case EIGRP_TLV_ATALK:
2519                 dissect_eigrp_atalk_tlv(ti, tlv_tree, tvb_new_subset_length(tvb, (offset + 4), (size - 4)), tlv);
2520                 break;
2521 
2522             case EIGRP_TLV_IPX:
2523                 dissect_eigrp_ipx_tlv(ti, tlv_tree, tvb_new_subset_length(tvb, (offset + 4), (size - 4)), pinfo, tlv);
2524                 break;
2525 
2526             case EIGRP_TLV_IPv6:
2527                 dissect_eigrp_ipv6_tlv(ti, tlv_tree, tvb_new_subset_length(tvb, (offset + 4), (size - 4)), pinfo, tlv);
2528                 break;
2529 
2530             case EIGRP_TLV_MP:
2531                 dissect_eigrp_multi_protocol_tlv(ti, tlv_tree, tvb_new_subset_length(tvb, (offset + 4), (size - 4)),
2532                                                  pinfo, tlv);
2533                 break;
2534 
2535             case EIGRP_TLV_MTR:
2536                 dissect_eigrp_multi_topology_tlv(ti, tlv_tree, tvb_new_subset_length(tvb, (offset + 4), (size - 4)),
2537                                                  pinfo, tlv);
2538                 break;
2539 
2540             default:
2541                 expert_add_info_format(pinfo, ti, &ei_eigrp_tlv_type, "Unknown TLV Group (0x%04x)", tlv);
2542             }
2543 
2544             offset += size;
2545         }
2546         break;
2547     }
2548 
2549     /* Return the amount of data this dissector was able to dissect */
2550     return(tvb_captured_length(tvb));
2551 }
2552 
2553 static void
eigrp_fmt_cable_range(gchar * result,guint32 revision)2554 eigrp_fmt_cable_range(gchar *result, guint32 revision )
2555 {
2556    g_snprintf( result, ITEM_LABEL_LENGTH, "%u-%u", (guint16)(( revision & 0xFFFF0000 ) >> 16), (guint16)(revision & 0xFFFF) );
2557 }
2558 
2559 static void
eigrp_fmt_nexthop_address(gchar * result,guint32 revision)2560 eigrp_fmt_nexthop_address(gchar *result, guint32 revision )
2561 {
2562    g_snprintf( result, ITEM_LABEL_LENGTH, "%u.%u", (guint16)(( revision & 0xFFFF0000 ) >> 16), (guint16)(revision & 0xFFFF) );
2563 }
2564 
2565 static void
eigrp_fmt_version(gchar * result,guint32 revision)2566 eigrp_fmt_version(gchar *result, guint32 revision )
2567 {
2568    g_snprintf( result, ITEM_LABEL_LENGTH, "%d.%02d", (guint8)(( revision & 0xFF00 ) >> 8), (guint8)(revision & 0xFF) );
2569 }
2570 
2571 /**
2572  *@fn void proto_register_eigrp (void)
2573  *
2574  * @usage
2575  *      you can not have the function name inside a comment or else Wireshark
2576  *      will fail with "duplicate protocol" error.  Don't you hate it when tools
2577  *      try to be to smart :(
2578  *
2579  * @par
2580  *      Register the protocol with Wireshark
2581  *      this format is require because a script is used to build the C function
2582  *      that calls all the protocol registration.
2583  */
2584 void
proto_register_eigrp(void)2585 proto_register_eigrp(void)
2586 {
2587     /* Setup list of header fields  See Section 1.6.1 for details
2588      */
2589     static hf_register_info hf[] = {
2590         /*
2591          *
2592          * EIGRP Packet Header definitions
2593          *
2594          *    0                   1                   2                   3
2595          *    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
2596          *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2597          *   |Ver              |  Opcode       |          Checksum           |
2598          *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2599          *   |                          Flags                                |
2600          *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2601          *   |                      Sequence number                          |
2602          *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2603          *   |                    Acknowledgement number                     |
2604          *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2605          *   |  Virtual Router ID              | Autonomous system number    |
2606          *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2607          */
2608         { &hf_eigrp_version,
2609           { "Version", "eigrp.version",
2610             FT_UINT8, BASE_DEC, NULL, 0x0,
2611             "Version - Version of EIGRP packet format", HFILL }
2612         },
2613         { &hf_eigrp_opcode,
2614           { "Opcode", "eigrp.opcode",
2615             FT_UINT8, BASE_DEC, VALS(eigrp_opcode2string), 0x0,
2616             "Opcode - Operation code indicating the message type", HFILL }
2617         },
2618         { &hf_eigrp_flags,
2619           { "Flags", "eigrp.flags",
2620             FT_UINT32, BASE_HEX, NULL, 0x0,
2621             "Flag - Initialization bit and is used in establishing "
2622             "a new neighbor relationship", HFILL }
2623         },
2624         { &hf_eigrp_sequence,
2625           { "Sequence", "eigrp.seq",
2626             FT_UINT32, BASE_DEC, NULL, 0x0,
2627             "Sequence number -- used to send messages reliably", HFILL }
2628         },
2629         { &hf_eigrp_acknowledge,
2630           { "Acknowledge", "eigrp.ack",
2631             FT_UINT32, BASE_DEC, NULL, 0x0,
2632             "Acknowledge number -- used to send messages reliably", HFILL }
2633         },
2634         { &hf_eigrp_vrid,
2635           { "Virtual Router ID", "eigrp.vrid",
2636             FT_UINT16, BASE_DEC, NULL, 0,
2637             "Virtual Router ID - For each Virtual Router, there is a separate topology "
2638             "table and routing/service table; even for matching AS. "
2639             "This field allows the gateway to select which set router to use.", HFILL }
2640         },
2641         { &hf_eigrp_as,
2642           { "Autonomous System", "eigrp.as",
2643             FT_UINT16, BASE_DEC, NULL, 0x0,
2644             "Autonomous system number - Each AS has a separate topology table "
2645             "which for a give routing/service table. A gateway can participate "
2646             "in more than one AS. This field allows the gateway to"
2647             "select which set of topology tables to use.", HFILL }
2648         },
2649 
2650         /*
2651          * Define eigrp_flags bits here
2652          *
2653          * Init bit definition. First unicast transmitted Update has this
2654          * bit set in the flags field of the fixed header. It tells the neighbor
2655          * to send its full topology table.
2656          */
2657         { &hf_eigrp_flags_init,
2658           { "Init", "eigrp.flags.init",
2659             FT_BOOLEAN, 32, TFS(&tfs_set_notset), EIGRP_INIT_FLAG,
2660             "Init - tells the neighbor to send its full topology table", HFILL }
2661         },
2662 
2663         /*
2664          * Conditionally Received - Any packet with the CR-bit set can
2665          * be accepted by an EIGRP speaker if and only if a previous Hello was
2666          * received with the SEQUENCE_TYPE TLV present.
2667          * This allows multicasts to be transmitted in order and reliably at the
2668          * same time as unicasts are transmitted.
2669          */
2670         { &hf_eigrp_flags_condrecv,
2671           { "Conditional Receive", "eigrp.flags.condrecv",
2672             FT_BOOLEAN, 32, TFS(&tfs_set_notset), EIGRP_CR_FLAG,
2673             "Conditionally Received the next packet if address was in listed "
2674             "in the previous HELLO", HFILL }
2675         },
2676 
2677         /*
2678          * Restart flag is set in the hello and the init update
2679          * packets during the nsf signaling period.  A nsf-aware
2680          * router looks at the RS flag to detect if a peer is restarting
2681          * and maintain the adjacency. A restarting router looks at
2682          * this flag to determine if the peer is helping out with the restart.
2683          */
2684         { &hf_eigrp_flags_restart,
2685           { "Restart", "eigrp.flags.restart",
2686             FT_BOOLEAN, 32, TFS(&tfs_set_notset), EIGRP_RS_FLAG,
2687             "Restart flag - Set in the HELLO and the initial "
2688             "UPDATE packets during the nsf signaling period.", HFILL },
2689         },
2690 
2691         /*
2692          * EOT bit.  The End-of-Table flag marks the end of the start-up updates
2693          * sent to a new peer.  A nsf restarting router looks at this flag to
2694          * determine if it has finished receiving the start-up updates from all
2695          * peers.  A nsf-aware router waits for this flag before cleaning up
2696          * the stale routes from the restarting peer.
2697          */
2698         { &hf_eigrp_flags_eot,
2699           { "End Of Table", "eigrp.flags.eot",
2700             FT_BOOLEAN, 32, TFS(&tfs_set_notset), EIGRP_EOT_FLAG,
2701             "End-of-Table - Marks the end of the start-up UPDATES indicating the "
2702             "complete topology database has been sent to a new peer", HFILL }
2703         },
2704 
2705         /**
2706          * TLV type definitions.  Generic (protocol-independent) TLV types are
2707          * defined here.  Protocol-specific ones are defined later
2708          *
2709          *     +-----+------------------+
2710          *     |     |     |            |
2711          *     | Type| Len |    Vector  |
2712          *     |     |     |            |
2713          *     +-----+------------------+
2714          *
2715          * TLV type definitions.  Generic (protocol-independent) TLV types are
2716          * defined here.  Protocol-specific ones are defined elsewhere.
2717          *
2718          * EIGRP_PARAMETER              0x0001          parameter
2719          * EIGRP_AUTH                   0x0002          authentication
2720          * EIGRP_SEQUENCE               0x0003          sequenced packet
2721          * EIGRP_SW_VERSION             0x0004          software version
2722          * EIGRP_NEXT_MCAST_SEQ         0x0005          multicast sequence
2723          * EIGRP_PEER_STUBINFO          0x0006          stub information
2724          * EIGRP_PEER_TERMINATION       0x0007          peer termination
2725          */
2726         { &hf_eigrp_tlv_type,
2727           { "Type", "eigrp.tlv_type",
2728             FT_UINT16, BASE_HEX, VALS(eigrp_tlv2string), 0x0,
2729             "TLV Type", HFILL }
2730         },
2731         { &hf_eigrp_tlv_len,
2732           { "Length", "eigrp.tlv.len",
2733             FT_UINT16, BASE_DEC, NULL, 0x0,
2734             "TLV Length", HFILL }
2735         },
2736 
2737 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2738  * Parameters TLV
2739  */
2740         { &hf_eigrp_par_k1, { "K1", "eigrp.par.k1", FT_UINT8, BASE_DEC, NULL, 0x0,
2741                               "Bandwidth/Throughput Coefficient", HFILL }},
2742         { &hf_eigrp_par_k2, { "K2", "eigrp.par.k2", FT_UINT8, BASE_DEC, NULL, 0x0,
2743                               "Load Coefficient", HFILL }},
2744         { &hf_eigrp_par_k3, { "K3", "eigrp.par.k3", FT_UINT8, BASE_DEC, NULL, 0x0,
2745                               "Delay/Latency Coefficient", HFILL }},
2746         { &hf_eigrp_par_k4, { "K4", "eigrp.par.k4", FT_UINT8, BASE_DEC, NULL, 0x0,
2747                               "Reliability Coefficient", HFILL }},
2748         { &hf_eigrp_par_k5, { "K5", "eigrp.par.k5", FT_UINT8, BASE_DEC, NULL, 0x0,
2749                               "Reliability Coefficient", HFILL }},
2750         { &hf_eigrp_par_k6, { "K6", "eigrp.par.k6", FT_UINT8, BASE_DEC, NULL, 0x0,
2751                               "Extended Metric Coefficient", HFILL }},
2752         { &hf_eigrp_par_holdtime,
2753           { "Hold Time", "eigrp.par.holdtime", FT_UINT16, BASE_DEC, NULL, 0x0,
2754             "How long to ignore lost HELLO's", HFILL }
2755         },
2756 
2757 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2758  * Authentication TLV
2759  */
2760         { &hf_eigrp_auth_type,
2761           { "Type", "eigrp.auth.type",
2762             FT_UINT16, BASE_DEC, VALS(eigrp_auth2string), 0x0,
2763             NULL, HFILL }
2764         },
2765         { &hf_eigrp_auth_len,
2766           { "Length", "eigrp.auth.length",
2767             FT_UINT16, BASE_DEC, NULL, 0x0,
2768             NULL, HFILL }
2769         },
2770         { &hf_eigrp_auth_keyid,
2771           { "Key ID", "eigrp.auth.keyid",
2772             FT_UINT32, BASE_DEC, NULL, 0x0,
2773             NULL, HFILL }
2774         },
2775         { &hf_eigrp_auth_keyseq,
2776           { "Key Sequence", "eigrp.auth.keyseq",
2777             FT_UINT32, BASE_DEC, NULL, 0x0,
2778             NULL, HFILL }
2779         },
2780         { &hf_eigrp_auth_digest,
2781           { "Digest", "eigrp.auth.digest",
2782             FT_BYTES, BASE_NONE, NULL, 0x0,
2783             NULL, HFILL }
2784         },
2785 
2786 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2787  * Sequence TLV
2788  */
2789         { &hf_eigrp_seq_addrlen,
2790           { "Address length", "eigrp.seq.addrlen",
2791             FT_UINT8, BASE_DEC, NULL, 0x0,
2792             NULL, HFILL }
2793         },
2794         { &hf_eigrp_seq_ipv4addr,
2795           { "IP Address", "eigrp.seq.ipv4addr",
2796             FT_IPv4, BASE_NONE, NULL, 0x0,
2797             NULL, HFILL }
2798         },
2799         { &hf_eigrp_seq_ipv6addr,
2800           { "IPv6 Address", "eigrp.seq.ipv6addr",
2801             FT_IPv6, BASE_NONE, NULL, 0x0,
2802             NULL, HFILL }
2803         },
2804 
2805 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2806  * Next Multicast Sequence
2807  */
2808         /*
2809          * This was added to the hello containing the sequence TLV so that the
2810          * hello packet could be more tightly bound to the multicast packet bearing
2811          * the CR bit that follows it.  The sequence number of the impending multicast
2812          * is carried herein.
2813          */
2814         { &hf_eigrp_next_mcast_seq,
2815           { "Multicast Sequence", "eigrp.next_mcast_seq",
2816             FT_UINT32, BASE_DEC, NULL, 0x0,
2817             NULL, HFILL }
2818         },
2819 
2820 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2821  * Peer Stub Information TLV
2822  */
2823         { &hf_eigrp_stub_flags,
2824           { "Stub Options", "eigrp.stub_options",
2825             FT_UINT16, BASE_HEX, NULL, 0x0,
2826             NULL, HFILL }
2827         },
2828 
2829         /*
2830          * Define eigrp_stub_flags bits here
2831          */
2832         { &hf_eigrp_stub_flags_connected,
2833           { "Connected", "eigrp.stub_options.connected",
2834             FT_BOOLEAN, 16, TFS(&tfs_set_notset), EIGRP_PEER_ALLOWS_CONNECTED,
2835             NULL, HFILL }
2836         },
2837         { &hf_eigrp_stub_flags_static,
2838           { "Static", "eigrp.stub_options.static",
2839             FT_BOOLEAN, 16, TFS(&tfs_set_notset), EIGRP_PEER_ALLOWS_STATIC,
2840             NULL, HFILL }
2841         },
2842         { &hf_eigrp_stub_flags_summary,
2843           { "Summary", "eigrp.stub_options.summary",
2844             FT_BOOLEAN, 16, TFS(&tfs_set_notset), EIGRP_PEER_ALLOWS_SUMMARY,
2845             NULL, HFILL }
2846         },
2847         { &hf_eigrp_stub_flags_redist,
2848           { "Redistributed", "eigrp.stub_options.redist",
2849             FT_BOOLEAN, 16, TFS(&tfs_set_notset), EIGRP_PEER_ALLOWS_REDIST,
2850             NULL, HFILL }
2851         },
2852         { &hf_eigrp_stub_flags_leakmap,
2853           { "Leak-Map", "eigrp.stub_options.leakmap",
2854             FT_BOOLEAN, 16, TFS(&tfs_set_notset), EIGRP_PEER_ALLOWS_LEAKING,
2855             NULL, HFILL }
2856         },
2857         { &hf_eigrp_stub_flags_recvonly,
2858           { "Receive-Only", "eigrp.stub_options.recvonly",
2859             FT_BOOLEAN, 16, TFS(&tfs_set_notset), EIGRP_PEER_ALLOWS_RCVONLY,
2860             NULL, HFILL }
2861         },
2862 
2863 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2864  * Peer Termination TLV
2865  */
2866         /* Place holder - this TLV has no options */
2867 
2868 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2869  * EIGRP 3.0 Vector Header  (deprecated)
2870  */
2871         /*
2872          * common header for all version 3 tlvs
2873          */
2874         { &hf_eigrp_tid,
2875           { "Topology", "eigrp.tid",
2876             FT_UINT16, BASE_DEC, NULL, 0x0,
2877             NULL, HFILL }
2878         },
2879         { &hf_eigrp_afi,
2880           { "AFI", "eigrp.afi",
2881             FT_UINT16, BASE_DEC, VALS(eigrp_afi2string), 0x0,
2882             NULL, HFILL }
2883         },
2884 
2885 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2886  * EIGRP TLV 1.2 (legacy) and TLV 3.0 Metric (deprecated) definition
2887  */
2888         { &hf_eigrp_legacy_metric_delay,
2889           { "Scaled Delay", "eigrp.old_metric.delay",
2890             FT_UINT32, BASE_DEC, NULL, 0x0,
2891             "delay, in 39.1 nanosec interments", HFILL }
2892         },
2893         { &hf_eigrp_legacy_metric_bw,
2894           { "Scaled BW", "eigrp.old_metric.bw",
2895             FT_UINT32, BASE_DEC, NULL, 0x0,
2896             "bandwidth, in units of 1 Kbit/sec", HFILL }
2897         },
2898         { &hf_eigrp_legacy_metric_mtu,
2899           { "MTU", "eigrp.old_metric.mtu",
2900             FT_UINT24, BASE_DEC, NULL, 0x0,
2901             "MTU, in octets", HFILL }
2902         },
2903         { &hf_eigrp_legacy_metric_hopcount,
2904           { "Hop Count", "eigrp.old_metric.hopcount",
2905             FT_UINT8, BASE_DEC, NULL, 0x0,
2906             "Number of hops to destination", HFILL }
2907         },
2908         { &hf_eigrp_legacy_metric_rel,
2909           { "Reliability", "eigrp.old_metric.rel",
2910             FT_UINT8, BASE_DEC, NULL, 0x0,
2911             "percent packets successfully tx/rx", HFILL }
2912         },
2913         { &hf_eigrp_legacy_metric_load,
2914           { "Load", "eigrp.old_metric.load",
2915             FT_UINT8, BASE_DEC, NULL, 0x0,
2916             "percent of channel occupied", HFILL }
2917         },
2918         { &hf_eigrp_legacy_metric_intag,
2919           { "Route Tag", "eigrp.old_metric.intag",
2920             FT_UINT8, BASE_DEC, NULL, 0x0,
2921             "Internal Route Tag", HFILL }
2922         },
2923 
2924 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2925  * EIGRP 3.0 TIDLIST TLV  (only survivor in MTR)
2926  */
2927         { &hf_eigrp_tidlist_tid,
2928           { "TID List", "eigrp.tidlist",
2929             FT_UINT16, BASE_DEC, NULL, 0x0,
2930             NULL, HFILL }
2931         },
2932         { &hf_eigrp_tidlist_flags,
2933           { "TID List Flags", "eigrp.tidlist.flags",
2934             FT_UINT16, BASE_HEX, NULL, 0x0,
2935             NULL, HFILL }
2936         },
2937         { &hf_eigrp_tidlist_len,
2938           { "TID List Size", "eigrp.tidlist.len",
2939             FT_UINT16, BASE_DEC, NULL, 0x0,
2940             NULL, HFILL }
2941         },
2942         { &hf_eigrp_routerid,
2943           { "RouterID", "eigrp.routerid",
2944             FT_IPv4, BASE_NONE, NULL, 0x0,
2945             "Router ID of injecting router", HFILL }
2946         },
2947         { &hf_eigrp_legacy_metric_tag,
2948           { "Tag", "eigrp.old_metric.tag",
2949             FT_UINT32, BASE_DEC, NULL, 0x0,
2950             "route tag", HFILL }
2951         },
2952 
2953 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2954  *
2955  * PDM opaque flag field definitions
2956  */
2957         { &hf_eigrp_metric_flags_srcwd,
2958           { "Source Withdraw", "eigrp.metric.flags.srcwd",
2959             FT_BOOLEAN, 8, TFS(&tfs_true_false), EIGRP_OPAQUE_SRCWD,
2960             "Route Source Withdraw", HFILL }
2961         },
2962         { &hf_eigrp_metric_flags_cd,
2963           { "Candidate Default", "eigrp.metric.flags.cd",
2964             FT_BOOLEAN, 8, TFS(&tfs_true_false), EIGRP_OPAQUE_CD,
2965             NULL, HFILL }
2966         },
2967         { &hf_eigrp_metric_flags_active,
2968           { "Route is Active", "eigrp.metric.flags.active",
2969             FT_BOOLEAN, 8, TFS(&tfs_true_false), EIGRP_OPAQUE_ACTIVE,
2970             "Route is currently in active state", HFILL }
2971         },
2972         { &hf_eigrp_metric_flags_repl,
2973           { "Route is Replicated", "eigrp.metric.flags.repl",
2974             FT_BOOLEAN, 8, TFS(&tfs_true_false), EIGRP_OPAQUE_REPL,
2975             "Route is replicated from different tableid", HFILL }
2976         },
2977 
2978 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2979  * EIGRP TLV 1.2/3.0 ExtData Definitions
2980  */
2981         { &hf_eigrp_extdata_origrid,
2982           { "Originating RouterID", "eigrp.extdata.origrid",
2983             FT_IPv4, BASE_NONE, NULL, 0x0,
2984             "Router ID of redistributing router", HFILL }
2985         },
2986 
2987         { &hf_eigrp_extdata_as,
2988           { "Originating A.S.", "eigrp.extdata.as",
2989             FT_UINT32, BASE_DEC, NULL, 0x0,
2990             "Autonomous System of redistributing protocol", HFILL }
2991         },
2992 
2993         { &hf_eigrp_extdata_tag,
2994           { "Administrative Tag", "eigrp.extdata.tag",
2995             FT_UINT32, BASE_DEC, NULL, 0x0,
2996             "Administrative Route Tag", HFILL }
2997         },
2998         { &hf_eigrp_extdata_metric,
2999           { "External Metric", "eigrp.extdata.metric",
3000             FT_UINT32, BASE_DEC, NULL, 0x0,
3001             "Metric reported by redistributing protocol", HFILL }
3002         },
3003         { &hf_eigrp_extdata_reserved,
3004           { "Reserved", "eigrp.extdata.reserved",
3005             FT_UINT16, BASE_DEC, NULL, 0x0,
3006             NULL, HFILL }
3007         },
3008 
3009         /* IPX ExtData Definitions */
3010         { &hf_eigrp_ipx_extdata_delay,
3011           { "External Delay", "eigrp.extdata.ipx_delay",
3012             FT_UINT16, BASE_DEC, NULL, 0x0,
3013             "Delay reported by redistributing protocol", HFILL }
3014         },
3015         { &hf_eigrp_ipx_extdata_metric,
3016           { "External Metric", "eigrp.extdata.ipx_metric",
3017             FT_UINT16, BASE_DEC, NULL, 0x0,
3018             "Delay reported by redistributing protocol", HFILL }
3019         },
3020 
3021         { &hf_eigrp_extdata_proto,
3022           { "External Protocol ID", "eigrp.extdata.proto",
3023             FT_UINT8, BASE_DEC, VALS(eigrp_proto2string), 0x0,
3024             NULL, HFILL }
3025         },
3026 
3027         { &hf_eigrp_extdata_flag_ext,
3028           { "Route is External", "eigrp.opaque.flag.ext",
3029             FT_BOOLEAN, 8, TFS(&tfs_true_false), EIGRP_OPAQUE_EXT,
3030             "External route", HFILL }
3031         },
3032         { &hf_eigrp_extdata_flag_cd,
3033           { "Route is Candidate Default", "eigrp.opaque.flag.cd",
3034             FT_BOOLEAN, 8, TFS(&tfs_true_false), EIGRP_OPAQUE_CD,
3035             "Candidate-Default route", HFILL }
3036         },
3037 
3038 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
3039  * EIGRP TLV 2.0 "Wide" Metric format definition
3040  */
3041         /* Number of 16bit words in the metric section, used to determine the
3042          * start of the destination/attribute information.
3043          */
3044         { &hf_eigrp_metric_offset,
3045           { "Offset", "eigrp.metric.offset",
3046             FT_UINT8, BASE_DEC, NULL, 0x0,
3047             "Number of 16bit words to reach the start of the"
3048             "destination/attribute information", HFILL }
3049         },
3050 
3051         /* Priority of the prefix when transmitting a group of destination
3052          * addresses to neighboring routers. A priority of zero indicates no
3053          * priority is set.
3054          */
3055         { &hf_eigrp_metric_priority,
3056           { "Priority", "eigrp.metric.priority",
3057             FT_UINT8, BASE_DEC, NULL, 0x0,
3058             "Priority of the prefix for ordering transmission", HFILL }
3059         },
3060 
3061         /** The current error rate for the path. Measured as an error
3062          * percentage. A value of 255 indicates 100% reliability
3063          */
3064         { &hf_eigrp_metric_rel,
3065           { "Reliability", "eigrp.metric.reliability",
3066             FT_UINT8, BASE_DEC, NULL, 0x0,
3067             "percent packets successfully tx/rx", HFILL }
3068         },
3069 
3070         /** The load utilization of the path to the destination. Measured as a
3071          * percentage of load. A value of 255 indicates 100% load.
3072          */
3073         { &hf_eigrp_metric_load,
3074           { "Load", "eigrp.metric.load",
3075             FT_UINT8, BASE_DEC, NULL, 0x0,
3076             "percent of channel occupied", HFILL }
3077         },
3078 
3079         /** The minimum maximum transmission unit size for the path to the
3080          * destination. Not used in metric calculation, but available to
3081          * underlying protocols
3082          */
3083         { &hf_eigrp_metric_mtu,
3084           { "MTU", "eigrp.metric.mtu",
3085             FT_UINT24, BASE_DEC, NULL, 0x0,
3086             "MTU, in octets", HFILL }
3087         },
3088 
3089         /** number of router traversals to the destination */
3090         { &hf_eigrp_metric_hopcount,
3091           { "Hop Count", "eigrp.metric.hopcount",
3092             FT_UINT8, BASE_DEC, NULL, 0x0,
3093             "Number of hops to destination", HFILL }
3094         },
3095 
3096         /* Reserved - Transmitted as 0x0000 */
3097         { &hf_eigrp_metric_reserved,
3098           { "Reserved", "eigrp.metric.reserved",
3099             FT_UINT16, BASE_HEX, NULL, 0x0,
3100             NULL, HFILL }
3101         },
3102 
3103 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
3104  * EIGRP TLV 2.0 Extended Metric Attributes
3105  */
3106         { &hf_eigrp_attr_opcode,
3107           { "Opcode", "eigrp.attr.opcode",
3108             FT_UINT8, BASE_DEC, VALS(eigrp_attr_opcode2string), 0x0,
3109             "Opcode - Operation code indicating the attribute type", HFILL }
3110         },
3111         { &hf_eigrp_attr_offset,
3112           { "Offset", "eigrp.attr.offset",
3113             FT_UINT8, BASE_DEC, NULL, 0x0,
3114             "Number of 2 byte words of data", HFILL }
3115         },
3116         { &hf_eigrp_attr_scaled,
3117           { "Legacy Metric", "eigrp.attr.scaled",
3118             FT_UINT16, BASE_DEC, NULL, 0x0,
3119             "Metric calculated from legacy TLVs", HFILL }
3120         },
3121         { &hf_eigrp_attr_tag,
3122           { "Tag", "eigrp.attr.tag",
3123             FT_UINT16, BASE_DEC, NULL, 0x0,
3124             "Tag assigned by admin for dest", HFILL }
3125         },
3126         { &hf_eigrp_attr_jitter,
3127           { "Jitter", "eigrp.attr.jitter",
3128             FT_UINT16, BASE_DEC, NULL, 0x0,
3129             "Variation in path delay", HFILL }
3130         },
3131         { &hf_eigrp_attr_qenergy,
3132           { "Q-Energy", "eigrp.attr.qenergy",
3133             FT_UINT16, BASE_DEC, NULL, 0x0,
3134             "Non-Active energy usage along path", HFILL }
3135         },
3136         { &hf_eigrp_attr_energy,
3137           { "Energy", "eigrp.attr.energy",
3138             FT_UINT16, BASE_DEC, NULL, 0x0,
3139             "Active energy usage along path", HFILL }
3140         },
3141 
3142 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
3143  *
3144  * IPv4 specific address definitions
3145  */
3146         { &hf_eigrp_ipv4_nexthop,
3147           { "NextHop", "eigrp.ipv4.nexthop",
3148             FT_IPv4, BASE_NONE, NULL, 0x0,
3149             NULL, HFILL }
3150         },
3151         { &hf_eigrp_ipv4_prefixlen,
3152           { "Prefix Length", "eigrp.ipv4.prefixlen",
3153             FT_UINT8, BASE_DEC, NULL, 0x0,
3154             NULL, HFILL }
3155         },
3156 
3157 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
3158  *
3159  * IPv6 specific address definitions
3160  */
3161         { &hf_eigrp_ipv6_nexthop,
3162           { "NextHop", "eigrp.ipv6.nexthop",
3163             FT_IPv6, BASE_NONE, NULL, 0x0,
3164             NULL, HFILL }
3165         },
3166 
3167         { &hf_eigrp_ipv6_prefixlen,
3168           { "Prefix Length", "eigrp.ipv6.prefixlen",
3169             FT_UINT8, BASE_DEC, NULL, 0x0,
3170             NULL, HFILL }
3171         },
3172 
3173 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
3174  *
3175  * IPX specific address definitions
3176  */
3177         { &hf_eigrp_ipx_nexthop_net,
3178           { "NextHop Net", "eigrp.ipx.nexthop_net",
3179             FT_IPXNET, BASE_NONE, NULL, 0x0,
3180             NULL, HFILL }
3181         },
3182         { &hf_eigrp_ipx_nexthop_host,
3183           { "NextHop Host", "eigrp.ipx.nexthop_host",
3184             FT_ETHER, BASE_NONE, NULL, 0x0,
3185             NULL, HFILL }
3186         },
3187         { &hf_eigrp_ipx_extdata_routerid,
3188           { "External RouterID", "eigrp.ipx.routerid",
3189             FT_ETHER, BASE_NONE, NULL, 0x0,
3190             "Router ID of redistributing router", HFILL }
3191         },
3192         { &hf_eigrp_ipx_dest,
3193           { "Destination", "eigrp.ipx.dest",
3194             FT_IPXNET, BASE_NONE, NULL, 0x0,
3195             NULL, HFILL }
3196         },
3197 
3198 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
3199  *
3200  * AppleTalk specific address definitions
3201  */
3202         { &hf_eigrp_atalk_routerid,
3203           { "AppleTalk Router ID", "eigrp.atalk.routerid",
3204             FT_UINT32, BASE_DEC, NULL, 0x0,
3205             NULL, HFILL }
3206         },
3207 
3208 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
3209  * Service Advertisement Framework definitions
3210  */
3211         { &hf_eigrp_saf_service,
3212           { "Service", "eigrp.saf.service",
3213             FT_UINT16, BASE_DEC, VALS(eigrp_saf_srv2string), 0x0,
3214             NULL, HFILL }
3215         },
3216         { &hf_eigrp_saf_subservice,
3217           { "Sub-Service", "eigrp.saf.subservice",
3218             FT_UINT16, BASE_DEC, NULL, 0x0,
3219             NULL, HFILL }
3220         },
3221         { &hf_eigrp_saf_guid,
3222           { "GUID", "eigrp.saf.guid",
3223             FT_GUID, BASE_NONE, NULL, 0x0,
3224             NULL, HFILL }
3225         },
3226         { &hf_eigrp_saf_data_type,
3227           { "Type", "eigrp.saf.data.type",
3228             FT_UINT16, BASE_HEX, VALS(eigrp_saf_type2string), 0x0,
3229             "SAF Message Data Type", HFILL }
3230         },
3231         { &hf_eigrp_saf_data_length,
3232           { "Length", "eigrp.saf.data.length",
3233             FT_UINT16, BASE_DEC, NULL, 0x0,
3234             NULL, HFILL }
3235         },
3236         { &hf_eigrp_saf_data_sequence,
3237           { "Sequence", "eigrp.saf.data.sequence",
3238             FT_UINT32, BASE_DEC, NULL, 0x0,
3239             NULL, HFILL }
3240         },
3241         { &hf_eigrp_saf_reachability_afi,
3242           { "AFI", "eigrp.saf.data.reachability.afi",
3243             FT_UINT16, BASE_DEC, VALS(eigrp_afi2string), 0x0,
3244             NULL, HFILL }
3245         },
3246         { &hf_eigrp_saf_reachability_port,
3247           { "Port", "eigrp.saf.data.reachability.port",
3248             FT_UINT16, BASE_DEC, NULL, 0x0,
3249             NULL, HFILL }
3250         },
3251         { &hf_eigrp_saf_reachability_protocol,
3252           { "Protocol", "eigrp.saf.data.reachability.protocol",
3253             FT_UINT16, BASE_DEC, NULL, 0x0,
3254             NULL, HFILL }
3255         },
3256         { &hf_eigrp_saf_reachability_addr_ipv4,
3257           { "IPv4 Addr", "eigrp.saf.data.reachability.addr_ipv4",
3258             FT_IPv4, BASE_NONE, NULL, 0x0,
3259             NULL, HFILL }
3260         },
3261         { &hf_eigrp_saf_reachability_addr_ipv6,
3262           { "IPv6 Addr", "eigrp.saf.data.reachability.addr_ipv6",
3263             FT_IPv6, BASE_NONE, NULL, 0x0,
3264             NULL, HFILL }
3265         },
3266         { &hf_eigrp_saf_reachability_addr_hex,
3267           { "Addr", "eigrp.saf.data.reachability.addr_hex",
3268             FT_BYTES, BASE_NONE, NULL, 0x0,
3269             NULL, HFILL }
3270         },
3271 
3272         /* misc field used in a couple places */
3273         { &hf_eigrp_nullpad,
3274           { "Nullpad", "eigrp.nullpad",
3275             FT_BYTES, BASE_NONE, NULL, 0x0,
3276             NULL, HFILL }
3277         },
3278 
3279       /* Generated from convert_proto_tree_add_text.pl */
3280       { &hf_eigrp_ipx_address, { "IPX Address", "eigrp.ipx_address", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3281       { &hf_eigrp_release, { "EIGRP Release", "eigrp.release_version", FT_UINT16, BASE_CUSTOM, CF_FUNC(eigrp_fmt_version), 0x0, NULL, HFILL }},
3282       { &hf_eigrp_tlv_version, { "EIGRP TLV version", "eigrp.tlv_version", FT_UINT16, BASE_CUSTOM, CF_FUNC(eigrp_fmt_version), 0x0, NULL, HFILL }},
3283       { &hf_eigrp_ipv4_destination, { "Destination", "eigrp.ipv4.destination", FT_IPv4, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3284       { &hf_eigrp_ipv6_destination, { "Destination", "eigrp.ipv6.destination", FT_IPv6, BASE_NONE, NULL, 0x0, NULL, HFILL }},
3285       { &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 }},
3286       { &hf_eigrp_nexthop_address, { "NextHop Address", "eigrp.nexthop_address", FT_UINT32, BASE_CUSTOM, CF_FUNC(eigrp_fmt_nexthop_address), 0x0, NULL, HFILL }},
3287       { &hf_eigrp_cable_range, { "Cable range", "eigrp.cable_range", FT_UINT32, BASE_CUSTOM, CF_FUNC(eigrp_fmt_cable_range), 0x0, NULL, HFILL }},
3288       { &hf_eigrp_metric_delay, { "Delay", "eigrp.metric.delay", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3289       { &hf_eigrp_metric_bandwidth, { "Bandwidth", "eigrp.metric.bandwidth", FT_UINT64, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3290       { &hf_eigrp_checksum, { "Checksum", "eigrp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3291       { &hf_eigrp_checksum_status, { "Checksum Status", "eigrp.checksum.status", FT_UINT8, BASE_NONE, VALS(proto_checksum_vals), 0x0, NULL, HFILL }},
3292       { &hf_eigrp_metric_comm_type, { "Type", "eigrp.metric.comm_type", FT_UINT16, BASE_DEC, VALS(eigrp_metric_comm_type_vals), 0x0, NULL, HFILL }},
3293       { &hf_eigrp_extcomm_eigrp_flag, { "FLAG", "eigrp.extcomm.flag", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3294       { &hf_eigrp_extcomm_eigrp_tag, { "TAG", "eigrp.extcomm.tag", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3295       { &hf_eigrp_extcomm_eigrp_res, { "RES", "eigrp.extcomm.res", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3296       { &hf_eigrp_extcomm_eigrp_rid, { "RID", "eigrp.extcomm.rid", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3297       { &hf_eigrp_extcomm_eigrp_as, { "AS", "eigrp.extcomm.as", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3298       { &hf_eigrp_extcomm_eigrp_sdly, { "SDLY", "eigrp.extcomm.sdly", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3299       { &hf_eigrp_extcomm_eigrp_rel, { "RID", "eigrp.extcomm.rel", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3300       { &hf_eigrp_extcomm_eigrp_hop, { "AS", "eigrp.extcomm.hop", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3301       { &hf_eigrp_extcomm_eigrp_sbw, { "SDLY", "eigrp.extcomm.sbw", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3302       { &hf_eigrp_extcomm_eigrp_load, { "LOAD", "eigrp.extcomm.load", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3303       { &hf_eigrp_extcomm_eigrp_mtu, { "MTU", "eigrp.extcomm.mtu", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3304       { &hf_eigrp_extcomm_eigrp_xas, { "xAS", "eigrp.extcomm.xas", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3305       { &hf_eigrp_extcomm_eigrp_xrid, { "xRID", "eigrp.extcomm.xrid", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3306       { &hf_eigrp_extcomm_eigrp_xproto, { "xProto", "eigrp.extcomm.xproto", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
3307       { &hf_eigrp_extcomm_eigrp_xmetric, { "xMETRIC", "eigrp.extcomm.xmetric", FT_UINT32, BASE_DEC, NULL, 0x0, NULL, HFILL }},
3308     };
3309 
3310     /* Setup protocol subtree array */
3311     static gint *ett[] = {
3312         /* header flag */
3313         &ett_eigrp,
3314         &ett_eigrp_flags,
3315 
3316         /* tlv specific */
3317         &ett_eigrp_tlv,
3318         &ett_eigrp_tlv_metric,
3319         &ett_eigrp_tlv_attr,
3320         &ett_eigrp_tlv_extdata,
3321 
3322         &ett_eigrp_tidlist,
3323         &ett_eigrp_stub_flags,
3324         &ett_eigrp_saf_reachability,
3325 
3326         /* metric tlv specific */
3327         &ett_eigrp_metric_flags,
3328         &ett_eigrp_extdata_flags,
3329 
3330         &ett_metric_comm_type
3331     };
3332 
3333     static ei_register_info ei[] = {
3334         { &ei_eigrp_peer_termination, { "eigrp.peer_termination", PI_RESPONSE_CODE, PI_NOTE, "Peer Termination", EXPFILL }},
3335         { &ei_eigrp_auth_len, { "eigrp.auth.length.invalid", PI_MALFORMED, PI_WARN, "Invalid auth len", EXPFILL }},
3336         { &ei_eigrp_auth_type, { "eigrp.auth.type.invalid", PI_PROTOCOL, PI_WARN, "Invalid auth type", EXPFILL }},
3337         { &ei_eigrp_seq_addrlen, { "eigrp.seq.addrlen.invalid", PI_MALFORMED, PI_ERROR, "Invalid address length", EXPFILL }},
3338         { &ei_eigrp_peer_termination_graceful, { "eigrp.peer_termination_graceful", PI_RESPONSE_CODE, PI_NOTE, "Peer Termination (Graceful Shutdown)", EXPFILL }},
3339         { &ei_eigrp_prefixlen, { "eigrp.prefixlen.invalid", PI_MALFORMED, PI_WARN, "Invalid prefix length", EXPFILL }},
3340         { &ei_eigrp_unreachable, { "eigrp.unreachable", PI_RESPONSE_CODE, PI_NOTE, "Unreachable", EXPFILL }},
3341         { &ei_eigrp_tlv_type, { "eigrp.tlv_type.unknown", PI_PROTOCOL, PI_WARN, "Unknown TLV", EXPFILL }},
3342         { &ei_eigrp_afi, { "eigrp.afi.unknown", PI_PROTOCOL, PI_WARN, "Unknown AFI", EXPFILL }},
3343         { &ei_eigrp_checksum_bad, { "eigrp.checksum.bad", PI_CHECKSUM, PI_WARN, "Bad Checksum", EXPFILL }},
3344         { &ei_eigrp_tlv_len, { "eigrp.tlv.len.invalid", PI_MALFORMED, PI_ERROR, "Corrupt TLV (Length field less than 4)", EXPFILL }},
3345         { &ei_eigrp_tlv_trunc, { "eigrp.tlv.truncated", PI_MALFORMED, PI_ERROR, "Corrupt TLV (Truncated prematurely)", EXPFILL }},
3346     };
3347 
3348     expert_module_t* expert_eigrp;
3349 
3350     /* Register the protocol name and description */
3351     proto_eigrp = proto_register_protocol(
3352         "Enhanced Interior Gateway Routing Protocol",   /* name         */
3353         "EIGRP",                                        /* short name   */
3354         "eigrp"                                         /* abbrev       */
3355         );
3356 
3357     /* Required function calls to register the header fields and subtrees used */
3358     proto_register_field_array(proto_eigrp, hf, array_length(hf));
3359     proto_register_subtree_array(ett, array_length(ett));
3360     expert_eigrp = expert_register_protocol(proto_eigrp);
3361     expert_register_field_array(expert_eigrp, ei, array_length(ei));
3362 }
3363 
3364 /**
3365  *@fn void proto_reg_handoff_eigrp(void)
3366  *
3367  * @usage
3368  * This exact format is required because a script is used to find these
3369  * routines and create the code that calls these routines.
3370  *
3371  * @par
3372  * If this dissector uses sub-dissector registration add a registration routine.
3373  *
3374  * This form of the reg_handoff function is used if if you perform registration
3375  * functions which are dependent upon prefs.  If this function is registered as
3376  * a prefs callback (see prefs_register_protocol above) this function is also
3377  * called by preferences whenever "Apply" is pressed;
3378  *
3379  * In that case, it should accommodate being called more than once.
3380  */
3381 void
proto_reg_handoff_eigrp(void)3382 proto_reg_handoff_eigrp(void)
3383 {
3384     dissector_handle_t eigrp_handle;
3385 
3386     ipxsap_handle = find_dissector_add_dependency("ipxsap", proto_eigrp);
3387     media_type_table = find_dissector_table("media_type");
3388 
3389     eigrp_handle = create_dissector_handle(dissect_eigrp, proto_eigrp);
3390 
3391     dissector_add_uint("ip.proto", IP_PROTO_EIGRP, eigrp_handle);
3392     dissector_add_uint("ddp.type", DDP_EIGRP, eigrp_handle);
3393     dissector_add_uint("ipx.socket", IPX_SOCKET_EIGRP, eigrp_handle);
3394 }
3395 
3396 /*
3397  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
3398  *
3399  * Local variables:
3400  * c-basic-offset: 4
3401  * tab-width: 8
3402  * indent-tabs-mode: nil
3403  * End:
3404  *
3405  * vi: set shiftwidth=4 tabstop=8 expandtab:
3406  * :indentSize=4:tabSize=8:noTabs=true:
3407  */
3408