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