1146773Ssam/*
2146773Ssam * Copyright (c) 1998-2004  Hannes Gredler <hannes@tcpdump.org>
3146773Ssam *      The TCPDUMP project
4146773Ssam *
5146773Ssam * Redistribution and use in source and binary forms, with or without
6146773Ssam * modification, are permitted provided that: (1) source code
7146773Ssam * distributions retain the above copyright notice and this paragraph
8146773Ssam * in its entirety, and (2) distributions including binary code include
9146773Ssam * the above copyright notice and this paragraph in its entirety in
10146773Ssam * the documentation or other materials provided with the distribution.
11146773Ssam * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
12146773Ssam * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
13146773Ssam * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
14146773Ssam * FOR A PARTICULAR PURPOSE.
15146773Ssam */
16146773Ssam
17146773Ssam#ifndef lint
18146773Ssamstatic const char rcsid[] _U_ =
19190207Srpaulo    "@(#) $Header: /tcpdump/master/tcpdump/print-eigrp.c,v 1.7 2005-05-06 02:53:26 guy Exp $";
20146773Ssam#endif
21146773Ssam
22146773Ssam#ifdef HAVE_CONFIG_H
23146773Ssam#include "config.h"
24146773Ssam#endif
25146773Ssam
26146773Ssam#include <tcpdump-stdinc.h>
27146773Ssam
28146773Ssam#include <stdio.h>
29146773Ssam#include <stdlib.h>
30146773Ssam#include <string.h>
31146773Ssam
32146773Ssam#include "interface.h"
33146773Ssam#include "extract.h"
34146773Ssam#include "addrtoname.h"
35146773Ssam
36146773Ssam/*
37146773Ssam * packet format documented at
38146773Ssam * http://www.rhyshaden.com/eigrp.htm
39146773Ssam */
40146773Ssam
41146773Ssamstruct eigrp_common_header {
42146773Ssam    u_int8_t version;
43146773Ssam    u_int8_t opcode;
44146773Ssam    u_int8_t checksum[2];
45146773Ssam    u_int8_t flags[4];
46146773Ssam    u_int8_t seq[4];
47146773Ssam    u_int8_t ack[4];
48146773Ssam    u_int8_t asn[4];
49146773Ssam};
50146773Ssam
51146773Ssam#define	EIGRP_VERSION                        2
52146773Ssam
53146773Ssam#define	EIGRP_OPCODE_UPDATE                  1
54146773Ssam#define	EIGRP_OPCODE_QUERY                   3
55146773Ssam#define	EIGRP_OPCODE_REPLY                   4
56146773Ssam#define	EIGRP_OPCODE_HELLO                   5
57146773Ssam#define	EIGRP_OPCODE_IPXSAP                  6
58146773Ssam#define	EIGRP_OPCODE_PROBE                   7
59146773Ssam
60146773Ssamstatic const struct tok eigrp_opcode_values[] = {
61146773Ssam    { EIGRP_OPCODE_UPDATE, "Update" },
62146773Ssam    { EIGRP_OPCODE_QUERY, "Query" },
63146773Ssam    { EIGRP_OPCODE_REPLY, "Reply" },
64146773Ssam    { EIGRP_OPCODE_HELLO, "Hello" },
65146773Ssam    { EIGRP_OPCODE_IPXSAP, "IPX SAP" },
66146773Ssam    { EIGRP_OPCODE_PROBE, "Probe" },
67146773Ssam    { 0, NULL}
68146773Ssam};
69146773Ssam
70146773Ssamstatic const struct tok eigrp_common_header_flag_values[] = {
71146773Ssam    { 0x01, "Init" },
72146773Ssam    { 0x02, "Conditionally Received" },
73146773Ssam    { 0, NULL}
74146773Ssam};
75146773Ssam
76146773Ssamstruct eigrp_tlv_header {
77146773Ssam    u_int8_t type[2];
78146773Ssam    u_int8_t length[2];
79146773Ssam};
80146773Ssam
81146773Ssam#define EIGRP_TLV_GENERAL_PARM   0x0001
82146773Ssam#define EIGRP_TLV_AUTH           0x0002
83146773Ssam#define EIGRP_TLV_SEQ            0x0003
84146773Ssam#define EIGRP_TLV_SW_VERSION     0x0004
85146773Ssam#define EIGRP_TLV_MCAST_SEQ      0x0005
86146773Ssam#define EIGRP_TLV_IP_INT         0x0102
87146773Ssam#define EIGRP_TLV_IP_EXT         0x0103
88146773Ssam#define EIGRP_TLV_AT_INT         0x0202
89146773Ssam#define EIGRP_TLV_AT_EXT         0x0203
90146773Ssam#define EIGRP_TLV_AT_CABLE_SETUP 0x0204
91146773Ssam#define EIGRP_TLV_IPX_INT        0x0302
92146773Ssam#define EIGRP_TLV_IPX_EXT        0x0303
93146773Ssam
94146773Ssamstatic const struct tok eigrp_tlv_values[] = {
95146773Ssam    { EIGRP_TLV_GENERAL_PARM, "General Parameters"},
96146773Ssam    { EIGRP_TLV_AUTH, "Authentication"},
97146773Ssam    { EIGRP_TLV_SEQ, "Sequence"},
98146773Ssam    { EIGRP_TLV_SW_VERSION, "Software Version"},
99146773Ssam    { EIGRP_TLV_MCAST_SEQ, "Next Multicast Sequence"},
100146773Ssam    { EIGRP_TLV_IP_INT, "IP Internal routes"},
101146773Ssam    { EIGRP_TLV_IP_EXT, "IP External routes"},
102146773Ssam    { EIGRP_TLV_AT_INT, "AppleTalk Internal routes"},
103146773Ssam    { EIGRP_TLV_AT_EXT, "AppleTalk External routes"},
104146773Ssam    { EIGRP_TLV_AT_CABLE_SETUP, "AppleTalk Cable setup"},
105146773Ssam    { EIGRP_TLV_IPX_INT, "IPX Internal routes"},
106146773Ssam    { EIGRP_TLV_IPX_EXT, "IPX External routes"},
107146773Ssam    { 0, NULL}
108146773Ssam};
109146773Ssam
110146773Ssamstruct eigrp_tlv_general_parm_t {
111146773Ssam    u_int8_t k1;
112146773Ssam    u_int8_t k2;
113146773Ssam    u_int8_t k3;
114146773Ssam    u_int8_t k4;
115146773Ssam    u_int8_t k5;
116146773Ssam    u_int8_t res;
117146773Ssam    u_int8_t holdtime[2];
118146773Ssam};
119146773Ssam
120146773Ssamstruct eigrp_tlv_sw_version_t {
121146773Ssam    u_int8_t ios_major;
122146773Ssam    u_int8_t ios_minor;
123146773Ssam    u_int8_t eigrp_major;
124146773Ssam    u_int8_t eigrp_minor;
125146773Ssam};
126146773Ssam
127146773Ssamstruct eigrp_tlv_ip_int_t {
128146773Ssam    u_int8_t nexthop[4];
129146773Ssam    u_int8_t delay[4];
130146773Ssam    u_int8_t bandwidth[4];
131146773Ssam    u_int8_t mtu[3];
132146773Ssam    u_int8_t hopcount;
133146773Ssam    u_int8_t reliability;
134146773Ssam    u_int8_t load;
135146773Ssam    u_int8_t reserved[2];
136146773Ssam    u_int8_t plen;
137146773Ssam    u_int8_t destination; /* variable length [1-4] bytes encoding */
138146773Ssam};
139146773Ssam
140146773Ssamstruct eigrp_tlv_ip_ext_t {
141146773Ssam    u_int8_t nexthop[4];
142146773Ssam    u_int8_t origin_router[4];
143146773Ssam    u_int8_t origin_as[4];
144146773Ssam    u_int8_t tag[4];
145146773Ssam    u_int8_t metric[4];
146146773Ssam    u_int8_t reserved[2];
147146773Ssam    u_int8_t proto_id;
148146773Ssam    u_int8_t flags;
149146773Ssam    u_int8_t delay[4];
150146773Ssam    u_int8_t bandwidth[4];
151146773Ssam    u_int8_t mtu[3];
152146773Ssam    u_int8_t hopcount;
153146773Ssam    u_int8_t reliability;
154146773Ssam    u_int8_t load;
155146773Ssam    u_int8_t reserved2[2];
156146773Ssam    u_int8_t plen;
157146773Ssam    u_int8_t destination; /* variable length [1-4] bytes encoding */
158146773Ssam};
159146773Ssam
160146773Ssamstruct eigrp_tlv_at_cable_setup_t {
161146773Ssam    u_int8_t cable_start[2];
162146773Ssam    u_int8_t cable_end[2];
163146773Ssam    u_int8_t router_id[4];
164146773Ssam};
165146773Ssam
166146773Ssamstruct eigrp_tlv_at_int_t {
167146773Ssam    u_int8_t nexthop[4];
168146773Ssam    u_int8_t delay[4];
169146773Ssam    u_int8_t bandwidth[4];
170146773Ssam    u_int8_t mtu[3];
171146773Ssam    u_int8_t hopcount;
172146773Ssam    u_int8_t reliability;
173146773Ssam    u_int8_t load;
174146773Ssam    u_int8_t reserved[2];
175146773Ssam    u_int8_t cable_start[2];
176146773Ssam    u_int8_t cable_end[2];
177146773Ssam};
178146773Ssam
179146773Ssamstruct eigrp_tlv_at_ext_t {
180146773Ssam    u_int8_t nexthop[4];
181146773Ssam    u_int8_t origin_router[4];
182146773Ssam    u_int8_t origin_as[4];
183146773Ssam    u_int8_t tag[4];
184146773Ssam    u_int8_t proto_id;
185146773Ssam    u_int8_t flags;
186146773Ssam    u_int8_t metric[2];
187146773Ssam    u_int8_t delay[4];
188146773Ssam    u_int8_t bandwidth[4];
189146773Ssam    u_int8_t mtu[3];
190146773Ssam    u_int8_t hopcount;
191146773Ssam    u_int8_t reliability;
192146773Ssam    u_int8_t load;
193146773Ssam    u_int8_t reserved2[2];
194146773Ssam    u_int8_t cable_start[2];
195146773Ssam    u_int8_t cable_end[2];
196146773Ssam};
197146773Ssam
198146773Ssamstatic const struct tok eigrp_ext_proto_id_values[] = {
199146773Ssam    { 0x01, "IGRP" },
200146773Ssam    { 0x02, "EIGRP" },
201146773Ssam    { 0x03, "Static" },
202146773Ssam    { 0x04, "RIP" },
203146773Ssam    { 0x05, "Hello" },
204146773Ssam    { 0x06, "OSPF" },
205146773Ssam    { 0x07, "IS-IS" },
206146773Ssam    { 0x08, "EGP" },
207146773Ssam    { 0x09, "BGP" },
208146773Ssam    { 0x0a, "IDRP" },
209146773Ssam    { 0x0b, "Connected" },
210146773Ssam    { 0, NULL}
211146773Ssam};
212146773Ssam
213146773Ssamvoid
214146773Ssameigrp_print(register const u_char *pptr, register u_int len) {
215146773Ssam
216146773Ssam    const struct eigrp_common_header *eigrp_com_header;
217146773Ssam    const struct eigrp_tlv_header *eigrp_tlv_header;
218146773Ssam    const u_char *tptr,*tlv_tptr;
219147899Ssam    u_int tlen,eigrp_tlv_len,eigrp_tlv_type,tlv_tlen, byte_length, bit_length;
220146773Ssam    u_int8_t prefix[4];
221146773Ssam
222146773Ssam    union {
223146773Ssam        const struct eigrp_tlv_general_parm_t *eigrp_tlv_general_parm;
224146773Ssam        const struct eigrp_tlv_sw_version_t *eigrp_tlv_sw_version;
225146773Ssam        const struct eigrp_tlv_ip_int_t *eigrp_tlv_ip_int;
226146773Ssam        const struct eigrp_tlv_ip_ext_t *eigrp_tlv_ip_ext;
227146773Ssam        const struct eigrp_tlv_at_cable_setup_t *eigrp_tlv_at_cable_setup;
228146773Ssam        const struct eigrp_tlv_at_int_t *eigrp_tlv_at_int;
229146773Ssam        const struct eigrp_tlv_at_ext_t *eigrp_tlv_at_ext;
230146773Ssam    } tlv_ptr;
231146773Ssam
232146773Ssam    tptr=pptr;
233146773Ssam    eigrp_com_header = (const struct eigrp_common_header *)pptr;
234146773Ssam    TCHECK(*eigrp_com_header);
235146773Ssam
236146773Ssam    /*
237146773Ssam     * Sanity checking of the header.
238146773Ssam     */
239146773Ssam    if (eigrp_com_header->version != EIGRP_VERSION) {
240146773Ssam	printf("EIGRP version %u packet not supported",eigrp_com_header->version);
241146773Ssam	return;
242146773Ssam    }
243146773Ssam
244146773Ssam    /* in non-verbose mode just lets print the basic Message Type*/
245146773Ssam    if (vflag < 1) {
246146773Ssam        printf("EIGRP %s, length: %u",
247146773Ssam               tok2str(eigrp_opcode_values, "unknown (%u)",eigrp_com_header->opcode),
248146773Ssam               len);
249146773Ssam        return;
250146773Ssam    }
251146773Ssam
252146773Ssam    /* ok they seem to want to know everything - lets fully decode it */
253146773Ssam
254146773Ssam    tlen=len-sizeof(struct eigrp_common_header);
255146773Ssam
256146773Ssam    /* FIXME print other header info */
257146773Ssam    printf("\n\tEIGRP v%u, opcode: %s (%u), chksum: 0x%04x, Flags: [%s]\n\tseq: 0x%08x, ack: 0x%08x, AS: %u, length: %u",
258146773Ssam           eigrp_com_header->version,
259146773Ssam           tok2str(eigrp_opcode_values, "unknown, type: %u",eigrp_com_header->opcode),
260146773Ssam           eigrp_com_header->opcode,
261146773Ssam           EXTRACT_16BITS(&eigrp_com_header->checksum),
262146773Ssam           tok2str(eigrp_common_header_flag_values,
263146773Ssam                   "none",
264146773Ssam                   EXTRACT_32BITS(&eigrp_com_header->flags)),
265146773Ssam           EXTRACT_32BITS(&eigrp_com_header->seq),
266146773Ssam           EXTRACT_32BITS(&eigrp_com_header->ack),
267146773Ssam           EXTRACT_32BITS(&eigrp_com_header->asn),
268146773Ssam           tlen);
269146773Ssam
270146773Ssam    tptr+=sizeof(const struct eigrp_common_header);
271146773Ssam
272146773Ssam    while(tlen>0) {
273146773Ssam        /* did we capture enough for fully decoding the object header ? */
274147899Ssam        TCHECK2(*tptr, sizeof(struct eigrp_tlv_header));
275146773Ssam
276146773Ssam        eigrp_tlv_header = (const struct eigrp_tlv_header *)tptr;
277146773Ssam        eigrp_tlv_len=EXTRACT_16BITS(&eigrp_tlv_header->length);
278146773Ssam        eigrp_tlv_type=EXTRACT_16BITS(&eigrp_tlv_header->type);
279146773Ssam
280146773Ssam
281147899Ssam        if (eigrp_tlv_len < sizeof(struct eigrp_tlv_header) ||
282147899Ssam            eigrp_tlv_len > tlen) {
283228926Skevlo            print_unknown_data(tptr+sizeof(struct eigrp_tlv_header),"\n\t    ",tlen);
284146773Ssam            return;
285146773Ssam        }
286146773Ssam
287146773Ssam        printf("\n\t  %s TLV (0x%04x), length: %u",
288146773Ssam               tok2str(eigrp_tlv_values,
289146773Ssam                       "Unknown",
290146773Ssam                       eigrp_tlv_type),
291146773Ssam               eigrp_tlv_type,
292146773Ssam               eigrp_tlv_len);
293146773Ssam
294146773Ssam        tlv_tptr=tptr+sizeof(struct eigrp_tlv_header);
295146773Ssam        tlv_tlen=eigrp_tlv_len-sizeof(struct eigrp_tlv_header);
296146773Ssam
297146773Ssam        /* did we capture enough for fully decoding the object ? */
298147899Ssam        TCHECK2(*tptr, eigrp_tlv_len);
299146773Ssam
300146773Ssam        switch(eigrp_tlv_type) {
301146773Ssam
302146773Ssam        case EIGRP_TLV_GENERAL_PARM:
303146773Ssam            tlv_ptr.eigrp_tlv_general_parm = (const struct eigrp_tlv_general_parm_t *)tlv_tptr;
304146773Ssam
305146773Ssam            printf("\n\t    holdtime: %us, k1 %u, k2 %u, k3 %u, k4 %u, k5 %u",
306146773Ssam                   EXTRACT_16BITS(tlv_ptr.eigrp_tlv_general_parm->holdtime),
307146773Ssam                   tlv_ptr.eigrp_tlv_general_parm->k1,
308146773Ssam                   tlv_ptr.eigrp_tlv_general_parm->k2,
309146773Ssam                   tlv_ptr.eigrp_tlv_general_parm->k3,
310146773Ssam                   tlv_ptr.eigrp_tlv_general_parm->k4,
311146773Ssam                   tlv_ptr.eigrp_tlv_general_parm->k5);
312146773Ssam            break;
313146773Ssam
314146773Ssam        case EIGRP_TLV_SW_VERSION:
315146773Ssam            tlv_ptr.eigrp_tlv_sw_version = (const struct eigrp_tlv_sw_version_t *)tlv_tptr;
316146773Ssam
317146773Ssam            printf("\n\t    IOS version: %u.%u, EIGRP version %u.%u",
318146773Ssam                   tlv_ptr.eigrp_tlv_sw_version->ios_major,
319146773Ssam                   tlv_ptr.eigrp_tlv_sw_version->ios_minor,
320146773Ssam                   tlv_ptr.eigrp_tlv_sw_version->eigrp_major,
321146773Ssam                   tlv_ptr.eigrp_tlv_sw_version->eigrp_minor);
322146773Ssam            break;
323146773Ssam
324146773Ssam        case EIGRP_TLV_IP_INT:
325146773Ssam            tlv_ptr.eigrp_tlv_ip_int = (const struct eigrp_tlv_ip_int_t *)tlv_tptr;
326146773Ssam
327146773Ssam            bit_length = tlv_ptr.eigrp_tlv_ip_int->plen;
328147899Ssam            if (bit_length > 32) {
329146773Ssam                printf("\n\t    illegal prefix length %u",bit_length);
330146773Ssam                break;
331146773Ssam            }
332146773Ssam            byte_length = (bit_length + 7) / 8; /* variable length encoding */
333146773Ssam            memset(prefix, 0, 4);
334146773Ssam            memcpy(prefix,&tlv_ptr.eigrp_tlv_ip_int->destination,byte_length);
335146773Ssam
336146773Ssam            printf("\n\t    IPv4 prefix: %15s/%u, nexthop: ",
337146773Ssam                   ipaddr_string(prefix),
338146773Ssam                   bit_length);
339146773Ssam            if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->nexthop) == 0)
340146773Ssam                printf("self");
341146773Ssam            else
342147899Ssam                printf("%s",ipaddr_string(&tlv_ptr.eigrp_tlv_ip_int->nexthop));
343146773Ssam
344146773Ssam            printf("\n\t      delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
345146773Ssam                   (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->delay)/100),
346146773Ssam                   EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->bandwidth),
347146773Ssam                   EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_ip_int->mtu),
348146773Ssam                   tlv_ptr.eigrp_tlv_ip_int->hopcount,
349146773Ssam                   tlv_ptr.eigrp_tlv_ip_int->reliability,
350146773Ssam                   tlv_ptr.eigrp_tlv_ip_int->load);
351146773Ssam            break;
352146773Ssam
353146773Ssam        case EIGRP_TLV_IP_EXT:
354146773Ssam            tlv_ptr.eigrp_tlv_ip_ext = (const struct eigrp_tlv_ip_ext_t *)tlv_tptr;
355146773Ssam
356146773Ssam            bit_length = tlv_ptr.eigrp_tlv_ip_ext->plen;
357147899Ssam            if (bit_length > 32) {
358146773Ssam                printf("\n\t    illegal prefix length %u",bit_length);
359146773Ssam                break;
360146773Ssam            }
361146773Ssam            byte_length = (bit_length + 7) / 8; /* variable length encoding */
362146773Ssam            memset(prefix, 0, 4);
363146773Ssam            memcpy(prefix,&tlv_ptr.eigrp_tlv_ip_ext->destination,byte_length);
364146773Ssam
365146773Ssam            printf("\n\t    IPv4 prefix: %15s/%u, nexthop: ",
366146773Ssam                   ipaddr_string(prefix),
367146773Ssam                   bit_length);
368146773Ssam            if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->nexthop) == 0)
369146773Ssam                printf("self");
370146773Ssam            else
371147899Ssam                printf("%s",ipaddr_string(&tlv_ptr.eigrp_tlv_ip_ext->nexthop));
372146773Ssam
373146773Ssam            printf("\n\t      origin-router %s, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u",
374146773Ssam                   ipaddr_string(tlv_ptr.eigrp_tlv_ip_ext->origin_router),
375146773Ssam                   EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->origin_as),
376146773Ssam                   tok2str(eigrp_ext_proto_id_values,"unknown",tlv_ptr.eigrp_tlv_ip_ext->proto_id),
377146773Ssam                   tlv_ptr.eigrp_tlv_ip_ext->flags,
378146773Ssam                   EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->tag),
379146773Ssam                   EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->metric));
380146773Ssam
381146773Ssam            printf("\n\t      delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
382146773Ssam                   (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->delay)/100),
383146773Ssam                   EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->bandwidth),
384146773Ssam                   EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_ip_ext->mtu),
385146773Ssam                   tlv_ptr.eigrp_tlv_ip_ext->hopcount,
386146773Ssam                   tlv_ptr.eigrp_tlv_ip_ext->reliability,
387146773Ssam                   tlv_ptr.eigrp_tlv_ip_ext->load);
388146773Ssam            break;
389146773Ssam
390146773Ssam        case EIGRP_TLV_AT_CABLE_SETUP:
391146773Ssam            tlv_ptr.eigrp_tlv_at_cable_setup = (const struct eigrp_tlv_at_cable_setup_t *)tlv_tptr;
392146773Ssam
393146773Ssam            printf("\n\t    Cable-range: %u-%u, Router-ID %u",
394146773Ssam                   EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->cable_start),
395146773Ssam                   EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->cable_end),
396146773Ssam                   EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->router_id));
397146773Ssam            break;
398146773Ssam
399146773Ssam        case EIGRP_TLV_AT_INT:
400146773Ssam            tlv_ptr.eigrp_tlv_at_int = (const struct eigrp_tlv_at_int_t *)tlv_tptr;
401146773Ssam
402146773Ssam            printf("\n\t     Cable-Range: %u-%u, nexthop: ",
403146773Ssam                   EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->cable_start),
404146773Ssam                   EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->cable_end));
405146773Ssam
406146773Ssam            if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop) == 0)
407146773Ssam                printf("self");
408146773Ssam            else
409146773Ssam                printf("%u.%u",
410146773Ssam                       EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop),
411146773Ssam                       EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop[2]));
412146773Ssam
413146773Ssam            printf("\n\t      delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
414146773Ssam                   (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->delay)/100),
415146773Ssam                   EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->bandwidth),
416146773Ssam                   EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_at_int->mtu),
417146773Ssam                   tlv_ptr.eigrp_tlv_at_int->hopcount,
418146773Ssam                   tlv_ptr.eigrp_tlv_at_int->reliability,
419146773Ssam                   tlv_ptr.eigrp_tlv_at_int->load);
420146773Ssam            break;
421146773Ssam
422146773Ssam        case EIGRP_TLV_AT_EXT:
423146773Ssam            tlv_ptr.eigrp_tlv_at_ext = (const struct eigrp_tlv_at_ext_t *)tlv_tptr;
424146773Ssam
425146773Ssam            printf("\n\t     Cable-Range: %u-%u, nexthop: ",
426146773Ssam                   EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->cable_start),
427146773Ssam                   EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->cable_end));
428146773Ssam
429146773Ssam            if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop) == 0)
430146773Ssam                printf("self");
431146773Ssam            else
432146773Ssam                printf("%u.%u",
433146773Ssam                       EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop),
434146773Ssam                       EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop[2]));
435146773Ssam
436146773Ssam            printf("\n\t      origin-router %u, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u",
437146773Ssam                   EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->origin_router),
438146773Ssam                   EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->origin_as),
439146773Ssam                   tok2str(eigrp_ext_proto_id_values,"unknown",tlv_ptr.eigrp_tlv_at_ext->proto_id),
440146773Ssam                   tlv_ptr.eigrp_tlv_at_ext->flags,
441146773Ssam                   EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->tag),
442146773Ssam                   EXTRACT_16BITS(tlv_ptr.eigrp_tlv_at_ext->metric));
443146773Ssam
444146773Ssam            printf("\n\t      delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
445146773Ssam                   (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->delay)/100),
446146773Ssam                   EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->bandwidth),
447146773Ssam                   EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_at_ext->mtu),
448146773Ssam                   tlv_ptr.eigrp_tlv_at_ext->hopcount,
449146773Ssam                   tlv_ptr.eigrp_tlv_at_ext->reliability,
450146773Ssam                   tlv_ptr.eigrp_tlv_at_ext->load);
451146773Ssam            break;
452146773Ssam
453146773Ssam            /*
454146773Ssam             * FIXME those are the defined TLVs that lack a decoder
455146773Ssam             * you are welcome to contribute code ;-)
456146773Ssam             */
457146773Ssam
458146773Ssam        case EIGRP_TLV_AUTH:
459146773Ssam        case EIGRP_TLV_SEQ:
460146773Ssam        case EIGRP_TLV_MCAST_SEQ:
461146773Ssam        case EIGRP_TLV_IPX_INT:
462146773Ssam        case EIGRP_TLV_IPX_EXT:
463146773Ssam
464146773Ssam        default:
465146773Ssam            if (vflag <= 1)
466146773Ssam                print_unknown_data(tlv_tptr,"\n\t    ",tlv_tlen);
467146773Ssam            break;
468146773Ssam        }
469146773Ssam        /* do we want to see an additionally hexdump ? */
470146773Ssam        if (vflag > 1)
471228926Skevlo            print_unknown_data(tptr+sizeof(struct eigrp_tlv_header),"\n\t    ",
472146773Ssam                               eigrp_tlv_len-sizeof(struct eigrp_tlv_header));
473146773Ssam
474146773Ssam        tptr+=eigrp_tlv_len;
475146773Ssam        tlen-=eigrp_tlv_len;
476146773Ssam    }
477146773Ssam    return;
478146773Ssamtrunc:
479146773Ssam    printf("\n\t\t packet exceeded snapshot");
480146773Ssam}
481