xref: /freebsd/contrib/tcpdump/print-eigrp.c (revision 3340d77368116708ab5b5b95acf6c9c710528300)
11de50e9fSSam Leffler /*
21de50e9fSSam Leffler  * Copyright (c) 1998-2004  Hannes Gredler <hannes@tcpdump.org>
31de50e9fSSam Leffler  *      The TCPDUMP project
41de50e9fSSam Leffler  *
51de50e9fSSam Leffler  * Redistribution and use in source and binary forms, with or without
61de50e9fSSam Leffler  * modification, are permitted provided that: (1) source code
71de50e9fSSam Leffler  * distributions retain the above copyright notice and this paragraph
81de50e9fSSam Leffler  * in its entirety, and (2) distributions including binary code include
91de50e9fSSam Leffler  * the above copyright notice and this paragraph in its entirety in
101de50e9fSSam Leffler  * the documentation or other materials provided with the distribution.
111de50e9fSSam Leffler  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
121de50e9fSSam Leffler  * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
131de50e9fSSam Leffler  * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
141de50e9fSSam Leffler  * FOR A PARTICULAR PURPOSE.
151de50e9fSSam Leffler  */
161de50e9fSSam Leffler 
17*3340d773SGleb Smirnoff /* \summary: Enhanced Interior Gateway Routing Protocol (EIGRP) printer */
18*3340d773SGleb Smirnoff 
191de50e9fSSam Leffler #ifdef HAVE_CONFIG_H
201de50e9fSSam Leffler #include "config.h"
211de50e9fSSam Leffler #endif
221de50e9fSSam Leffler 
23*3340d773SGleb Smirnoff #include <netdissect-stdinc.h>
241de50e9fSSam Leffler 
251de50e9fSSam Leffler #include <string.h>
261de50e9fSSam Leffler 
27*3340d773SGleb Smirnoff #include "netdissect.h"
281de50e9fSSam Leffler #include "extract.h"
291de50e9fSSam Leffler #include "addrtoname.h"
301de50e9fSSam Leffler 
311de50e9fSSam Leffler /*
321de50e9fSSam Leffler  * packet format documented at
331de50e9fSSam Leffler  * http://www.rhyshaden.com/eigrp.htm
341de50e9fSSam Leffler  */
351de50e9fSSam Leffler 
361de50e9fSSam Leffler struct eigrp_common_header {
373c602fabSXin LI     uint8_t version;
383c602fabSXin LI     uint8_t opcode;
393c602fabSXin LI     uint8_t checksum[2];
403c602fabSXin LI     uint8_t flags[4];
413c602fabSXin LI     uint8_t seq[4];
423c602fabSXin LI     uint8_t ack[4];
433c602fabSXin LI     uint8_t asn[4];
441de50e9fSSam Leffler };
451de50e9fSSam Leffler 
461de50e9fSSam Leffler #define	EIGRP_VERSION                        2
471de50e9fSSam Leffler 
481de50e9fSSam Leffler #define	EIGRP_OPCODE_UPDATE                  1
491de50e9fSSam Leffler #define	EIGRP_OPCODE_QUERY                   3
501de50e9fSSam Leffler #define	EIGRP_OPCODE_REPLY                   4
511de50e9fSSam Leffler #define	EIGRP_OPCODE_HELLO                   5
521de50e9fSSam Leffler #define	EIGRP_OPCODE_IPXSAP                  6
531de50e9fSSam Leffler #define	EIGRP_OPCODE_PROBE                   7
541de50e9fSSam Leffler 
551de50e9fSSam Leffler static const struct tok eigrp_opcode_values[] = {
561de50e9fSSam Leffler     { EIGRP_OPCODE_UPDATE, "Update" },
571de50e9fSSam Leffler     { EIGRP_OPCODE_QUERY, "Query" },
581de50e9fSSam Leffler     { EIGRP_OPCODE_REPLY, "Reply" },
591de50e9fSSam Leffler     { EIGRP_OPCODE_HELLO, "Hello" },
601de50e9fSSam Leffler     { EIGRP_OPCODE_IPXSAP, "IPX SAP" },
611de50e9fSSam Leffler     { EIGRP_OPCODE_PROBE, "Probe" },
621de50e9fSSam Leffler     { 0, NULL}
631de50e9fSSam Leffler };
641de50e9fSSam Leffler 
651de50e9fSSam Leffler static const struct tok eigrp_common_header_flag_values[] = {
661de50e9fSSam Leffler     { 0x01, "Init" },
671de50e9fSSam Leffler     { 0x02, "Conditionally Received" },
681de50e9fSSam Leffler     { 0, NULL}
691de50e9fSSam Leffler };
701de50e9fSSam Leffler 
711de50e9fSSam Leffler struct eigrp_tlv_header {
723c602fabSXin LI     uint8_t type[2];
733c602fabSXin LI     uint8_t length[2];
741de50e9fSSam Leffler };
751de50e9fSSam Leffler 
761de50e9fSSam Leffler #define EIGRP_TLV_GENERAL_PARM   0x0001
771de50e9fSSam Leffler #define EIGRP_TLV_AUTH           0x0002
781de50e9fSSam Leffler #define EIGRP_TLV_SEQ            0x0003
791de50e9fSSam Leffler #define EIGRP_TLV_SW_VERSION     0x0004
801de50e9fSSam Leffler #define EIGRP_TLV_MCAST_SEQ      0x0005
811de50e9fSSam Leffler #define EIGRP_TLV_IP_INT         0x0102
821de50e9fSSam Leffler #define EIGRP_TLV_IP_EXT         0x0103
831de50e9fSSam Leffler #define EIGRP_TLV_AT_INT         0x0202
841de50e9fSSam Leffler #define EIGRP_TLV_AT_EXT         0x0203
851de50e9fSSam Leffler #define EIGRP_TLV_AT_CABLE_SETUP 0x0204
861de50e9fSSam Leffler #define EIGRP_TLV_IPX_INT        0x0302
871de50e9fSSam Leffler #define EIGRP_TLV_IPX_EXT        0x0303
881de50e9fSSam Leffler 
891de50e9fSSam Leffler static const struct tok eigrp_tlv_values[] = {
901de50e9fSSam Leffler     { EIGRP_TLV_GENERAL_PARM, "General Parameters"},
911de50e9fSSam Leffler     { EIGRP_TLV_AUTH, "Authentication"},
921de50e9fSSam Leffler     { EIGRP_TLV_SEQ, "Sequence"},
931de50e9fSSam Leffler     { EIGRP_TLV_SW_VERSION, "Software Version"},
941de50e9fSSam Leffler     { EIGRP_TLV_MCAST_SEQ, "Next Multicast Sequence"},
951de50e9fSSam Leffler     { EIGRP_TLV_IP_INT, "IP Internal routes"},
961de50e9fSSam Leffler     { EIGRP_TLV_IP_EXT, "IP External routes"},
971de50e9fSSam Leffler     { EIGRP_TLV_AT_INT, "AppleTalk Internal routes"},
981de50e9fSSam Leffler     { EIGRP_TLV_AT_EXT, "AppleTalk External routes"},
991de50e9fSSam Leffler     { EIGRP_TLV_AT_CABLE_SETUP, "AppleTalk Cable setup"},
1001de50e9fSSam Leffler     { EIGRP_TLV_IPX_INT, "IPX Internal routes"},
1011de50e9fSSam Leffler     { EIGRP_TLV_IPX_EXT, "IPX External routes"},
1021de50e9fSSam Leffler     { 0, NULL}
1031de50e9fSSam Leffler };
1041de50e9fSSam Leffler 
1051de50e9fSSam Leffler struct eigrp_tlv_general_parm_t {
1063c602fabSXin LI     uint8_t k1;
1073c602fabSXin LI     uint8_t k2;
1083c602fabSXin LI     uint8_t k3;
1093c602fabSXin LI     uint8_t k4;
1103c602fabSXin LI     uint8_t k5;
1113c602fabSXin LI     uint8_t res;
1123c602fabSXin LI     uint8_t holdtime[2];
1131de50e9fSSam Leffler };
1141de50e9fSSam Leffler 
1151de50e9fSSam Leffler struct eigrp_tlv_sw_version_t {
1163c602fabSXin LI     uint8_t ios_major;
1173c602fabSXin LI     uint8_t ios_minor;
1183c602fabSXin LI     uint8_t eigrp_major;
1193c602fabSXin LI     uint8_t eigrp_minor;
1201de50e9fSSam Leffler };
1211de50e9fSSam Leffler 
1221de50e9fSSam Leffler struct eigrp_tlv_ip_int_t {
1233c602fabSXin LI     uint8_t nexthop[4];
1243c602fabSXin LI     uint8_t delay[4];
1253c602fabSXin LI     uint8_t bandwidth[4];
1263c602fabSXin LI     uint8_t mtu[3];
1273c602fabSXin LI     uint8_t hopcount;
1283c602fabSXin LI     uint8_t reliability;
1293c602fabSXin LI     uint8_t load;
1303c602fabSXin LI     uint8_t reserved[2];
1313c602fabSXin LI     uint8_t plen;
1323c602fabSXin LI     uint8_t destination; /* variable length [1-4] bytes encoding */
1331de50e9fSSam Leffler };
1341de50e9fSSam Leffler 
1351de50e9fSSam Leffler struct eigrp_tlv_ip_ext_t {
1363c602fabSXin LI     uint8_t nexthop[4];
1373c602fabSXin LI     uint8_t origin_router[4];
1383c602fabSXin LI     uint8_t origin_as[4];
1393c602fabSXin LI     uint8_t tag[4];
1403c602fabSXin LI     uint8_t metric[4];
1413c602fabSXin LI     uint8_t reserved[2];
1423c602fabSXin LI     uint8_t proto_id;
1433c602fabSXin LI     uint8_t flags;
1443c602fabSXin LI     uint8_t delay[4];
1453c602fabSXin LI     uint8_t bandwidth[4];
1463c602fabSXin LI     uint8_t mtu[3];
1473c602fabSXin LI     uint8_t hopcount;
1483c602fabSXin LI     uint8_t reliability;
1493c602fabSXin LI     uint8_t load;
1503c602fabSXin LI     uint8_t reserved2[2];
1513c602fabSXin LI     uint8_t plen;
1523c602fabSXin LI     uint8_t destination; /* variable length [1-4] bytes encoding */
1531de50e9fSSam Leffler };
1541de50e9fSSam Leffler 
1551de50e9fSSam Leffler struct eigrp_tlv_at_cable_setup_t {
1563c602fabSXin LI     uint8_t cable_start[2];
1573c602fabSXin LI     uint8_t cable_end[2];
1583c602fabSXin LI     uint8_t router_id[4];
1591de50e9fSSam Leffler };
1601de50e9fSSam Leffler 
1611de50e9fSSam Leffler struct eigrp_tlv_at_int_t {
1623c602fabSXin LI     uint8_t nexthop[4];
1633c602fabSXin LI     uint8_t delay[4];
1643c602fabSXin LI     uint8_t bandwidth[4];
1653c602fabSXin LI     uint8_t mtu[3];
1663c602fabSXin LI     uint8_t hopcount;
1673c602fabSXin LI     uint8_t reliability;
1683c602fabSXin LI     uint8_t load;
1693c602fabSXin LI     uint8_t reserved[2];
1703c602fabSXin LI     uint8_t cable_start[2];
1713c602fabSXin LI     uint8_t cable_end[2];
1721de50e9fSSam Leffler };
1731de50e9fSSam Leffler 
1741de50e9fSSam Leffler struct eigrp_tlv_at_ext_t {
1753c602fabSXin LI     uint8_t nexthop[4];
1763c602fabSXin LI     uint8_t origin_router[4];
1773c602fabSXin LI     uint8_t origin_as[4];
1783c602fabSXin LI     uint8_t tag[4];
1793c602fabSXin LI     uint8_t proto_id;
1803c602fabSXin LI     uint8_t flags;
1813c602fabSXin LI     uint8_t metric[2];
1823c602fabSXin LI     uint8_t delay[4];
1833c602fabSXin LI     uint8_t bandwidth[4];
1843c602fabSXin LI     uint8_t mtu[3];
1853c602fabSXin LI     uint8_t hopcount;
1863c602fabSXin LI     uint8_t reliability;
1873c602fabSXin LI     uint8_t load;
1883c602fabSXin LI     uint8_t reserved2[2];
1893c602fabSXin LI     uint8_t cable_start[2];
1903c602fabSXin LI     uint8_t cable_end[2];
1911de50e9fSSam Leffler };
1921de50e9fSSam Leffler 
1931de50e9fSSam Leffler static const struct tok eigrp_ext_proto_id_values[] = {
1941de50e9fSSam Leffler     { 0x01, "IGRP" },
1951de50e9fSSam Leffler     { 0x02, "EIGRP" },
1961de50e9fSSam Leffler     { 0x03, "Static" },
1971de50e9fSSam Leffler     { 0x04, "RIP" },
1981de50e9fSSam Leffler     { 0x05, "Hello" },
1991de50e9fSSam Leffler     { 0x06, "OSPF" },
2001de50e9fSSam Leffler     { 0x07, "IS-IS" },
2011de50e9fSSam Leffler     { 0x08, "EGP" },
2021de50e9fSSam Leffler     { 0x09, "BGP" },
2031de50e9fSSam Leffler     { 0x0a, "IDRP" },
2041de50e9fSSam Leffler     { 0x0b, "Connected" },
2051de50e9fSSam Leffler     { 0, NULL}
2061de50e9fSSam Leffler };
2071de50e9fSSam Leffler 
2081de50e9fSSam Leffler void
2098bdc5a62SPatrick Kelsey eigrp_print(netdissect_options *ndo, register const u_char *pptr, register u_int len)
2108bdc5a62SPatrick Kelsey {
2111de50e9fSSam Leffler     const struct eigrp_common_header *eigrp_com_header;
2121de50e9fSSam Leffler     const struct eigrp_tlv_header *eigrp_tlv_header;
2131de50e9fSSam Leffler     const u_char *tptr,*tlv_tptr;
214f4d0c64aSSam Leffler     u_int tlen,eigrp_tlv_len,eigrp_tlv_type,tlv_tlen, byte_length, bit_length;
2153c602fabSXin LI     uint8_t prefix[4];
2161de50e9fSSam Leffler 
2171de50e9fSSam Leffler     union {
2181de50e9fSSam Leffler         const struct eigrp_tlv_general_parm_t *eigrp_tlv_general_parm;
2191de50e9fSSam Leffler         const struct eigrp_tlv_sw_version_t *eigrp_tlv_sw_version;
2201de50e9fSSam Leffler         const struct eigrp_tlv_ip_int_t *eigrp_tlv_ip_int;
2211de50e9fSSam Leffler         const struct eigrp_tlv_ip_ext_t *eigrp_tlv_ip_ext;
2221de50e9fSSam Leffler         const struct eigrp_tlv_at_cable_setup_t *eigrp_tlv_at_cable_setup;
2231de50e9fSSam Leffler         const struct eigrp_tlv_at_int_t *eigrp_tlv_at_int;
2241de50e9fSSam Leffler         const struct eigrp_tlv_at_ext_t *eigrp_tlv_at_ext;
2251de50e9fSSam Leffler     } tlv_ptr;
2261de50e9fSSam Leffler 
2271de50e9fSSam Leffler     tptr=pptr;
2281de50e9fSSam Leffler     eigrp_com_header = (const struct eigrp_common_header *)pptr;
2293c602fabSXin LI     ND_TCHECK(*eigrp_com_header);
2301de50e9fSSam Leffler 
2311de50e9fSSam Leffler     /*
2321de50e9fSSam Leffler      * Sanity checking of the header.
2331de50e9fSSam Leffler      */
2341de50e9fSSam Leffler     if (eigrp_com_header->version != EIGRP_VERSION) {
2353c602fabSXin LI 	ND_PRINT((ndo, "EIGRP version %u packet not supported",eigrp_com_header->version));
2361de50e9fSSam Leffler 	return;
2371de50e9fSSam Leffler     }
2381de50e9fSSam Leffler 
2391de50e9fSSam Leffler     /* in non-verbose mode just lets print the basic Message Type*/
2403c602fabSXin LI     if (ndo->ndo_vflag < 1) {
2413c602fabSXin LI         ND_PRINT((ndo, "EIGRP %s, length: %u",
2421de50e9fSSam Leffler                tok2str(eigrp_opcode_values, "unknown (%u)",eigrp_com_header->opcode),
2433c602fabSXin LI                len));
2441de50e9fSSam Leffler         return;
2451de50e9fSSam Leffler     }
2461de50e9fSSam Leffler 
2471de50e9fSSam Leffler     /* ok they seem to want to know everything - lets fully decode it */
2481de50e9fSSam Leffler 
2491de50e9fSSam Leffler     tlen=len-sizeof(struct eigrp_common_header);
2501de50e9fSSam Leffler 
2511de50e9fSSam Leffler     /* FIXME print other header info */
2523c602fabSXin LI     ND_PRINT((ndo, "\n\tEIGRP v%u, opcode: %s (%u), chksum: 0x%04x, Flags: [%s]\n\tseq: 0x%08x, ack: 0x%08x, AS: %u, length: %u",
2531de50e9fSSam Leffler            eigrp_com_header->version,
2541de50e9fSSam Leffler            tok2str(eigrp_opcode_values, "unknown, type: %u",eigrp_com_header->opcode),
2551de50e9fSSam Leffler            eigrp_com_header->opcode,
2561de50e9fSSam Leffler            EXTRACT_16BITS(&eigrp_com_header->checksum),
2571de50e9fSSam Leffler            tok2str(eigrp_common_header_flag_values,
2581de50e9fSSam Leffler                    "none",
2591de50e9fSSam Leffler                    EXTRACT_32BITS(&eigrp_com_header->flags)),
2601de50e9fSSam Leffler            EXTRACT_32BITS(&eigrp_com_header->seq),
2611de50e9fSSam Leffler            EXTRACT_32BITS(&eigrp_com_header->ack),
2621de50e9fSSam Leffler            EXTRACT_32BITS(&eigrp_com_header->asn),
2633c602fabSXin LI            tlen));
2641de50e9fSSam Leffler 
2651de50e9fSSam Leffler     tptr+=sizeof(const struct eigrp_common_header);
2661de50e9fSSam Leffler 
2671de50e9fSSam Leffler     while(tlen>0) {
2681de50e9fSSam Leffler         /* did we capture enough for fully decoding the object header ? */
2693c602fabSXin LI         ND_TCHECK2(*tptr, sizeof(struct eigrp_tlv_header));
2701de50e9fSSam Leffler 
2711de50e9fSSam Leffler         eigrp_tlv_header = (const struct eigrp_tlv_header *)tptr;
2721de50e9fSSam Leffler         eigrp_tlv_len=EXTRACT_16BITS(&eigrp_tlv_header->length);
2731de50e9fSSam Leffler         eigrp_tlv_type=EXTRACT_16BITS(&eigrp_tlv_header->type);
2741de50e9fSSam Leffler 
2751de50e9fSSam Leffler 
276f4d0c64aSSam Leffler         if (eigrp_tlv_len < sizeof(struct eigrp_tlv_header) ||
277f4d0c64aSSam Leffler             eigrp_tlv_len > tlen) {
2783c602fabSXin LI             print_unknown_data(ndo,tptr+sizeof(struct eigrp_tlv_header),"\n\t    ",tlen);
2791de50e9fSSam Leffler             return;
2801de50e9fSSam Leffler         }
2811de50e9fSSam Leffler 
2823c602fabSXin LI         ND_PRINT((ndo, "\n\t  %s TLV (0x%04x), length: %u",
2831de50e9fSSam Leffler                tok2str(eigrp_tlv_values,
2841de50e9fSSam Leffler                        "Unknown",
2851de50e9fSSam Leffler                        eigrp_tlv_type),
2861de50e9fSSam Leffler                eigrp_tlv_type,
2873c602fabSXin LI                eigrp_tlv_len));
2881de50e9fSSam Leffler 
2891de50e9fSSam Leffler         tlv_tptr=tptr+sizeof(struct eigrp_tlv_header);
2901de50e9fSSam Leffler         tlv_tlen=eigrp_tlv_len-sizeof(struct eigrp_tlv_header);
2911de50e9fSSam Leffler 
2921de50e9fSSam Leffler         /* did we capture enough for fully decoding the object ? */
2933c602fabSXin LI         ND_TCHECK2(*tptr, eigrp_tlv_len);
2941de50e9fSSam Leffler 
2951de50e9fSSam Leffler         switch(eigrp_tlv_type) {
2961de50e9fSSam Leffler 
2971de50e9fSSam Leffler         case EIGRP_TLV_GENERAL_PARM:
2981de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_general_parm = (const struct eigrp_tlv_general_parm_t *)tlv_tptr;
2991de50e9fSSam Leffler 
3003c602fabSXin LI             ND_PRINT((ndo, "\n\t    holdtime: %us, k1 %u, k2 %u, k3 %u, k4 %u, k5 %u",
3011de50e9fSSam Leffler                    EXTRACT_16BITS(tlv_ptr.eigrp_tlv_general_parm->holdtime),
3021de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_general_parm->k1,
3031de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_general_parm->k2,
3041de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_general_parm->k3,
3051de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_general_parm->k4,
3063c602fabSXin LI                    tlv_ptr.eigrp_tlv_general_parm->k5));
3071de50e9fSSam Leffler             break;
3081de50e9fSSam Leffler 
3091de50e9fSSam Leffler         case EIGRP_TLV_SW_VERSION:
3101de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_sw_version = (const struct eigrp_tlv_sw_version_t *)tlv_tptr;
3111de50e9fSSam Leffler 
3123c602fabSXin LI             ND_PRINT((ndo, "\n\t    IOS version: %u.%u, EIGRP version %u.%u",
3131de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_sw_version->ios_major,
3141de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_sw_version->ios_minor,
3151de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_sw_version->eigrp_major,
3163c602fabSXin LI                    tlv_ptr.eigrp_tlv_sw_version->eigrp_minor));
3171de50e9fSSam Leffler             break;
3181de50e9fSSam Leffler 
3191de50e9fSSam Leffler         case EIGRP_TLV_IP_INT:
3201de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_ip_int = (const struct eigrp_tlv_ip_int_t *)tlv_tptr;
3211de50e9fSSam Leffler 
3221de50e9fSSam Leffler             bit_length = tlv_ptr.eigrp_tlv_ip_int->plen;
323f4d0c64aSSam Leffler             if (bit_length > 32) {
3243c602fabSXin LI                 ND_PRINT((ndo, "\n\t    illegal prefix length %u",bit_length));
3251de50e9fSSam Leffler                 break;
3261de50e9fSSam Leffler             }
3271de50e9fSSam Leffler             byte_length = (bit_length + 7) / 8; /* variable length encoding */
3281de50e9fSSam Leffler             memset(prefix, 0, 4);
3291de50e9fSSam Leffler             memcpy(prefix,&tlv_ptr.eigrp_tlv_ip_int->destination,byte_length);
3301de50e9fSSam Leffler 
3313c602fabSXin LI             ND_PRINT((ndo, "\n\t    IPv4 prefix: %15s/%u, nexthop: ",
3323c602fabSXin LI                    ipaddr_string(ndo, prefix),
3333c602fabSXin LI                    bit_length));
3341de50e9fSSam Leffler             if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->nexthop) == 0)
3353c602fabSXin LI                 ND_PRINT((ndo, "self"));
3361de50e9fSSam Leffler             else
3373c602fabSXin LI                 ND_PRINT((ndo, "%s",ipaddr_string(ndo, &tlv_ptr.eigrp_tlv_ip_int->nexthop)));
3381de50e9fSSam Leffler 
3393c602fabSXin LI             ND_PRINT((ndo, "\n\t      delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
3401de50e9fSSam Leffler                    (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->delay)/100),
3411de50e9fSSam Leffler                    EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->bandwidth),
3421de50e9fSSam Leffler                    EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_ip_int->mtu),
3431de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_ip_int->hopcount,
3441de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_ip_int->reliability,
3453c602fabSXin LI                    tlv_ptr.eigrp_tlv_ip_int->load));
3461de50e9fSSam Leffler             break;
3471de50e9fSSam Leffler 
3481de50e9fSSam Leffler         case EIGRP_TLV_IP_EXT:
3491de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_ip_ext = (const struct eigrp_tlv_ip_ext_t *)tlv_tptr;
3501de50e9fSSam Leffler 
3511de50e9fSSam Leffler             bit_length = tlv_ptr.eigrp_tlv_ip_ext->plen;
352f4d0c64aSSam Leffler             if (bit_length > 32) {
3533c602fabSXin LI                 ND_PRINT((ndo, "\n\t    illegal prefix length %u",bit_length));
3541de50e9fSSam Leffler                 break;
3551de50e9fSSam Leffler             }
3561de50e9fSSam Leffler             byte_length = (bit_length + 7) / 8; /* variable length encoding */
3571de50e9fSSam Leffler             memset(prefix, 0, 4);
3581de50e9fSSam Leffler             memcpy(prefix,&tlv_ptr.eigrp_tlv_ip_ext->destination,byte_length);
3591de50e9fSSam Leffler 
3603c602fabSXin LI             ND_PRINT((ndo, "\n\t    IPv4 prefix: %15s/%u, nexthop: ",
3613c602fabSXin LI                    ipaddr_string(ndo, prefix),
3623c602fabSXin LI                    bit_length));
3631de50e9fSSam Leffler             if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->nexthop) == 0)
3643c602fabSXin LI                 ND_PRINT((ndo, "self"));
3651de50e9fSSam Leffler             else
3663c602fabSXin LI                 ND_PRINT((ndo, "%s",ipaddr_string(ndo, &tlv_ptr.eigrp_tlv_ip_ext->nexthop)));
3671de50e9fSSam Leffler 
3683c602fabSXin LI             ND_PRINT((ndo, "\n\t      origin-router %s, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u",
3693c602fabSXin LI                    ipaddr_string(ndo, tlv_ptr.eigrp_tlv_ip_ext->origin_router),
3701de50e9fSSam Leffler                    EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->origin_as),
3711de50e9fSSam Leffler                    tok2str(eigrp_ext_proto_id_values,"unknown",tlv_ptr.eigrp_tlv_ip_ext->proto_id),
3721de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_ip_ext->flags,
3731de50e9fSSam Leffler                    EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->tag),
3743c602fabSXin LI                    EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->metric)));
3751de50e9fSSam Leffler 
3763c602fabSXin LI             ND_PRINT((ndo, "\n\t      delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
3771de50e9fSSam Leffler                    (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->delay)/100),
3781de50e9fSSam Leffler                    EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->bandwidth),
3791de50e9fSSam Leffler                    EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_ip_ext->mtu),
3801de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_ip_ext->hopcount,
3811de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_ip_ext->reliability,
3823c602fabSXin LI                    tlv_ptr.eigrp_tlv_ip_ext->load));
3831de50e9fSSam Leffler             break;
3841de50e9fSSam Leffler 
3851de50e9fSSam Leffler         case EIGRP_TLV_AT_CABLE_SETUP:
3861de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_at_cable_setup = (const struct eigrp_tlv_at_cable_setup_t *)tlv_tptr;
3871de50e9fSSam Leffler 
3883c602fabSXin LI             ND_PRINT((ndo, "\n\t    Cable-range: %u-%u, Router-ID %u",
3891de50e9fSSam Leffler                    EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->cable_start),
3901de50e9fSSam Leffler                    EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->cable_end),
3913c602fabSXin LI                    EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->router_id)));
3921de50e9fSSam Leffler             break;
3931de50e9fSSam Leffler 
3941de50e9fSSam Leffler         case EIGRP_TLV_AT_INT:
3951de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_at_int = (const struct eigrp_tlv_at_int_t *)tlv_tptr;
3961de50e9fSSam Leffler 
3973c602fabSXin LI             ND_PRINT((ndo, "\n\t     Cable-Range: %u-%u, nexthop: ",
3981de50e9fSSam Leffler                    EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->cable_start),
3993c602fabSXin LI                    EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->cable_end)));
4001de50e9fSSam Leffler 
4011de50e9fSSam Leffler             if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop) == 0)
4023c602fabSXin LI                 ND_PRINT((ndo, "self"));
4031de50e9fSSam Leffler             else
4043c602fabSXin LI                 ND_PRINT((ndo, "%u.%u",
4051de50e9fSSam Leffler                        EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop),
4063c602fabSXin LI                        EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop[2])));
4071de50e9fSSam Leffler 
4083c602fabSXin LI             ND_PRINT((ndo, "\n\t      delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
4091de50e9fSSam Leffler                    (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->delay)/100),
4101de50e9fSSam Leffler                    EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->bandwidth),
4111de50e9fSSam Leffler                    EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_at_int->mtu),
4121de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_at_int->hopcount,
4131de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_at_int->reliability,
4143c602fabSXin LI                    tlv_ptr.eigrp_tlv_at_int->load));
4151de50e9fSSam Leffler             break;
4161de50e9fSSam Leffler 
4171de50e9fSSam Leffler         case EIGRP_TLV_AT_EXT:
4181de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_at_ext = (const struct eigrp_tlv_at_ext_t *)tlv_tptr;
4191de50e9fSSam Leffler 
4203c602fabSXin LI             ND_PRINT((ndo, "\n\t     Cable-Range: %u-%u, nexthop: ",
4211de50e9fSSam Leffler                    EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->cable_start),
4223c602fabSXin LI                    EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->cable_end)));
4231de50e9fSSam Leffler 
4241de50e9fSSam Leffler             if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop) == 0)
4253c602fabSXin LI                 ND_PRINT((ndo, "self"));
4261de50e9fSSam Leffler             else
4273c602fabSXin LI                 ND_PRINT((ndo, "%u.%u",
4281de50e9fSSam Leffler                        EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop),
4293c602fabSXin LI                        EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop[2])));
4301de50e9fSSam Leffler 
4313c602fabSXin LI             ND_PRINT((ndo, "\n\t      origin-router %u, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u",
4321de50e9fSSam Leffler                    EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->origin_router),
4331de50e9fSSam Leffler                    EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->origin_as),
4341de50e9fSSam Leffler                    tok2str(eigrp_ext_proto_id_values,"unknown",tlv_ptr.eigrp_tlv_at_ext->proto_id),
4351de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_at_ext->flags,
4361de50e9fSSam Leffler                    EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->tag),
4373c602fabSXin LI                    EXTRACT_16BITS(tlv_ptr.eigrp_tlv_at_ext->metric)));
4381de50e9fSSam Leffler 
4393c602fabSXin LI             ND_PRINT((ndo, "\n\t      delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
4401de50e9fSSam Leffler                    (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->delay)/100),
4411de50e9fSSam Leffler                    EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->bandwidth),
4421de50e9fSSam Leffler                    EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_at_ext->mtu),
4431de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_at_ext->hopcount,
4441de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_at_ext->reliability,
4453c602fabSXin LI                    tlv_ptr.eigrp_tlv_at_ext->load));
4461de50e9fSSam Leffler             break;
4471de50e9fSSam Leffler 
4481de50e9fSSam Leffler             /*
4491de50e9fSSam Leffler              * FIXME those are the defined TLVs that lack a decoder
4501de50e9fSSam Leffler              * you are welcome to contribute code ;-)
4511de50e9fSSam Leffler              */
4521de50e9fSSam Leffler 
4531de50e9fSSam Leffler         case EIGRP_TLV_AUTH:
4541de50e9fSSam Leffler         case EIGRP_TLV_SEQ:
4551de50e9fSSam Leffler         case EIGRP_TLV_MCAST_SEQ:
4561de50e9fSSam Leffler         case EIGRP_TLV_IPX_INT:
4571de50e9fSSam Leffler         case EIGRP_TLV_IPX_EXT:
4581de50e9fSSam Leffler 
4591de50e9fSSam Leffler         default:
4603c602fabSXin LI             if (ndo->ndo_vflag <= 1)
4613c602fabSXin LI                 print_unknown_data(ndo,tlv_tptr,"\n\t    ",tlv_tlen);
4621de50e9fSSam Leffler             break;
4631de50e9fSSam Leffler         }
4641de50e9fSSam Leffler         /* do we want to see an additionally hexdump ? */
4653c602fabSXin LI         if (ndo->ndo_vflag > 1)
4663c602fabSXin LI             print_unknown_data(ndo,tptr+sizeof(struct eigrp_tlv_header),"\n\t    ",
4671de50e9fSSam Leffler                                eigrp_tlv_len-sizeof(struct eigrp_tlv_header));
4681de50e9fSSam Leffler 
4691de50e9fSSam Leffler         tptr+=eigrp_tlv_len;
4701de50e9fSSam Leffler         tlen-=eigrp_tlv_len;
4711de50e9fSSam Leffler     }
4721de50e9fSSam Leffler     return;
4731de50e9fSSam Leffler trunc:
4743c602fabSXin LI     ND_PRINT((ndo, "\n\t\t packet exceeded snapshot"));
4751de50e9fSSam Leffler }
476