Fix markup. Fix backslashes to surive roff.
[netbsd-mini2440.git] / dist / tcpdump / print-ospf6.c
blob64fd92ad8187b11d1c3e17f98bb66101c2aee463
1 /* $NetBSD$ */
3 /*
4 * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that: (1) source code distributions
9 * retain the above copyright notice and this paragraph in its entirety, (2)
10 * distributions including binary code include the above copyright notice and
11 * this paragraph in its entirety in the documentation or other materials
12 * provided with the distribution, and (3) all advertising materials mentioning
13 * features or use of this software display the following acknowledgement:
14 * ``This product includes software developed by the University of California,
15 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16 * the University nor the names of its contributors may be used to endorse
17 * or promote products derived from this software without specific prior
18 * written permission.
19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23 * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu)
26 #include <sys/cdefs.h>
27 #ifndef lint
28 #if 0
29 static const char rcsid[] _U_ =
30 "@(#) Header: /tcpdump/master/tcpdump/print-ospf6.c,v 1.13 2003/11/16 09:36:31 guy Exp (LBL)";
31 #else
32 __RCSID("$NetBSD: tcpdump2rcsid.ex,v 1.1 2001/06/25 20:09:58 itojun Exp $");
33 #endif
34 #endif
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
40 #include <tcpdump-stdinc.h>
42 #include <stdio.h>
43 #include <string.h>
45 #include "interface.h"
46 #include "addrtoname.h"
47 #include "extract.h"
49 #include "ospf6.h"
51 struct bits {
52 u_int32_t bit;
53 const char *str;
56 static 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 }
66 static 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 }
74 static const struct bits ospf6_asla_flag_bits[] = {
75 { ASLA_FLAG_EXTERNAL, "E" },
76 { ASLA_FLAG_FWDADDR, "F" },
77 { ASLA_FLAG_ROUTETAG, "T" },
78 { 0, NULL }
81 static struct tok type2str[] = {
82 { OSPF_TYPE_UMD, "umd" },
83 { OSPF_TYPE_HELLO, "hello" },
84 { OSPF_TYPE_DB, "dd" },
85 { OSPF_TYPE_LSR, "ls_req" },
86 { OSPF_TYPE_LSU, "ls_upd" },
87 { OSPF_TYPE_LSA, "ls_ack" },
88 { 0, NULL }
91 static char tstr[] = " [|ospf]";
93 #ifdef WIN32
94 #define inline __inline
95 #endif /* WIN32 */
97 /* Forwards */
98 static inline void ospf6_print_seqage(u_int32_t, time_t);
99 static inline void ospf6_print_bits(const struct bits *, u_char);
100 static void ospf6_print_ls_type(u_int, const rtrid_t *,
101 const rtrid_t *, const char *);
102 static int ospf6_print_lshdr(const struct lsa_hdr *);
103 static int ospf6_print_lsa(const struct lsa *);
104 static int ospf6_decode_v3(const struct ospf6hdr *, const u_char *);
106 static inline void
107 ospf6_print_seqage(register u_int32_t seq, register time_t us)
109 register time_t sec = us % 60;
110 register time_t mins = (us / 60) % 60;
111 register time_t hour = us / 3600;
113 printf(" S %X age ", seq);
114 if (hour)
115 printf("%u:%02u:%02u",
116 (u_int32_t) hour, (u_int32_t) mins, (u_int32_t) sec);
117 else if (mins)
118 printf("%u:%02u", (u_int32_t) mins, (u_int32_t) sec);
119 else
120 printf("%u", (u_int32_t) sec);
124 static inline void
125 ospf6_print_bits(register const struct bits *bp, register u_char options)
127 register char sep = ' ';
129 do {
130 if (options & bp->bit) {
131 printf("%c%s", sep, bp->str);
132 sep = '/';
134 } while ((++bp)->bit);
137 static void
138 ospf6_print_ls_type(register u_int ls_type,
139 register const rtrid_t *ls_stateid,
140 register const rtrid_t *ls_router, register const char *fmt)
142 const char *scope;
144 switch (ls_type & LS_SCOPE_MASK) {
145 case LS_SCOPE_LINKLOCAL:
146 scope = "linklocal-";
147 break;
148 case LS_SCOPE_AREA:
149 scope = "area-";
150 break;
151 case LS_SCOPE_AS:
152 scope = "AS-";
153 break;
154 default:
155 scope = "";
156 break;
159 switch (ls_type & LS_TYPE_MASK) {
160 case LS_TYPE_ROUTER:
161 printf(" %srtr %s", scope, ipaddr_string(ls_router));
162 break;
164 case LS_TYPE_NETWORK:
165 printf(" %snet dr %s if %s", scope,
166 ipaddr_string(ls_router),
167 ipaddr_string(ls_stateid));
168 break;
170 case LS_TYPE_INTER_AP:
171 printf(" %sinter-area-prefix %s abr %s", scope,
172 ipaddr_string(ls_stateid),
173 ipaddr_string(ls_router));
174 break;
176 case LS_TYPE_INTER_AR:
177 printf(" %sinter-area-router %s rtr %s", scope,
178 ipaddr_string(ls_router),
179 ipaddr_string(ls_stateid));
180 break;
182 case LS_TYPE_ASE:
183 printf(" %sase %s asbr %s", scope,
184 ipaddr_string(ls_stateid),
185 ipaddr_string(ls_router));
186 break;
188 case LS_TYPE_GROUP:
189 printf(" %sgroup %s rtr %s", scope,
190 ipaddr_string(ls_stateid),
191 ipaddr_string(ls_router));
192 break;
194 case LS_TYPE_TYPE7:
195 printf(" %stype7 %s rtr %s", scope,
196 ipaddr_string(ls_stateid),
197 ipaddr_string(ls_router));
198 break;
200 case LS_TYPE_LINK:
201 printf(" %slink %s rtr %s", scope,
202 ipaddr_string(ls_stateid),
203 ipaddr_string(ls_router));
204 break;
206 case LS_TYPE_INTRA_AP:
207 printf(" %sintra-area-prefix %s rtr %s", scope,
208 ipaddr_string(ls_stateid),
209 ipaddr_string(ls_router));
210 break;
212 default:
213 printf(" %s", scope);
214 printf(fmt, ls_type);
215 break;
220 static int
221 ospf6_print_lshdr(register const struct lsa_hdr *lshp)
224 TCHECK(lshp->ls_type);
225 printf(" {"); /* } (ctags) */
227 TCHECK(lshp->ls_seq);
228 ospf6_print_seqage(EXTRACT_32BITS(&lshp->ls_seq), EXTRACT_16BITS(&lshp->ls_age));
229 ospf6_print_ls_type(EXTRACT_16BITS(&lshp->ls_type), &lshp->ls_stateid,
230 &lshp->ls_router, "ls_type %d");
232 return (0);
233 trunc:
234 return (1);
237 static int
238 ospf6_print_lsaprefix(register const struct lsa_prefix *lsapp)
240 u_int k;
241 struct in6_addr prefix;
243 TCHECK(*lsapp);
244 k = (lsapp->lsa_p_len + 31) / 32;
245 if (k * 4 > sizeof(struct in6_addr)) {
246 printf("??prefixlen %d??", lsapp->lsa_p_len);
247 goto trunc;
249 memset(&prefix, 0, sizeof(prefix));
250 memcpy(&prefix, lsapp->lsa_p_prefix, k * 4);
251 printf(" %s/%d", ip6addr_string(&prefix),
252 lsapp->lsa_p_len);
253 if (lsapp->lsa_p_opt)
254 printf("(opt=%x)", lsapp->lsa_p_opt);
255 if (lsapp->lsa_p_mbz)
256 printf("(mbz=%x)", EXTRACT_16BITS(&lsapp->lsa_p_mbz)); /* XXX */
257 return sizeof(*lsapp) - 4 + k * 4;
259 trunc:
260 return -1;
265 * Print a single link state advertisement. If truncated return 1, else 0.
267 static int
268 ospf6_print_lsa(register const struct lsa *lsap)
270 register const u_char *ls_end, *ls_opt;
271 register const struct rlalink *rlp;
272 #if 0
273 register const struct tos_metric *tosp;
274 #endif
275 register const rtrid_t *ap;
276 #if 0
277 register const struct aslametric *almp;
278 register const struct mcla *mcp;
279 #endif
280 register const struct llsa *llsap;
281 register const struct lsa_prefix *lsapp;
282 #if 0
283 register const u_int32_t *lp;
284 #endif
285 register u_int j;
286 register int k;
287 u_int32_t flags32;
289 if (ospf6_print_lshdr(&lsap->ls_hdr))
290 return (1);
291 TCHECK(lsap->ls_hdr.ls_length);
292 ls_end = (u_char *)lsap + EXTRACT_16BITS(&lsap->ls_hdr.ls_length);
293 switch (EXTRACT_16BITS(&lsap->ls_hdr.ls_type)) {
294 case LS_TYPE_ROUTER | LS_SCOPE_AREA:
295 TCHECK(lsap->lsa_un.un_rla.rla_flags);
296 ospf6_print_bits(ospf6_rla_flag_bits,
297 lsap->lsa_un.un_rla.rla_flags);
298 TCHECK(lsap->lsa_un.un_rla.rla_options);
299 ospf6_print_bits(ospf6_option_bits,
300 EXTRACT_32BITS(&lsap->lsa_un.un_rla.rla_options));
302 TCHECK(lsap->lsa_un.un_rla.rla_link);
303 rlp = lsap->lsa_un.un_rla.rla_link;
304 while (rlp + sizeof(*rlp) <= (struct rlalink *)ls_end) {
305 TCHECK(*rlp);
306 printf(" {"); /* } (ctags) */
307 switch (rlp->link_type) {
309 case RLA_TYPE_VIRTUAL:
310 printf(" virt");
311 /* Fall through */
313 case RLA_TYPE_ROUTER:
314 printf(" nbrid %s nbrif %s if %s",
315 ipaddr_string(&rlp->link_nrtid),
316 ipaddr_string(&rlp->link_nifid),
317 ipaddr_string(&rlp->link_ifid));
318 break;
320 case RLA_TYPE_TRANSIT:
321 printf(" dr %s drif %s if %s",
322 ipaddr_string(&rlp->link_nrtid),
323 ipaddr_string(&rlp->link_nifid),
324 ipaddr_string(&rlp->link_ifid));
325 break;
327 default:
328 /* { (ctags) */
329 printf(" ??RouterLinksType 0x%02x?? }",
330 rlp->link_type);
331 return (0);
333 printf(" metric %d", EXTRACT_16BITS(&rlp->link_metric));
334 /* { (ctags) */
335 printf(" }");
336 rlp++;
338 break;
340 case LS_TYPE_NETWORK | LS_SCOPE_AREA:
341 TCHECK(lsap->lsa_un.un_nla.nla_options);
342 ospf6_print_bits(ospf6_option_bits,
343 EXTRACT_32BITS(&lsap->lsa_un.un_nla.nla_options));
344 printf(" rtrs");
345 ap = lsap->lsa_un.un_nla.nla_router;
346 while ((u_char *)ap < ls_end) {
347 TCHECK(*ap);
348 printf(" %s", ipaddr_string(ap));
349 ++ap;
351 break;
353 case LS_TYPE_INTER_AP | LS_SCOPE_AREA:
354 TCHECK(lsap->lsa_un.un_inter_ap.inter_ap_metric);
355 printf(" metric %u",
356 EXTRACT_32BITS(&lsap->lsa_un.un_inter_ap.inter_ap_metric) & SLA_MASK_METRIC);
357 lsapp = lsap->lsa_un.un_inter_ap.inter_ap_prefix;
358 while (lsapp + sizeof(lsapp) <= (struct lsa_prefix *)ls_end) {
359 k = ospf6_print_lsaprefix(lsapp);
360 if (k)
361 goto trunc;
362 lsapp = (struct lsa_prefix *)(((u_char *)lsapp) + k);
364 break;
365 case LS_SCOPE_AS | LS_TYPE_ASE:
366 TCHECK(lsap->lsa_un.un_asla.asla_metric);
367 flags32 = EXTRACT_32BITS(&lsap->lsa_un.un_asla.asla_metric);
368 ospf6_print_bits(ospf6_asla_flag_bits, flags32);
369 printf(" metric %u",
370 EXTRACT_32BITS(&lsap->lsa_un.un_asla.asla_metric) &
371 ASLA_MASK_METRIC);
372 lsapp = lsap->lsa_un.un_asla.asla_prefix;
373 k = ospf6_print_lsaprefix(lsapp);
374 if (k < 0)
375 goto trunc;
376 if ((ls_opt = (u_char *)(((u_char *)lsapp) + k)) < ls_end) {
377 struct in6_addr *fwdaddr6;
379 if ((flags32 & ASLA_FLAG_FWDADDR) != 0) {
380 fwdaddr6 = (struct in6_addr *)ls_opt;
381 TCHECK(*fwdaddr6);
382 printf(" forward %s",
383 ip6addr_string(fwdaddr6));
385 ls_opt += sizeof(struct in6_addr);
388 if ((flags32 & ASLA_FLAG_ROUTETAG) != 0) {
389 TCHECK(*(u_int32_t *)ls_opt);
390 printf(" tag %s",
391 ipaddr_string((u_int32_t *)ls_opt));
393 ls_opt += sizeof(u_int32_t);
396 if (lsapp->lsa_p_mbz) {
397 TCHECK(*(u_int32_t *)ls_opt);
398 printf(" RefLSID: %s",
399 ipaddr_string((u_int32_t *)ls_opt));
401 ls_opt += sizeof(u_int32_t);
404 break;
405 #if 0
406 case LS_TYPE_SUM_ABR:
407 TCHECK(lsap->lsa_un.un_sla.sla_tosmetric);
408 lp = lsap->lsa_un.un_sla.sla_tosmetric;
409 while ((u_char *)lp < ls_end) {
410 register u_int32_t ul;
412 TCHECK(*lp);
413 ul = EXTRACT_32BITS(lp);
414 printf(" tos %d metric %d",
415 (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS,
416 ul & SLA_MASK_METRIC);
417 ++lp;
419 break;
421 case LS_TYPE_GROUP:
422 /* Multicast extensions as of 23 July 1991 */
423 mcp = lsap->lsa_un.un_mcla;
424 while ((u_char *)mcp < ls_end) {
425 TCHECK(mcp->mcla_vid);
426 switch (EXTRACT_32BITS(&mcp->mcla_vtype)) {
428 case MCLA_VERTEX_ROUTER:
429 printf(" rtr rtrid %s",
430 ipaddr_string(&mcp->mcla_vid));
431 break;
433 case MCLA_VERTEX_NETWORK:
434 printf(" net dr %s",
435 ipaddr_string(&mcp->mcla_vid));
436 break;
438 default:
439 printf(" ??VertexType %u??",
440 EXTRACT_32BITS(&mcp->mcla_vtype));
441 break;
443 ++mcp;
445 #endif
447 case LS_TYPE_LINK:
448 /* Link LSA */
449 llsap = &lsap->lsa_un.un_llsa;
450 TCHECK(llsap->llsa_options);
451 ospf6_print_bits(ospf6_option_bits, EXTRACT_32BITS(&llsap->llsa_options));
452 TCHECK(llsap->llsa_nprefix);
453 printf(" pri %d lladdr %s npref %d", llsap->llsa_priority,
454 ip6addr_string(&llsap->llsa_lladdr),
455 EXTRACT_32BITS(&llsap->llsa_nprefix));
456 lsapp = llsap->llsa_prefix;
457 for (j = 0; j < EXTRACT_32BITS(&llsap->llsa_nprefix); j++) {
458 k = ospf6_print_lsaprefix(lsapp);
459 if (k)
460 goto trunc;
461 lsapp = (struct lsa_prefix *)(((u_char *)lsapp) + k);
463 break;
465 case LS_TYPE_INTRA_AP | LS_SCOPE_AREA:
466 /* Intra-Area-Prefix LSA */
467 TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_rtid);
468 ospf6_print_ls_type(
469 EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_lstype),
470 &lsap->lsa_un.un_intra_ap.intra_ap_lsid,
471 &lsap->lsa_un.un_intra_ap.intra_ap_rtid,
472 "LinkStateType %d");
473 TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_nprefix);
474 printf(" npref %d",
475 EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_nprefix));
477 lsapp = lsap->lsa_un.un_intra_ap.intra_ap_prefix;
478 for (j = 0;
479 j < EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_nprefix);
480 j++) {
481 k = ospf6_print_lsaprefix(lsapp);
482 if (k)
483 goto trunc;
484 lsapp = (struct lsa_prefix *)(((u_char *)lsapp) + k);
486 break;
488 default:
489 printf(" ??LinkStateType 0x%04x??",
490 EXTRACT_16BITS(&lsap->ls_hdr.ls_type));
493 /* { (ctags) */
494 fputs(" }", stdout);
495 return (0);
496 trunc:
497 fputs(" }", stdout);
498 return (1);
501 static int
502 ospf6_decode_v3(register const struct ospf6hdr *op,
503 register const u_char *dataend)
505 register const rtrid_t *ap;
506 register const struct lsr *lsrp;
507 register const struct lsa_hdr *lshp;
508 register const struct lsa *lsap;
509 register char sep;
510 register int i;
512 switch (op->ospf6_type) {
514 case OSPF_TYPE_UMD:
516 * Rob Coltun's special monitoring packets;
517 * do nothing
519 break;
521 case OSPF_TYPE_HELLO:
522 if (vflag) {
523 TCHECK(op->ospf6_hello.hello_deadint);
524 ospf6_print_bits(ospf6_option_bits,
525 EXTRACT_32BITS(&op->ospf6_hello.hello_options));
526 printf(" ifid %s pri %d int %d dead %u",
527 ipaddr_string(&op->ospf6_hello.hello_ifid),
528 op->ospf6_hello.hello_priority,
529 EXTRACT_16BITS(&op->ospf6_hello.hello_helloint),
530 EXTRACT_16BITS(&op->ospf6_hello.hello_deadint));
532 TCHECK(op->ospf6_hello.hello_dr);
533 if (op->ospf6_hello.hello_dr != 0)
534 printf(" dr %s",
535 ipaddr_string(&op->ospf6_hello.hello_dr));
536 TCHECK(op->ospf6_hello.hello_bdr);
537 if (op->ospf6_hello.hello_bdr != 0)
538 printf(" bdr %s",
539 ipaddr_string(&op->ospf6_hello.hello_bdr));
540 if (vflag) {
541 printf(" nbrs");
542 ap = op->ospf6_hello.hello_neighbor;
543 while ((u_char *)ap < dataend) {
544 TCHECK(*ap);
545 printf(" %s", ipaddr_string(ap));
546 ++ap;
549 break; /* HELLO */
551 case OSPF_TYPE_DB:
552 TCHECK(op->ospf6_db.db_options);
553 ospf6_print_bits(ospf6_option_bits,
554 EXTRACT_32BITS(&op->ospf6_db.db_options));
555 sep = ' ';
556 TCHECK(op->ospf6_db.db_flags);
557 if (op->ospf6_db.db_flags & OSPF6_DB_INIT) {
558 printf("%cI", sep);
559 sep = '/';
561 if (op->ospf6_db.db_flags & OSPF6_DB_MORE) {
562 printf("%cM", sep);
563 sep = '/';
565 if (op->ospf6_db.db_flags & OSPF6_DB_MASTER) {
566 printf("%cMS", sep);
567 sep = '/';
569 TCHECK(op->ospf6_db.db_seq);
570 printf(" mtu %u S %X", EXTRACT_16BITS(&op->ospf6_db.db_mtu),
571 EXTRACT_32BITS(&op->ospf6_db.db_seq));
573 if (vflag) {
574 /* Print all the LS adv's */
575 lshp = op->ospf6_db.db_lshdr;
577 while (!ospf6_print_lshdr(lshp)) {
578 /* { (ctags) */
579 printf(" }");
580 ++lshp;
583 break;
585 case OSPF_TYPE_LSR:
586 if (vflag) {
587 lsrp = op->ospf6_lsr;
588 while ((u_char *)lsrp < dataend) {
589 TCHECK(*lsrp);
590 printf(" {"); /* } (ctags) */
591 ospf6_print_ls_type(EXTRACT_16BITS(&lsrp->ls_type),
592 &lsrp->ls_stateid,
593 &lsrp->ls_router,
594 "LinkStateType %d");
595 /* { (ctags) */
596 printf(" }");
597 ++lsrp;
600 break;
602 case OSPF_TYPE_LSU:
603 if (vflag) {
604 lsap = op->ospf6_lsu.lsu_lsa;
605 TCHECK(op->ospf6_lsu.lsu_count);
606 i = EXTRACT_32BITS(&op->ospf6_lsu.lsu_count);
607 while (i--) {
608 if (ospf6_print_lsa(lsap))
609 goto trunc;
610 lsap = (struct lsa *)((u_char *)lsap +
611 EXTRACT_16BITS(&lsap->ls_hdr.ls_length));
614 break;
617 case OSPF_TYPE_LSA:
618 if (vflag) {
619 lshp = op->ospf6_lsa.lsa_lshdr;
621 while (!ospf6_print_lshdr(lshp)) {
622 /* { (ctags) */
623 printf(" }");
624 ++lshp;
627 break;
629 default:
630 printf("v3 type %d", op->ospf6_type);
631 break;
633 return (0);
634 trunc:
635 return (1);
638 void
639 ospf6_print(register const u_char *bp, register u_int length)
641 register const struct ospf6hdr *op;
642 register const u_char *dataend;
643 register const char *cp;
645 op = (struct ospf6hdr *)bp;
647 /* If the type is valid translate it, or just print the type */
648 /* value. If it's not valid, say so and return */
649 TCHECK(op->ospf6_type);
650 cp = tok2str(type2str, "type%d", op->ospf6_type);
651 printf("OSPFv%d-%s %d:", op->ospf6_version, cp, length);
652 if (*cp == 't')
653 return;
655 TCHECK(op->ospf6_len);
656 if (length != EXTRACT_16BITS(&op->ospf6_len)) {
657 printf(" [len %d]", EXTRACT_16BITS(&op->ospf6_len));
658 return;
660 dataend = bp + length;
662 /* Print the routerid if it is not the same as the source */
663 TCHECK(op->ospf6_routerid);
664 printf(" rtrid %s", ipaddr_string(&op->ospf6_routerid));
666 TCHECK(op->ospf6_areaid);
667 if (op->ospf6_areaid != 0)
668 printf(" area %s", ipaddr_string(&op->ospf6_areaid));
669 else
670 printf(" backbone");
671 TCHECK(op->ospf6_instanceid);
672 if (op->ospf6_instanceid)
673 printf(" instance %u", op->ospf6_instanceid);
675 /* Do rest according to version. */
676 switch (op->ospf6_version) {
678 case 3:
679 /* ospf version 3 */
680 if (ospf6_decode_v3(op, dataend))
681 goto trunc;
682 break;
684 default:
685 printf(" ospf [version %d]", op->ospf6_version);
686 break;
687 } /* end switch on version */
689 return;
690 trunc:
691 fputs(tstr, stdout);