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