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