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