xref: /freebsd/contrib/tcpdump/print-eigrp.c (revision 8bdc5a6251ddffc81a013f36b4384c8ace9c4bec)
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 
173c602fabSXin LI #define NETDISSECT_REWORKED
181de50e9fSSam Leffler #ifdef HAVE_CONFIG_H
191de50e9fSSam Leffler #include "config.h"
201de50e9fSSam Leffler #endif
211de50e9fSSam Leffler 
221de50e9fSSam Leffler #include <tcpdump-stdinc.h>
231de50e9fSSam Leffler 
241de50e9fSSam Leffler #include <string.h>
251de50e9fSSam Leffler 
261de50e9fSSam Leffler #include "interface.h"
271de50e9fSSam Leffler #include "extract.h"
281de50e9fSSam Leffler #include "addrtoname.h"
291de50e9fSSam Leffler 
301de50e9fSSam Leffler /*
311de50e9fSSam Leffler  * packet format documented at
321de50e9fSSam Leffler  * http://www.rhyshaden.com/eigrp.htm
331de50e9fSSam Leffler  */
341de50e9fSSam Leffler 
351de50e9fSSam Leffler struct eigrp_common_header {
363c602fabSXin LI     uint8_t version;
373c602fabSXin LI     uint8_t opcode;
383c602fabSXin LI     uint8_t checksum[2];
393c602fabSXin LI     uint8_t flags[4];
403c602fabSXin LI     uint8_t seq[4];
413c602fabSXin LI     uint8_t ack[4];
423c602fabSXin LI     uint8_t asn[4];
431de50e9fSSam Leffler };
441de50e9fSSam Leffler 
451de50e9fSSam Leffler #define	EIGRP_VERSION                        2
461de50e9fSSam Leffler 
471de50e9fSSam Leffler #define	EIGRP_OPCODE_UPDATE                  1
481de50e9fSSam Leffler #define	EIGRP_OPCODE_QUERY                   3
491de50e9fSSam Leffler #define	EIGRP_OPCODE_REPLY                   4
501de50e9fSSam Leffler #define	EIGRP_OPCODE_HELLO                   5
511de50e9fSSam Leffler #define	EIGRP_OPCODE_IPXSAP                  6
521de50e9fSSam Leffler #define	EIGRP_OPCODE_PROBE                   7
531de50e9fSSam Leffler 
541de50e9fSSam Leffler static const struct tok eigrp_opcode_values[] = {
551de50e9fSSam Leffler     { EIGRP_OPCODE_UPDATE, "Update" },
561de50e9fSSam Leffler     { EIGRP_OPCODE_QUERY, "Query" },
571de50e9fSSam Leffler     { EIGRP_OPCODE_REPLY, "Reply" },
581de50e9fSSam Leffler     { EIGRP_OPCODE_HELLO, "Hello" },
591de50e9fSSam Leffler     { EIGRP_OPCODE_IPXSAP, "IPX SAP" },
601de50e9fSSam Leffler     { EIGRP_OPCODE_PROBE, "Probe" },
611de50e9fSSam Leffler     { 0, NULL}
621de50e9fSSam Leffler };
631de50e9fSSam Leffler 
641de50e9fSSam Leffler static const struct tok eigrp_common_header_flag_values[] = {
651de50e9fSSam Leffler     { 0x01, "Init" },
661de50e9fSSam Leffler     { 0x02, "Conditionally Received" },
671de50e9fSSam Leffler     { 0, NULL}
681de50e9fSSam Leffler };
691de50e9fSSam Leffler 
701de50e9fSSam Leffler struct eigrp_tlv_header {
713c602fabSXin LI     uint8_t type[2];
723c602fabSXin LI     uint8_t length[2];
731de50e9fSSam Leffler };
741de50e9fSSam Leffler 
751de50e9fSSam Leffler #define EIGRP_TLV_GENERAL_PARM   0x0001
761de50e9fSSam Leffler #define EIGRP_TLV_AUTH           0x0002
771de50e9fSSam Leffler #define EIGRP_TLV_SEQ            0x0003
781de50e9fSSam Leffler #define EIGRP_TLV_SW_VERSION     0x0004
791de50e9fSSam Leffler #define EIGRP_TLV_MCAST_SEQ      0x0005
801de50e9fSSam Leffler #define EIGRP_TLV_IP_INT         0x0102
811de50e9fSSam Leffler #define EIGRP_TLV_IP_EXT         0x0103
821de50e9fSSam Leffler #define EIGRP_TLV_AT_INT         0x0202
831de50e9fSSam Leffler #define EIGRP_TLV_AT_EXT         0x0203
841de50e9fSSam Leffler #define EIGRP_TLV_AT_CABLE_SETUP 0x0204
851de50e9fSSam Leffler #define EIGRP_TLV_IPX_INT        0x0302
861de50e9fSSam Leffler #define EIGRP_TLV_IPX_EXT        0x0303
871de50e9fSSam Leffler 
881de50e9fSSam Leffler static const struct tok eigrp_tlv_values[] = {
891de50e9fSSam Leffler     { EIGRP_TLV_GENERAL_PARM, "General Parameters"},
901de50e9fSSam Leffler     { EIGRP_TLV_AUTH, "Authentication"},
911de50e9fSSam Leffler     { EIGRP_TLV_SEQ, "Sequence"},
921de50e9fSSam Leffler     { EIGRP_TLV_SW_VERSION, "Software Version"},
931de50e9fSSam Leffler     { EIGRP_TLV_MCAST_SEQ, "Next Multicast Sequence"},
941de50e9fSSam Leffler     { EIGRP_TLV_IP_INT, "IP Internal routes"},
951de50e9fSSam Leffler     { EIGRP_TLV_IP_EXT, "IP External routes"},
961de50e9fSSam Leffler     { EIGRP_TLV_AT_INT, "AppleTalk Internal routes"},
971de50e9fSSam Leffler     { EIGRP_TLV_AT_EXT, "AppleTalk External routes"},
981de50e9fSSam Leffler     { EIGRP_TLV_AT_CABLE_SETUP, "AppleTalk Cable setup"},
991de50e9fSSam Leffler     { EIGRP_TLV_IPX_INT, "IPX Internal routes"},
1001de50e9fSSam Leffler     { EIGRP_TLV_IPX_EXT, "IPX External routes"},
1011de50e9fSSam Leffler     { 0, NULL}
1021de50e9fSSam Leffler };
1031de50e9fSSam Leffler 
1041de50e9fSSam Leffler struct eigrp_tlv_general_parm_t {
1053c602fabSXin LI     uint8_t k1;
1063c602fabSXin LI     uint8_t k2;
1073c602fabSXin LI     uint8_t k3;
1083c602fabSXin LI     uint8_t k4;
1093c602fabSXin LI     uint8_t k5;
1103c602fabSXin LI     uint8_t res;
1113c602fabSXin LI     uint8_t holdtime[2];
1121de50e9fSSam Leffler };
1131de50e9fSSam Leffler 
1141de50e9fSSam Leffler struct eigrp_tlv_sw_version_t {
1153c602fabSXin LI     uint8_t ios_major;
1163c602fabSXin LI     uint8_t ios_minor;
1173c602fabSXin LI     uint8_t eigrp_major;
1183c602fabSXin LI     uint8_t eigrp_minor;
1191de50e9fSSam Leffler };
1201de50e9fSSam Leffler 
1211de50e9fSSam Leffler struct eigrp_tlv_ip_int_t {
1223c602fabSXin LI     uint8_t nexthop[4];
1233c602fabSXin LI     uint8_t delay[4];
1243c602fabSXin LI     uint8_t bandwidth[4];
1253c602fabSXin LI     uint8_t mtu[3];
1263c602fabSXin LI     uint8_t hopcount;
1273c602fabSXin LI     uint8_t reliability;
1283c602fabSXin LI     uint8_t load;
1293c602fabSXin LI     uint8_t reserved[2];
1303c602fabSXin LI     uint8_t plen;
1313c602fabSXin LI     uint8_t destination; /* variable length [1-4] bytes encoding */
1321de50e9fSSam Leffler };
1331de50e9fSSam Leffler 
1341de50e9fSSam Leffler struct eigrp_tlv_ip_ext_t {
1353c602fabSXin LI     uint8_t nexthop[4];
1363c602fabSXin LI     uint8_t origin_router[4];
1373c602fabSXin LI     uint8_t origin_as[4];
1383c602fabSXin LI     uint8_t tag[4];
1393c602fabSXin LI     uint8_t metric[4];
1403c602fabSXin LI     uint8_t reserved[2];
1413c602fabSXin LI     uint8_t proto_id;
1423c602fabSXin LI     uint8_t flags;
1433c602fabSXin LI     uint8_t delay[4];
1443c602fabSXin LI     uint8_t bandwidth[4];
1453c602fabSXin LI     uint8_t mtu[3];
1463c602fabSXin LI     uint8_t hopcount;
1473c602fabSXin LI     uint8_t reliability;
1483c602fabSXin LI     uint8_t load;
1493c602fabSXin LI     uint8_t reserved2[2];
1503c602fabSXin LI     uint8_t plen;
1513c602fabSXin LI     uint8_t destination; /* variable length [1-4] bytes encoding */
1521de50e9fSSam Leffler };
1531de50e9fSSam Leffler 
1541de50e9fSSam Leffler struct eigrp_tlv_at_cable_setup_t {
1553c602fabSXin LI     uint8_t cable_start[2];
1563c602fabSXin LI     uint8_t cable_end[2];
1573c602fabSXin LI     uint8_t router_id[4];
1581de50e9fSSam Leffler };
1591de50e9fSSam Leffler 
1601de50e9fSSam Leffler struct eigrp_tlv_at_int_t {
1613c602fabSXin LI     uint8_t nexthop[4];
1623c602fabSXin LI     uint8_t delay[4];
1633c602fabSXin LI     uint8_t bandwidth[4];
1643c602fabSXin LI     uint8_t mtu[3];
1653c602fabSXin LI     uint8_t hopcount;
1663c602fabSXin LI     uint8_t reliability;
1673c602fabSXin LI     uint8_t load;
1683c602fabSXin LI     uint8_t reserved[2];
1693c602fabSXin LI     uint8_t cable_start[2];
1703c602fabSXin LI     uint8_t cable_end[2];
1711de50e9fSSam Leffler };
1721de50e9fSSam Leffler 
1731de50e9fSSam Leffler struct eigrp_tlv_at_ext_t {
1743c602fabSXin LI     uint8_t nexthop[4];
1753c602fabSXin LI     uint8_t origin_router[4];
1763c602fabSXin LI     uint8_t origin_as[4];
1773c602fabSXin LI     uint8_t tag[4];
1783c602fabSXin LI     uint8_t proto_id;
1793c602fabSXin LI     uint8_t flags;
1803c602fabSXin LI     uint8_t metric[2];
1813c602fabSXin LI     uint8_t delay[4];
1823c602fabSXin LI     uint8_t bandwidth[4];
1833c602fabSXin LI     uint8_t mtu[3];
1843c602fabSXin LI     uint8_t hopcount;
1853c602fabSXin LI     uint8_t reliability;
1863c602fabSXin LI     uint8_t load;
1873c602fabSXin LI     uint8_t reserved2[2];
1883c602fabSXin LI     uint8_t cable_start[2];
1893c602fabSXin LI     uint8_t cable_end[2];
1901de50e9fSSam Leffler };
1911de50e9fSSam Leffler 
1921de50e9fSSam Leffler static const struct tok eigrp_ext_proto_id_values[] = {
1931de50e9fSSam Leffler     { 0x01, "IGRP" },
1941de50e9fSSam Leffler     { 0x02, "EIGRP" },
1951de50e9fSSam Leffler     { 0x03, "Static" },
1961de50e9fSSam Leffler     { 0x04, "RIP" },
1971de50e9fSSam Leffler     { 0x05, "Hello" },
1981de50e9fSSam Leffler     { 0x06, "OSPF" },
1991de50e9fSSam Leffler     { 0x07, "IS-IS" },
2001de50e9fSSam Leffler     { 0x08, "EGP" },
2011de50e9fSSam Leffler     { 0x09, "BGP" },
2021de50e9fSSam Leffler     { 0x0a, "IDRP" },
2031de50e9fSSam Leffler     { 0x0b, "Connected" },
2041de50e9fSSam Leffler     { 0, NULL}
2051de50e9fSSam Leffler };
2061de50e9fSSam Leffler 
2071de50e9fSSam Leffler void
208*8bdc5a62SPatrick Kelsey eigrp_print(netdissect_options *ndo, register const u_char *pptr, register u_int len)
209*8bdc5a62SPatrick Kelsey {
2101de50e9fSSam Leffler     const struct eigrp_common_header *eigrp_com_header;
2111de50e9fSSam Leffler     const struct eigrp_tlv_header *eigrp_tlv_header;
2121de50e9fSSam Leffler     const u_char *tptr,*tlv_tptr;
213f4d0c64aSSam Leffler     u_int tlen,eigrp_tlv_len,eigrp_tlv_type,tlv_tlen, byte_length, bit_length;
2143c602fabSXin LI     uint8_t prefix[4];
2151de50e9fSSam Leffler 
2161de50e9fSSam Leffler     union {
2171de50e9fSSam Leffler         const struct eigrp_tlv_general_parm_t *eigrp_tlv_general_parm;
2181de50e9fSSam Leffler         const struct eigrp_tlv_sw_version_t *eigrp_tlv_sw_version;
2191de50e9fSSam Leffler         const struct eigrp_tlv_ip_int_t *eigrp_tlv_ip_int;
2201de50e9fSSam Leffler         const struct eigrp_tlv_ip_ext_t *eigrp_tlv_ip_ext;
2211de50e9fSSam Leffler         const struct eigrp_tlv_at_cable_setup_t *eigrp_tlv_at_cable_setup;
2221de50e9fSSam Leffler         const struct eigrp_tlv_at_int_t *eigrp_tlv_at_int;
2231de50e9fSSam Leffler         const struct eigrp_tlv_at_ext_t *eigrp_tlv_at_ext;
2241de50e9fSSam Leffler     } tlv_ptr;
2251de50e9fSSam Leffler 
2261de50e9fSSam Leffler     tptr=pptr;
2271de50e9fSSam Leffler     eigrp_com_header = (const struct eigrp_common_header *)pptr;
2283c602fabSXin LI     ND_TCHECK(*eigrp_com_header);
2291de50e9fSSam Leffler 
2301de50e9fSSam Leffler     /*
2311de50e9fSSam Leffler      * Sanity checking of the header.
2321de50e9fSSam Leffler      */
2331de50e9fSSam Leffler     if (eigrp_com_header->version != EIGRP_VERSION) {
2343c602fabSXin LI 	ND_PRINT((ndo, "EIGRP version %u packet not supported",eigrp_com_header->version));
2351de50e9fSSam Leffler 	return;
2361de50e9fSSam Leffler     }
2371de50e9fSSam Leffler 
2381de50e9fSSam Leffler     /* in non-verbose mode just lets print the basic Message Type*/
2393c602fabSXin LI     if (ndo->ndo_vflag < 1) {
2403c602fabSXin LI         ND_PRINT((ndo, "EIGRP %s, length: %u",
2411de50e9fSSam Leffler                tok2str(eigrp_opcode_values, "unknown (%u)",eigrp_com_header->opcode),
2423c602fabSXin LI                len));
2431de50e9fSSam Leffler         return;
2441de50e9fSSam Leffler     }
2451de50e9fSSam Leffler 
2461de50e9fSSam Leffler     /* ok they seem to want to know everything - lets fully decode it */
2471de50e9fSSam Leffler 
2481de50e9fSSam Leffler     tlen=len-sizeof(struct eigrp_common_header);
2491de50e9fSSam Leffler 
2501de50e9fSSam Leffler     /* FIXME print other header info */
2513c602fabSXin 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",
2521de50e9fSSam Leffler            eigrp_com_header->version,
2531de50e9fSSam Leffler            tok2str(eigrp_opcode_values, "unknown, type: %u",eigrp_com_header->opcode),
2541de50e9fSSam Leffler            eigrp_com_header->opcode,
2551de50e9fSSam Leffler            EXTRACT_16BITS(&eigrp_com_header->checksum),
2561de50e9fSSam Leffler            tok2str(eigrp_common_header_flag_values,
2571de50e9fSSam Leffler                    "none",
2581de50e9fSSam Leffler                    EXTRACT_32BITS(&eigrp_com_header->flags)),
2591de50e9fSSam Leffler            EXTRACT_32BITS(&eigrp_com_header->seq),
2601de50e9fSSam Leffler            EXTRACT_32BITS(&eigrp_com_header->ack),
2611de50e9fSSam Leffler            EXTRACT_32BITS(&eigrp_com_header->asn),
2623c602fabSXin LI            tlen));
2631de50e9fSSam Leffler 
2641de50e9fSSam Leffler     tptr+=sizeof(const struct eigrp_common_header);
2651de50e9fSSam Leffler 
2661de50e9fSSam Leffler     while(tlen>0) {
2671de50e9fSSam Leffler         /* did we capture enough for fully decoding the object header ? */
2683c602fabSXin LI         ND_TCHECK2(*tptr, sizeof(struct eigrp_tlv_header));
2691de50e9fSSam Leffler 
2701de50e9fSSam Leffler         eigrp_tlv_header = (const struct eigrp_tlv_header *)tptr;
2711de50e9fSSam Leffler         eigrp_tlv_len=EXTRACT_16BITS(&eigrp_tlv_header->length);
2721de50e9fSSam Leffler         eigrp_tlv_type=EXTRACT_16BITS(&eigrp_tlv_header->type);
2731de50e9fSSam Leffler 
2741de50e9fSSam Leffler 
275f4d0c64aSSam Leffler         if (eigrp_tlv_len < sizeof(struct eigrp_tlv_header) ||
276f4d0c64aSSam Leffler             eigrp_tlv_len > tlen) {
2773c602fabSXin LI             print_unknown_data(ndo,tptr+sizeof(struct eigrp_tlv_header),"\n\t    ",tlen);
2781de50e9fSSam Leffler             return;
2791de50e9fSSam Leffler         }
2801de50e9fSSam Leffler 
2813c602fabSXin LI         ND_PRINT((ndo, "\n\t  %s TLV (0x%04x), length: %u",
2821de50e9fSSam Leffler                tok2str(eigrp_tlv_values,
2831de50e9fSSam Leffler                        "Unknown",
2841de50e9fSSam Leffler                        eigrp_tlv_type),
2851de50e9fSSam Leffler                eigrp_tlv_type,
2863c602fabSXin LI                eigrp_tlv_len));
2871de50e9fSSam Leffler 
2881de50e9fSSam Leffler         tlv_tptr=tptr+sizeof(struct eigrp_tlv_header);
2891de50e9fSSam Leffler         tlv_tlen=eigrp_tlv_len-sizeof(struct eigrp_tlv_header);
2901de50e9fSSam Leffler 
2911de50e9fSSam Leffler         /* did we capture enough for fully decoding the object ? */
2923c602fabSXin LI         ND_TCHECK2(*tptr, eigrp_tlv_len);
2931de50e9fSSam Leffler 
2941de50e9fSSam Leffler         switch(eigrp_tlv_type) {
2951de50e9fSSam Leffler 
2961de50e9fSSam Leffler         case EIGRP_TLV_GENERAL_PARM:
2971de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_general_parm = (const struct eigrp_tlv_general_parm_t *)tlv_tptr;
2981de50e9fSSam Leffler 
2993c602fabSXin LI             ND_PRINT((ndo, "\n\t    holdtime: %us, k1 %u, k2 %u, k3 %u, k4 %u, k5 %u",
3001de50e9fSSam Leffler                    EXTRACT_16BITS(tlv_ptr.eigrp_tlv_general_parm->holdtime),
3011de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_general_parm->k1,
3021de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_general_parm->k2,
3031de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_general_parm->k3,
3041de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_general_parm->k4,
3053c602fabSXin LI                    tlv_ptr.eigrp_tlv_general_parm->k5));
3061de50e9fSSam Leffler             break;
3071de50e9fSSam Leffler 
3081de50e9fSSam Leffler         case EIGRP_TLV_SW_VERSION:
3091de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_sw_version = (const struct eigrp_tlv_sw_version_t *)tlv_tptr;
3101de50e9fSSam Leffler 
3113c602fabSXin LI             ND_PRINT((ndo, "\n\t    IOS version: %u.%u, EIGRP version %u.%u",
3121de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_sw_version->ios_major,
3131de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_sw_version->ios_minor,
3141de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_sw_version->eigrp_major,
3153c602fabSXin LI                    tlv_ptr.eigrp_tlv_sw_version->eigrp_minor));
3161de50e9fSSam Leffler             break;
3171de50e9fSSam Leffler 
3181de50e9fSSam Leffler         case EIGRP_TLV_IP_INT:
3191de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_ip_int = (const struct eigrp_tlv_ip_int_t *)tlv_tptr;
3201de50e9fSSam Leffler 
3211de50e9fSSam Leffler             bit_length = tlv_ptr.eigrp_tlv_ip_int->plen;
322f4d0c64aSSam Leffler             if (bit_length > 32) {
3233c602fabSXin LI                 ND_PRINT((ndo, "\n\t    illegal prefix length %u",bit_length));
3241de50e9fSSam Leffler                 break;
3251de50e9fSSam Leffler             }
3261de50e9fSSam Leffler             byte_length = (bit_length + 7) / 8; /* variable length encoding */
3271de50e9fSSam Leffler             memset(prefix, 0, 4);
3281de50e9fSSam Leffler             memcpy(prefix,&tlv_ptr.eigrp_tlv_ip_int->destination,byte_length);
3291de50e9fSSam Leffler 
3303c602fabSXin LI             ND_PRINT((ndo, "\n\t    IPv4 prefix: %15s/%u, nexthop: ",
3313c602fabSXin LI                    ipaddr_string(ndo, prefix),
3323c602fabSXin LI                    bit_length));
3331de50e9fSSam Leffler             if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->nexthop) == 0)
3343c602fabSXin LI                 ND_PRINT((ndo, "self"));
3351de50e9fSSam Leffler             else
3363c602fabSXin LI                 ND_PRINT((ndo, "%s",ipaddr_string(ndo, &tlv_ptr.eigrp_tlv_ip_int->nexthop)));
3371de50e9fSSam Leffler 
3383c602fabSXin LI             ND_PRINT((ndo, "\n\t      delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
3391de50e9fSSam Leffler                    (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->delay)/100),
3401de50e9fSSam Leffler                    EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->bandwidth),
3411de50e9fSSam Leffler                    EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_ip_int->mtu),
3421de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_ip_int->hopcount,
3431de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_ip_int->reliability,
3443c602fabSXin LI                    tlv_ptr.eigrp_tlv_ip_int->load));
3451de50e9fSSam Leffler             break;
3461de50e9fSSam Leffler 
3471de50e9fSSam Leffler         case EIGRP_TLV_IP_EXT:
3481de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_ip_ext = (const struct eigrp_tlv_ip_ext_t *)tlv_tptr;
3491de50e9fSSam Leffler 
3501de50e9fSSam Leffler             bit_length = tlv_ptr.eigrp_tlv_ip_ext->plen;
351f4d0c64aSSam Leffler             if (bit_length > 32) {
3523c602fabSXin LI                 ND_PRINT((ndo, "\n\t    illegal prefix length %u",bit_length));
3531de50e9fSSam Leffler                 break;
3541de50e9fSSam Leffler             }
3551de50e9fSSam Leffler             byte_length = (bit_length + 7) / 8; /* variable length encoding */
3561de50e9fSSam Leffler             memset(prefix, 0, 4);
3571de50e9fSSam Leffler             memcpy(prefix,&tlv_ptr.eigrp_tlv_ip_ext->destination,byte_length);
3581de50e9fSSam Leffler 
3593c602fabSXin LI             ND_PRINT((ndo, "\n\t    IPv4 prefix: %15s/%u, nexthop: ",
3603c602fabSXin LI                    ipaddr_string(ndo, prefix),
3613c602fabSXin LI                    bit_length));
3621de50e9fSSam Leffler             if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->nexthop) == 0)
3633c602fabSXin LI                 ND_PRINT((ndo, "self"));
3641de50e9fSSam Leffler             else
3653c602fabSXin LI                 ND_PRINT((ndo, "%s",ipaddr_string(ndo, &tlv_ptr.eigrp_tlv_ip_ext->nexthop)));
3661de50e9fSSam Leffler 
3673c602fabSXin LI             ND_PRINT((ndo, "\n\t      origin-router %s, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u",
3683c602fabSXin LI                    ipaddr_string(ndo, tlv_ptr.eigrp_tlv_ip_ext->origin_router),
3691de50e9fSSam Leffler                    EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->origin_as),
3701de50e9fSSam Leffler                    tok2str(eigrp_ext_proto_id_values,"unknown",tlv_ptr.eigrp_tlv_ip_ext->proto_id),
3711de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_ip_ext->flags,
3721de50e9fSSam Leffler                    EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->tag),
3733c602fabSXin LI                    EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->metric)));
3741de50e9fSSam Leffler 
3753c602fabSXin LI             ND_PRINT((ndo, "\n\t      delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
3761de50e9fSSam Leffler                    (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->delay)/100),
3771de50e9fSSam Leffler                    EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->bandwidth),
3781de50e9fSSam Leffler                    EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_ip_ext->mtu),
3791de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_ip_ext->hopcount,
3801de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_ip_ext->reliability,
3813c602fabSXin LI                    tlv_ptr.eigrp_tlv_ip_ext->load));
3821de50e9fSSam Leffler             break;
3831de50e9fSSam Leffler 
3841de50e9fSSam Leffler         case EIGRP_TLV_AT_CABLE_SETUP:
3851de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_at_cable_setup = (const struct eigrp_tlv_at_cable_setup_t *)tlv_tptr;
3861de50e9fSSam Leffler 
3873c602fabSXin LI             ND_PRINT((ndo, "\n\t    Cable-range: %u-%u, Router-ID %u",
3881de50e9fSSam Leffler                    EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->cable_start),
3891de50e9fSSam Leffler                    EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->cable_end),
3903c602fabSXin LI                    EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->router_id)));
3911de50e9fSSam Leffler             break;
3921de50e9fSSam Leffler 
3931de50e9fSSam Leffler         case EIGRP_TLV_AT_INT:
3941de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_at_int = (const struct eigrp_tlv_at_int_t *)tlv_tptr;
3951de50e9fSSam Leffler 
3963c602fabSXin LI             ND_PRINT((ndo, "\n\t     Cable-Range: %u-%u, nexthop: ",
3971de50e9fSSam Leffler                    EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->cable_start),
3983c602fabSXin LI                    EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->cable_end)));
3991de50e9fSSam Leffler 
4001de50e9fSSam Leffler             if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop) == 0)
4013c602fabSXin LI                 ND_PRINT((ndo, "self"));
4021de50e9fSSam Leffler             else
4033c602fabSXin LI                 ND_PRINT((ndo, "%u.%u",
4041de50e9fSSam Leffler                        EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop),
4053c602fabSXin LI                        EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop[2])));
4061de50e9fSSam Leffler 
4073c602fabSXin LI             ND_PRINT((ndo, "\n\t      delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
4081de50e9fSSam Leffler                    (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->delay)/100),
4091de50e9fSSam Leffler                    EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->bandwidth),
4101de50e9fSSam Leffler                    EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_at_int->mtu),
4111de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_at_int->hopcount,
4121de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_at_int->reliability,
4133c602fabSXin LI                    tlv_ptr.eigrp_tlv_at_int->load));
4141de50e9fSSam Leffler             break;
4151de50e9fSSam Leffler 
4161de50e9fSSam Leffler         case EIGRP_TLV_AT_EXT:
4171de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_at_ext = (const struct eigrp_tlv_at_ext_t *)tlv_tptr;
4181de50e9fSSam Leffler 
4193c602fabSXin LI             ND_PRINT((ndo, "\n\t     Cable-Range: %u-%u, nexthop: ",
4201de50e9fSSam Leffler                    EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->cable_start),
4213c602fabSXin LI                    EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->cable_end)));
4221de50e9fSSam Leffler 
4231de50e9fSSam Leffler             if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop) == 0)
4243c602fabSXin LI                 ND_PRINT((ndo, "self"));
4251de50e9fSSam Leffler             else
4263c602fabSXin LI                 ND_PRINT((ndo, "%u.%u",
4271de50e9fSSam Leffler                        EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop),
4283c602fabSXin LI                        EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop[2])));
4291de50e9fSSam Leffler 
4303c602fabSXin LI             ND_PRINT((ndo, "\n\t      origin-router %u, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u",
4311de50e9fSSam Leffler                    EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->origin_router),
4321de50e9fSSam Leffler                    EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->origin_as),
4331de50e9fSSam Leffler                    tok2str(eigrp_ext_proto_id_values,"unknown",tlv_ptr.eigrp_tlv_at_ext->proto_id),
4341de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_at_ext->flags,
4351de50e9fSSam Leffler                    EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->tag),
4363c602fabSXin LI                    EXTRACT_16BITS(tlv_ptr.eigrp_tlv_at_ext->metric)));
4371de50e9fSSam Leffler 
4383c602fabSXin LI             ND_PRINT((ndo, "\n\t      delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
4391de50e9fSSam Leffler                    (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->delay)/100),
4401de50e9fSSam Leffler                    EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->bandwidth),
4411de50e9fSSam Leffler                    EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_at_ext->mtu),
4421de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_at_ext->hopcount,
4431de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_at_ext->reliability,
4443c602fabSXin LI                    tlv_ptr.eigrp_tlv_at_ext->load));
4451de50e9fSSam Leffler             break;
4461de50e9fSSam Leffler 
4471de50e9fSSam Leffler             /*
4481de50e9fSSam Leffler              * FIXME those are the defined TLVs that lack a decoder
4491de50e9fSSam Leffler              * you are welcome to contribute code ;-)
4501de50e9fSSam Leffler              */
4511de50e9fSSam Leffler 
4521de50e9fSSam Leffler         case EIGRP_TLV_AUTH:
4531de50e9fSSam Leffler         case EIGRP_TLV_SEQ:
4541de50e9fSSam Leffler         case EIGRP_TLV_MCAST_SEQ:
4551de50e9fSSam Leffler         case EIGRP_TLV_IPX_INT:
4561de50e9fSSam Leffler         case EIGRP_TLV_IPX_EXT:
4571de50e9fSSam Leffler 
4581de50e9fSSam Leffler         default:
4593c602fabSXin LI             if (ndo->ndo_vflag <= 1)
4603c602fabSXin LI                 print_unknown_data(ndo,tlv_tptr,"\n\t    ",tlv_tlen);
4611de50e9fSSam Leffler             break;
4621de50e9fSSam Leffler         }
4631de50e9fSSam Leffler         /* do we want to see an additionally hexdump ? */
4643c602fabSXin LI         if (ndo->ndo_vflag > 1)
4653c602fabSXin LI             print_unknown_data(ndo,tptr+sizeof(struct eigrp_tlv_header),"\n\t    ",
4661de50e9fSSam Leffler                                eigrp_tlv_len-sizeof(struct eigrp_tlv_header));
4671de50e9fSSam Leffler 
4681de50e9fSSam Leffler         tptr+=eigrp_tlv_len;
4691de50e9fSSam Leffler         tlen-=eigrp_tlv_len;
4701de50e9fSSam Leffler     }
4711de50e9fSSam Leffler     return;
4721de50e9fSSam Leffler trunc:
4733c602fabSXin LI     ND_PRINT((ndo, "\n\t\t packet exceeded snapshot"));
4741de50e9fSSam Leffler }
475