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