117680Spst/* 239297Sfenner * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997 317680Spst * The Regents of the University of California. All rights reserved. 417680Spst * 517680Spst * Redistribution and use in source and binary forms, with or without 617680Spst * modification, are permitted provided that: (1) source code distributions 717680Spst * retain the above copyright notice and this paragraph in its entirety, (2) 817680Spst * distributions including binary code include the above copyright notice and 917680Spst * this paragraph in its entirety in the documentation or other materials 1017680Spst * provided with the distribution, and (3) all advertising materials mentioning 1117680Spst * features or use of this software display the following acknowledgement: 1217680Spst * ``This product includes software developed by the University of California, 1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1417680Spst * the University nor the names of its contributors may be used to endorse 1517680Spst * or promote products derived from this software without specific prior 1617680Spst * written permission. 1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2017680Spst * 2117680Spst * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu) 2217680Spst */ 2317680Spst 2417680Spst#ifndef lint 25127668Sbmsstatic const char rcsid[] _U_ = 26190207Srpaulo "@(#) $Header: /tcpdump/master/tcpdump/print-ospf.c,v 1.66 2007-10-08 07:53:21 hannes Exp $ (LBL)"; 2717680Spst#endif 2817680Spst 2956893Sfenner#ifdef HAVE_CONFIG_H 3056893Sfenner#include "config.h" 3156893Sfenner#endif 3256893Sfenner 33127668Sbms#include <tcpdump-stdinc.h> 3417680Spst 3517680Spst#include <stdio.h> 3617680Spst 3717680Spst#include "interface.h" 3817680Spst#include "addrtoname.h" 39127668Sbms#include "extract.h" 40127668Sbms#include "gmpls.h" 4117680Spst 4217680Spst#include "ospf.h" 4317680Spst 4475115Sfenner#include "ip.h" 4575115Sfenner 46127668Sbmsstatic struct tok ospf_option_values[] = { 47190207Srpaulo { OSPF_OPTION_T, "MultiTopology" }, /* draft-ietf-ospf-mt-09 */ 48127668Sbms { OSPF_OPTION_E, "External" }, 49127668Sbms { OSPF_OPTION_MC, "Multicast" }, 50127668Sbms { OSPF_OPTION_NP, "NSSA" }, 51190207Srpaulo { OSPF_OPTION_L, "LLS" }, 52127668Sbms { OSPF_OPTION_DC, "Demand Circuit" }, 53127668Sbms { OSPF_OPTION_O, "Opaque" }, 54146773Ssam { OSPF_OPTION_DN, "Up/Down" }, 55127668Sbms { 0, NULL } 5617680Spst}; 5717680Spst 58127668Sbmsstatic struct tok ospf_authtype_values[] = { 59127668Sbms { OSPF_AUTH_NONE, "none" }, 60172683Smlaier { OSPF_AUTH_SIMPLE, "simple" }, 61127668Sbms { OSPF_AUTH_MD5, "MD5" }, 6217680Spst { 0, NULL } 6317680Spst}; 6417680Spst 65127668Sbmsstatic struct tok ospf_rla_flag_values[] = { 66127668Sbms { RLA_FLAG_B, "ABR" }, 67127668Sbms { RLA_FLAG_E, "ASBR" }, 68127668Sbms { RLA_FLAG_W1, "Virtual" }, 6917680Spst { RLA_FLAG_W2, "W2" }, 7017680Spst { 0, NULL } 7117680Spst}; 7217680Spst 7326180Sfennerstatic struct tok type2str[] = { 74127668Sbms { OSPF_TYPE_UMD, "UMD" }, 75127668Sbms { OSPF_TYPE_HELLO, "Hello" }, 76127668Sbms { OSPF_TYPE_DD, "Database Description" }, 77127668Sbms { OSPF_TYPE_LS_REQ, "LS-Request" }, 78127668Sbms { OSPF_TYPE_LS_UPDATE, "LS-Update" }, 79127668Sbms { OSPF_TYPE_LS_ACK, "LS-Ack" }, 8026180Sfenner { 0, NULL } 8117680Spst}; 8217680Spst 83127668Sbmsstatic struct tok lsa_values[] = { 84127668Sbms { LS_TYPE_ROUTER, "Router" }, 85127668Sbms { LS_TYPE_NETWORK, "Network" }, 86127668Sbms { LS_TYPE_SUM_IP, "Summary" }, 87127668Sbms { LS_TYPE_SUM_ABR, "ASBR Summary" }, 88127668Sbms { LS_TYPE_ASE, "External" }, 89127668Sbms { LS_TYPE_GROUP, "Multicast Group" }, 90127668Sbms { LS_TYPE_NSSA, "NSSA" }, 91127668Sbms { LS_TYPE_OPAQUE_LL, "Link Local Opaque" }, 92127668Sbms { LS_TYPE_OPAQUE_AL, "Area Local Opaque" }, 93127668Sbms { LS_TYPE_OPAQUE_DW, "Domain Wide Opaque" }, 94127668Sbms { 0, NULL } 95127668Sbms}; 9626180Sfenner 97127668Sbmsstatic struct tok ospf_dd_flag_values[] = { 98127668Sbms { OSPF_DB_INIT, "Init" }, 99127668Sbms { OSPF_DB_MORE, "More" }, 100127668Sbms { OSPF_DB_MASTER, "Master" }, 101190207Srpaulo { OSPF_DB_RESYNC, "OOBResync" }, 102127668Sbms { 0, NULL } 103127668Sbms}; 10426180Sfenner 105127668Sbmsstatic struct tok lsa_opaque_values[] = { 106127668Sbms { LS_OPAQUE_TYPE_TE, "Traffic Engineering" }, 107127668Sbms { LS_OPAQUE_TYPE_GRACE, "Graceful restart" }, 108146773Ssam { LS_OPAQUE_TYPE_RI, "Router Information" }, 109127668Sbms { 0, NULL } 110127668Sbms}; 11117680Spst 112127668Sbmsstatic struct tok lsa_opaque_te_tlv_values[] = { 113127668Sbms { LS_OPAQUE_TE_TLV_ROUTER, "Router Address" }, 114127668Sbms { LS_OPAQUE_TE_TLV_LINK, "Link" }, 115127668Sbms { 0, NULL } 116127668Sbms}; 11717680Spst 118127668Sbmsstatic struct tok lsa_opaque_te_link_tlv_subtlv_values[] = { 119127668Sbms { LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE, "Link Type" }, 120127668Sbms { LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID, "Link ID" }, 121127668Sbms { LS_OPAQUE_TE_LINK_SUBTLV_LOCAL_IP, "Local Interface IP address" }, 122127668Sbms { LS_OPAQUE_TE_LINK_SUBTLV_REMOTE_IP, "Remote Interface IP address" }, 123127668Sbms { LS_OPAQUE_TE_LINK_SUBTLV_TE_METRIC, "Traffic Engineering Metric" }, 124127668Sbms { LS_OPAQUE_TE_LINK_SUBTLV_MAX_BW, "Maximum Bandwidth" }, 125127668Sbms { LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW, "Maximum Reservable Bandwidth" }, 126127668Sbms { LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW, "Unreserved Bandwidth" }, 127127668Sbms { LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP, "Administrative Group" }, 128127668Sbms { LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID, "Link Local/Remote Identifier" }, 129127668Sbms { LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE, "Link Protection Type" }, 130127668Sbms { LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR, "Interface Switching Capability" }, 131127668Sbms { LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP, "Shared Risk Link Group" }, 132162017Ssam { LS_OPAQUE_TE_LINK_SUBTLV_BW_CONSTRAINTS, "Bandwidth Constraints" }, 133127668Sbms { 0, NULL } 134127668Sbms}; 13517680Spst 136146773Ssamstatic struct tok lsa_opaque_grace_tlv_values[] = { 137146773Ssam { LS_OPAQUE_GRACE_TLV_PERIOD, "Grace Period" }, 138146773Ssam { LS_OPAQUE_GRACE_TLV_REASON, "Graceful restart Reason" }, 139146773Ssam { LS_OPAQUE_GRACE_TLV_INT_ADDRESS, "IPv4 interface address" }, 140146773Ssam { 0, NULL } 141146773Ssam}; 14217680Spst 143146773Ssamstatic struct tok lsa_opaque_grace_tlv_reason_values[] = { 144146773Ssam { LS_OPAQUE_GRACE_TLV_REASON_UNKNOWN, "Unknown" }, 145146773Ssam { LS_OPAQUE_GRACE_TLV_REASON_SW_RESTART, "Software Restart" }, 146146773Ssam { LS_OPAQUE_GRACE_TLV_REASON_SW_UPGRADE, "Software Reload/Upgrade" }, 147146773Ssam { LS_OPAQUE_GRACE_TLV_REASON_CP_SWITCH, "Control Processor Switch" }, 148146773Ssam { 0, NULL } 149146773Ssam}; 150146773Ssam 151127668Sbmsstatic struct tok lsa_opaque_te_tlv_link_type_sub_tlv_values[] = { 152127668Sbms { LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_PTP, "Point-to-point" }, 153127668Sbms { LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_MA, "Multi-Access" }, 154127668Sbms { 0, NULL } 155127668Sbms}; 15617680Spst 157146773Ssamstatic struct tok lsa_opaque_ri_tlv_values[] = { 158146773Ssam { LS_OPAQUE_RI_TLV_CAP, "Router Capabilities" }, 159146773Ssam { 0, NULL } 160146773Ssam}; 161146773Ssam 162146773Ssamstatic struct tok lsa_opaque_ri_tlv_cap_values[] = { 163146773Ssam { 1, "Reserved" }, 164146773Ssam { 2, "Reserved" }, 165146773Ssam { 4, "Reserved" }, 166146773Ssam { 8, "Reserved" }, 167146773Ssam { 16, "graceful restart capable" }, 168146773Ssam { 32, "graceful restart helper" }, 169146773Ssam { 64, "Stub router support" }, 170146773Ssam { 128, "Traffic engineering" }, 171146773Ssam { 256, "p2p over LAN" }, 172146773Ssam { 512, "path computation server" }, 173146773Ssam { 0, NULL } 174146773Ssam}; 175146773Ssam 176190207Srpaulostatic struct tok ospf_lls_tlv_values[] = { 177190207Srpaulo { OSPF_LLS_EO, "Extended Options" }, 178190207Srpaulo { OSPF_LLS_MD5, "MD5 Authentication" }, 179190207Srpaulo { 0, NULL } 180190207Srpaulo}; 18117680Spst 182190207Srpaulostatic struct tok ospf_lls_eo_options[] = { 183190207Srpaulo { OSPF_LLS_EO_LR, "LSDB resync" }, 184190207Srpaulo { OSPF_LLS_EO_RS, "Restart" }, 185190207Srpaulo { 0, NULL } 186190207Srpaulo}; 187190207Srpaulo 188190207Srpaulostatic char tstr[] = " [|ospf2]"; 189190207Srpaulo 190127668Sbms#ifdef WIN32 191127668Sbms#define inline __inline 192127668Sbms#endif /* WIN32 */ 19317680Spst 194127668Sbmsstatic int ospf_print_lshdr(const struct lsa_hdr *); 195127668Sbmsstatic const u_char *ospf_print_lsa(const struct lsa *); 196127668Sbmsstatic int ospf_decode_v2(const struct ospfhdr *, const u_char *); 197190207Srpaulostatic int ospf_decode_lls(const struct ospfhdr *, register u_int); 19817680Spst 199190207Srpauloint 200235530Sdelphijospf_print_grace_lsa (const u_int8_t *tptr, u_int ls_length) { 201190207Srpaulo 202190207Srpaulo u_int tlv_type, tlv_length; 203190207Srpaulo 204190207Srpaulo 205190207Srpaulo while (ls_length > 0) { 206190207Srpaulo TCHECK2(*tptr, 4); 207190207Srpaulo if (ls_length < 4) { 208190207Srpaulo printf("\n\t Remaining LS length %u < 4", ls_length); 209190207Srpaulo return -1; 210190207Srpaulo } 211190207Srpaulo tlv_type = EXTRACT_16BITS(tptr); 212190207Srpaulo tlv_length = EXTRACT_16BITS(tptr+2); 213190207Srpaulo tptr+=4; 214190207Srpaulo ls_length-=4; 215190207Srpaulo 216190207Srpaulo printf("\n\t %s TLV (%u), length %u, value: ", 217190207Srpaulo tok2str(lsa_opaque_grace_tlv_values,"unknown",tlv_type), 218190207Srpaulo tlv_type, 219190207Srpaulo tlv_length); 220190207Srpaulo 221190207Srpaulo if (tlv_length > ls_length) { 222190207Srpaulo printf("\n\t Bogus length %u > %u", tlv_length, 223190207Srpaulo ls_length); 224190207Srpaulo return -1; 225190207Srpaulo } 226190207Srpaulo 227190207Srpaulo /* Infinite loop protection. */ 228190207Srpaulo if (tlv_type == 0 || tlv_length ==0) { 229190207Srpaulo return -1; 230190207Srpaulo } 231190207Srpaulo 232190207Srpaulo TCHECK2(*tptr, tlv_length); 233190207Srpaulo switch(tlv_type) { 234190207Srpaulo 235190207Srpaulo case LS_OPAQUE_GRACE_TLV_PERIOD: 236190207Srpaulo if (tlv_length != 4) { 237190207Srpaulo printf("\n\t Bogus length %u != 4", tlv_length); 238190207Srpaulo return -1; 239190207Srpaulo } 240190207Srpaulo printf("%us",EXTRACT_32BITS(tptr)); 241190207Srpaulo break; 242190207Srpaulo 243190207Srpaulo case LS_OPAQUE_GRACE_TLV_REASON: 244190207Srpaulo if (tlv_length != 1) { 245190207Srpaulo printf("\n\t Bogus length %u != 1", tlv_length); 246190207Srpaulo return -1; 247190207Srpaulo } 248190207Srpaulo printf("%s (%u)", 249190207Srpaulo tok2str(lsa_opaque_grace_tlv_reason_values, "Unknown", *tptr), 250190207Srpaulo *tptr); 251190207Srpaulo break; 252190207Srpaulo 253190207Srpaulo case LS_OPAQUE_GRACE_TLV_INT_ADDRESS: 254190207Srpaulo if (tlv_length != 4) { 255190207Srpaulo printf("\n\t Bogus length %u != 4", tlv_length); 256190207Srpaulo return -1; 257190207Srpaulo } 258190207Srpaulo printf("%s", ipaddr_string(tptr)); 259190207Srpaulo break; 260190207Srpaulo 261190207Srpaulo default: 262190207Srpaulo if (vflag <= 1) { 263190207Srpaulo if(!print_unknown_data(tptr,"\n\t ",tlv_length)) 264190207Srpaulo return -1; 265190207Srpaulo } 266190207Srpaulo break; 267190207Srpaulo 268190207Srpaulo } 269190207Srpaulo /* in OSPF everything has to be 32-bit aligned, including TLVs */ 270190207Srpaulo if (tlv_length%4 != 0) 271190207Srpaulo tlv_length+=4-(tlv_length%4); 272190207Srpaulo ls_length-=tlv_length; 273190207Srpaulo tptr+=tlv_length; 274190207Srpaulo } 275190207Srpaulo 276190207Srpaulo return 0; 277190207Srpaulotrunc: 278190207Srpaulo return -1; 279190207Srpaulo} 280190207Srpaulo 281190207Srpauloint 282235530Sdelphijospf_print_te_lsa (const u_int8_t *tptr, u_int ls_length) { 283190207Srpaulo 284190207Srpaulo u_int tlv_type, tlv_length, subtlv_type, subtlv_length; 285190207Srpaulo u_int priority_level, te_class, count_srlg; 286190207Srpaulo union { /* int to float conversion buffer for several subTLVs */ 287190207Srpaulo float f; 288190207Srpaulo u_int32_t i; 289190207Srpaulo } bw; 290190207Srpaulo 291190207Srpaulo while (ls_length != 0) { 292190207Srpaulo TCHECK2(*tptr, 4); 293190207Srpaulo if (ls_length < 4) { 294190207Srpaulo printf("\n\t Remaining LS length %u < 4", ls_length); 295190207Srpaulo return -1; 296190207Srpaulo } 297190207Srpaulo tlv_type = EXTRACT_16BITS(tptr); 298190207Srpaulo tlv_length = EXTRACT_16BITS(tptr+2); 299190207Srpaulo tptr+=4; 300190207Srpaulo ls_length-=4; 301190207Srpaulo 302190207Srpaulo printf("\n\t %s TLV (%u), length: %u", 303190207Srpaulo tok2str(lsa_opaque_te_tlv_values,"unknown",tlv_type), 304190207Srpaulo tlv_type, 305190207Srpaulo tlv_length); 306190207Srpaulo 307190207Srpaulo if (tlv_length > ls_length) { 308190207Srpaulo printf("\n\t Bogus length %u > %u", tlv_length, 309190207Srpaulo ls_length); 310190207Srpaulo return -1; 311190207Srpaulo } 312190207Srpaulo 313190207Srpaulo /* Infinite loop protection. */ 314190207Srpaulo if (tlv_type == 0 || tlv_length ==0) { 315190207Srpaulo return -1; 316190207Srpaulo } 317190207Srpaulo 318190207Srpaulo switch(tlv_type) { 319190207Srpaulo case LS_OPAQUE_TE_TLV_LINK: 320190207Srpaulo while (tlv_length >= sizeof(subtlv_type) + sizeof(subtlv_length)) { 321190207Srpaulo if (tlv_length < 4) { 322190207Srpaulo printf("\n\t Remaining TLV length %u < 4", 323190207Srpaulo tlv_length); 324190207Srpaulo return -1; 325190207Srpaulo } 326190207Srpaulo TCHECK2(*tptr, 4); 327190207Srpaulo subtlv_type = EXTRACT_16BITS(tptr); 328190207Srpaulo subtlv_length = EXTRACT_16BITS(tptr+2); 329190207Srpaulo tptr+=4; 330190207Srpaulo tlv_length-=4; 331190207Srpaulo 332190207Srpaulo printf("\n\t %s subTLV (%u), length: %u", 333190207Srpaulo tok2str(lsa_opaque_te_link_tlv_subtlv_values,"unknown",subtlv_type), 334190207Srpaulo subtlv_type, 335190207Srpaulo subtlv_length); 336190207Srpaulo 337190207Srpaulo TCHECK2(*tptr, subtlv_length); 338190207Srpaulo switch(subtlv_type) { 339190207Srpaulo case LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP: 340190207Srpaulo printf(", 0x%08x", EXTRACT_32BITS(tptr)); 341190207Srpaulo break; 342190207Srpaulo case LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID: 343190207Srpaulo case LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID: 344190207Srpaulo printf(", %s (0x%08x)", 345190207Srpaulo ipaddr_string(tptr), 346190207Srpaulo EXTRACT_32BITS(tptr)); 347190207Srpaulo if (subtlv_length == 8) /* rfc4203 */ 348190207Srpaulo printf(", %s (0x%08x)", 349190207Srpaulo ipaddr_string(tptr+4), 350190207Srpaulo EXTRACT_32BITS(tptr+4)); 351190207Srpaulo break; 352190207Srpaulo case LS_OPAQUE_TE_LINK_SUBTLV_LOCAL_IP: 353190207Srpaulo case LS_OPAQUE_TE_LINK_SUBTLV_REMOTE_IP: 354190207Srpaulo printf(", %s", ipaddr_string(tptr)); 355190207Srpaulo break; 356190207Srpaulo case LS_OPAQUE_TE_LINK_SUBTLV_MAX_BW: 357190207Srpaulo case LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW: 358190207Srpaulo bw.i = EXTRACT_32BITS(tptr); 359190207Srpaulo printf(", %.3f Mbps", bw.f*8/1000000 ); 360190207Srpaulo break; 361190207Srpaulo case LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW: 362190207Srpaulo for (te_class = 0; te_class < 8; te_class++) { 363190207Srpaulo bw.i = EXTRACT_32BITS(tptr+te_class*4); 364190207Srpaulo printf("\n\t\tTE-Class %u: %.3f Mbps", 365190207Srpaulo te_class, 366190207Srpaulo bw.f*8/1000000 ); 367190207Srpaulo } 368190207Srpaulo break; 369190207Srpaulo case LS_OPAQUE_TE_LINK_SUBTLV_BW_CONSTRAINTS: 370190207Srpaulo printf("\n\t\tBandwidth Constraints Model ID: %s (%u)", 371190207Srpaulo tok2str(diffserv_te_bc_values, "unknown", *tptr), 372190207Srpaulo *tptr); 373190207Srpaulo /* decode BCs until the subTLV ends */ 374190207Srpaulo for (te_class = 0; te_class < (subtlv_length-4)/4; te_class++) { 375190207Srpaulo bw.i = EXTRACT_32BITS(tptr+4+te_class*4); 376190207Srpaulo printf("\n\t\t Bandwidth constraint CT%u: %.3f Mbps", 377190207Srpaulo te_class, 378190207Srpaulo bw.f*8/1000000 ); 379190207Srpaulo } 380190207Srpaulo break; 381190207Srpaulo case LS_OPAQUE_TE_LINK_SUBTLV_TE_METRIC: 382190207Srpaulo printf(", Metric %u", EXTRACT_32BITS(tptr)); 383190207Srpaulo break; 384190207Srpaulo case LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE: 385190207Srpaulo printf(", %s, Priority %u", 386190207Srpaulo bittok2str(gmpls_link_prot_values, "none", *tptr), 387190207Srpaulo *(tptr+1)); 388190207Srpaulo break; 389190207Srpaulo case LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR: 390190207Srpaulo printf("\n\t\tInterface Switching Capability: %s", 391190207Srpaulo tok2str(gmpls_switch_cap_values, "Unknown", *(tptr))); 392190207Srpaulo printf("\n\t\tLSP Encoding: %s\n\t\tMax LSP Bandwidth:", 393190207Srpaulo tok2str(gmpls_encoding_values, "Unknown", *(tptr+1))); 394190207Srpaulo for (priority_level = 0; priority_level < 8; priority_level++) { 395190207Srpaulo bw.i = EXTRACT_32BITS(tptr+4+(priority_level*4)); 396190207Srpaulo printf("\n\t\t priority level %d: %.3f Mbps", 397190207Srpaulo priority_level, 398190207Srpaulo bw.f*8/1000000 ); 399190207Srpaulo } 400190207Srpaulo break; 401190207Srpaulo case LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE: 402190207Srpaulo printf(", %s (%u)", 403190207Srpaulo tok2str(lsa_opaque_te_tlv_link_type_sub_tlv_values,"unknown",*tptr), 404190207Srpaulo *tptr); 405190207Srpaulo break; 406190207Srpaulo 407190207Srpaulo case LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP: 408190207Srpaulo count_srlg = subtlv_length / 4; 409190207Srpaulo if (count_srlg != 0) 410190207Srpaulo printf("\n\t\t Shared risk group: "); 411190207Srpaulo while (count_srlg > 0) { 412190207Srpaulo bw.i = EXTRACT_32BITS(tptr); 413190207Srpaulo printf("%d",bw.i); 414190207Srpaulo tptr+=4; 415190207Srpaulo count_srlg--; 416190207Srpaulo if (count_srlg > 0) 417190207Srpaulo printf(", "); 418190207Srpaulo } 419190207Srpaulo break; 420190207Srpaulo 421190207Srpaulo default: 422190207Srpaulo if (vflag <= 1) { 423190207Srpaulo if(!print_unknown_data(tptr,"\n\t\t",subtlv_length)) 424190207Srpaulo return -1; 425190207Srpaulo } 426190207Srpaulo break; 427190207Srpaulo } 428190207Srpaulo /* in OSPF everything has to be 32-bit aligned, including subTLVs */ 429190207Srpaulo if (subtlv_length%4 != 0) 430190207Srpaulo subtlv_length+=4-(subtlv_length%4); 431190207Srpaulo 432190207Srpaulo tlv_length-=subtlv_length; 433190207Srpaulo tptr+=subtlv_length; 434190207Srpaulo 435190207Srpaulo } 436190207Srpaulo break; 437190207Srpaulo 438190207Srpaulo case LS_OPAQUE_TE_TLV_ROUTER: 439190207Srpaulo if (tlv_length < 4) { 440190207Srpaulo printf("\n\t TLV length %u < 4", tlv_length); 441190207Srpaulo return -1; 442190207Srpaulo } 443190207Srpaulo TCHECK2(*tptr, 4); 444190207Srpaulo printf(", %s", ipaddr_string(tptr)); 445190207Srpaulo break; 446190207Srpaulo 447190207Srpaulo default: 448190207Srpaulo if (vflag <= 1) { 449190207Srpaulo if(!print_unknown_data(tptr,"\n\t ",tlv_length)) 450190207Srpaulo return -1; 451190207Srpaulo } 452190207Srpaulo break; 453190207Srpaulo } 454190207Srpaulo /* in OSPF everything has to be 32-bit aligned, including TLVs */ 455190207Srpaulo if (tlv_length%4 != 0) 456190207Srpaulo tlv_length+=4-(tlv_length%4); 457190207Srpaulo ls_length-=tlv_length; 458190207Srpaulo tptr+=tlv_length; 459190207Srpaulo } 460190207Srpaulo return 0; 461190207Srpaulotrunc: 462190207Srpaulo return -1; 463190207Srpaulo} 464190207Srpaulo 465190207Srpaulo 466127668Sbmsstatic int 467127668Sbmsospf_print_lshdr(register const struct lsa_hdr *lshp) 468127668Sbms{ 469127668Sbms u_int ls_length; 47017680Spst 471127668Sbms TCHECK(lshp->ls_length); 472127668Sbms ls_length = EXTRACT_16BITS(&lshp->ls_length); 473127668Sbms if (ls_length < sizeof(struct lsa_hdr)) { 474190207Srpaulo printf("\n\t Bogus length %u < header (%lu)", ls_length, 475127668Sbms (unsigned long)sizeof(struct lsa_hdr)); 476127668Sbms return(-1); 477127668Sbms } 47817680Spst 479127668Sbms TCHECK(lshp->ls_seq); /* XXX - ls_length check checked this */ 480190207Srpaulo printf("\n\t Advertising Router %s, seq 0x%08x, age %us, length %u", 481127668Sbms ipaddr_string(&lshp->ls_router), 482127668Sbms EXTRACT_32BITS(&lshp->ls_seq), 483127668Sbms EXTRACT_16BITS(&lshp->ls_age), 484127668Sbms ls_length-(u_int)sizeof(struct lsa_hdr)); 48517680Spst 486127668Sbms TCHECK(lshp->ls_type); /* XXX - ls_length check checked this */ 487127668Sbms switch (lshp->ls_type) { 488127668Sbms /* the LSA header for opaque LSAs was slightly changed */ 489127668Sbms case LS_TYPE_OPAQUE_LL: 490127668Sbms case LS_TYPE_OPAQUE_AL: 491127668Sbms case LS_TYPE_OPAQUE_DW: 492190207Srpaulo printf("\n\t %s LSA (%d), Opaque-Type %s LSA (%u), Opaque-ID %u", 493127668Sbms tok2str(lsa_values,"unknown",lshp->ls_type), 494127668Sbms lshp->ls_type, 49517680Spst 496127668Sbms tok2str(lsa_opaque_values, 497127668Sbms "unknown", 498127668Sbms *(&lshp->un_lsa_id.opaque_field.opaque_type)), 499127668Sbms *(&lshp->un_lsa_id.opaque_field.opaque_type), 500127668Sbms EXTRACT_24BITS(&lshp->un_lsa_id.opaque_field.opaque_id) 501127668Sbms 502127668Sbms ); 503127668Sbms break; 50426180Sfenner 505127668Sbms /* all other LSA types use regular style LSA headers */ 50626180Sfenner default: 507127668Sbms printf("\n\t %s LSA (%d), LSA-ID: %s", 508127668Sbms tok2str(lsa_values,"unknown",lshp->ls_type), 509127668Sbms lshp->ls_type, 510127668Sbms ipaddr_string(&lshp->un_lsa_id.lsa_id)); 511127668Sbms break; 512127668Sbms } 51317680Spst 514127668Sbms TCHECK(lshp->ls_options); /* XXX - ls_length check checked this */ 515127668Sbms printf("\n\t Options: [%s]", bittok2str(ospf_option_values,"none",lshp->ls_options)); 51617680Spst 517127668Sbms return (ls_length); 51826180Sfennertrunc: 519127668Sbms return (-1); 52026180Sfenner} 52126180Sfenner 522190207Srpaulo/* draft-ietf-ospf-mt-09 */ 523190207Srpaulostatic struct tok ospf_topology_values[] = { 524190207Srpaulo { 0, "default " }, 525190207Srpaulo { 1, "multicast " }, 526190207Srpaulo { 2, "management " }, 527190207Srpaulo { 0, NULL } 528190207Srpaulo}; 529190207Srpaulo 53017680Spst/* 531190207Srpaulo * Print all the per-topology metrics. 532190207Srpaulo */ 533190207Srpaulostatic void 534190207Srpauloospf_print_tos_metrics(const union un_tos *tos) 535190207Srpaulo{ 536190207Srpaulo int metric_count; 537190207Srpaulo int toscount; 538190207Srpaulo 539190207Srpaulo toscount = tos->link.link_tos_count+1; 540190207Srpaulo metric_count = 0; 541190207Srpaulo 542190207Srpaulo /* 543190207Srpaulo * All but the first metric contain a valid topology id. 544190207Srpaulo */ 545190207Srpaulo while (toscount) { 546190207Srpaulo printf("\n\t\ttopology %s(%u), metric %u", 547190207Srpaulo tok2str(ospf_topology_values, "", 548190207Srpaulo metric_count ? tos->metrics.tos_type : 0), 549190207Srpaulo metric_count ? tos->metrics.tos_type : 0, 550190207Srpaulo EXTRACT_16BITS(&tos->metrics.tos_metric)); 551190207Srpaulo metric_count++; 552190207Srpaulo tos++; 553190207Srpaulo toscount--; 554190207Srpaulo } 555190207Srpaulo} 556190207Srpaulo 557190207Srpaulo/* 558127668Sbms * Print a single link state advertisement. If truncated or if LSA length 559127668Sbms * field is less than the length of the LSA header, return NULl, else 560127668Sbms * return pointer to data past end of LSA. 56117680Spst */ 562127668Sbmsstatic const u_int8_t * 56326180Sfennerospf_print_lsa(register const struct lsa *lsap) 56417680Spst{ 565127668Sbms register const u_int8_t *ls_end; 56626180Sfenner register const struct rlalink *rlp; 56726180Sfenner register const struct in_addr *ap; 56826180Sfenner register const struct aslametric *almp; 56926180Sfenner register const struct mcla *mcp; 57026180Sfenner register const u_int32_t *lp; 571190207Srpaulo register int j, tlv_type, tlv_length, topology; 572127668Sbms register int ls_length; 573127668Sbms const u_int8_t *tptr; 57417680Spst 575127668Sbms tptr = (u_int8_t *)lsap->lsa_un.un_unknown; /* squelch compiler warnings */ 576127668Sbms ls_length = ospf_print_lshdr(&lsap->ls_hdr); 577127668Sbms if (ls_length == -1) 578127668Sbms return(NULL); 579127668Sbms ls_end = (u_int8_t *)lsap + ls_length; 580127668Sbms ls_length -= sizeof(struct lsa_hdr); 581127668Sbms 58226180Sfenner switch (lsap->ls_hdr.ls_type) { 58317680Spst 58426180Sfenner case LS_TYPE_ROUTER: 58526180Sfenner TCHECK(lsap->lsa_un.un_rla.rla_flags); 586127668Sbms printf("\n\t Router LSA Options: [%s]", bittok2str(ospf_rla_flag_values,"none",lsap->lsa_un.un_rla.rla_flags)); 58717680Spst 58826180Sfenner TCHECK(lsap->lsa_un.un_rla.rla_count); 589127668Sbms j = EXTRACT_16BITS(&lsap->lsa_un.un_rla.rla_count); 59026180Sfenner TCHECK(lsap->lsa_un.un_rla.rla_link); 59126180Sfenner rlp = lsap->lsa_un.un_rla.rla_link; 59226180Sfenner while (j--) { 59339297Sfenner TCHECK(*rlp); 594190207Srpaulo switch (rlp->un_tos.link.link_type) { 59517680Spst 59626180Sfenner case RLA_TYPE_VIRTUAL: 597127668Sbms printf("\n\t Virtual Link: Neighbor Router-ID: %s, Interface Address: %s", 598127668Sbms ipaddr_string(&rlp->link_id), 599127668Sbms ipaddr_string(&rlp->link_data)); 600127668Sbms break; 60117680Spst 60226180Sfenner case RLA_TYPE_ROUTER: 603127668Sbms printf("\n\t Neighbor Router-ID: %s, Interface Address: %s", 60426180Sfenner ipaddr_string(&rlp->link_id), 60526180Sfenner ipaddr_string(&rlp->link_data)); 60626180Sfenner break; 60717680Spst 60826180Sfenner case RLA_TYPE_TRANSIT: 609127668Sbms printf("\n\t Neighbor Network-ID: %s, Interface Address: %s", 61026180Sfenner ipaddr_string(&rlp->link_id), 61126180Sfenner ipaddr_string(&rlp->link_data)); 61226180Sfenner break; 61317680Spst 61426180Sfenner case RLA_TYPE_STUB: 615127668Sbms printf("\n\t Stub Network: %s, Mask: %s", 61626180Sfenner ipaddr_string(&rlp->link_id), 61726180Sfenner ipaddr_string(&rlp->link_data)); 61826180Sfenner break; 61917680Spst 62026180Sfenner default: 621127668Sbms printf("\n\t Unknown Router Link Type (%u)", 622190207Srpaulo rlp->un_tos.link.link_type); 623127668Sbms return (ls_end); 62426180Sfenner } 625190207Srpaulo 626190207Srpaulo ospf_print_tos_metrics(&rlp->un_tos); 627190207Srpaulo 62839297Sfenner rlp = (struct rlalink *)((u_char *)(rlp + 1) + 629190207Srpaulo ((rlp->un_tos.link.link_tos_count) * sizeof(union un_tos))); 63026180Sfenner } 63117680Spst break; 63217680Spst 63326180Sfenner case LS_TYPE_NETWORK: 63426180Sfenner TCHECK(lsap->lsa_un.un_nla.nla_mask); 635127668Sbms printf("\n\t Mask %s\n\t Connected Routers:", 63626180Sfenner ipaddr_string(&lsap->lsa_un.un_nla.nla_mask)); 63726180Sfenner ap = lsap->lsa_un.un_nla.nla_router; 63826180Sfenner while ((u_char *)ap < ls_end) { 63926180Sfenner TCHECK(*ap); 640127668Sbms printf("\n\t %s", ipaddr_string(ap)); 64126180Sfenner ++ap; 64226180Sfenner } 64317680Spst break; 64417680Spst 64526180Sfenner case LS_TYPE_SUM_IP: 64626180Sfenner TCHECK(lsap->lsa_un.un_nla.nla_mask); 647127668Sbms printf("\n\t Mask %s", 64826180Sfenner ipaddr_string(&lsap->lsa_un.un_sla.sla_mask)); 649127668Sbms TCHECK(lsap->lsa_un.un_sla.sla_tosmetric); 650127668Sbms lp = lsap->lsa_un.un_sla.sla_tosmetric; 651127668Sbms while ((u_char *)lp < ls_end) { 652127668Sbms register u_int32_t ul; 65317680Spst 654127668Sbms TCHECK(*lp); 655127668Sbms ul = EXTRACT_32BITS(lp); 656190207Srpaulo topology = (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS; 657190207Srpaulo printf("\n\t\ttopology %s(%u) metric %d", 658190207Srpaulo tok2str(ospf_topology_values, "", topology), 659190207Srpaulo topology, 660190207Srpaulo ul & SLA_MASK_METRIC); 661127668Sbms ++lp; 662127668Sbms } 663127668Sbms break; 664127668Sbms 66526180Sfenner case LS_TYPE_SUM_ABR: 66626180Sfenner TCHECK(lsap->lsa_un.un_sla.sla_tosmetric); 66726180Sfenner lp = lsap->lsa_un.un_sla.sla_tosmetric; 66826180Sfenner while ((u_char *)lp < ls_end) { 66926180Sfenner register u_int32_t ul; 67017680Spst 67126180Sfenner TCHECK(*lp); 672127668Sbms ul = EXTRACT_32BITS(lp); 673190207Srpaulo topology = (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS; 674190207Srpaulo printf("\n\t\ttopology %s(%u) metric %d", 675190207Srpaulo tok2str(ospf_topology_values, "", topology), 676190207Srpaulo topology, 677190207Srpaulo ul & SLA_MASK_METRIC); 67826180Sfenner ++lp; 67926180Sfenner } 68026180Sfenner break; 68117680Spst 68226180Sfenner case LS_TYPE_ASE: 683146773Ssam case LS_TYPE_NSSA: /* fall through - those LSAs share the same format */ 68426180Sfenner TCHECK(lsap->lsa_un.un_nla.nla_mask); 685127668Sbms printf("\n\t Mask %s", 68626180Sfenner ipaddr_string(&lsap->lsa_un.un_asla.asla_mask)); 68717680Spst 68826180Sfenner TCHECK(lsap->lsa_un.un_sla.sla_tosmetric); 68926180Sfenner almp = lsap->lsa_un.un_asla.asla_metric; 69026180Sfenner while ((u_char *)almp < ls_end) { 69126180Sfenner register u_int32_t ul; 69217680Spst 69326180Sfenner TCHECK(almp->asla_tosmetric); 694127668Sbms ul = EXTRACT_32BITS(&almp->asla_tosmetric); 695190207Srpaulo topology = ((ul & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS); 696190207Srpaulo printf("\n\t\ttopology %s(%u), type %d, metric", 697190207Srpaulo tok2str(ospf_topology_values, "", topology), 698190207Srpaulo topology, 699190207Srpaulo (ul & ASLA_FLAG_EXTERNAL) ? 2 : 1); 700127668Sbms if ((ul & ASLA_MASK_METRIC)==0xffffff) 701127668Sbms printf(" infinite"); 702127668Sbms else 703127668Sbms printf(" %d", (ul & ASLA_MASK_METRIC)); 704127668Sbms 70526180Sfenner TCHECK(almp->asla_forward); 70626180Sfenner if (almp->asla_forward.s_addr) { 707127668Sbms printf(", forward %s", 70826180Sfenner ipaddr_string(&almp->asla_forward)); 70926180Sfenner } 71026180Sfenner TCHECK(almp->asla_tag); 71126180Sfenner if (almp->asla_tag.s_addr) { 712127668Sbms printf(", tag %s", 71326180Sfenner ipaddr_string(&almp->asla_tag)); 71426180Sfenner } 71526180Sfenner ++almp; 71626180Sfenner } 71726180Sfenner break; 71817680Spst 71926180Sfenner case LS_TYPE_GROUP: 72026180Sfenner /* Multicast extensions as of 23 July 1991 */ 72126180Sfenner mcp = lsap->lsa_un.un_mcla; 72226180Sfenner while ((u_char *)mcp < ls_end) { 72326180Sfenner TCHECK(mcp->mcla_vid); 724127668Sbms switch (EXTRACT_32BITS(&mcp->mcla_vtype)) { 72517680Spst 72626180Sfenner case MCLA_VERTEX_ROUTER: 727127668Sbms printf("\n\t Router Router-ID %s", 72826180Sfenner ipaddr_string(&mcp->mcla_vid)); 72926180Sfenner break; 73017680Spst 73126180Sfenner case MCLA_VERTEX_NETWORK: 732127668Sbms printf("\n\t Network Designated Router %s", 73326180Sfenner ipaddr_string(&mcp->mcla_vid)); 73426180Sfenner break; 73517680Spst 73626180Sfenner default: 737127668Sbms printf("\n\t unknown VertexType (%u)", 738127668Sbms EXTRACT_32BITS(&mcp->mcla_vtype)); 73926180Sfenner break; 74026180Sfenner } 74126180Sfenner ++mcp; 74226180Sfenner } 743127668Sbms break; 74417680Spst 745127668Sbms case LS_TYPE_OPAQUE_LL: /* fall through */ 746127668Sbms case LS_TYPE_OPAQUE_AL: 747127668Sbms case LS_TYPE_OPAQUE_DW: 748127668Sbms 749127668Sbms switch (*(&lsap->ls_hdr.un_lsa_id.opaque_field.opaque_type)) { 750146773Ssam case LS_OPAQUE_TYPE_RI: 751146773Ssam tptr = (u_int8_t *)(&lsap->lsa_un.un_ri_tlv.type); 752146773Ssam 753146773Ssam while (ls_length != 0) { 754146773Ssam TCHECK2(*tptr, 4); 755146773Ssam if (ls_length < 4) { 756146773Ssam printf("\n\t Remaining LS length %u < 4", ls_length); 757146773Ssam return(ls_end); 758146773Ssam } 759146773Ssam tlv_type = EXTRACT_16BITS(tptr); 760146773Ssam tlv_length = EXTRACT_16BITS(tptr+2); 761146773Ssam tptr+=4; 762146773Ssam ls_length-=4; 763146773Ssam 764146773Ssam printf("\n\t %s TLV (%u), length: %u, value: ", 765146773Ssam tok2str(lsa_opaque_ri_tlv_values,"unknown",tlv_type), 766146773Ssam tlv_type, 767146773Ssam tlv_length); 768146773Ssam 769146773Ssam if (tlv_length > ls_length) { 770146773Ssam printf("\n\t Bogus length %u > %u", tlv_length, 771146773Ssam ls_length); 772146773Ssam return(ls_end); 773146773Ssam } 774146773Ssam TCHECK2(*tptr, tlv_length); 775146773Ssam switch(tlv_type) { 776146773Ssam 777146773Ssam case LS_OPAQUE_RI_TLV_CAP: 778146773Ssam if (tlv_length != 4) { 779146773Ssam printf("\n\t Bogus length %u != 4", tlv_length); 780146773Ssam return(ls_end); 781146773Ssam } 782146773Ssam printf("Capabilities: %s", 783146773Ssam bittok2str(lsa_opaque_ri_tlv_cap_values, "Unknown", EXTRACT_32BITS(tptr))); 784146773Ssam break; 785146773Ssam default: 786146773Ssam if (vflag <= 1) { 787146773Ssam if(!print_unknown_data(tptr,"\n\t ",tlv_length)) 788146773Ssam return(ls_end); 789146773Ssam } 790146773Ssam break; 791146773Ssam 792146773Ssam } 793146773Ssam tptr+=tlv_length; 794190207Srpaulo ls_length-=tlv_length; 795146773Ssam } 796190207Srpaulo break; 797146773Ssam 798190207Srpaulo case LS_OPAQUE_TYPE_GRACE: 799190207Srpaulo if (ospf_print_grace_lsa((u_int8_t *)(&lsap->lsa_un.un_grace_tlv.type), 800190207Srpaulo ls_length) == -1) { 801190207Srpaulo return(ls_end); 802190207Srpaulo } 803146773Ssam break; 804146773Ssam 805190207Srpaulo case LS_OPAQUE_TYPE_TE: 806190207Srpaulo if (ospf_print_te_lsa((u_int8_t *)(&lsap->lsa_un.un_te_lsa_tlv.type), 807190207Srpaulo ls_length) == -1) { 808190207Srpaulo return(ls_end); 809146773Ssam } 810146773Ssam break; 811127668Sbms 812190207Srpaulo default: 813190207Srpaulo if (vflag <= 1) { 814190207Srpaulo if(!print_unknown_data((u_int8_t *)lsap->lsa_un.un_unknown, 815190207Srpaulo "\n\t ", ls_length)) 816127668Sbms return(ls_end); 817190207Srpaulo } 818127668Sbms break; 819190207Srpaulo } 820127668Sbms } 821127668Sbms 822127668Sbms /* do we want to see an additionally hexdump ? */ 823127668Sbms if (vflag> 1) 824127668Sbms if(!print_unknown_data((u_int8_t *)lsap->lsa_un.un_unknown, 825127668Sbms "\n\t ", ls_length)) { 826127668Sbms return(ls_end); 827127668Sbms } 828127668Sbms 829127668Sbms return (ls_end); 83026180Sfennertrunc: 831127668Sbms return (NULL); 83217680Spst} 83317680Spst 83426180Sfennerstatic int 835190207Srpauloospf_decode_lls(register const struct ospfhdr *op, 836190207Srpaulo register u_int length) 837190207Srpaulo{ 838190207Srpaulo register const u_char *dptr; 839190207Srpaulo register const u_char *dataend; 840190207Srpaulo register u_int length2; 841190207Srpaulo register u_int16_t lls_type, lls_len; 842190207Srpaulo register u_int32_t lls_flags; 843190207Srpaulo 844190207Srpaulo switch (op->ospf_type) { 845190207Srpaulo 846190207Srpaulo case OSPF_TYPE_HELLO: 847190207Srpaulo if (!(op->ospf_hello.hello_options & OSPF_OPTION_L)) 848190207Srpaulo return (0); 849190207Srpaulo break; 850190207Srpaulo 851190207Srpaulo case OSPF_TYPE_DD: 852190207Srpaulo if (!(op->ospf_db.db_options & OSPF_OPTION_L)) 853190207Srpaulo return (0); 854190207Srpaulo break; 855190207Srpaulo 856190207Srpaulo default: 857190207Srpaulo return (0); 858190207Srpaulo } 859190207Srpaulo 860190207Srpaulo /* dig deeper if LLS data is available; see RFC4813 */ 861190207Srpaulo length2 = EXTRACT_16BITS(&op->ospf_len); 862190207Srpaulo dptr = (u_char *)op + length2; 863190207Srpaulo dataend = (u_char *)op + length; 864190207Srpaulo 865190207Srpaulo if (EXTRACT_16BITS(&op->ospf_authtype) == OSPF_AUTH_MD5) { 866190207Srpaulo dptr = dptr + op->ospf_authdata[3]; 867190207Srpaulo length2 += op->ospf_authdata[3]; 868190207Srpaulo } 869190207Srpaulo if (length2 >= length) { 870190207Srpaulo printf("\n\t[LLS truncated]"); 871190207Srpaulo return (1); 872190207Srpaulo } 873190207Srpaulo TCHECK2(*dptr, 2); 874190207Srpaulo printf("\n\t LLS: checksum: 0x%04x", (u_int)EXTRACT_16BITS(dptr)); 875190207Srpaulo 876190207Srpaulo dptr += 2; 877190207Srpaulo TCHECK2(*dptr, 2); 878190207Srpaulo length2 = EXTRACT_16BITS(dptr); 879190207Srpaulo printf(", length: %u", length2); 880190207Srpaulo 881190207Srpaulo dptr += 2; 882190207Srpaulo TCHECK(*dptr); 883190207Srpaulo while (dptr < dataend) { 884190207Srpaulo TCHECK2(*dptr, 2); 885190207Srpaulo lls_type = EXTRACT_16BITS(dptr); 886190207Srpaulo printf("\n\t %s (%u)", 887190207Srpaulo tok2str(ospf_lls_tlv_values,"Unknown TLV",lls_type), 888190207Srpaulo lls_type); 889190207Srpaulo dptr += 2; 890190207Srpaulo TCHECK2(*dptr, 2); 891190207Srpaulo lls_len = EXTRACT_16BITS(dptr); 892190207Srpaulo printf(", length: %u", lls_len); 893190207Srpaulo dptr += 2; 894190207Srpaulo switch (lls_type) { 895190207Srpaulo 896190207Srpaulo case OSPF_LLS_EO: 897190207Srpaulo if (lls_len != 4) { 898190207Srpaulo printf(" [should be 4]"); 899190207Srpaulo lls_len = 4; 900190207Srpaulo } 901190207Srpaulo TCHECK2(*dptr, 4); 902190207Srpaulo lls_flags = EXTRACT_32BITS(dptr); 903190207Srpaulo printf("\n\t Options: 0x%08x [%s]", lls_flags, 904190207Srpaulo bittok2str(ospf_lls_eo_options,"?",lls_flags)); 905190207Srpaulo 906190207Srpaulo break; 907190207Srpaulo 908190207Srpaulo case OSPF_LLS_MD5: 909190207Srpaulo if (lls_len != 20) { 910190207Srpaulo printf(" [should be 20]"); 911190207Srpaulo lls_len = 20; 912190207Srpaulo } 913190207Srpaulo TCHECK2(*dptr, 4); 914190207Srpaulo printf("\n\t Sequence number: 0x%08x", EXTRACT_32BITS(dptr)); 915190207Srpaulo break; 916190207Srpaulo } 917190207Srpaulo 918190207Srpaulo dptr += lls_len; 919190207Srpaulo } 920190207Srpaulo 921190207Srpaulo return (0); 922190207Srpaulotrunc: 923190207Srpaulo return (1); 924190207Srpaulo} 925190207Srpaulo 926190207Srpaulostatic int 92726180Sfennerospf_decode_v2(register const struct ospfhdr *op, 92826180Sfenner register const u_char *dataend) 92917680Spst{ 93026180Sfenner register const struct in_addr *ap; 93126180Sfenner register const struct lsr *lsrp; 93226180Sfenner register const struct lsa_hdr *lshp; 93326180Sfenner register const struct lsa *lsap; 934127668Sbms register u_int32_t lsa_count,lsa_count_max; 93517680Spst 93626180Sfenner switch (op->ospf_type) { 93717680Spst 93826180Sfenner case OSPF_TYPE_UMD: 93926180Sfenner /* 94026180Sfenner * Rob Coltun's special monitoring packets; 94126180Sfenner * do nothing 94226180Sfenner */ 94326180Sfenner break; 94417680Spst 94526180Sfenner case OSPF_TYPE_HELLO: 946190207Srpaulo printf("\n\tOptions [%s]", 947127668Sbms bittok2str(ospf_option_values,"none",op->ospf_hello.hello_options)); 948127668Sbms 949127668Sbms TCHECK(op->ospf_hello.hello_deadint); 950190207Srpaulo printf("\n\t Hello Timer %us, Dead Timer %us, Mask %s, Priority %u", 951127668Sbms EXTRACT_16BITS(&op->ospf_hello.hello_helloint), 952127668Sbms EXTRACT_32BITS(&op->ospf_hello.hello_deadint), 953127668Sbms ipaddr_string(&op->ospf_hello.hello_mask), 954127668Sbms op->ospf_hello.hello_priority); 955127668Sbms 95626180Sfenner TCHECK(op->ospf_hello.hello_dr); 95726180Sfenner if (op->ospf_hello.hello_dr.s_addr != 0) 958127668Sbms printf("\n\t Designated Router %s", 95926180Sfenner ipaddr_string(&op->ospf_hello.hello_dr)); 960127668Sbms 96126180Sfenner TCHECK(op->ospf_hello.hello_bdr); 96226180Sfenner if (op->ospf_hello.hello_bdr.s_addr != 0) 963127668Sbms printf(", Backup Designated Router %s", 96426180Sfenner ipaddr_string(&op->ospf_hello.hello_bdr)); 965127668Sbms 966127668Sbms ap = op->ospf_hello.hello_neighbor; 967127668Sbms if ((u_char *)ap < dataend) 968127668Sbms printf("\n\t Neighbor List:"); 969127668Sbms while ((u_char *)ap < dataend) { 970127668Sbms TCHECK(*ap); 971127668Sbms printf("\n\t %s", ipaddr_string(ap)); 972127668Sbms ++ap; 973127668Sbms } 97426180Sfenner break; /* HELLO */ 97517680Spst 976127668Sbms case OSPF_TYPE_DD: 97726180Sfenner TCHECK(op->ospf_db.db_options); 978190207Srpaulo printf("\n\tOptions [%s]", 979127668Sbms bittok2str(ospf_option_values,"none",op->ospf_db.db_options)); 98026180Sfenner TCHECK(op->ospf_db.db_flags); 981190207Srpaulo printf(", DD Flags [%s]", 982127668Sbms bittok2str(ospf_dd_flag_values,"none",op->ospf_db.db_flags)); 983190207Srpaulo TCHECK(op->ospf_db.db_ifmtu); 984190207Srpaulo if (op->ospf_db.db_ifmtu) { 985214478Srpaulo printf(", MTU: %u", EXTRACT_16BITS(&op->ospf_db.db_ifmtu)); 986190207Srpaulo } 987190207Srpaulo TCHECK(op->ospf_db.db_seq); 988190207Srpaulo printf(", Sequence: 0x%08x", EXTRACT_32BITS(&op->ospf_db.db_seq)); 98917680Spst 990190207Srpaulo /* Print all the LS adv's */ 991190207Srpaulo lshp = op->ospf_db.db_lshdr; 992190207Srpaulo while (((u_char *)lshp < dataend) && ospf_print_lshdr(lshp) != -1) { 993190207Srpaulo ++lshp; 994190207Srpaulo } 99526180Sfenner break; 99617680Spst 997127668Sbms case OSPF_TYPE_LS_REQ: 998127668Sbms lsrp = op->ospf_lsr; 999127668Sbms while ((u_char *)lsrp < dataend) { 1000127668Sbms TCHECK(*lsrp); 1001127668Sbms 1002127668Sbms printf("\n\t Advertising Router: %s, %s LSA (%u)", 1003127668Sbms ipaddr_string(&lsrp->ls_router), 1004127668Sbms tok2str(lsa_values,"unknown",EXTRACT_32BITS(lsrp->ls_type)), 1005127668Sbms EXTRACT_32BITS(&lsrp->ls_type)); 1006127668Sbms 1007127668Sbms switch (EXTRACT_32BITS(lsrp->ls_type)) { 1008127668Sbms /* the LSA header for opaque LSAs was slightly changed */ 1009127668Sbms case LS_TYPE_OPAQUE_LL: 1010127668Sbms case LS_TYPE_OPAQUE_AL: 1011127668Sbms case LS_TYPE_OPAQUE_DW: 1012127668Sbms printf(", Opaque-Type: %s LSA (%u), Opaque-ID: %u", 1013127668Sbms tok2str(lsa_opaque_values, "unknown",lsrp->un_ls_stateid.opaque_field.opaque_type), 1014127668Sbms lsrp->un_ls_stateid.opaque_field.opaque_type, 1015127668Sbms EXTRACT_24BITS(&lsrp->un_ls_stateid.opaque_field.opaque_id)); 1016127668Sbms break; 1017127668Sbms default: 1018127668Sbms printf(", LSA-ID: %s", 1019127668Sbms ipaddr_string(&lsrp->un_ls_stateid.ls_stateid)); 1020127668Sbms break; 1021127668Sbms } 1022127668Sbms 1023127668Sbms ++lsrp; 1024127668Sbms } 102526180Sfenner break; 102617680Spst 1027127668Sbms case OSPF_TYPE_LS_UPDATE: 1028127668Sbms lsap = op->ospf_lsu.lsu_lsa; 1029127668Sbms TCHECK(op->ospf_lsu.lsu_count); 1030127668Sbms lsa_count_max = EXTRACT_32BITS(&op->ospf_lsu.lsu_count); 1031235530Sdelphij printf(", %d LSA%s",lsa_count_max, PLURAL_SUFFIX(lsa_count_max)); 1032127668Sbms for (lsa_count=1;lsa_count <= lsa_count_max;lsa_count++) { 1033127668Sbms printf("\n\t LSA #%u",lsa_count); 1034127668Sbms lsap = (const struct lsa *)ospf_print_lsa(lsap); 1035127668Sbms if (lsap == NULL) 1036127668Sbms goto trunc; 1037127668Sbms } 103826180Sfenner break; 103917680Spst 1040127668Sbms case OSPF_TYPE_LS_ACK: 1041127668Sbms lshp = op->ospf_lsa.lsa_lshdr; 1042127668Sbms while (ospf_print_lshdr(lshp) != -1) { 1043127668Sbms ++lshp; 1044127668Sbms } 1045127668Sbms break; 104617680Spst 104717680Spst default: 104826180Sfenner break; 104917680Spst } 105026180Sfenner return (0); 105126180Sfennertrunc: 105226180Sfenner return (1); 105326180Sfenner} 105417680Spst 105526180Sfennervoid 105626180Sfennerospf_print(register const u_char *bp, register u_int length, 1057147899Ssam const u_char *bp2 _U_) 105826180Sfenner{ 105926180Sfenner register const struct ospfhdr *op; 106026180Sfenner register const u_char *dataend; 106126180Sfenner register const char *cp; 106217680Spst 106326180Sfenner op = (struct ospfhdr *)bp; 106417680Spst 106539297Sfenner /* XXX Before we do anything else, strip off the MD5 trailer */ 106639297Sfenner TCHECK(op->ospf_authtype); 1067127668Sbms if (EXTRACT_16BITS(&op->ospf_authtype) == OSPF_AUTH_MD5) { 106839297Sfenner length -= OSPF_AUTH_MD5_LEN; 106939297Sfenner snapend -= OSPF_AUTH_MD5_LEN; 107039297Sfenner } 107139297Sfenner 107226180Sfenner /* If the type is valid translate it, or just print the type */ 107326180Sfenner /* value. If it's not valid, say so and return */ 107426180Sfenner TCHECK(op->ospf_type); 1075127668Sbms cp = tok2str(type2str, "unknown LS-type", op->ospf_type); 1076190207Srpaulo printf("OSPFv%u, %s, length %u", 1077127668Sbms op->ospf_version, 1078127668Sbms cp, 1079127668Sbms length); 1080127668Sbms if (*cp == 'u') 108126180Sfenner return; 108217680Spst 1083190207Srpaulo if(!vflag) { /* non verbose - so lets bail out here */ 1084127668Sbms return; 1085190207Srpaulo } 1086127668Sbms 108726180Sfenner TCHECK(op->ospf_len); 1088127668Sbms if (length != EXTRACT_16BITS(&op->ospf_len)) { 1089127668Sbms printf(" [len %d]", EXTRACT_16BITS(&op->ospf_len)); 109026180Sfenner } 109117680Spst 1092190207Srpaulo if (length > EXTRACT_16BITS(&op->ospf_len)) { 1093190207Srpaulo dataend = bp + EXTRACT_16BITS(&op->ospf_len); 1094190207Srpaulo } else { 1095190207Srpaulo dataend = bp + length; 1096190207Srpaulo } 1097190207Srpaulo 109826180Sfenner TCHECK(op->ospf_routerid); 1099190207Srpaulo printf("\n\tRouter-ID %s", ipaddr_string(&op->ospf_routerid)); 110017680Spst 110126180Sfenner TCHECK(op->ospf_areaid); 110226180Sfenner if (op->ospf_areaid.s_addr != 0) 1103127668Sbms printf(", Area %s", ipaddr_string(&op->ospf_areaid)); 110426180Sfenner else 1105127668Sbms printf(", Backbone Area"); 110617680Spst 110726180Sfenner if (vflag) { 110826180Sfenner /* Print authentication data (should we really do this?) */ 110926180Sfenner TCHECK2(op->ospf_authdata[0], sizeof(op->ospf_authdata)); 111017680Spst 1111127668Sbms printf(", Authentication Type: %s (%u)", 1112127668Sbms tok2str(ospf_authtype_values,"unknown",EXTRACT_16BITS(&op->ospf_authtype)), 1113127668Sbms EXTRACT_16BITS(&op->ospf_authtype)); 1114127668Sbms 1115127668Sbms switch (EXTRACT_16BITS(&op->ospf_authtype)) { 1116127668Sbms 111726180Sfenner case OSPF_AUTH_NONE: 111817680Spst break; 111917680Spst 112026180Sfenner case OSPF_AUTH_SIMPLE: 1121172683Smlaier printf("\n\tSimple text password: "); 1122190207Srpaulo safeputs((const char *)op->ospf_authdata, OSPF_AUTH_SIMPLE_LEN); 112317680Spst break; 112417680Spst 112539297Sfenner case OSPF_AUTH_MD5: 1126127668Sbms printf("\n\tKey-ID: %u, Auth-Length: %u, Crypto Sequence Number: 0x%08x", 1127127668Sbms *((op->ospf_authdata)+2), 1128127668Sbms *((op->ospf_authdata)+3), 1129127668Sbms EXTRACT_32BITS((op->ospf_authdata)+4)); 113039297Sfenner break; 113139297Sfenner 113226180Sfenner default: 113326180Sfenner return; 113417680Spst } 113526180Sfenner } 113626180Sfenner /* Do rest according to version. */ 113726180Sfenner switch (op->ospf_version) { 113817680Spst 113926180Sfenner case 2: 114026180Sfenner /* ospf version 2 */ 114126180Sfenner if (ospf_decode_v2(op, dataend)) 114226180Sfenner goto trunc; 1143190207Srpaulo if (length > EXTRACT_16BITS(&op->ospf_len)) { 1144190207Srpaulo if (ospf_decode_lls(op, length)) 1145190207Srpaulo goto trunc; 1146190207Srpaulo } 114726180Sfenner break; 114817680Spst 114926180Sfenner default: 115026180Sfenner printf(" ospf [version %d]", op->ospf_version); 115117680Spst break; 115226180Sfenner } /* end switch on version */ 115317680Spst 115426180Sfenner return; 115526180Sfennertrunc: 115626180Sfenner fputs(tstr, stdout); 115717680Spst} 1158