"Fossies" - the Fresh Open Source Software Archive

Member "tcpdump-4.99.1/./print-eigrp.c" (7 Jun 2021, 20161 Bytes) of package /linux/misc/tcpdump-4.99.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "print-eigrp.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 4.99.0_vs_4.99.1.

    1 /*
    2  * Copyright (c) 1998-2004  Hannes Gredler <hannes@gredler.at>
    3  *      The TCPDUMP project
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that: (1) source code
    7  * distributions retain the above copyright notice and this paragraph
    8  * in its entirety, and (2) distributions including binary code include
    9  * the above copyright notice and this paragraph in its entirety in
   10  * the documentation or other materials provided with the distribution.
   11  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
   12  * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
   13  * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   14  * FOR A PARTICULAR PURPOSE.
   15  */
   16 
   17 /* \summary: Enhanced Interior Gateway Routing Protocol (EIGRP) printer */
   18 
   19 /*
   20  * specification:
   21  *
   22  * https://web.archive.org/web/20190722221712/https://www.rhyshaden.com/eigrp.htm
   23  * RFC 7868
   24  */
   25 
   26 #ifdef HAVE_CONFIG_H
   27 #include <config.h>
   28 #endif
   29 
   30 #include "netdissect-stdinc.h"
   31 
   32 #include <string.h>
   33 
   34 #include "netdissect.h"
   35 #include "extract.h"
   36 #include "addrtoname.h"
   37 
   38 
   39 struct eigrp_common_header {
   40     nd_uint8_t  version;
   41     nd_uint8_t  opcode;
   42     nd_uint16_t checksum;
   43     nd_uint32_t flags;
   44     nd_uint32_t seq;
   45     nd_uint32_t ack;
   46     nd_uint16_t vrid;
   47     nd_uint16_t asn;
   48 };
   49 
   50 #define EIGRP_VERSION                        2
   51 
   52 #define EIGRP_OPCODE_UPDATE                  1
   53 #define EIGRP_OPCODE_QUERY                   3
   54 #define EIGRP_OPCODE_REPLY                   4
   55 #define EIGRP_OPCODE_HELLO                   5
   56 #define EIGRP_OPCODE_IPXSAP                  6
   57 #define EIGRP_OPCODE_PROBE                   7
   58 
   59 static const struct tok eigrp_opcode_values[] = {
   60     { EIGRP_OPCODE_UPDATE, "Update" },
   61     { EIGRP_OPCODE_QUERY, "Query" },
   62     { EIGRP_OPCODE_REPLY, "Reply" },
   63     { EIGRP_OPCODE_HELLO, "Hello" },
   64     { EIGRP_OPCODE_IPXSAP, "IPX SAP" },
   65     { EIGRP_OPCODE_PROBE, "Probe" },
   66     { 0, NULL}
   67 };
   68 
   69 static const struct tok eigrp_common_header_flag_values[] = {
   70     { 0x01, "Init" },
   71     { 0x02, "Conditionally Received" },
   72     { 0x04, "Restart" },
   73     { 0x08, "End-of-Table" },
   74     { 0, NULL}
   75 };
   76 
   77 struct eigrp_tlv_header {
   78     nd_uint16_t type;
   79     nd_uint16_t length;
   80 };
   81 
   82 #define EIGRP_TLV_GENERAL_PARM   0x0001
   83 #define EIGRP_TLV_AUTH           0x0002
   84 #define EIGRP_TLV_SEQ            0x0003
   85 #define EIGRP_TLV_SW_VERSION     0x0004
   86 #define EIGRP_TLV_MCAST_SEQ      0x0005
   87 #define EIGRP_TLV_IP_INT         0x0102
   88 #define EIGRP_TLV_IP_EXT         0x0103
   89 #define EIGRP_TLV_AT_INT         0x0202
   90 #define EIGRP_TLV_AT_EXT         0x0203
   91 #define EIGRP_TLV_AT_CABLE_SETUP 0x0204
   92 #define EIGRP_TLV_IPX_INT        0x0302
   93 #define EIGRP_TLV_IPX_EXT        0x0303
   94 
   95 static const struct tok eigrp_tlv_values[] = {
   96     { EIGRP_TLV_GENERAL_PARM, "General Parameters"},
   97     { EIGRP_TLV_AUTH, "Authentication"},
   98     { EIGRP_TLV_SEQ, "Sequence"},
   99     { EIGRP_TLV_SW_VERSION, "Software Version"},
  100     { EIGRP_TLV_MCAST_SEQ, "Next Multicast Sequence"},
  101     { EIGRP_TLV_IP_INT, "IP Internal routes"},
  102     { EIGRP_TLV_IP_EXT, "IP External routes"},
  103     { EIGRP_TLV_AT_INT, "AppleTalk Internal routes"},
  104     { EIGRP_TLV_AT_EXT, "AppleTalk External routes"},
  105     { EIGRP_TLV_AT_CABLE_SETUP, "AppleTalk Cable setup"},
  106     { EIGRP_TLV_IPX_INT, "IPX Internal routes"},
  107     { EIGRP_TLV_IPX_EXT, "IPX External routes"},
  108     { 0, NULL}
  109 };
  110 
  111 struct eigrp_tlv_general_parm_t {
  112     nd_uint8_t  k1;
  113     nd_uint8_t  k2;
  114     nd_uint8_t  k3;
  115     nd_uint8_t  k4;
  116     nd_uint8_t  k5;
  117     nd_uint8_t  res;
  118     nd_uint16_t holdtime;
  119 };
  120 
  121 struct eigrp_tlv_sw_version_t {
  122     nd_uint8_t ios_major;
  123     nd_uint8_t ios_minor;
  124     nd_uint8_t eigrp_major;
  125     nd_uint8_t eigrp_minor;
  126 };
  127 
  128 struct eigrp_tlv_ip_int_t {
  129     nd_ipv4     nexthop;
  130     nd_uint32_t delay;
  131     nd_uint32_t bandwidth;
  132     nd_uint24_t mtu;
  133     nd_uint8_t  hopcount;
  134     nd_uint8_t  reliability;
  135     nd_uint8_t  load;
  136     nd_byte     reserved[2];
  137     nd_uint8_t  plen;
  138     nd_uint8_t  destination; /* variable length [1-4] bytes encoding */
  139 };
  140 
  141 struct eigrp_tlv_ip_ext_t {
  142     nd_ipv4     nexthop;
  143     nd_ipv4     origin_router;
  144     nd_uint32_t origin_as;
  145     nd_uint32_t tag;
  146     nd_uint32_t metric;
  147     nd_byte     reserved[2];
  148     nd_uint8_t  proto_id;
  149     nd_uint8_t  flags;
  150     nd_uint32_t delay;
  151     nd_uint32_t bandwidth;
  152     nd_uint24_t mtu;
  153     nd_uint8_t  hopcount;
  154     nd_uint8_t  reliability;
  155     nd_uint8_t  load;
  156     nd_byte     reserved2[2];
  157     nd_uint8_t  plen;
  158     nd_uint8_t  destination; /* variable length [1-4] bytes encoding */
  159 };
  160 
  161 struct eigrp_tlv_at_cable_setup_t {
  162     nd_uint16_t cable_start;
  163     nd_uint16_t cable_end;
  164     nd_uint32_t router_id;
  165 };
  166 
  167 struct eigrp_tlv_at_int_t {
  168     nd_byte     nexthop[4];
  169     nd_uint32_t delay;
  170     nd_uint32_t bandwidth;
  171     nd_uint24_t mtu;
  172     nd_uint8_t  hopcount;
  173     nd_uint8_t  reliability;
  174     nd_uint8_t  load;
  175     nd_byte     reserved[2];
  176     nd_uint16_t cable_start;
  177     nd_uint16_t cable_end;
  178 };
  179 
  180 struct eigrp_tlv_at_ext_t {
  181     nd_byte     nexthop[4];
  182     nd_uint32_t origin_router;
  183     nd_uint32_t origin_as;
  184     nd_uint32_t tag;
  185     nd_uint8_t  proto_id;
  186     nd_uint8_t  flags;
  187     nd_uint16_t metric;
  188     nd_uint32_t delay;
  189     nd_uint32_t bandwidth;
  190     nd_uint24_t mtu;
  191     nd_uint8_t  hopcount;
  192     nd_uint8_t  reliability;
  193     nd_uint8_t  load;
  194     nd_byte     reserved2[2];
  195     nd_uint16_t cable_start;
  196     nd_uint16_t cable_end;
  197 };
  198 
  199 static const struct tok eigrp_ext_proto_id_values[] = {
  200     { 0x01, "IGRP" },
  201     { 0x02, "EIGRP" },
  202     { 0x03, "Static" },
  203     { 0x04, "RIP" },
  204     { 0x05, "Hello" },
  205     { 0x06, "OSPF" },
  206     { 0x07, "IS-IS" },
  207     { 0x08, "EGP" },
  208     { 0x09, "BGP" },
  209     { 0x0a, "IDRP" },
  210     { 0x0b, "Connected" },
  211     { 0, NULL}
  212 };
  213 
  214 void
  215 eigrp_print(netdissect_options *ndo, const u_char *pptr, u_int len)
  216 {
  217     const struct eigrp_common_header *eigrp_com_header;
  218     const struct eigrp_tlv_header *eigrp_tlv_header;
  219     const u_char *tptr,*tlv_tptr;
  220     u_int tlen,eigrp_tlv_len,eigrp_tlv_type,tlv_tlen, byte_length, bit_length;
  221     uint8_t prefix[4];
  222 
  223     union {
  224         const struct eigrp_tlv_general_parm_t *eigrp_tlv_general_parm;
  225         const struct eigrp_tlv_sw_version_t *eigrp_tlv_sw_version;
  226         const struct eigrp_tlv_ip_int_t *eigrp_tlv_ip_int;
  227         const struct eigrp_tlv_ip_ext_t *eigrp_tlv_ip_ext;
  228         const struct eigrp_tlv_at_cable_setup_t *eigrp_tlv_at_cable_setup;
  229         const struct eigrp_tlv_at_int_t *eigrp_tlv_at_int;
  230         const struct eigrp_tlv_at_ext_t *eigrp_tlv_at_ext;
  231     } tlv_ptr;
  232 
  233     ndo->ndo_protocol = "eigrp";
  234     tptr=pptr;
  235     eigrp_com_header = (const struct eigrp_common_header *)pptr;
  236     ND_TCHECK_SIZE(eigrp_com_header);
  237 
  238     /*
  239      * Sanity checking of the header.
  240      */
  241     if (GET_U_1(eigrp_com_header->version) != EIGRP_VERSION) {
  242         ND_PRINT("EIGRP version %u packet not supported",
  243                  GET_U_1(eigrp_com_header->version));
  244         return;
  245     }
  246 
  247     /* in non-verbose mode just lets print the basic Message Type*/
  248     if (ndo->ndo_vflag < 1) {
  249         ND_PRINT("EIGRP %s, length: %u",
  250                tok2str(eigrp_opcode_values, "unknown (%u)",GET_U_1(eigrp_com_header->opcode)),
  251                len);
  252         return;
  253     }
  254 
  255     /* ok they seem to want to know everything - lets fully decode it */
  256 
  257     if (len < sizeof(struct eigrp_common_header)) {
  258         ND_PRINT("EIGRP %s, length: %u (too short, < %zu)",
  259                tok2str(eigrp_opcode_values, "unknown (%u)",GET_U_1(eigrp_com_header->opcode)),
  260                len, sizeof(struct eigrp_common_header));
  261         return;
  262     }
  263     tlen=len-sizeof(struct eigrp_common_header);
  264 
  265     ND_PRINT("\n\tEIGRP v%u, opcode: %s (%u), chksum: 0x%04x, Flags: [%s]"
  266              "\n\tseq: 0x%08x, ack: 0x%08x, VRID: %u, AS: %u, length: %u",
  267            GET_U_1(eigrp_com_header->version),
  268            tok2str(eigrp_opcode_values, "unknown, type: %u",GET_U_1(eigrp_com_header->opcode)),
  269            GET_U_1(eigrp_com_header->opcode),
  270            GET_BE_U_2(eigrp_com_header->checksum),
  271            bittok2str(eigrp_common_header_flag_values,
  272                    "none",
  273                    GET_BE_U_4(eigrp_com_header->flags)),
  274            GET_BE_U_4(eigrp_com_header->seq),
  275            GET_BE_U_4(eigrp_com_header->ack),
  276            GET_BE_U_2(eigrp_com_header->vrid),
  277            GET_BE_U_2(eigrp_com_header->asn),
  278            tlen);
  279 
  280     tptr+=sizeof(struct eigrp_common_header);
  281 
  282     while(tlen>0) {
  283         /* did we capture enough for fully decoding the object header ? */
  284         ND_TCHECK_LEN(tptr, sizeof(struct eigrp_tlv_header));
  285 
  286         eigrp_tlv_header = (const struct eigrp_tlv_header *)tptr;
  287         eigrp_tlv_len=GET_BE_U_2(eigrp_tlv_header->length);
  288         eigrp_tlv_type=GET_BE_U_2(eigrp_tlv_header->type);
  289 
  290 
  291         if (eigrp_tlv_len < sizeof(struct eigrp_tlv_header) ||
  292             eigrp_tlv_len > tlen) {
  293             print_unknown_data(ndo,tptr+sizeof(struct eigrp_tlv_header),"\n\t    ",tlen);
  294             return;
  295         }
  296 
  297         ND_PRINT("\n\t  %s TLV (0x%04x), length: %u",
  298                tok2str(eigrp_tlv_values,
  299                        "Unknown",
  300                        eigrp_tlv_type),
  301                eigrp_tlv_type,
  302                eigrp_tlv_len);
  303 
  304         if (eigrp_tlv_len < sizeof(struct eigrp_tlv_header)) {
  305                 ND_PRINT(" (too short, < %zu)",
  306                          sizeof(struct eigrp_tlv_header));
  307                 break;
  308         }
  309         tlv_tptr=tptr+sizeof(struct eigrp_tlv_header);
  310         tlv_tlen=eigrp_tlv_len-sizeof(struct eigrp_tlv_header);
  311 
  312         /* did we capture enough for fully decoding the object ? */
  313         ND_TCHECK_LEN(tptr, eigrp_tlv_len);
  314 
  315         switch(eigrp_tlv_type) {
  316 
  317         case EIGRP_TLV_GENERAL_PARM:
  318             tlv_ptr.eigrp_tlv_general_parm = (const struct eigrp_tlv_general_parm_t *)tlv_tptr;
  319             if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_general_parm)) {
  320                 ND_PRINT(" (too short, < %zu)",
  321                  sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_general_parm));
  322                 break;
  323             }
  324 
  325             ND_PRINT("\n\t    holdtime: %us, k1 %u, k2 %u, k3 %u, k4 %u, k5 %u",
  326                    GET_BE_U_2(tlv_ptr.eigrp_tlv_general_parm->holdtime),
  327                    GET_U_1(tlv_ptr.eigrp_tlv_general_parm->k1),
  328                    GET_U_1(tlv_ptr.eigrp_tlv_general_parm->k2),
  329                    GET_U_1(tlv_ptr.eigrp_tlv_general_parm->k3),
  330                    GET_U_1(tlv_ptr.eigrp_tlv_general_parm->k4),
  331                    GET_U_1(tlv_ptr.eigrp_tlv_general_parm->k5));
  332             break;
  333 
  334         case EIGRP_TLV_SW_VERSION:
  335             tlv_ptr.eigrp_tlv_sw_version = (const struct eigrp_tlv_sw_version_t *)tlv_tptr;
  336             if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_sw_version)) {
  337                 ND_PRINT(" (too short, < %zu)",
  338                          sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_sw_version));
  339                 break;
  340             }
  341 
  342             ND_PRINT("\n\t    IOS version: %u.%u, EIGRP version %u.%u",
  343                    GET_U_1(tlv_ptr.eigrp_tlv_sw_version->ios_major),
  344                    GET_U_1(tlv_ptr.eigrp_tlv_sw_version->ios_minor),
  345                    GET_U_1(tlv_ptr.eigrp_tlv_sw_version->eigrp_major),
  346                    GET_U_1(tlv_ptr.eigrp_tlv_sw_version->eigrp_minor));
  347             break;
  348 
  349         case EIGRP_TLV_IP_INT:
  350             tlv_ptr.eigrp_tlv_ip_int = (const struct eigrp_tlv_ip_int_t *)tlv_tptr;
  351             if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_ip_int)) {
  352                 ND_PRINT(" (too short, < %zu)",
  353                          sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_ip_int));
  354                 break;
  355             }
  356 
  357             bit_length = GET_U_1(tlv_ptr.eigrp_tlv_ip_int->plen);
  358             if (bit_length > 32) {
  359                 ND_PRINT("\n\t    illegal prefix length %u",bit_length);
  360                 break;
  361             }
  362             byte_length = (bit_length + 7) / 8; /* variable length encoding */
  363             memset(prefix, 0, 4);
  364             GET_CPY_BYTES(prefix, tlv_ptr.eigrp_tlv_ip_int->destination, byte_length);
  365 
  366             ND_PRINT("\n\t    IPv4 prefix: %15s/%u, nexthop: ",
  367                    ipaddr_string(ndo, prefix),  /* local buffer, not packet data; don't use GET_IPADDR_STRING() */
  368                    bit_length);
  369             if (GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_int->nexthop) == 0)
  370                 ND_PRINT("self");
  371             else
  372                 ND_PRINT("%s",
  373                          GET_IPADDR_STRING(tlv_ptr.eigrp_tlv_ip_int->nexthop));
  374 
  375             ND_PRINT("\n\t      delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
  376                    (GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_int->delay)/100),
  377                    GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_int->bandwidth),
  378                    GET_BE_U_3(tlv_ptr.eigrp_tlv_ip_int->mtu),
  379                    GET_U_1(tlv_ptr.eigrp_tlv_ip_int->hopcount),
  380                    GET_U_1(tlv_ptr.eigrp_tlv_ip_int->reliability),
  381                    GET_U_1(tlv_ptr.eigrp_tlv_ip_int->load));
  382             break;
  383 
  384         case EIGRP_TLV_IP_EXT:
  385             tlv_ptr.eigrp_tlv_ip_ext = (const struct eigrp_tlv_ip_ext_t *)tlv_tptr;
  386             if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_ip_ext)) {
  387                 ND_PRINT(" (too short, < %zu)",
  388                          sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_ip_ext));
  389                 break;
  390             }
  391 
  392             bit_length = GET_U_1(tlv_ptr.eigrp_tlv_ip_ext->plen);
  393             if (bit_length > 32) {
  394                 ND_PRINT("\n\t    illegal prefix length %u",bit_length);
  395                 break;
  396             }
  397             byte_length = (bit_length + 7) / 8; /* variable length encoding */
  398             memset(prefix, 0, 4);
  399             GET_CPY_BYTES(prefix, tlv_ptr.eigrp_tlv_ip_ext->destination, byte_length);
  400 
  401             ND_PRINT("\n\t    IPv4 prefix: %15s/%u, nexthop: ",
  402                    ipaddr_string(ndo, prefix),  /* local buffer, not packet data; don't use GET_IPADDR_STRING() */
  403                    bit_length);
  404             if (GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_ext->nexthop) == 0)
  405                 ND_PRINT("self");
  406             else
  407                 ND_PRINT("%s",
  408                          GET_IPADDR_STRING(tlv_ptr.eigrp_tlv_ip_ext->nexthop));
  409 
  410             ND_PRINT("\n\t      origin-router %s, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u",
  411                    GET_IPADDR_STRING(tlv_ptr.eigrp_tlv_ip_ext->origin_router),
  412                    GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_ext->origin_as),
  413                    tok2str(eigrp_ext_proto_id_values,"unknown",GET_U_1(tlv_ptr.eigrp_tlv_ip_ext->proto_id)),
  414                    GET_U_1(tlv_ptr.eigrp_tlv_ip_ext->flags),
  415                    GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_ext->tag),
  416                    GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_ext->metric));
  417 
  418             ND_PRINT("\n\t      delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
  419                    (GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_ext->delay)/100),
  420                    GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_ext->bandwidth),
  421                    GET_BE_U_3(tlv_ptr.eigrp_tlv_ip_ext->mtu),
  422                    GET_U_1(tlv_ptr.eigrp_tlv_ip_ext->hopcount),
  423                    GET_U_1(tlv_ptr.eigrp_tlv_ip_ext->reliability),
  424                    GET_U_1(tlv_ptr.eigrp_tlv_ip_ext->load));
  425             break;
  426 
  427         case EIGRP_TLV_AT_CABLE_SETUP:
  428             tlv_ptr.eigrp_tlv_at_cable_setup = (const struct eigrp_tlv_at_cable_setup_t *)tlv_tptr;
  429             if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_cable_setup)) {
  430                 ND_PRINT(" (too short, < %zu)",
  431                          sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_cable_setup));
  432                 break;
  433             }
  434 
  435             ND_PRINT("\n\t    Cable-range: %u-%u, Router-ID %u",
  436                    GET_BE_U_2(tlv_ptr.eigrp_tlv_at_cable_setup->cable_start),
  437                    GET_BE_U_2(tlv_ptr.eigrp_tlv_at_cable_setup->cable_end),
  438                    GET_BE_U_4(tlv_ptr.eigrp_tlv_at_cable_setup->router_id));
  439             break;
  440 
  441         case EIGRP_TLV_AT_INT:
  442             tlv_ptr.eigrp_tlv_at_int = (const struct eigrp_tlv_at_int_t *)tlv_tptr;
  443             if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_int)) {
  444                 ND_PRINT(" (too short, < %zu)",
  445                          sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_int));
  446                 break;
  447             }
  448 
  449             ND_PRINT("\n\t     Cable-Range: %u-%u, nexthop: ",
  450                    GET_BE_U_2(tlv_ptr.eigrp_tlv_at_int->cable_start),
  451                    GET_BE_U_2(tlv_ptr.eigrp_tlv_at_int->cable_end));
  452 
  453             if (GET_BE_U_4(tlv_ptr.eigrp_tlv_at_int->nexthop) == 0)
  454                 ND_PRINT("self");
  455             else
  456                 ND_PRINT("%u.%u",
  457                        GET_BE_U_2(&tlv_ptr.eigrp_tlv_at_int->nexthop[0]),
  458                        GET_BE_U_2(&tlv_ptr.eigrp_tlv_at_int->nexthop[2]));
  459 
  460             ND_PRINT("\n\t      delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
  461                    (GET_BE_U_4(tlv_ptr.eigrp_tlv_at_int->delay)/100),
  462                    GET_BE_U_4(tlv_ptr.eigrp_tlv_at_int->bandwidth),
  463                    GET_BE_U_3(tlv_ptr.eigrp_tlv_at_int->mtu),
  464                    GET_U_1(tlv_ptr.eigrp_tlv_at_int->hopcount),
  465                    GET_U_1(tlv_ptr.eigrp_tlv_at_int->reliability),
  466                    GET_U_1(tlv_ptr.eigrp_tlv_at_int->load));
  467             break;
  468 
  469         case EIGRP_TLV_AT_EXT:
  470             tlv_ptr.eigrp_tlv_at_ext = (const struct eigrp_tlv_at_ext_t *)tlv_tptr;
  471             if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_ext)) {
  472                 ND_PRINT(" (too short, < %zu)",
  473                          sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_ext));
  474                 break;
  475             }
  476 
  477             ND_PRINT("\n\t     Cable-Range: %u-%u, nexthop: ",
  478                    GET_BE_U_2(tlv_ptr.eigrp_tlv_at_ext->cable_start),
  479                    GET_BE_U_2(tlv_ptr.eigrp_tlv_at_ext->cable_end));
  480 
  481             if (GET_BE_U_4(tlv_ptr.eigrp_tlv_at_ext->nexthop) == 0)
  482                 ND_PRINT("self");
  483             else
  484                 ND_PRINT("%u.%u",
  485                        GET_BE_U_2(&tlv_ptr.eigrp_tlv_at_ext->nexthop[0]),
  486                        GET_BE_U_2(&tlv_ptr.eigrp_tlv_at_ext->nexthop[2]));
  487 
  488             ND_PRINT("\n\t      origin-router %u, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u",
  489                    GET_BE_U_4(tlv_ptr.eigrp_tlv_at_ext->origin_router),
  490                    GET_BE_U_4(tlv_ptr.eigrp_tlv_at_ext->origin_as),
  491                    tok2str(eigrp_ext_proto_id_values,"unknown",GET_U_1(tlv_ptr.eigrp_tlv_at_ext->proto_id)),
  492                    GET_U_1(tlv_ptr.eigrp_tlv_at_ext->flags),
  493                    GET_BE_U_4(tlv_ptr.eigrp_tlv_at_ext->tag),
  494                    GET_BE_U_2(tlv_ptr.eigrp_tlv_at_ext->metric));
  495 
  496             ND_PRINT("\n\t      delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
  497                    (GET_BE_U_4(tlv_ptr.eigrp_tlv_at_ext->delay)/100),
  498                    GET_BE_U_4(tlv_ptr.eigrp_tlv_at_ext->bandwidth),
  499                    GET_BE_U_3(tlv_ptr.eigrp_tlv_at_ext->mtu),
  500                    GET_U_1(tlv_ptr.eigrp_tlv_at_ext->hopcount),
  501                    GET_U_1(tlv_ptr.eigrp_tlv_at_ext->reliability),
  502                    GET_U_1(tlv_ptr.eigrp_tlv_at_ext->load));
  503             break;
  504 
  505             /*
  506              * FIXME those are the defined TLVs that lack a decoder
  507              * you are welcome to contribute code ;-)
  508              */
  509 
  510         case EIGRP_TLV_AUTH:
  511         case EIGRP_TLV_SEQ:
  512         case EIGRP_TLV_MCAST_SEQ:
  513         case EIGRP_TLV_IPX_INT:
  514         case EIGRP_TLV_IPX_EXT:
  515 
  516         default:
  517             if (ndo->ndo_vflag <= 1)
  518                 print_unknown_data(ndo,tlv_tptr,"\n\t    ",tlv_tlen);
  519             break;
  520         }
  521         /* do we want to see an additionally hexdump ? */
  522         if (ndo->ndo_vflag > 1)
  523             print_unknown_data(ndo,tptr+sizeof(struct eigrp_tlv_header),"\n\t    ",
  524                                eigrp_tlv_len-sizeof(struct eigrp_tlv_header));
  525 
  526         tptr+=eigrp_tlv_len;
  527         tlen-=eigrp_tlv_len;
  528     }
  529     return;
  530 trunc:
  531     nd_print_trunc(ndo);
  532 }