print-ospf6.c revision 356341
1/*
2 * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 *
21 * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu)
22 */
23
24/* \summary: IPv6 Open Shortest Path First (OSPFv3) printer */
25
26#ifdef HAVE_CONFIG_H
27#include "config.h"
28#endif
29
30#include <netdissect-stdinc.h>
31
32#include <string.h>
33
34#include "netdissect.h"
35#include "addrtoname.h"
36#include "extract.h"
37
38#include "ospf.h"
39
40#define	OSPF_TYPE_HELLO         1	/* Hello */
41#define	OSPF_TYPE_DD            2	/* Database Description */
42#define	OSPF_TYPE_LS_REQ        3	/* Link State Request */
43#define	OSPF_TYPE_LS_UPDATE     4	/* Link State Update */
44#define	OSPF_TYPE_LS_ACK        5	/* Link State Ack */
45
46/* Options *_options	*/
47#define OSPF6_OPTION_V6	0x01	/* V6 bit: A bit for peeping tom */
48#define OSPF6_OPTION_E	0x02	/* E bit: External routes advertised	*/
49#define OSPF6_OPTION_MC	0x04	/* MC bit: Multicast capable */
50#define OSPF6_OPTION_N	0x08	/* N bit: For type-7 LSA */
51#define OSPF6_OPTION_R	0x10	/* R bit: Router bit */
52#define OSPF6_OPTION_DC	0x20	/* DC bit: Demand circuits */
53/* The field is actually 24-bit (RFC5340 Section A.2). */
54#define OSPF6_OPTION_AF	0x0100	/* AF bit: Multiple address families */
55#define OSPF6_OPTION_L	0x0200	/* L bit: Link-local signaling (LLS) */
56#define OSPF6_OPTION_AT	0x0400	/* AT bit: Authentication trailer */
57
58
59/* db_flags	*/
60#define	OSPF6_DB_INIT		0x04	    /*	*/
61#define	OSPF6_DB_MORE		0x02
62#define	OSPF6_DB_MASTER		0x01
63#define	OSPF6_DB_M6		0x10  /* IPv6 MTU */
64
65/* ls_type	*/
66#define	LS_TYPE_ROUTER		1   /* router link */
67#define	LS_TYPE_NETWORK		2   /* network link */
68#define	LS_TYPE_INTER_AP	3   /* Inter-Area-Prefix */
69#define	LS_TYPE_INTER_AR	4   /* Inter-Area-Router */
70#define	LS_TYPE_ASE		5   /* ASE */
71#define	LS_TYPE_GROUP		6   /* Group membership */
72#define	LS_TYPE_NSSA		7   /* NSSA */
73#define	LS_TYPE_LINK		8   /* Link LSA */
74#define	LS_TYPE_INTRA_AP	9   /* Intra-Area-Prefix */
75#define LS_TYPE_INTRA_ATE       10  /* Intra-Area-TE */
76#define LS_TYPE_GRACE           11  /* Grace LSA */
77#define LS_TYPE_RI		12  /* Router information */
78#define LS_TYPE_INTER_ASTE	13  /* Inter-AS-TE */
79#define LS_TYPE_L1VPN		14  /* L1VPN */
80#define LS_TYPE_MASK		0x1fff
81
82#define LS_SCOPE_LINKLOCAL	0x0000
83#define LS_SCOPE_AREA		0x2000
84#define LS_SCOPE_AS		0x4000
85#define LS_SCOPE_MASK		0x6000
86#define LS_SCOPE_U              0x8000
87
88/* rla_link.link_type	*/
89#define	RLA_TYPE_ROUTER		1   /* point-to-point to another router	*/
90#define	RLA_TYPE_TRANSIT	2   /* connection to transit network	*/
91#define RLA_TYPE_VIRTUAL	4   /* virtual link			*/
92
93/* rla_flags	*/
94#define	RLA_FLAG_B	0x01
95#define	RLA_FLAG_E	0x02
96#define	RLA_FLAG_V	0x04
97#define	RLA_FLAG_W	0x08
98#define RLA_FLAG_N      0x10
99
100/* lsa_prefix options */
101#define LSA_PREFIX_OPT_NU 0x01
102#define LSA_PREFIX_OPT_LA 0x02
103#define LSA_PREFIX_OPT_MC 0x04
104#define LSA_PREFIX_OPT_P  0x08
105#define LSA_PREFIX_OPT_DN 0x10
106
107/* sla_tosmetric breakdown	*/
108#define	SLA_MASK_TOS		0x7f000000
109#define	SLA_MASK_METRIC		0x00ffffff
110#define SLA_SHIFT_TOS		24
111
112/* asla_metric */
113#define ASLA_FLAG_FWDADDR	0x02000000
114#define ASLA_FLAG_ROUTETAG	0x01000000
115#define	ASLA_MASK_METRIC	0x00ffffff
116
117/* RFC6506 Section 4.1 */
118#define OSPF6_AT_HDRLEN             16U
119#define OSPF6_AUTH_TYPE_HMAC        0x0001
120
121typedef uint32_t rtrid_t;
122
123/* link state advertisement header */
124struct lsa6_hdr {
125    uint16_t ls_age;
126    uint16_t ls_type;
127    rtrid_t ls_stateid;
128    rtrid_t ls_router;
129    uint32_t ls_seq;
130    uint16_t ls_chksum;
131    uint16_t ls_length;
132};
133
134/* Length of an IPv6 address, in bytes. */
135#define IPV6_ADDR_LEN_BYTES (128/8)
136
137struct lsa6_prefix {
138    uint8_t lsa_p_len;
139    uint8_t lsa_p_opt;
140    uint16_t lsa_p_metric;
141    uint8_t lsa_p_prefix[IPV6_ADDR_LEN_BYTES]; /* maximum length */
142};
143
144/* link state advertisement */
145struct lsa6 {
146    struct lsa6_hdr ls_hdr;
147
148    /* Link state types */
149    union {
150	/* Router links advertisements */
151	struct {
152	    union {
153		uint8_t flg;
154		uint32_t opt;
155	    } rla_flgandopt;
156#define rla_flags	rla_flgandopt.flg
157#define rla_options	rla_flgandopt.opt
158	    struct rlalink6 {
159		uint8_t link_type;
160		uint8_t link_zero[1];
161		uint16_t link_metric;
162		uint32_t link_ifid;
163		uint32_t link_nifid;
164		rtrid_t link_nrtid;
165	    } rla_link[1];		/* may repeat	*/
166	} un_rla;
167
168	/* Network links advertisements */
169	struct {
170	    uint32_t nla_options;
171	    rtrid_t nla_router[1];	/* may repeat	*/
172	} un_nla;
173
174	/* Inter Area Prefix LSA */
175	struct {
176	    uint32_t inter_ap_metric;
177	    struct lsa6_prefix inter_ap_prefix[1];
178	} un_inter_ap;
179
180	/* AS external links advertisements */
181	struct {
182	    uint32_t asla_metric;
183	    struct lsa6_prefix asla_prefix[1];
184	    /* some optional fields follow */
185	} un_asla;
186
187#if 0
188	/* Summary links advertisements */
189	struct {
190	    struct in_addr sla_mask;
191	    uint32_t sla_tosmetric[1];	/* may repeat	*/
192	} un_sla;
193
194	/* Multicast group membership */
195	struct mcla {
196	    uint32_t mcla_vtype;
197	    struct in_addr mcla_vid;
198	} un_mcla[1];
199#endif
200
201	/* Type 7 LSA */
202
203	/* Link LSA */
204	struct llsa {
205	    union {
206		uint8_t pri;
207		uint32_t opt;
208	    } llsa_priandopt;
209#define llsa_priority	llsa_priandopt.pri
210#define llsa_options	llsa_priandopt.opt
211	    struct in6_addr llsa_lladdr;
212	    uint32_t llsa_nprefix;
213	    struct lsa6_prefix llsa_prefix[1];
214	} un_llsa;
215
216	/* Intra-Area-Prefix */
217	struct {
218	    uint16_t intra_ap_nprefix;
219	    uint16_t intra_ap_lstype;
220	    rtrid_t intra_ap_lsid;
221	    rtrid_t intra_ap_rtid;
222	    struct lsa6_prefix intra_ap_prefix[1];
223	} un_intra_ap;
224    } lsa_un;
225};
226
227/*
228 * the main header
229 */
230struct ospf6hdr {
231    uint8_t ospf6_version;
232    uint8_t ospf6_type;
233    uint16_t ospf6_len;
234    rtrid_t ospf6_routerid;
235    rtrid_t ospf6_areaid;
236    uint16_t ospf6_chksum;
237    uint8_t ospf6_instanceid;
238    uint8_t ospf6_rsvd;
239};
240
241/*
242 * The OSPF6 header length is 16 bytes, regardless of how your compiler
243 * might choose to pad the above structure.
244 */
245#define OSPF6HDR_LEN    16
246
247/* Hello packet */
248struct hello6 {
249    uint32_t hello_ifid;
250    union {
251	uint8_t pri;
252	uint32_t opt;
253    } hello_priandopt;
254#define hello_priority	hello_priandopt.pri
255#define hello_options	hello_priandopt.opt
256    uint16_t hello_helloint;
257    uint16_t hello_deadint;
258    rtrid_t hello_dr;
259    rtrid_t hello_bdr;
260    rtrid_t hello_neighbor[1]; /* may repeat	*/
261};
262
263/* Database Description packet */
264struct dd6 {
265    uint32_t db_options;
266    uint16_t db_mtu;
267    uint8_t db_mbz;
268    uint8_t db_flags;
269    uint32_t db_seq;
270    struct lsa6_hdr db_lshdr[1]; /* may repeat	*/
271};
272
273/* Link State Request */
274struct lsr6 {
275    uint16_t ls_mbz;
276    uint16_t ls_type;
277    rtrid_t ls_stateid;
278    rtrid_t ls_router;
279};
280
281/* Link State Update */
282struct lsu6 {
283    uint32_t lsu_count;
284    struct lsa6 lsu_lsa[1]; /* may repeat	*/
285};
286
287static const char tstr[] = " [|ospf3]";
288
289static const struct tok ospf6_option_values[] = {
290	{ OSPF6_OPTION_V6,	"V6" },
291	{ OSPF6_OPTION_E,	"External" },
292	{ OSPF6_OPTION_MC,	"Deprecated" },
293	{ OSPF6_OPTION_N,	"NSSA" },
294	{ OSPF6_OPTION_R,	"Router" },
295	{ OSPF6_OPTION_DC,	"Demand Circuit" },
296	{ OSPF6_OPTION_AF,	"AFs Support" },
297	{ OSPF6_OPTION_L,	"LLS" },
298	{ OSPF6_OPTION_AT,	"Authentication Trailer" },
299	{ 0,			NULL }
300};
301
302static const struct tok ospf6_rla_flag_values[] = {
303	{ RLA_FLAG_B,		"ABR" },
304	{ RLA_FLAG_E,		"External" },
305	{ RLA_FLAG_V,		"Virtual-Link Endpoint" },
306	{ RLA_FLAG_W,		"Wildcard Receiver" },
307        { RLA_FLAG_N,           "NSSA Translator" },
308	{ 0,			NULL }
309};
310
311static const struct tok ospf6_asla_flag_values[] = {
312	{ ASLA_FLAG_EXTERNAL,	"External Type 2" },
313	{ ASLA_FLAG_FWDADDR,	"Forwarding" },
314	{ ASLA_FLAG_ROUTETAG,	"Tag" },
315	{ 0,			NULL }
316};
317
318static const struct tok ospf6_type_values[] = {
319	{ OSPF_TYPE_HELLO,	"Hello" },
320	{ OSPF_TYPE_DD,		"Database Description" },
321	{ OSPF_TYPE_LS_REQ,	"LS-Request" },
322	{ OSPF_TYPE_LS_UPDATE,	"LS-Update" },
323	{ OSPF_TYPE_LS_ACK,	"LS-Ack" },
324	{ 0,			NULL }
325};
326
327static const struct tok ospf6_lsa_values[] = {
328	{ LS_TYPE_ROUTER,       "Router" },
329	{ LS_TYPE_NETWORK,      "Network" },
330	{ LS_TYPE_INTER_AP,     "Inter-Area Prefix" },
331	{ LS_TYPE_INTER_AR,     "Inter-Area Router" },
332	{ LS_TYPE_ASE,          "External" },
333	{ LS_TYPE_GROUP,        "Deprecated" },
334	{ LS_TYPE_NSSA,         "NSSA" },
335	{ LS_TYPE_LINK,         "Link" },
336	{ LS_TYPE_INTRA_AP,     "Intra-Area Prefix" },
337        { LS_TYPE_INTRA_ATE,    "Intra-Area TE" },
338        { LS_TYPE_GRACE,        "Grace" },
339	{ LS_TYPE_RI,           "Router Information" },
340	{ LS_TYPE_INTER_ASTE,   "Inter-AS-TE" },
341	{ LS_TYPE_L1VPN,        "Layer 1 VPN" },
342	{ 0,			NULL }
343};
344
345static const struct tok ospf6_ls_scope_values[] = {
346	{ LS_SCOPE_LINKLOCAL,   "Link Local" },
347	{ LS_SCOPE_AREA,        "Area Local" },
348	{ LS_SCOPE_AS,          "Domain Wide" },
349	{ 0,			NULL }
350};
351
352static const struct tok ospf6_dd_flag_values[] = {
353	{ OSPF6_DB_INIT,	"Init" },
354	{ OSPF6_DB_MORE,	"More" },
355	{ OSPF6_DB_MASTER,	"Master" },
356	{ OSPF6_DB_M6,		"IPv6 MTU" },
357	{ 0,			NULL }
358};
359
360static const struct tok ospf6_lsa_prefix_option_values[] = {
361        { LSA_PREFIX_OPT_NU, "No Unicast" },
362        { LSA_PREFIX_OPT_LA, "Local address" },
363        { LSA_PREFIX_OPT_MC, "Deprecated" },
364        { LSA_PREFIX_OPT_P, "Propagate" },
365        { LSA_PREFIX_OPT_DN, "Down" },
366	{ 0, NULL }
367};
368
369static const struct tok ospf6_auth_type_str[] = {
370	{ OSPF6_AUTH_TYPE_HMAC,        "HMAC" },
371	{ 0, NULL }
372};
373
374static void
375ospf6_print_ls_type(netdissect_options *ndo,
376                    register u_int ls_type, register const rtrid_t *ls_stateid)
377{
378        ND_PRINT((ndo, "\n\t    %s LSA (%d), %s Scope%s, LSA-ID %s",
379               tok2str(ospf6_lsa_values, "Unknown", ls_type & LS_TYPE_MASK),
380               ls_type & LS_TYPE_MASK,
381               tok2str(ospf6_ls_scope_values, "Unknown", ls_type & LS_SCOPE_MASK),
382               ls_type &0x8000 ? ", transitive" : "", /* U-bit */
383               ipaddr_string(ndo, ls_stateid)));
384}
385
386static int
387ospf6_print_lshdr(netdissect_options *ndo,
388                  register const struct lsa6_hdr *lshp, const u_char *dataend)
389{
390	if ((const u_char *)(lshp + 1) > dataend)
391		goto trunc;
392	ND_TCHECK(lshp->ls_length);	/* last field of struct lsa6_hdr */
393
394	ND_PRINT((ndo, "\n\t  Advertising Router %s, seq 0x%08x, age %us, length %u",
395               ipaddr_string(ndo, &lshp->ls_router),
396               EXTRACT_32BITS(&lshp->ls_seq),
397               EXTRACT_16BITS(&lshp->ls_age),
398               EXTRACT_16BITS(&lshp->ls_length)-(u_int)sizeof(struct lsa6_hdr)));
399
400	ospf6_print_ls_type(ndo, EXTRACT_16BITS(&lshp->ls_type), &lshp->ls_stateid);
401
402	return (0);
403trunc:
404	return (1);
405}
406
407static int
408ospf6_print_lsaprefix(netdissect_options *ndo,
409                      const uint8_t *tptr, u_int lsa_length)
410{
411	const struct lsa6_prefix *lsapp = (const struct lsa6_prefix *)tptr;
412	u_int wordlen;
413	struct in6_addr prefix;
414
415	if (lsa_length < sizeof (*lsapp) - IPV6_ADDR_LEN_BYTES)
416		goto trunc;
417	lsa_length -= sizeof (*lsapp) - IPV6_ADDR_LEN_BYTES;
418	ND_TCHECK2(*lsapp, sizeof (*lsapp) - IPV6_ADDR_LEN_BYTES);
419	wordlen = (lsapp->lsa_p_len + 31) / 32;
420	if (wordlen * 4 > sizeof(struct in6_addr)) {
421		ND_PRINT((ndo, " bogus prefixlen /%d", lsapp->lsa_p_len));
422		goto trunc;
423	}
424	if (lsa_length < wordlen * 4)
425		goto trunc;
426	lsa_length -= wordlen * 4;
427	ND_TCHECK2(lsapp->lsa_p_prefix, wordlen * 4);
428	memset(&prefix, 0, sizeof(prefix));
429	memcpy(&prefix, lsapp->lsa_p_prefix, wordlen * 4);
430	ND_PRINT((ndo, "\n\t\t%s/%d", ip6addr_string(ndo, &prefix),
431		lsapp->lsa_p_len));
432        if (lsapp->lsa_p_opt) {
433            ND_PRINT((ndo, ", Options [%s]",
434                   bittok2str(ospf6_lsa_prefix_option_values,
435                              "none", lsapp->lsa_p_opt)));
436        }
437        ND_PRINT((ndo, ", metric %u", EXTRACT_16BITS(&lsapp->lsa_p_metric)));
438	return sizeof(*lsapp) - IPV6_ADDR_LEN_BYTES + wordlen * 4;
439
440trunc:
441	return -1;
442}
443
444
445/*
446 * Print a single link state advertisement.  If truncated return 1, else 0.
447 */
448static int
449ospf6_print_lsa(netdissect_options *ndo,
450                register const struct lsa6 *lsap, const u_char *dataend)
451{
452	register const struct rlalink6 *rlp;
453#if 0
454	register const struct tos_metric *tosp;
455#endif
456	register const rtrid_t *ap;
457#if 0
458	register const struct aslametric *almp;
459	register const struct mcla *mcp;
460#endif
461	register const struct llsa *llsap;
462	register const struct lsa6_prefix *lsapp;
463#if 0
464	register const uint32_t *lp;
465#endif
466	register u_int prefixes;
467	register int bytelen;
468	register u_int length, lsa_length;
469	uint32_t flags32;
470	const uint8_t *tptr;
471
472	if (ospf6_print_lshdr(ndo, &lsap->ls_hdr, dataend))
473		return (1);
474	ND_TCHECK(lsap->ls_hdr.ls_length);
475        length = EXTRACT_16BITS(&lsap->ls_hdr.ls_length);
476
477	/*
478	 * The LSA length includes the length of the header;
479	 * it must have a value that's at least that length.
480	 * If it does, find the length of what follows the
481	 * header.
482	 */
483        if (length < sizeof(struct lsa6_hdr) || (const u_char *)lsap + length > dataend)
484        	return (1);
485        lsa_length = length - sizeof(struct lsa6_hdr);
486        tptr = (const uint8_t *)lsap+sizeof(struct lsa6_hdr);
487
488	switch (EXTRACT_16BITS(&lsap->ls_hdr.ls_type)) {
489	case LS_TYPE_ROUTER | LS_SCOPE_AREA:
490		if (lsa_length < sizeof (lsap->lsa_un.un_rla.rla_options))
491			return (1);
492		lsa_length -= sizeof (lsap->lsa_un.un_rla.rla_options);
493		ND_TCHECK(lsap->lsa_un.un_rla.rla_options);
494		ND_PRINT((ndo, "\n\t      Options [%s]",
495		          bittok2str(ospf6_option_values, "none",
496		          EXTRACT_32BITS(&lsap->lsa_un.un_rla.rla_options))));
497		ND_PRINT((ndo, ", RLA-Flags [%s]",
498		          bittok2str(ospf6_rla_flag_values, "none",
499		          lsap->lsa_un.un_rla.rla_flags)));
500
501		rlp = lsap->lsa_un.un_rla.rla_link;
502		while (lsa_length != 0) {
503			if (lsa_length < sizeof (*rlp))
504				return (1);
505			lsa_length -= sizeof (*rlp);
506			ND_TCHECK(*rlp);
507			switch (rlp->link_type) {
508
509			case RLA_TYPE_VIRTUAL:
510				ND_PRINT((ndo, "\n\t      Virtual Link: Neighbor Router-ID %s"
511                                       "\n\t      Neighbor Interface-ID %s, Interface %s",
512                                       ipaddr_string(ndo, &rlp->link_nrtid),
513                                       ipaddr_string(ndo, &rlp->link_nifid),
514                                       ipaddr_string(ndo, &rlp->link_ifid)));
515                                break;
516
517			case RLA_TYPE_ROUTER:
518				ND_PRINT((ndo, "\n\t      Neighbor Router-ID %s"
519                                       "\n\t      Neighbor Interface-ID %s, Interface %s",
520                                       ipaddr_string(ndo, &rlp->link_nrtid),
521                                       ipaddr_string(ndo, &rlp->link_nifid),
522                                       ipaddr_string(ndo, &rlp->link_ifid)));
523				break;
524
525			case RLA_TYPE_TRANSIT:
526				ND_PRINT((ndo, "\n\t      Neighbor Network-ID %s"
527                                       "\n\t      Neighbor Interface-ID %s, Interface %s",
528				    ipaddr_string(ndo, &rlp->link_nrtid),
529				    ipaddr_string(ndo, &rlp->link_nifid),
530				    ipaddr_string(ndo, &rlp->link_ifid)));
531				break;
532
533			default:
534				ND_PRINT((ndo, "\n\t      Unknown Router Links Type 0x%02x",
535				    rlp->link_type));
536				return (0);
537			}
538			ND_PRINT((ndo, ", metric %d", EXTRACT_16BITS(&rlp->link_metric)));
539			rlp++;
540		}
541		break;
542
543	case LS_TYPE_NETWORK | LS_SCOPE_AREA:
544		if (lsa_length < sizeof (lsap->lsa_un.un_nla.nla_options))
545			return (1);
546		lsa_length -= sizeof (lsap->lsa_un.un_nla.nla_options);
547		ND_TCHECK(lsap->lsa_un.un_nla.nla_options);
548		ND_PRINT((ndo, "\n\t      Options [%s]",
549		          bittok2str(ospf6_option_values, "none",
550		          EXTRACT_32BITS(&lsap->lsa_un.un_nla.nla_options))));
551
552		ND_PRINT((ndo, "\n\t      Connected Routers:"));
553		ap = lsap->lsa_un.un_nla.nla_router;
554		while (lsa_length != 0) {
555			if (lsa_length < sizeof (*ap))
556				return (1);
557			lsa_length -= sizeof (*ap);
558			ND_TCHECK(*ap);
559			ND_PRINT((ndo, "\n\t\t%s", ipaddr_string(ndo, ap)));
560			++ap;
561		}
562		break;
563
564	case LS_TYPE_INTER_AP | LS_SCOPE_AREA:
565		if (lsa_length < sizeof (lsap->lsa_un.un_inter_ap.inter_ap_metric))
566			return (1);
567		lsa_length -= sizeof (lsap->lsa_un.un_inter_ap.inter_ap_metric);
568		ND_TCHECK(lsap->lsa_un.un_inter_ap.inter_ap_metric);
569		ND_PRINT((ndo, ", metric %u",
570			EXTRACT_32BITS(&lsap->lsa_un.un_inter_ap.inter_ap_metric) & SLA_MASK_METRIC));
571
572		tptr = (const uint8_t *)lsap->lsa_un.un_inter_ap.inter_ap_prefix;
573		while (lsa_length != 0) {
574			bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length);
575			if (bytelen < 0)
576				goto trunc;
577			lsa_length -= bytelen;
578			tptr += bytelen;
579		}
580		break;
581
582	case LS_TYPE_ASE | LS_SCOPE_AS:
583		if (lsa_length < sizeof (lsap->lsa_un.un_asla.asla_metric))
584			return (1);
585		lsa_length -= sizeof (lsap->lsa_un.un_asla.asla_metric);
586		ND_TCHECK(lsap->lsa_un.un_asla.asla_metric);
587		flags32 = EXTRACT_32BITS(&lsap->lsa_un.un_asla.asla_metric);
588		ND_PRINT((ndo, "\n\t     Flags [%s]",
589		          bittok2str(ospf6_asla_flag_values, "none", flags32)));
590		ND_PRINT((ndo, " metric %u",
591		       EXTRACT_32BITS(&lsap->lsa_un.un_asla.asla_metric) &
592		       ASLA_MASK_METRIC));
593
594		tptr = (const uint8_t *)lsap->lsa_un.un_asla.asla_prefix;
595		lsapp = (const struct lsa6_prefix *)tptr;
596		bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length);
597		if (bytelen < 0)
598			goto trunc;
599		lsa_length -= bytelen;
600		tptr += bytelen;
601
602		if ((flags32 & ASLA_FLAG_FWDADDR) != 0) {
603			const struct in6_addr *fwdaddr6;
604
605			fwdaddr6 = (const struct in6_addr *)tptr;
606			if (lsa_length < sizeof (*fwdaddr6))
607				return (1);
608			lsa_length -= sizeof (*fwdaddr6);
609			ND_TCHECK(*fwdaddr6);
610			ND_PRINT((ndo, " forward %s",
611			       ip6addr_string(ndo, fwdaddr6)));
612			tptr += sizeof(*fwdaddr6);
613		}
614
615		if ((flags32 & ASLA_FLAG_ROUTETAG) != 0) {
616			if (lsa_length < sizeof (uint32_t))
617				return (1);
618			lsa_length -= sizeof (uint32_t);
619			ND_TCHECK(*(const uint32_t *)tptr);
620			ND_PRINT((ndo, " tag %s",
621			       ipaddr_string(ndo, (const uint32_t *)tptr)));
622			tptr += sizeof(uint32_t);
623		}
624
625		if (lsapp->lsa_p_metric) {
626			if (lsa_length < sizeof (uint32_t))
627				return (1);
628			lsa_length -= sizeof (uint32_t);
629			ND_TCHECK(*(const uint32_t *)tptr);
630			ND_PRINT((ndo, " RefLSID: %s",
631			       ipaddr_string(ndo, (const uint32_t *)tptr)));
632			tptr += sizeof(uint32_t);
633		}
634		break;
635
636	case LS_TYPE_LINK:
637		/* Link LSA */
638		llsap = &lsap->lsa_un.un_llsa;
639		if (lsa_length < sizeof (llsap->llsa_priandopt))
640			return (1);
641		lsa_length -= sizeof (llsap->llsa_priandopt);
642		ND_TCHECK(llsap->llsa_priandopt);
643		ND_PRINT((ndo, "\n\t      Options [%s]",
644		          bittok2str(ospf6_option_values, "none",
645		          EXTRACT_32BITS(&llsap->llsa_options))));
646
647		if (lsa_length < sizeof (llsap->llsa_lladdr) + sizeof (llsap->llsa_nprefix))
648			return (1);
649		lsa_length -= sizeof (llsap->llsa_lladdr) + sizeof (llsap->llsa_nprefix);
650                ND_TCHECK(llsap->llsa_nprefix);
651                prefixes = EXTRACT_32BITS(&llsap->llsa_nprefix);
652		ND_PRINT((ndo, "\n\t      Priority %d, Link-local address %s, Prefixes %d:",
653                       llsap->llsa_priority,
654                       ip6addr_string(ndo, &llsap->llsa_lladdr),
655                       prefixes));
656
657		tptr = (const uint8_t *)llsap->llsa_prefix;
658		while (prefixes > 0) {
659			bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length);
660			if (bytelen < 0)
661				goto trunc;
662			prefixes--;
663			lsa_length -= bytelen;
664			tptr += bytelen;
665		}
666		break;
667
668	case LS_TYPE_INTRA_AP | LS_SCOPE_AREA:
669		/* Intra-Area-Prefix LSA */
670		if (lsa_length < sizeof (lsap->lsa_un.un_intra_ap.intra_ap_rtid))
671			return (1);
672		lsa_length -= sizeof (lsap->lsa_un.un_intra_ap.intra_ap_rtid);
673		ND_TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_rtid);
674		ospf6_print_ls_type(ndo,
675			EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_lstype),
676			&lsap->lsa_un.un_intra_ap.intra_ap_lsid);
677
678		if (lsa_length < sizeof (lsap->lsa_un.un_intra_ap.intra_ap_nprefix))
679			return (1);
680		lsa_length -= sizeof (lsap->lsa_un.un_intra_ap.intra_ap_nprefix);
681		ND_TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_nprefix);
682                prefixes = EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_nprefix);
683		ND_PRINT((ndo, "\n\t      Prefixes %d:", prefixes));
684
685		tptr = (const uint8_t *)lsap->lsa_un.un_intra_ap.intra_ap_prefix;
686		while (prefixes > 0) {
687			bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length);
688			if (bytelen < 0)
689				goto trunc;
690			prefixes--;
691			lsa_length -= bytelen;
692			tptr += bytelen;
693		}
694		break;
695
696        case LS_TYPE_GRACE | LS_SCOPE_LINKLOCAL:
697                if (ospf_print_grace_lsa(ndo, tptr, lsa_length) == -1) {
698                    return 1;
699                }
700                break;
701
702        case LS_TYPE_INTRA_ATE | LS_SCOPE_LINKLOCAL:
703                if (ospf_print_te_lsa(ndo, tptr, lsa_length) == -1) {
704                    return 1;
705                }
706                break;
707
708	default:
709                if(!print_unknown_data(ndo,tptr,
710                                       "\n\t      ",
711                                       lsa_length)) {
712                    return (1);
713                }
714                break;
715	}
716
717	return (0);
718trunc:
719	return (1);
720}
721
722static int
723ospf6_decode_v3(netdissect_options *ndo,
724                register const struct ospf6hdr *op,
725                register const u_char *dataend)
726{
727	register const rtrid_t *ap;
728	register const struct lsr6 *lsrp;
729	register const struct lsa6_hdr *lshp;
730	register const struct lsa6 *lsap;
731	register int i;
732
733	switch (op->ospf6_type) {
734
735	case OSPF_TYPE_HELLO: {
736		register const struct hello6 *hellop = (const struct hello6 *)((const uint8_t *)op + OSPF6HDR_LEN);
737
738		ND_TCHECK_32BITS(&hellop->hello_options);
739		ND_PRINT((ndo, "\n\tOptions [%s]",
740		          bittok2str(ospf6_option_values, "none",
741		          EXTRACT_32BITS(&hellop->hello_options))));
742
743		ND_TCHECK(hellop->hello_deadint);
744		ND_PRINT((ndo, "\n\t  Hello Timer %us, Dead Timer %us, Interface-ID %s, Priority %u",
745		          EXTRACT_16BITS(&hellop->hello_helloint),
746		          EXTRACT_16BITS(&hellop->hello_deadint),
747		          ipaddr_string(ndo, &hellop->hello_ifid),
748		          hellop->hello_priority));
749
750		ND_TCHECK(hellop->hello_dr);
751		if (EXTRACT_32BITS(&hellop->hello_dr) != 0)
752			ND_PRINT((ndo, "\n\t  Designated Router %s",
753			    ipaddr_string(ndo, &hellop->hello_dr)));
754		ND_TCHECK(hellop->hello_bdr);
755		if (EXTRACT_32BITS(&hellop->hello_bdr) != 0)
756			ND_PRINT((ndo, ", Backup Designated Router %s",
757			    ipaddr_string(ndo, &hellop->hello_bdr)));
758		if (ndo->ndo_vflag > 1) {
759			ND_PRINT((ndo, "\n\t  Neighbor List:"));
760			ap = hellop->hello_neighbor;
761			while ((const u_char *)ap < dataend) {
762				ND_TCHECK(*ap);
763				ND_PRINT((ndo, "\n\t    %s", ipaddr_string(ndo, ap)));
764				++ap;
765			}
766		}
767		break;	/* HELLO */
768	}
769
770	case OSPF_TYPE_DD: {
771		register const struct dd6 *ddp = (const struct dd6 *)((const uint8_t *)op + OSPF6HDR_LEN);
772
773		ND_TCHECK(ddp->db_options);
774		ND_PRINT((ndo, "\n\tOptions [%s]",
775		          bittok2str(ospf6_option_values, "none",
776		          EXTRACT_32BITS(&ddp->db_options))));
777		ND_TCHECK(ddp->db_flags);
778		ND_PRINT((ndo, ", DD Flags [%s]",
779		          bittok2str(ospf6_dd_flag_values,"none",ddp->db_flags)));
780
781		ND_TCHECK(ddp->db_seq);
782		ND_PRINT((ndo, ", MTU %u, DD-Sequence 0x%08x",
783                       EXTRACT_16BITS(&ddp->db_mtu),
784                       EXTRACT_32BITS(&ddp->db_seq)));
785		if (ndo->ndo_vflag > 1) {
786			/* Print all the LS adv's */
787			lshp = ddp->db_lshdr;
788			while ((const u_char *)lshp < dataend) {
789				if (ospf6_print_lshdr(ndo, lshp++, dataend))
790					goto trunc;
791			}
792		}
793		break;
794	}
795
796	case OSPF_TYPE_LS_REQ:
797		if (ndo->ndo_vflag > 1) {
798			lsrp = (const struct lsr6 *)((const uint8_t *)op + OSPF6HDR_LEN);
799			while ((const u_char *)lsrp < dataend) {
800				ND_TCHECK(*lsrp);
801				ND_PRINT((ndo, "\n\t  Advertising Router %s",
802				          ipaddr_string(ndo, &lsrp->ls_router)));
803				ospf6_print_ls_type(ndo, EXTRACT_16BITS(&lsrp->ls_type),
804                                                    &lsrp->ls_stateid);
805				++lsrp;
806			}
807		}
808		break;
809
810	case OSPF_TYPE_LS_UPDATE:
811		if (ndo->ndo_vflag > 1) {
812			register const struct lsu6 *lsup = (const struct lsu6 *)((const uint8_t *)op + OSPF6HDR_LEN);
813
814			ND_TCHECK(lsup->lsu_count);
815			i = EXTRACT_32BITS(&lsup->lsu_count);
816			lsap = lsup->lsu_lsa;
817			while ((const u_char *)lsap < dataend && i--) {
818				if (ospf6_print_lsa(ndo, lsap, dataend))
819					goto trunc;
820				lsap = (const struct lsa6 *)((const u_char *)lsap +
821				    EXTRACT_16BITS(&lsap->ls_hdr.ls_length));
822			}
823		}
824		break;
825
826	case OSPF_TYPE_LS_ACK:
827		if (ndo->ndo_vflag > 1) {
828			lshp = (const struct lsa6_hdr *)((const uint8_t *)op + OSPF6HDR_LEN);
829			while ((const u_char *)lshp < dataend) {
830				if (ospf6_print_lshdr(ndo, lshp++, dataend))
831					goto trunc;
832			}
833		}
834		break;
835
836	default:
837		break;
838	}
839	return (0);
840trunc:
841	return (1);
842}
843
844/* RFC5613 Section 2.2 (w/o the TLVs) */
845static int
846ospf6_print_lls(netdissect_options *ndo,
847                const u_char *cp, const u_int len)
848{
849	uint16_t llsdatalen;
850
851	if (len == 0)
852		return 0;
853	if (len < OSPF_LLS_HDRLEN)
854		goto trunc;
855	/* Checksum */
856	ND_TCHECK2(*cp, 2);
857	ND_PRINT((ndo, "\n\tLLS Checksum 0x%04x", EXTRACT_16BITS(cp)));
858	cp += 2;
859	/* LLS Data Length */
860	ND_TCHECK2(*cp, 2);
861	llsdatalen = EXTRACT_16BITS(cp);
862	ND_PRINT((ndo, ", Data Length %u", llsdatalen));
863	if (llsdatalen < OSPF_LLS_HDRLEN || llsdatalen > len)
864		goto trunc;
865	cp += 2;
866	/* LLS TLVs */
867	ND_TCHECK2(*cp, llsdatalen - OSPF_LLS_HDRLEN);
868	/* FIXME: code in print-ospf.c can be reused to decode the TLVs */
869
870	return llsdatalen;
871trunc:
872	return -1;
873}
874
875/* RFC6506 Section 4.1 */
876static int
877ospf6_decode_at(netdissect_options *ndo,
878                const u_char *cp, const u_int len)
879{
880	uint16_t authdatalen;
881
882	if (len == 0)
883		return 0;
884	if (len < OSPF6_AT_HDRLEN)
885		goto trunc;
886	/* Authentication Type */
887	ND_TCHECK2(*cp, 2);
888	ND_PRINT((ndo, "\n\tAuthentication Type %s", tok2str(ospf6_auth_type_str, "unknown (0x%04x)", EXTRACT_16BITS(cp))));
889	cp += 2;
890	/* Auth Data Len */
891	ND_TCHECK2(*cp, 2);
892	authdatalen = EXTRACT_16BITS(cp);
893	ND_PRINT((ndo, ", Length %u", authdatalen));
894	if (authdatalen < OSPF6_AT_HDRLEN || authdatalen > len)
895		goto trunc;
896	cp += 2;
897	/* Reserved */
898	ND_TCHECK2(*cp, 2);
899	cp += 2;
900	/* Security Association ID */
901	ND_TCHECK2(*cp, 2);
902	ND_PRINT((ndo, ", SAID %u", EXTRACT_16BITS(cp)));
903	cp += 2;
904	/* Cryptographic Sequence Number (High-Order 32 Bits) */
905	ND_TCHECK2(*cp, 4);
906	ND_PRINT((ndo, ", CSN 0x%08x", EXTRACT_32BITS(cp)));
907	cp += 4;
908	/* Cryptographic Sequence Number (Low-Order 32 Bits) */
909	ND_TCHECK2(*cp, 4);
910	ND_PRINT((ndo, ":%08x", EXTRACT_32BITS(cp)));
911	cp += 4;
912	/* Authentication Data */
913	ND_TCHECK2(*cp, authdatalen - OSPF6_AT_HDRLEN);
914	if (ndo->ndo_vflag > 1)
915		print_unknown_data(ndo,cp, "\n\tAuthentication Data ", authdatalen - OSPF6_AT_HDRLEN);
916	return 0;
917
918trunc:
919	return 1;
920}
921
922/* The trailing data may include LLS and/or AT data (in this specific order).
923 * LLS data may be present only in Hello and DBDesc packets with the L-bit set.
924 * AT data may be present in Hello and DBDesc packets with the AT-bit set or in
925 * any other packet type, thus decode the AT data regardless of the AT-bit.
926 */
927static int
928ospf6_decode_v3_trailer(netdissect_options *ndo,
929                        const struct ospf6hdr *op, const u_char *cp, const unsigned len)
930{
931	int llslen = 0;
932	int lls_hello = 0;
933	int lls_dd = 0;
934
935	if (op->ospf6_type == OSPF_TYPE_HELLO) {
936		const struct hello6 *hellop = (const struct hello6 *)((const uint8_t *)op + OSPF6HDR_LEN);
937		ND_TCHECK(hellop->hello_options);
938		if (EXTRACT_32BITS(&hellop->hello_options) & OSPF6_OPTION_L)
939			lls_hello = 1;
940	} else if (op->ospf6_type == OSPF_TYPE_DD) {
941		const struct dd6 *ddp = (const struct dd6 *)((const uint8_t *)op + OSPF6HDR_LEN);
942		ND_TCHECK(ddp->db_options);
943		if (EXTRACT_32BITS(&ddp->db_options) & OSPF6_OPTION_L)
944			lls_dd = 1;
945	}
946	if ((lls_hello || lls_dd) && (llslen = ospf6_print_lls(ndo, cp, len)) < 0)
947		goto trunc;
948	return ospf6_decode_at(ndo, cp + llslen, len - llslen);
949
950trunc:
951	return 1;
952}
953
954void
955ospf6_print(netdissect_options *ndo,
956            register const u_char *bp, register u_int length)
957{
958	register const struct ospf6hdr *op;
959	register const u_char *dataend;
960	register const char *cp;
961	uint16_t datalen;
962
963	op = (const struct ospf6hdr *)bp;
964
965	/* If the type is valid translate it, or just print the type */
966	/* value.  If it's not valid, say so and return */
967	ND_TCHECK(op->ospf6_type);
968	cp = tok2str(ospf6_type_values, "unknown packet type (%u)", op->ospf6_type);
969	ND_PRINT((ndo, "OSPFv%u, %s, length %d", op->ospf6_version, cp, length));
970	if (*cp == 'u') {
971		return;
972	}
973
974	if(!ndo->ndo_vflag) { /* non verbose - so lets bail out here */
975		return;
976	}
977
978	/* OSPFv3 data always comes first and optional trailing data may follow. */
979	ND_TCHECK(op->ospf6_len);
980	datalen = EXTRACT_16BITS(&op->ospf6_len);
981	if (datalen > length) {
982		ND_PRINT((ndo, " [len %d]", datalen));
983		return;
984	}
985	dataend = bp + datalen;
986
987	ND_TCHECK(op->ospf6_routerid);
988	ND_PRINT((ndo, "\n\tRouter-ID %s", ipaddr_string(ndo, &op->ospf6_routerid)));
989
990	ND_TCHECK(op->ospf6_areaid);
991	if (EXTRACT_32BITS(&op->ospf6_areaid) != 0)
992		ND_PRINT((ndo, ", Area %s", ipaddr_string(ndo, &op->ospf6_areaid)));
993	else
994		ND_PRINT((ndo, ", Backbone Area"));
995	ND_TCHECK(op->ospf6_instanceid);
996	if (op->ospf6_instanceid)
997		ND_PRINT((ndo, ", Instance %u", op->ospf6_instanceid));
998
999	/* Do rest according to version.	 */
1000	switch (op->ospf6_version) {
1001
1002	case 3:
1003		/* ospf version 3 */
1004		if (ospf6_decode_v3(ndo, op, dataend) ||
1005		    ospf6_decode_v3_trailer(ndo, op, dataend, length - datalen))
1006			goto trunc;
1007		break;
1008	}			/* end switch on version */
1009
1010	return;
1011trunc:
1012	ND_PRINT((ndo, "%s", tstr));
1013}
1014