1/* 2 * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that: (1) source code distributions 7 * retain the above copyright notice and this paragraph in its entirety, (2) 8 * distributions including binary code include the above copyright notice and 9 * this paragraph in its entirety in the documentation or other materials 10 * provided with the distribution, and (3) all advertising materials mentioning 11 * features or use of this software display the following acknowledgement: 12 * ``This product includes software developed by the University of California, 13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14 * the University nor the names of its contributors may be used to endorse 15 * or promote products derived from this software without specific prior 16 * written permission. 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20 * 21 * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu) 22 */ 23 24#include <sys/cdefs.h> 25#ifndef lint 26__RCSID("$NetBSD: print-ospf.c,v 1.10 2023/08/17 20:19:40 christos Exp $"); 27#endif 28 29/* \summary: Open Shortest Path First (OSPF) printer */ 30 31#ifdef HAVE_CONFIG_H 32#include <config.h> 33#endif 34 35#include "netdissect-stdinc.h" 36 37#include "netdissect.h" 38#include "addrtoname.h" 39#include "extract.h" 40#include "gmpls.h" 41 42#include "ospf.h" 43 44 45static const struct tok ospf_option_values[] = { 46 { OSPF_OPTION_MT, "MultiTopology" }, /* draft-ietf-ospf-mt-09 */ 47 { OSPF_OPTION_E, "External" }, 48 { OSPF_OPTION_MC, "Multicast" }, 49 { OSPF_OPTION_NP, "NSSA" }, 50 { OSPF_OPTION_L, "LLS" }, 51 { OSPF_OPTION_DC, "Demand Circuit" }, 52 { OSPF_OPTION_O, "Opaque" }, 53 { OSPF_OPTION_DN, "Up/Down" }, 54 { 0, NULL } 55}; 56 57static const struct tok ospf_authtype_values[] = { 58 { OSPF_AUTH_NONE, "none" }, 59 { OSPF_AUTH_SIMPLE, "simple" }, 60 { OSPF_AUTH_MD5, "MD5" }, 61 { 0, NULL } 62}; 63 64static const struct tok ospf_rla_flag_values[] = { 65 { RLA_FLAG_B, "ABR" }, 66 { RLA_FLAG_E, "ASBR" }, 67 { RLA_FLAG_V, "Virtual" }, 68 { RLA_FLAG_W, "Wildcard" }, 69 { RLA_FLAG_NT, "Nt" }, 70 { RLA_FLAG_H, "Host" }, 71 { 0, NULL } 72}; 73 74static const struct tok type2str[] = { 75 { OSPF_TYPE_HELLO, "Hello" }, 76 { OSPF_TYPE_DD, "Database Description" }, 77 { OSPF_TYPE_LS_REQ, "LS-Request" }, 78 { OSPF_TYPE_LS_UPDATE, "LS-Update" }, 79 { OSPF_TYPE_LS_ACK, "LS-Ack" }, 80 { 0, NULL } 81}; 82 83static const struct tok lsa_values[] = { 84 { LS_TYPE_ROUTER, "Router" }, 85 { LS_TYPE_NETWORK, "Network" }, 86 { LS_TYPE_SUM_IP, "Summary" }, 87 { LS_TYPE_SUM_ABR, "ASBR Summary" }, 88 { LS_TYPE_ASE, "External" }, 89 { LS_TYPE_GROUP, "Multicast Group" }, 90 { LS_TYPE_NSSA, "NSSA" }, 91 { LS_TYPE_OPAQUE_LL, "Link Local Opaque" }, 92 { LS_TYPE_OPAQUE_AL, "Area Local Opaque" }, 93 { LS_TYPE_OPAQUE_DW, "Domain Wide Opaque" }, 94 { 0, NULL } 95}; 96 97static const struct tok ospf_dd_flag_values[] = { 98 { OSPF_DB_INIT, "Init" }, 99 { OSPF_DB_MORE, "More" }, 100 { OSPF_DB_MASTER, "Master" }, 101 { OSPF_DB_RESYNC, "OOBResync" }, 102 { 0, NULL } 103}; 104 105static const struct tok lsa_opaque_values[] = { 106 { LS_OPAQUE_TYPE_TE, "Traffic Engineering" }, 107 { LS_OPAQUE_TYPE_GRACE, "Graceful restart" }, 108 { LS_OPAQUE_TYPE_RI, "Router Information" }, 109 { 0, NULL } 110}; 111 112static const struct tok lsa_opaque_te_tlv_values[] = { 113 { LS_OPAQUE_TE_TLV_ROUTER, "Router Address" }, 114 { LS_OPAQUE_TE_TLV_LINK, "Link" }, 115 { 0, NULL } 116}; 117 118static const struct tok lsa_opaque_te_link_tlv_subtlv_values[] = { 119 { LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE, "Link Type" }, 120 { LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID, "Link ID" }, 121 { LS_OPAQUE_TE_LINK_SUBTLV_LOCAL_IP, "Local Interface IP address" }, 122 { LS_OPAQUE_TE_LINK_SUBTLV_REMOTE_IP, "Remote Interface IP address" }, 123 { LS_OPAQUE_TE_LINK_SUBTLV_TE_METRIC, "Traffic Engineering Metric" }, 124 { LS_OPAQUE_TE_LINK_SUBTLV_MAX_BW, "Maximum Bandwidth" }, 125 { LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW, "Maximum Reservable Bandwidth" }, 126 { LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW, "Unreserved Bandwidth" }, 127 { LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP, "Administrative Group" }, 128 { LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID, "Link Local/Remote Identifier" }, 129 { LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE, "Link Protection Type" }, 130 { LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR, "Interface Switching Capability" }, 131 { LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP, "Shared Risk Link Group" }, 132 { LS_OPAQUE_TE_LINK_SUBTLV_BW_CONSTRAINTS, "Bandwidth Constraints" }, 133 { 0, NULL } 134}; 135 136static const struct tok lsa_opaque_grace_tlv_values[] = { 137 { LS_OPAQUE_GRACE_TLV_PERIOD, "Grace Period" }, 138 { LS_OPAQUE_GRACE_TLV_REASON, "Graceful restart Reason" }, 139 { LS_OPAQUE_GRACE_TLV_INT_ADDRESS, "IPv4 interface address" }, 140 { 0, NULL } 141}; 142 143static const struct tok lsa_opaque_grace_tlv_reason_values[] = { 144 { LS_OPAQUE_GRACE_TLV_REASON_UNKNOWN, "Unknown" }, 145 { LS_OPAQUE_GRACE_TLV_REASON_SW_RESTART, "Software Restart" }, 146 { LS_OPAQUE_GRACE_TLV_REASON_SW_UPGRADE, "Software Reload/Upgrade" }, 147 { LS_OPAQUE_GRACE_TLV_REASON_CP_SWITCH, "Control Processor Switch" }, 148 { 0, NULL } 149}; 150 151static const struct tok lsa_opaque_te_tlv_link_type_sub_tlv_values[] = { 152 { LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_PTP, "Point-to-point" }, 153 { LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_MA, "Multi-Access" }, 154 { 0, NULL } 155}; 156 157static const struct tok lsa_opaque_ri_tlv_values[] = { 158 { LS_OPAQUE_RI_TLV_CAP, "Router Capabilities" }, 159 { 0, NULL } 160}; 161 162static const struct tok lsa_opaque_ri_tlv_cap_values[] = { 163 { 1, "Reserved" }, 164 { 2, "Reserved" }, 165 { 4, "Reserved" }, 166 { 8, "Reserved" }, 167 { 16, "graceful restart capable" }, 168 { 32, "graceful restart helper" }, 169 { 64, "Stub router support" }, 170 { 128, "Traffic engineering" }, 171 { 256, "p2p over LAN" }, 172 { 512, "path computation server" }, 173 { 0, NULL } 174}; 175 176static const struct tok ospf_lls_tlv_values[] = { 177 { OSPF_LLS_EO, "Extended Options" }, 178 { OSPF_LLS_MD5, "MD5 Authentication" }, 179 { 0, NULL } 180}; 181 182static const struct tok ospf_lls_eo_options[] = { 183 { OSPF_LLS_EO_LR, "LSDB resync" }, 184 { OSPF_LLS_EO_RS, "Restart" }, 185 { 0, NULL } 186}; 187 188int 189ospf_grace_lsa_print(netdissect_options *ndo, 190 const u_char *tptr, u_int ls_length) 191{ 192 u_int tlv_type, tlv_length; 193 194 195 while (ls_length > 0) { 196 ND_TCHECK_4(tptr); 197 if (ls_length < 4) { 198 ND_PRINT("\n\t Remaining LS length %u < 4", ls_length); 199 return -1; 200 } 201 tlv_type = GET_BE_U_2(tptr); 202 tlv_length = GET_BE_U_2(tptr + 2); 203 tptr+=4; 204 ls_length-=4; 205 206 ND_PRINT("\n\t %s TLV (%u), length %u, value: ", 207 tok2str(lsa_opaque_grace_tlv_values,"unknown",tlv_type), 208 tlv_type, 209 tlv_length); 210 211 if (tlv_length > ls_length) { 212 ND_PRINT("\n\t Bogus length %u > %u", tlv_length, 213 ls_length); 214 return -1; 215 } 216 217 /* Infinite loop protection. */ 218 if (tlv_type == 0 || tlv_length ==0) { 219 return -1; 220 } 221 222 ND_TCHECK_LEN(tptr, tlv_length); 223 switch(tlv_type) { 224 225 case LS_OPAQUE_GRACE_TLV_PERIOD: 226 if (tlv_length != 4) { 227 ND_PRINT("\n\t Bogus length %u != 4", tlv_length); 228 return -1; 229 } 230 ND_PRINT("%us", GET_BE_U_4(tptr)); 231 break; 232 233 case LS_OPAQUE_GRACE_TLV_REASON: 234 if (tlv_length != 1) { 235 ND_PRINT("\n\t Bogus length %u != 1", tlv_length); 236 return -1; 237 } 238 ND_PRINT("%s (%u)", 239 tok2str(lsa_opaque_grace_tlv_reason_values, "Unknown", GET_U_1(tptr)), 240 GET_U_1(tptr)); 241 break; 242 243 case LS_OPAQUE_GRACE_TLV_INT_ADDRESS: 244 if (tlv_length != 4) { 245 ND_PRINT("\n\t Bogus length %u != 4", tlv_length); 246 return -1; 247 } 248 ND_PRINT("%s", GET_IPADDR_STRING(tptr)); 249 break; 250 251 default: 252 if (ndo->ndo_vflag <= 1) { 253 if (!print_unknown_data(ndo, tptr, "\n\t ", tlv_length)) 254 return -1; 255 } 256 break; 257 258 } 259 /* in OSPF everything has to be 32-bit aligned, including TLVs */ 260 if (tlv_length%4 != 0) 261 tlv_length+=4-(tlv_length%4); 262 ls_length-=tlv_length; 263 tptr+=tlv_length; 264 } 265 266 return 0; 267trunc: 268 return -1; 269} 270 271int 272ospf_te_lsa_print(netdissect_options *ndo, 273 const u_char *tptr, u_int ls_length) 274{ 275 u_int tlv_type, tlv_length, subtlv_type, subtlv_length; 276 u_int priority_level, te_class, count_srlg; 277 union { /* int to float conversion buffer for several subTLVs */ 278 float f; 279 uint32_t i; 280 } bw; 281 282 while (ls_length != 0) { 283 ND_TCHECK_4(tptr); 284 if (ls_length < 4) { 285 ND_PRINT("\n\t Remaining LS length %u < 4", ls_length); 286 return -1; 287 } 288 tlv_type = GET_BE_U_2(tptr); 289 tlv_length = GET_BE_U_2(tptr + 2); 290 tptr+=4; 291 ls_length-=4; 292 293 ND_PRINT("\n\t %s TLV (%u), length: %u", 294 tok2str(lsa_opaque_te_tlv_values,"unknown",tlv_type), 295 tlv_type, 296 tlv_length); 297 298 if (tlv_length > ls_length) { 299 ND_PRINT("\n\t Bogus length %u > %u", tlv_length, 300 ls_length); 301 return -1; 302 } 303 304 /* Infinite loop protection. */ 305 if (tlv_type == 0 || tlv_length ==0) { 306 return -1; 307 } 308 309 switch(tlv_type) { 310 case LS_OPAQUE_TE_TLV_LINK: 311 while (tlv_length != 0) { 312 if (tlv_length < 4) { 313 ND_PRINT("\n\t Remaining TLV length %u < 4", 314 tlv_length); 315 return -1; 316 } 317 subtlv_type = GET_BE_U_2(tptr); 318 subtlv_length = GET_BE_U_2(tptr + 2); 319 tptr+=4; 320 tlv_length-=4; 321 322 /* Infinite loop protection */ 323 if (subtlv_type == 0 || subtlv_length == 0) 324 goto invalid; 325 326 ND_PRINT("\n\t %s subTLV (%u), length: %u", 327 tok2str(lsa_opaque_te_link_tlv_subtlv_values,"unknown",subtlv_type), 328 subtlv_type, 329 subtlv_length); 330 331 if (tlv_length < subtlv_length) { 332 ND_PRINT("\n\t Remaining TLV length %u < %u", 333 tlv_length + 4, subtlv_length + 4); 334 return -1; 335 } 336 ND_TCHECK_LEN(tptr, subtlv_length); 337 switch(subtlv_type) { 338 case LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP: 339 if (subtlv_length != 4) { 340 ND_PRINT(" != 4"); 341 goto invalid; 342 } 343 ND_PRINT(", 0x%08x", GET_BE_U_4(tptr)); 344 break; 345 case LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID: 346 case LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID: 347 if (subtlv_length != 4 && subtlv_length != 8) { 348 ND_PRINT(" != 4 && != 8"); 349 goto invalid; 350 } 351 ND_PRINT(", %s (0x%08x)", 352 GET_IPADDR_STRING(tptr), 353 GET_BE_U_4(tptr)); 354 if (subtlv_length == 8) /* rfc4203 */ 355 ND_PRINT(", %s (0x%08x)", 356 GET_IPADDR_STRING(tptr+4), 357 GET_BE_U_4(tptr + 4)); 358 break; 359 case LS_OPAQUE_TE_LINK_SUBTLV_LOCAL_IP: 360 case LS_OPAQUE_TE_LINK_SUBTLV_REMOTE_IP: 361 if (subtlv_length != 4) { 362 ND_PRINT(" != 4"); 363 goto invalid; 364 } 365 ND_PRINT(", %s", GET_IPADDR_STRING(tptr)); 366 break; 367 case LS_OPAQUE_TE_LINK_SUBTLV_MAX_BW: 368 case LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW: 369 if (subtlv_length != 4) { 370 ND_PRINT(" != 4"); 371 goto invalid; 372 } 373 bw.i = GET_BE_U_4(tptr); 374 ND_PRINT(", %.3f Mbps", bw.f * 8 / 1000000); 375 break; 376 case LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW: 377 if (subtlv_length != 32) { 378 ND_PRINT(" != 32"); 379 goto invalid; 380 } 381 for (te_class = 0; te_class < 8; te_class++) { 382 bw.i = GET_BE_U_4(tptr + te_class * 4); 383 ND_PRINT("\n\t\tTE-Class %u: %.3f Mbps", 384 te_class, 385 bw.f * 8 / 1000000); 386 } 387 break; 388 case LS_OPAQUE_TE_LINK_SUBTLV_BW_CONSTRAINTS: 389 if (subtlv_length < 4) { 390 ND_PRINT(" < 4"); 391 goto invalid; 392 } 393 /* BC Model Id (1 octet) + Reserved (3 octets) */ 394 ND_PRINT("\n\t\tBandwidth Constraints Model ID: %s (%u)", 395 tok2str(diffserv_te_bc_values, "unknown", GET_U_1(tptr)), 396 GET_U_1(tptr)); 397 if (subtlv_length % 4 != 0) { 398 ND_PRINT("\n\t\tlength %u != N x 4", subtlv_length); 399 goto invalid; 400 } 401 if (subtlv_length > 36) { 402 ND_PRINT("\n\t\tlength %u > 36", subtlv_length); 403 goto invalid; 404 } 405 /* decode BCs until the subTLV ends */ 406 for (te_class = 0; te_class < (subtlv_length-4)/4; te_class++) { 407 bw.i = GET_BE_U_4(tptr + 4 + te_class * 4); 408 ND_PRINT("\n\t\t Bandwidth constraint CT%u: %.3f Mbps", 409 te_class, 410 bw.f * 8 / 1000000); 411 } 412 break; 413 case LS_OPAQUE_TE_LINK_SUBTLV_TE_METRIC: 414 if (subtlv_length != 4) { 415 ND_PRINT(" != 4"); 416 goto invalid; 417 } 418 ND_PRINT(", Metric %u", GET_BE_U_4(tptr)); 419 break; 420 case LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE: 421 /* Protection Cap (1 octet) + Reserved ((3 octets) */ 422 if (subtlv_length != 4) { 423 ND_PRINT(" != 4"); 424 goto invalid; 425 } 426 ND_PRINT(", %s", 427 bittok2str(gmpls_link_prot_values, "none", GET_U_1(tptr))); 428 break; 429 case LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR: 430 if (subtlv_length < 36) { 431 ND_PRINT(" < 36"); 432 goto invalid; 433 } 434 /* Switching Cap (1 octet) + Encoding (1) + Reserved (2) */ 435 ND_PRINT("\n\t\tInterface Switching Capability: %s", 436 tok2str(gmpls_switch_cap_values, "Unknown", GET_U_1((tptr)))); 437 ND_PRINT("\n\t\tLSP Encoding: %s\n\t\tMax LSP Bandwidth:", 438 tok2str(gmpls_encoding_values, "Unknown", GET_U_1((tptr + 1)))); 439 for (priority_level = 0; priority_level < 8; priority_level++) { 440 bw.i = GET_BE_U_4(tptr + 4 + (priority_level * 4)); 441 ND_PRINT("\n\t\t priority level %u: %.3f Mbps", 442 priority_level, 443 bw.f * 8 / 1000000); 444 } 445 break; 446 case LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE: 447 if (subtlv_length != 1) { 448 ND_PRINT(" != 1"); 449 goto invalid; 450 } 451 ND_PRINT(", %s (%u)", 452 tok2str(lsa_opaque_te_tlv_link_type_sub_tlv_values,"unknown",GET_U_1(tptr)), 453 GET_U_1(tptr)); 454 break; 455 456 case LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP: 457 if (subtlv_length % 4 != 0) { 458 ND_PRINT(" != N x 4"); 459 goto invalid; 460 } 461 count_srlg = subtlv_length / 4; 462 if (count_srlg != 0) 463 ND_PRINT("\n\t\t Shared risk group: "); 464 while (count_srlg > 0) { 465 bw.i = GET_BE_U_4(tptr); 466 ND_PRINT("%u", bw.i); 467 tptr+=4; 468 count_srlg--; 469 if (count_srlg > 0) 470 ND_PRINT(", "); 471 } 472 break; 473 474 default: 475 if (ndo->ndo_vflag <= 1) { 476 if (!print_unknown_data(ndo, tptr, "\n\t\t", subtlv_length)) 477 return -1; 478 } 479 break; 480 } 481 /* in OSPF everything has to be 32-bit aligned, including subTLVs */ 482 if (subtlv_length%4 != 0) 483 subtlv_length+=4-(subtlv_length%4); 484 485 if (tlv_length < subtlv_length) { 486 ND_PRINT("\n\t Remaining TLV length %u < %u", 487 tlv_length + 4, subtlv_length + 4); 488 return -1; 489 } 490 tlv_length-=subtlv_length; 491 tptr+=subtlv_length; 492 493 } 494 break; 495 496 case LS_OPAQUE_TE_TLV_ROUTER: 497 if (tlv_length < 4) { 498 ND_PRINT("\n\t TLV length %u < 4", tlv_length); 499 return -1; 500 } 501 ND_PRINT(", %s", GET_IPADDR_STRING(tptr)); 502 break; 503 504 default: 505 if (ndo->ndo_vflag <= 1) { 506 if (!print_unknown_data(ndo, tptr, "\n\t ", tlv_length)) 507 return -1; 508 } 509 break; 510 } 511 /* in OSPF everything has to be 32-bit aligned, including TLVs */ 512 if (tlv_length%4 != 0) 513 tlv_length+=4-(tlv_length%4); 514 if (tlv_length > ls_length) { 515 ND_PRINT("\n\t Bogus padded length %u > %u", tlv_length, 516 ls_length); 517 return -1; 518 } 519 ls_length-=tlv_length; 520 tptr+=tlv_length; 521 } 522 return 0; 523trunc: 524 return -1; 525invalid: 526 nd_print_invalid(ndo); 527 return -1; 528} 529 530static int 531ospf_print_lshdr(netdissect_options *ndo, 532 const struct lsa_hdr *lshp) 533{ 534 u_int ls_type; 535 u_int ls_length; 536 537 ls_length = GET_BE_U_2(lshp->ls_length); 538 if (ls_length < sizeof(struct lsa_hdr)) { 539 ND_PRINT("\n\t Bogus length %u < header (%zu)", ls_length, 540 sizeof(struct lsa_hdr)); 541 return(-1); 542 } 543 ND_PRINT("\n\t Advertising Router %s, seq 0x%08x, age %us, length %zu", 544 GET_IPADDR_STRING(lshp->ls_router), 545 GET_BE_U_4(lshp->ls_seq), 546 GET_BE_U_2(lshp->ls_age), 547 ls_length - sizeof(struct lsa_hdr)); 548 ls_type = GET_U_1(lshp->ls_type); 549 switch (ls_type) { 550 /* the LSA header for opaque LSAs was slightly changed */ 551 case LS_TYPE_OPAQUE_LL: 552 case LS_TYPE_OPAQUE_AL: 553 case LS_TYPE_OPAQUE_DW: 554 ND_PRINT("\n\t %s LSA (%u), Opaque-Type %s LSA (%u), Opaque-ID %u", 555 tok2str(lsa_values,"unknown",ls_type), 556 ls_type, 557 558 tok2str(lsa_opaque_values, 559 "unknown", 560 GET_U_1(lshp->un_lsa_id.opaque_field.opaque_type)), 561 GET_U_1(lshp->un_lsa_id.opaque_field.opaque_type), 562 GET_BE_U_3(lshp->un_lsa_id.opaque_field.opaque_id) 563 564 ); 565 break; 566 567 /* all other LSA types use regular style LSA headers */ 568 default: 569 ND_PRINT("\n\t %s LSA (%u), LSA-ID: %s", 570 tok2str(lsa_values,"unknown",ls_type), 571 ls_type, 572 GET_IPADDR_STRING(lshp->un_lsa_id.lsa_id)); 573 break; 574 } 575 ND_PRINT("\n\t Options: [%s]", 576 bittok2str(ospf_option_values, "none", GET_U_1(lshp->ls_options))); 577 578 return (ls_length); 579} 580 581/* draft-ietf-ospf-mt-09 */ 582static const struct tok ospf_topology_values[] = { 583 { 0, "default" }, 584 { 1, "multicast" }, 585 { 2, "management" }, 586 { 0, NULL } 587}; 588 589/* 590 * Print all the per-topology metrics. 591 */ 592static void 593ospf_print_tos_metrics(netdissect_options *ndo, 594 const union un_tos *tos) 595{ 596 u_int metric_count; 597 u_int toscount; 598 u_int tos_type; 599 600 toscount = GET_U_1(tos->link.link_tos_count)+1; 601 metric_count = 0; 602 603 /* 604 * All but the first metric contain a valid topology id. 605 */ 606 while (toscount != 0) { 607 tos_type = GET_U_1(tos->metrics.tos_type); 608 ND_PRINT("\n\t\ttopology %s (%u), metric %u", 609 tok2str(ospf_topology_values, "Unknown", 610 metric_count ? tos_type : 0), 611 metric_count ? tos_type : 0, 612 GET_BE_U_2(tos->metrics.tos_metric)); 613 metric_count++; 614 tos++; 615 toscount--; 616 } 617} 618 619/* 620 * Print a single link state advertisement. If truncated or if LSA length 621 * field is less than the length of the LSA header, return NULl, else 622 * return pointer to data past end of LSA. 623 */ 624static const uint8_t * 625ospf_print_lsa(netdissect_options *ndo, 626 const struct lsa *lsap) 627{ 628 const uint8_t *ls_end; 629 const struct rlalink *rlp; 630 const nd_ipv4 *ap; 631 const struct aslametric *almp; 632 const struct mcla *mcp; 633 const uint8_t *lp; 634 u_int tlv_type, tlv_length, rla_count, topology; 635 int ospf_print_lshdr_ret; 636 u_int ls_length; 637 const uint8_t *tptr; 638 639 tptr = (const uint8_t *)lsap->lsa_un.un_unknown; /* squelch compiler warnings */ 640 ospf_print_lshdr_ret = ospf_print_lshdr(ndo, &lsap->ls_hdr); 641 if (ospf_print_lshdr_ret < 0) 642 return(NULL); 643 ls_length = (u_int)ospf_print_lshdr_ret; 644 ls_end = (const uint8_t *)lsap + ls_length; 645 /* 646 * ospf_print_lshdr() returns -1 if the length is too short, 647 * so we know ls_length is >= sizeof(struct lsa_hdr). 648 */ 649 ls_length -= sizeof(struct lsa_hdr); 650 651 switch (GET_U_1(lsap->ls_hdr.ls_type)) { 652 653 case LS_TYPE_ROUTER: 654 ND_PRINT("\n\t Router LSA Options: [%s]", 655 bittok2str(ospf_rla_flag_values, "none", GET_U_1(lsap->lsa_un.un_rla.rla_flags))); 656 657 rla_count = GET_BE_U_2(lsap->lsa_un.un_rla.rla_count); 658 ND_TCHECK_SIZE(lsap->lsa_un.un_rla.rla_link); 659 rlp = lsap->lsa_un.un_rla.rla_link; 660 for (u_int i = rla_count; i != 0; i--) { 661 ND_TCHECK_SIZE(rlp); 662 switch (GET_U_1(rlp->un_tos.link.link_type)) { 663 664 case RLA_TYPE_VIRTUAL: 665 ND_PRINT("\n\t Virtual Link: Neighbor Router-ID: %s, Interface Address: %s", 666 GET_IPADDR_STRING(rlp->link_id), 667 GET_IPADDR_STRING(rlp->link_data)); 668 break; 669 670 case RLA_TYPE_ROUTER: 671 ND_PRINT("\n\t Neighbor Router-ID: %s, Interface Address: %s", 672 GET_IPADDR_STRING(rlp->link_id), 673 GET_IPADDR_STRING(rlp->link_data)); 674 break; 675 676 case RLA_TYPE_TRANSIT: 677 ND_PRINT("\n\t Neighbor Network-ID: %s, Interface Address: %s", 678 GET_IPADDR_STRING(rlp->link_id), 679 GET_IPADDR_STRING(rlp->link_data)); 680 break; 681 682 case RLA_TYPE_STUB: 683 ND_PRINT("\n\t Stub Network: %s, Mask: %s", 684 GET_IPADDR_STRING(rlp->link_id), 685 GET_IPADDR_STRING(rlp->link_data)); 686 break; 687 688 default: 689 ND_PRINT("\n\t Unknown Router Link Type (%u)", 690 GET_U_1(rlp->un_tos.link.link_type)); 691 return (ls_end); 692 } 693 694 ospf_print_tos_metrics(ndo, &rlp->un_tos); 695 696 rlp = (const struct rlalink *)((const u_char *)(rlp + 1) + 697 (GET_U_1(rlp->un_tos.link.link_tos_count) * sizeof(union un_tos))); 698 } 699 break; 700 701 case LS_TYPE_NETWORK: 702 ND_PRINT("\n\t Mask %s\n\t Connected Routers:", 703 GET_IPADDR_STRING(lsap->lsa_un.un_nla.nla_mask)); 704 ap = lsap->lsa_un.un_nla.nla_router; 705 while ((const u_char *)ap < ls_end) { 706 ND_PRINT("\n\t %s", GET_IPADDR_STRING(ap)); 707 ++ap; 708 } 709 break; 710 711 case LS_TYPE_SUM_IP: 712 ND_TCHECK_4(lsap->lsa_un.un_nla.nla_mask); 713 ND_PRINT("\n\t Mask %s", 714 GET_IPADDR_STRING(lsap->lsa_un.un_sla.sla_mask)); 715 ND_TCHECK_SIZE(lsap->lsa_un.un_sla.sla_tosmetric); 716 lp = (const uint8_t *)lsap->lsa_un.un_sla.sla_tosmetric; 717 while (lp < ls_end) { 718 uint32_t ul; 719 720 ul = GET_BE_U_4(lp); 721 topology = (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS; 722 ND_PRINT("\n\t\ttopology %s (%u) metric %u", 723 tok2str(ospf_topology_values, "Unknown", topology), 724 topology, 725 ul & SLA_MASK_METRIC); 726 lp += 4; 727 } 728 break; 729 730 case LS_TYPE_SUM_ABR: 731 ND_TCHECK_SIZE(lsap->lsa_un.un_sla.sla_tosmetric); 732 lp = (const uint8_t *)lsap->lsa_un.un_sla.sla_tosmetric; 733 while (lp < ls_end) { 734 uint32_t ul; 735 736 ul = GET_BE_U_4(lp); 737 topology = (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS; 738 ND_PRINT("\n\t\ttopology %s (%u) metric %u", 739 tok2str(ospf_topology_values, "Unknown", topology), 740 topology, 741 ul & SLA_MASK_METRIC); 742 lp += 4; 743 } 744 break; 745 746 case LS_TYPE_ASE: 747 case LS_TYPE_NSSA: /* fall through - those LSAs share the same format */ 748 ND_TCHECK_4(lsap->lsa_un.un_nla.nla_mask); 749 ND_PRINT("\n\t Mask %s", 750 GET_IPADDR_STRING(lsap->lsa_un.un_asla.asla_mask)); 751 752 ND_TCHECK_SIZE(lsap->lsa_un.un_sla.sla_tosmetric); 753 almp = lsap->lsa_un.un_asla.asla_metric; 754 while ((const u_char *)almp < ls_end) { 755 uint32_t ul; 756 757 ul = GET_BE_U_4(almp->asla_tosmetric); 758 topology = ((ul & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS); 759 ND_PRINT("\n\t\ttopology %s (%u), type %u, metric", 760 tok2str(ospf_topology_values, "Unknown", topology), 761 topology, 762 (ul & ASLA_FLAG_EXTERNAL) ? 2 : 1); 763 if ((ul & ASLA_MASK_METRIC) == 0xffffff) 764 ND_PRINT(" infinite"); 765 else 766 ND_PRINT(" %u", (ul & ASLA_MASK_METRIC)); 767 768 if (GET_IPV4_TO_NETWORK_ORDER(almp->asla_forward) != 0) { 769 ND_PRINT(", forward %s", GET_IPADDR_STRING(almp->asla_forward)); 770 } 771 if (GET_IPV4_TO_NETWORK_ORDER(almp->asla_tag) != 0) { 772 ND_PRINT(", tag %s", GET_IPADDR_STRING(almp->asla_tag)); 773 } 774 ++almp; 775 } 776 break; 777 778 case LS_TYPE_GROUP: 779 /* Multicast extensions as of 23 July 1991 */ 780 mcp = lsap->lsa_un.un_mcla; 781 while ((const u_char *)mcp < ls_end) { 782 switch (GET_BE_U_4(mcp->mcla_vtype)) { 783 784 case MCLA_VERTEX_ROUTER: 785 ND_PRINT("\n\t Router Router-ID %s", 786 GET_IPADDR_STRING(mcp->mcla_vid)); 787 break; 788 789 case MCLA_VERTEX_NETWORK: 790 ND_PRINT("\n\t Network Designated Router %s", 791 GET_IPADDR_STRING(mcp->mcla_vid)); 792 break; 793 794 default: 795 ND_PRINT("\n\t unknown VertexType (%u)", 796 GET_BE_U_4(mcp->mcla_vtype)); 797 break; 798 } 799 ++mcp; 800 } 801 break; 802 803 case LS_TYPE_OPAQUE_LL: /* fall through */ 804 case LS_TYPE_OPAQUE_AL: 805 case LS_TYPE_OPAQUE_DW: 806 807 switch (GET_U_1(lsap->ls_hdr.un_lsa_id.opaque_field.opaque_type)) { 808 case LS_OPAQUE_TYPE_RI: 809 tptr = (const uint8_t *)(lsap->lsa_un.un_ri_tlv); 810 811 u_int ls_length_remaining = ls_length; 812 while (ls_length_remaining != 0) { 813 ND_TCHECK_4(tptr); 814 if (ls_length_remaining < 4) { 815 ND_PRINT("\n\t Remaining LS length %u < 4", ls_length_remaining); 816 return(ls_end); 817 } 818 tlv_type = GET_BE_U_2(tptr); 819 tlv_length = GET_BE_U_2(tptr + 2); 820 tptr+=4; 821 ls_length_remaining-=4; 822 823 ND_PRINT("\n\t %s TLV (%u), length: %u, value: ", 824 tok2str(lsa_opaque_ri_tlv_values,"unknown",tlv_type), 825 tlv_type, 826 tlv_length); 827 828 if (tlv_length > ls_length_remaining) { 829 ND_PRINT("\n\t Bogus length %u > remaining LS length %u", tlv_length, 830 ls_length_remaining); 831 return(ls_end); 832 } 833 ND_TCHECK_LEN(tptr, tlv_length); 834 switch(tlv_type) { 835 836 case LS_OPAQUE_RI_TLV_CAP: 837 if (tlv_length != 4) { 838 ND_PRINT("\n\t Bogus length %u != 4", tlv_length); 839 return(ls_end); 840 } 841 ND_PRINT("Capabilities: %s", 842 bittok2str(lsa_opaque_ri_tlv_cap_values, "Unknown", GET_BE_U_4(tptr))); 843 break; 844 default: 845 if (ndo->ndo_vflag <= 1) { 846 if (!print_unknown_data(ndo, tptr, "\n\t ", tlv_length)) 847 return(ls_end); 848 } 849 break; 850 851 } 852 tptr+=tlv_length; 853 ls_length_remaining-=tlv_length; 854 } 855 break; 856 857 case LS_OPAQUE_TYPE_GRACE: 858 if (ospf_grace_lsa_print(ndo, (const u_char *)(lsap->lsa_un.un_grace_tlv), 859 ls_length) == -1) { 860 return(ls_end); 861 } 862 break; 863 864 case LS_OPAQUE_TYPE_TE: 865 if (ospf_te_lsa_print(ndo, (const u_char *)(lsap->lsa_un.un_te_lsa_tlv), 866 ls_length) == -1) { 867 return(ls_end); 868 } 869 break; 870 871 default: 872 if (ndo->ndo_vflag <= 1) { 873 if (!print_unknown_data(ndo, (const uint8_t *)lsap->lsa_un.un_unknown, 874 "\n\t ", ls_length)) 875 return(ls_end); 876 } 877 break; 878 } 879 } 880 881 /* do we want to see an additionally hexdump ? */ 882 if (ndo->ndo_vflag> 1) 883 if (!print_unknown_data(ndo, (const uint8_t *)lsap->lsa_un.un_unknown, 884 "\n\t ", ls_length)) { 885 return(ls_end); 886 } 887 888 return (ls_end); 889trunc: 890 return (NULL); 891} 892 893static void 894ospf_decode_lls(netdissect_options *ndo, 895 const struct ospfhdr *op, u_int length) 896{ 897 const u_char *dptr; 898 const u_char *dataend; 899 u_int length2; 900 uint16_t lls_type, lls_len; 901 uint32_t lls_flags; 902 903 switch (GET_U_1(op->ospf_type)) { 904 905 case OSPF_TYPE_HELLO: 906 if (!(GET_U_1(op->ospf_hello.hello_options) & OSPF_OPTION_L)) 907 return; 908 break; 909 910 case OSPF_TYPE_DD: 911 if (!(GET_U_1(op->ospf_db.db_options) & OSPF_OPTION_L)) 912 return; 913 break; 914 915 default: 916 return; 917 } 918 919 /* dig deeper if LLS data is available; see RFC4813 */ 920 length2 = GET_BE_U_2(op->ospf_len); 921 dptr = (const u_char *)op + length2; 922 dataend = (const u_char *)op + length; 923 924 if (GET_BE_U_2(op->ospf_authtype) == OSPF_AUTH_MD5) { 925 dptr = dptr + GET_U_1(op->ospf_authdata + 3); 926 length2 += GET_U_1(op->ospf_authdata + 3); 927 } 928 if (length2 >= length) { 929 ND_PRINT("\n\t[LLS truncated]"); 930 return; 931 } 932 ND_PRINT("\n\t LLS: checksum: 0x%04x", (u_int) GET_BE_U_2(dptr)); 933 934 dptr += 2; 935 length2 = GET_BE_U_2(dptr); 936 ND_PRINT(", length: %u", length2); 937 938 dptr += 2; 939 while (dptr < dataend) { 940 lls_type = GET_BE_U_2(dptr); 941 ND_PRINT("\n\t %s (%u)", 942 tok2str(ospf_lls_tlv_values,"Unknown TLV",lls_type), 943 lls_type); 944 dptr += 2; 945 lls_len = GET_BE_U_2(dptr); 946 ND_PRINT(", length: %u", lls_len); 947 dptr += 2; 948 switch (lls_type) { 949 950 case OSPF_LLS_EO: 951 if (lls_len != 4) { 952 ND_PRINT(" [should be 4]"); 953 lls_len = 4; 954 } 955 lls_flags = GET_BE_U_4(dptr); 956 ND_PRINT("\n\t Options: 0x%08x [%s]", lls_flags, 957 bittok2str(ospf_lls_eo_options, "?", lls_flags)); 958 959 break; 960 961 case OSPF_LLS_MD5: 962 if (lls_len != 20) { 963 ND_PRINT(" [should be 20]"); 964 lls_len = 20; 965 } 966 ND_PRINT("\n\t Sequence number: 0x%08x", GET_BE_U_4(dptr)); 967 break; 968 } 969 970 dptr += lls_len; 971 } 972} 973 974static int 975ospf_decode_v2(netdissect_options *ndo, 976 const struct ospfhdr *op, const u_char *dataend) 977{ 978 const nd_ipv4 *ap; 979 const struct lsr *lsrp; 980 const struct lsa_hdr *lshp; 981 const struct lsa *lsap; 982 uint32_t lsa_count,lsa_count_max; 983 984 switch (GET_U_1(op->ospf_type)) { 985 986 case OSPF_TYPE_HELLO: 987 ND_PRINT("\n\tOptions [%s]", 988 bittok2str(ospf_option_values,"none",GET_U_1(op->ospf_hello.hello_options))); 989 990 ND_PRINT("\n\t Hello Timer %us, Dead Timer %us, Mask %s, Priority %u", 991 GET_BE_U_2(op->ospf_hello.hello_helloint), 992 GET_BE_U_4(op->ospf_hello.hello_deadint), 993 GET_IPADDR_STRING(op->ospf_hello.hello_mask), 994 GET_U_1(op->ospf_hello.hello_priority)); 995 996 if (GET_IPV4_TO_NETWORK_ORDER(op->ospf_hello.hello_dr) != 0) 997 ND_PRINT("\n\t Designated Router %s", 998 GET_IPADDR_STRING(op->ospf_hello.hello_dr)); 999 1000 if (GET_IPV4_TO_NETWORK_ORDER(op->ospf_hello.hello_bdr) != 0) 1001 ND_PRINT(", Backup Designated Router %s", 1002 GET_IPADDR_STRING(op->ospf_hello.hello_bdr)); 1003 1004 ap = op->ospf_hello.hello_neighbor; 1005 if ((const u_char *)ap < dataend) 1006 ND_PRINT("\n\t Neighbor List:"); 1007 while ((const u_char *)ap < dataend) { 1008 ND_PRINT("\n\t %s", GET_IPADDR_STRING(ap)); 1009 ++ap; 1010 } 1011 break; /* HELLO */ 1012 1013 case OSPF_TYPE_DD: 1014 ND_PRINT("\n\tOptions [%s]", 1015 bittok2str(ospf_option_values, "none", GET_U_1(op->ospf_db.db_options))); 1016 ND_PRINT(", DD Flags [%s]", 1017 bittok2str(ospf_dd_flag_values, "none", GET_U_1(op->ospf_db.db_flags))); 1018 if (GET_BE_U_2(op->ospf_db.db_ifmtu)) { 1019 ND_PRINT(", MTU: %u", 1020 GET_BE_U_2(op->ospf_db.db_ifmtu)); 1021 } 1022 ND_PRINT(", Sequence: 0x%08x", GET_BE_U_4(op->ospf_db.db_seq)); 1023 1024 /* Print all the LS adv's */ 1025 lshp = op->ospf_db.db_lshdr; 1026 while (((const u_char *)lshp < dataend) && ospf_print_lshdr(ndo, lshp) != -1) { 1027 ++lshp; 1028 } 1029 break; 1030 1031 case OSPF_TYPE_LS_REQ: 1032 lsrp = op->ospf_lsr; 1033 while ((const u_char *)lsrp < dataend) { 1034 ND_TCHECK_SIZE(lsrp); 1035 1036 ND_PRINT("\n\t Advertising Router: %s, %s LSA (%u)", 1037 GET_IPADDR_STRING(lsrp->ls_router), 1038 tok2str(lsa_values,"unknown",GET_BE_U_4(lsrp->ls_type)), 1039 GET_BE_U_4(lsrp->ls_type)); 1040 1041 switch (GET_BE_U_4(lsrp->ls_type)) { 1042 /* the LSA header for opaque LSAs was slightly changed */ 1043 case LS_TYPE_OPAQUE_LL: 1044 case LS_TYPE_OPAQUE_AL: 1045 case LS_TYPE_OPAQUE_DW: 1046 ND_PRINT(", Opaque-Type: %s LSA (%u), Opaque-ID: %u", 1047 tok2str(lsa_opaque_values, "unknown",GET_U_1(lsrp->un_ls_stateid.opaque_field.opaque_type)), 1048 GET_U_1(lsrp->un_ls_stateid.opaque_field.opaque_type), 1049 GET_BE_U_3(lsrp->un_ls_stateid.opaque_field.opaque_id)); 1050 break; 1051 default: 1052 ND_PRINT(", LSA-ID: %s", 1053 GET_IPADDR_STRING(lsrp->un_ls_stateid.ls_stateid)); 1054 break; 1055 } 1056 1057 ++lsrp; 1058 } 1059 break; 1060 1061 case OSPF_TYPE_LS_UPDATE: 1062 lsap = op->ospf_lsu.lsu_lsa; 1063 lsa_count_max = GET_BE_U_4(op->ospf_lsu.lsu_count); 1064 ND_PRINT(", %u LSA%s", lsa_count_max, PLURAL_SUFFIX(lsa_count_max)); 1065 for (lsa_count=1;lsa_count <= lsa_count_max;lsa_count++) { 1066 ND_PRINT("\n\t LSA #%u", lsa_count); 1067 lsap = (const struct lsa *)ospf_print_lsa(ndo, lsap); 1068 if (lsap == NULL) 1069 goto trunc; 1070 } 1071 break; 1072 1073 case OSPF_TYPE_LS_ACK: 1074 lshp = op->ospf_lsa.lsa_lshdr; 1075 while (ospf_print_lshdr(ndo, lshp) != -1) { 1076 ++lshp; 1077 } 1078 break; 1079 1080 default: 1081 break; 1082 } 1083 return (0); 1084trunc: 1085 return (1); 1086} 1087 1088void 1089ospf_print(netdissect_options *ndo, 1090 const u_char *bp, u_int length, 1091 const u_char *bp2 _U_) 1092{ 1093 const struct ospfhdr *op; 1094 const u_char *dataend; 1095 const char *cp; 1096 1097 ndo->ndo_protocol = "ospf2"; 1098 op = (const struct ospfhdr *)bp; 1099 1100 /* XXX Before we do anything else, strip off the MD5 trailer */ 1101 if (GET_BE_U_2(op->ospf_authtype) == OSPF_AUTH_MD5) { 1102 length -= OSPF_AUTH_MD5_LEN; 1103 ndo->ndo_snapend -= OSPF_AUTH_MD5_LEN; 1104 } 1105 1106 /* If the type is valid translate it, or just print the type */ 1107 /* value. If it's not valid, say so and return */ 1108 cp = tok2str(type2str, "unknown LS-type %u", GET_U_1(op->ospf_type)); 1109 ND_PRINT("OSPFv%u, %s, length %u", GET_U_1(op->ospf_version), cp, 1110 length); 1111 if (*cp == 'u') 1112 return; 1113 1114 if (!ndo->ndo_vflag) { /* non verbose - so lets bail out here */ 1115 return; 1116 } 1117 1118 if (length != GET_BE_U_2(op->ospf_len)) { 1119 ND_PRINT(" [len %u]", GET_BE_U_2(op->ospf_len)); 1120 } 1121 1122 if (length > GET_BE_U_2(op->ospf_len)) { 1123 dataend = bp + GET_BE_U_2(op->ospf_len); 1124 } else { 1125 dataend = bp + length; 1126 } 1127 1128 ND_PRINT("\n\tRouter-ID %s", GET_IPADDR_STRING(op->ospf_routerid)); 1129 1130 if (GET_IPV4_TO_NETWORK_ORDER(op->ospf_areaid) != 0) 1131 ND_PRINT(", Area %s", GET_IPADDR_STRING(op->ospf_areaid)); 1132 else 1133 ND_PRINT(", Backbone Area"); 1134 1135 if (ndo->ndo_vflag) { 1136 /* Print authentication data (should we really do this?) */ 1137 ND_TCHECK_LEN(op->ospf_authdata, sizeof(op->ospf_authdata)); 1138 1139 ND_PRINT(", Authentication Type: %s (%u)", 1140 tok2str(ospf_authtype_values, "unknown", GET_BE_U_2(op->ospf_authtype)), 1141 GET_BE_U_2(op->ospf_authtype)); 1142 1143 switch (GET_BE_U_2(op->ospf_authtype)) { 1144 1145 case OSPF_AUTH_NONE: 1146 break; 1147 1148 case OSPF_AUTH_SIMPLE: 1149 ND_PRINT("\n\tSimple text password: "); 1150 nd_printjnp(ndo, op->ospf_authdata, OSPF_AUTH_SIMPLE_LEN); 1151 break; 1152 1153 case OSPF_AUTH_MD5: 1154 ND_PRINT("\n\tKey-ID: %u, Auth-Length: %u, Crypto Sequence Number: 0x%08x", 1155 GET_U_1(op->ospf_authdata + 2), 1156 GET_U_1(op->ospf_authdata + 3), 1157 GET_BE_U_4((op->ospf_authdata) + 4)); 1158 break; 1159 1160 default: 1161 return; 1162 } 1163 } 1164 /* Do rest according to version. */ 1165 switch (GET_U_1(op->ospf_version)) { 1166 1167 case 2: 1168 /* ospf version 2 */ 1169 if (ospf_decode_v2(ndo, op, dataend)) 1170 goto trunc; 1171 if (length > GET_BE_U_2(op->ospf_len)) 1172 ospf_decode_lls(ndo, op, length); 1173 break; 1174 1175 default: 1176 ND_PRINT(" ospf [version %u]", GET_U_1(op->ospf_version)); 1177 break; 1178 } /* end switch on version */ 1179 1180 return; 1181trunc: 1182 nd_trunc_longjmp(ndo); 1183} 1184