xref: /openbsd/usr.sbin/tcpdump/print-ospf6.c (revision f96bb33f)
1 /*	$OpenBSD: print-ospf6.c,v 1.11 2020/01/24 22:46:37 procter Exp $	*/
2 
3 
4 /*
5  * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that: (1) source code distributions
10  * retain the above copyright notice and this paragraph in its entirety, (2)
11  * distributions including binary code include the above copyright notice and
12  * this paragraph in its entirety in the documentation or other materials
13  * provided with the distribution, and (3) all advertising materials mentioning
14  * features or use of this software display the following acknowledgement:
15  * ``This product includes software developed by the University of California,
16  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
17  * the University nor the names of its contributors may be used to endorse
18  * or promote products derived from this software without specific prior
19  * written permission.
20  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
21  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
22  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23  *
24  * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu)
25  */
26 
27 #include <sys/time.h>
28 #include <sys/socket.h>
29 
30 #include <netinet/in.h>
31 #include <netinet/ip.h>
32 #include <netinet/ip_var.h>
33 
34 #include <ctype.h>
35 #include <stdio.h>
36 #include <string.h>
37 
38 #include "interface.h"
39 #include "addrtoname.h"
40 
41 #include "ospf6.h"
42 
43 struct bits {
44 	u_int32_t bit;
45 	const char *str;
46 };
47 
48 static const struct bits ospf6_option_bits[] = {
49 	{ OSPF6_OPTION_V6,	"V6" },
50 	{ OSPF6_OPTION_E,	"E" },
51 	{ OSPF6_OPTION_MC,	"MC" },
52 	{ OSPF6_OPTION_N,	"N" },
53 	{ OSPF6_OPTION_R,	"R" },
54 	{ OSPF6_OPTION_DC,	"DC" },
55 	{ 0,			NULL }
56 };
57 
58 static const struct bits ospf6_rla_flag_bits[] = {
59 	{ RLA_FLAG_B,		"B" },
60 	{ RLA_FLAG_E,		"E" },
61 	{ RLA_FLAG_V,		"V" },
62 	{ RLA_FLAG_W,		"W" },
63 	{ 0,			NULL }
64 };
65 
66 static struct tok type2str[] = {
67 	{ OSPF_TYPE_UMD,	"umd" },
68 	{ OSPF_TYPE_HELLO,	"hello" },
69 	{ OSPF_TYPE_DB,		"dd" },
70 	{ OSPF_TYPE_LSR,	"ls_req" },
71 	{ OSPF_TYPE_LSU,	"ls_upd" },
72 	{ OSPF_TYPE_LSA,	"ls_ack" },
73 	{ 0,			NULL }
74 };
75 
76 static char tstr[] = " [|ospf]";
77 
78 /* Forwards */
79 static inline void ospf6_print_seqage(u_int32_t, time_t);
80 static inline void ospf6_print_bits(const struct bits *, u_char);
81 static void ospf6_print_ls_type(u_int, const rtrid_t *,
82     const rtrid_t *, const char *);
83 static int ospf6_print_lshdr(const struct lsa_hdr *);
84 static int ospf6_print_lsa(const struct lsa *);
85 static int ospf6_decode_v3(const struct ospf6hdr *, const u_char *);
86 
87 static inline void
ospf6_print_seqage(u_int32_t seq,time_t us)88 ospf6_print_seqage(u_int32_t seq, time_t us)
89 {
90 	time_t sec = us % 60;
91 	time_t mins = (us / 60) % 60;
92 	time_t hour = us / 3600;
93 
94 	printf(" S %X age ", seq);
95 	if (hour)
96 		printf("%u:%02u:%02u",
97 		    (u_int32_t) hour, (u_int32_t) mins, (u_int32_t) sec);
98 	else if (mins)
99 		printf("%u:%02u", (u_int32_t) mins, (u_int32_t) sec);
100 	else
101 		printf("%u", (u_int32_t) sec);
102 }
103 
104 
105 static inline void
ospf6_print_bits(const struct bits * bp,u_char options)106 ospf6_print_bits(const struct bits *bp, u_char options)
107 {
108 	char sep = ' ';
109 
110 	do {
111 		if (options & bp->bit) {
112 			printf("%c%s", sep, bp->str);
113 			sep = '/';
114 		}
115 	} while ((++bp)->bit);
116 }
117 
118 static void
ospf6_print_ls_type(u_int ls_type,const rtrid_t * ls_stateid,const rtrid_t * ls_router,const char * fmt)119 ospf6_print_ls_type(u_int ls_type, const rtrid_t *ls_stateid,
120     const rtrid_t *ls_router, const char *fmt)
121 {
122 	char *scope;
123 
124 	switch (ls_type & LS_SCOPE_MASK) {
125 	case LS_SCOPE_LINKLOCAL:
126 		scope = "linklocal-";
127 		break;
128 	case LS_SCOPE_AREA:
129 		scope = "area-";
130 		break;
131 	case LS_SCOPE_AS:
132 		scope = "AS-";
133 		break;
134 	default:
135 		scope = "";
136 		break;
137 	}
138 
139 	switch (ls_type & LS_TYPE_MASK) {
140 	case LS_TYPE_ROUTER:
141 		printf(" %srtr %s", scope, ipaddr_string(ls_router));
142 		break;
143 
144 	case LS_TYPE_NETWORK:
145 		printf(" %snet dr %s if %s", scope,
146 		    ipaddr_string(ls_router),
147 		    ipaddr_string(ls_stateid));
148 		break;
149 
150 	case LS_TYPE_INTER_AP:
151 		printf(" %sinter-area-prefix %s abr %s", scope,
152 		    ipaddr_string(ls_stateid),
153 		    ipaddr_string(ls_router));
154 		break;
155 
156 	case LS_TYPE_INTER_AR:
157 		printf(" %sinter-area-router %s rtr %s", scope,
158 		    ipaddr_string(ls_router),
159 		    ipaddr_string(ls_stateid));
160 		break;
161 
162 	case LS_TYPE_ASE:
163 		printf(" %sase %s asbr %s", scope,
164 		    ipaddr_string(ls_stateid),
165 		    ipaddr_string(ls_router));
166 		break;
167 
168 	case LS_TYPE_GROUP:
169 		printf(" %sgroup %s rtr %s", scope,
170 		    ipaddr_string(ls_stateid),
171 		    ipaddr_string(ls_router));
172 		break;
173 
174 	case LS_TYPE_TYPE7:
175 		printf(" %stype7 %s rtr %s", scope,
176 		    ipaddr_string(ls_stateid),
177 		    ipaddr_string(ls_router));
178 		break;
179 
180 	case LS_TYPE_LINK:
181 		printf(" %slink %s rtr %s", scope,
182 		    ipaddr_string(ls_stateid),
183 		    ipaddr_string(ls_router));
184 		break;
185 
186 	case LS_TYPE_INTRA_AP:
187 		printf(" %sintra-area-prefix %s rtr %s", scope,
188 		    ipaddr_string(ls_stateid),
189 		    ipaddr_string(ls_router));
190 		break;
191 
192 	default:
193 		printf(" %s", scope);
194 		printf(fmt, ls_type);
195 		break;
196 	}
197 
198 }
199 
200 static int
ospf6_print_lshdr(const struct lsa_hdr * lshp)201 ospf6_print_lshdr(const struct lsa_hdr *lshp)
202 {
203 
204 	TCHECK(lshp->ls_type);
205 	printf(" {");						/* } (ctags) */
206 
207 	TCHECK(lshp->ls_seq);
208 	ospf6_print_seqage(ntohl(lshp->ls_seq), ntohs(lshp->ls_age));
209 	ospf6_print_ls_type(ntohs(lshp->ls_type), &lshp->ls_stateid,
210 		&lshp->ls_router, "ls_type %d");
211 
212 	return (0);
213 trunc:
214 	return (1);
215 }
216 
217 static int
ospf6_print_lsaprefix(const struct lsa_prefix * lsapp)218 ospf6_print_lsaprefix(const struct lsa_prefix *lsapp)
219 {
220 	int k;
221 	struct in6_addr prefix;
222 
223 	TCHECK(*lsapp);
224 	k = (lsapp->lsa_p_len + 31) / 32;
225 	if (k * 4 > sizeof(struct in6_addr)) {
226 		printf("??prefixlen %d??", lsapp->lsa_p_len);
227 		goto trunc;
228 	}
229 	memset(&prefix, 0, sizeof(prefix));
230 	memcpy(&prefix, lsapp->lsa_p_prefix, k * 4);
231 	printf(" %s/%d", ip6addr_string(&prefix),
232 		lsapp->lsa_p_len);
233 	if (lsapp->lsa_p_opt)
234 		printf("(opt=%x)", lsapp->lsa_p_opt);
235 	return sizeof(*lsapp) - 4 + k * 4;
236 
237 trunc:
238 	return -1;
239 }
240 
241 
242 /*
243  * Print a single link state advertisement.  If truncated return 1, else 0.
244  */
245 static int
ospf6_print_lsa(const struct lsa * lsap)246 ospf6_print_lsa(const struct lsa *lsap)
247 {
248 	const u_char *ls_end;
249 	const struct rlalink *rlp;
250 #if 0
251 	const struct tos_metric *tosp;
252 #endif
253 	const rtrid_t *ap;
254 #if 0
255 	const struct aslametric *almp;
256 	const struct mcla *mcp;
257 #endif
258 	const struct llsa *llsap;
259 	const struct lsa_prefix *lsapp;
260 #if 0
261 	const u_int32_t *lp;
262 #endif
263 	int j, k;
264 
265 	if (ospf6_print_lshdr(&lsap->ls_hdr))
266 		return (1);
267 	TCHECK(lsap->ls_hdr.ls_length);
268 	ls_end = (u_char *)lsap + ntohs(lsap->ls_hdr.ls_length);
269 	switch (ntohs(lsap->ls_hdr.ls_type)) {
270 	case LS_TYPE_ROUTER | LS_SCOPE_AREA:
271 		TCHECK(lsap->lsa_un.un_rla.rla_flags);
272 		ospf6_print_bits(ospf6_rla_flag_bits,
273 			lsap->lsa_un.un_rla.rla_flags);
274 		TCHECK(lsap->lsa_un.un_rla.rla_options);
275 		ospf6_print_bits(ospf6_option_bits,
276 			ntohl(lsap->lsa_un.un_rla.rla_options));
277 
278 		TCHECK(lsap->lsa_un.un_rla.rla_link);
279 		rlp = lsap->lsa_un.un_rla.rla_link;
280 		while (rlp + sizeof(*rlp) <= (struct rlalink *)ls_end) {
281 			TCHECK(*rlp);
282 			printf(" {");				/* } (ctags) */
283 			switch (rlp->link_type) {
284 
285 			case RLA_TYPE_VIRTUAL:
286 				printf(" virt");
287 				/* FALLTHROUGH */
288 
289 			case RLA_TYPE_ROUTER:
290 				printf(" nbrid %s nbrif %s if %s",
291 				    ipaddr_string(&rlp->link_nrtid),
292 				    ipaddr_string(&rlp->link_nifid),
293 				    ipaddr_string(&rlp->link_ifid));
294 				break;
295 
296 			case RLA_TYPE_TRANSIT:
297 				printf(" dr %s drif %s if %s",
298 				    ipaddr_string(&rlp->link_nrtid),
299 				    ipaddr_string(&rlp->link_nifid),
300 				    ipaddr_string(&rlp->link_ifid));
301 				break;
302 
303 			default:
304 								/* { (ctags) */
305 				printf(" ??RouterLinksType 0x%02x?? }",
306 				    rlp->link_type);
307 				return (0);
308 			}
309 			printf(" metric %d", ntohs(rlp->link_metric));
310 								/* { (ctags) */
311 			printf(" }");
312 			rlp++;
313 		}
314 		break;
315 
316 	case LS_TYPE_NETWORK | LS_SCOPE_AREA:
317 		TCHECK(lsap->lsa_un.un_nla.nla_options);
318 		ospf6_print_bits(ospf6_option_bits,
319 			ntohl(lsap->lsa_un.un_nla.nla_options));
320 		printf(" rtrs");
321 		ap = lsap->lsa_un.un_nla.nla_router;
322 		while ((u_char *)ap < ls_end) {
323 			TCHECK(*ap);
324 			printf(" %s", ipaddr_string(ap));
325 			++ap;
326 		}
327 		break;
328 
329 	case LS_TYPE_INTER_AP | LS_SCOPE_AREA:
330 		TCHECK(lsap->lsa_un.un_inter_ap.inter_ap_metric);
331 		printf(" metric %u",
332 			(u_int32_t)ntohl(lsap->lsa_un.un_inter_ap.inter_ap_metric) & SLA_MASK_METRIC);
333 		lsapp = lsap->lsa_un.un_inter_ap.inter_ap_prefix;
334 		while (lsapp + sizeof(lsapp) <= (struct lsa_prefix *)ls_end) {
335 			k = ospf6_print_lsaprefix(lsapp);
336 			if (k < 0)
337 				goto trunc;
338 			lsapp = (struct lsa_prefix *)(((u_char *)lsapp) + k);
339 		}
340 		break;
341 
342 #if 0
343 	case LS_TYPE_SUM_ABR:
344 		TCHECK(lsap->lsa_un.un_sla.sla_tosmetric);
345 		lp = lsap->lsa_un.un_sla.sla_tosmetric;
346 		while ((u_char *)lp < ls_end) {
347 			u_int32_t ul;
348 
349 			TCHECK(*lp);
350 			ul = ntohl(*lp);
351 			printf(" tos %d metric %d",
352 			    (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS,
353 			    ul & SLA_MASK_METRIC);
354 			++lp;
355 		}
356 		break;
357 
358 	case LS_TYPE_ASE:
359 		TCHECK(lsap->lsa_un.un_nla.nla_mask);
360 		printf(" mask %s",
361 		    ipaddr_string(&lsap->lsa_un.un_asla.asla_mask));
362 
363 		TCHECK(lsap->lsa_un.un_sla.sla_tosmetric);
364 		almp = lsap->lsa_un.un_asla.asla_metric;
365 		while ((u_char *)almp < ls_end) {
366 			u_int32_t ul;
367 
368 			TCHECK(almp->asla_tosmetric);
369 			ul = ntohl(almp->asla_tosmetric);
370 			printf(" type %d tos %d metric %d",
371 			    (ul & ASLA_FLAG_EXTERNAL) ? 2 : 1,
372 			    (ul & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS,
373 			    (ul & ASLA_MASK_METRIC));
374 			TCHECK(almp->asla_forward);
375 			if (almp->asla_forward.s_addr) {
376 				printf(" forward %s",
377 				    ipaddr_string(&almp->asla_forward));
378 			}
379 			TCHECK(almp->asla_tag);
380 			if (almp->asla_tag.s_addr) {
381 				printf(" tag %s",
382 				    ipaddr_string(&almp->asla_tag));
383 			}
384 			++almp;
385 		}
386 		break;
387 
388 	case LS_TYPE_GROUP:
389 		/* Multicast extensions as of 23 July 1991 */
390 		mcp = lsap->lsa_un.un_mcla;
391 		while ((u_char *)mcp < ls_end) {
392 			TCHECK(mcp->mcla_vid);
393 			switch (ntohl(mcp->mcla_vtype)) {
394 
395 			case MCLA_VERTEX_ROUTER:
396 				printf(" rtr rtrid %s",
397 				    ipaddr_string(&mcp->mcla_vid));
398 				break;
399 
400 			case MCLA_VERTEX_NETWORK:
401 				printf(" net dr %s",
402 				    ipaddr_string(&mcp->mcla_vid));
403 				break;
404 
405 			default:
406 				printf(" ??VertexType %u??",
407 				    (u_int32_t)ntohl(mcp->mcla_vtype));
408 				break;
409 			}
410 		++mcp;
411 		}
412 #endif
413 
414 	case LS_TYPE_LINK:
415 		/* Link LSA */
416 		llsap = &lsap->lsa_un.un_llsa;
417 		TCHECK(llsap->llsa_options);
418 		ospf6_print_bits(ospf6_option_bits, ntohl(llsap->llsa_options));
419 		TCHECK(llsap->llsa_nprefix);
420 		printf(" pri %d lladdr %s npref %d", llsap->llsa_priority,
421 			ip6addr_string(&llsap->llsa_lladdr),
422 			(u_int32_t)ntohl(llsap->llsa_nprefix));
423 		lsapp = llsap->llsa_prefix;
424 		for (j = 0; j < ntohl(llsap->llsa_nprefix); j++) {
425 			k = ospf6_print_lsaprefix(lsapp);
426 			if (k < 0)
427 				goto trunc;
428 			lsapp = (struct lsa_prefix *)(((u_char *)lsapp) + k);
429 		}
430 		break;
431 
432 	case LS_TYPE_INTRA_AP | LS_SCOPE_AREA:
433 		/* Intra-Area-Prefix LSA */
434 		TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_rtid);
435 		ospf6_print_ls_type(
436 			ntohs(lsap->lsa_un.un_intra_ap.intra_ap_lstype),
437 			&lsap->lsa_un.un_intra_ap.intra_ap_lsid,
438 			&lsap->lsa_un.un_intra_ap.intra_ap_rtid,
439 			"LinkStateType %d");
440 		TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_nprefix);
441 		printf(" npref %d",
442 			ntohs(lsap->lsa_un.un_intra_ap.intra_ap_nprefix));
443 
444 		lsapp = lsap->lsa_un.un_intra_ap.intra_ap_prefix;
445 		for (j = 0;
446 		     j < ntohs(lsap->lsa_un.un_intra_ap.intra_ap_nprefix);
447 		     j++) {
448 			k = ospf6_print_lsaprefix(lsapp);
449 			if (k < 0)
450 				goto trunc;
451 			lsapp = (struct lsa_prefix *)(((u_char *)lsapp) + k);
452 		}
453 		break;
454 
455 	default:
456 		printf(" ??LinkStateType 0x%04x??",
457 			ntohs(lsap->ls_hdr.ls_type));
458 	}
459 
460 								/* { (ctags) */
461 	printf(" }");
462 	return (0);
463 trunc:
464 	printf(" }");
465 	return (1);
466 }
467 
468 static int
ospf6_decode_v3(const struct ospf6hdr * op,const u_char * dataend)469 ospf6_decode_v3(const struct ospf6hdr *op, const u_char *dataend)
470 {
471 	const rtrid_t *ap;
472 	const struct lsr *lsrp;
473 	const struct lsa_hdr *lshp;
474 	const struct lsa *lsap;
475 	char sep;
476 	int i;
477 
478 	switch (op->ospf6_type) {
479 
480 	case OSPF_TYPE_UMD:
481 		/*
482 		 * Rob Coltun's special monitoring packets;
483 		 * do nothing
484 		 */
485 		break;
486 
487 	case OSPF_TYPE_HELLO:
488 		if (vflag) {
489 			TCHECK(op->ospf6_hello.hello_deadint);
490 			ospf6_print_bits(ospf6_option_bits,
491 			    ntohl(op->ospf6_hello.hello_options));
492 			printf(" ifid %s pri %d int %d dead %u",
493 			    ipaddr_string(&op->ospf6_hello.hello_ifid),
494 			    op->ospf6_hello.hello_priority,
495 			    ntohs(op->ospf6_hello.hello_helloint),
496 			    ntohs(op->ospf6_hello.hello_deadint));
497 		}
498 		TCHECK(op->ospf6_hello.hello_dr);
499 		if (op->ospf6_hello.hello_dr != 0)
500 			printf(" dr %s",
501 			    ipaddr_string(&op->ospf6_hello.hello_dr));
502 		TCHECK(op->ospf6_hello.hello_bdr);
503 		if (op->ospf6_hello.hello_bdr != 0)
504 			printf(" bdr %s",
505 			    ipaddr_string(&op->ospf6_hello.hello_bdr));
506 		if (vflag) {
507 			printf(" nbrs");
508 			ap = op->ospf6_hello.hello_neighbor;
509 			while ((u_char *)ap < dataend) {
510 				TCHECK(*ap);
511 				printf(" %s", ipaddr_string(ap));
512 				++ap;
513 			}
514 		}
515 		break;	/* HELLO */
516 
517 	case OSPF_TYPE_DB:
518 		TCHECK(op->ospf6_db.db_options);
519 		ospf6_print_bits(ospf6_option_bits,
520 			ntohl(op->ospf6_db.db_options));
521 		sep = ' ';
522 		TCHECK(op->ospf6_db.db_flags);
523 		if (op->ospf6_db.db_flags & OSPF6_DB_INIT) {
524 			printf("%cI", sep);
525 			sep = '/';
526 		}
527 		if (op->ospf6_db.db_flags & OSPF6_DB_MORE) {
528 			printf("%cM", sep);
529 			sep = '/';
530 		}
531 		if (op->ospf6_db.db_flags & OSPF6_DB_MASTER) {
532 			printf("%cMS", sep);
533 			sep = '/';
534 		}
535 		TCHECK(op->ospf6_db.db_seq);
536 		printf(" mtu %u S %X", ntohs(op->ospf6_db.db_mtu),
537 			(u_int32_t)ntohl(op->ospf6_db.db_seq));
538 
539 		if (vflag) {
540 			/* Print all the LS adv's */
541 			lshp = op->ospf6_db.db_lshdr;
542 
543 			while (!ospf6_print_lshdr(lshp)) {
544 							/* { (ctags) */
545 				printf(" }");
546 				++lshp;
547 			}
548 		}
549 		break;
550 
551 	case OSPF_TYPE_LSR:
552 		if (vflag) {
553 			lsrp = op->ospf6_lsr;
554 			while ((u_char *)lsrp < dataend) {
555 				TCHECK(*lsrp);
556 				printf(" {");		/* } (ctags) */
557 				ospf6_print_ls_type(ntohs(lsrp->ls_type),
558 				    &lsrp->ls_stateid,
559 				    &lsrp->ls_router,
560 				    "LinkStateType %d");
561 							/* { (ctags) */
562 				printf(" }");
563 				++lsrp;
564 			}
565 		}
566 		break;
567 
568 	case OSPF_TYPE_LSU:
569 		if (vflag) {
570 			lsap = op->ospf6_lsu.lsu_lsa;
571 			TCHECK(op->ospf6_lsu.lsu_count);
572 			i = ntohl(op->ospf6_lsu.lsu_count);
573 			while (i--) {
574 				if (ospf6_print_lsa(lsap))
575 					goto trunc;
576 				lsap = (struct lsa *)((u_char *)lsap +
577 				    ntohs(lsap->ls_hdr.ls_length));
578 			}
579 		}
580 		break;
581 
582 
583 	case OSPF_TYPE_LSA:
584 		if (vflag) {
585 			lshp = op->ospf6_lsa.lsa_lshdr;
586 
587 			while (!ospf6_print_lshdr(lshp)) {
588 							/* { (ctags) */
589 				printf(" }");
590 				++lshp;
591 			}
592 		}
593 		break;
594 
595 	default:
596 		printf("v3 type %d", op->ospf6_type);
597 		break;
598 	}
599 	return (0);
600 trunc:
601 	return (1);
602 }
603 
604 void
ospf6_print(const u_char * bp,u_int length)605 ospf6_print(const u_char *bp, u_int length)
606 {
607 	const struct ospf6hdr *op;
608 	const u_char *dataend;
609 	const char *cp;
610 
611 	op = (struct ospf6hdr *)bp;
612 
613 	/* If the type is valid translate it, or just print the type */
614 	/* value.  If it's not valid, say so and return */
615 	TCHECK(op->ospf6_type);
616 	cp = tok2str(type2str, "type%d", op->ospf6_type);
617 	printf(" OSPFv%d-%s %d:", op->ospf6_version, cp, length);
618 	if (*cp == 't')
619 		return;
620 
621 	TCHECK(op->ospf6_len);
622 	if (length != ntohs(op->ospf6_len)) {
623 		printf(" [len %d]", ntohs(op->ospf6_len));
624 		return;
625 	}
626 	dataend = bp + length;
627 
628 	TCHECK(op->ospf6_routerid);
629 	printf(" rtrid %s", ipaddr_string(&op->ospf6_routerid));
630 
631 	TCHECK(op->ospf6_areaid);
632 	if (op->ospf6_areaid != 0)
633 		printf(" area %s", ipaddr_string(&op->ospf6_areaid));
634 	else
635 		printf(" backbone");
636 	TCHECK(op->ospf6_instanceid);
637 	if (op->ospf6_instanceid)
638 		printf(" instance %u", op->ospf6_instanceid);
639 
640 	/* Do rest according to version.	 */
641 	switch (op->ospf6_version) {
642 
643 	case 3:
644 		/* ospf version 3 */
645 		if (ospf6_decode_v3(op, dataend))
646 			goto trunc;
647 		break;
648 
649 	default:
650 		printf(" ospf [version %d]", op->ospf6_version);
651 		break;
652 	}			/* end switch on version */
653 
654 	return;
655 trunc:
656 	printf("%s", tstr);
657 }
658