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