156893Sfenner/* 256893Sfenner * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997 356893Sfenner * The Regents of the University of California. All rights reserved. 456893Sfenner * 556893Sfenner * Redistribution and use in source and binary forms, with or without 656893Sfenner * modification, are permitted provided that: (1) source code distributions 756893Sfenner * retain the above copyright notice and this paragraph in its entirety, (2) 856893Sfenner * distributions including binary code include the above copyright notice and 956893Sfenner * this paragraph in its entirety in the documentation or other materials 1056893Sfenner * provided with the distribution, and (3) all advertising materials mentioning 1156893Sfenner * features or use of this software display the following acknowledgement: 1256893Sfenner * ``This product includes software developed by the University of California, 1356893Sfenner * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1456893Sfenner * the University nor the names of its contributors may be used to endorse 1556893Sfenner * or promote products derived from this software without specific prior 1656893Sfenner * written permission. 1756893Sfenner * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1856893Sfenner * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1956893Sfenner * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2056893Sfenner * 2156893Sfenner * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu) 2256893Sfenner */ 2356893Sfenner 2456893Sfenner#ifndef lint 25127668Sbmsstatic const char rcsid[] _U_ = 26190207Srpaulo "@(#) $Header: /tcpdump/master/tcpdump/print-ospf6.c,v 1.15 2006-09-13 06:31:11 guy Exp $ (LBL)"; 2756893Sfenner#endif 2856893Sfenner 2956893Sfenner#ifdef HAVE_CONFIG_H 3056893Sfenner#include "config.h" 3156893Sfenner#endif 3256893Sfenner 33127668Sbms#include <tcpdump-stdinc.h> 3456893Sfenner 3556893Sfenner#include <stdio.h> 3656893Sfenner#include <string.h> 3756893Sfenner 3856893Sfenner#include "interface.h" 3956893Sfenner#include "addrtoname.h" 40127668Sbms#include "extract.h" 4156893Sfenner 42190207Srpaulo#include "ospf.h" 4356893Sfenner#include "ospf6.h" 4456893Sfenner 45190207Srpaulostatic const struct tok ospf6_option_values[] = { 46190207Srpaulo { OSPF6_OPTION_V6, "V6" }, 47190207Srpaulo { OSPF6_OPTION_E, "External" }, 48190207Srpaulo { OSPF6_OPTION_MC, "Multicast" }, 49190207Srpaulo { OSPF6_OPTION_N, "NSSA" }, 50190207Srpaulo { OSPF6_OPTION_R, "Router" }, 51190207Srpaulo { OSPF6_OPTION_DC, "Demand Circuit" }, 52190207Srpaulo { 0, NULL } 5356893Sfenner}; 5456893Sfenner 55190207Srpaulostatic const struct tok ospf6_rla_flag_values[] = { 56190207Srpaulo { RLA_FLAG_B, "ABR" }, 57190207Srpaulo { RLA_FLAG_E, "External" }, 58190207Srpaulo { RLA_FLAG_V, "Virtual-Link Endpoint" }, 59190207Srpaulo { RLA_FLAG_W, "Wildcard Receiver" }, 60190207Srpaulo { RLA_FLAG_N, "NSSA Translator" }, 6156893Sfenner { 0, NULL } 6256893Sfenner}; 6356893Sfenner 64190207Srpaulostatic const struct tok ospf6_asla_flag_values[] = { 65190207Srpaulo { ASLA_FLAG_EXTERNAL, "External Type 2" }, 66190207Srpaulo { ASLA_FLAG_FWDADDR, "Fforwarding" }, 67190207Srpaulo { ASLA_FLAG_ROUTETAG, "Tag" }, 6856893Sfenner { 0, NULL } 6956893Sfenner}; 7056893Sfenner 71190207Srpaulostatic struct tok ospf6_type_values[] = { 72190207Srpaulo { OSPF_TYPE_HELLO, "Hello" }, 73190207Srpaulo { OSPF_TYPE_DD, "Database Description" }, 74190207Srpaulo { OSPF_TYPE_LS_REQ, "LS-Request" }, 75190207Srpaulo { OSPF_TYPE_LS_UPDATE, "LS-Update" }, 76190207Srpaulo { OSPF_TYPE_LS_ACK, "LS-Ack" }, 7775115Sfenner { 0, NULL } 7875115Sfenner}; 7975115Sfenner 80190207Srpaulostatic struct tok ospf6_lsa_values[] = { 81190207Srpaulo { LS_TYPE_ROUTER, "Router" }, 82190207Srpaulo { LS_TYPE_NETWORK, "Network" }, 83190207Srpaulo { LS_TYPE_INTER_AP, "Inter-Area Prefix" }, 84190207Srpaulo { LS_TYPE_INTER_AR, "Inter-Area Router" }, 85190207Srpaulo { LS_TYPE_ASE, "External" }, 86190207Srpaulo { LS_TYPE_GROUP, "Multicast Group" }, 87190207Srpaulo { LS_TYPE_NSSA, "NSSA" }, 88190207Srpaulo { LS_TYPE_LINK, "Link" }, 89190207Srpaulo { LS_TYPE_INTRA_AP, "Intra-Area Prefix" }, 90190207Srpaulo { LS_TYPE_INTRA_ATE, "Intra-Area TE" }, 91190207Srpaulo { LS_TYPE_GRACE, "Grace" }, 9256893Sfenner { 0, NULL } 9356893Sfenner}; 9456893Sfenner 95190207Srpaulostatic struct tok ospf6_ls_scope_values[] = { 96190207Srpaulo { LS_SCOPE_LINKLOCAL, "Link Local" }, 97190207Srpaulo { LS_SCOPE_AREA, "Area Local" }, 98190207Srpaulo { LS_SCOPE_AS, "Domain Wide" }, 99190207Srpaulo { 0, NULL } 100190207Srpaulo}; 10156893Sfenner 102190207Srpaulostatic struct tok ospf6_dd_flag_values[] = { 103190207Srpaulo { OSPF6_DB_INIT, "Init" }, 104190207Srpaulo { OSPF6_DB_MORE, "More" }, 105190207Srpaulo { OSPF6_DB_MASTER, "Master" }, 106190207Srpaulo { 0, NULL } 107190207Srpaulo}; 108190207Srpaulo 109190207Srpaulostatic struct tok ospf6_lsa_prefix_option_values[] = { 110190207Srpaulo { LSA_PREFIX_OPT_NU, "No Unicast" }, 111190207Srpaulo { LSA_PREFIX_OPT_LA, "Local address" }, 112190207Srpaulo { LSA_PREFIX_OPT_MC, "Multicast" }, 113190207Srpaulo { LSA_PREFIX_OPT_P, "Propagate" }, 114190207Srpaulo { LSA_PREFIX_OPT_DN, "Down" }, 115190207Srpaulo { 0, NULL } 116190207Srpaulo}; 117190207Srpaulo 118190207Srpaulostatic char tstr[] = " [|ospf3]"; 119190207Srpaulo 120127668Sbms#ifdef WIN32 121127668Sbms#define inline __inline 122127668Sbms#endif /* WIN32 */ 123127668Sbms 12456893Sfenner/* Forwards */ 125190207Srpaulostatic void ospf6_print_ls_type(u_int, const rtrid_t *); 126190207Srpaulostatic int ospf6_print_lshdr(const struct lsa6_hdr *); 127190207Srpaulostatic int ospf6_print_lsa(const struct lsa6 *); 12856893Sfennerstatic int ospf6_decode_v3(const struct ospf6hdr *, const u_char *); 12956893Sfenner 13056893Sfenner 13156893Sfennerstatic void 132190207Srpauloospf6_print_ls_type(register u_int ls_type, register const rtrid_t *ls_stateid) 13356893Sfenner{ 134190207Srpaulo printf("\n\t %s LSA (%d), %s Scope%s, LSA-ID %s", 135190207Srpaulo tok2str(ospf6_lsa_values, "Unknown", ls_type & LS_TYPE_MASK), 136190207Srpaulo ls_type & LS_TYPE_MASK, 137190207Srpaulo tok2str(ospf6_ls_scope_values, "Unknown", ls_type & LS_SCOPE_MASK), 138190207Srpaulo ls_type &0x8000 ? ", transitive" : "", /* U-bit */ 139190207Srpaulo ipaddr_string(ls_stateid)); 14056893Sfenner} 14156893Sfenner 14256893Sfennerstatic int 143190207Srpauloospf6_print_lshdr(register const struct lsa6_hdr *lshp) 14456893Sfenner{ 14556893Sfenner 14656893Sfenner TCHECK(lshp->ls_type); 14756893Sfenner TCHECK(lshp->ls_seq); 14856893Sfenner 149190207Srpaulo printf("\n\t Advertising Router %s, seq 0x%08x, age %us, length %u", 150190207Srpaulo ipaddr_string(&lshp->ls_router), 151190207Srpaulo EXTRACT_32BITS(&lshp->ls_seq), 152190207Srpaulo EXTRACT_16BITS(&lshp->ls_age), 153190207Srpaulo EXTRACT_16BITS(&lshp->ls_length)-(u_int)sizeof(struct lsa6_hdr)); 154190207Srpaulo 155190207Srpaulo ospf6_print_ls_type(EXTRACT_16BITS(&lshp->ls_type), &lshp->ls_stateid); 156190207Srpaulo 15756893Sfenner return (0); 15856893Sfennertrunc: 15956893Sfenner return (1); 16056893Sfenner} 16156893Sfenner 16256893Sfennerstatic int 163241235Sdelphijospf6_print_lsaprefix(const u_int8_t *tptr, u_int lsa_length) 16456893Sfenner{ 165241235Sdelphij const struct lsa6_prefix *lsapp = (struct lsa6_prefix *)tptr; 166190207Srpaulo u_int wordlen; 16756893Sfenner struct in6_addr prefix; 16856893Sfenner 169241235Sdelphij if (lsa_length < sizeof (*lsapp) - 4) 170241235Sdelphij goto trunc; 171241235Sdelphij lsa_length -= sizeof (*lsapp) - 4; 172241235Sdelphij TCHECK2(*lsapp, sizeof (*lsapp) - 4); 173190207Srpaulo wordlen = (lsapp->lsa_p_len + 31) / 32; 174190207Srpaulo if (wordlen * 4 > sizeof(struct in6_addr)) { 175190207Srpaulo printf(" bogus prefixlen /%d", lsapp->lsa_p_len); 17656893Sfenner goto trunc; 17756893Sfenner } 178241235Sdelphij if (lsa_length < wordlen * 4) 179241235Sdelphij goto trunc; 180241235Sdelphij lsa_length -= wordlen * 4; 181241235Sdelphij TCHECK2(lsapp->lsa_p_prefix, wordlen * 4); 18256893Sfenner memset(&prefix, 0, sizeof(prefix)); 183190207Srpaulo memcpy(&prefix, lsapp->lsa_p_prefix, wordlen * 4); 184190207Srpaulo printf("\n\t\t%s/%d", ip6addr_string(&prefix), 18556893Sfenner lsapp->lsa_p_len); 186190207Srpaulo if (lsapp->lsa_p_opt) { 187190207Srpaulo printf(", Options [%s]", 188190207Srpaulo bittok2str(ospf6_lsa_prefix_option_values, 189190207Srpaulo "none", lsapp->lsa_p_opt)); 190190207Srpaulo } 191190207Srpaulo printf(", metric %u", EXTRACT_16BITS(&lsapp->lsa_p_metric)); 192190207Srpaulo return sizeof(*lsapp) - 4 + wordlen * 4; 19356893Sfenner 19456893Sfennertrunc: 19556893Sfenner return -1; 19656893Sfenner} 19756893Sfenner 19856893Sfenner 19956893Sfenner/* 20056893Sfenner * Print a single link state advertisement. If truncated return 1, else 0. 20156893Sfenner */ 20256893Sfennerstatic int 203190207Srpauloospf6_print_lsa(register const struct lsa6 *lsap) 20456893Sfenner{ 205190207Srpaulo register const struct rlalink6 *rlp; 20656893Sfenner#if 0 20756893Sfenner register const struct tos_metric *tosp; 20856893Sfenner#endif 20956893Sfenner register const rtrid_t *ap; 21056893Sfenner#if 0 21156893Sfenner register const struct aslametric *almp; 21256893Sfenner register const struct mcla *mcp; 21356893Sfenner#endif 21456893Sfenner register const struct llsa *llsap; 215190207Srpaulo register const struct lsa6_prefix *lsapp; 21656893Sfenner#if 0 21756893Sfenner register const u_int32_t *lp; 21856893Sfenner#endif 219190207Srpaulo register u_int prefixes; 220241235Sdelphij register int bytelen; 221241235Sdelphij register u_int length, lsa_length; 22275115Sfenner u_int32_t flags32; 223241235Sdelphij const u_int8_t *tptr; 22456893Sfenner 22556893Sfenner if (ospf6_print_lshdr(&lsap->ls_hdr)) 22656893Sfenner return (1); 22756893Sfenner TCHECK(lsap->ls_hdr.ls_length); 228190207Srpaulo length = EXTRACT_16BITS(&lsap->ls_hdr.ls_length); 229241235Sdelphij 230241235Sdelphij /* 231241235Sdelphij * The LSA length includes the length of the header; 232241235Sdelphij * it must have a value that's at least that length. 233241235Sdelphij * If it does, find the length of what follows the 234241235Sdelphij * header. 235241235Sdelphij */ 236241235Sdelphij if (length < sizeof(struct lsa6_hdr)) 237241235Sdelphij return (1); 238190207Srpaulo lsa_length = length - sizeof(struct lsa6_hdr); 239190207Srpaulo tptr = (u_int8_t *)lsap+sizeof(struct lsa6_hdr); 240190207Srpaulo 241127668Sbms switch (EXTRACT_16BITS(&lsap->ls_hdr.ls_type)) { 24256893Sfenner case LS_TYPE_ROUTER | LS_SCOPE_AREA: 243241235Sdelphij if (lsa_length < sizeof (lsap->lsa_un.un_rla.rla_options)) 244241235Sdelphij return (1); 245241235Sdelphij lsa_length -= sizeof (lsap->lsa_un.un_rla.rla_options); 24656893Sfenner TCHECK(lsap->lsa_un.un_rla.rla_options); 247190207Srpaulo printf("\n\t Options [%s]", 248190207Srpaulo bittok2str(ospf6_option_values, "none", 249190207Srpaulo EXTRACT_32BITS(&lsap->lsa_un.un_rla.rla_options))); 250190207Srpaulo printf(", RLA-Flags [%s]", 251190207Srpaulo bittok2str(ospf6_rla_flag_values, "none", 252190207Srpaulo lsap->lsa_un.un_rla.rla_flags)); 253190207Srpaulo 25456893Sfenner rlp = lsap->lsa_un.un_rla.rla_link; 255241235Sdelphij while (lsa_length != 0) { 256241235Sdelphij if (lsa_length < sizeof (*rlp)) 257241235Sdelphij return (1); 258241235Sdelphij lsa_length -= sizeof (*rlp); 25956893Sfenner TCHECK(*rlp); 26056893Sfenner switch (rlp->link_type) { 26156893Sfenner 26256893Sfenner case RLA_TYPE_VIRTUAL: 263190207Srpaulo printf("\n\t Virtual Link: Neighbor Router-ID %s" 264190207Srpaulo "\n\t Neighbor Interface-ID %s, Interface %s", 265190207Srpaulo ipaddr_string(&rlp->link_nrtid), 266190207Srpaulo ipaddr_string(&rlp->link_nifid), 267190207Srpaulo ipaddr_string(&rlp->link_ifid)); 268190207Srpaulo break; 26956893Sfenner 27056893Sfenner case RLA_TYPE_ROUTER: 271190207Srpaulo printf("\n\t Neighbor Router-ID %s" 272190207Srpaulo "\n\t Neighbor Interface-ID %s, Interface %s", 273190207Srpaulo ipaddr_string(&rlp->link_nrtid), 274190207Srpaulo ipaddr_string(&rlp->link_nifid), 275190207Srpaulo ipaddr_string(&rlp->link_ifid)); 27656893Sfenner break; 27756893Sfenner 27856893Sfenner case RLA_TYPE_TRANSIT: 279190207Srpaulo printf("\n\t Neighbor Network-ID %s" 280190207Srpaulo "\n\t Neighbor Interface-ID %s, Interface %s", 28156893Sfenner ipaddr_string(&rlp->link_nrtid), 28256893Sfenner ipaddr_string(&rlp->link_nifid), 28356893Sfenner ipaddr_string(&rlp->link_ifid)); 28456893Sfenner break; 28556893Sfenner 28656893Sfenner default: 287190207Srpaulo printf("\n\t Unknown Router Links Type 0x%02x", 28856893Sfenner rlp->link_type); 28956893Sfenner return (0); 29056893Sfenner } 291190207Srpaulo printf(", metric %d", EXTRACT_16BITS(&rlp->link_metric)); 29256893Sfenner rlp++; 29356893Sfenner } 29456893Sfenner break; 29556893Sfenner 29656893Sfenner case LS_TYPE_NETWORK | LS_SCOPE_AREA: 297241235Sdelphij if (lsa_length < sizeof (lsap->lsa_un.un_nla.nla_options)) 298241235Sdelphij return (1); 299241235Sdelphij lsa_length -= sizeof (lsap->lsa_un.un_nla.nla_options); 30056893Sfenner TCHECK(lsap->lsa_un.un_nla.nla_options); 301190207Srpaulo printf("\n\t Options [%s]", 302190207Srpaulo bittok2str(ospf6_option_values, "none", 303190207Srpaulo EXTRACT_32BITS(&lsap->lsa_un.un_nla.nla_options))); 304241235Sdelphij 305190207Srpaulo printf("\n\t Connected Routers:"); 30656893Sfenner ap = lsap->lsa_un.un_nla.nla_router; 307241235Sdelphij while (lsa_length != 0) { 308241235Sdelphij if (lsa_length < sizeof (*ap)) 309241235Sdelphij return (1); 310241235Sdelphij lsa_length -= sizeof (*ap); 31156893Sfenner TCHECK(*ap); 312190207Srpaulo printf("\n\t\t%s", ipaddr_string(ap)); 31356893Sfenner ++ap; 31456893Sfenner } 31556893Sfenner break; 31656893Sfenner 31756893Sfenner case LS_TYPE_INTER_AP | LS_SCOPE_AREA: 318241235Sdelphij if (lsa_length < sizeof (lsap->lsa_un.un_inter_ap.inter_ap_metric)) 319241235Sdelphij return (1); 320241235Sdelphij lsa_length -= sizeof (lsap->lsa_un.un_inter_ap.inter_ap_metric); 32156893Sfenner TCHECK(lsap->lsa_un.un_inter_ap.inter_ap_metric); 322190207Srpaulo printf(", metric %u", 323127668Sbms EXTRACT_32BITS(&lsap->lsa_un.un_inter_ap.inter_ap_metric) & SLA_MASK_METRIC); 324241235Sdelphij 325241235Sdelphij tptr = (u_int8_t *)lsap->lsa_un.un_inter_ap.inter_ap_prefix; 326241235Sdelphij while (lsa_length != 0) { 327241235Sdelphij bytelen = ospf6_print_lsaprefix(tptr, lsa_length); 328241235Sdelphij if (bytelen < 0) 32956893Sfenner goto trunc; 330241235Sdelphij lsa_length -= bytelen; 331241235Sdelphij tptr += bytelen; 33256893Sfenner } 33356893Sfenner break; 334241235Sdelphij 335241235Sdelphij case LS_TYPE_ASE | LS_SCOPE_AS: 336241235Sdelphij if (lsa_length < sizeof (lsap->lsa_un.un_asla.asla_metric)) 337241235Sdelphij return (1); 338241235Sdelphij lsa_length -= sizeof (lsap->lsa_un.un_asla.asla_metric); 33975115Sfenner TCHECK(lsap->lsa_un.un_asla.asla_metric); 340127668Sbms flags32 = EXTRACT_32BITS(&lsap->lsa_un.un_asla.asla_metric); 341190207Srpaulo printf("\n\t Flags [%s]", 342190207Srpaulo bittok2str(ospf6_asla_flag_values, "none", flags32)); 34375115Sfenner printf(" metric %u", 344127668Sbms EXTRACT_32BITS(&lsap->lsa_un.un_asla.asla_metric) & 34575115Sfenner ASLA_MASK_METRIC); 346241235Sdelphij 347241235Sdelphij tptr = (u_int8_t *)lsap->lsa_un.un_asla.asla_prefix; 348241235Sdelphij lsapp = (struct lsa6_prefix *)tptr; 349241235Sdelphij bytelen = ospf6_print_lsaprefix(tptr, lsa_length); 350190207Srpaulo if (bytelen < 0) 35175115Sfenner goto trunc; 352241235Sdelphij lsa_length -= bytelen; 353241235Sdelphij tptr += bytelen; 354241235Sdelphij 355241235Sdelphij if ((flags32 & ASLA_FLAG_FWDADDR) != 0) { 35675115Sfenner struct in6_addr *fwdaddr6; 35756893Sfenner 358241235Sdelphij fwdaddr6 = (struct in6_addr *)tptr; 359241235Sdelphij if (lsa_length < sizeof (*fwdaddr6)) 360241235Sdelphij return (1); 361241235Sdelphij lsa_length -= sizeof (*fwdaddr6); 362241235Sdelphij TCHECK(*fwdaddr6); 363241235Sdelphij printf(" forward %s", 364241235Sdelphij ip6addr_string(fwdaddr6)); 365241235Sdelphij tptr += sizeof(*fwdaddr6); 366241235Sdelphij } 36775115Sfenner 368241235Sdelphij if ((flags32 & ASLA_FLAG_ROUTETAG) != 0) { 369241235Sdelphij if (lsa_length < sizeof (u_int32_t)) 370241235Sdelphij return (1); 371241235Sdelphij lsa_length -= sizeof (u_int32_t); 372241235Sdelphij TCHECK(*(u_int32_t *)tptr); 373241235Sdelphij printf(" tag %s", 374241235Sdelphij ipaddr_string((u_int32_t *)tptr)); 375241235Sdelphij tptr += sizeof(u_int32_t); 376241235Sdelphij } 37775115Sfenner 378241235Sdelphij if (lsapp->lsa_p_metric) { 379241235Sdelphij if (lsa_length < sizeof (u_int32_t)) 380241235Sdelphij return (1); 381241235Sdelphij lsa_length -= sizeof (u_int32_t); 382241235Sdelphij TCHECK(*(u_int32_t *)tptr); 383241235Sdelphij printf(" RefLSID: %s", 384241235Sdelphij ipaddr_string((u_int32_t *)tptr)); 385241235Sdelphij tptr += sizeof(u_int32_t); 38675115Sfenner } 38775115Sfenner break; 38856893Sfenner 38956893Sfenner case LS_TYPE_LINK: 39056893Sfenner /* Link LSA */ 39156893Sfenner llsap = &lsap->lsa_un.un_llsa; 392241235Sdelphij if (lsa_length < sizeof (llsap->llsa_priandopt)) 393241235Sdelphij return (1); 394241235Sdelphij lsa_length -= sizeof (llsap->llsa_priandopt); 395241235Sdelphij TCHECK(llsap->llsa_priandopt); 396190207Srpaulo printf("\n\t Options [%s]", 397190207Srpaulo bittok2str(ospf6_option_values, "none", 398190207Srpaulo EXTRACT_32BITS(&llsap->llsa_options))); 399241235Sdelphij 400241235Sdelphij if (lsa_length < sizeof (llsap->llsa_lladdr) + sizeof (llsap->llsa_nprefix)) 401241235Sdelphij return (1); 402241235Sdelphij lsa_length -= sizeof (llsap->llsa_lladdr) + sizeof (llsap->llsa_nprefix); 403190207Srpaulo prefixes = EXTRACT_32BITS(&llsap->llsa_nprefix); 404190207Srpaulo printf("\n\t Priority %d, Link-local address %s, Prefixes %d:", 405190207Srpaulo llsap->llsa_priority, 406190207Srpaulo ip6addr_string(&llsap->llsa_lladdr), 407190207Srpaulo prefixes); 408190207Srpaulo 409190207Srpaulo tptr = (u_int8_t *)llsap->llsa_prefix; 410241235Sdelphij while (prefixes > 0) { 411241235Sdelphij bytelen = ospf6_print_lsaprefix(tptr, lsa_length); 412241235Sdelphij if (bytelen < 0) 413241235Sdelphij goto trunc; 414241235Sdelphij prefixes--; 415241235Sdelphij lsa_length -= bytelen; 416241235Sdelphij tptr += bytelen; 417241235Sdelphij } 41856893Sfenner break; 41956893Sfenner 42056893Sfenner case LS_TYPE_INTRA_AP | LS_SCOPE_AREA: 42156893Sfenner /* Intra-Area-Prefix LSA */ 422241235Sdelphij if (lsa_length < sizeof (lsap->lsa_un.un_intra_ap.intra_ap_rtid)) 423241235Sdelphij return (1); 424241235Sdelphij lsa_length -= sizeof (lsap->lsa_un.un_intra_ap.intra_ap_rtid); 42556893Sfenner TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_rtid); 42656893Sfenner ospf6_print_ls_type( 427127668Sbms EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_lstype), 428190207Srpaulo &lsap->lsa_un.un_intra_ap.intra_ap_lsid); 429241235Sdelphij 430241235Sdelphij if (lsa_length < sizeof (lsap->lsa_un.un_intra_ap.intra_ap_nprefix)) 431241235Sdelphij return (1); 432241235Sdelphij lsa_length -= sizeof (lsap->lsa_un.un_intra_ap.intra_ap_nprefix); 43356893Sfenner TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_nprefix); 434190207Srpaulo prefixes = EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_nprefix); 435190207Srpaulo printf("\n\t Prefixes %d:", prefixes); 43656893Sfenner 437241235Sdelphij tptr = (u_int8_t *)lsap->lsa_un.un_intra_ap.intra_ap_prefix; 438241235Sdelphij while (prefixes > 0) { 439241235Sdelphij bytelen = ospf6_print_lsaprefix(tptr, lsa_length); 440241235Sdelphij if (bytelen < 0) 441241235Sdelphij goto trunc; 442241235Sdelphij prefixes--; 443241235Sdelphij lsa_length -= bytelen; 444241235Sdelphij tptr += bytelen; 445241235Sdelphij } 44656893Sfenner break; 44756893Sfenner 448190207Srpaulo case LS_TYPE_GRACE | LS_SCOPE_LINKLOCAL: 449190207Srpaulo if (ospf_print_grace_lsa(tptr, lsa_length) == -1) { 450190207Srpaulo return 1; 451190207Srpaulo } 452241235Sdelphij break; 453190207Srpaulo 454190207Srpaulo case LS_TYPE_INTRA_ATE | LS_SCOPE_LINKLOCAL: 455241235Sdelphij if (ospf_print_te_lsa(tptr, lsa_length) == -1) { 456241235Sdelphij return 1; 457241235Sdelphij } 458241235Sdelphij break; 459190207Srpaulo 46056893Sfenner default: 461241235Sdelphij if(!print_unknown_data(tptr, 462241235Sdelphij "\n\t ", 463241235Sdelphij lsa_length)) { 464241235Sdelphij return (1); 465241235Sdelphij } 466241235Sdelphij break; 46756893Sfenner } 46856893Sfenner 46956893Sfenner return (0); 47056893Sfennertrunc: 47156893Sfenner return (1); 47256893Sfenner} 47356893Sfenner 47456893Sfennerstatic int 47556893Sfennerospf6_decode_v3(register const struct ospf6hdr *op, 47656893Sfenner register const u_char *dataend) 47756893Sfenner{ 47856893Sfenner register const rtrid_t *ap; 479190207Srpaulo register const struct lsr6 *lsrp; 480190207Srpaulo register const struct lsa6_hdr *lshp; 481190207Srpaulo register const struct lsa6 *lsap; 48256893Sfenner register int i; 48356893Sfenner 48456893Sfenner switch (op->ospf6_type) { 48556893Sfenner 486190207Srpaulo case OSPF_TYPE_HELLO: 487190207Srpaulo printf("\n\tOptions [%s]", 488190207Srpaulo bittok2str(ospf6_option_values, "none", 489190207Srpaulo EXTRACT_32BITS(&op->ospf6_hello.hello_options))); 49056893Sfenner 491190207Srpaulo TCHECK(op->ospf6_hello.hello_deadint); 492190207Srpaulo printf("\n\t Hello Timer %us, Dead Timer %us, Interface-ID %s, Priority %u", 493190207Srpaulo EXTRACT_16BITS(&op->ospf6_hello.hello_helloint), 494190207Srpaulo EXTRACT_16BITS(&op->ospf6_hello.hello_deadint), 495190207Srpaulo ipaddr_string(&op->ospf6_hello.hello_ifid), 496190207Srpaulo op->ospf6_hello.hello_priority); 497190207Srpaulo 49856893Sfenner TCHECK(op->ospf6_hello.hello_dr); 49956893Sfenner if (op->ospf6_hello.hello_dr != 0) 500190207Srpaulo printf("\n\t Designated Router %s", 50156893Sfenner ipaddr_string(&op->ospf6_hello.hello_dr)); 50256893Sfenner TCHECK(op->ospf6_hello.hello_bdr); 50356893Sfenner if (op->ospf6_hello.hello_bdr != 0) 504190207Srpaulo printf(", Backup Designated Router %s", 50556893Sfenner ipaddr_string(&op->ospf6_hello.hello_bdr)); 50656893Sfenner if (vflag) { 507190207Srpaulo printf("\n\t Neighbor List:"); 50856893Sfenner ap = op->ospf6_hello.hello_neighbor; 50956893Sfenner while ((u_char *)ap < dataend) { 51056893Sfenner TCHECK(*ap); 511190207Srpaulo printf("\n\t %s", ipaddr_string(ap)); 51256893Sfenner ++ap; 51356893Sfenner } 51456893Sfenner } 51556893Sfenner break; /* HELLO */ 51656893Sfenner 517190207Srpaulo case OSPF_TYPE_DD: 51856893Sfenner TCHECK(op->ospf6_db.db_options); 519190207Srpaulo printf("\n\tOptions [%s]", 520190207Srpaulo bittok2str(ospf6_option_values, "none", 521190207Srpaulo EXTRACT_32BITS(&op->ospf6_db.db_options))); 52256893Sfenner TCHECK(op->ospf6_db.db_flags); 523190207Srpaulo printf(", DD Flags [%s]", 524190207Srpaulo bittok2str(ospf6_dd_flag_values,"none",op->ospf6_db.db_flags)); 525190207Srpaulo 52656893Sfenner TCHECK(op->ospf6_db.db_seq); 527190207Srpaulo printf(", MTU %u, DD-Sequence 0x%08x", 528190207Srpaulo EXTRACT_16BITS(&op->ospf6_db.db_mtu), 529190207Srpaulo EXTRACT_32BITS(&op->ospf6_db.db_seq)); 53056893Sfenner 531190207Srpaulo /* Print all the LS adv's */ 532190207Srpaulo lshp = op->ospf6_db.db_lshdr; 533190207Srpaulo while (!ospf6_print_lshdr(lshp)) { 534190207Srpaulo ++lshp; 535190207Srpaulo } 53656893Sfenner break; 53756893Sfenner 538190207Srpaulo case OSPF_TYPE_LS_REQ: 53956893Sfenner if (vflag) { 54056893Sfenner lsrp = op->ospf6_lsr; 54156893Sfenner while ((u_char *)lsrp < dataend) { 54256893Sfenner TCHECK(*lsrp); 543190207Srpaulo printf("\n\t Advertising Router %s", 544190207Srpaulo ipaddr_string(&lsrp->ls_router)); 545127668Sbms ospf6_print_ls_type(EXTRACT_16BITS(&lsrp->ls_type), 546190207Srpaulo &lsrp->ls_stateid); 54756893Sfenner ++lsrp; 54856893Sfenner } 54956893Sfenner } 55056893Sfenner break; 55156893Sfenner 552190207Srpaulo case OSPF_TYPE_LS_UPDATE: 55356893Sfenner if (vflag) { 55456893Sfenner lsap = op->ospf6_lsu.lsu_lsa; 55556893Sfenner TCHECK(op->ospf6_lsu.lsu_count); 556127668Sbms i = EXTRACT_32BITS(&op->ospf6_lsu.lsu_count); 55756893Sfenner while (i--) { 55856893Sfenner if (ospf6_print_lsa(lsap)) 55956893Sfenner goto trunc; 560190207Srpaulo lsap = (struct lsa6 *)((u_char *)lsap + 561127668Sbms EXTRACT_16BITS(&lsap->ls_hdr.ls_length)); 56256893Sfenner } 56356893Sfenner } 56456893Sfenner break; 56556893Sfenner 56656893Sfenner 567190207Srpaulo case OSPF_TYPE_LS_ACK: 56856893Sfenner if (vflag) { 56956893Sfenner lshp = op->ospf6_lsa.lsa_lshdr; 57056893Sfenner 57156893Sfenner while (!ospf6_print_lshdr(lshp)) { 57256893Sfenner ++lshp; 57356893Sfenner } 57456893Sfenner } 57556893Sfenner break; 57656893Sfenner 57756893Sfenner default: 57856893Sfenner break; 57956893Sfenner } 58056893Sfenner return (0); 58156893Sfennertrunc: 58256893Sfenner return (1); 58356893Sfenner} 58456893Sfenner 58556893Sfennervoid 58656893Sfennerospf6_print(register const u_char *bp, register u_int length) 58756893Sfenner{ 58856893Sfenner register const struct ospf6hdr *op; 58956893Sfenner register const u_char *dataend; 59056893Sfenner register const char *cp; 59156893Sfenner 59256893Sfenner op = (struct ospf6hdr *)bp; 59356893Sfenner 59456893Sfenner /* If the type is valid translate it, or just print the type */ 59556893Sfenner /* value. If it's not valid, say so and return */ 59656893Sfenner TCHECK(op->ospf6_type); 597190207Srpaulo cp = tok2str(ospf6_type_values, "unknown LS-type", op->ospf6_type); 598190207Srpaulo printf("OSPFv%u, %s, length %d", op->ospf6_version, cp, length); 599190207Srpaulo if (*cp == 'u') { 60056893Sfenner return; 601190207Srpaulo } 60256893Sfenner 603190207Srpaulo if(!vflag) { /* non verbose - so lets bail out here */ 604190207Srpaulo return; 605190207Srpaulo } 606190207Srpaulo 60756893Sfenner TCHECK(op->ospf6_len); 608127668Sbms if (length != EXTRACT_16BITS(&op->ospf6_len)) { 609127668Sbms printf(" [len %d]", EXTRACT_16BITS(&op->ospf6_len)); 61056893Sfenner return; 61156893Sfenner } 61256893Sfenner dataend = bp + length; 61356893Sfenner 61456893Sfenner /* Print the routerid if it is not the same as the source */ 61556893Sfenner TCHECK(op->ospf6_routerid); 616190207Srpaulo printf("\n\tRouter-ID %s", ipaddr_string(&op->ospf6_routerid)); 61756893Sfenner 61856893Sfenner TCHECK(op->ospf6_areaid); 61956893Sfenner if (op->ospf6_areaid != 0) 620190207Srpaulo printf(", Area %s", ipaddr_string(&op->ospf6_areaid)); 62156893Sfenner else 622190207Srpaulo printf(", Backbone Area"); 62356893Sfenner TCHECK(op->ospf6_instanceid); 62456893Sfenner if (op->ospf6_instanceid) 625190207Srpaulo printf(", Instance %u", op->ospf6_instanceid); 62656893Sfenner 62756893Sfenner /* Do rest according to version. */ 62856893Sfenner switch (op->ospf6_version) { 62956893Sfenner 63056893Sfenner case 3: 63156893Sfenner /* ospf version 3 */ 63256893Sfenner if (ospf6_decode_v3(op, dataend)) 63356893Sfenner goto trunc; 63456893Sfenner break; 63556893Sfenner 63656893Sfenner default: 63756893Sfenner printf(" ospf [version %d]", op->ospf6_version); 63856893Sfenner break; 63956893Sfenner } /* end switch on version */ 64056893Sfenner 64156893Sfenner return; 64256893Sfennertrunc: 64356893Sfenner fputs(tstr, stdout); 64456893Sfenner} 645