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