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