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