From Peter Paluch via bug #5877: EIGRP dissector enhancement for RS/EOT
[obnox/wireshark/wip.git] / epan / dissectors / packet-eigrp.c
1 /* packet-eigrp.c
2  * Routines for EIGRP Stub Routing, Authentication and IPv6 TLV dissection
3  *
4  * Copyright 2009, Jochen Bartl <jochen.bartl@gmail.com>
5  *
6  * Routines for EIGRP dissection
7  * Copyright 2000, Paul Ionescu <paul@acorp.ro>
8  *
9  * $Id$
10  *
11  * Wireshark - Network traffic analyzer
12  * By Gerald Combs <gerald@wireshark.org>
13  * Copyright 1998 Gerald Combs
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
28  */
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #include <glib.h>
35 #include <epan/packet.h>
36 #include <epan/addr_resolv.h>
37
38 #include <epan/atalk-utils.h>
39 #include <epan/addr_and_mask.h>
40 #include <epan/ipproto.h>
41 #include "packet-ipx.h"
42 #include <epan/expert.h>
43
44 /*
45  * See
46  *
47  *      http://www.rhyshaden.com/eigrp.htm
48  */
49
50 #define EIGRP_UPDATE    0x01
51 #define EIGRP_REQUEST   0x02
52 #define EIGRP_QUERY     0x03
53 #define EIGRP_REPLY     0x04
54 #define EIGRP_HELLO     0x05
55 #define EIGRP_SAP       0x06
56 #define EIGRP_SIA_QUERY 0x0a
57 #define EIGRP_SIA_REPLY 0x0b
58 #define EIGRP_HI        0x20  /* This value is for my own need to make a difference between Hello and Ack */
59 #define EIGRP_ACK       0x40  /* This value is for my own need to make a difference between Hello and Ack */
60
61 #define TLV_PAR         0x0001
62 #define TLV_AUTH        0x0002
63 #define TLV_SEQ         0x0003
64 #define TLV_SV          0x0004
65 #define TLV_NMS         0x0005
66 #define TLV_STUB        0x0006
67 #define TLV_IP_INT      0x0102
68 #define TLV_IP_EXT      0x0103
69 #define TLV_AT_INT      0x0202
70 #define TLV_AT_EXT      0x0203
71 #define TLV_AT_CBL      0x0204
72 #define TLV_IPX_INT     0x0302
73 #define TLV_IPX_EXT     0x0303
74 #define TLV_IP6_INT     0x0402
75 #define TLV_IP6_EXT     0x0403
76
77 #define EIGRP_FLAGS_INIT        0x00000001
78 #define EIGRP_FLAGS_CONDRECV    0x00000002
79 #define EIGRP_FLAGS_RESTART     0x00000004
80 #define EIGRP_FLAGS_ENDOFTABLE  0x00000008
81
82 #define EIGRP_STUB_FLAGS_CONNECTED      0x0001
83 #define EIGRP_STUB_FLAGS_STATIC         0x0002
84 #define EIGRP_STUB_FLAGS_SUMMARY        0x0004
85 #define EIGRP_STUB_FLAGS_RECVONLY       0x0008
86 #define EIGRP_STUB_FLAGS_REDIST         0x0010
87 #define EIGRP_STUB_FLAGS_LEAKMAP        0x0020
88
89 #define EIGRP_IP_EXT_FLAGS_EXT          0x01
90 #define EIGRP_IP_EXT_FLAGS_DEFAULT      0x02
91
92 #define EIGRP_HEADER_LENGTH             20
93
94 static gint proto_eigrp = -1;
95
96 static gint hf_eigrp_version = -1;
97 static gint hf_eigrp_opcode = -1;
98 static gint hf_eigrp_checksum = -1;
99
100 static gint hf_eigrp_flags = -1; /* Flags Tree */
101 static gint hf_eigrp_flags_init = -1;
102 static gint hf_eigrp_flags_condrecv = -1;
103 static gint hf_eigrp_flags_restart = -1;
104 static gint hf_eigrp_flags_eot = -1;
105
106 static gint hf_eigrp_sequence = -1;
107 static gint hf_eigrp_acknowledge = -1;
108 static gint hf_eigrp_as = -1;
109 static gint hf_eigrp_tlv = -1;
110 static gint hf_eigrp_tlv_size = -1;
111
112 /* EIGRP Parameters TLV */
113 static gint hf_eigrp_par_k1 = -1;
114 static gint hf_eigrp_par_k2 = -1;
115 static gint hf_eigrp_par_k3 = -1;
116 static gint hf_eigrp_par_k4 = -1;
117 static gint hf_eigrp_par_k5 = -1;
118 static gint hf_eigrp_par_reserved = -1;
119 static gint hf_eigrp_par_holdtime = -1;
120
121 /* Authentication TLV */
122 static gint hf_eigrp_auth_type = -1;
123 static gint hf_eigrp_auth_keysize = -1;
124 static gint hf_eigrp_auth_keyid = -1;
125 static gint hf_eigrp_auth_nullpad = -1;
126 static gint hf_eigrp_auth_data = -1;
127
128 /* Sequence TLV */
129 static gint hf_eigrp_seq_addrlen = -1;
130 static gint hf_eigrp_seq_ipaddr = -1;
131 static gint hf_eigrp_seq_ip6addr = -1;
132
133 /* Software Version TLV */
134 static gint hf_eigrp_sv_ios = -1;
135 static gint hf_eigrp_sv_eigrp = -1;
136
137 /* Next multicast sequence TLV */
138 static gint hf_eigrp_nms = -1;
139
140 /* Stub routing TLV */
141 static gint hf_eigrp_stub_flags = -1; /* Stub Flags Tree */
142 static gint hf_eigrp_stub_flags_connected = -1;
143 static gint hf_eigrp_stub_flags_static = -1;
144 static gint hf_eigrp_stub_flags_summary = -1;
145 static gint hf_eigrp_stub_flags_recvonly = -1;
146 static gint hf_eigrp_stub_flags_redist = -1;
147 static gint hf_eigrp_stub_flags_leakmap = -1;
148
149 /* IP internal route TLV */
150 static gint hf_eigrp_ip_int_nexthop = -1;
151 static gint hf_eigrp_ip_int_delay = -1;
152 static gint hf_eigrp_ip_int_bandwidth = -1;
153 static gint hf_eigrp_ip_int_mtu = -1;
154 static gint hf_eigrp_ip_int_hopcount = -1;
155 static gint hf_eigrp_ip_int_reliability = -1;
156 static gint hf_eigrp_ip_int_load = -1;
157 static gint hf_eigrp_ip_int_reserved = -1;
158 static gint hf_eigrp_ip_int_prefixlen = -1;
159 static gint hf_eigrp_ip_int_dst = -1;
160
161 /* IP external route TLV */
162 static gint hf_eigrp_ip_ext_nexthop = -1;
163 static gint hf_eigrp_ip_ext_origrouter = -1;
164 static gint hf_eigrp_ip_ext_as = -1;
165 static gint hf_eigrp_ip_ext_tag = -1;
166 static gint hf_eigrp_ip_ext_metric = -1;
167 static gint hf_eigrp_ip_ext_reserved = -1;
168 static gint hf_eigrp_ip_ext_proto = -1;
169
170 static gint hf_eigrp_ip_ext_flags = -1; /* IP external route Flags Tree */
171 static gint hf_eigrp_ip_ext_flags_ext = -1;
172 static gint hf_eigrp_ip_ext_flags_default = -1;
173
174 static gint hf_eigrp_ip_ext_delay = -1;
175 static gint hf_eigrp_ip_ext_bandwidth = -1;
176 static gint hf_eigrp_ip_ext_mtu = -1;
177 static gint hf_eigrp_ip_ext_hopcount = -1;
178 static gint hf_eigrp_ip_ext_reliability = -1;
179 static gint hf_eigrp_ip_ext_load = -1;
180 static gint hf_eigrp_ip_ext_reserved2 = -1;
181 static gint hf_eigrp_ip_ext_prefixlen = -1;
182
183 /* IPX internal route TLV */
184 static gint hf_eigrp_ipx_int_nexthop_addr = -1;
185 static gint hf_eigrp_ipx_int_nexthop_id = -1;
186 static gint hf_eigrp_ipx_int_delay = -1;
187 static gint hf_eigrp_ipx_int_bandwidth = -1;
188 static gint hf_eigrp_ipx_int_mtu = -1;
189 static gint hf_eigrp_ipx_int_hopcount = -1;
190 static gint hf_eigrp_ipx_int_reliability = -1;
191 static gint hf_eigrp_ipx_int_load = -1;
192 static gint hf_eigrp_ipx_int_reserved = -1;
193 static gint hf_eigrp_ipx_int_dst = -1;
194
195 /* IPX external route TLV */
196 static gint hf_eigrp_ipx_ext_nexthop_addr = -1;
197 static gint hf_eigrp_ipx_ext_nexthop_id = -1;
198 static gint hf_eigrp_ipx_ext_origrouter = -1;
199 static gint hf_eigrp_ipx_ext_as = -1;
200 static gint hf_eigrp_ipx_ext_tag = -1;
201 static gint hf_eigrp_ipx_ext_proto = -1;
202 static gint hf_eigrp_ipx_ext_reserved = -1;
203 static gint hf_eigrp_ipx_ext_metric = -1;
204 static gint hf_eigrp_ipx_ext_extdelay = -1;
205 static gint hf_eigrp_ipx_ext_delay = -1;
206 static gint hf_eigrp_ipx_ext_bandwidth = -1;
207 static gint hf_eigrp_ipx_ext_mtu = -1;
208 static gint hf_eigrp_ipx_ext_hopcount = -1;
209 static gint hf_eigrp_ipx_ext_reliability = -1;
210 static gint hf_eigrp_ipx_ext_load = -1;
211 static gint hf_eigrp_ipx_ext_reserved2 = -1;
212 static gint hf_eigrp_ipx_ext_dst = -1;
213
214 /* AppleTalk cable configuration TLV */
215 static gint hf_eigrp_at_cbl_routerid = -1;
216
217 /* AppleTalk internal route TLV */
218 static gint hf_eigrp_at_int_delay = -1;
219 static gint hf_eigrp_at_int_bandwidth = -1;
220 static gint hf_eigrp_at_int_mtu = -1;
221 static gint hf_eigrp_at_int_hopcount = -1;
222 static gint hf_eigrp_at_int_reliability = -1;
223 static gint hf_eigrp_at_int_load = -1;
224 static gint hf_eigrp_at_int_reserved = -1;
225
226 /* AppleTalk external route TLV */
227 static gint hf_eigrp_at_ext_origrouter = -1;
228 static gint hf_eigrp_at_ext_as = -1;
229 static gint hf_eigrp_at_ext_tag = -1;
230 static gint hf_eigrp_at_ext_proto = -1;
231
232 static gint hf_eigrp_at_ext_flags = -1; /* AppleTalk external route Flags Tree */
233 static gint hf_eigrp_at_ext_flags_ext = -1;
234 static gint hf_eigrp_at_ext_flags_default = -1;
235
236 static gint hf_eigrp_at_ext_metric = -1;
237
238 static gint hf_eigrp_at_ext_delay = -1;
239 static gint hf_eigrp_at_ext_bandwidth = -1;
240 static gint hf_eigrp_at_ext_mtu = -1;
241 static gint hf_eigrp_at_ext_hopcount = -1;
242 static gint hf_eigrp_at_ext_reliability = -1;
243 static gint hf_eigrp_at_ext_load = -1;
244 static gint hf_eigrp_at_ext_reserved = -1;
245
246 /* IPv6 internal route TLV */
247 static gint hf_eigrp_ip6_int_nexthop = -1;
248 static gint hf_eigrp_ip6_int_delay = -1;
249 static gint hf_eigrp_ip6_int_bandwidth = -1;
250 static gint hf_eigrp_ip6_int_mtu = -1;
251 static gint hf_eigrp_ip6_int_hopcount = -1;
252 static gint hf_eigrp_ip6_int_reliability = -1;
253 static gint hf_eigrp_ip6_int_load = -1;
254 static gint hf_eigrp_ip6_int_reserved = -1;
255 static gint hf_eigrp_ip6_int_prefixlen = -1;
256
257 /* IPv6 external route TLV */
258 static gint hf_eigrp_ip6_ext_nexthop = -1;
259 static gint hf_eigrp_ip6_ext_origrouter = -1;
260 static gint hf_eigrp_ip6_ext_as = -1;
261 static gint hf_eigrp_ip6_ext_tag = -1;
262 static gint hf_eigrp_ip6_ext_metric = -1;
263 static gint hf_eigrp_ip6_ext_reserved = -1;
264 static gint hf_eigrp_ip6_ext_proto = -1;
265
266 static gint hf_eigrp_ip6_ext_flags = -1; /* IPv6 external route Flags Tree */
267 static gint hf_eigrp_ip6_ext_flags_ext = -1;
268 static gint hf_eigrp_ip6_ext_flags_default = -1;
269
270 static gint hf_eigrp_ip6_ext_delay = -1;
271 static gint hf_eigrp_ip6_ext_bandwidth = -1;
272 static gint hf_eigrp_ip6_ext_mtu = -1;
273 static gint hf_eigrp_ip6_ext_hopcount = -1;
274 static gint hf_eigrp_ip6_ext_reliability = -1;
275 static gint hf_eigrp_ip6_ext_load = -1;
276 static gint hf_eigrp_ip6_ext_reserved2 = -1;
277 static gint hf_eigrp_ip6_ext_prefixlen = -1;
278
279 static gint ett_eigrp = -1;
280 static gint ett_eigrp_flags = -1;
281 static gint ett_tlv = -1;
282 static gint ett_eigrp_stub_flags = -1;
283 static gint ett_eigrp_ip_ext_flags = -1;
284 static gint ett_eigrp_ip6_ext_flags = -1;
285 static gint ett_eigrp_at_ext_flags = -1;
286
287 static dissector_handle_t ipxsap_handle;
288
289
290 static const value_string eigrp_opcode_vals[] = {
291         { EIGRP_HELLO,          "Hello/Ack" },
292         { EIGRP_UPDATE,         "Update" },
293         { EIGRP_REPLY,          "Reply" },
294         { EIGRP_QUERY,          "Query" },
295         { EIGRP_REQUEST,        "Request" },
296         { EIGRP_SAP,            "IPX/SAP Update" },
297         { EIGRP_SIA_QUERY,      "SIA-Query" },
298         { EIGRP_SIA_REPLY,      "SIA-Reply" },
299         { EIGRP_HI,             "Hello" },
300         { EIGRP_ACK,            "Acknowledge" },
301         { 0,                            NULL }
302 };
303
304 static const value_string eigrp_tlv_vals[] = {
305         { TLV_PAR,     "EIGRP Parameters"},
306         { TLV_AUTH,    "Authentication data"},
307         { TLV_SEQ ,    "Sequence"},
308         { TLV_SV,      "Software Version"},
309         { TLV_NMS   ,  "Next multicast sequence"},
310         { TLV_STUB  ,  "Stub routing"},
311         { TLV_IP_INT,  "IP internal route"},
312         { TLV_IP_EXT,  "IP external route"},
313         { TLV_AT_INT,  "AppleTalk internal route"},
314         { TLV_AT_EXT,  "AppleTalk external route"},
315         { TLV_AT_CBL,  "AppleTalk cable configuration"},
316         { TLV_IPX_INT, "IPX internal route"},
317         { TLV_IPX_EXT, "IPX external route"},
318         { TLV_IP6_INT,  "IPv6 internal route"},
319         { TLV_IP6_EXT,  "IPv6 external route"},
320         { 0,            NULL}
321 };
322
323 static const value_string eigrp_pid_vals[] = {
324         { 1,    "IGRP"},
325         { 2,    "EIGRP"},
326         { 3,    "Static Route"},
327         { 4,    "RIP"},
328         { 5,    "Hello"},
329         { 6,    "OSPF"},
330         { 7,    "IS-IS"},
331         { 8,    "EGP"},
332         { 9,    "BGP"},
333         { 10,   "IDRP"},
334         { 11,   "Connected link"},
335         { 0,    NULL}
336 };
337
338 static const value_string eigrp_auth_type_vals[] = {
339         { 2,    "MD5"},
340         { 0,    NULL}
341 };
342
343 static void dissect_eigrp_par(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti);
344 static void dissect_eigrp_auth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
345 static void dissect_eigrp_seq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
346 static void dissect_eigrp_sv(tvbuff_t *tvb, proto_tree *tree, proto_item *ti);
347 static void dissect_eigrp_nms(tvbuff_t *tvb, proto_tree *tree, proto_item *ti);
348 static void dissect_eigrp_stub(tvbuff_t *tvb, proto_tree *tree);
349
350 static void dissect_eigrp_ip_int(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti);
351 static void dissect_eigrp_ip_ext(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti);
352
353 static void dissect_eigrp_ipx_int(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti);
354 static void dissect_eigrp_ipx_ext(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti);
355
356 static void dissect_eigrp_at_cbl(tvbuff_t *tvb, proto_tree *tree, proto_item *ti);
357 static void dissect_eigrp_at_int(tvbuff_t *tvb, proto_tree *tree, proto_item *ti);
358 static void dissect_eigrp_at_ext(tvbuff_t *tvb, proto_tree *tree, proto_item *ti);
359
360 static void dissect_eigrp_ip6_int(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti);
361 static void dissect_eigrp_ip6_ext(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti);
362
363
364 static void dissect_eigrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
365
366         proto_tree *eigrp_tree = NULL, *tlv_tree, *eigrp_flags_tree;
367         proto_item *ti;
368
369         guint opcode, opcode_tmp;
370         guint16 tlv;
371         guint32 ack, size, offset = EIGRP_HEADER_LENGTH;
372
373         col_set_str(pinfo->cinfo, COL_PROTOCOL, "EIGRP");
374         col_clear(pinfo->cinfo, COL_INFO);
375
376         opcode_tmp = opcode = tvb_get_guint8(tvb, 1);
377         ack = tvb_get_ntohl(tvb, 12);
378         if (opcode == EIGRP_HELLO) { if (ack == 0) opcode_tmp = EIGRP_HI; else opcode_tmp = EIGRP_ACK; }
379
380         col_add_str(pinfo->cinfo, COL_INFO,
381                         val_to_str(opcode_tmp, eigrp_opcode_vals, "Unknown (0x%04x)"));
382
383         if (tree) {
384
385                 ti = proto_tree_add_protocol_format(tree, proto_eigrp, tvb, 0, -1, "Cisco EIGRP");
386
387                 eigrp_tree = proto_item_add_subtree(ti, ett_eigrp);
388
389                 proto_tree_add_item(eigrp_tree, hf_eigrp_version, tvb, 0, 1, FALSE);
390                 proto_tree_add_item(eigrp_tree, hf_eigrp_opcode, tvb, 1, 1, FALSE);
391                 proto_tree_add_item(eigrp_tree, hf_eigrp_checksum, tvb, 2, 2, FALSE);
392 /* Decode the EIGRP Flags Field */
393
394                 ti = proto_tree_add_item(eigrp_tree, hf_eigrp_flags, tvb, 4, 4, FALSE);
395                 eigrp_flags_tree = proto_item_add_subtree(ti, ett_eigrp_flags);
396
397                 proto_tree_add_item(eigrp_flags_tree, hf_eigrp_flags_init, tvb, 4, 4, FALSE);
398                 proto_tree_add_item(eigrp_flags_tree, hf_eigrp_flags_condrecv, tvb, 4, 4, FALSE);
399                 proto_tree_add_item(eigrp_flags_tree, hf_eigrp_flags_restart, tvb, 4, 4, FALSE);
400                 proto_tree_add_item(eigrp_flags_tree, hf_eigrp_flags_eot, tvb, 4, 4, FALSE);
401
402 /* End Decode the EIGRP Flags Field */
403
404                 proto_tree_add_item(eigrp_tree, hf_eigrp_sequence, tvb, 8, 4, FALSE);
405                 proto_tree_add_item(eigrp_tree, hf_eigrp_acknowledge, tvb, 12, 4, FALSE);
406                 proto_tree_add_item(eigrp_tree, hf_eigrp_as, tvb, 16, 4, FALSE);
407         }
408
409         if (opcode == EIGRP_SAP) {
410                 call_dissector(ipxsap_handle, tvb_new_subset(tvb, EIGRP_HEADER_LENGTH, -1, -1), pinfo, eigrp_tree);
411                 return;
412         }
413
414         if (tree) {
415                 while (tvb_reported_length_remaining(tvb, offset) > 0) {
416
417                         tlv = tvb_get_ntohs(tvb, offset);
418                         size =  tvb_get_ntohs(tvb, offset + 2);
419
420                         if (size == 0) {
421                                 ti = proto_tree_add_text(eigrp_tree, tvb, offset, -1, "Unknown data (maybe authentication)");
422                                 expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR, "Unknown data (maybe authentication)");
423                                 return;
424                         }
425
426                         ti = proto_tree_add_text(eigrp_tree, tvb, offset,size,
427                                 "%s", val_to_str(tlv, eigrp_tlv_vals, "Unknown (0x%04x)"));
428
429                         tlv_tree = proto_item_add_subtree(ti, ett_tlv);
430                         proto_tree_add_item(tlv_tree, hf_eigrp_tlv, tvb, offset, 2, FALSE);
431                         proto_tree_add_item(tlv_tree, hf_eigrp_tlv_size, tvb, offset + 2, 2, FALSE);
432
433
434                         switch (tlv) {
435                                 case TLV_PAR:
436                                         dissect_eigrp_par(tvb_new_subset(tvb, offset + 4, size - 4, -1), pinfo, tlv_tree, ti);
437                                         break;
438                                 case TLV_AUTH:
439                                         dissect_eigrp_auth(tvb_new_subset(tvb, offset + 4, size - 4, -1), pinfo, tlv_tree);
440                                         break;
441                                 case TLV_SEQ:
442                                         dissect_eigrp_seq(tvb_new_subset(tvb, offset + 4, size - 4, -1), pinfo, tlv_tree);
443                                         break;
444                                 case TLV_SV:
445                                         dissect_eigrp_sv(tvb_new_subset(tvb, offset + 4, size - 4, -1), tlv_tree, ti);
446                                         break;
447                                 case TLV_NMS:
448                                         dissect_eigrp_nms(tvb_new_subset(tvb, offset + 4, size - 4, -1), tlv_tree, ti);
449                                         break;
450                                 case TLV_STUB:
451                                         dissect_eigrp_stub(tvb_new_subset(tvb, offset + 4, size - 4, -1), tlv_tree);
452                                         break;
453
454                                 case TLV_IP_INT:
455                                         dissect_eigrp_ip_int(tvb_new_subset(tvb, offset + 4, size - 4, -1), pinfo, tlv_tree, ti);
456                                         break;
457                                 case TLV_IP_EXT:
458                                         dissect_eigrp_ip_ext(tvb_new_subset(tvb, offset + 4, size - 4, -1), pinfo, tlv_tree, ti);
459                                         break;
460
461                                 case TLV_IPX_INT:
462                                         dissect_eigrp_ipx_int(tvb_new_subset(tvb, offset + 4, size - 4, -1), pinfo, tlv_tree, ti);
463                                         break;
464                                 case TLV_IPX_EXT:
465                                         dissect_eigrp_ipx_ext(tvb_new_subset(tvb, offset + 4, size - 4, -1), pinfo, tlv_tree, ti);
466                                         break;
467
468                                 case TLV_AT_CBL:
469                                         dissect_eigrp_at_cbl(tvb_new_subset(tvb, offset + 4, size - 4, -1), tlv_tree, ti);
470                                         break;
471                                 case TLV_AT_INT:
472                                         dissect_eigrp_at_int(tvb_new_subset(tvb, offset + 4, size - 4, -1), tlv_tree, ti);
473                                         break;
474                                 case TLV_AT_EXT:
475                                         dissect_eigrp_at_ext(tvb_new_subset(tvb, offset + 4, size - 4, -1), tlv_tree, ti);
476                                         break;
477
478                                 case TLV_IP6_INT:
479                                         dissect_eigrp_ip6_int(tvb_new_subset(tvb, offset + 4, size - 4, -1), pinfo, tlv_tree, ti);
480                                         break;
481                                 case TLV_IP6_EXT:
482                                         dissect_eigrp_ip6_ext(tvb_new_subset(tvb, offset + 4, size - 4, -1), pinfo, tlv_tree, ti);
483                                         break;
484                                 default:
485                                         expert_add_info_format(pinfo, ti, PI_UNDECODED, PI_WARN, "Unknown TLV (0x%04x)", tlv);
486                         }
487
488                         offset += size;
489                 }
490         }
491 }
492
493
494
495 static void dissect_eigrp_par(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti) {
496
497         int offset = 0;
498         guint8 k1, k2, k3, k4, k5;
499
500         k1 = tvb_get_guint8(tvb, 1);
501         proto_tree_add_item(tree, hf_eigrp_par_k1, tvb, offset, 1, FALSE);
502         offset += 1;
503         k2 = tvb_get_guint8(tvb, 1);
504         proto_tree_add_item(tree, hf_eigrp_par_k2, tvb, offset, 1, FALSE);
505         offset += 1;
506         k3 = tvb_get_guint8(tvb, 1);
507         proto_tree_add_item(tree, hf_eigrp_par_k3, tvb, offset, 1, FALSE);
508         offset += 1;
509         k4 = tvb_get_guint8(tvb, 1);
510         proto_tree_add_item(tree, hf_eigrp_par_k4, tvb, offset, 1, FALSE);
511         offset += 1;
512         k5 = tvb_get_guint8(tvb, 1);
513         proto_tree_add_item(tree, hf_eigrp_par_k5, tvb, offset, 1, FALSE);
514         offset += 1;
515         proto_tree_add_item(tree, hf_eigrp_par_reserved, tvb, offset, 1, FALSE);
516         offset += 1;
517         proto_tree_add_item(tree, hf_eigrp_par_holdtime, tvb, offset, 2, FALSE);
518
519         if (k1 == 255 && k2 == 255 && k3 == 255 && k4 == 255 && k5 == 255) {
520                 proto_item_append_text(ti, ": Goodbye Message");
521                 expert_add_info_format(pinfo, ti, PI_RESPONSE_CODE, PI_NOTE, "Goodbye Message (Graceful Shutdown)");
522         }
523 }
524
525 static void dissect_eigrp_auth(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
526
527         proto_item *ti_keysize;
528         int offset = 0;
529         guint16 keysize;
530
531         keysize = tvb_get_ntohs(tvb, 2);
532
533         proto_tree_add_item(tree, hf_eigrp_auth_type, tvb, offset, 2, FALSE);
534         offset += 2;
535         ti_keysize = proto_tree_add_item(tree, hf_eigrp_auth_keysize, tvb, offset, 2, FALSE);
536         offset += 2;
537         proto_tree_add_item(tree, hf_eigrp_auth_keyid, tvb, offset, 4, FALSE);
538         offset += 4;
539         proto_tree_add_item(tree, hf_eigrp_auth_nullpad, tvb, offset, 12, FALSE);
540         offset += 12;
541
542         switch (keysize) {
543                 /* MD5 */
544                 case 16:
545                         proto_tree_add_item(tree, hf_eigrp_auth_data, tvb, offset, keysize, FALSE);
546                         break;
547                 default:
548                         expert_add_info_format(pinfo, ti_keysize, PI_UNDECODED, PI_WARN,
549                                         "Invalid key size %u: Only a value of 16 for MD5 is supported", keysize);
550         }
551 }
552
553 static void dissect_eigrp_seq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
554
555         proto_item *ti_addrlen;
556         int offset = 0;
557         guint8 addr_len;
558
559         addr_len = tvb_get_guint8(tvb, 0);
560
561         ti_addrlen = proto_tree_add_item(tree, hf_eigrp_seq_addrlen, tvb, offset, 1, FALSE);
562         offset += 1;
563
564         switch (addr_len) {
565                 /* IPv4 */
566                 case 4:
567                         proto_tree_add_item(tree, hf_eigrp_seq_ipaddr, tvb, offset, addr_len, FALSE);
568                         break;
569                 /* IPX */
570                 case 10:
571                         proto_tree_add_text(tree, tvb, offset, addr_len, "IPX Address = %08x.%04x.%04x.%04x",
572                                         tvb_get_ntohl(tvb, 1), tvb_get_ntohs(tvb, 5),
573                                         tvb_get_ntohs(tvb, 7), tvb_get_ntohs(tvb, 9));
574                         break;
575                 /* IPv6 */
576                 case 16:
577                         proto_tree_add_item(tree, hf_eigrp_seq_ip6addr, tvb, offset, addr_len, FALSE);
578                         break;
579                 default:
580                         expert_add_info_format(pinfo, ti_addrlen, PI_MALFORMED, PI_ERROR, "Invalid address length");
581         }
582 }
583
584 static void dissect_eigrp_sv(tvbuff_t *tvb, proto_tree *tree, proto_item *ti) {
585
586         int offset = 0;
587         guint8 ios_rel_major, ios_rel_minor;
588         guint8 eigrp_rel_major, eigrp_rel_minor;
589
590         ios_rel_major = tvb_get_guint8(tvb, 0);
591         ios_rel_minor = tvb_get_guint8(tvb, 1);
592         proto_tree_add_text(tree, tvb, offset, 2, "IOS release version: %u.%u",
593                             ios_rel_major, ios_rel_minor);
594         offset += 2;
595         proto_item_append_text(ti, ": IOS=%u.%u", ios_rel_major, ios_rel_minor);
596
597         eigrp_rel_major = tvb_get_guint8(tvb, 2);
598         eigrp_rel_minor = tvb_get_guint8(tvb, 3);
599         proto_tree_add_text(tree,tvb,offset, 2, "EIGRP release version: %u.%u",
600                             eigrp_rel_major, eigrp_rel_minor);
601         proto_item_append_text(ti, ", EIGRP=%u.%u",
602                                eigrp_rel_major, eigrp_rel_minor);
603 }
604
605 static void dissect_eigrp_nms(tvbuff_t *tvb, proto_tree *tree, proto_item *ti) {
606
607         proto_tree_add_item(tree, hf_eigrp_nms, tvb, 0, 4, FALSE);
608         proto_item_append_text(ti, ": %u", tvb_get_ntohl(tvb, 0));
609 }
610
611 static void dissect_eigrp_stub(tvbuff_t *tvb, proto_tree *tree) {
612
613         proto_tree *eigrp_stub_flags_tree;
614         proto_item *ti;
615
616         ti = proto_tree_add_item(tree, hf_eigrp_stub_flags, tvb, 0, 2, FALSE);
617         eigrp_stub_flags_tree = proto_item_add_subtree(ti, ett_eigrp_stub_flags);
618
619         proto_tree_add_item(eigrp_stub_flags_tree, hf_eigrp_stub_flags_connected, tvb, 0, 2, FALSE);
620         proto_tree_add_item(eigrp_stub_flags_tree, hf_eigrp_stub_flags_static, tvb, 0, 2, FALSE);
621         proto_tree_add_item(eigrp_stub_flags_tree, hf_eigrp_stub_flags_summary, tvb, 0, 2, FALSE);
622         proto_tree_add_item(eigrp_stub_flags_tree, hf_eigrp_stub_flags_recvonly, tvb, 0, 2, FALSE);
623         proto_tree_add_item(eigrp_stub_flags_tree, hf_eigrp_stub_flags_redist, tvb, 0, 2, FALSE);
624         proto_tree_add_item(eigrp_stub_flags_tree, hf_eigrp_stub_flags_leakmap, tvb, 0, 2, FALSE);
625 }
626
627 static void dissect_eigrp_ip_int(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti) {
628
629         guint8 ip_addr[4], length;
630         int addr_len, offset = 0;
631         proto_item *ti_prefixlen, *ti_dst;
632
633         tvb_memcpy(tvb, ip_addr, 0, 4);
634
635         proto_tree_add_item(tree, hf_eigrp_ip_int_nexthop, tvb, offset, 4, FALSE);
636         offset += 4;
637         proto_tree_add_item(tree, hf_eigrp_ip_int_delay, tvb, offset, 4, FALSE);
638         offset += 4;
639         proto_tree_add_item(tree, hf_eigrp_ip_int_bandwidth, tvb, offset, 4, FALSE);
640         offset += 4;
641         proto_tree_add_item(tree, hf_eigrp_ip_int_mtu, tvb, offset, 3, FALSE);
642         offset += 3;
643         proto_tree_add_item(tree, hf_eigrp_ip_int_hopcount, tvb, offset, 1, FALSE);
644         offset += 1;
645         proto_tree_add_item(tree, hf_eigrp_ip_int_reliability, tvb, offset, 1, FALSE);
646         offset += 1;
647         proto_tree_add_item(tree, hf_eigrp_ip_int_load, tvb, offset, 1, FALSE);
648         offset += 1;
649         proto_tree_add_item(tree, hf_eigrp_ip_int_reserved, tvb, offset, 2, FALSE);
650         offset += 2;
651
652         for (offset = 20; tvb_length_remaining(tvb, offset) > 0; offset += (1 + addr_len)) {
653                 length = tvb_get_guint8(tvb, offset);
654                 addr_len = ipv4_addr_and_mask(tvb, offset + 1, ip_addr, length);
655
656                 if (addr_len < 0) {
657                         ti_prefixlen = proto_tree_add_item(tree, hf_eigrp_ip_int_prefixlen, tvb, offset, 1, FALSE);
658                         expert_add_info_format(pinfo, ti_prefixlen, PI_UNDECODED, PI_WARN,
659                                         "Invalid prefix length %u, must be <= 32", length);
660                         addr_len = 4; /* assure we can exit the loop */
661                 } else {
662                         proto_tree_add_item(tree, hf_eigrp_ip_int_prefixlen, tvb, offset, 1, FALSE);
663                         offset += 1;
664                         ti_dst = proto_tree_add_text(tree, tvb, offset, addr_len, "Destination: %s", ip_to_str(ip_addr));
665                         proto_item_append_text (ti,"  %c   %s/%u%s", offset == 21 ? '=':',',
666                                 ip_to_str(ip_addr), length, ((tvb_get_ntohl(tvb, 4 )== 0xffffffff) ? " - Destination unreachable":""));
667                         if (tvb_get_ntohl(tvb, 4) == 0xffffffff) {
668                                 expert_add_info_format(pinfo, ti_dst, PI_RESPONSE_CODE, PI_NOTE, "Destination unreachable");
669                         }
670                 }
671         }
672 }
673
674 static void dissect_eigrp_ip_ext(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti) {
675
676         guint8 ip_addr[4], length;
677         int addr_len, offset = 0;
678         proto_tree *eigrp_ip_ext_flags_tree;
679         proto_item *eigrp_ip_ext_ti, *ti_prefixlen, *ti_dst;
680
681         eigrp_ip_ext_ti = ti;
682
683         tvb_memcpy(tvb, ip_addr, 0, 4);
684         proto_tree_add_item(tree, hf_eigrp_ip_ext_nexthop, tvb, offset, 4, FALSE);
685         offset += 4;
686         tvb_memcpy(tvb,ip_addr, 4, 4);
687         proto_tree_add_item(tree, hf_eigrp_ip_ext_origrouter, tvb, offset, 4, FALSE);
688         offset += 4;
689         proto_tree_add_item(tree, hf_eigrp_ip_ext_as, tvb, offset, 4, FALSE);
690         offset += 4;
691         proto_tree_add_item(tree, hf_eigrp_ip_ext_tag, tvb, offset, 4, FALSE);
692         offset += 4;
693         proto_tree_add_item(tree, hf_eigrp_ip_ext_metric, tvb, offset, 4, FALSE);
694         offset += 4;
695         proto_tree_add_item(tree, hf_eigrp_ip_ext_reserved, tvb, offset, 2, FALSE);
696         offset += 2;
697         proto_tree_add_item(tree, hf_eigrp_ip_ext_proto, tvb, offset, 1, FALSE);
698         offset += 1;
699
700 /* Decode the IP external route Flags Field */
701         ti = proto_tree_add_item(tree, hf_eigrp_ip_ext_flags, tvb, offset, 1, FALSE);
702         eigrp_ip_ext_flags_tree = proto_item_add_subtree(ti, ett_eigrp_ip_ext_flags);
703
704         proto_tree_add_item(eigrp_ip_ext_flags_tree, hf_eigrp_ip_ext_flags_ext, tvb, offset, 1, FALSE);
705         proto_tree_add_item(eigrp_ip_ext_flags_tree, hf_eigrp_ip_ext_flags_default, tvb, offset, 1, FALSE);
706         offset += 1;
707 /* End Decode the IP external route Flags Field */
708
709         proto_tree_add_item(tree, hf_eigrp_ip_ext_delay, tvb, offset, 4, FALSE);
710         offset += 4;
711         proto_tree_add_item(tree, hf_eigrp_ip_ext_bandwidth, tvb, offset, 4, FALSE);
712         offset += 4;
713         proto_tree_add_item(tree, hf_eigrp_ip_ext_mtu, tvb, offset, 3, FALSE);
714         offset += 3;
715         proto_tree_add_item(tree, hf_eigrp_ip_ext_hopcount, tvb, offset, 1, FALSE);
716         offset += 1;
717         proto_tree_add_item(tree, hf_eigrp_ip_ext_reliability, tvb, offset, 1, FALSE);
718         offset += 1;
719         proto_tree_add_item(tree, hf_eigrp_ip_ext_load, tvb, offset, 1, FALSE);
720         offset += 1;
721         proto_tree_add_item(tree, hf_eigrp_ip_ext_reserved2, tvb, offset, 2, FALSE);
722         offset += 2;
723
724         for (offset = 40; tvb_length_remaining(tvb, offset) > 0; offset += (1 + addr_len)) {
725                 length = tvb_get_guint8(tvb, offset);
726                 addr_len = ipv4_addr_and_mask(tvb, offset + 1, ip_addr, length);
727
728                 if (addr_len < 0) {
729                         ti_prefixlen = proto_tree_add_item(tree, hf_eigrp_ip_ext_prefixlen, tvb, offset, 1, FALSE);
730                         expert_add_info_format(pinfo, ti_prefixlen, PI_UNDECODED, PI_WARN,
731                                         "Invalid prefix length %u, must be <= 32", length);
732                         addr_len = 4; /* assure we can exit the loop */
733                 } else {
734                         proto_tree_add_item(tree, hf_eigrp_ip_ext_prefixlen, tvb, offset, 1, FALSE);
735                         offset += 1;
736                         ti_dst = proto_tree_add_text(tree, tvb, offset, addr_len, "Destination = %s", ip_to_str(ip_addr));
737                         proto_item_append_text(eigrp_ip_ext_ti, "  %c   %s/%u%s", offset == 41 ? '=':',',
738                                 ip_to_str(ip_addr), length, ((tvb_get_ntohl(tvb, 24) == 0xffffffff) ? " - Destination unreachable":""));
739                         if (tvb_get_ntohl(tvb, 24) == 0xffffffff) {
740                                 expert_add_info_format(pinfo, ti_dst, PI_RESPONSE_CODE, PI_NOTE, "Destination unreachable");
741                         }
742                 }
743         }
744 }
745
746
747
748 static void dissect_eigrp_ipx_int(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti) {
749
750         int offset = 0;
751         proto_item *ti_dst;
752
753         proto_tree_add_item(tree, hf_eigrp_ipx_int_nexthop_addr, tvb, offset, 4, FALSE);
754         offset += 4;
755         proto_tree_add_item(tree, hf_eigrp_ipx_int_nexthop_id, tvb, offset, 6, FALSE);
756         offset += 6;
757         proto_tree_add_item(tree, hf_eigrp_ipx_int_delay, tvb, offset, 4, FALSE);
758         offset += 4;
759         proto_tree_add_item(tree, hf_eigrp_ipx_int_bandwidth, tvb, offset, 4, FALSE);
760         offset += 4;
761         proto_tree_add_item(tree, hf_eigrp_ipx_int_mtu, tvb, offset, 3, FALSE);
762         offset += 3;
763         proto_tree_add_item(tree, hf_eigrp_ipx_int_hopcount, tvb, offset, 1, FALSE);
764         offset += 1;
765         proto_tree_add_item(tree, hf_eigrp_ipx_int_reliability, tvb, offset, 1, FALSE);
766         offset += 1;
767         proto_tree_add_item(tree, hf_eigrp_ipx_int_load, tvb, offset, 1, FALSE);
768         offset += 1;
769         proto_tree_add_item(tree, hf_eigrp_ipx_int_reserved, tvb, offset, 2, FALSE);
770         offset += 2;
771         ti_dst = proto_tree_add_item(tree, hf_eigrp_ipx_int_dst, tvb, offset, 4, FALSE);
772         proto_item_append_text(ti, "  =   %08x%s", tvb_get_ntohl(tvb, 26), ((tvb_get_ntohl(tvb, 10) == 0xffffffff) ? " - Destination unreachable":""));
773         if (tvb_get_ntohl(tvb, 10) == 0xffffffff) {
774                 expert_add_info_format(pinfo, ti_dst, PI_RESPONSE_CODE, PI_NOTE, "Destination unreachable");
775         }
776 }
777
778 static void dissect_eigrp_ipx_ext(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti) {
779
780         int offset = 0;
781         proto_item *ti_dst;
782
783         proto_tree_add_item(tree, hf_eigrp_ipx_ext_nexthop_addr, tvb, offset, 4, FALSE);
784         offset += 4;
785         proto_tree_add_item(tree, hf_eigrp_ipx_ext_nexthop_id, tvb, offset, 6, FALSE);
786         offset += 6;
787         proto_tree_add_item(tree, hf_eigrp_ipx_ext_origrouter, tvb, offset, 6, FALSE);
788         offset += 6;
789         proto_tree_add_item(tree, hf_eigrp_ipx_ext_as, tvb, offset, 4, FALSE);
790         offset += 4;
791         proto_tree_add_item(tree, hf_eigrp_ipx_ext_tag, tvb, offset, 4, FALSE);
792         offset += 4;
793         proto_tree_add_item(tree, hf_eigrp_ipx_ext_proto, tvb, offset, 1, FALSE);
794         offset += 1;
795         proto_tree_add_item(tree, hf_eigrp_ipx_ext_reserved, tvb, offset, 1, FALSE);
796         offset += 1;
797         proto_tree_add_item(tree, hf_eigrp_ipx_ext_metric, tvb, offset, 2, FALSE);
798         offset += 2;
799         proto_tree_add_item(tree, hf_eigrp_ipx_ext_extdelay, tvb, offset, 2, FALSE);
800         offset += 2;
801
802         proto_tree_add_item(tree, hf_eigrp_ipx_ext_delay, tvb, offset, 4, FALSE);
803         offset += 4;
804         proto_tree_add_item(tree, hf_eigrp_ipx_ext_bandwidth, tvb, offset, 4, FALSE);
805         offset += 4;
806         proto_tree_add_item(tree, hf_eigrp_ipx_ext_mtu, tvb, offset, 3, FALSE);
807         offset += 3;
808         proto_tree_add_item(tree, hf_eigrp_ipx_ext_hopcount, tvb, offset, 1, FALSE);
809         offset += 1;
810         proto_tree_add_item(tree, hf_eigrp_ipx_ext_reliability, tvb, offset, 1, FALSE);
811         offset += 1;
812         proto_tree_add_item(tree, hf_eigrp_ipx_ext_load, tvb, offset, 1, FALSE);
813         offset += 1;
814         proto_tree_add_item(tree, hf_eigrp_ipx_ext_reserved2, tvb, offset, 2, FALSE);
815         offset += 2;
816         ti_dst = proto_tree_add_item(tree, hf_eigrp_ipx_ext_dst, tvb, offset, 4, FALSE);
817         proto_item_append_text(ti, "  =   %08x%s", tvb_get_ntohl(tvb, 46), ((tvb_get_ntohl(tvb, 30) == 0xffffffff) ? " - Destination unreachable":""));
818         if (tvb_get_ntohl(tvb, 30) == 0xffffffff) {
819                 expert_add_info_format(pinfo, ti_dst, PI_RESPONSE_CODE, PI_NOTE, "Destination unreachable");
820         }
821 }
822
823
824
825 static void dissect_eigrp_at_cbl(tvbuff_t *tvb, proto_tree *tree, proto_item *ti) {
826
827         proto_tree_add_text(tree, tvb, 0, 4, "AppleTalk Cable Range = %u-%u", tvb_get_ntohs(tvb, 0), tvb_get_ntohs(tvb, 2));
828         proto_tree_add_item(tree, hf_eigrp_at_cbl_routerid, tvb, 4, 4, FALSE);
829         proto_item_append_text(ti, ": Cable range= %u-%u, Router ID= %u", tvb_get_ntohs(tvb, 0), tvb_get_ntohs(tvb, 2), tvb_get_ntohl(tvb, 4));
830
831 }
832
833 static void dissect_eigrp_at_int(tvbuff_t *tvb, proto_tree *tree, proto_item *ti) {
834
835         int offset = 0;
836
837         proto_tree_add_text(tree, tvb, offset, 4, "Next Hop Address = %u.%u", tvb_get_ntohs(tvb, 0), tvb_get_ntohs(tvb, 2));
838         offset += 4;
839
840         proto_tree_add_item(tree, hf_eigrp_at_int_delay, tvb, offset, 4, FALSE);
841         offset += 4;
842         proto_tree_add_item(tree, hf_eigrp_at_int_bandwidth, tvb, offset, 4, FALSE);
843         offset += 4;
844         proto_tree_add_item(tree, hf_eigrp_at_int_mtu, tvb, offset, 3, FALSE);
845         offset += 3;
846         proto_tree_add_item(tree, hf_eigrp_at_int_hopcount, tvb, offset, 1, FALSE);
847         offset += 1;
848         proto_tree_add_item(tree, hf_eigrp_at_int_reliability, tvb, offset, 1, FALSE);
849         offset += 1;
850         proto_tree_add_item(tree, hf_eigrp_at_int_load, tvb, offset, 1, FALSE);
851         offset += 1;
852         proto_tree_add_item(tree, hf_eigrp_at_int_reserved, tvb, offset, 2, FALSE);
853         offset += 2;
854         proto_tree_add_text(tree,tvb,offset,4,"Cable range = %u-%u",tvb_get_ntohs(tvb,20),tvb_get_ntohs(tvb,22));
855
856         proto_item_append_text(ti, ": %u-%u", tvb_get_ntohs(tvb, 20), tvb_get_ntohs(tvb, 22));
857 }
858
859 static void dissect_eigrp_at_ext(tvbuff_t *tvb, proto_tree *tree, proto_item *ti) {
860
861         int offset = 0;
862         proto_tree *eigrp_at_ext_flags_tree;
863
864         proto_tree_add_text(tree, tvb, offset, 4, "Next Hop Address = %u.%u", tvb_get_ntohs(tvb, 0), tvb_get_ntohs(tvb, 2));
865         offset += 4;
866         proto_tree_add_item(tree, hf_eigrp_at_ext_origrouter, tvb, offset, 4, FALSE);
867         offset += 4;
868         proto_tree_add_item(tree, hf_eigrp_at_ext_as, tvb, offset, 4, FALSE);
869         offset += 4;
870         proto_tree_add_item(tree, hf_eigrp_at_ext_tag, tvb, offset, 4, FALSE);
871         offset += 4;
872         proto_tree_add_item(tree, hf_eigrp_at_ext_proto, tvb, offset, 1, FALSE);
873         offset += 1;
874
875 /* Decode the AppleTalk external route Flags Field */
876         ti = proto_tree_add_item(tree, hf_eigrp_at_ext_flags, tvb, offset, 1, FALSE);
877         eigrp_at_ext_flags_tree = proto_item_add_subtree(ti, ett_eigrp_at_ext_flags);
878
879         proto_tree_add_item(eigrp_at_ext_flags_tree, hf_eigrp_at_ext_flags_ext, tvb, offset, 1, FALSE);
880         proto_tree_add_item(eigrp_at_ext_flags_tree, hf_eigrp_at_ext_flags_default, tvb, offset, 1, FALSE);
881         offset += 1;
882 /* End Decode the AppleTalk external route Flags Field */
883
884         proto_tree_add_item(tree, hf_eigrp_at_ext_metric, tvb, offset, 2, FALSE);
885         offset += 2;
886
887         proto_tree_add_item(tree, hf_eigrp_at_ext_delay, tvb, offset, 4, FALSE);
888         offset += 4;
889         proto_tree_add_item(tree, hf_eigrp_at_ext_bandwidth, tvb, offset, 4, FALSE);
890         offset += 4;
891         proto_tree_add_item(tree, hf_eigrp_at_ext_mtu, tvb, offset, 3, FALSE);
892         offset += 3;
893         proto_tree_add_item(tree, hf_eigrp_at_ext_hopcount, tvb, offset, 1, FALSE);
894         offset += 1;
895         proto_tree_add_item(tree, hf_eigrp_at_ext_reliability, tvb, offset, 1, FALSE);
896         offset += 1;
897         proto_tree_add_item(tree, hf_eigrp_at_ext_load, tvb, offset, 1, FALSE);
898         offset += 1;
899         proto_tree_add_item(tree, hf_eigrp_at_ext_reserved, tvb, offset, 2, FALSE);
900         offset += 2;
901         proto_tree_add_text(tree, tvb, offset, 4, "Cable range = %u-%u", tvb_get_ntohs(tvb, 36), tvb_get_ntohs(tvb, 38));
902
903         proto_item_append_text(ti, ": %u-%u", tvb_get_ntohs(tvb, 36), tvb_get_ntohs(tvb, 38));
904 }
905
906 static void dissect_eigrp_ip6_int(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti) {
907
908         guint8 length;
909         int addr_len, offset = 0;
910         struct e_in6_addr addr;
911         proto_item *ti_prefixlen, *ti_dst;
912
913         proto_tree_add_item(tree, hf_eigrp_ip6_int_nexthop, tvb, offset, 16, FALSE);
914         offset += 16;
915         proto_tree_add_item(tree, hf_eigrp_ip6_int_delay, tvb, offset, 4, FALSE);
916         offset += 4;
917         proto_tree_add_item(tree, hf_eigrp_ip6_int_bandwidth, tvb, offset, 4, FALSE);
918         offset += 4;
919         proto_tree_add_item(tree, hf_eigrp_ip6_int_mtu, tvb, offset, 3, FALSE);
920         offset += 3;
921         proto_tree_add_item(tree, hf_eigrp_ip6_int_hopcount, tvb, offset, 1, FALSE);
922         offset += 1;
923         proto_tree_add_item(tree, hf_eigrp_ip6_int_reliability, tvb, offset, 1, FALSE);
924         offset += 1;
925         proto_tree_add_item(tree, hf_eigrp_ip6_int_load, tvb, offset, 1, FALSE);
926         offset += 1;
927         proto_tree_add_item(tree, hf_eigrp_ip6_int_reserved, tvb, offset, 2, FALSE);
928         offset += 2;
929
930         for (offset = 32; tvb_length_remaining(tvb, offset) > 0; offset += (1 + addr_len)) {
931                 length = tvb_get_guint8(tvb, offset);
932                 addr_len = ipv6_addr_and_mask(tvb, offset + 1, &addr, length);
933
934                 if (addr_len < 0) {
935                         ti_prefixlen = proto_tree_add_item(tree, hf_eigrp_ip6_int_prefixlen, tvb, offset, 1, FALSE);
936                         expert_add_info_format(pinfo, ti_prefixlen, PI_UNDECODED, PI_WARN,
937                                         "Invalid prefix length %u, must be <= 128", length);
938                         addr_len = 16; /* assure we can exit the loop */
939                 } else {
940                         proto_tree_add_item(tree, hf_eigrp_ip6_int_prefixlen, tvb, offset, 1, FALSE);
941                         offset += 1;
942
943                         if ((length < 128) && (length % 8 == 0)) {
944                                 addr_len++;
945                         }
946
947                         ti_dst = proto_tree_add_text(tree, tvb, offset, addr_len, "Destination: %s", ip6_to_str(&addr));
948                         proto_item_append_text(ti, "  %c   %s/%u%s", offset == 33 ? '=':',',
949                                 ip6_to_str(&addr), length, ((tvb_get_ntohl(tvb, 16) == 0xffffffff) ? " - Destination unreachable":""));
950                         if (tvb_get_ntohl(tvb, 16) == 0xffffffff) {
951                                 expert_add_info_format(pinfo, ti_dst, PI_RESPONSE_CODE, PI_NOTE, "Destination unreachable");
952                         }
953                 }
954         }
955 }
956
957 static void dissect_eigrp_ip6_ext(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti) {
958
959         guint8 length;
960         int addr_len, offset = 0;
961         struct e_in6_addr addr;
962         proto_tree *eigrp_ip6_ext_flags_tree;
963         proto_item *eigrp_ip6_ext_ti, *ti_prefixlen, *ti_dst;
964
965         eigrp_ip6_ext_ti = ti;
966
967         proto_tree_add_item(tree, hf_eigrp_ip6_ext_nexthop, tvb, offset, 16, FALSE);
968         offset += 16;
969         proto_tree_add_item(tree, hf_eigrp_ip6_ext_origrouter, tvb, offset, 4, FALSE);
970         offset += 4;
971         proto_tree_add_item(tree, hf_eigrp_ip6_ext_as, tvb, offset, 4, FALSE);
972         offset += 4;
973         proto_tree_add_item(tree, hf_eigrp_ip6_ext_tag, tvb, offset, 4, FALSE);
974         offset += 4;
975         proto_tree_add_item(tree, hf_eigrp_ip6_ext_metric, tvb, offset, 4, FALSE);
976         offset += 4;
977         proto_tree_add_item(tree, hf_eigrp_ip6_ext_reserved, tvb, offset, 2, FALSE);
978         offset += 2;
979         proto_tree_add_item(tree, hf_eigrp_ip6_ext_proto, tvb, offset, 1, FALSE);
980         offset += 1;
981
982 /* Decode the IPv6 external route Flags Field */
983         ti = proto_tree_add_item(tree, hf_eigrp_ip6_ext_flags, tvb, offset, 1, FALSE);
984         eigrp_ip6_ext_flags_tree = proto_item_add_subtree(ti, ett_eigrp_ip6_ext_flags);
985
986         proto_tree_add_item(eigrp_ip6_ext_flags_tree, hf_eigrp_ip6_ext_flags_ext, tvb, offset, 1, FALSE);
987         proto_tree_add_item(eigrp_ip6_ext_flags_tree, hf_eigrp_ip6_ext_flags_default, tvb, offset, 1, FALSE);
988         offset += 1;
989 /* End Decode the IPv6 external route Flags Field */
990
991         proto_tree_add_item(tree, hf_eigrp_ip6_ext_delay, tvb, offset, 4, FALSE);
992         offset += 4;
993         proto_tree_add_item(tree, hf_eigrp_ip6_ext_bandwidth, tvb, offset, 4, FALSE);
994         offset += 4;
995         proto_tree_add_item(tree, hf_eigrp_ip6_ext_mtu, tvb, offset, 3, FALSE);
996         offset += 3;
997         proto_tree_add_item(tree, hf_eigrp_ip6_ext_hopcount, tvb, offset, 1, FALSE);
998         offset += 1;
999         proto_tree_add_item(tree, hf_eigrp_ip6_ext_reliability, tvb, offset, 1, FALSE);
1000         offset += 1;
1001         proto_tree_add_item(tree, hf_eigrp_ip6_ext_load, tvb, offset, 1, FALSE);
1002         offset += 1;
1003         proto_tree_add_item(tree, hf_eigrp_ip6_ext_reserved2, tvb, offset, 2, FALSE);
1004         offset += 2;
1005
1006         for (offset = 52; tvb_length_remaining(tvb, offset) > 0; offset += (1 + addr_len))
1007         {
1008                 length = tvb_get_guint8(tvb, offset);
1009                 addr_len = ipv6_addr_and_mask(tvb, offset + 1, &addr, length);
1010
1011                 if (addr_len < 0) {
1012                         ti_prefixlen = proto_tree_add_item(tree, hf_eigrp_ip6_ext_prefixlen, tvb, offset, 1, FALSE);
1013                         expert_add_info_format(pinfo, ti_prefixlen, PI_UNDECODED, PI_WARN,
1014                                         "Invalid prefix length %u, must be <= 128", length);
1015                         addr_len = 16; /* assure we can exit the loop */
1016                 } else {
1017                         proto_tree_add_item(tree, hf_eigrp_ip6_ext_prefixlen, tvb, offset, 1, FALSE);
1018                         offset += 1;
1019
1020                         if ((length < 128) && (length % 8 == 0)) {
1021                                 addr_len++;
1022                         }
1023
1024                         ti_dst = proto_tree_add_text(tree, tvb, offset, addr_len, "Destination: %s", ip6_to_str(&addr));
1025                         proto_item_append_text(eigrp_ip6_ext_ti, "  %c   %s/%u%s", offset == 53 ? '=':',',
1026                                 ip6_to_str(&addr), length, ((tvb_get_ntohl(tvb, 36) == 0xffffffff) ? " - Destination unreachable":""));
1027                         if (tvb_get_ntohl(tvb, 36) == 0xffffffff) {
1028                                 expert_add_info_format(pinfo, ti_dst, PI_RESPONSE_CODE, PI_NOTE, "Destination unreachable");
1029                         }
1030                 }
1031         }
1032 }
1033
1034
1035 void proto_register_eigrp(void) {
1036
1037         static hf_register_info hf[] = {
1038                 { &hf_eigrp_version,
1039                   { "Version", "eigrp.version",
1040                     FT_UINT8, BASE_DEC, NULL, 0x0,
1041                     NULL, HFILL }
1042                 },
1043                 { &hf_eigrp_opcode,
1044                   { "Opcode", "eigrp.opcode",
1045                     FT_UINT8, BASE_DEC, VALS(eigrp_opcode_vals), 0x0,
1046                     "Opcode number", HFILL }
1047                 },
1048                 { &hf_eigrp_checksum,
1049                   { "Checksum", "eigrp.checksum",
1050                     FT_UINT16, BASE_HEX, NULL, 0x0,
1051                     NULL, HFILL }
1052                 },
1053                 { &hf_eigrp_flags,
1054                   { "Flags", "eigrp.flags",
1055                     FT_UINT32, BASE_HEX, NULL, 0x0,
1056                     NULL, HFILL }
1057                 },
1058                 { &hf_eigrp_flags_init,
1059                   { "Init", "eigrp.flags.init",
1060                     FT_BOOLEAN, 32, NULL, EIGRP_FLAGS_INIT,
1061                     NULL, HFILL }
1062                 },
1063                 { &hf_eigrp_flags_condrecv,
1064                   { "Conditional Receive", "eigrp.flags.condrecv",
1065                     FT_BOOLEAN, 32, NULL, EIGRP_FLAGS_CONDRECV,
1066                     NULL, HFILL }
1067                 },
1068                 { &hf_eigrp_flags_restart,
1069                   { "Restart", "eigrp.flags.restart",
1070                     FT_BOOLEAN, 32, NULL, EIGRP_FLAGS_RESTART,
1071                     NULL, HFILL },
1072                 },
1073                 { &hf_eigrp_flags_eot,
1074                   { "End Of Table", "eigrp.flags.eot",
1075                     FT_BOOLEAN, 32, NULL, EIGRP_FLAGS_ENDOFTABLE,
1076                     NULL, HFILL }
1077                 },
1078                 { &hf_eigrp_sequence,
1079                   { "Sequence", "eigrp.seq",
1080                     FT_UINT32, BASE_DEC, NULL, 0x0,
1081                     NULL, HFILL }
1082                 },
1083                 { &hf_eigrp_acknowledge,
1084                   { "Acknowledge", "eigrp.ack",
1085                     FT_UINT32, BASE_DEC, NULL, 0x0,
1086                     NULL, HFILL }
1087                 },
1088                 { &hf_eigrp_as,
1089                   { "Autonomous System", "eigrp.as",
1090                     FT_UINT16, BASE_DEC, NULL, 0x0,
1091                     "Autonomous System number", HFILL }
1092                 },
1093                 { &hf_eigrp_tlv,
1094                   { "Type",           "eigrp.tlv",
1095                     FT_UINT16, BASE_DEC, VALS(eigrp_tlv_vals), 0x0,
1096                     "Type/Length/Value", HFILL }
1097                 },
1098                 { &hf_eigrp_tlv_size,
1099                   { "Size", "eigrp.tlv.size",
1100                     FT_UINT16, BASE_DEC, NULL, 0x0,
1101                     "TLV size", HFILL }
1102                 },
1103 /* EIGRP Parameters TLV */
1104                 { &hf_eigrp_par_k1,
1105                   { "K1", "eigrp.par.k1",
1106                     FT_UINT8, BASE_DEC, NULL, 0x0,
1107                     NULL, HFILL }
1108                 },
1109                 { &hf_eigrp_par_k2,
1110                   { "K2", "eigrp.par.k2",
1111                     FT_UINT8, BASE_DEC, NULL, 0x0,
1112                     NULL, HFILL }
1113                 },
1114                 { &hf_eigrp_par_k3,
1115                   { "K3", "eigrp.par.k3",
1116                     FT_UINT8, BASE_DEC, NULL, 0x0,
1117                     NULL, HFILL }
1118                 },
1119                 { &hf_eigrp_par_k4,
1120                   { "K4", "eigrp.par.k4",
1121                     FT_UINT8, BASE_DEC, NULL, 0x0,
1122                     NULL, HFILL }
1123                 },
1124                 { &hf_eigrp_par_k5,
1125                   { "K5", "eigrp.par.k5",
1126                     FT_UINT8, BASE_DEC, NULL, 0x0,
1127                     NULL, HFILL }
1128                 },
1129                 { &hf_eigrp_par_reserved,
1130                   { "Reserved", "eigrp.par.reserved",
1131                     FT_UINT8, BASE_DEC, NULL, 0x0,
1132                     NULL, HFILL }
1133                 },
1134                 { &hf_eigrp_par_holdtime,
1135                   { "Hold Time", "eigrp.par.holdtime",
1136                     FT_UINT16, BASE_DEC, NULL, 0x0,
1137                     NULL, HFILL }
1138                 },
1139 /* Authentication TLV */
1140                 { &hf_eigrp_auth_type,
1141                   { "Authentication Type", "eigrp.auth.type",
1142                     FT_UINT16, BASE_DEC, VALS(eigrp_auth_type_vals), 0x0,
1143                     NULL, HFILL }
1144                 },
1145                 { &hf_eigrp_auth_keysize,
1146                   { "Key size", "eigrp.auth.keysize",
1147                     FT_UINT16, BASE_DEC, NULL, 0x0,
1148                     NULL, HFILL }
1149                 },
1150                 { &hf_eigrp_auth_keyid,
1151                   { "Key ID", "eigrp.auth.keyid",
1152                     FT_UINT32, BASE_DEC, NULL, 0x0,
1153                     NULL, HFILL }
1154                 },
1155                 { &hf_eigrp_auth_nullpad,
1156                   { "Nullpad", "eigrp.auth.nullapd",
1157                     FT_STRING, BASE_NONE, NULL, 0x0,
1158                     NULL, HFILL }
1159                 },
1160                 { &hf_eigrp_auth_data,
1161                   { "Data", "eigrp.auth.data",
1162                     FT_STRING, BASE_NONE, NULL, 0x0,
1163                     NULL, HFILL }
1164                 },
1165 /* Sequence TLV */
1166                 { &hf_eigrp_seq_addrlen,
1167                   { "Address length", "eigrp.seq.addrlen",
1168                     FT_UINT8, BASE_DEC, NULL, 0x0,
1169                     NULL, HFILL }
1170                 },
1171                 { &hf_eigrp_seq_ipaddr,
1172                   { "IP Address", "eigrp.seq.ipaddr",
1173                     FT_IPv4, BASE_NONE, NULL, 0x0,
1174                     NULL, HFILL }
1175                 },
1176                 { &hf_eigrp_seq_ip6addr,
1177                   { "IPv6 Address", "eigrp.seq.ip6addr",
1178                     FT_IPv6, BASE_NONE, NULL, 0x0,
1179                     NULL, HFILL }
1180                 },
1181 /* Software Version TLV */
1182                 { &hf_eigrp_sv_ios,
1183                   { "IOS release version", "eigrp.sv.ios",
1184                     FT_STRING, BASE_NONE, NULL, 0x0,
1185                     NULL, HFILL }
1186                 },
1187                 { &hf_eigrp_sv_eigrp,
1188                   { "EIGRP release version", "eigrp.sv.eigrp",
1189                     FT_STRING, BASE_NONE, NULL, 0x0,
1190                     NULL, HFILL }
1191                 },
1192 /* Next multicast sequence TLV */
1193                 { &hf_eigrp_nms,
1194                   { "Next Multicast Sequence", "eigrp.nms",
1195                     FT_UINT32, BASE_DEC, NULL, 0x0,
1196                     NULL, HFILL }
1197                 },
1198 /* Stub routing TLV */
1199                 { &hf_eigrp_stub_flags,
1200                   { "Stub Flags", "eigrp.stub_flags",
1201                     FT_UINT16, BASE_HEX, NULL, 0x0,
1202                     NULL, HFILL }
1203                 },
1204                 { &hf_eigrp_stub_flags_connected,
1205                   { "Connected", "eigrp.stub_flags.connected",
1206                     FT_BOOLEAN, 16, NULL, EIGRP_STUB_FLAGS_CONNECTED,
1207                     NULL, HFILL }
1208                 },
1209                 { &hf_eigrp_stub_flags_static,
1210                   { "Static", "eigrp.stub_flags.static",
1211                     FT_BOOLEAN, 16, NULL, EIGRP_STUB_FLAGS_STATIC,
1212                     NULL, HFILL }
1213                 },
1214                 { &hf_eigrp_stub_flags_summary,
1215                   { "Summary", "eigrp.stub_flags.summary",
1216                     FT_BOOLEAN, 16, NULL, EIGRP_STUB_FLAGS_SUMMARY,
1217                     NULL, HFILL }
1218                 },
1219                 { &hf_eigrp_stub_flags_recvonly,
1220                   { "Receive-Only", "eigrp.stub_flags.recvonly",
1221                     FT_BOOLEAN, 16, NULL, EIGRP_STUB_FLAGS_RECVONLY,
1222                     NULL, HFILL }
1223                 },
1224                 { &hf_eigrp_stub_flags_redist,
1225                   { "Redistributed", "eigrp.stub_flags.redist",
1226                     FT_BOOLEAN, 16, NULL, EIGRP_STUB_FLAGS_REDIST,
1227                     NULL, HFILL }
1228                 },
1229                 { &hf_eigrp_stub_flags_leakmap,
1230                   { "Leak-Map", "eigrp.stub_flags.leakmap",
1231                     FT_BOOLEAN, 16, NULL, EIGRP_STUB_FLAGS_LEAKMAP,
1232                     NULL, HFILL }
1233                 },
1234 /* IP internal route TLV */
1235                 { &hf_eigrp_ip_int_nexthop,
1236                   { "Next Hop", "eigrp.ip_int.nexthop",
1237                     FT_IPv4, BASE_NONE, NULL, 0x0,
1238                     NULL, HFILL }
1239                 },
1240                 { &hf_eigrp_ip_int_delay,
1241                   { "Delay", "eigrp.ip_int.delay",
1242                     FT_UINT32, BASE_DEC, NULL, 0x0,
1243                     NULL, HFILL }
1244                 },
1245                 { &hf_eigrp_ip_int_bandwidth,
1246                   { "Bandwidth", "eigrp.ip_int.bandwidth",
1247                     FT_UINT32, BASE_DEC, NULL, 0x0,
1248                     NULL, HFILL }
1249                 },
1250                 { &hf_eigrp_ip_int_mtu,
1251                   { "MTU", "eigrp.ip_int.mtu",
1252                     FT_UINT24, BASE_DEC, NULL, 0x0,
1253                     NULL, HFILL }
1254                 },
1255                 { &hf_eigrp_ip_int_hopcount,
1256                   { "Hop Count", "eigrp.ip_int.hopcount",
1257                     FT_UINT8, BASE_DEC, NULL, 0x0,
1258                     NULL, HFILL }
1259                 },
1260                 { &hf_eigrp_ip_int_reliability,
1261                   { "Reliability", "eigrp.ip_int.reliability",
1262                     FT_UINT8, BASE_DEC, NULL, 0x0,
1263                     NULL, HFILL }
1264                 },
1265                 { &hf_eigrp_ip_int_load,
1266                   { "Load", "eigrp.ip_int.load",
1267                     FT_UINT8, BASE_DEC, NULL, 0x0,
1268                     NULL, HFILL }
1269                 },
1270                 { &hf_eigrp_ip_int_reserved,
1271                   { "Reserved", "eigrp.ip_int.reserved",
1272                     FT_UINT16, BASE_DEC, NULL, 0x0,
1273                     NULL, HFILL }
1274                 },
1275                 { &hf_eigrp_ip_int_prefixlen,
1276                   { "Prefix Length", "eigrp.ip_int.prefixlen",
1277                     FT_UINT8, BASE_DEC, NULL, 0x0,
1278                     NULL, HFILL }
1279                 },
1280                 { &hf_eigrp_ip_int_dst,
1281                   { "Destination", "eigrp.ip_int.dst",
1282                     FT_STRING, BASE_NONE, NULL, 0x0,
1283                     NULL, HFILL }
1284                 },
1285 /* IP external route TLV */
1286                 { &hf_eigrp_ip_ext_nexthop,
1287                   { "Next Hop", "eigrp.ip_ext.nexthop",
1288                     FT_IPv4, BASE_NONE, NULL, 0x0,
1289                     NULL, HFILL }
1290                 },
1291                 { &hf_eigrp_ip_ext_origrouter,
1292                   { "Originating router", "eigrp.ip_ext.origrouter",
1293                     FT_IPv4, BASE_NONE, NULL, 0x0,
1294                     NULL, HFILL }
1295                 },
1296                 { &hf_eigrp_ip_ext_as,
1297                   { "Originating A.S.", "eigrp.ip_ext.as",
1298                     FT_UINT32, BASE_DEC, NULL, 0x0,
1299                     NULL, HFILL }
1300                 },
1301                 { &hf_eigrp_ip_ext_tag,
1302                   { "Arbitrary tag", "eigrp.ip_ext.tag",
1303                     FT_UINT32, BASE_DEC, NULL, 0x0,
1304                     NULL, HFILL }
1305                 },
1306                 { &hf_eigrp_ip_ext_metric,
1307                   { "External protocol metric", "eigrp.ip_ext.metric",
1308                     FT_UINT32, BASE_DEC, NULL, 0x0,
1309                     NULL, HFILL }
1310                 },
1311                 { &hf_eigrp_ip_ext_reserved,
1312                   { "Reserved", "eigrp.ip_ext.reserved",
1313                     FT_UINT16, BASE_DEC, NULL, 0x0,
1314                     NULL, HFILL }
1315                 },
1316                 { &hf_eigrp_ip_ext_proto,
1317                   { "External protocol ID", "eigrp.ip_ext.proto",
1318                     FT_UINT8, BASE_DEC, VALS(eigrp_pid_vals), 0x0,
1319                     NULL, HFILL }
1320                 },
1321                 { &hf_eigrp_ip_ext_flags,
1322                   { "Flags", "eigrp.ip_ext.flags",
1323                     FT_UINT8, BASE_HEX, NULL, 0x0,
1324                     NULL, HFILL }
1325                 },
1326                 { &hf_eigrp_ip_ext_flags_ext,
1327                   { "External Route", "eigrp.ip_ext.flags.ext",
1328                     FT_BOOLEAN, 8, NULL, EIGRP_IP_EXT_FLAGS_EXT,
1329                     NULL, HFILL }
1330                 },
1331                 { &hf_eigrp_ip_ext_flags_default,
1332                   { "Candidate Default Route", "eigrp.ip_ext.flags.default",
1333                     FT_BOOLEAN, 8, NULL, EIGRP_IP_EXT_FLAGS_DEFAULT,
1334                     NULL, HFILL }
1335                 },
1336                 { &hf_eigrp_ip_ext_delay,
1337                   { "Delay", "eigrp.ip_ext.delay",
1338                     FT_UINT32, BASE_DEC, NULL, 0x0,
1339                     NULL, HFILL }
1340                 },
1341                 { &hf_eigrp_ip_ext_bandwidth,
1342                   { "Bandwidth", "eigrp.ip_ext.bandwidth",
1343                     FT_UINT32, BASE_DEC, NULL, 0x0,
1344                     NULL, HFILL }
1345                 },
1346                 { &hf_eigrp_ip_ext_mtu,
1347                   { "MTU", "eigrp.ip_ext.mtu",
1348                     FT_UINT24, BASE_DEC, NULL, 0x0,
1349                     NULL, HFILL }
1350                 },
1351                 { &hf_eigrp_ip_ext_hopcount,
1352                   { "Hop Count", "eigrp.ip_ext.hopcount",
1353                     FT_UINT8, BASE_DEC, NULL, 0x0,
1354                     NULL, HFILL }
1355                 },
1356                 { &hf_eigrp_ip_ext_reliability,
1357                   { "Reliability", "eigrp.ip_ext.reliability",
1358                     FT_UINT8, BASE_DEC, NULL, 0x0,
1359                     NULL, HFILL }
1360                 },
1361                 { &hf_eigrp_ip_ext_load,
1362                   { "Load", "eigrp.ip_ext.load",
1363                     FT_UINT8, BASE_DEC, NULL, 0x0,
1364                     NULL, HFILL }
1365                 },
1366                 { &hf_eigrp_ip_ext_reserved2,
1367                   { "Reserved", "eigrp.ip_ext.reserved2",
1368                     FT_UINT16, BASE_DEC, NULL, 0x0,
1369                     NULL, HFILL }
1370                 },
1371                 { &hf_eigrp_ip_ext_prefixlen,
1372                   { "Prefix Length", "eigrp.ip_ext.prefixlen",
1373                     FT_UINT8, BASE_DEC, NULL, 0x0,
1374                     NULL, HFILL }
1375                 },
1376 /* IPX internal route TLV */
1377                 { &hf_eigrp_ipx_int_nexthop_addr,
1378                   { "Next Hop Address", "eigrp.ipx_int.nexthop_addr",
1379                     FT_IPXNET, BASE_NONE, NULL, 0x0,
1380                     NULL, HFILL }
1381                 },
1382                 { &hf_eigrp_ipx_int_nexthop_id,
1383                   { "Next Hop ID", "eigrp.ipx_int.nexthop_id",
1384                     FT_ETHER, BASE_NONE, NULL, 0x0,
1385                     NULL, HFILL }
1386                 },
1387                 { &hf_eigrp_ipx_int_delay,
1388                   { "Delay", "eigrp.ipx_int.delay",
1389                     FT_UINT32, BASE_DEC, NULL, 0x0,
1390                     NULL, HFILL }
1391                 },
1392                 { &hf_eigrp_ipx_int_bandwidth,
1393                   { "Bandwidth", "eigrp.ipx_int.bandwidth",
1394                     FT_UINT32, BASE_DEC, NULL, 0x0,
1395                     NULL, HFILL }
1396                 },
1397                 { &hf_eigrp_ipx_int_mtu,
1398                   { "MTU", "eigrp.ipx_int.mtu",
1399                     FT_UINT24, BASE_DEC, NULL, 0x0,
1400                     NULL, HFILL }
1401                 },
1402                 { &hf_eigrp_ipx_int_hopcount,
1403                   { "Hop Count", "eigrp.ipx_int.hopcount",
1404                     FT_UINT8, BASE_DEC, NULL, 0x0,
1405                     NULL, HFILL }
1406                 },
1407                 { &hf_eigrp_ipx_int_reliability,
1408                   { "Reliability", "eigrp.ipx_int.reliability",
1409                     FT_UINT8, BASE_DEC, NULL, 0x0,
1410                     NULL, HFILL }
1411                 },
1412                 { &hf_eigrp_ipx_int_load,
1413                   { "Load", "eigrp.ipx_int.load",
1414                     FT_UINT8, BASE_DEC, NULL, 0x0,
1415                     NULL, HFILL }
1416                 },
1417                 { &hf_eigrp_ipx_int_reserved,
1418                   { "Reserved", "eigrp.ipx_int.reserved",
1419                     FT_UINT16, BASE_DEC, NULL, 0x0,
1420                     NULL, HFILL }
1421                 },
1422                 { &hf_eigrp_ipx_int_dst,
1423                   { "Destination", "eigrp.ipx_int.dst",
1424                     FT_IPXNET, BASE_NONE, NULL, 0x0,
1425                     NULL, HFILL }
1426                 },
1427 /* IPX external route TLV */
1428                 { &hf_eigrp_ipx_ext_nexthop_addr,
1429                   { "Next Hop Address", "eigrp.ipx_ext.nexthop_addr",
1430                     FT_IPXNET, BASE_NONE, NULL, 0x0,
1431                     NULL, HFILL }
1432                 },
1433                 { &hf_eigrp_ipx_ext_nexthop_id,
1434                   { "Next Hop ID", "eigrp.ipx_ext.nexthop_id",
1435                     FT_ETHER, BASE_NONE, NULL, 0x0,
1436                     NULL, HFILL }
1437                 },
1438                 { &hf_eigrp_ipx_ext_origrouter,
1439                   { "Originating router", "eigrp.ipx_ext.origrouter",
1440                     FT_ETHER, BASE_NONE, NULL, 0x0,
1441                     NULL, HFILL }
1442                 },
1443                 { &hf_eigrp_ipx_ext_as,
1444                   { "Originating A.S.", "eigrp.ipx_ext.as",
1445                     FT_UINT32, BASE_DEC, NULL, 0x0,
1446                     NULL, HFILL }
1447                 },
1448                 { &hf_eigrp_ipx_ext_tag,
1449                   { "Arbitrary tag", "eigrp.ipx_ext.tag",
1450                     FT_UINT32, BASE_DEC, NULL, 0x0,
1451                     NULL, HFILL }
1452                 },
1453                 { &hf_eigrp_ipx_ext_proto,
1454                   { "External protocol ID", "eigrp.ipx_ext.proto",
1455                     FT_UINT8, BASE_DEC, VALS(eigrp_pid_vals), 0x0,
1456                     NULL, HFILL }
1457                 },
1458                 { &hf_eigrp_ipx_ext_reserved,
1459                   { "Reserved", "eigrp.ipx_ext.reserved",
1460                     FT_UINT8, BASE_DEC, NULL, 0x0,
1461                     NULL, HFILL }
1462                 },
1463                 { &hf_eigrp_ipx_ext_metric,
1464                   { "External protocol metric", "eigrp.ipx_ext.metric",
1465                     FT_UINT16, BASE_DEC, NULL, 0x0,
1466                     NULL, HFILL }
1467                 },
1468                 { &hf_eigrp_ipx_ext_extdelay,
1469                   { "External protocol delay", "eigrp.ipx_ext.extdelay",
1470                     FT_UINT16, BASE_DEC, NULL, 0x0,
1471                     NULL, HFILL }
1472                 },
1473                 { &hf_eigrp_ipx_ext_delay,
1474                   { "Delay", "eigrp.ipx_ext.delay",
1475                     FT_UINT32, BASE_DEC, NULL, 0x0,
1476                     NULL, HFILL }
1477                 },
1478                 { &hf_eigrp_ipx_ext_bandwidth,
1479                   { "Bandwidth", "eigrp.ipx_ext.bandwidth",
1480                     FT_UINT32, BASE_DEC, NULL, 0x0,
1481                     NULL, HFILL }
1482                 },
1483                 { &hf_eigrp_ipx_ext_mtu,
1484                   { "MTU", "eigrp.ipx_ext.mtu",
1485                     FT_UINT24, BASE_DEC, NULL, 0x0,
1486                     NULL, HFILL }
1487                 },
1488                 { &hf_eigrp_ipx_ext_hopcount,
1489                   { "Hop Count", "eigrp.ipx_ext.hopcount",
1490                     FT_UINT8, BASE_DEC, NULL, 0x0,
1491                     NULL, HFILL }
1492                 },
1493                 { &hf_eigrp_ipx_ext_reliability,
1494                   { "Reliability", "eigrp.ipx_ext.reliability",
1495                     FT_UINT8, BASE_DEC, NULL, 0x0,
1496                     NULL, HFILL }
1497                 },
1498                 { &hf_eigrp_ipx_ext_load,
1499                   { "Load", "eigrp.ipx_ext.load",
1500                     FT_UINT8, BASE_DEC, NULL, 0x0,
1501                     NULL, HFILL }
1502                 },
1503                 { &hf_eigrp_ipx_ext_reserved2,
1504                   { "Reserved", "eigrp.ipx_ext.reserved2",
1505                     FT_UINT16, BASE_DEC, NULL, 0x0,
1506                     NULL, HFILL }
1507                 },
1508                 { &hf_eigrp_ipx_ext_dst,
1509                   { "Destination", "eigrp.ipx_ext.dst",
1510                     FT_IPXNET, BASE_NONE, NULL, 0x0,
1511                     NULL, HFILL }
1512                 },
1513 /* AppleTalk cable configuration TLV */
1514                 { &hf_eigrp_at_cbl_routerid,
1515                   { "AppleTalk Router ID", "eigrp.at_cbl.routerid",
1516                     FT_UINT32, BASE_DEC, NULL, 0x0,
1517                     NULL, HFILL }
1518                 },
1519 /* AppleTalk internal route TLV */
1520                 { &hf_eigrp_at_int_delay,
1521                   { "Delay", "eigrp.at_int.delay",
1522                     FT_UINT32, BASE_DEC, NULL, 0x0,
1523                     NULL, HFILL }
1524                 },
1525                 { &hf_eigrp_at_int_bandwidth,
1526                   { "Bandwidth", "eigrp.at_int.bandwidth",
1527                     FT_UINT32, BASE_DEC, NULL, 0x0,
1528                     NULL, HFILL }
1529                 },
1530                 { &hf_eigrp_at_int_mtu,
1531                   { "MTU", "eigrp.at_int.mtu",
1532                     FT_UINT24, BASE_DEC, NULL, 0x0,
1533                     NULL, HFILL }
1534                 },
1535                 { &hf_eigrp_at_int_hopcount,
1536                   { "Hop Count", "eigrp.at_int.hopcount",
1537                     FT_UINT8, BASE_DEC, NULL, 0x0,
1538                     NULL, HFILL }
1539                 },
1540                 { &hf_eigrp_at_int_reliability,
1541                   { "Reliability", "eigrp.at_int.reliability",
1542                     FT_UINT8, BASE_DEC, NULL, 0x0,
1543                     NULL, HFILL }
1544                 },
1545                 { &hf_eigrp_at_int_load,
1546                   { "Load", "eigrp.at_int.load",
1547                     FT_UINT8, BASE_DEC, NULL, 0x0,
1548                     NULL, HFILL }
1549                 },
1550                 { &hf_eigrp_at_int_reserved,
1551                   { "Reserved", "eigrp.at_int.reserved",
1552                     FT_UINT16, BASE_DEC, NULL, 0x0,
1553                     NULL, HFILL }
1554                 },
1555 /* AppleTalk external route TLV */
1556                 { &hf_eigrp_at_ext_origrouter,
1557                   { "Originating router", "eigrp.at_ext.origrouter",
1558                     FT_UINT32, BASE_DEC, NULL, 0x0,
1559                     NULL, HFILL }
1560                 },
1561                 { &hf_eigrp_at_ext_as,
1562                   { "Originating A.S.", "eigrp.at_ext.as",
1563                     FT_UINT32, BASE_DEC, NULL, 0x0,
1564                     NULL, HFILL }
1565                 },
1566                 { &hf_eigrp_at_ext_tag,
1567                   { "Arbitrary tag", "eigrp.at_ext.tag",
1568                     FT_UINT32, BASE_DEC, NULL, 0x0,
1569                     NULL, HFILL }
1570                 },
1571                 { &hf_eigrp_at_ext_proto,
1572                   { "External protocol ID", "eigrp.at_ext.proto",
1573                     FT_UINT8, BASE_DEC, VALS(eigrp_pid_vals), 0x0,
1574                     NULL, HFILL }
1575                 },
1576                 { &hf_eigrp_at_ext_flags,
1577                   { "Flags", "eigrp.at_ext.flags",
1578                     FT_UINT8, BASE_HEX, NULL, 0x0,
1579                     NULL, HFILL }
1580                 },
1581                 { &hf_eigrp_at_ext_flags_ext,
1582                   { "External Route", "eigrp.at_ext.flags.ext",
1583                     FT_BOOLEAN, 8, NULL, EIGRP_IP_EXT_FLAGS_EXT,
1584                     NULL, HFILL }
1585                 },
1586                 { &hf_eigrp_at_ext_flags_default,
1587                   { "Candidate Default Route", "eigrp.at_ext.flags.default",
1588                     FT_BOOLEAN, 8, NULL, EIGRP_IP_EXT_FLAGS_DEFAULT,
1589                     NULL, HFILL }
1590                 },
1591                 { &hf_eigrp_at_ext_metric,
1592                   { "External protocol metric", "eigrp.at_ext.metric",
1593                     FT_UINT16, BASE_DEC, NULL, 0x0,
1594                     NULL, HFILL }
1595                 },
1596                 { &hf_eigrp_at_ext_delay,
1597                   { "Delay", "eigrp.at_ext.delay",
1598                     FT_UINT32, BASE_DEC, NULL, 0x0,
1599                     NULL, HFILL }
1600                 },
1601                 { &hf_eigrp_at_ext_bandwidth,
1602                   { "Bandwidth", "eigrp.at_ext.bandwidth",
1603                     FT_UINT32, BASE_DEC, NULL, 0x0,
1604                     NULL, HFILL }
1605                 },
1606                 { &hf_eigrp_at_ext_mtu,
1607                   { "MTU", "eigrp.at_ext.mtu",
1608                     FT_UINT24, BASE_DEC, NULL, 0x0,
1609                     NULL, HFILL }
1610                 },
1611                 { &hf_eigrp_at_ext_hopcount,
1612                   { "Hop Count", "eigrp.at_ext.hopcount",
1613                     FT_UINT8, BASE_DEC, NULL, 0x0,
1614                     NULL, HFILL }
1615                 },
1616                 { &hf_eigrp_at_ext_reliability,
1617                   { "Reliability", "eigrp.at_ext.reliability",
1618                     FT_UINT8, BASE_DEC, NULL, 0x0,
1619                     NULL, HFILL }
1620                 },
1621                 { &hf_eigrp_at_ext_load,
1622                   { "Load", "eigrp.at_ext.load",
1623                     FT_UINT8, BASE_DEC, NULL, 0x0,
1624                     NULL, HFILL }
1625                 },
1626                 { &hf_eigrp_at_ext_reserved,
1627                   { "Reserved", "eigrp.at_ext.reserved",
1628                     FT_UINT16, BASE_DEC, NULL, 0x0,
1629                     NULL, HFILL }
1630                 },
1631 /* IPv6 internal route TLV */
1632                 { &hf_eigrp_ip6_int_nexthop,
1633                   { "Next Hop", "eigrp.ip6_int.nexthop",
1634                     FT_IPv6, BASE_NONE, NULL, 0x0,
1635                     NULL, HFILL }
1636                 },
1637                 { &hf_eigrp_ip6_int_delay,
1638                   { "Delay", "eigrp.ip6_int.delay",
1639                     FT_UINT32, BASE_DEC, NULL, 0x0,
1640                     NULL, HFILL }
1641                 },
1642                 { &hf_eigrp_ip6_int_bandwidth,
1643                   { "Bandwidth", "eigrp.ip6_int.bandwidth",
1644                     FT_UINT32, BASE_DEC, NULL, 0x0,
1645                     NULL, HFILL }
1646                 },
1647                 { &hf_eigrp_ip6_int_mtu,
1648                   { "MTU", "eigrp.ip6_int.mtu",
1649                     FT_UINT24, BASE_DEC, NULL, 0x0,
1650                     NULL, HFILL }
1651                 },
1652                 { &hf_eigrp_ip6_int_hopcount,
1653                   { "Hop Count", "eigrp.ip6_int.hopcount",
1654                     FT_UINT8, BASE_DEC, NULL, 0x0,
1655                     NULL, HFILL }
1656                 },
1657                 { &hf_eigrp_ip6_int_reliability,
1658                   { "Reliability", "eigrp.ip6_int.reliability",
1659                     FT_UINT8, BASE_DEC, NULL, 0x0,
1660                     NULL, HFILL }
1661                 },
1662                 { &hf_eigrp_ip6_int_load,
1663                   { "Load", "eigrp.ip6_int.load",
1664                     FT_UINT8, BASE_DEC, NULL, 0x0,
1665                     NULL, HFILL }
1666                 },
1667                 { &hf_eigrp_ip6_int_reserved,
1668                   { "Reserved", "eigrp.ip6_int.reserved",
1669                     FT_UINT16, BASE_DEC, NULL, 0x0,
1670                     NULL, HFILL }
1671                 },
1672                 { &hf_eigrp_ip6_int_prefixlen,
1673                   { "Prefix Length", "eigrp.ip6_int.prefixlen",
1674                     FT_UINT8, BASE_DEC, NULL, 0x0,
1675                     NULL, HFILL }
1676                 },
1677 /* IPv6 external route TLV */
1678                 { &hf_eigrp_ip6_ext_nexthop,
1679                   { "Next Hop", "eigrp.ip6_ext.nexthop",
1680                     FT_IPv6, BASE_NONE, NULL, 0x0,
1681                     NULL, HFILL }
1682                 },
1683                 { &hf_eigrp_ip6_ext_origrouter,
1684                   { "Originating router", "eigrp.ip6_ext.origrouter",
1685                     FT_IPv4, BASE_NONE, NULL, 0x0,
1686                     NULL, HFILL }
1687                 },
1688                 { &hf_eigrp_ip6_ext_as,
1689                   { "Originating A.S.", "eigrp.ip6_ext.as",
1690                     FT_UINT32, BASE_DEC, NULL, 0x0,
1691                     NULL, HFILL }
1692                 },
1693                 { &hf_eigrp_ip6_ext_tag,
1694                   { "Arbitrary tag", "eigrp.ip6_ext.tag",
1695                     FT_UINT32, BASE_DEC, NULL, 0x0,
1696                     NULL, HFILL }
1697                 },
1698                 { &hf_eigrp_ip6_ext_metric,
1699                   { "External protocol metric", "eigrp.ip6_ext.metric",
1700                     FT_UINT32, BASE_DEC, NULL, 0x0,
1701                     NULL, HFILL }
1702                 },
1703                 { &hf_eigrp_ip6_ext_reserved,
1704                   { "Reserved", "eigrp.ip6_ext.reserved",
1705                     FT_UINT16, BASE_DEC, NULL, 0x0,
1706                     NULL, HFILL }
1707                 },
1708                 { &hf_eigrp_ip6_ext_proto,
1709                   { "External protocol ID", "eigrp.ip6_ext.proto",
1710                     FT_UINT8, BASE_DEC, VALS(eigrp_pid_vals), 0x0,
1711                     NULL, HFILL }
1712                 },
1713                 { &hf_eigrp_ip6_ext_flags,
1714                   { "Flags", "eigrp.ip6_ext.flags",
1715                     FT_UINT8, BASE_HEX, NULL, 0x0,
1716                     NULL, HFILL }
1717                 },
1718                 { &hf_eigrp_ip6_ext_flags_ext,
1719                   { "External Route", "eigrp.ip6_ext.flags.ext",
1720                     FT_BOOLEAN, 8, NULL, EIGRP_IP_EXT_FLAGS_EXT,
1721                     NULL, HFILL }
1722                 },
1723                 { &hf_eigrp_ip6_ext_flags_default,
1724                   { "Candidate Default Route", "eigrp.ip6_ext.flags.default",
1725                     FT_BOOLEAN, 8, NULL, EIGRP_IP_EXT_FLAGS_DEFAULT,
1726                     NULL, HFILL }
1727                 },
1728                 { &hf_eigrp_ip6_ext_delay,
1729                   { "Delay", "eigrp.ip6_ext.delay",
1730                     FT_UINT32, BASE_DEC, NULL, 0x0,
1731                     NULL, HFILL }
1732                 },
1733                 { &hf_eigrp_ip6_ext_bandwidth,
1734                   { "Bandwidth", "eigrp.ip6_ext.bandwidth",
1735                     FT_UINT32, BASE_DEC, NULL, 0x0,
1736                     NULL, HFILL }
1737                 },
1738                 { &hf_eigrp_ip6_ext_mtu,
1739                   { "MTU", "eigrp.ip6_ext.mtu",
1740                     FT_UINT24, BASE_DEC, NULL, 0x0,
1741                     NULL, HFILL }
1742                 },
1743                 { &hf_eigrp_ip6_ext_hopcount,
1744                   { "Hop Count", "eigrp.ip6_ext.hopcount",
1745                     FT_UINT8, BASE_DEC, NULL, 0x0,
1746                     NULL, HFILL }
1747                 },
1748                 { &hf_eigrp_ip6_ext_reliability,
1749                   { "Reliability", "eigrp.ip6_ext.reliability",
1750                     FT_UINT8, BASE_DEC, NULL, 0x0,
1751                     NULL, HFILL }
1752                 },
1753                 { &hf_eigrp_ip6_ext_load,
1754                   { "Load", "eigrp.ip6_ext.load",
1755                     FT_UINT8, BASE_DEC, NULL, 0x0,
1756                     NULL, HFILL }
1757                 },
1758                 { &hf_eigrp_ip6_ext_reserved2,
1759                   { "Reserved", "eigrp.ip6_ext.reserved2",
1760                     FT_UINT16, BASE_DEC, NULL, 0x0,
1761                     NULL, HFILL }
1762                 },
1763                 { &hf_eigrp_ip6_ext_prefixlen,
1764                   { "Prefix Length", "eigrp.ip6_ext.prefixlen",
1765                     FT_UINT8, BASE_DEC, NULL, 0x0,
1766                     NULL, HFILL }
1767                 }
1768         };
1769
1770         static gint *ett[] = {
1771                 &ett_eigrp,
1772                 &ett_eigrp_flags,
1773                 &ett_tlv,
1774                 &ett_eigrp_stub_flags,
1775                 &ett_eigrp_ip_ext_flags,
1776                 &ett_eigrp_ip6_ext_flags,
1777                 &ett_eigrp_at_ext_flags
1778         };
1779
1780         proto_eigrp = proto_register_protocol("Enhanced Interior Gateway Routing Protocol", "EIGRP", "eigrp");
1781         proto_register_field_array(proto_eigrp, hf, array_length(hf));
1782         proto_register_subtree_array(ett, array_length(ett));
1783 }
1784
1785 void proto_reg_handoff_eigrp(void) {
1786
1787         dissector_handle_t eigrp_handle;
1788
1789         ipxsap_handle = find_dissector("ipxsap");
1790         eigrp_handle = create_dissector_handle(dissect_eigrp, proto_eigrp);
1791         dissector_add_uint("ip.proto", IP_PROTO_EIGRP, eigrp_handle);
1792         dissector_add_uint("ddp.type", DDP_EIGRP, eigrp_handle);
1793         dissector_add_uint("ipx.socket", IPX_SOCKET_EIGRP, eigrp_handle);
1794 }