xref: /freebsd/contrib/tcpdump/print-eigrp.c (revision 0bff6a5af8cb6d8e5123f8b667df78cac885dbb7)
11de50e9fSSam Leffler /*
2*0bff6a5aSEd Maste  * Copyright (c) 1998-2004  Hannes Gredler <hannes@gredler.at>
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 
173340d773SGleb Smirnoff /* \summary: Enhanced Interior Gateway Routing Protocol (EIGRP) printer */
183340d773SGleb Smirnoff 
191de50e9fSSam Leffler #ifdef HAVE_CONFIG_H
201de50e9fSSam Leffler #include "config.h"
211de50e9fSSam Leffler #endif
221de50e9fSSam Leffler 
233340d773SGleb Smirnoff #include <netdissect-stdinc.h>
241de50e9fSSam Leffler 
251de50e9fSSam Leffler #include <string.h>
261de50e9fSSam Leffler 
273340d773SGleb 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
34*0bff6a5aSEd Maste  * RFC 7868
351de50e9fSSam Leffler  */
361de50e9fSSam Leffler 
371de50e9fSSam Leffler struct eigrp_common_header {
383c602fabSXin LI     uint8_t version;
393c602fabSXin LI     uint8_t opcode;
403c602fabSXin LI     uint8_t checksum[2];
413c602fabSXin LI     uint8_t flags[4];
423c602fabSXin LI     uint8_t seq[4];
433c602fabSXin LI     uint8_t ack[4];
443c602fabSXin LI     uint8_t asn[4];
451de50e9fSSam Leffler };
461de50e9fSSam Leffler 
471de50e9fSSam Leffler #define	EIGRP_VERSION                        2
481de50e9fSSam Leffler 
491de50e9fSSam Leffler #define	EIGRP_OPCODE_UPDATE                  1
501de50e9fSSam Leffler #define	EIGRP_OPCODE_QUERY                   3
511de50e9fSSam Leffler #define	EIGRP_OPCODE_REPLY                   4
521de50e9fSSam Leffler #define	EIGRP_OPCODE_HELLO                   5
531de50e9fSSam Leffler #define	EIGRP_OPCODE_IPXSAP                  6
541de50e9fSSam Leffler #define	EIGRP_OPCODE_PROBE                   7
551de50e9fSSam Leffler 
561de50e9fSSam Leffler static const struct tok eigrp_opcode_values[] = {
571de50e9fSSam Leffler     { EIGRP_OPCODE_UPDATE, "Update" },
581de50e9fSSam Leffler     { EIGRP_OPCODE_QUERY, "Query" },
591de50e9fSSam Leffler     { EIGRP_OPCODE_REPLY, "Reply" },
601de50e9fSSam Leffler     { EIGRP_OPCODE_HELLO, "Hello" },
611de50e9fSSam Leffler     { EIGRP_OPCODE_IPXSAP, "IPX SAP" },
621de50e9fSSam Leffler     { EIGRP_OPCODE_PROBE, "Probe" },
631de50e9fSSam Leffler     { 0, NULL}
641de50e9fSSam Leffler };
651de50e9fSSam Leffler 
661de50e9fSSam Leffler static const struct tok eigrp_common_header_flag_values[] = {
671de50e9fSSam Leffler     { 0x01, "Init" },
681de50e9fSSam Leffler     { 0x02, "Conditionally Received" },
691de50e9fSSam Leffler     { 0, NULL}
701de50e9fSSam Leffler };
711de50e9fSSam Leffler 
721de50e9fSSam Leffler struct eigrp_tlv_header {
733c602fabSXin LI     uint8_t type[2];
743c602fabSXin LI     uint8_t length[2];
751de50e9fSSam Leffler };
761de50e9fSSam Leffler 
771de50e9fSSam Leffler #define EIGRP_TLV_GENERAL_PARM   0x0001
781de50e9fSSam Leffler #define EIGRP_TLV_AUTH           0x0002
791de50e9fSSam Leffler #define EIGRP_TLV_SEQ            0x0003
801de50e9fSSam Leffler #define EIGRP_TLV_SW_VERSION     0x0004
811de50e9fSSam Leffler #define EIGRP_TLV_MCAST_SEQ      0x0005
821de50e9fSSam Leffler #define EIGRP_TLV_IP_INT         0x0102
831de50e9fSSam Leffler #define EIGRP_TLV_IP_EXT         0x0103
841de50e9fSSam Leffler #define EIGRP_TLV_AT_INT         0x0202
851de50e9fSSam Leffler #define EIGRP_TLV_AT_EXT         0x0203
861de50e9fSSam Leffler #define EIGRP_TLV_AT_CABLE_SETUP 0x0204
871de50e9fSSam Leffler #define EIGRP_TLV_IPX_INT        0x0302
881de50e9fSSam Leffler #define EIGRP_TLV_IPX_EXT        0x0303
891de50e9fSSam Leffler 
901de50e9fSSam Leffler static const struct tok eigrp_tlv_values[] = {
911de50e9fSSam Leffler     { EIGRP_TLV_GENERAL_PARM, "General Parameters"},
921de50e9fSSam Leffler     { EIGRP_TLV_AUTH, "Authentication"},
931de50e9fSSam Leffler     { EIGRP_TLV_SEQ, "Sequence"},
941de50e9fSSam Leffler     { EIGRP_TLV_SW_VERSION, "Software Version"},
951de50e9fSSam Leffler     { EIGRP_TLV_MCAST_SEQ, "Next Multicast Sequence"},
961de50e9fSSam Leffler     { EIGRP_TLV_IP_INT, "IP Internal routes"},
971de50e9fSSam Leffler     { EIGRP_TLV_IP_EXT, "IP External routes"},
981de50e9fSSam Leffler     { EIGRP_TLV_AT_INT, "AppleTalk Internal routes"},
991de50e9fSSam Leffler     { EIGRP_TLV_AT_EXT, "AppleTalk External routes"},
1001de50e9fSSam Leffler     { EIGRP_TLV_AT_CABLE_SETUP, "AppleTalk Cable setup"},
1011de50e9fSSam Leffler     { EIGRP_TLV_IPX_INT, "IPX Internal routes"},
1021de50e9fSSam Leffler     { EIGRP_TLV_IPX_EXT, "IPX External routes"},
1031de50e9fSSam Leffler     { 0, NULL}
1041de50e9fSSam Leffler };
1051de50e9fSSam Leffler 
1061de50e9fSSam Leffler struct eigrp_tlv_general_parm_t {
1073c602fabSXin LI     uint8_t k1;
1083c602fabSXin LI     uint8_t k2;
1093c602fabSXin LI     uint8_t k3;
1103c602fabSXin LI     uint8_t k4;
1113c602fabSXin LI     uint8_t k5;
1123c602fabSXin LI     uint8_t res;
1133c602fabSXin LI     uint8_t holdtime[2];
1141de50e9fSSam Leffler };
1151de50e9fSSam Leffler 
1161de50e9fSSam Leffler struct eigrp_tlv_sw_version_t {
1173c602fabSXin LI     uint8_t ios_major;
1183c602fabSXin LI     uint8_t ios_minor;
1193c602fabSXin LI     uint8_t eigrp_major;
1203c602fabSXin LI     uint8_t eigrp_minor;
1211de50e9fSSam Leffler };
1221de50e9fSSam Leffler 
1231de50e9fSSam Leffler struct eigrp_tlv_ip_int_t {
1243c602fabSXin LI     uint8_t nexthop[4];
1253c602fabSXin LI     uint8_t delay[4];
1263c602fabSXin LI     uint8_t bandwidth[4];
1273c602fabSXin LI     uint8_t mtu[3];
1283c602fabSXin LI     uint8_t hopcount;
1293c602fabSXin LI     uint8_t reliability;
1303c602fabSXin LI     uint8_t load;
1313c602fabSXin LI     uint8_t reserved[2];
1323c602fabSXin LI     uint8_t plen;
1333c602fabSXin LI     uint8_t destination; /* variable length [1-4] bytes encoding */
1341de50e9fSSam Leffler };
1351de50e9fSSam Leffler 
1361de50e9fSSam Leffler struct eigrp_tlv_ip_ext_t {
1373c602fabSXin LI     uint8_t nexthop[4];
1383c602fabSXin LI     uint8_t origin_router[4];
1393c602fabSXin LI     uint8_t origin_as[4];
1403c602fabSXin LI     uint8_t tag[4];
1413c602fabSXin LI     uint8_t metric[4];
1423c602fabSXin LI     uint8_t reserved[2];
1433c602fabSXin LI     uint8_t proto_id;
1443c602fabSXin LI     uint8_t flags;
1453c602fabSXin LI     uint8_t delay[4];
1463c602fabSXin LI     uint8_t bandwidth[4];
1473c602fabSXin LI     uint8_t mtu[3];
1483c602fabSXin LI     uint8_t hopcount;
1493c602fabSXin LI     uint8_t reliability;
1503c602fabSXin LI     uint8_t load;
1513c602fabSXin LI     uint8_t reserved2[2];
1523c602fabSXin LI     uint8_t plen;
1533c602fabSXin LI     uint8_t destination; /* variable length [1-4] bytes encoding */
1541de50e9fSSam Leffler };
1551de50e9fSSam Leffler 
1561de50e9fSSam Leffler struct eigrp_tlv_at_cable_setup_t {
1573c602fabSXin LI     uint8_t cable_start[2];
1583c602fabSXin LI     uint8_t cable_end[2];
1593c602fabSXin LI     uint8_t router_id[4];
1601de50e9fSSam Leffler };
1611de50e9fSSam Leffler 
1621de50e9fSSam Leffler struct eigrp_tlv_at_int_t {
1633c602fabSXin LI     uint8_t nexthop[4];
1643c602fabSXin LI     uint8_t delay[4];
1653c602fabSXin LI     uint8_t bandwidth[4];
1663c602fabSXin LI     uint8_t mtu[3];
1673c602fabSXin LI     uint8_t hopcount;
1683c602fabSXin LI     uint8_t reliability;
1693c602fabSXin LI     uint8_t load;
1703c602fabSXin LI     uint8_t reserved[2];
1713c602fabSXin LI     uint8_t cable_start[2];
1723c602fabSXin LI     uint8_t cable_end[2];
1731de50e9fSSam Leffler };
1741de50e9fSSam Leffler 
1751de50e9fSSam Leffler struct eigrp_tlv_at_ext_t {
1763c602fabSXin LI     uint8_t nexthop[4];
1773c602fabSXin LI     uint8_t origin_router[4];
1783c602fabSXin LI     uint8_t origin_as[4];
1793c602fabSXin LI     uint8_t tag[4];
1803c602fabSXin LI     uint8_t proto_id;
1813c602fabSXin LI     uint8_t flags;
1823c602fabSXin LI     uint8_t metric[2];
1833c602fabSXin LI     uint8_t delay[4];
1843c602fabSXin LI     uint8_t bandwidth[4];
1853c602fabSXin LI     uint8_t mtu[3];
1863c602fabSXin LI     uint8_t hopcount;
1873c602fabSXin LI     uint8_t reliability;
1883c602fabSXin LI     uint8_t load;
1893c602fabSXin LI     uint8_t reserved2[2];
1903c602fabSXin LI     uint8_t cable_start[2];
1913c602fabSXin LI     uint8_t cable_end[2];
1921de50e9fSSam Leffler };
1931de50e9fSSam Leffler 
1941de50e9fSSam Leffler static const struct tok eigrp_ext_proto_id_values[] = {
1951de50e9fSSam Leffler     { 0x01, "IGRP" },
1961de50e9fSSam Leffler     { 0x02, "EIGRP" },
1971de50e9fSSam Leffler     { 0x03, "Static" },
1981de50e9fSSam Leffler     { 0x04, "RIP" },
1991de50e9fSSam Leffler     { 0x05, "Hello" },
2001de50e9fSSam Leffler     { 0x06, "OSPF" },
2011de50e9fSSam Leffler     { 0x07, "IS-IS" },
2021de50e9fSSam Leffler     { 0x08, "EGP" },
2031de50e9fSSam Leffler     { 0x09, "BGP" },
2041de50e9fSSam Leffler     { 0x0a, "IDRP" },
2051de50e9fSSam Leffler     { 0x0b, "Connected" },
2061de50e9fSSam Leffler     { 0, NULL}
2071de50e9fSSam Leffler };
2081de50e9fSSam Leffler 
2091de50e9fSSam Leffler void
2108bdc5a62SPatrick Kelsey eigrp_print(netdissect_options *ndo, register const u_char *pptr, register u_int len)
2118bdc5a62SPatrick Kelsey {
2121de50e9fSSam Leffler     const struct eigrp_common_header *eigrp_com_header;
2131de50e9fSSam Leffler     const struct eigrp_tlv_header *eigrp_tlv_header;
2141de50e9fSSam Leffler     const u_char *tptr,*tlv_tptr;
215f4d0c64aSSam Leffler     u_int tlen,eigrp_tlv_len,eigrp_tlv_type,tlv_tlen, byte_length, bit_length;
2163c602fabSXin LI     uint8_t prefix[4];
2171de50e9fSSam Leffler 
2181de50e9fSSam Leffler     union {
2191de50e9fSSam Leffler         const struct eigrp_tlv_general_parm_t *eigrp_tlv_general_parm;
2201de50e9fSSam Leffler         const struct eigrp_tlv_sw_version_t *eigrp_tlv_sw_version;
2211de50e9fSSam Leffler         const struct eigrp_tlv_ip_int_t *eigrp_tlv_ip_int;
2221de50e9fSSam Leffler         const struct eigrp_tlv_ip_ext_t *eigrp_tlv_ip_ext;
2231de50e9fSSam Leffler         const struct eigrp_tlv_at_cable_setup_t *eigrp_tlv_at_cable_setup;
2241de50e9fSSam Leffler         const struct eigrp_tlv_at_int_t *eigrp_tlv_at_int;
2251de50e9fSSam Leffler         const struct eigrp_tlv_at_ext_t *eigrp_tlv_at_ext;
2261de50e9fSSam Leffler     } tlv_ptr;
2271de50e9fSSam Leffler 
2281de50e9fSSam Leffler     tptr=pptr;
2291de50e9fSSam Leffler     eigrp_com_header = (const struct eigrp_common_header *)pptr;
2303c602fabSXin LI     ND_TCHECK(*eigrp_com_header);
2311de50e9fSSam Leffler 
2321de50e9fSSam Leffler     /*
2331de50e9fSSam Leffler      * Sanity checking of the header.
2341de50e9fSSam Leffler      */
2351de50e9fSSam Leffler     if (eigrp_com_header->version != EIGRP_VERSION) {
2363c602fabSXin LI 	ND_PRINT((ndo, "EIGRP version %u packet not supported",eigrp_com_header->version));
2371de50e9fSSam Leffler 	return;
2381de50e9fSSam Leffler     }
2391de50e9fSSam Leffler 
2401de50e9fSSam Leffler     /* in non-verbose mode just lets print the basic Message Type*/
2413c602fabSXin LI     if (ndo->ndo_vflag < 1) {
2423c602fabSXin LI         ND_PRINT((ndo, "EIGRP %s, length: %u",
2431de50e9fSSam Leffler                tok2str(eigrp_opcode_values, "unknown (%u)",eigrp_com_header->opcode),
2443c602fabSXin LI                len));
2451de50e9fSSam Leffler         return;
2461de50e9fSSam Leffler     }
2471de50e9fSSam Leffler 
2481de50e9fSSam Leffler     /* ok they seem to want to know everything - lets fully decode it */
2491de50e9fSSam Leffler 
250*0bff6a5aSEd Maste     if (len < sizeof(struct eigrp_common_header)) {
251*0bff6a5aSEd Maste         ND_PRINT((ndo, "EIGRP %s, length: %u (too short, < %u)",
252*0bff6a5aSEd Maste                tok2str(eigrp_opcode_values, "unknown (%u)",eigrp_com_header->opcode),
253*0bff6a5aSEd Maste                len, (u_int) sizeof(struct eigrp_common_header)));
254*0bff6a5aSEd Maste         return;
255*0bff6a5aSEd Maste     }
2561de50e9fSSam Leffler     tlen=len-sizeof(struct eigrp_common_header);
2571de50e9fSSam Leffler 
2581de50e9fSSam Leffler     /* FIXME print other header info */
2593c602fabSXin 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",
2601de50e9fSSam Leffler            eigrp_com_header->version,
2611de50e9fSSam Leffler            tok2str(eigrp_opcode_values, "unknown, type: %u",eigrp_com_header->opcode),
2621de50e9fSSam Leffler            eigrp_com_header->opcode,
2631de50e9fSSam Leffler            EXTRACT_16BITS(&eigrp_com_header->checksum),
2641de50e9fSSam Leffler            tok2str(eigrp_common_header_flag_values,
2651de50e9fSSam Leffler                    "none",
2661de50e9fSSam Leffler                    EXTRACT_32BITS(&eigrp_com_header->flags)),
2671de50e9fSSam Leffler            EXTRACT_32BITS(&eigrp_com_header->seq),
2681de50e9fSSam Leffler            EXTRACT_32BITS(&eigrp_com_header->ack),
2691de50e9fSSam Leffler            EXTRACT_32BITS(&eigrp_com_header->asn),
2703c602fabSXin LI            tlen));
2711de50e9fSSam Leffler 
2721de50e9fSSam Leffler     tptr+=sizeof(const struct eigrp_common_header);
2731de50e9fSSam Leffler 
2741de50e9fSSam Leffler     while(tlen>0) {
2751de50e9fSSam Leffler         /* did we capture enough for fully decoding the object header ? */
2763c602fabSXin LI         ND_TCHECK2(*tptr, sizeof(struct eigrp_tlv_header));
2771de50e9fSSam Leffler 
2781de50e9fSSam Leffler         eigrp_tlv_header = (const struct eigrp_tlv_header *)tptr;
2791de50e9fSSam Leffler         eigrp_tlv_len=EXTRACT_16BITS(&eigrp_tlv_header->length);
2801de50e9fSSam Leffler         eigrp_tlv_type=EXTRACT_16BITS(&eigrp_tlv_header->type);
2811de50e9fSSam Leffler 
2821de50e9fSSam Leffler 
283f4d0c64aSSam Leffler         if (eigrp_tlv_len < sizeof(struct eigrp_tlv_header) ||
284f4d0c64aSSam Leffler             eigrp_tlv_len > tlen) {
2853c602fabSXin LI             print_unknown_data(ndo,tptr+sizeof(struct eigrp_tlv_header),"\n\t    ",tlen);
2861de50e9fSSam Leffler             return;
2871de50e9fSSam Leffler         }
2881de50e9fSSam Leffler 
2893c602fabSXin LI         ND_PRINT((ndo, "\n\t  %s TLV (0x%04x), length: %u",
2901de50e9fSSam Leffler                tok2str(eigrp_tlv_values,
2911de50e9fSSam Leffler                        "Unknown",
2921de50e9fSSam Leffler                        eigrp_tlv_type),
2931de50e9fSSam Leffler                eigrp_tlv_type,
2943c602fabSXin LI                eigrp_tlv_len));
2951de50e9fSSam Leffler 
296*0bff6a5aSEd Maste         if (eigrp_tlv_len < sizeof(struct eigrp_tlv_header)) {
297*0bff6a5aSEd Maste                 ND_PRINT((ndo, " (too short, < %u)",
298*0bff6a5aSEd Maste                         (u_int) sizeof(struct eigrp_tlv_header)));
299*0bff6a5aSEd Maste                 break;
300*0bff6a5aSEd Maste         }
3011de50e9fSSam Leffler         tlv_tptr=tptr+sizeof(struct eigrp_tlv_header);
3021de50e9fSSam Leffler         tlv_tlen=eigrp_tlv_len-sizeof(struct eigrp_tlv_header);
3031de50e9fSSam Leffler 
3041de50e9fSSam Leffler         /* did we capture enough for fully decoding the object ? */
3053c602fabSXin LI         ND_TCHECK2(*tptr, eigrp_tlv_len);
3061de50e9fSSam Leffler 
3071de50e9fSSam Leffler         switch(eigrp_tlv_type) {
3081de50e9fSSam Leffler 
3091de50e9fSSam Leffler         case EIGRP_TLV_GENERAL_PARM:
3101de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_general_parm = (const struct eigrp_tlv_general_parm_t *)tlv_tptr;
311*0bff6a5aSEd Maste             if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_general_parm)) {
312*0bff6a5aSEd Maste                 ND_PRINT((ndo, " (too short, < %u)",
313*0bff6a5aSEd Maste                     (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_general_parm))));
314*0bff6a5aSEd Maste                 break;
315*0bff6a5aSEd Maste             }
3161de50e9fSSam Leffler 
3173c602fabSXin LI             ND_PRINT((ndo, "\n\t    holdtime: %us, k1 %u, k2 %u, k3 %u, k4 %u, k5 %u",
3181de50e9fSSam Leffler                    EXTRACT_16BITS(tlv_ptr.eigrp_tlv_general_parm->holdtime),
3191de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_general_parm->k1,
3201de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_general_parm->k2,
3211de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_general_parm->k3,
3221de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_general_parm->k4,
3233c602fabSXin LI                    tlv_ptr.eigrp_tlv_general_parm->k5));
3241de50e9fSSam Leffler             break;
3251de50e9fSSam Leffler 
3261de50e9fSSam Leffler         case EIGRP_TLV_SW_VERSION:
3271de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_sw_version = (const struct eigrp_tlv_sw_version_t *)tlv_tptr;
328*0bff6a5aSEd Maste             if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_sw_version)) {
329*0bff6a5aSEd Maste                 ND_PRINT((ndo, " (too short, < %u)",
330*0bff6a5aSEd Maste                     (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_sw_version))));
331*0bff6a5aSEd Maste                 break;
332*0bff6a5aSEd Maste             }
3331de50e9fSSam Leffler 
3343c602fabSXin LI             ND_PRINT((ndo, "\n\t    IOS version: %u.%u, EIGRP version %u.%u",
3351de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_sw_version->ios_major,
3361de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_sw_version->ios_minor,
3371de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_sw_version->eigrp_major,
3383c602fabSXin LI                    tlv_ptr.eigrp_tlv_sw_version->eigrp_minor));
3391de50e9fSSam Leffler             break;
3401de50e9fSSam Leffler 
3411de50e9fSSam Leffler         case EIGRP_TLV_IP_INT:
3421de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_ip_int = (const struct eigrp_tlv_ip_int_t *)tlv_tptr;
343*0bff6a5aSEd Maste             if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_ip_int)) {
344*0bff6a5aSEd Maste                 ND_PRINT((ndo, " (too short, < %u)",
345*0bff6a5aSEd Maste                     (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_ip_int))));
346*0bff6a5aSEd Maste                 break;
347*0bff6a5aSEd Maste             }
3481de50e9fSSam Leffler 
3491de50e9fSSam Leffler             bit_length = tlv_ptr.eigrp_tlv_ip_int->plen;
350f4d0c64aSSam Leffler             if (bit_length > 32) {
3513c602fabSXin LI                 ND_PRINT((ndo, "\n\t    illegal prefix length %u",bit_length));
3521de50e9fSSam Leffler                 break;
3531de50e9fSSam Leffler             }
3541de50e9fSSam Leffler             byte_length = (bit_length + 7) / 8; /* variable length encoding */
3551de50e9fSSam Leffler             memset(prefix, 0, 4);
3561de50e9fSSam Leffler             memcpy(prefix,&tlv_ptr.eigrp_tlv_ip_int->destination,byte_length);
3571de50e9fSSam Leffler 
3583c602fabSXin LI             ND_PRINT((ndo, "\n\t    IPv4 prefix: %15s/%u, nexthop: ",
3593c602fabSXin LI                    ipaddr_string(ndo, prefix),
3603c602fabSXin LI                    bit_length));
3611de50e9fSSam Leffler             if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->nexthop) == 0)
3623c602fabSXin LI                 ND_PRINT((ndo, "self"));
3631de50e9fSSam Leffler             else
3643c602fabSXin LI                 ND_PRINT((ndo, "%s",ipaddr_string(ndo, &tlv_ptr.eigrp_tlv_ip_int->nexthop)));
3651de50e9fSSam Leffler 
3663c602fabSXin LI             ND_PRINT((ndo, "\n\t      delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
3671de50e9fSSam Leffler                    (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->delay)/100),
3681de50e9fSSam Leffler                    EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->bandwidth),
3691de50e9fSSam Leffler                    EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_ip_int->mtu),
3701de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_ip_int->hopcount,
3711de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_ip_int->reliability,
3723c602fabSXin LI                    tlv_ptr.eigrp_tlv_ip_int->load));
3731de50e9fSSam Leffler             break;
3741de50e9fSSam Leffler 
3751de50e9fSSam Leffler         case EIGRP_TLV_IP_EXT:
3761de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_ip_ext = (const struct eigrp_tlv_ip_ext_t *)tlv_tptr;
377*0bff6a5aSEd Maste             if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_ip_ext)) {
378*0bff6a5aSEd Maste                 ND_PRINT((ndo, " (too short, < %u)",
379*0bff6a5aSEd Maste                     (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_ip_ext))));
380*0bff6a5aSEd Maste                 break;
381*0bff6a5aSEd Maste             }
3821de50e9fSSam Leffler 
3831de50e9fSSam Leffler             bit_length = tlv_ptr.eigrp_tlv_ip_ext->plen;
384f4d0c64aSSam Leffler             if (bit_length > 32) {
3853c602fabSXin LI                 ND_PRINT((ndo, "\n\t    illegal prefix length %u",bit_length));
3861de50e9fSSam Leffler                 break;
3871de50e9fSSam Leffler             }
3881de50e9fSSam Leffler             byte_length = (bit_length + 7) / 8; /* variable length encoding */
3891de50e9fSSam Leffler             memset(prefix, 0, 4);
3901de50e9fSSam Leffler             memcpy(prefix,&tlv_ptr.eigrp_tlv_ip_ext->destination,byte_length);
3911de50e9fSSam Leffler 
3923c602fabSXin LI             ND_PRINT((ndo, "\n\t    IPv4 prefix: %15s/%u, nexthop: ",
3933c602fabSXin LI                    ipaddr_string(ndo, prefix),
3943c602fabSXin LI                    bit_length));
3951de50e9fSSam Leffler             if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->nexthop) == 0)
3963c602fabSXin LI                 ND_PRINT((ndo, "self"));
3971de50e9fSSam Leffler             else
3983c602fabSXin LI                 ND_PRINT((ndo, "%s",ipaddr_string(ndo, &tlv_ptr.eigrp_tlv_ip_ext->nexthop)));
3991de50e9fSSam Leffler 
4003c602fabSXin LI             ND_PRINT((ndo, "\n\t      origin-router %s, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u",
4013c602fabSXin LI                    ipaddr_string(ndo, tlv_ptr.eigrp_tlv_ip_ext->origin_router),
4021de50e9fSSam Leffler                    EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->origin_as),
4031de50e9fSSam Leffler                    tok2str(eigrp_ext_proto_id_values,"unknown",tlv_ptr.eigrp_tlv_ip_ext->proto_id),
4041de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_ip_ext->flags,
4051de50e9fSSam Leffler                    EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->tag),
4063c602fabSXin LI                    EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->metric)));
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_ip_ext->delay)/100),
4101de50e9fSSam Leffler                    EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->bandwidth),
4111de50e9fSSam Leffler                    EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_ip_ext->mtu),
4121de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_ip_ext->hopcount,
4131de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_ip_ext->reliability,
4143c602fabSXin LI                    tlv_ptr.eigrp_tlv_ip_ext->load));
4151de50e9fSSam Leffler             break;
4161de50e9fSSam Leffler 
4171de50e9fSSam Leffler         case EIGRP_TLV_AT_CABLE_SETUP:
4181de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_at_cable_setup = (const struct eigrp_tlv_at_cable_setup_t *)tlv_tptr;
419*0bff6a5aSEd Maste             if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_cable_setup)) {
420*0bff6a5aSEd Maste                 ND_PRINT((ndo, " (too short, < %u)",
421*0bff6a5aSEd Maste                     (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_cable_setup))));
422*0bff6a5aSEd Maste                 break;
423*0bff6a5aSEd Maste             }
4241de50e9fSSam Leffler 
4253c602fabSXin LI             ND_PRINT((ndo, "\n\t    Cable-range: %u-%u, Router-ID %u",
4261de50e9fSSam Leffler                    EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->cable_start),
4271de50e9fSSam Leffler                    EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->cable_end),
4283c602fabSXin LI                    EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->router_id)));
4291de50e9fSSam Leffler             break;
4301de50e9fSSam Leffler 
4311de50e9fSSam Leffler         case EIGRP_TLV_AT_INT:
4321de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_at_int = (const struct eigrp_tlv_at_int_t *)tlv_tptr;
433*0bff6a5aSEd Maste             if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_int)) {
434*0bff6a5aSEd Maste                 ND_PRINT((ndo, " (too short, < %u)",
435*0bff6a5aSEd Maste                     (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_int))));
436*0bff6a5aSEd Maste                 break;
437*0bff6a5aSEd Maste             }
4381de50e9fSSam Leffler 
4393c602fabSXin LI             ND_PRINT((ndo, "\n\t     Cable-Range: %u-%u, nexthop: ",
4401de50e9fSSam Leffler                    EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->cable_start),
4413c602fabSXin LI                    EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->cable_end)));
4421de50e9fSSam Leffler 
4431de50e9fSSam Leffler             if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop) == 0)
4443c602fabSXin LI                 ND_PRINT((ndo, "self"));
4451de50e9fSSam Leffler             else
4463c602fabSXin LI                 ND_PRINT((ndo, "%u.%u",
4471de50e9fSSam Leffler                        EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop),
4483c602fabSXin LI                        EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop[2])));
4491de50e9fSSam Leffler 
4503c602fabSXin LI             ND_PRINT((ndo, "\n\t      delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
4511de50e9fSSam Leffler                    (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->delay)/100),
4521de50e9fSSam Leffler                    EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->bandwidth),
4531de50e9fSSam Leffler                    EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_at_int->mtu),
4541de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_at_int->hopcount,
4551de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_at_int->reliability,
4563c602fabSXin LI                    tlv_ptr.eigrp_tlv_at_int->load));
4571de50e9fSSam Leffler             break;
4581de50e9fSSam Leffler 
4591de50e9fSSam Leffler         case EIGRP_TLV_AT_EXT:
4601de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_at_ext = (const struct eigrp_tlv_at_ext_t *)tlv_tptr;
461*0bff6a5aSEd Maste             if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_ext)) {
462*0bff6a5aSEd Maste                 ND_PRINT((ndo, " (too short, < %u)",
463*0bff6a5aSEd Maste                     (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_ext))));
464*0bff6a5aSEd Maste                 break;
465*0bff6a5aSEd Maste             }
4661de50e9fSSam Leffler 
4673c602fabSXin LI             ND_PRINT((ndo, "\n\t     Cable-Range: %u-%u, nexthop: ",
4681de50e9fSSam Leffler                    EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->cable_start),
4693c602fabSXin LI                    EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->cable_end)));
4701de50e9fSSam Leffler 
4711de50e9fSSam Leffler             if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop) == 0)
4723c602fabSXin LI                 ND_PRINT((ndo, "self"));
4731de50e9fSSam Leffler             else
4743c602fabSXin LI                 ND_PRINT((ndo, "%u.%u",
4751de50e9fSSam Leffler                        EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop),
4763c602fabSXin LI                        EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop[2])));
4771de50e9fSSam Leffler 
4783c602fabSXin LI             ND_PRINT((ndo, "\n\t      origin-router %u, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u",
4791de50e9fSSam Leffler                    EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->origin_router),
4801de50e9fSSam Leffler                    EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->origin_as),
4811de50e9fSSam Leffler                    tok2str(eigrp_ext_proto_id_values,"unknown",tlv_ptr.eigrp_tlv_at_ext->proto_id),
4821de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_at_ext->flags,
4831de50e9fSSam Leffler                    EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->tag),
4843c602fabSXin LI                    EXTRACT_16BITS(tlv_ptr.eigrp_tlv_at_ext->metric)));
4851de50e9fSSam Leffler 
4863c602fabSXin LI             ND_PRINT((ndo, "\n\t      delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
4871de50e9fSSam Leffler                    (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->delay)/100),
4881de50e9fSSam Leffler                    EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->bandwidth),
4891de50e9fSSam Leffler                    EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_at_ext->mtu),
4901de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_at_ext->hopcount,
4911de50e9fSSam Leffler                    tlv_ptr.eigrp_tlv_at_ext->reliability,
4923c602fabSXin LI                    tlv_ptr.eigrp_tlv_at_ext->load));
4931de50e9fSSam Leffler             break;
4941de50e9fSSam Leffler 
4951de50e9fSSam Leffler             /*
4961de50e9fSSam Leffler              * FIXME those are the defined TLVs that lack a decoder
4971de50e9fSSam Leffler              * you are welcome to contribute code ;-)
4981de50e9fSSam Leffler              */
4991de50e9fSSam Leffler 
5001de50e9fSSam Leffler         case EIGRP_TLV_AUTH:
5011de50e9fSSam Leffler         case EIGRP_TLV_SEQ:
5021de50e9fSSam Leffler         case EIGRP_TLV_MCAST_SEQ:
5031de50e9fSSam Leffler         case EIGRP_TLV_IPX_INT:
5041de50e9fSSam Leffler         case EIGRP_TLV_IPX_EXT:
5051de50e9fSSam Leffler 
5061de50e9fSSam Leffler         default:
5073c602fabSXin LI             if (ndo->ndo_vflag <= 1)
5083c602fabSXin LI                 print_unknown_data(ndo,tlv_tptr,"\n\t    ",tlv_tlen);
5091de50e9fSSam Leffler             break;
5101de50e9fSSam Leffler         }
5111de50e9fSSam Leffler         /* do we want to see an additionally hexdump ? */
5123c602fabSXin LI         if (ndo->ndo_vflag > 1)
5133c602fabSXin LI             print_unknown_data(ndo,tptr+sizeof(struct eigrp_tlv_header),"\n\t    ",
5141de50e9fSSam Leffler                                eigrp_tlv_len-sizeof(struct eigrp_tlv_header));
5151de50e9fSSam Leffler 
5161de50e9fSSam Leffler         tptr+=eigrp_tlv_len;
5171de50e9fSSam Leffler         tlen-=eigrp_tlv_len;
5181de50e9fSSam Leffler     }
5191de50e9fSSam Leffler     return;
5201de50e9fSSam Leffler trunc:
5213c602fabSXin LI     ND_PRINT((ndo, "\n\t\t packet exceeded snapshot"));
5221de50e9fSSam Leffler }
523