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.10 2019/10/01 16:06:16 christos Exp $"); 20 #endif 21 22 /* \summary: Enhanced Interior Gateway Routing Protocol (EIGRP) printer */ 23 24 #ifdef HAVE_CONFIG_H 25 #include "config.h" 26 #endif 27 28 #include <netdissect-stdinc.h> 29 30 #include <string.h> 31 32 #include "netdissect.h" 33 #include "extract.h" 34 #include "addrtoname.h" 35 36 /* 37 * packet format documented at 38 * http://www.rhyshaden.com/eigrp.htm 39 * RFC 7868 40 */ 41 42 struct eigrp_common_header { 43 uint8_t version; 44 uint8_t opcode; 45 uint8_t checksum[2]; 46 uint8_t flags[4]; 47 uint8_t seq[4]; 48 uint8_t ack[4]; 49 uint8_t asn[4]; 50 }; 51 52 #define EIGRP_VERSION 2 53 54 #define EIGRP_OPCODE_UPDATE 1 55 #define EIGRP_OPCODE_QUERY 3 56 #define EIGRP_OPCODE_REPLY 4 57 #define EIGRP_OPCODE_HELLO 5 58 #define EIGRP_OPCODE_IPXSAP 6 59 #define EIGRP_OPCODE_PROBE 7 60 61 static const struct tok eigrp_opcode_values[] = { 62 { EIGRP_OPCODE_UPDATE, "Update" }, 63 { EIGRP_OPCODE_QUERY, "Query" }, 64 { EIGRP_OPCODE_REPLY, "Reply" }, 65 { EIGRP_OPCODE_HELLO, "Hello" }, 66 { EIGRP_OPCODE_IPXSAP, "IPX SAP" }, 67 { EIGRP_OPCODE_PROBE, "Probe" }, 68 { 0, NULL} 69 }; 70 71 static const struct tok eigrp_common_header_flag_values[] = { 72 { 0x01, "Init" }, 73 { 0x02, "Conditionally Received" }, 74 { 0, NULL} 75 }; 76 77 struct eigrp_tlv_header { 78 uint8_t type[2]; 79 uint8_t length[2]; 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 uint8_t k1; 113 uint8_t k2; 114 uint8_t k3; 115 uint8_t k4; 116 uint8_t k5; 117 uint8_t res; 118 uint8_t holdtime[2]; 119 }; 120 121 struct eigrp_tlv_sw_version_t { 122 uint8_t ios_major; 123 uint8_t ios_minor; 124 uint8_t eigrp_major; 125 uint8_t eigrp_minor; 126 }; 127 128 struct eigrp_tlv_ip_int_t { 129 uint8_t nexthop[4]; 130 uint8_t delay[4]; 131 uint8_t bandwidth[4]; 132 uint8_t mtu[3]; 133 uint8_t hopcount; 134 uint8_t reliability; 135 uint8_t load; 136 uint8_t reserved[2]; 137 uint8_t plen; 138 uint8_t destination; /* variable length [1-4] bytes encoding */ 139 }; 140 141 struct eigrp_tlv_ip_ext_t { 142 uint8_t nexthop[4]; 143 uint8_t origin_router[4]; 144 uint8_t origin_as[4]; 145 uint8_t tag[4]; 146 uint8_t metric[4]; 147 uint8_t reserved[2]; 148 uint8_t proto_id; 149 uint8_t flags; 150 uint8_t delay[4]; 151 uint8_t bandwidth[4]; 152 uint8_t mtu[3]; 153 uint8_t hopcount; 154 uint8_t reliability; 155 uint8_t load; 156 uint8_t reserved2[2]; 157 uint8_t plen; 158 uint8_t destination; /* variable length [1-4] bytes encoding */ 159 }; 160 161 struct eigrp_tlv_at_cable_setup_t { 162 uint8_t cable_start[2]; 163 uint8_t cable_end[2]; 164 uint8_t router_id[4]; 165 }; 166 167 struct eigrp_tlv_at_int_t { 168 uint8_t nexthop[4]; 169 uint8_t delay[4]; 170 uint8_t bandwidth[4]; 171 uint8_t mtu[3]; 172 uint8_t hopcount; 173 uint8_t reliability; 174 uint8_t load; 175 uint8_t reserved[2]; 176 uint8_t cable_start[2]; 177 uint8_t cable_end[2]; 178 }; 179 180 struct eigrp_tlv_at_ext_t { 181 uint8_t nexthop[4]; 182 uint8_t origin_router[4]; 183 uint8_t origin_as[4]; 184 uint8_t tag[4]; 185 uint8_t proto_id; 186 uint8_t flags; 187 uint8_t metric[2]; 188 uint8_t delay[4]; 189 uint8_t bandwidth[4]; 190 uint8_t mtu[3]; 191 uint8_t hopcount; 192 uint8_t reliability; 193 uint8_t load; 194 uint8_t reserved2[2]; 195 uint8_t cable_start[2]; 196 uint8_t cable_end[2]; 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, register const u_char *pptr, register 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 tptr=pptr; 234 eigrp_com_header = (const struct eigrp_common_header *)pptr; 235 ND_TCHECK(*eigrp_com_header); 236 237 /* 238 * Sanity checking of the header. 239 */ 240 if (eigrp_com_header->version != EIGRP_VERSION) { 241 ND_PRINT((ndo, "EIGRP version %u packet not supported",eigrp_com_header->version)); 242 return; 243 } 244 245 /* in non-verbose mode just lets print the basic Message Type*/ 246 if (ndo->ndo_vflag < 1) { 247 ND_PRINT((ndo, "EIGRP %s, length: %u", 248 tok2str(eigrp_opcode_values, "unknown (%u)",eigrp_com_header->opcode), 249 len)); 250 return; 251 } 252 253 /* ok they seem to want to know everything - lets fully decode it */ 254 255 if (len < sizeof(struct eigrp_common_header)) { 256 ND_PRINT((ndo, "EIGRP %s, length: %u (too short, < %u)", 257 tok2str(eigrp_opcode_values, "unknown (%u)",eigrp_com_header->opcode), 258 len, (u_int) sizeof(struct eigrp_common_header))); 259 return; 260 } 261 tlen=len-sizeof(struct eigrp_common_header); 262 263 /* FIXME print other header info */ 264 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", 265 eigrp_com_header->version, 266 tok2str(eigrp_opcode_values, "unknown, type: %u",eigrp_com_header->opcode), 267 eigrp_com_header->opcode, 268 EXTRACT_16BITS(&eigrp_com_header->checksum), 269 tok2str(eigrp_common_header_flag_values, 270 "none", 271 EXTRACT_32BITS(&eigrp_com_header->flags)), 272 EXTRACT_32BITS(&eigrp_com_header->seq), 273 EXTRACT_32BITS(&eigrp_com_header->ack), 274 EXTRACT_32BITS(&eigrp_com_header->asn), 275 tlen)); 276 277 tptr+=sizeof(const struct eigrp_common_header); 278 279 while(tlen>0) { 280 /* did we capture enough for fully decoding the object header ? */ 281 ND_TCHECK2(*tptr, sizeof(struct eigrp_tlv_header)); 282 283 eigrp_tlv_header = (const struct eigrp_tlv_header *)tptr; 284 eigrp_tlv_len=EXTRACT_16BITS(&eigrp_tlv_header->length); 285 eigrp_tlv_type=EXTRACT_16BITS(&eigrp_tlv_header->type); 286 287 288 if (eigrp_tlv_len < sizeof(struct eigrp_tlv_header) || 289 eigrp_tlv_len > tlen) { 290 print_unknown_data(ndo,tptr+sizeof(struct eigrp_tlv_header),"\n\t ",tlen); 291 return; 292 } 293 294 ND_PRINT((ndo, "\n\t %s TLV (0x%04x), length: %u", 295 tok2str(eigrp_tlv_values, 296 "Unknown", 297 eigrp_tlv_type), 298 eigrp_tlv_type, 299 eigrp_tlv_len)); 300 301 if (eigrp_tlv_len < sizeof(struct eigrp_tlv_header)) { 302 ND_PRINT((ndo, " (too short, < %u)", 303 (u_int) sizeof(struct eigrp_tlv_header))); 304 break; 305 } 306 tlv_tptr=tptr+sizeof(struct eigrp_tlv_header); 307 tlv_tlen=eigrp_tlv_len-sizeof(struct eigrp_tlv_header); 308 309 /* did we capture enough for fully decoding the object ? */ 310 ND_TCHECK2(*tptr, eigrp_tlv_len); 311 312 switch(eigrp_tlv_type) { 313 314 case EIGRP_TLV_GENERAL_PARM: 315 tlv_ptr.eigrp_tlv_general_parm = (const struct eigrp_tlv_general_parm_t *)tlv_tptr; 316 if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_general_parm)) { 317 ND_PRINT((ndo, " (too short, < %u)", 318 (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_general_parm)))); 319 break; 320 } 321 322 ND_PRINT((ndo, "\n\t holdtime: %us, k1 %u, k2 %u, k3 %u, k4 %u, k5 %u", 323 EXTRACT_16BITS(tlv_ptr.eigrp_tlv_general_parm->holdtime), 324 tlv_ptr.eigrp_tlv_general_parm->k1, 325 tlv_ptr.eigrp_tlv_general_parm->k2, 326 tlv_ptr.eigrp_tlv_general_parm->k3, 327 tlv_ptr.eigrp_tlv_general_parm->k4, 328 tlv_ptr.eigrp_tlv_general_parm->k5)); 329 break; 330 331 case EIGRP_TLV_SW_VERSION: 332 tlv_ptr.eigrp_tlv_sw_version = (const struct eigrp_tlv_sw_version_t *)tlv_tptr; 333 if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_sw_version)) { 334 ND_PRINT((ndo, " (too short, < %u)", 335 (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_sw_version)))); 336 break; 337 } 338 339 ND_PRINT((ndo, "\n\t IOS version: %u.%u, EIGRP version %u.%u", 340 tlv_ptr.eigrp_tlv_sw_version->ios_major, 341 tlv_ptr.eigrp_tlv_sw_version->ios_minor, 342 tlv_ptr.eigrp_tlv_sw_version->eigrp_major, 343 tlv_ptr.eigrp_tlv_sw_version->eigrp_minor)); 344 break; 345 346 case EIGRP_TLV_IP_INT: 347 tlv_ptr.eigrp_tlv_ip_int = (const struct eigrp_tlv_ip_int_t *)tlv_tptr; 348 if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_ip_int)) { 349 ND_PRINT((ndo, " (too short, < %u)", 350 (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_ip_int)))); 351 break; 352 } 353 354 bit_length = tlv_ptr.eigrp_tlv_ip_int->plen; 355 if (bit_length > 32) { 356 ND_PRINT((ndo, "\n\t illegal prefix length %u",bit_length)); 357 break; 358 } 359 byte_length = (bit_length + 7) / 8; /* variable length encoding */ 360 memset(prefix, 0, 4); 361 ND_TCHECK2(tlv_ptr.eigrp_tlv_ip_int->destination, byte_length); 362 memcpy(prefix,&tlv_ptr.eigrp_tlv_ip_int->destination,byte_length); 363 364 ND_PRINT((ndo, "\n\t IPv4 prefix: %15s/%u, nexthop: ", 365 ipaddr_string(ndo, prefix), 366 bit_length)); 367 if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->nexthop) == 0) 368 ND_PRINT((ndo, "self")); 369 else 370 ND_PRINT((ndo, "%s",ipaddr_string(ndo, &tlv_ptr.eigrp_tlv_ip_int->nexthop))); 371 372 ND_PRINT((ndo, "\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u", 373 (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->delay)/100), 374 EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_int->bandwidth), 375 EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_ip_int->mtu), 376 tlv_ptr.eigrp_tlv_ip_int->hopcount, 377 tlv_ptr.eigrp_tlv_ip_int->reliability, 378 tlv_ptr.eigrp_tlv_ip_int->load)); 379 break; 380 381 case EIGRP_TLV_IP_EXT: 382 tlv_ptr.eigrp_tlv_ip_ext = (const struct eigrp_tlv_ip_ext_t *)tlv_tptr; 383 if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_ip_ext)) { 384 ND_PRINT((ndo, " (too short, < %u)", 385 (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_ip_ext)))); 386 break; 387 } 388 389 bit_length = tlv_ptr.eigrp_tlv_ip_ext->plen; 390 if (bit_length > 32) { 391 ND_PRINT((ndo, "\n\t illegal prefix length %u",bit_length)); 392 break; 393 } 394 byte_length = (bit_length + 7) / 8; /* variable length encoding */ 395 memset(prefix, 0, 4); 396 ND_TCHECK2(tlv_ptr.eigrp_tlv_ip_ext->destination, byte_length); 397 memcpy(prefix,&tlv_ptr.eigrp_tlv_ip_ext->destination,byte_length); 398 399 ND_PRINT((ndo, "\n\t IPv4 prefix: %15s/%u, nexthop: ", 400 ipaddr_string(ndo, prefix), 401 bit_length)); 402 if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->nexthop) == 0) 403 ND_PRINT((ndo, "self")); 404 else 405 ND_PRINT((ndo, "%s",ipaddr_string(ndo, &tlv_ptr.eigrp_tlv_ip_ext->nexthop))); 406 407 ND_PRINT((ndo, "\n\t origin-router %s, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u", 408 ipaddr_string(ndo, tlv_ptr.eigrp_tlv_ip_ext->origin_router), 409 EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->origin_as), 410 tok2str(eigrp_ext_proto_id_values,"unknown",tlv_ptr.eigrp_tlv_ip_ext->proto_id), 411 tlv_ptr.eigrp_tlv_ip_ext->flags, 412 EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->tag), 413 EXTRACT_32BITS(tlv_ptr.eigrp_tlv_ip_ext->metric))); 414 415 ND_PRINT((ndo, "\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u", 416 (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->delay)/100), 417 EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_ip_ext->bandwidth), 418 EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_ip_ext->mtu), 419 tlv_ptr.eigrp_tlv_ip_ext->hopcount, 420 tlv_ptr.eigrp_tlv_ip_ext->reliability, 421 tlv_ptr.eigrp_tlv_ip_ext->load)); 422 break; 423 424 case EIGRP_TLV_AT_CABLE_SETUP: 425 tlv_ptr.eigrp_tlv_at_cable_setup = (const struct eigrp_tlv_at_cable_setup_t *)tlv_tptr; 426 if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_cable_setup)) { 427 ND_PRINT((ndo, " (too short, < %u)", 428 (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_cable_setup)))); 429 break; 430 } 431 432 ND_PRINT((ndo, "\n\t Cable-range: %u-%u, Router-ID %u", 433 EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->cable_start), 434 EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->cable_end), 435 EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_cable_setup->router_id))); 436 break; 437 438 case EIGRP_TLV_AT_INT: 439 tlv_ptr.eigrp_tlv_at_int = (const struct eigrp_tlv_at_int_t *)tlv_tptr; 440 if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_int)) { 441 ND_PRINT((ndo, " (too short, < %u)", 442 (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_int)))); 443 break; 444 } 445 446 ND_PRINT((ndo, "\n\t Cable-Range: %u-%u, nexthop: ", 447 EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->cable_start), 448 EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->cable_end))); 449 450 if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop) == 0) 451 ND_PRINT((ndo, "self")); 452 else 453 ND_PRINT((ndo, "%u.%u", 454 EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop), 455 EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_int->nexthop[2]))); 456 457 ND_PRINT((ndo, "\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u", 458 (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->delay)/100), 459 EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_int->bandwidth), 460 EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_at_int->mtu), 461 tlv_ptr.eigrp_tlv_at_int->hopcount, 462 tlv_ptr.eigrp_tlv_at_int->reliability, 463 tlv_ptr.eigrp_tlv_at_int->load)); 464 break; 465 466 case EIGRP_TLV_AT_EXT: 467 tlv_ptr.eigrp_tlv_at_ext = (const struct eigrp_tlv_at_ext_t *)tlv_tptr; 468 if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_ext)) { 469 ND_PRINT((ndo, " (too short, < %u)", 470 (u_int) (sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_ext)))); 471 break; 472 } 473 474 ND_PRINT((ndo, "\n\t Cable-Range: %u-%u, nexthop: ", 475 EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->cable_start), 476 EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->cable_end))); 477 478 if (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop) == 0) 479 ND_PRINT((ndo, "self")); 480 else 481 ND_PRINT((ndo, "%u.%u", 482 EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop), 483 EXTRACT_16BITS(&tlv_ptr.eigrp_tlv_at_ext->nexthop[2]))); 484 485 ND_PRINT((ndo, "\n\t origin-router %u, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u", 486 EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->origin_router), 487 EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->origin_as), 488 tok2str(eigrp_ext_proto_id_values,"unknown",tlv_ptr.eigrp_tlv_at_ext->proto_id), 489 tlv_ptr.eigrp_tlv_at_ext->flags, 490 EXTRACT_32BITS(tlv_ptr.eigrp_tlv_at_ext->tag), 491 EXTRACT_16BITS(tlv_ptr.eigrp_tlv_at_ext->metric))); 492 493 ND_PRINT((ndo, "\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u", 494 (EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->delay)/100), 495 EXTRACT_32BITS(&tlv_ptr.eigrp_tlv_at_ext->bandwidth), 496 EXTRACT_24BITS(&tlv_ptr.eigrp_tlv_at_ext->mtu), 497 tlv_ptr.eigrp_tlv_at_ext->hopcount, 498 tlv_ptr.eigrp_tlv_at_ext->reliability, 499 tlv_ptr.eigrp_tlv_at_ext->load)); 500 break; 501 502 /* 503 * FIXME those are the defined TLVs that lack a decoder 504 * you are welcome to contribute code ;-) 505 */ 506 507 case EIGRP_TLV_AUTH: 508 case EIGRP_TLV_SEQ: 509 case EIGRP_TLV_MCAST_SEQ: 510 case EIGRP_TLV_IPX_INT: 511 case EIGRP_TLV_IPX_EXT: 512 513 default: 514 if (ndo->ndo_vflag <= 1) 515 print_unknown_data(ndo,tlv_tptr,"\n\t ",tlv_tlen); 516 break; 517 } 518 /* do we want to see an additionally hexdump ? */ 519 if (ndo->ndo_vflag > 1) 520 print_unknown_data(ndo,tptr+sizeof(struct eigrp_tlv_header),"\n\t ", 521 eigrp_tlv_len-sizeof(struct eigrp_tlv_header)); 522 523 tptr+=eigrp_tlv_len; 524 tlen-=eigrp_tlv_len; 525 } 526 return; 527 trunc: 528 ND_PRINT((ndo, "\n\t\t packet exceeded snapshot")); 529 } 530