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