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