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