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