xref: /freebsd/contrib/tcpdump/print-eigrp.c (revision 0a7e5f1f02aad2ff5fff1c60f44c6975fd07e1d9)
11de50e9fSSam Leffler /*
20bff6a5aSEd 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 
19*ee67461eSJoseph Mingrone /*
20*ee67461eSJoseph Mingrone  * specification:
21*ee67461eSJoseph Mingrone  *
22*ee67461eSJoseph Mingrone  * https://web.archive.org/web/20190722221712/https://www.rhyshaden.com/eigrp.htm
23*ee67461eSJoseph Mingrone  * RFC 7868
24*ee67461eSJoseph Mingrone  */
25*ee67461eSJoseph Mingrone 
26*ee67461eSJoseph Mingrone #include <config.h>
271de50e9fSSam Leffler 
28*ee67461eSJoseph Mingrone #include "netdissect-stdinc.h"
291de50e9fSSam Leffler 
301de50e9fSSam Leffler #include <string.h>
311de50e9fSSam Leffler 
323340d773SGleb Smirnoff #include "netdissect.h"
331de50e9fSSam Leffler #include "extract.h"
341de50e9fSSam Leffler #include "addrtoname.h"
351de50e9fSSam Leffler 
361de50e9fSSam Leffler 
371de50e9fSSam Leffler struct eigrp_common_header {
38*ee67461eSJoseph Mingrone     nd_uint8_t  version;
39*ee67461eSJoseph Mingrone     nd_uint8_t  opcode;
40*ee67461eSJoseph Mingrone     nd_uint16_t checksum;
41*ee67461eSJoseph Mingrone     nd_uint32_t flags;
42*ee67461eSJoseph Mingrone     nd_uint32_t seq;
43*ee67461eSJoseph Mingrone     nd_uint32_t ack;
44*ee67461eSJoseph Mingrone     nd_uint16_t vrid;
45*ee67461eSJoseph Mingrone     nd_uint16_t asn;
461de50e9fSSam Leffler };
471de50e9fSSam Leffler 
481de50e9fSSam Leffler #define	EIGRP_VERSION                        2
491de50e9fSSam Leffler 
501de50e9fSSam Leffler #define	EIGRP_OPCODE_UPDATE                  1
511de50e9fSSam Leffler #define	EIGRP_OPCODE_QUERY                   3
521de50e9fSSam Leffler #define	EIGRP_OPCODE_REPLY                   4
531de50e9fSSam Leffler #define	EIGRP_OPCODE_HELLO                   5
541de50e9fSSam Leffler #define	EIGRP_OPCODE_IPXSAP                  6
551de50e9fSSam Leffler #define	EIGRP_OPCODE_PROBE                   7
561de50e9fSSam Leffler 
571de50e9fSSam Leffler static const struct tok eigrp_opcode_values[] = {
581de50e9fSSam Leffler     { EIGRP_OPCODE_UPDATE, "Update" },
591de50e9fSSam Leffler     { EIGRP_OPCODE_QUERY, "Query" },
601de50e9fSSam Leffler     { EIGRP_OPCODE_REPLY, "Reply" },
611de50e9fSSam Leffler     { EIGRP_OPCODE_HELLO, "Hello" },
621de50e9fSSam Leffler     { EIGRP_OPCODE_IPXSAP, "IPX SAP" },
631de50e9fSSam Leffler     { EIGRP_OPCODE_PROBE, "Probe" },
641de50e9fSSam Leffler     { 0, NULL}
651de50e9fSSam Leffler };
661de50e9fSSam Leffler 
671de50e9fSSam Leffler static const struct tok eigrp_common_header_flag_values[] = {
681de50e9fSSam Leffler     { 0x01, "Init" },
691de50e9fSSam Leffler     { 0x02, "Conditionally Received" },
70*ee67461eSJoseph Mingrone     { 0x04, "Restart" },
71*ee67461eSJoseph Mingrone     { 0x08, "End-of-Table" },
721de50e9fSSam Leffler     { 0, NULL}
731de50e9fSSam Leffler };
741de50e9fSSam Leffler 
751de50e9fSSam Leffler struct eigrp_tlv_header {
76*ee67461eSJoseph Mingrone     nd_uint16_t type;
77*ee67461eSJoseph Mingrone     nd_uint16_t length;
781de50e9fSSam Leffler };
791de50e9fSSam Leffler 
801de50e9fSSam Leffler #define EIGRP_TLV_GENERAL_PARM   0x0001
811de50e9fSSam Leffler #define EIGRP_TLV_AUTH           0x0002
821de50e9fSSam Leffler #define EIGRP_TLV_SEQ            0x0003
831de50e9fSSam Leffler #define EIGRP_TLV_SW_VERSION     0x0004
841de50e9fSSam Leffler #define EIGRP_TLV_MCAST_SEQ      0x0005
851de50e9fSSam Leffler #define EIGRP_TLV_IP_INT         0x0102
861de50e9fSSam Leffler #define EIGRP_TLV_IP_EXT         0x0103
871de50e9fSSam Leffler #define EIGRP_TLV_AT_INT         0x0202
881de50e9fSSam Leffler #define EIGRP_TLV_AT_EXT         0x0203
891de50e9fSSam Leffler #define EIGRP_TLV_AT_CABLE_SETUP 0x0204
901de50e9fSSam Leffler #define EIGRP_TLV_IPX_INT        0x0302
911de50e9fSSam Leffler #define EIGRP_TLV_IPX_EXT        0x0303
921de50e9fSSam Leffler 
931de50e9fSSam Leffler static const struct tok eigrp_tlv_values[] = {
941de50e9fSSam Leffler     { EIGRP_TLV_GENERAL_PARM, "General Parameters"},
951de50e9fSSam Leffler     { EIGRP_TLV_AUTH, "Authentication"},
961de50e9fSSam Leffler     { EIGRP_TLV_SEQ, "Sequence"},
971de50e9fSSam Leffler     { EIGRP_TLV_SW_VERSION, "Software Version"},
981de50e9fSSam Leffler     { EIGRP_TLV_MCAST_SEQ, "Next Multicast Sequence"},
991de50e9fSSam Leffler     { EIGRP_TLV_IP_INT, "IP Internal routes"},
1001de50e9fSSam Leffler     { EIGRP_TLV_IP_EXT, "IP External routes"},
1011de50e9fSSam Leffler     { EIGRP_TLV_AT_INT, "AppleTalk Internal routes"},
1021de50e9fSSam Leffler     { EIGRP_TLV_AT_EXT, "AppleTalk External routes"},
1031de50e9fSSam Leffler     { EIGRP_TLV_AT_CABLE_SETUP, "AppleTalk Cable setup"},
1041de50e9fSSam Leffler     { EIGRP_TLV_IPX_INT, "IPX Internal routes"},
1051de50e9fSSam Leffler     { EIGRP_TLV_IPX_EXT, "IPX External routes"},
1061de50e9fSSam Leffler     { 0, NULL}
1071de50e9fSSam Leffler };
1081de50e9fSSam Leffler 
1091de50e9fSSam Leffler struct eigrp_tlv_general_parm_t {
110*ee67461eSJoseph Mingrone     nd_uint8_t  k1;
111*ee67461eSJoseph Mingrone     nd_uint8_t  k2;
112*ee67461eSJoseph Mingrone     nd_uint8_t  k3;
113*ee67461eSJoseph Mingrone     nd_uint8_t  k4;
114*ee67461eSJoseph Mingrone     nd_uint8_t  k5;
115*ee67461eSJoseph Mingrone     nd_uint8_t  res;
116*ee67461eSJoseph Mingrone     nd_uint16_t holdtime;
1171de50e9fSSam Leffler };
1181de50e9fSSam Leffler 
1191de50e9fSSam Leffler struct eigrp_tlv_sw_version_t {
120*ee67461eSJoseph Mingrone     nd_uint8_t ios_major;
121*ee67461eSJoseph Mingrone     nd_uint8_t ios_minor;
122*ee67461eSJoseph Mingrone     nd_uint8_t eigrp_major;
123*ee67461eSJoseph Mingrone     nd_uint8_t eigrp_minor;
1241de50e9fSSam Leffler };
1251de50e9fSSam Leffler 
1261de50e9fSSam Leffler struct eigrp_tlv_ip_int_t {
127*ee67461eSJoseph Mingrone     nd_ipv4     nexthop;
128*ee67461eSJoseph Mingrone     nd_uint32_t delay;
129*ee67461eSJoseph Mingrone     nd_uint32_t bandwidth;
130*ee67461eSJoseph Mingrone     nd_uint24_t mtu;
131*ee67461eSJoseph Mingrone     nd_uint8_t  hopcount;
132*ee67461eSJoseph Mingrone     nd_uint8_t  reliability;
133*ee67461eSJoseph Mingrone     nd_uint8_t  load;
134*ee67461eSJoseph Mingrone     nd_byte     reserved[2];
135*ee67461eSJoseph Mingrone     nd_uint8_t  plen;
136*ee67461eSJoseph Mingrone     nd_uint8_t  destination; /* variable length [1-4] bytes encoding */
1371de50e9fSSam Leffler };
1381de50e9fSSam Leffler 
1391de50e9fSSam Leffler struct eigrp_tlv_ip_ext_t {
140*ee67461eSJoseph Mingrone     nd_ipv4     nexthop;
141*ee67461eSJoseph Mingrone     nd_ipv4     origin_router;
142*ee67461eSJoseph Mingrone     nd_uint32_t origin_as;
143*ee67461eSJoseph Mingrone     nd_uint32_t tag;
144*ee67461eSJoseph Mingrone     nd_uint32_t metric;
145*ee67461eSJoseph Mingrone     nd_byte     reserved[2];
146*ee67461eSJoseph Mingrone     nd_uint8_t  proto_id;
147*ee67461eSJoseph Mingrone     nd_uint8_t  flags;
148*ee67461eSJoseph Mingrone     nd_uint32_t delay;
149*ee67461eSJoseph Mingrone     nd_uint32_t bandwidth;
150*ee67461eSJoseph Mingrone     nd_uint24_t mtu;
151*ee67461eSJoseph Mingrone     nd_uint8_t  hopcount;
152*ee67461eSJoseph Mingrone     nd_uint8_t  reliability;
153*ee67461eSJoseph Mingrone     nd_uint8_t  load;
154*ee67461eSJoseph Mingrone     nd_byte     reserved2[2];
155*ee67461eSJoseph Mingrone     nd_uint8_t  plen;
156*ee67461eSJoseph Mingrone     nd_uint8_t  destination; /* variable length [1-4] bytes encoding */
1571de50e9fSSam Leffler };
1581de50e9fSSam Leffler 
1591de50e9fSSam Leffler struct eigrp_tlv_at_cable_setup_t {
160*ee67461eSJoseph Mingrone     nd_uint16_t cable_start;
161*ee67461eSJoseph Mingrone     nd_uint16_t cable_end;
162*ee67461eSJoseph Mingrone     nd_uint32_t router_id;
1631de50e9fSSam Leffler };
1641de50e9fSSam Leffler 
1651de50e9fSSam Leffler struct eigrp_tlv_at_int_t {
166*ee67461eSJoseph Mingrone     nd_byte     nexthop[4];
167*ee67461eSJoseph Mingrone     nd_uint32_t delay;
168*ee67461eSJoseph Mingrone     nd_uint32_t bandwidth;
169*ee67461eSJoseph Mingrone     nd_uint24_t mtu;
170*ee67461eSJoseph Mingrone     nd_uint8_t  hopcount;
171*ee67461eSJoseph Mingrone     nd_uint8_t  reliability;
172*ee67461eSJoseph Mingrone     nd_uint8_t  load;
173*ee67461eSJoseph Mingrone     nd_byte     reserved[2];
174*ee67461eSJoseph Mingrone     nd_uint16_t cable_start;
175*ee67461eSJoseph Mingrone     nd_uint16_t cable_end;
1761de50e9fSSam Leffler };
1771de50e9fSSam Leffler 
1781de50e9fSSam Leffler struct eigrp_tlv_at_ext_t {
179*ee67461eSJoseph Mingrone     nd_byte     nexthop[4];
180*ee67461eSJoseph Mingrone     nd_uint32_t origin_router;
181*ee67461eSJoseph Mingrone     nd_uint32_t origin_as;
182*ee67461eSJoseph Mingrone     nd_uint32_t tag;
183*ee67461eSJoseph Mingrone     nd_uint8_t  proto_id;
184*ee67461eSJoseph Mingrone     nd_uint8_t  flags;
185*ee67461eSJoseph Mingrone     nd_uint16_t metric;
186*ee67461eSJoseph Mingrone     nd_uint32_t delay;
187*ee67461eSJoseph Mingrone     nd_uint32_t bandwidth;
188*ee67461eSJoseph Mingrone     nd_uint24_t mtu;
189*ee67461eSJoseph Mingrone     nd_uint8_t  hopcount;
190*ee67461eSJoseph Mingrone     nd_uint8_t  reliability;
191*ee67461eSJoseph Mingrone     nd_uint8_t  load;
192*ee67461eSJoseph Mingrone     nd_byte     reserved2[2];
193*ee67461eSJoseph Mingrone     nd_uint16_t cable_start;
194*ee67461eSJoseph Mingrone     nd_uint16_t cable_end;
1951de50e9fSSam Leffler };
1961de50e9fSSam Leffler 
1971de50e9fSSam Leffler static const struct tok eigrp_ext_proto_id_values[] = {
1981de50e9fSSam Leffler     { 0x01, "IGRP" },
1991de50e9fSSam Leffler     { 0x02, "EIGRP" },
2001de50e9fSSam Leffler     { 0x03, "Static" },
2011de50e9fSSam Leffler     { 0x04, "RIP" },
2021de50e9fSSam Leffler     { 0x05, "Hello" },
2031de50e9fSSam Leffler     { 0x06, "OSPF" },
2041de50e9fSSam Leffler     { 0x07, "IS-IS" },
2051de50e9fSSam Leffler     { 0x08, "EGP" },
2061de50e9fSSam Leffler     { 0x09, "BGP" },
2071de50e9fSSam Leffler     { 0x0a, "IDRP" },
2081de50e9fSSam Leffler     { 0x0b, "Connected" },
2091de50e9fSSam Leffler     { 0, NULL}
2101de50e9fSSam Leffler };
2111de50e9fSSam Leffler 
2121de50e9fSSam Leffler void
eigrp_print(netdissect_options * ndo,const u_char * pptr,u_int len)213*ee67461eSJoseph Mingrone eigrp_print(netdissect_options *ndo, const u_char *pptr, u_int len)
2148bdc5a62SPatrick Kelsey {
2151de50e9fSSam Leffler     const struct eigrp_common_header *eigrp_com_header;
2161de50e9fSSam Leffler     const struct eigrp_tlv_header *eigrp_tlv_header;
2171de50e9fSSam Leffler     const u_char *tptr,*tlv_tptr;
218f4d0c64aSSam Leffler     u_int tlen,eigrp_tlv_len,eigrp_tlv_type,tlv_tlen, byte_length, bit_length;
2193c602fabSXin LI     uint8_t prefix[4];
2201de50e9fSSam Leffler 
2211de50e9fSSam Leffler     union {
2221de50e9fSSam Leffler         const struct eigrp_tlv_general_parm_t *eigrp_tlv_general_parm;
2231de50e9fSSam Leffler         const struct eigrp_tlv_sw_version_t *eigrp_tlv_sw_version;
2241de50e9fSSam Leffler         const struct eigrp_tlv_ip_int_t *eigrp_tlv_ip_int;
2251de50e9fSSam Leffler         const struct eigrp_tlv_ip_ext_t *eigrp_tlv_ip_ext;
2261de50e9fSSam Leffler         const struct eigrp_tlv_at_cable_setup_t *eigrp_tlv_at_cable_setup;
2271de50e9fSSam Leffler         const struct eigrp_tlv_at_int_t *eigrp_tlv_at_int;
2281de50e9fSSam Leffler         const struct eigrp_tlv_at_ext_t *eigrp_tlv_at_ext;
2291de50e9fSSam Leffler     } tlv_ptr;
2301de50e9fSSam Leffler 
231*ee67461eSJoseph Mingrone     ndo->ndo_protocol = "eigrp";
2321de50e9fSSam Leffler     tptr=pptr;
2331de50e9fSSam Leffler     eigrp_com_header = (const struct eigrp_common_header *)pptr;
234*ee67461eSJoseph Mingrone     ND_TCHECK_SIZE(eigrp_com_header);
2351de50e9fSSam Leffler 
2361de50e9fSSam Leffler     /*
2371de50e9fSSam Leffler      * Sanity checking of the header.
2381de50e9fSSam Leffler      */
239*ee67461eSJoseph Mingrone     if (GET_U_1(eigrp_com_header->version) != EIGRP_VERSION) {
240*ee67461eSJoseph Mingrone         ND_PRINT("EIGRP version %u packet not supported",
241*ee67461eSJoseph Mingrone                  GET_U_1(eigrp_com_header->version));
2421de50e9fSSam Leffler         return;
2431de50e9fSSam Leffler     }
2441de50e9fSSam Leffler 
2451de50e9fSSam Leffler     /* in non-verbose mode just lets print the basic Message Type*/
2463c602fabSXin LI     if (ndo->ndo_vflag < 1) {
247*ee67461eSJoseph Mingrone         ND_PRINT("EIGRP %s, length: %u",
248*ee67461eSJoseph Mingrone                tok2str(eigrp_opcode_values, "unknown (%u)",GET_U_1(eigrp_com_header->opcode)),
249*ee67461eSJoseph Mingrone                len);
2501de50e9fSSam Leffler         return;
2511de50e9fSSam Leffler     }
2521de50e9fSSam Leffler 
2531de50e9fSSam Leffler     /* ok they seem to want to know everything - lets fully decode it */
2541de50e9fSSam Leffler 
2550bff6a5aSEd Maste     if (len < sizeof(struct eigrp_common_header)) {
256*ee67461eSJoseph Mingrone         ND_PRINT("EIGRP %s, length: %u (too short, < %zu)",
257*ee67461eSJoseph Mingrone                tok2str(eigrp_opcode_values, "unknown (%u)",GET_U_1(eigrp_com_header->opcode)),
258*ee67461eSJoseph Mingrone                len, sizeof(struct eigrp_common_header));
2590bff6a5aSEd Maste         return;
2600bff6a5aSEd Maste     }
2611de50e9fSSam Leffler     tlen=len-sizeof(struct eigrp_common_header);
2621de50e9fSSam Leffler 
263*ee67461eSJoseph Mingrone     ND_PRINT("\n\tEIGRP v%u, opcode: %s (%u), chksum: 0x%04x, Flags: [%s]"
264*ee67461eSJoseph Mingrone              "\n\tseq: 0x%08x, ack: 0x%08x, VRID: %u, AS: %u, length: %u",
265*ee67461eSJoseph Mingrone            GET_U_1(eigrp_com_header->version),
266*ee67461eSJoseph Mingrone            tok2str(eigrp_opcode_values, "unknown, type: %u",GET_U_1(eigrp_com_header->opcode)),
267*ee67461eSJoseph Mingrone            GET_U_1(eigrp_com_header->opcode),
268*ee67461eSJoseph Mingrone            GET_BE_U_2(eigrp_com_header->checksum),
269*ee67461eSJoseph Mingrone            bittok2str(eigrp_common_header_flag_values,
2701de50e9fSSam Leffler                    "none",
271*ee67461eSJoseph Mingrone                    GET_BE_U_4(eigrp_com_header->flags)),
272*ee67461eSJoseph Mingrone            GET_BE_U_4(eigrp_com_header->seq),
273*ee67461eSJoseph Mingrone            GET_BE_U_4(eigrp_com_header->ack),
274*ee67461eSJoseph Mingrone            GET_BE_U_2(eigrp_com_header->vrid),
275*ee67461eSJoseph Mingrone            GET_BE_U_2(eigrp_com_header->asn),
276*ee67461eSJoseph Mingrone            tlen);
2771de50e9fSSam Leffler 
278*ee67461eSJoseph Mingrone     tptr+=sizeof(struct eigrp_common_header);
2791de50e9fSSam Leffler 
2801de50e9fSSam Leffler     while(tlen>0) {
2811de50e9fSSam Leffler         /* did we capture enough for fully decoding the object header ? */
282*ee67461eSJoseph Mingrone         ND_TCHECK_LEN(tptr, sizeof(struct eigrp_tlv_header));
2831de50e9fSSam Leffler 
2841de50e9fSSam Leffler         eigrp_tlv_header = (const struct eigrp_tlv_header *)tptr;
285*ee67461eSJoseph Mingrone         eigrp_tlv_len=GET_BE_U_2(eigrp_tlv_header->length);
286*ee67461eSJoseph Mingrone         eigrp_tlv_type=GET_BE_U_2(eigrp_tlv_header->type);
2871de50e9fSSam Leffler 
2881de50e9fSSam Leffler 
289f4d0c64aSSam Leffler         if (eigrp_tlv_len < sizeof(struct eigrp_tlv_header) ||
290f4d0c64aSSam Leffler             eigrp_tlv_len > tlen) {
2913c602fabSXin LI             print_unknown_data(ndo,tptr+sizeof(struct eigrp_tlv_header),"\n\t    ",tlen);
2921de50e9fSSam Leffler             return;
2931de50e9fSSam Leffler         }
2941de50e9fSSam Leffler 
295*ee67461eSJoseph Mingrone         ND_PRINT("\n\t  %s TLV (0x%04x), length: %u",
2961de50e9fSSam Leffler                tok2str(eigrp_tlv_values,
2971de50e9fSSam Leffler                        "Unknown",
2981de50e9fSSam Leffler                        eigrp_tlv_type),
2991de50e9fSSam Leffler                eigrp_tlv_type,
300*ee67461eSJoseph Mingrone                eigrp_tlv_len);
3011de50e9fSSam Leffler 
3020bff6a5aSEd Maste         if (eigrp_tlv_len < sizeof(struct eigrp_tlv_header)) {
303*ee67461eSJoseph Mingrone                 ND_PRINT(" (too short, < %zu)",
304*ee67461eSJoseph Mingrone                          sizeof(struct eigrp_tlv_header));
3050bff6a5aSEd Maste                 break;
3060bff6a5aSEd Maste         }
3071de50e9fSSam Leffler         tlv_tptr=tptr+sizeof(struct eigrp_tlv_header);
3081de50e9fSSam Leffler         tlv_tlen=eigrp_tlv_len-sizeof(struct eigrp_tlv_header);
3091de50e9fSSam Leffler 
3101de50e9fSSam Leffler         /* did we capture enough for fully decoding the object ? */
311*ee67461eSJoseph Mingrone         ND_TCHECK_LEN(tptr, eigrp_tlv_len);
3121de50e9fSSam Leffler 
3131de50e9fSSam Leffler         switch(eigrp_tlv_type) {
3141de50e9fSSam Leffler 
3151de50e9fSSam Leffler         case EIGRP_TLV_GENERAL_PARM:
3161de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_general_parm = (const struct eigrp_tlv_general_parm_t *)tlv_tptr;
3170bff6a5aSEd Maste             if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_general_parm)) {
318*ee67461eSJoseph Mingrone                 ND_PRINT(" (too short, < %zu)",
319*ee67461eSJoseph Mingrone 			 sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_general_parm));
3200bff6a5aSEd Maste                 break;
3210bff6a5aSEd Maste             }
3221de50e9fSSam Leffler 
323*ee67461eSJoseph Mingrone             ND_PRINT("\n\t    holdtime: %us, k1 %u, k2 %u, k3 %u, k4 %u, k5 %u",
324*ee67461eSJoseph Mingrone                    GET_BE_U_2(tlv_ptr.eigrp_tlv_general_parm->holdtime),
325*ee67461eSJoseph Mingrone                    GET_U_1(tlv_ptr.eigrp_tlv_general_parm->k1),
326*ee67461eSJoseph Mingrone                    GET_U_1(tlv_ptr.eigrp_tlv_general_parm->k2),
327*ee67461eSJoseph Mingrone                    GET_U_1(tlv_ptr.eigrp_tlv_general_parm->k3),
328*ee67461eSJoseph Mingrone                    GET_U_1(tlv_ptr.eigrp_tlv_general_parm->k4),
329*ee67461eSJoseph Mingrone                    GET_U_1(tlv_ptr.eigrp_tlv_general_parm->k5));
3301de50e9fSSam Leffler             break;
3311de50e9fSSam Leffler 
3321de50e9fSSam Leffler         case EIGRP_TLV_SW_VERSION:
3331de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_sw_version = (const struct eigrp_tlv_sw_version_t *)tlv_tptr;
3340bff6a5aSEd Maste             if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_sw_version)) {
335*ee67461eSJoseph Mingrone                 ND_PRINT(" (too short, < %zu)",
336*ee67461eSJoseph Mingrone                          sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_sw_version));
3370bff6a5aSEd Maste                 break;
3380bff6a5aSEd Maste             }
3391de50e9fSSam Leffler 
340*ee67461eSJoseph Mingrone             ND_PRINT("\n\t    IOS version: %u.%u, EIGRP version %u.%u",
341*ee67461eSJoseph Mingrone                    GET_U_1(tlv_ptr.eigrp_tlv_sw_version->ios_major),
342*ee67461eSJoseph Mingrone                    GET_U_1(tlv_ptr.eigrp_tlv_sw_version->ios_minor),
343*ee67461eSJoseph Mingrone                    GET_U_1(tlv_ptr.eigrp_tlv_sw_version->eigrp_major),
344*ee67461eSJoseph Mingrone                    GET_U_1(tlv_ptr.eigrp_tlv_sw_version->eigrp_minor));
3451de50e9fSSam Leffler             break;
3461de50e9fSSam Leffler 
3471de50e9fSSam Leffler         case EIGRP_TLV_IP_INT:
3481de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_ip_int = (const struct eigrp_tlv_ip_int_t *)tlv_tptr;
3490bff6a5aSEd Maste             if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_ip_int)) {
350*ee67461eSJoseph Mingrone                 ND_PRINT(" (too short, < %zu)",
351*ee67461eSJoseph Mingrone                          sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_ip_int));
3520bff6a5aSEd Maste                 break;
3530bff6a5aSEd Maste             }
3541de50e9fSSam Leffler 
355*ee67461eSJoseph Mingrone             bit_length = GET_U_1(tlv_ptr.eigrp_tlv_ip_int->plen);
356f4d0c64aSSam Leffler             if (bit_length > 32) {
357*ee67461eSJoseph Mingrone                 ND_PRINT("\n\t    illegal prefix length %u",bit_length);
3581de50e9fSSam Leffler                 break;
3591de50e9fSSam Leffler             }
3601de50e9fSSam Leffler             byte_length = (bit_length + 7) / 8; /* variable length encoding */
3611de50e9fSSam Leffler             memset(prefix, 0, 4);
362*ee67461eSJoseph Mingrone             GET_CPY_BYTES(prefix, tlv_ptr.eigrp_tlv_ip_int->destination, byte_length);
3631de50e9fSSam Leffler 
364*ee67461eSJoseph Mingrone             ND_PRINT("\n\t    IPv4 prefix: %15s/%u, nexthop: ",
365*ee67461eSJoseph Mingrone                    ipaddr_string(ndo, prefix),	/* local buffer, not packet data; don't use GET_IPADDR_STRING() */
366*ee67461eSJoseph Mingrone                    bit_length);
367*ee67461eSJoseph Mingrone             if (GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_int->nexthop) == 0)
368*ee67461eSJoseph Mingrone                 ND_PRINT("self");
3691de50e9fSSam Leffler             else
370*ee67461eSJoseph Mingrone                 ND_PRINT("%s",
371*ee67461eSJoseph Mingrone                          GET_IPADDR_STRING(tlv_ptr.eigrp_tlv_ip_int->nexthop));
3721de50e9fSSam Leffler 
373*ee67461eSJoseph Mingrone             ND_PRINT("\n\t      delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
374*ee67461eSJoseph Mingrone                    (GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_int->delay)/100),
375*ee67461eSJoseph Mingrone                    GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_int->bandwidth),
376*ee67461eSJoseph Mingrone                    GET_BE_U_3(tlv_ptr.eigrp_tlv_ip_int->mtu),
377*ee67461eSJoseph Mingrone                    GET_U_1(tlv_ptr.eigrp_tlv_ip_int->hopcount),
378*ee67461eSJoseph Mingrone                    GET_U_1(tlv_ptr.eigrp_tlv_ip_int->reliability),
379*ee67461eSJoseph Mingrone                    GET_U_1(tlv_ptr.eigrp_tlv_ip_int->load));
3801de50e9fSSam Leffler             break;
3811de50e9fSSam Leffler 
3821de50e9fSSam Leffler         case EIGRP_TLV_IP_EXT:
3831de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_ip_ext = (const struct eigrp_tlv_ip_ext_t *)tlv_tptr;
3840bff6a5aSEd Maste             if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_ip_ext)) {
385*ee67461eSJoseph Mingrone                 ND_PRINT(" (too short, < %zu)",
386*ee67461eSJoseph Mingrone                          sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_ip_ext));
3870bff6a5aSEd Maste                 break;
3880bff6a5aSEd Maste             }
3891de50e9fSSam Leffler 
390*ee67461eSJoseph Mingrone             bit_length = GET_U_1(tlv_ptr.eigrp_tlv_ip_ext->plen);
391f4d0c64aSSam Leffler             if (bit_length > 32) {
392*ee67461eSJoseph Mingrone                 ND_PRINT("\n\t    illegal prefix length %u",bit_length);
3931de50e9fSSam Leffler                 break;
3941de50e9fSSam Leffler             }
3951de50e9fSSam Leffler             byte_length = (bit_length + 7) / 8; /* variable length encoding */
3961de50e9fSSam Leffler             memset(prefix, 0, 4);
397*ee67461eSJoseph Mingrone             GET_CPY_BYTES(prefix, tlv_ptr.eigrp_tlv_ip_ext->destination, byte_length);
3981de50e9fSSam Leffler 
399*ee67461eSJoseph Mingrone             ND_PRINT("\n\t    IPv4 prefix: %15s/%u, nexthop: ",
400*ee67461eSJoseph Mingrone                    ipaddr_string(ndo, prefix),	/* local buffer, not packet data; don't use GET_IPADDR_STRING() */
401*ee67461eSJoseph Mingrone                    bit_length);
402*ee67461eSJoseph Mingrone             if (GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_ext->nexthop) == 0)
403*ee67461eSJoseph Mingrone                 ND_PRINT("self");
4041de50e9fSSam Leffler             else
405*ee67461eSJoseph Mingrone                 ND_PRINT("%s",
406*ee67461eSJoseph Mingrone                          GET_IPADDR_STRING(tlv_ptr.eigrp_tlv_ip_ext->nexthop));
4071de50e9fSSam Leffler 
408*ee67461eSJoseph Mingrone             ND_PRINT("\n\t      origin-router %s, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u",
409*ee67461eSJoseph Mingrone                    GET_IPADDR_STRING(tlv_ptr.eigrp_tlv_ip_ext->origin_router),
410*ee67461eSJoseph Mingrone                    GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_ext->origin_as),
411*ee67461eSJoseph Mingrone                    tok2str(eigrp_ext_proto_id_values,"unknown",GET_U_1(tlv_ptr.eigrp_tlv_ip_ext->proto_id)),
412*ee67461eSJoseph Mingrone                    GET_U_1(tlv_ptr.eigrp_tlv_ip_ext->flags),
413*ee67461eSJoseph Mingrone                    GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_ext->tag),
414*ee67461eSJoseph Mingrone                    GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_ext->metric));
4151de50e9fSSam Leffler 
416*ee67461eSJoseph Mingrone             ND_PRINT("\n\t      delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
417*ee67461eSJoseph Mingrone                    (GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_ext->delay)/100),
418*ee67461eSJoseph Mingrone                    GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_ext->bandwidth),
419*ee67461eSJoseph Mingrone                    GET_BE_U_3(tlv_ptr.eigrp_tlv_ip_ext->mtu),
420*ee67461eSJoseph Mingrone                    GET_U_1(tlv_ptr.eigrp_tlv_ip_ext->hopcount),
421*ee67461eSJoseph Mingrone                    GET_U_1(tlv_ptr.eigrp_tlv_ip_ext->reliability),
422*ee67461eSJoseph Mingrone                    GET_U_1(tlv_ptr.eigrp_tlv_ip_ext->load));
4231de50e9fSSam Leffler             break;
4241de50e9fSSam Leffler 
4251de50e9fSSam Leffler         case EIGRP_TLV_AT_CABLE_SETUP:
4261de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_at_cable_setup = (const struct eigrp_tlv_at_cable_setup_t *)tlv_tptr;
4270bff6a5aSEd Maste             if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_cable_setup)) {
428*ee67461eSJoseph Mingrone                 ND_PRINT(" (too short, < %zu)",
429*ee67461eSJoseph Mingrone                          sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_cable_setup));
4300bff6a5aSEd Maste                 break;
4310bff6a5aSEd Maste             }
4321de50e9fSSam Leffler 
433*ee67461eSJoseph Mingrone             ND_PRINT("\n\t    Cable-range: %u-%u, Router-ID %u",
434*ee67461eSJoseph Mingrone                    GET_BE_U_2(tlv_ptr.eigrp_tlv_at_cable_setup->cable_start),
435*ee67461eSJoseph Mingrone                    GET_BE_U_2(tlv_ptr.eigrp_tlv_at_cable_setup->cable_end),
436*ee67461eSJoseph Mingrone                    GET_BE_U_4(tlv_ptr.eigrp_tlv_at_cable_setup->router_id));
4371de50e9fSSam Leffler             break;
4381de50e9fSSam Leffler 
4391de50e9fSSam Leffler         case EIGRP_TLV_AT_INT:
4401de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_at_int = (const struct eigrp_tlv_at_int_t *)tlv_tptr;
4410bff6a5aSEd Maste             if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_int)) {
442*ee67461eSJoseph Mingrone                 ND_PRINT(" (too short, < %zu)",
443*ee67461eSJoseph Mingrone                          sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_int));
4440bff6a5aSEd Maste                 break;
4450bff6a5aSEd Maste             }
4461de50e9fSSam Leffler 
447*ee67461eSJoseph Mingrone             ND_PRINT("\n\t     Cable-Range: %u-%u, nexthop: ",
448*ee67461eSJoseph Mingrone                    GET_BE_U_2(tlv_ptr.eigrp_tlv_at_int->cable_start),
449*ee67461eSJoseph Mingrone                    GET_BE_U_2(tlv_ptr.eigrp_tlv_at_int->cable_end));
4501de50e9fSSam Leffler 
451*ee67461eSJoseph Mingrone             if (GET_BE_U_4(tlv_ptr.eigrp_tlv_at_int->nexthop) == 0)
452*ee67461eSJoseph Mingrone                 ND_PRINT("self");
4531de50e9fSSam Leffler             else
454*ee67461eSJoseph Mingrone                 ND_PRINT("%u.%u",
455*ee67461eSJoseph Mingrone                        GET_BE_U_2(&tlv_ptr.eigrp_tlv_at_int->nexthop[0]),
456*ee67461eSJoseph Mingrone                        GET_BE_U_2(&tlv_ptr.eigrp_tlv_at_int->nexthop[2]));
4571de50e9fSSam Leffler 
458*ee67461eSJoseph Mingrone             ND_PRINT("\n\t      delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
459*ee67461eSJoseph Mingrone                    (GET_BE_U_4(tlv_ptr.eigrp_tlv_at_int->delay)/100),
460*ee67461eSJoseph Mingrone                    GET_BE_U_4(tlv_ptr.eigrp_tlv_at_int->bandwidth),
461*ee67461eSJoseph Mingrone                    GET_BE_U_3(tlv_ptr.eigrp_tlv_at_int->mtu),
462*ee67461eSJoseph Mingrone                    GET_U_1(tlv_ptr.eigrp_tlv_at_int->hopcount),
463*ee67461eSJoseph Mingrone                    GET_U_1(tlv_ptr.eigrp_tlv_at_int->reliability),
464*ee67461eSJoseph Mingrone                    GET_U_1(tlv_ptr.eigrp_tlv_at_int->load));
4651de50e9fSSam Leffler             break;
4661de50e9fSSam Leffler 
4671de50e9fSSam Leffler         case EIGRP_TLV_AT_EXT:
4681de50e9fSSam Leffler             tlv_ptr.eigrp_tlv_at_ext = (const struct eigrp_tlv_at_ext_t *)tlv_tptr;
4690bff6a5aSEd Maste             if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_ext)) {
470*ee67461eSJoseph Mingrone                 ND_PRINT(" (too short, < %zu)",
471*ee67461eSJoseph Mingrone                          sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_ext));
4720bff6a5aSEd Maste                 break;
4730bff6a5aSEd Maste             }
4741de50e9fSSam Leffler 
475*ee67461eSJoseph Mingrone             ND_PRINT("\n\t     Cable-Range: %u-%u, nexthop: ",
476*ee67461eSJoseph Mingrone                    GET_BE_U_2(tlv_ptr.eigrp_tlv_at_ext->cable_start),
477*ee67461eSJoseph Mingrone                    GET_BE_U_2(tlv_ptr.eigrp_tlv_at_ext->cable_end));
4781de50e9fSSam Leffler 
479*ee67461eSJoseph Mingrone             if (GET_BE_U_4(tlv_ptr.eigrp_tlv_at_ext->nexthop) == 0)
480*ee67461eSJoseph Mingrone                 ND_PRINT("self");
4811de50e9fSSam Leffler             else
482*ee67461eSJoseph Mingrone                 ND_PRINT("%u.%u",
483*ee67461eSJoseph Mingrone                        GET_BE_U_2(&tlv_ptr.eigrp_tlv_at_ext->nexthop[0]),
484*ee67461eSJoseph Mingrone                        GET_BE_U_2(&tlv_ptr.eigrp_tlv_at_ext->nexthop[2]));
4851de50e9fSSam Leffler 
486*ee67461eSJoseph Mingrone             ND_PRINT("\n\t      origin-router %u, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u",
487*ee67461eSJoseph Mingrone                    GET_BE_U_4(tlv_ptr.eigrp_tlv_at_ext->origin_router),
488*ee67461eSJoseph Mingrone                    GET_BE_U_4(tlv_ptr.eigrp_tlv_at_ext->origin_as),
489*ee67461eSJoseph Mingrone                    tok2str(eigrp_ext_proto_id_values,"unknown",GET_U_1(tlv_ptr.eigrp_tlv_at_ext->proto_id)),
490*ee67461eSJoseph Mingrone                    GET_U_1(tlv_ptr.eigrp_tlv_at_ext->flags),
491*ee67461eSJoseph Mingrone                    GET_BE_U_4(tlv_ptr.eigrp_tlv_at_ext->tag),
492*ee67461eSJoseph Mingrone                    GET_BE_U_2(tlv_ptr.eigrp_tlv_at_ext->metric));
4931de50e9fSSam Leffler 
494*ee67461eSJoseph Mingrone             ND_PRINT("\n\t      delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u",
495*ee67461eSJoseph Mingrone                    (GET_BE_U_4(tlv_ptr.eigrp_tlv_at_ext->delay)/100),
496*ee67461eSJoseph Mingrone                    GET_BE_U_4(tlv_ptr.eigrp_tlv_at_ext->bandwidth),
497*ee67461eSJoseph Mingrone                    GET_BE_U_3(tlv_ptr.eigrp_tlv_at_ext->mtu),
498*ee67461eSJoseph Mingrone                    GET_U_1(tlv_ptr.eigrp_tlv_at_ext->hopcount),
499*ee67461eSJoseph Mingrone                    GET_U_1(tlv_ptr.eigrp_tlv_at_ext->reliability),
500*ee67461eSJoseph Mingrone                    GET_U_1(tlv_ptr.eigrp_tlv_at_ext->load));
5011de50e9fSSam Leffler             break;
5021de50e9fSSam Leffler 
5031de50e9fSSam Leffler             /*
5041de50e9fSSam Leffler              * FIXME those are the defined TLVs that lack a decoder
5051de50e9fSSam Leffler              * you are welcome to contribute code ;-)
5061de50e9fSSam Leffler              */
5071de50e9fSSam Leffler 
5081de50e9fSSam Leffler         case EIGRP_TLV_AUTH:
5091de50e9fSSam Leffler         case EIGRP_TLV_SEQ:
5101de50e9fSSam Leffler         case EIGRP_TLV_MCAST_SEQ:
5111de50e9fSSam Leffler         case EIGRP_TLV_IPX_INT:
5121de50e9fSSam Leffler         case EIGRP_TLV_IPX_EXT:
5131de50e9fSSam Leffler 
5141de50e9fSSam Leffler         default:
5153c602fabSXin LI             if (ndo->ndo_vflag <= 1)
5163c602fabSXin LI                 print_unknown_data(ndo,tlv_tptr,"\n\t    ",tlv_tlen);
5171de50e9fSSam Leffler             break;
5181de50e9fSSam Leffler         }
5191de50e9fSSam Leffler         /* do we want to see an additionally hexdump ? */
5203c602fabSXin LI         if (ndo->ndo_vflag > 1)
5213c602fabSXin LI             print_unknown_data(ndo,tptr+sizeof(struct eigrp_tlv_header),"\n\t    ",
5221de50e9fSSam Leffler                                eigrp_tlv_len-sizeof(struct eigrp_tlv_header));
5231de50e9fSSam Leffler 
5241de50e9fSSam Leffler         tptr+=eigrp_tlv_len;
5251de50e9fSSam Leffler         tlen-=eigrp_tlv_len;
5261de50e9fSSam Leffler     }
5271de50e9fSSam Leffler     return;
5281de50e9fSSam Leffler trunc:
529*ee67461eSJoseph Mingrone     nd_print_trunc(ndo);
5301de50e9fSSam Leffler }
531