10f74e101Schristos /* 20f74e101Schristos * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997 30f74e101Schristos * The Regents of the University of California. All rights reserved. 40f74e101Schristos * 50f74e101Schristos * Redistribution and use in source and binary forms, with or without 60f74e101Schristos * modification, are permitted provided that: (1) source code distributions 70f74e101Schristos * retain the above copyright notice and this paragraph in its entirety, (2) 80f74e101Schristos * distributions including binary code include the above copyright notice and 90f74e101Schristos * this paragraph in its entirety in the documentation or other materials 100f74e101Schristos * provided with the distribution, and (3) all advertising materials mentioning 110f74e101Schristos * features or use of this software display the following acknowledgement: 120f74e101Schristos * ``This product includes software developed by the University of California, 130f74e101Schristos * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 140f74e101Schristos * the University nor the names of its contributors may be used to endorse 150f74e101Schristos * or promote products derived from this software without specific prior 160f74e101Schristos * written permission. 170f74e101Schristos * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 180f74e101Schristos * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 190f74e101Schristos * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 200f74e101Schristos * 210f74e101Schristos * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu) 220f74e101Schristos */ 230f74e101Schristos 2411b3aaa1Schristos #include <sys/cdefs.h> 250f74e101Schristos #ifndef lint 26*26ba0b50Schristos __RCSID("$NetBSD: print-ospf.c,v 1.11 2024/09/02 16:15:32 christos Exp $"); 270f74e101Schristos #endif 280f74e101Schristos 29dc860a36Sspz /* \summary: Open Shortest Path First (OSPF) printer */ 30dc860a36Sspz 31c74ad251Schristos #include <config.h> 320f74e101Schristos 33c74ad251Schristos #include "netdissect-stdinc.h" 340f74e101Schristos 35fdccd7e4Schristos #include "netdissect.h" 360f74e101Schristos #include "addrtoname.h" 370f74e101Schristos #include "extract.h" 380f74e101Schristos #include "gmpls.h" 390f74e101Schristos 400f74e101Schristos #include "ospf.h" 410f74e101Schristos 420f74e101Schristos 43870189d2Schristos static const struct tok ospf_option_values[] = { 44c74ad251Schristos { OSPF_OPTION_MT, "MultiTopology" }, /* draft-ietf-ospf-mt-09 */ 450f74e101Schristos { OSPF_OPTION_E, "External" }, 460f74e101Schristos { OSPF_OPTION_MC, "Multicast" }, 470f74e101Schristos { OSPF_OPTION_NP, "NSSA" }, 480f74e101Schristos { OSPF_OPTION_L, "LLS" }, 490f74e101Schristos { OSPF_OPTION_DC, "Demand Circuit" }, 500f74e101Schristos { OSPF_OPTION_O, "Opaque" }, 510f74e101Schristos { OSPF_OPTION_DN, "Up/Down" }, 520f74e101Schristos { 0, NULL } 530f74e101Schristos }; 540f74e101Schristos 55870189d2Schristos static const struct tok ospf_authtype_values[] = { 560f74e101Schristos { OSPF_AUTH_NONE, "none" }, 570f74e101Schristos { OSPF_AUTH_SIMPLE, "simple" }, 580f74e101Schristos { OSPF_AUTH_MD5, "MD5" }, 590f74e101Schristos { 0, NULL } 600f74e101Schristos }; 610f74e101Schristos 62870189d2Schristos static const struct tok ospf_rla_flag_values[] = { 630f74e101Schristos { RLA_FLAG_B, "ABR" }, 640f74e101Schristos { RLA_FLAG_E, "ASBR" }, 65c74ad251Schristos { RLA_FLAG_V, "Virtual" }, 66c74ad251Schristos { RLA_FLAG_W, "Wildcard" }, 67c74ad251Schristos { RLA_FLAG_NT, "Nt" }, 68c74ad251Schristos { RLA_FLAG_H, "Host" }, 690f74e101Schristos { 0, NULL } 700f74e101Schristos }; 710f74e101Schristos 72870189d2Schristos static const struct tok type2str[] = { 730f74e101Schristos { OSPF_TYPE_HELLO, "Hello" }, 740f74e101Schristos { OSPF_TYPE_DD, "Database Description" }, 750f74e101Schristos { OSPF_TYPE_LS_REQ, "LS-Request" }, 760f74e101Schristos { OSPF_TYPE_LS_UPDATE, "LS-Update" }, 770f74e101Schristos { OSPF_TYPE_LS_ACK, "LS-Ack" }, 780f74e101Schristos { 0, NULL } 790f74e101Schristos }; 800f74e101Schristos 81870189d2Schristos static const struct tok lsa_values[] = { 820f74e101Schristos { LS_TYPE_ROUTER, "Router" }, 830f74e101Schristos { LS_TYPE_NETWORK, "Network" }, 840f74e101Schristos { LS_TYPE_SUM_IP, "Summary" }, 850f74e101Schristos { LS_TYPE_SUM_ABR, "ASBR Summary" }, 860f74e101Schristos { LS_TYPE_ASE, "External" }, 870f74e101Schristos { LS_TYPE_GROUP, "Multicast Group" }, 880f74e101Schristos { LS_TYPE_NSSA, "NSSA" }, 890f74e101Schristos { LS_TYPE_OPAQUE_LL, "Link Local Opaque" }, 900f74e101Schristos { LS_TYPE_OPAQUE_AL, "Area Local Opaque" }, 910f74e101Schristos { LS_TYPE_OPAQUE_DW, "Domain Wide Opaque" }, 920f74e101Schristos { 0, NULL } 930f74e101Schristos }; 940f74e101Schristos 95870189d2Schristos static const struct tok ospf_dd_flag_values[] = { 960f74e101Schristos { OSPF_DB_INIT, "Init" }, 970f74e101Schristos { OSPF_DB_MORE, "More" }, 980f74e101Schristos { OSPF_DB_MASTER, "Master" }, 990f74e101Schristos { OSPF_DB_RESYNC, "OOBResync" }, 1000f74e101Schristos { 0, NULL } 1010f74e101Schristos }; 1020f74e101Schristos 103870189d2Schristos static const struct tok lsa_opaque_values[] = { 1040f74e101Schristos { LS_OPAQUE_TYPE_TE, "Traffic Engineering" }, 1050f74e101Schristos { LS_OPAQUE_TYPE_GRACE, "Graceful restart" }, 1060f74e101Schristos { LS_OPAQUE_TYPE_RI, "Router Information" }, 1070f74e101Schristos { 0, NULL } 1080f74e101Schristos }; 1090f74e101Schristos 110870189d2Schristos static const struct tok lsa_opaque_te_tlv_values[] = { 1110f74e101Schristos { LS_OPAQUE_TE_TLV_ROUTER, "Router Address" }, 1120f74e101Schristos { LS_OPAQUE_TE_TLV_LINK, "Link" }, 1130f74e101Schristos { 0, NULL } 1140f74e101Schristos }; 1150f74e101Schristos 116870189d2Schristos static const struct tok lsa_opaque_te_link_tlv_subtlv_values[] = { 1170f74e101Schristos { LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE, "Link Type" }, 1180f74e101Schristos { LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID, "Link ID" }, 1190f74e101Schristos { LS_OPAQUE_TE_LINK_SUBTLV_LOCAL_IP, "Local Interface IP address" }, 1200f74e101Schristos { LS_OPAQUE_TE_LINK_SUBTLV_REMOTE_IP, "Remote Interface IP address" }, 1210f74e101Schristos { LS_OPAQUE_TE_LINK_SUBTLV_TE_METRIC, "Traffic Engineering Metric" }, 1220f74e101Schristos { LS_OPAQUE_TE_LINK_SUBTLV_MAX_BW, "Maximum Bandwidth" }, 1230f74e101Schristos { LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW, "Maximum Reservable Bandwidth" }, 1240f74e101Schristos { LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW, "Unreserved Bandwidth" }, 1250f74e101Schristos { LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP, "Administrative Group" }, 1260f74e101Schristos { LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID, "Link Local/Remote Identifier" }, 1270f74e101Schristos { LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE, "Link Protection Type" }, 1280f74e101Schristos { LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR, "Interface Switching Capability" }, 1290f74e101Schristos { LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP, "Shared Risk Link Group" }, 1300f74e101Schristos { LS_OPAQUE_TE_LINK_SUBTLV_BW_CONSTRAINTS, "Bandwidth Constraints" }, 1310f74e101Schristos { 0, NULL } 1320f74e101Schristos }; 1330f74e101Schristos 134870189d2Schristos static const struct tok lsa_opaque_grace_tlv_values[] = { 1350f74e101Schristos { LS_OPAQUE_GRACE_TLV_PERIOD, "Grace Period" }, 1360f74e101Schristos { LS_OPAQUE_GRACE_TLV_REASON, "Graceful restart Reason" }, 1370f74e101Schristos { LS_OPAQUE_GRACE_TLV_INT_ADDRESS, "IPv4 interface address" }, 1380f74e101Schristos { 0, NULL } 1390f74e101Schristos }; 1400f74e101Schristos 141870189d2Schristos static const struct tok lsa_opaque_grace_tlv_reason_values[] = { 1420f74e101Schristos { LS_OPAQUE_GRACE_TLV_REASON_UNKNOWN, "Unknown" }, 1430f74e101Schristos { LS_OPAQUE_GRACE_TLV_REASON_SW_RESTART, "Software Restart" }, 1440f74e101Schristos { LS_OPAQUE_GRACE_TLV_REASON_SW_UPGRADE, "Software Reload/Upgrade" }, 1450f74e101Schristos { LS_OPAQUE_GRACE_TLV_REASON_CP_SWITCH, "Control Processor Switch" }, 1460f74e101Schristos { 0, NULL } 1470f74e101Schristos }; 1480f74e101Schristos 149870189d2Schristos static const struct tok lsa_opaque_te_tlv_link_type_sub_tlv_values[] = { 1500f74e101Schristos { LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_PTP, "Point-to-point" }, 1510f74e101Schristos { LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_MA, "Multi-Access" }, 1520f74e101Schristos { 0, NULL } 1530f74e101Schristos }; 1540f74e101Schristos 155870189d2Schristos static const struct tok lsa_opaque_ri_tlv_values[] = { 1560f74e101Schristos { LS_OPAQUE_RI_TLV_CAP, "Router Capabilities" }, 1570f74e101Schristos { 0, NULL } 1580f74e101Schristos }; 1590f74e101Schristos 160870189d2Schristos static const struct tok lsa_opaque_ri_tlv_cap_values[] = { 1610f74e101Schristos { 1, "Reserved" }, 1620f74e101Schristos { 2, "Reserved" }, 1630f74e101Schristos { 4, "Reserved" }, 1640f74e101Schristos { 8, "Reserved" }, 1650f74e101Schristos { 16, "graceful restart capable" }, 1660f74e101Schristos { 32, "graceful restart helper" }, 1670f74e101Schristos { 64, "Stub router support" }, 1680f74e101Schristos { 128, "Traffic engineering" }, 1690f74e101Schristos { 256, "p2p over LAN" }, 1700f74e101Schristos { 512, "path computation server" }, 1710f74e101Schristos { 0, NULL } 1720f74e101Schristos }; 1730f74e101Schristos 174870189d2Schristos static const struct tok ospf_lls_tlv_values[] = { 1750f74e101Schristos { OSPF_LLS_EO, "Extended Options" }, 1760f74e101Schristos { OSPF_LLS_MD5, "MD5 Authentication" }, 1770f74e101Schristos { 0, NULL } 1780f74e101Schristos }; 1790f74e101Schristos 180870189d2Schristos static const struct tok ospf_lls_eo_options[] = { 1810f74e101Schristos { OSPF_LLS_EO_LR, "LSDB resync" }, 1820f74e101Schristos { OSPF_LLS_EO_RS, "Restart" }, 1830f74e101Schristos { 0, NULL } 1840f74e101Schristos }; 1850f74e101Schristos 1860f74e101Schristos int 187c74ad251Schristos ospf_grace_lsa_print(netdissect_options *ndo, 188c74ad251Schristos const u_char *tptr, u_int ls_length) 189ba2ff121Schristos { 1900f74e101Schristos u_int tlv_type, tlv_length; 1910f74e101Schristos 1920f74e101Schristos 1930f74e101Schristos while (ls_length > 0) { 194c74ad251Schristos ND_TCHECK_4(tptr); 1950f74e101Schristos if (ls_length < 4) { 196c74ad251Schristos ND_PRINT("\n\t Remaining LS length %u < 4", ls_length); 1970f74e101Schristos return -1; 1980f74e101Schristos } 199c74ad251Schristos tlv_type = GET_BE_U_2(tptr); 200c74ad251Schristos tlv_length = GET_BE_U_2(tptr + 2); 2010f74e101Schristos tptr+=4; 2020f74e101Schristos ls_length-=4; 2030f74e101Schristos 204c74ad251Schristos ND_PRINT("\n\t %s TLV (%u), length %u, value: ", 2050f74e101Schristos tok2str(lsa_opaque_grace_tlv_values,"unknown",tlv_type), 2060f74e101Schristos tlv_type, 207c74ad251Schristos tlv_length); 2080f74e101Schristos 2090f74e101Schristos if (tlv_length > ls_length) { 210c74ad251Schristos ND_PRINT("\n\t Bogus length %u > %u", tlv_length, 211c74ad251Schristos ls_length); 2120f74e101Schristos return -1; 2130f74e101Schristos } 2140f74e101Schristos 2150f74e101Schristos /* Infinite loop protection. */ 2160f74e101Schristos if (tlv_type == 0 || tlv_length ==0) { 2170f74e101Schristos return -1; 2180f74e101Schristos } 2190f74e101Schristos 220c74ad251Schristos ND_TCHECK_LEN(tptr, tlv_length); 2210f74e101Schristos switch(tlv_type) { 2220f74e101Schristos 2230f74e101Schristos case LS_OPAQUE_GRACE_TLV_PERIOD: 2240f74e101Schristos if (tlv_length != 4) { 225c74ad251Schristos ND_PRINT("\n\t Bogus length %u != 4", tlv_length); 2260f74e101Schristos return -1; 2270f74e101Schristos } 228c74ad251Schristos ND_PRINT("%us", GET_BE_U_4(tptr)); 2290f74e101Schristos break; 2300f74e101Schristos 2310f74e101Schristos case LS_OPAQUE_GRACE_TLV_REASON: 2320f74e101Schristos if (tlv_length != 1) { 233c74ad251Schristos ND_PRINT("\n\t Bogus length %u != 1", tlv_length); 2340f74e101Schristos return -1; 2350f74e101Schristos } 236c74ad251Schristos ND_PRINT("%s (%u)", 237c74ad251Schristos tok2str(lsa_opaque_grace_tlv_reason_values, "Unknown", GET_U_1(tptr)), 238c74ad251Schristos GET_U_1(tptr)); 2390f74e101Schristos break; 2400f74e101Schristos 2410f74e101Schristos case LS_OPAQUE_GRACE_TLV_INT_ADDRESS: 2420f74e101Schristos if (tlv_length != 4) { 243c74ad251Schristos ND_PRINT("\n\t Bogus length %u != 4", tlv_length); 2440f74e101Schristos return -1; 2450f74e101Schristos } 246c74ad251Schristos ND_PRINT("%s", GET_IPADDR_STRING(tptr)); 2470f74e101Schristos break; 2480f74e101Schristos 2490f74e101Schristos default: 250b3a00663Schristos if (ndo->ndo_vflag <= 1) { 251b3a00663Schristos if (!print_unknown_data(ndo, tptr, "\n\t ", tlv_length)) 2520f74e101Schristos return -1; 2530f74e101Schristos } 2540f74e101Schristos break; 2550f74e101Schristos 2560f74e101Schristos } 2570f74e101Schristos /* in OSPF everything has to be 32-bit aligned, including TLVs */ 2580f74e101Schristos if (tlv_length%4 != 0) 2590f74e101Schristos tlv_length+=4-(tlv_length%4); 2600f74e101Schristos ls_length-=tlv_length; 2610f74e101Schristos tptr+=tlv_length; 2620f74e101Schristos } 2630f74e101Schristos 2640f74e101Schristos return 0; 2650f74e101Schristos trunc: 2660f74e101Schristos return -1; 2670f74e101Schristos } 2680f74e101Schristos 2690f74e101Schristos int 270c74ad251Schristos ospf_te_lsa_print(netdissect_options *ndo, 271c74ad251Schristos const u_char *tptr, u_int ls_length) 272ba2ff121Schristos { 2730f74e101Schristos u_int tlv_type, tlv_length, subtlv_type, subtlv_length; 2740f74e101Schristos u_int priority_level, te_class, count_srlg; 2750f74e101Schristos union { /* int to float conversion buffer for several subTLVs */ 2760f74e101Schristos float f; 277b3a00663Schristos uint32_t i; 2780f74e101Schristos } bw; 2790f74e101Schristos 2800f74e101Schristos while (ls_length != 0) { 281c74ad251Schristos ND_TCHECK_4(tptr); 2820f74e101Schristos if (ls_length < 4) { 283c74ad251Schristos ND_PRINT("\n\t Remaining LS length %u < 4", ls_length); 2840f74e101Schristos return -1; 2850f74e101Schristos } 286c74ad251Schristos tlv_type = GET_BE_U_2(tptr); 287c74ad251Schristos tlv_length = GET_BE_U_2(tptr + 2); 2880f74e101Schristos tptr+=4; 2890f74e101Schristos ls_length-=4; 2900f74e101Schristos 291c74ad251Schristos ND_PRINT("\n\t %s TLV (%u), length: %u", 2920f74e101Schristos tok2str(lsa_opaque_te_tlv_values,"unknown",tlv_type), 2930f74e101Schristos tlv_type, 294c74ad251Schristos tlv_length); 2950f74e101Schristos 2960f74e101Schristos if (tlv_length > ls_length) { 297c74ad251Schristos ND_PRINT("\n\t Bogus length %u > %u", tlv_length, 298c74ad251Schristos ls_length); 2990f74e101Schristos return -1; 3000f74e101Schristos } 3010f74e101Schristos 3020f74e101Schristos /* Infinite loop protection. */ 3030f74e101Schristos if (tlv_type == 0 || tlv_length ==0) { 3040f74e101Schristos return -1; 3050f74e101Schristos } 3060f74e101Schristos 3070f74e101Schristos switch(tlv_type) { 3080f74e101Schristos case LS_OPAQUE_TE_TLV_LINK: 309c74ad251Schristos while (tlv_length != 0) { 3100f74e101Schristos if (tlv_length < 4) { 311c74ad251Schristos ND_PRINT("\n\t Remaining TLV length %u < 4", 312c74ad251Schristos tlv_length); 3130f74e101Schristos return -1; 3140f74e101Schristos } 315c74ad251Schristos subtlv_type = GET_BE_U_2(tptr); 316c74ad251Schristos subtlv_length = GET_BE_U_2(tptr + 2); 3170f74e101Schristos tptr+=4; 3180f74e101Schristos tlv_length-=4; 3190f74e101Schristos 320fdccd7e4Schristos /* Infinite loop protection */ 321fdccd7e4Schristos if (subtlv_type == 0 || subtlv_length == 0) 322fdccd7e4Schristos goto invalid; 323fdccd7e4Schristos 324c74ad251Schristos ND_PRINT("\n\t %s subTLV (%u), length: %u", 3250f74e101Schristos tok2str(lsa_opaque_te_link_tlv_subtlv_values,"unknown",subtlv_type), 3260f74e101Schristos subtlv_type, 327c74ad251Schristos subtlv_length); 3280f74e101Schristos 329c74ad251Schristos if (tlv_length < subtlv_length) { 330c74ad251Schristos ND_PRINT("\n\t Remaining TLV length %u < %u", 331c74ad251Schristos tlv_length + 4, subtlv_length + 4); 332c74ad251Schristos return -1; 333c74ad251Schristos } 334c74ad251Schristos ND_TCHECK_LEN(tptr, subtlv_length); 3350f74e101Schristos switch(subtlv_type) { 3360f74e101Schristos case LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP: 337fdccd7e4Schristos if (subtlv_length != 4) { 338c74ad251Schristos ND_PRINT(" != 4"); 339fdccd7e4Schristos goto invalid; 340fdccd7e4Schristos } 341c74ad251Schristos ND_PRINT(", 0x%08x", GET_BE_U_4(tptr)); 3420f74e101Schristos break; 3430f74e101Schristos case LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID: 3440f74e101Schristos case LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID: 345fdccd7e4Schristos if (subtlv_length != 4 && subtlv_length != 8) { 346c74ad251Schristos ND_PRINT(" != 4 && != 8"); 347fdccd7e4Schristos goto invalid; 348fdccd7e4Schristos } 349c74ad251Schristos ND_PRINT(", %s (0x%08x)", 350c74ad251Schristos GET_IPADDR_STRING(tptr), 351c74ad251Schristos GET_BE_U_4(tptr)); 3520f74e101Schristos if (subtlv_length == 8) /* rfc4203 */ 353c74ad251Schristos ND_PRINT(", %s (0x%08x)", 354c74ad251Schristos GET_IPADDR_STRING(tptr+4), 355c74ad251Schristos GET_BE_U_4(tptr + 4)); 3560f74e101Schristos break; 3570f74e101Schristos case LS_OPAQUE_TE_LINK_SUBTLV_LOCAL_IP: 3580f74e101Schristos case LS_OPAQUE_TE_LINK_SUBTLV_REMOTE_IP: 359fdccd7e4Schristos if (subtlv_length != 4) { 360c74ad251Schristos ND_PRINT(" != 4"); 361fdccd7e4Schristos goto invalid; 362fdccd7e4Schristos } 363c74ad251Schristos ND_PRINT(", %s", GET_IPADDR_STRING(tptr)); 3640f74e101Schristos break; 3650f74e101Schristos case LS_OPAQUE_TE_LINK_SUBTLV_MAX_BW: 3660f74e101Schristos case LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW: 367fdccd7e4Schristos if (subtlv_length != 4) { 368c74ad251Schristos ND_PRINT(" != 4"); 369fdccd7e4Schristos goto invalid; 370fdccd7e4Schristos } 371c74ad251Schristos bw.i = GET_BE_U_4(tptr); 372c74ad251Schristos ND_PRINT(", %.3f Mbps", bw.f * 8 / 1000000); 3730f74e101Schristos break; 3740f74e101Schristos case LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW: 375fdccd7e4Schristos if (subtlv_length != 32) { 376c74ad251Schristos ND_PRINT(" != 32"); 377fdccd7e4Schristos goto invalid; 378fdccd7e4Schristos } 3790f74e101Schristos for (te_class = 0; te_class < 8; te_class++) { 380c74ad251Schristos bw.i = GET_BE_U_4(tptr + te_class * 4); 381c74ad251Schristos ND_PRINT("\n\t\tTE-Class %u: %.3f Mbps", 3820f74e101Schristos te_class, 383c74ad251Schristos bw.f * 8 / 1000000); 3840f74e101Schristos } 3850f74e101Schristos break; 3860f74e101Schristos case LS_OPAQUE_TE_LINK_SUBTLV_BW_CONSTRAINTS: 387fdccd7e4Schristos if (subtlv_length < 4) { 388c74ad251Schristos ND_PRINT(" < 4"); 389fdccd7e4Schristos goto invalid; 390fdccd7e4Schristos } 391fdccd7e4Schristos /* BC Model Id (1 octet) + Reserved (3 octets) */ 392c74ad251Schristos ND_PRINT("\n\t\tBandwidth Constraints Model ID: %s (%u)", 393c74ad251Schristos tok2str(diffserv_te_bc_values, "unknown", GET_U_1(tptr)), 394c74ad251Schristos GET_U_1(tptr)); 395fdccd7e4Schristos if (subtlv_length % 4 != 0) { 396c74ad251Schristos ND_PRINT("\n\t\tlength %u != N x 4", subtlv_length); 397fdccd7e4Schristos goto invalid; 398fdccd7e4Schristos } 399fdccd7e4Schristos if (subtlv_length > 36) { 400c74ad251Schristos ND_PRINT("\n\t\tlength %u > 36", subtlv_length); 401fdccd7e4Schristos goto invalid; 402fdccd7e4Schristos } 4030f74e101Schristos /* decode BCs until the subTLV ends */ 4040f74e101Schristos for (te_class = 0; te_class < (subtlv_length-4)/4; te_class++) { 405c74ad251Schristos bw.i = GET_BE_U_4(tptr + 4 + te_class * 4); 406c74ad251Schristos ND_PRINT("\n\t\t Bandwidth constraint CT%u: %.3f Mbps", 4070f74e101Schristos te_class, 408c74ad251Schristos bw.f * 8 / 1000000); 4090f74e101Schristos } 4100f74e101Schristos break; 4110f74e101Schristos case LS_OPAQUE_TE_LINK_SUBTLV_TE_METRIC: 412fdccd7e4Schristos if (subtlv_length != 4) { 413c74ad251Schristos ND_PRINT(" != 4"); 414fdccd7e4Schristos goto invalid; 415fdccd7e4Schristos } 416c74ad251Schristos ND_PRINT(", Metric %u", GET_BE_U_4(tptr)); 4170f74e101Schristos break; 4180f74e101Schristos case LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE: 419fdccd7e4Schristos /* Protection Cap (1 octet) + Reserved ((3 octets) */ 420fdccd7e4Schristos if (subtlv_length != 4) { 421c74ad251Schristos ND_PRINT(" != 4"); 422fdccd7e4Schristos goto invalid; 423fdccd7e4Schristos } 424c74ad251Schristos ND_PRINT(", %s", 425c74ad251Schristos bittok2str(gmpls_link_prot_values, "none", GET_U_1(tptr))); 4260f74e101Schristos break; 4270f74e101Schristos case LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR: 428fdccd7e4Schristos if (subtlv_length < 36) { 429c74ad251Schristos ND_PRINT(" < 36"); 430fdccd7e4Schristos goto invalid; 431fdccd7e4Schristos } 432fdccd7e4Schristos /* Switching Cap (1 octet) + Encoding (1) + Reserved (2) */ 433c74ad251Schristos ND_PRINT("\n\t\tInterface Switching Capability: %s", 434c74ad251Schristos tok2str(gmpls_switch_cap_values, "Unknown", GET_U_1((tptr)))); 435c74ad251Schristos ND_PRINT("\n\t\tLSP Encoding: %s\n\t\tMax LSP Bandwidth:", 436c74ad251Schristos tok2str(gmpls_encoding_values, "Unknown", GET_U_1((tptr + 1)))); 4370f74e101Schristos for (priority_level = 0; priority_level < 8; priority_level++) { 438c74ad251Schristos bw.i = GET_BE_U_4(tptr + 4 + (priority_level * 4)); 439c74ad251Schristos ND_PRINT("\n\t\t priority level %u: %.3f Mbps", 4400f74e101Schristos priority_level, 441c74ad251Schristos bw.f * 8 / 1000000); 4420f74e101Schristos } 4430f74e101Schristos break; 4440f74e101Schristos case LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE: 445fdccd7e4Schristos if (subtlv_length != 1) { 446c74ad251Schristos ND_PRINT(" != 1"); 447fdccd7e4Schristos goto invalid; 448fdccd7e4Schristos } 449c74ad251Schristos ND_PRINT(", %s (%u)", 450c74ad251Schristos tok2str(lsa_opaque_te_tlv_link_type_sub_tlv_values,"unknown",GET_U_1(tptr)), 451c74ad251Schristos GET_U_1(tptr)); 4520f74e101Schristos break; 4530f74e101Schristos 4540f74e101Schristos case LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP: 455fdccd7e4Schristos if (subtlv_length % 4 != 0) { 456c74ad251Schristos ND_PRINT(" != N x 4"); 457fdccd7e4Schristos goto invalid; 458fdccd7e4Schristos } 4590f74e101Schristos count_srlg = subtlv_length / 4; 4600f74e101Schristos if (count_srlg != 0) 461c74ad251Schristos ND_PRINT("\n\t\t Shared risk group: "); 4620f74e101Schristos while (count_srlg > 0) { 463c74ad251Schristos bw.i = GET_BE_U_4(tptr); 464c74ad251Schristos ND_PRINT("%u", bw.i); 4650f74e101Schristos tptr+=4; 4660f74e101Schristos count_srlg--; 4670f74e101Schristos if (count_srlg > 0) 468c74ad251Schristos ND_PRINT(", "); 4690f74e101Schristos } 4700f74e101Schristos break; 4710f74e101Schristos 4720f74e101Schristos default: 473b3a00663Schristos if (ndo->ndo_vflag <= 1) { 474b3a00663Schristos if (!print_unknown_data(ndo, tptr, "\n\t\t", subtlv_length)) 4750f74e101Schristos return -1; 4760f74e101Schristos } 4770f74e101Schristos break; 4780f74e101Schristos } 4790f74e101Schristos /* in OSPF everything has to be 32-bit aligned, including subTLVs */ 4800f74e101Schristos if (subtlv_length%4 != 0) 4810f74e101Schristos subtlv_length+=4-(subtlv_length%4); 4820f74e101Schristos 483c74ad251Schristos if (tlv_length < subtlv_length) { 484c74ad251Schristos ND_PRINT("\n\t Remaining TLV length %u < %u", 485c74ad251Schristos tlv_length + 4, subtlv_length + 4); 486c74ad251Schristos return -1; 487c74ad251Schristos } 4880f74e101Schristos tlv_length-=subtlv_length; 4890f74e101Schristos tptr+=subtlv_length; 4900f74e101Schristos 4910f74e101Schristos } 4920f74e101Schristos break; 4930f74e101Schristos 4940f74e101Schristos case LS_OPAQUE_TE_TLV_ROUTER: 4950f74e101Schristos if (tlv_length < 4) { 496c74ad251Schristos ND_PRINT("\n\t TLV length %u < 4", tlv_length); 4970f74e101Schristos return -1; 4980f74e101Schristos } 499c74ad251Schristos ND_PRINT(", %s", GET_IPADDR_STRING(tptr)); 5000f74e101Schristos break; 5010f74e101Schristos 5020f74e101Schristos default: 503b3a00663Schristos if (ndo->ndo_vflag <= 1) { 504b3a00663Schristos if (!print_unknown_data(ndo, tptr, "\n\t ", tlv_length)) 5050f74e101Schristos return -1; 5060f74e101Schristos } 5070f74e101Schristos break; 5080f74e101Schristos } 5090f74e101Schristos /* in OSPF everything has to be 32-bit aligned, including TLVs */ 5100f74e101Schristos if (tlv_length%4 != 0) 5110f74e101Schristos tlv_length+=4-(tlv_length%4); 512c74ad251Schristos if (tlv_length > ls_length) { 513c74ad251Schristos ND_PRINT("\n\t Bogus padded length %u > %u", tlv_length, 514c74ad251Schristos ls_length); 515c74ad251Schristos return -1; 516c74ad251Schristos } 5170f74e101Schristos ls_length-=tlv_length; 5180f74e101Schristos tptr+=tlv_length; 5190f74e101Schristos } 5200f74e101Schristos return 0; 5210f74e101Schristos trunc: 5220f74e101Schristos return -1; 523fdccd7e4Schristos invalid: 524c74ad251Schristos nd_print_invalid(ndo); 525fdccd7e4Schristos return -1; 5260f74e101Schristos } 5270f74e101Schristos 5280f74e101Schristos static int 529b3a00663Schristos ospf_print_lshdr(netdissect_options *ndo, 530c74ad251Schristos const struct lsa_hdr *lshp) 5310f74e101Schristos { 532c74ad251Schristos u_int ls_type; 5330f74e101Schristos u_int ls_length; 5340f74e101Schristos 535c74ad251Schristos ls_length = GET_BE_U_2(lshp->ls_length); 5360f74e101Schristos if (ls_length < sizeof(struct lsa_hdr)) { 537c74ad251Schristos ND_PRINT("\n\t Bogus length %u < header (%zu)", ls_length, 538c74ad251Schristos sizeof(struct lsa_hdr)); 5390f74e101Schristos return(-1); 5400f74e101Schristos } 541c74ad251Schristos ND_PRINT("\n\t Advertising Router %s, seq 0x%08x, age %us, length %zu", 542c74ad251Schristos GET_IPADDR_STRING(lshp->ls_router), 543c74ad251Schristos GET_BE_U_4(lshp->ls_seq), 544c74ad251Schristos GET_BE_U_2(lshp->ls_age), 545c74ad251Schristos ls_length - sizeof(struct lsa_hdr)); 546c74ad251Schristos ls_type = GET_U_1(lshp->ls_type); 547c74ad251Schristos switch (ls_type) { 5480f74e101Schristos /* the LSA header for opaque LSAs was slightly changed */ 5490f74e101Schristos case LS_TYPE_OPAQUE_LL: 5500f74e101Schristos case LS_TYPE_OPAQUE_AL: 5510f74e101Schristos case LS_TYPE_OPAQUE_DW: 552c74ad251Schristos ND_PRINT("\n\t %s LSA (%u), Opaque-Type %s LSA (%u), Opaque-ID %u", 553c74ad251Schristos tok2str(lsa_values,"unknown",ls_type), 554c74ad251Schristos ls_type, 5550f74e101Schristos 5560f74e101Schristos tok2str(lsa_opaque_values, 5570f74e101Schristos "unknown", 558c74ad251Schristos GET_U_1(lshp->un_lsa_id.opaque_field.opaque_type)), 559c74ad251Schristos GET_U_1(lshp->un_lsa_id.opaque_field.opaque_type), 560c74ad251Schristos GET_BE_U_3(lshp->un_lsa_id.opaque_field.opaque_id) 5610f74e101Schristos 562c74ad251Schristos ); 5630f74e101Schristos break; 5640f74e101Schristos 5650f74e101Schristos /* all other LSA types use regular style LSA headers */ 5660f74e101Schristos default: 567c74ad251Schristos ND_PRINT("\n\t %s LSA (%u), LSA-ID: %s", 568c74ad251Schristos tok2str(lsa_values,"unknown",ls_type), 569c74ad251Schristos ls_type, 570c74ad251Schristos GET_IPADDR_STRING(lshp->un_lsa_id.lsa_id)); 5710f74e101Schristos break; 5720f74e101Schristos } 573c74ad251Schristos ND_PRINT("\n\t Options: [%s]", 574c74ad251Schristos bittok2str(ospf_option_values, "none", GET_U_1(lshp->ls_options))); 5750f74e101Schristos 5760f74e101Schristos return (ls_length); 5770f74e101Schristos } 5780f74e101Schristos 5790f74e101Schristos /* draft-ietf-ospf-mt-09 */ 580870189d2Schristos static const struct tok ospf_topology_values[] = { 5810f74e101Schristos { 0, "default" }, 5820f74e101Schristos { 1, "multicast" }, 5830f74e101Schristos { 2, "management" }, 5840f74e101Schristos { 0, NULL } 5850f74e101Schristos }; 5860f74e101Schristos 5870f74e101Schristos /* 5880f74e101Schristos * Print all the per-topology metrics. 5890f74e101Schristos */ 590c74ad251Schristos static void 591b3a00663Schristos ospf_print_tos_metrics(netdissect_options *ndo, 592b3a00663Schristos const union un_tos *tos) 5930f74e101Schristos { 594c74ad251Schristos u_int metric_count; 595c74ad251Schristos u_int toscount; 596c74ad251Schristos u_int tos_type; 5970f74e101Schristos 598c74ad251Schristos toscount = GET_U_1(tos->link.link_tos_count)+1; 5990f74e101Schristos metric_count = 0; 6000f74e101Schristos 6010f74e101Schristos /* 6020f74e101Schristos * All but the first metric contain a valid topology id. 6030f74e101Schristos */ 604c74ad251Schristos while (toscount != 0) { 605c74ad251Schristos tos_type = GET_U_1(tos->metrics.tos_type); 606c74ad251Schristos ND_PRINT("\n\t\ttopology %s (%u), metric %u", 607fdccd7e4Schristos tok2str(ospf_topology_values, "Unknown", 608c74ad251Schristos metric_count ? tos_type : 0), 609c74ad251Schristos metric_count ? tos_type : 0, 610c74ad251Schristos GET_BE_U_2(tos->metrics.tos_metric)); 6110f74e101Schristos metric_count++; 6120f74e101Schristos tos++; 6130f74e101Schristos toscount--; 6140f74e101Schristos } 6150f74e101Schristos } 6160f74e101Schristos 6170f74e101Schristos /* 6180f74e101Schristos * Print a single link state advertisement. If truncated or if LSA length 6190f74e101Schristos * field is less than the length of the LSA header, return NULl, else 6200f74e101Schristos * return pointer to data past end of LSA. 6210f74e101Schristos */ 622b3a00663Schristos static const uint8_t * 623b3a00663Schristos ospf_print_lsa(netdissect_options *ndo, 624c74ad251Schristos const struct lsa *lsap) 6250f74e101Schristos { 626c74ad251Schristos const uint8_t *ls_end; 627c74ad251Schristos const struct rlalink *rlp; 628c74ad251Schristos const nd_ipv4 *ap; 629c74ad251Schristos const struct aslametric *almp; 630c74ad251Schristos const struct mcla *mcp; 631c74ad251Schristos const uint8_t *lp; 632c74ad251Schristos u_int tlv_type, tlv_length, rla_count, topology; 633c74ad251Schristos int ospf_print_lshdr_ret; 634c74ad251Schristos u_int ls_length; 635b3a00663Schristos const uint8_t *tptr; 6360f74e101Schristos 637fdccd7e4Schristos tptr = (const uint8_t *)lsap->lsa_un.un_unknown; /* squelch compiler warnings */ 638c74ad251Schristos ospf_print_lshdr_ret = ospf_print_lshdr(ndo, &lsap->ls_hdr); 639c74ad251Schristos if (ospf_print_lshdr_ret < 0) 6400f74e101Schristos return(NULL); 641c74ad251Schristos ls_length = (u_int)ospf_print_lshdr_ret; 642fdccd7e4Schristos ls_end = (const uint8_t *)lsap + ls_length; 643c74ad251Schristos /* 644c74ad251Schristos * ospf_print_lshdr() returns -1 if the length is too short, 645c74ad251Schristos * so we know ls_length is >= sizeof(struct lsa_hdr). 646c74ad251Schristos */ 6470f74e101Schristos ls_length -= sizeof(struct lsa_hdr); 6480f74e101Schristos 649c74ad251Schristos switch (GET_U_1(lsap->ls_hdr.ls_type)) { 6500f74e101Schristos 6510f74e101Schristos case LS_TYPE_ROUTER: 652c74ad251Schristos ND_PRINT("\n\t Router LSA Options: [%s]", 653c74ad251Schristos bittok2str(ospf_rla_flag_values, "none", GET_U_1(lsap->lsa_un.un_rla.rla_flags))); 6540f74e101Schristos 655c74ad251Schristos rla_count = GET_BE_U_2(lsap->lsa_un.un_rla.rla_count); 656c74ad251Schristos ND_TCHECK_SIZE(lsap->lsa_un.un_rla.rla_link); 6570f74e101Schristos rlp = lsap->lsa_un.un_rla.rla_link; 658c74ad251Schristos for (u_int i = rla_count; i != 0; i--) { 659c74ad251Schristos ND_TCHECK_SIZE(rlp); 660c74ad251Schristos switch (GET_U_1(rlp->un_tos.link.link_type)) { 6610f74e101Schristos 6620f74e101Schristos case RLA_TYPE_VIRTUAL: 663c74ad251Schristos ND_PRINT("\n\t Virtual Link: Neighbor Router-ID: %s, Interface Address: %s", 664c74ad251Schristos GET_IPADDR_STRING(rlp->link_id), 665c74ad251Schristos GET_IPADDR_STRING(rlp->link_data)); 6660f74e101Schristos break; 6670f74e101Schristos 6680f74e101Schristos case RLA_TYPE_ROUTER: 669c74ad251Schristos ND_PRINT("\n\t Neighbor Router-ID: %s, Interface Address: %s", 670c74ad251Schristos GET_IPADDR_STRING(rlp->link_id), 671c74ad251Schristos GET_IPADDR_STRING(rlp->link_data)); 6720f74e101Schristos break; 6730f74e101Schristos 6740f74e101Schristos case RLA_TYPE_TRANSIT: 675c74ad251Schristos ND_PRINT("\n\t Neighbor Network-ID: %s, Interface Address: %s", 676c74ad251Schristos GET_IPADDR_STRING(rlp->link_id), 677c74ad251Schristos GET_IPADDR_STRING(rlp->link_data)); 6780f74e101Schristos break; 6790f74e101Schristos 6800f74e101Schristos case RLA_TYPE_STUB: 681c74ad251Schristos ND_PRINT("\n\t Stub Network: %s, Mask: %s", 682c74ad251Schristos GET_IPADDR_STRING(rlp->link_id), 683c74ad251Schristos GET_IPADDR_STRING(rlp->link_data)); 6840f74e101Schristos break; 6850f74e101Schristos 6860f74e101Schristos default: 687c74ad251Schristos ND_PRINT("\n\t Unknown Router Link Type (%u)", 688c74ad251Schristos GET_U_1(rlp->un_tos.link.link_type)); 6890f74e101Schristos return (ls_end); 6900f74e101Schristos } 6910f74e101Schristos 692c74ad251Schristos ospf_print_tos_metrics(ndo, &rlp->un_tos); 6930f74e101Schristos 694fdccd7e4Schristos rlp = (const struct rlalink *)((const u_char *)(rlp + 1) + 695c74ad251Schristos (GET_U_1(rlp->un_tos.link.link_tos_count) * sizeof(union un_tos))); 6960f74e101Schristos } 6970f74e101Schristos break; 6980f74e101Schristos 6990f74e101Schristos case LS_TYPE_NETWORK: 700c74ad251Schristos ND_PRINT("\n\t Mask %s\n\t Connected Routers:", 701c74ad251Schristos GET_IPADDR_STRING(lsap->lsa_un.un_nla.nla_mask)); 7020f74e101Schristos ap = lsap->lsa_un.un_nla.nla_router; 703fdccd7e4Schristos while ((const u_char *)ap < ls_end) { 704c74ad251Schristos ND_PRINT("\n\t %s", GET_IPADDR_STRING(ap)); 7050f74e101Schristos ++ap; 7060f74e101Schristos } 7070f74e101Schristos break; 7080f74e101Schristos 7090f74e101Schristos case LS_TYPE_SUM_IP: 710c74ad251Schristos ND_TCHECK_4(lsap->lsa_un.un_nla.nla_mask); 711c74ad251Schristos ND_PRINT("\n\t Mask %s", 712c74ad251Schristos GET_IPADDR_STRING(lsap->lsa_un.un_sla.sla_mask)); 713c74ad251Schristos ND_TCHECK_SIZE(lsap->lsa_un.un_sla.sla_tosmetric); 714c74ad251Schristos lp = (const uint8_t *)lsap->lsa_un.un_sla.sla_tosmetric; 715c74ad251Schristos while (lp < ls_end) { 716c74ad251Schristos uint32_t ul; 7170f74e101Schristos 718c74ad251Schristos ul = GET_BE_U_4(lp); 7190f74e101Schristos topology = (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS; 720c74ad251Schristos ND_PRINT("\n\t\ttopology %s (%u) metric %u", 721fdccd7e4Schristos tok2str(ospf_topology_values, "Unknown", topology), 7220f74e101Schristos topology, 723c74ad251Schristos ul & SLA_MASK_METRIC); 724c74ad251Schristos lp += 4; 7250f74e101Schristos } 7260f74e101Schristos break; 7270f74e101Schristos 7280f74e101Schristos case LS_TYPE_SUM_ABR: 729c74ad251Schristos ND_TCHECK_SIZE(lsap->lsa_un.un_sla.sla_tosmetric); 730c74ad251Schristos lp = (const uint8_t *)lsap->lsa_un.un_sla.sla_tosmetric; 731c74ad251Schristos while (lp < ls_end) { 732c74ad251Schristos uint32_t ul; 7330f74e101Schristos 734c74ad251Schristos ul = GET_BE_U_4(lp); 7350f74e101Schristos topology = (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS; 736c74ad251Schristos ND_PRINT("\n\t\ttopology %s (%u) metric %u", 737fdccd7e4Schristos tok2str(ospf_topology_values, "Unknown", topology), 7380f74e101Schristos topology, 739c74ad251Schristos ul & SLA_MASK_METRIC); 740c74ad251Schristos lp += 4; 7410f74e101Schristos } 7420f74e101Schristos break; 7430f74e101Schristos 7440f74e101Schristos case LS_TYPE_ASE: 7450f74e101Schristos case LS_TYPE_NSSA: /* fall through - those LSAs share the same format */ 746c74ad251Schristos ND_TCHECK_4(lsap->lsa_un.un_nla.nla_mask); 747c74ad251Schristos ND_PRINT("\n\t Mask %s", 748c74ad251Schristos GET_IPADDR_STRING(lsap->lsa_un.un_asla.asla_mask)); 7490f74e101Schristos 750c74ad251Schristos ND_TCHECK_SIZE(lsap->lsa_un.un_sla.sla_tosmetric); 7510f74e101Schristos almp = lsap->lsa_un.un_asla.asla_metric; 752fdccd7e4Schristos while ((const u_char *)almp < ls_end) { 753c74ad251Schristos uint32_t ul; 7540f74e101Schristos 755c74ad251Schristos ul = GET_BE_U_4(almp->asla_tosmetric); 7560f74e101Schristos topology = ((ul & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS); 757c74ad251Schristos ND_PRINT("\n\t\ttopology %s (%u), type %u, metric", 758fdccd7e4Schristos tok2str(ospf_topology_values, "Unknown", topology), 7590f74e101Schristos topology, 760c74ad251Schristos (ul & ASLA_FLAG_EXTERNAL) ? 2 : 1); 7610f74e101Schristos if ((ul & ASLA_MASK_METRIC) == 0xffffff) 762c74ad251Schristos ND_PRINT(" infinite"); 7630f74e101Schristos else 764c74ad251Schristos ND_PRINT(" %u", (ul & ASLA_MASK_METRIC)); 7650f74e101Schristos 766c74ad251Schristos if (GET_IPV4_TO_NETWORK_ORDER(almp->asla_forward) != 0) { 767c74ad251Schristos ND_PRINT(", forward %s", GET_IPADDR_STRING(almp->asla_forward)); 7680f74e101Schristos } 769c74ad251Schristos if (GET_IPV4_TO_NETWORK_ORDER(almp->asla_tag) != 0) { 770c74ad251Schristos ND_PRINT(", tag %s", GET_IPADDR_STRING(almp->asla_tag)); 7710f74e101Schristos } 7720f74e101Schristos ++almp; 7730f74e101Schristos } 7740f74e101Schristos break; 7750f74e101Schristos 7760f74e101Schristos case LS_TYPE_GROUP: 7770f74e101Schristos /* Multicast extensions as of 23 July 1991 */ 7780f74e101Schristos mcp = lsap->lsa_un.un_mcla; 779fdccd7e4Schristos while ((const u_char *)mcp < ls_end) { 780c74ad251Schristos switch (GET_BE_U_4(mcp->mcla_vtype)) { 7810f74e101Schristos 7820f74e101Schristos case MCLA_VERTEX_ROUTER: 783c74ad251Schristos ND_PRINT("\n\t Router Router-ID %s", 784c74ad251Schristos GET_IPADDR_STRING(mcp->mcla_vid)); 7850f74e101Schristos break; 7860f74e101Schristos 7870f74e101Schristos case MCLA_VERTEX_NETWORK: 788c74ad251Schristos ND_PRINT("\n\t Network Designated Router %s", 789c74ad251Schristos GET_IPADDR_STRING(mcp->mcla_vid)); 7900f74e101Schristos break; 7910f74e101Schristos 7920f74e101Schristos default: 793c74ad251Schristos ND_PRINT("\n\t unknown VertexType (%u)", 794c74ad251Schristos GET_BE_U_4(mcp->mcla_vtype)); 7950f74e101Schristos break; 7960f74e101Schristos } 7970f74e101Schristos ++mcp; 7980f74e101Schristos } 7990f74e101Schristos break; 8000f74e101Schristos 8010f74e101Schristos case LS_TYPE_OPAQUE_LL: /* fall through */ 8020f74e101Schristos case LS_TYPE_OPAQUE_AL: 8030f74e101Schristos case LS_TYPE_OPAQUE_DW: 8040f74e101Schristos 805c74ad251Schristos switch (GET_U_1(lsap->ls_hdr.un_lsa_id.opaque_field.opaque_type)) { 8060f74e101Schristos case LS_OPAQUE_TYPE_RI: 807c74ad251Schristos tptr = (const uint8_t *)(lsap->lsa_un.un_ri_tlv); 8080f74e101Schristos 809c74ad251Schristos u_int ls_length_remaining = ls_length; 810c74ad251Schristos while (ls_length_remaining != 0) { 811c74ad251Schristos ND_TCHECK_4(tptr); 812c74ad251Schristos if (ls_length_remaining < 4) { 813c74ad251Schristos ND_PRINT("\n\t Remaining LS length %u < 4", ls_length_remaining); 8140f74e101Schristos return(ls_end); 8150f74e101Schristos } 816c74ad251Schristos tlv_type = GET_BE_U_2(tptr); 817c74ad251Schristos tlv_length = GET_BE_U_2(tptr + 2); 8180f74e101Schristos tptr+=4; 819c74ad251Schristos ls_length_remaining-=4; 8200f74e101Schristos 821c74ad251Schristos ND_PRINT("\n\t %s TLV (%u), length: %u, value: ", 8220f74e101Schristos tok2str(lsa_opaque_ri_tlv_values,"unknown",tlv_type), 8230f74e101Schristos tlv_type, 824c74ad251Schristos tlv_length); 8250f74e101Schristos 826c74ad251Schristos if (tlv_length > ls_length_remaining) { 827c74ad251Schristos ND_PRINT("\n\t Bogus length %u > remaining LS length %u", tlv_length, 828c74ad251Schristos ls_length_remaining); 8290f74e101Schristos return(ls_end); 8300f74e101Schristos } 831c74ad251Schristos ND_TCHECK_LEN(tptr, tlv_length); 8320f74e101Schristos switch(tlv_type) { 8330f74e101Schristos 8340f74e101Schristos case LS_OPAQUE_RI_TLV_CAP: 8350f74e101Schristos if (tlv_length != 4) { 836c74ad251Schristos ND_PRINT("\n\t Bogus length %u != 4", tlv_length); 8370f74e101Schristos return(ls_end); 8380f74e101Schristos } 839c74ad251Schristos ND_PRINT("Capabilities: %s", 840c74ad251Schristos bittok2str(lsa_opaque_ri_tlv_cap_values, "Unknown", GET_BE_U_4(tptr))); 8410f74e101Schristos break; 8420f74e101Schristos default: 843b3a00663Schristos if (ndo->ndo_vflag <= 1) { 844b3a00663Schristos if (!print_unknown_data(ndo, tptr, "\n\t ", tlv_length)) 8450f74e101Schristos return(ls_end); 8460f74e101Schristos } 8470f74e101Schristos break; 8480f74e101Schristos 8490f74e101Schristos } 850*26ba0b50Schristos 851*26ba0b50Schristos /* in OSPF everything has to be 32-bit aligned, including TLVs */ 852*26ba0b50Schristos if (tlv_length % 4) { 853*26ba0b50Schristos tlv_length += (4 - (tlv_length % 4)); 854*26ba0b50Schristos } 8550f74e101Schristos tptr+=tlv_length; 856c74ad251Schristos ls_length_remaining-=tlv_length; 8570f74e101Schristos } 8580f74e101Schristos break; 8590f74e101Schristos 8600f74e101Schristos case LS_OPAQUE_TYPE_GRACE: 861c74ad251Schristos if (ospf_grace_lsa_print(ndo, (const u_char *)(lsap->lsa_un.un_grace_tlv), 8620f74e101Schristos ls_length) == -1) { 8630f74e101Schristos return(ls_end); 8640f74e101Schristos } 8650f74e101Schristos break; 8660f74e101Schristos 8670f74e101Schristos case LS_OPAQUE_TYPE_TE: 868c74ad251Schristos if (ospf_te_lsa_print(ndo, (const u_char *)(lsap->lsa_un.un_te_lsa_tlv), 8690f74e101Schristos ls_length) == -1) { 8700f74e101Schristos return(ls_end); 8710f74e101Schristos } 8720f74e101Schristos break; 8730f74e101Schristos 8740f74e101Schristos default: 875b3a00663Schristos if (ndo->ndo_vflag <= 1) { 876fdccd7e4Schristos if (!print_unknown_data(ndo, (const uint8_t *)lsap->lsa_un.un_unknown, 8770f74e101Schristos "\n\t ", ls_length)) 8780f74e101Schristos return(ls_end); 8790f74e101Schristos } 8800f74e101Schristos break; 8810f74e101Schristos } 8820f74e101Schristos } 8830f74e101Schristos 8840f74e101Schristos /* do we want to see an additionally hexdump ? */ 885b3a00663Schristos if (ndo->ndo_vflag> 1) 886fdccd7e4Schristos if (!print_unknown_data(ndo, (const uint8_t *)lsap->lsa_un.un_unknown, 8870f74e101Schristos "\n\t ", ls_length)) { 8880f74e101Schristos return(ls_end); 8890f74e101Schristos } 8900f74e101Schristos 8910f74e101Schristos return (ls_end); 8920f74e101Schristos trunc: 8930f74e101Schristos return (NULL); 8940f74e101Schristos } 8950f74e101Schristos 896c74ad251Schristos static void 897b3a00663Schristos ospf_decode_lls(netdissect_options *ndo, 898c74ad251Schristos const struct ospfhdr *op, u_int length) 8990f74e101Schristos { 900c74ad251Schristos const u_char *dptr; 901c74ad251Schristos const u_char *dataend; 902c74ad251Schristos u_int length2; 903c74ad251Schristos uint16_t lls_type, lls_len; 904c74ad251Schristos uint32_t lls_flags; 9050f74e101Schristos 906c74ad251Schristos switch (GET_U_1(op->ospf_type)) { 9070f74e101Schristos 9080f74e101Schristos case OSPF_TYPE_HELLO: 909c74ad251Schristos if (!(GET_U_1(op->ospf_hello.hello_options) & OSPF_OPTION_L)) 910c74ad251Schristos return; 9110f74e101Schristos break; 9120f74e101Schristos 9130f74e101Schristos case OSPF_TYPE_DD: 914c74ad251Schristos if (!(GET_U_1(op->ospf_db.db_options) & OSPF_OPTION_L)) 915c74ad251Schristos return; 9160f74e101Schristos break; 9170f74e101Schristos 9180f74e101Schristos default: 919c74ad251Schristos return; 9200f74e101Schristos } 9210f74e101Schristos 9220f74e101Schristos /* dig deeper if LLS data is available; see RFC4813 */ 923c74ad251Schristos length2 = GET_BE_U_2(op->ospf_len); 924fdccd7e4Schristos dptr = (const u_char *)op + length2; 925fdccd7e4Schristos dataend = (const u_char *)op + length; 9260f74e101Schristos 927c74ad251Schristos if (GET_BE_U_2(op->ospf_authtype) == OSPF_AUTH_MD5) { 928c74ad251Schristos dptr = dptr + GET_U_1(op->ospf_authdata + 3); 929c74ad251Schristos length2 += GET_U_1(op->ospf_authdata + 3); 9300f74e101Schristos } 9310f74e101Schristos if (length2 >= length) { 932c74ad251Schristos ND_PRINT("\n\t[LLS truncated]"); 933c74ad251Schristos return; 9340f74e101Schristos } 935c74ad251Schristos ND_PRINT("\n\t LLS: checksum: 0x%04x", (u_int) GET_BE_U_2(dptr)); 9360f74e101Schristos 9370f74e101Schristos dptr += 2; 938c74ad251Schristos length2 = GET_BE_U_2(dptr); 939c74ad251Schristos ND_PRINT(", length: %u", length2); 9400f74e101Schristos 9410f74e101Schristos dptr += 2; 9420f74e101Schristos while (dptr < dataend) { 943c74ad251Schristos lls_type = GET_BE_U_2(dptr); 944c74ad251Schristos ND_PRINT("\n\t %s (%u)", 9450f74e101Schristos tok2str(ospf_lls_tlv_values,"Unknown TLV",lls_type), 946c74ad251Schristos lls_type); 9470f74e101Schristos dptr += 2; 948c74ad251Schristos lls_len = GET_BE_U_2(dptr); 949c74ad251Schristos ND_PRINT(", length: %u", lls_len); 9500f74e101Schristos dptr += 2; 9510f74e101Schristos switch (lls_type) { 9520f74e101Schristos 9530f74e101Schristos case OSPF_LLS_EO: 9540f74e101Schristos if (lls_len != 4) { 955c74ad251Schristos ND_PRINT(" [should be 4]"); 9560f74e101Schristos lls_len = 4; 9570f74e101Schristos } 958c74ad251Schristos lls_flags = GET_BE_U_4(dptr); 959c74ad251Schristos ND_PRINT("\n\t Options: 0x%08x [%s]", lls_flags, 960c74ad251Schristos bittok2str(ospf_lls_eo_options, "?", lls_flags)); 9610f74e101Schristos 9620f74e101Schristos break; 9630f74e101Schristos 9640f74e101Schristos case OSPF_LLS_MD5: 9650f74e101Schristos if (lls_len != 20) { 966c74ad251Schristos ND_PRINT(" [should be 20]"); 9670f74e101Schristos lls_len = 20; 9680f74e101Schristos } 969c74ad251Schristos ND_PRINT("\n\t Sequence number: 0x%08x", GET_BE_U_4(dptr)); 9700f74e101Schristos break; 9710f74e101Schristos } 9720f74e101Schristos 9730f74e101Schristos dptr += lls_len; 9740f74e101Schristos } 9750f74e101Schristos } 9760f74e101Schristos 9770f74e101Schristos static int 978b3a00663Schristos ospf_decode_v2(netdissect_options *ndo, 979c74ad251Schristos const struct ospfhdr *op, const u_char *dataend) 9800f74e101Schristos { 981c74ad251Schristos const nd_ipv4 *ap; 982c74ad251Schristos const struct lsr *lsrp; 983c74ad251Schristos const struct lsa_hdr *lshp; 984c74ad251Schristos const struct lsa *lsap; 985c74ad251Schristos uint32_t lsa_count,lsa_count_max; 9860f74e101Schristos 987c74ad251Schristos switch (GET_U_1(op->ospf_type)) { 9880f74e101Schristos 9890f74e101Schristos case OSPF_TYPE_HELLO: 990c74ad251Schristos ND_PRINT("\n\tOptions [%s]", 991c74ad251Schristos bittok2str(ospf_option_values,"none",GET_U_1(op->ospf_hello.hello_options))); 9920f74e101Schristos 993c74ad251Schristos ND_PRINT("\n\t Hello Timer %us, Dead Timer %us, Mask %s, Priority %u", 994c74ad251Schristos GET_BE_U_2(op->ospf_hello.hello_helloint), 995c74ad251Schristos GET_BE_U_4(op->ospf_hello.hello_deadint), 996c74ad251Schristos GET_IPADDR_STRING(op->ospf_hello.hello_mask), 997c74ad251Schristos GET_U_1(op->ospf_hello.hello_priority)); 9980f74e101Schristos 999c74ad251Schristos if (GET_IPV4_TO_NETWORK_ORDER(op->ospf_hello.hello_dr) != 0) 1000c74ad251Schristos ND_PRINT("\n\t Designated Router %s", 1001c74ad251Schristos GET_IPADDR_STRING(op->ospf_hello.hello_dr)); 10020f74e101Schristos 1003c74ad251Schristos if (GET_IPV4_TO_NETWORK_ORDER(op->ospf_hello.hello_bdr) != 0) 1004c74ad251Schristos ND_PRINT(", Backup Designated Router %s", 1005c74ad251Schristos GET_IPADDR_STRING(op->ospf_hello.hello_bdr)); 10060f74e101Schristos 10070f74e101Schristos ap = op->ospf_hello.hello_neighbor; 1008fdccd7e4Schristos if ((const u_char *)ap < dataend) 1009c74ad251Schristos ND_PRINT("\n\t Neighbor List:"); 1010fdccd7e4Schristos while ((const u_char *)ap < dataend) { 1011c74ad251Schristos ND_PRINT("\n\t %s", GET_IPADDR_STRING(ap)); 10120f74e101Schristos ++ap; 10130f74e101Schristos } 10140f74e101Schristos break; /* HELLO */ 10150f74e101Schristos 10160f74e101Schristos case OSPF_TYPE_DD: 1017c74ad251Schristos ND_PRINT("\n\tOptions [%s]", 1018c74ad251Schristos bittok2str(ospf_option_values, "none", GET_U_1(op->ospf_db.db_options))); 1019c74ad251Schristos ND_PRINT(", DD Flags [%s]", 1020c74ad251Schristos bittok2str(ospf_dd_flag_values, "none", GET_U_1(op->ospf_db.db_flags))); 1021c74ad251Schristos if (GET_BE_U_2(op->ospf_db.db_ifmtu)) { 1022c74ad251Schristos ND_PRINT(", MTU: %u", 1023c74ad251Schristos GET_BE_U_2(op->ospf_db.db_ifmtu)); 10240f74e101Schristos } 1025c74ad251Schristos ND_PRINT(", Sequence: 0x%08x", GET_BE_U_4(op->ospf_db.db_seq)); 10260f74e101Schristos 10270f74e101Schristos /* Print all the LS adv's */ 10280f74e101Schristos lshp = op->ospf_db.db_lshdr; 1029fdccd7e4Schristos while (((const u_char *)lshp < dataend) && ospf_print_lshdr(ndo, lshp) != -1) { 10300f74e101Schristos ++lshp; 10310f74e101Schristos } 10320f74e101Schristos break; 10330f74e101Schristos 10340f74e101Schristos case OSPF_TYPE_LS_REQ: 10350f74e101Schristos lsrp = op->ospf_lsr; 1036fdccd7e4Schristos while ((const u_char *)lsrp < dataend) { 1037c74ad251Schristos ND_TCHECK_SIZE(lsrp); 10380f74e101Schristos 1039c74ad251Schristos ND_PRINT("\n\t Advertising Router: %s, %s LSA (%u)", 1040c74ad251Schristos GET_IPADDR_STRING(lsrp->ls_router), 1041c74ad251Schristos tok2str(lsa_values,"unknown",GET_BE_U_4(lsrp->ls_type)), 1042c74ad251Schristos GET_BE_U_4(lsrp->ls_type)); 10430f74e101Schristos 1044c74ad251Schristos switch (GET_BE_U_4(lsrp->ls_type)) { 10450f74e101Schristos /* the LSA header for opaque LSAs was slightly changed */ 10460f74e101Schristos case LS_TYPE_OPAQUE_LL: 10470f74e101Schristos case LS_TYPE_OPAQUE_AL: 10480f74e101Schristos case LS_TYPE_OPAQUE_DW: 1049c74ad251Schristos ND_PRINT(", Opaque-Type: %s LSA (%u), Opaque-ID: %u", 1050c74ad251Schristos tok2str(lsa_opaque_values, "unknown",GET_U_1(lsrp->un_ls_stateid.opaque_field.opaque_type)), 1051c74ad251Schristos GET_U_1(lsrp->un_ls_stateid.opaque_field.opaque_type), 1052c74ad251Schristos GET_BE_U_3(lsrp->un_ls_stateid.opaque_field.opaque_id)); 10530f74e101Schristos break; 10540f74e101Schristos default: 1055c74ad251Schristos ND_PRINT(", LSA-ID: %s", 1056c74ad251Schristos GET_IPADDR_STRING(lsrp->un_ls_stateid.ls_stateid)); 10570f74e101Schristos break; 10580f74e101Schristos } 10590f74e101Schristos 10600f74e101Schristos ++lsrp; 10610f74e101Schristos } 10620f74e101Schristos break; 10630f74e101Schristos 10640f74e101Schristos case OSPF_TYPE_LS_UPDATE: 10650f74e101Schristos lsap = op->ospf_lsu.lsu_lsa; 1066c74ad251Schristos lsa_count_max = GET_BE_U_4(op->ospf_lsu.lsu_count); 1067c74ad251Schristos ND_PRINT(", %u LSA%s", lsa_count_max, PLURAL_SUFFIX(lsa_count_max)); 10680f74e101Schristos for (lsa_count=1;lsa_count <= lsa_count_max;lsa_count++) { 1069c74ad251Schristos ND_PRINT("\n\t LSA #%u", lsa_count); 1070b3a00663Schristos lsap = (const struct lsa *)ospf_print_lsa(ndo, lsap); 10710f74e101Schristos if (lsap == NULL) 10720f74e101Schristos goto trunc; 10730f74e101Schristos } 10740f74e101Schristos break; 10750f74e101Schristos 10760f74e101Schristos case OSPF_TYPE_LS_ACK: 10770f74e101Schristos lshp = op->ospf_lsa.lsa_lshdr; 1078*26ba0b50Schristos while ((const u_char *)lshp < dataend) { 1079*26ba0b50Schristos ospf_print_lshdr(ndo, lshp); 10800f74e101Schristos ++lshp; 10810f74e101Schristos } 10820f74e101Schristos break; 10830f74e101Schristos 10840f74e101Schristos default: 10850f74e101Schristos break; 10860f74e101Schristos } 10870f74e101Schristos return (0); 10880f74e101Schristos trunc: 10890f74e101Schristos return (1); 10900f74e101Schristos } 10910f74e101Schristos 10920f74e101Schristos void 1093b3a00663Schristos ospf_print(netdissect_options *ndo, 1094c74ad251Schristos const u_char *bp, u_int length, 10950f74e101Schristos const u_char *bp2 _U_) 10960f74e101Schristos { 1097c74ad251Schristos const struct ospfhdr *op; 1098c74ad251Schristos const u_char *dataend; 1099c74ad251Schristos const char *cp; 11000f74e101Schristos 1101c74ad251Schristos ndo->ndo_protocol = "ospf2"; 1102fdccd7e4Schristos op = (const struct ospfhdr *)bp; 11030f74e101Schristos 11040f74e101Schristos /* XXX Before we do anything else, strip off the MD5 trailer */ 1105c74ad251Schristos if (GET_BE_U_2(op->ospf_authtype) == OSPF_AUTH_MD5) { 11060f74e101Schristos length -= OSPF_AUTH_MD5_LEN; 1107b3a00663Schristos ndo->ndo_snapend -= OSPF_AUTH_MD5_LEN; 11080f74e101Schristos } 11090f74e101Schristos 11100f74e101Schristos /* If the type is valid translate it, or just print the type */ 11110f74e101Schristos /* value. If it's not valid, say so and return */ 1112c74ad251Schristos cp = tok2str(type2str, "unknown LS-type %u", GET_U_1(op->ospf_type)); 1113c74ad251Schristos ND_PRINT("OSPFv%u, %s, length %u", GET_U_1(op->ospf_version), cp, 1114c74ad251Schristos length); 11150f74e101Schristos if (*cp == 'u') 11160f74e101Schristos return; 11170f74e101Schristos 1118b3a00663Schristos if (!ndo->ndo_vflag) { /* non verbose - so lets bail out here */ 11190f74e101Schristos return; 11200f74e101Schristos } 11210f74e101Schristos 1122c74ad251Schristos if (length != GET_BE_U_2(op->ospf_len)) { 1123c74ad251Schristos ND_PRINT(" [len %u]", GET_BE_U_2(op->ospf_len)); 11240f74e101Schristos } 11250f74e101Schristos 1126c74ad251Schristos if (length > GET_BE_U_2(op->ospf_len)) { 1127c74ad251Schristos dataend = bp + GET_BE_U_2(op->ospf_len); 11280f74e101Schristos } else { 11290f74e101Schristos dataend = bp + length; 11300f74e101Schristos } 11310f74e101Schristos 1132c74ad251Schristos ND_PRINT("\n\tRouter-ID %s", GET_IPADDR_STRING(op->ospf_routerid)); 11330f74e101Schristos 1134c74ad251Schristos if (GET_IPV4_TO_NETWORK_ORDER(op->ospf_areaid) != 0) 1135c74ad251Schristos ND_PRINT(", Area %s", GET_IPADDR_STRING(op->ospf_areaid)); 11360f74e101Schristos else 1137c74ad251Schristos ND_PRINT(", Backbone Area"); 11380f74e101Schristos 1139b3a00663Schristos if (ndo->ndo_vflag) { 11400f74e101Schristos /* Print authentication data (should we really do this?) */ 1141c74ad251Schristos ND_TCHECK_LEN(op->ospf_authdata, sizeof(op->ospf_authdata)); 11420f74e101Schristos 1143c74ad251Schristos ND_PRINT(", Authentication Type: %s (%u)", 1144c74ad251Schristos tok2str(ospf_authtype_values, "unknown", GET_BE_U_2(op->ospf_authtype)), 1145c74ad251Schristos GET_BE_U_2(op->ospf_authtype)); 11460f74e101Schristos 1147c74ad251Schristos switch (GET_BE_U_2(op->ospf_authtype)) { 11480f74e101Schristos 11490f74e101Schristos case OSPF_AUTH_NONE: 11500f74e101Schristos break; 11510f74e101Schristos 11520f74e101Schristos case OSPF_AUTH_SIMPLE: 1153c74ad251Schristos ND_PRINT("\n\tSimple text password: "); 1154c74ad251Schristos nd_printjnp(ndo, op->ospf_authdata, OSPF_AUTH_SIMPLE_LEN); 11550f74e101Schristos break; 11560f74e101Schristos 11570f74e101Schristos case OSPF_AUTH_MD5: 1158c74ad251Schristos ND_PRINT("\n\tKey-ID: %u, Auth-Length: %u, Crypto Sequence Number: 0x%08x", 1159c74ad251Schristos GET_U_1(op->ospf_authdata + 2), 1160c74ad251Schristos GET_U_1(op->ospf_authdata + 3), 1161c74ad251Schristos GET_BE_U_4((op->ospf_authdata) + 4)); 11620f74e101Schristos break; 11630f74e101Schristos 11640f74e101Schristos default: 11650f74e101Schristos return; 11660f74e101Schristos } 11670f74e101Schristos } 11680f74e101Schristos /* Do rest according to version. */ 1169c74ad251Schristos switch (GET_U_1(op->ospf_version)) { 11700f74e101Schristos 11710f74e101Schristos case 2: 11720f74e101Schristos /* ospf version 2 */ 1173b3a00663Schristos if (ospf_decode_v2(ndo, op, dataend)) 11740f74e101Schristos goto trunc; 1175c74ad251Schristos if (length > GET_BE_U_2(op->ospf_len)) 1176c74ad251Schristos ospf_decode_lls(ndo, op, length); 11770f74e101Schristos break; 11780f74e101Schristos 11790f74e101Schristos default: 1180c74ad251Schristos ND_PRINT(" ospf [version %u]", GET_U_1(op->ospf_version)); 11810f74e101Schristos break; 11820f74e101Schristos } /* end switch on version */ 11830f74e101Schristos 11840f74e101Schristos return; 11850f74e101Schristos trunc: 1186c74ad251Schristos nd_trunc_longjmp(ndo); 11870f74e101Schristos } 1188