2 * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997
3 * The Regents of the University of California. All rights reserved.
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
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.
21 * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu)
25 static const char rcsid
[] _U_
=
26 "@(#) $Header: /tcpdump/master/tcpdump/print-ospf6.c,v 1.15 2006-09-13 06:31:11 guy Exp $ (LBL)";
33 #include <tcpdump-stdinc.h>
38 #include "interface.h"
39 #include "addrtoname.h"
45 static const struct tok ospf6_option_values
[] = {
46 { OSPF6_OPTION_V6
, "V6" },
47 { OSPF6_OPTION_E
, "External" },
48 { OSPF6_OPTION_MC
, "Multicast" },
49 { OSPF6_OPTION_N
, "NSSA" },
50 { OSPF6_OPTION_R
, "Router" },
51 { OSPF6_OPTION_DC
, "Demand Circuit" },
55 static const struct tok ospf6_rla_flag_values
[] = {
56 { RLA_FLAG_B
, "ABR" },
57 { RLA_FLAG_E
, "External" },
58 { RLA_FLAG_V
, "Virtual-Link Endpoint" },
59 { RLA_FLAG_W
, "Wildcard Receiver" },
60 { RLA_FLAG_N
, "NSSA Translator" },
64 static const struct tok ospf6_asla_flag_values
[] = {
65 { ASLA_FLAG_EXTERNAL
, "External Type 2" },
66 { ASLA_FLAG_FWDADDR
, "Fforwarding" },
67 { ASLA_FLAG_ROUTETAG
, "Tag" },
71 static struct tok ospf6_type_values
[] = {
72 { OSPF_TYPE_HELLO
, "Hello" },
73 { OSPF_TYPE_DD
, "Database Description" },
74 { OSPF_TYPE_LS_REQ
, "LS-Request" },
75 { OSPF_TYPE_LS_UPDATE
, "LS-Update" },
76 { OSPF_TYPE_LS_ACK
, "LS-Ack" },
80 static struct tok ospf6_lsa_values
[] = {
81 { LS_TYPE_ROUTER
, "Router" },
82 { LS_TYPE_NETWORK
, "Network" },
83 { LS_TYPE_INTER_AP
, "Inter-Area Prefix" },
84 { LS_TYPE_INTER_AR
, "Inter-Area Router" },
85 { LS_TYPE_ASE
, "External" },
86 { LS_TYPE_GROUP
, "Multicast Group" },
87 { LS_TYPE_NSSA
, "NSSA" },
88 { LS_TYPE_LINK
, "Link" },
89 { LS_TYPE_INTRA_AP
, "Intra-Area Prefix" },
90 { LS_TYPE_INTRA_ATE
, "Intra-Area TE" },
91 { LS_TYPE_GRACE
, "Grace" },
95 static struct tok ospf6_ls_scope_values
[] = {
96 { LS_SCOPE_LINKLOCAL
, "Link Local" },
97 { LS_SCOPE_AREA
, "Area Local" },
98 { LS_SCOPE_AS
, "Domain Wide" },
102 static struct tok ospf6_dd_flag_values
[] = {
103 { OSPF6_DB_INIT
, "Init" },
104 { OSPF6_DB_MORE
, "More" },
105 { OSPF6_DB_MASTER
, "Master" },
109 static struct tok ospf6_lsa_prefix_option_values
[] = {
110 { LSA_PREFIX_OPT_NU
, "No Unicast" },
111 { LSA_PREFIX_OPT_LA
, "Local address" },
112 { LSA_PREFIX_OPT_MC
, "Multicast" },
113 { LSA_PREFIX_OPT_P
, "Propagate" },
114 { LSA_PREFIX_OPT_DN
, "Down" },
118 static char tstr
[] = " [|ospf3]";
121 #define inline __inline
125 static void ospf6_print_ls_type(u_int
, const rtrid_t
*);
126 static int ospf6_print_lshdr(const struct lsa6_hdr
*);
127 static int ospf6_print_lsa(const struct lsa6
*);
128 static int ospf6_decode_v3(const struct ospf6hdr
*, const u_char
*);
132 ospf6_print_ls_type(register u_int ls_type
, register const rtrid_t
*ls_stateid
)
134 printf("\n\t %s LSA (%d), %s Scope%s, LSA-ID %s",
135 tok2str(ospf6_lsa_values
, "Unknown", ls_type
& LS_TYPE_MASK
),
136 ls_type
& LS_TYPE_MASK
,
137 tok2str(ospf6_ls_scope_values
, "Unknown", ls_type
& LS_SCOPE_MASK
),
138 ls_type
&0x8000 ? ", transitive" : "", /* U-bit */
139 ipaddr_string(ls_stateid
));
143 ospf6_print_lshdr(register const struct lsa6_hdr
*lshp
)
146 TCHECK(lshp
->ls_type
);
147 TCHECK(lshp
->ls_seq
);
149 printf("\n\t Advertising Router %s, seq 0x%08x, age %us, length %u",
150 ipaddr_string(&lshp
->ls_router
),
151 EXTRACT_32BITS(&lshp
->ls_seq
),
152 EXTRACT_16BITS(&lshp
->ls_age
),
153 EXTRACT_16BITS(&lshp
->ls_length
)-(u_int
)sizeof(struct lsa6_hdr
));
155 ospf6_print_ls_type(EXTRACT_16BITS(&lshp
->ls_type
), &lshp
->ls_stateid
);
163 ospf6_print_lsaprefix(const u_int8_t
*tptr
, u_int lsa_length
)
165 const struct lsa6_prefix
*lsapp
= (struct lsa6_prefix
*)tptr
;
167 struct in6_addr prefix
;
169 if (lsa_length
< sizeof (*lsapp
) - 4)
171 lsa_length
-= sizeof (*lsapp
) - 4;
172 TCHECK2(*lsapp
, sizeof (*lsapp
) - 4);
173 wordlen
= (lsapp
->lsa_p_len
+ 31) / 32;
174 if (wordlen
* 4 > sizeof(struct in6_addr
)) {
175 printf(" bogus prefixlen /%d", lsapp
->lsa_p_len
);
178 if (lsa_length
< wordlen
* 4)
180 lsa_length
-= wordlen
* 4;
181 TCHECK2(lsapp
->lsa_p_prefix
, wordlen
* 4);
182 memset(&prefix
, 0, sizeof(prefix
));
183 memcpy(&prefix
, lsapp
->lsa_p_prefix
, wordlen
* 4);
184 printf("\n\t\t%s/%d", ip6addr_string(&prefix
),
186 if (lsapp
->lsa_p_opt
) {
187 printf(", Options [%s]",
188 bittok2str(ospf6_lsa_prefix_option_values
,
189 "none", lsapp
->lsa_p_opt
));
191 printf(", metric %u", EXTRACT_16BITS(&lsapp
->lsa_p_metric
));
192 return sizeof(*lsapp
) - 4 + wordlen
* 4;
200 * Print a single link state advertisement. If truncated return 1, else 0.
203 ospf6_print_lsa(register const struct lsa6
*lsap
)
205 register const struct rlalink6
*rlp
;
207 register const struct tos_metric
*tosp
;
209 register const rtrid_t
*ap
;
211 register const struct aslametric
*almp
;
212 register const struct mcla
*mcp
;
214 register const struct llsa
*llsap
;
215 register const struct lsa6_prefix
*lsapp
;
217 register const u_int32_t
*lp
;
219 register u_int prefixes
;
220 register int bytelen
;
221 register u_int length
, lsa_length
;
223 const u_int8_t
*tptr
;
225 if (ospf6_print_lshdr(&lsap
->ls_hdr
))
227 TCHECK(lsap
->ls_hdr
.ls_length
);
228 length
= EXTRACT_16BITS(&lsap
->ls_hdr
.ls_length
);
231 * The LSA length includes the length of the header;
232 * it must have a value that's at least that length.
233 * If it does, find the length of what follows the
236 if (length
< sizeof(struct lsa6_hdr
))
238 lsa_length
= length
- sizeof(struct lsa6_hdr
);
239 tptr
= (u_int8_t
*)lsap
+sizeof(struct lsa6_hdr
);
241 switch (EXTRACT_16BITS(&lsap
->ls_hdr
.ls_type
)) {
242 case LS_TYPE_ROUTER
| LS_SCOPE_AREA
:
243 if (lsa_length
< sizeof (lsap
->lsa_un
.un_rla
.rla_options
))
245 lsa_length
-= sizeof (lsap
->lsa_un
.un_rla
.rla_options
);
246 TCHECK(lsap
->lsa_un
.un_rla
.rla_options
);
247 printf("\n\t Options [%s]",
248 bittok2str(ospf6_option_values
, "none",
249 EXTRACT_32BITS(&lsap
->lsa_un
.un_rla
.rla_options
)));
250 printf(", RLA-Flags [%s]",
251 bittok2str(ospf6_rla_flag_values
, "none",
252 lsap
->lsa_un
.un_rla
.rla_flags
));
254 rlp
= lsap
->lsa_un
.un_rla
.rla_link
;
255 while (lsa_length
!= 0) {
256 if (lsa_length
< sizeof (*rlp
))
258 lsa_length
-= sizeof (*rlp
);
260 switch (rlp
->link_type
) {
262 case RLA_TYPE_VIRTUAL
:
263 printf("\n\t Virtual Link: Neighbor Router-ID %s"
264 "\n\t Neighbor Interface-ID %s, Interface %s",
265 ipaddr_string(&rlp
->link_nrtid
),
266 ipaddr_string(&rlp
->link_nifid
),
267 ipaddr_string(&rlp
->link_ifid
));
270 case RLA_TYPE_ROUTER
:
271 printf("\n\t Neighbor Router-ID %s"
272 "\n\t Neighbor Interface-ID %s, Interface %s",
273 ipaddr_string(&rlp
->link_nrtid
),
274 ipaddr_string(&rlp
->link_nifid
),
275 ipaddr_string(&rlp
->link_ifid
));
278 case RLA_TYPE_TRANSIT
:
279 printf("\n\t Neighbor Network-ID %s"
280 "\n\t Neighbor Interface-ID %s, Interface %s",
281 ipaddr_string(&rlp
->link_nrtid
),
282 ipaddr_string(&rlp
->link_nifid
),
283 ipaddr_string(&rlp
->link_ifid
));
287 printf("\n\t Unknown Router Links Type 0x%02x",
291 printf(", metric %d", EXTRACT_16BITS(&rlp
->link_metric
));
296 case LS_TYPE_NETWORK
| LS_SCOPE_AREA
:
297 if (lsa_length
< sizeof (lsap
->lsa_un
.un_nla
.nla_options
))
299 lsa_length
-= sizeof (lsap
->lsa_un
.un_nla
.nla_options
);
300 TCHECK(lsap
->lsa_un
.un_nla
.nla_options
);
301 printf("\n\t Options [%s]",
302 bittok2str(ospf6_option_values
, "none",
303 EXTRACT_32BITS(&lsap
->lsa_un
.un_nla
.nla_options
)));
305 printf("\n\t Connected Routers:");
306 ap
= lsap
->lsa_un
.un_nla
.nla_router
;
307 while (lsa_length
!= 0) {
308 if (lsa_length
< sizeof (*ap
))
310 lsa_length
-= sizeof (*ap
);
312 printf("\n\t\t%s", ipaddr_string(ap
));
317 case LS_TYPE_INTER_AP
| LS_SCOPE_AREA
:
318 if (lsa_length
< sizeof (lsap
->lsa_un
.un_inter_ap
.inter_ap_metric
))
320 lsa_length
-= sizeof (lsap
->lsa_un
.un_inter_ap
.inter_ap_metric
);
321 TCHECK(lsap
->lsa_un
.un_inter_ap
.inter_ap_metric
);
322 printf(", metric %u",
323 EXTRACT_32BITS(&lsap
->lsa_un
.un_inter_ap
.inter_ap_metric
) & SLA_MASK_METRIC
);
325 tptr
= (u_int8_t
*)lsap
->lsa_un
.un_inter_ap
.inter_ap_prefix
;
326 while (lsa_length
!= 0) {
327 bytelen
= ospf6_print_lsaprefix(tptr
, lsa_length
);
330 lsa_length
-= bytelen
;
335 case LS_TYPE_ASE
| LS_SCOPE_AS
:
336 if (lsa_length
< sizeof (lsap
->lsa_un
.un_asla
.asla_metric
))
338 lsa_length
-= sizeof (lsap
->lsa_un
.un_asla
.asla_metric
);
339 TCHECK(lsap
->lsa_un
.un_asla
.asla_metric
);
340 flags32
= EXTRACT_32BITS(&lsap
->lsa_un
.un_asla
.asla_metric
);
341 printf("\n\t Flags [%s]",
342 bittok2str(ospf6_asla_flag_values
, "none", flags32
));
344 EXTRACT_32BITS(&lsap
->lsa_un
.un_asla
.asla_metric
) &
347 tptr
= (u_int8_t
*)lsap
->lsa_un
.un_asla
.asla_prefix
;
348 lsapp
= (struct lsa6_prefix
*)tptr
;
349 bytelen
= ospf6_print_lsaprefix(tptr
, lsa_length
);
352 lsa_length
-= bytelen
;
355 if ((flags32
& ASLA_FLAG_FWDADDR
) != 0) {
356 struct in6_addr
*fwdaddr6
;
358 fwdaddr6
= (struct in6_addr
*)tptr
;
359 if (lsa_length
< sizeof (*fwdaddr6
))
361 lsa_length
-= sizeof (*fwdaddr6
);
363 printf(" forward %s",
364 ip6addr_string(fwdaddr6
));
365 tptr
+= sizeof(*fwdaddr6
);
368 if ((flags32
& ASLA_FLAG_ROUTETAG
) != 0) {
369 if (lsa_length
< sizeof (u_int32_t
))
371 lsa_length
-= sizeof (u_int32_t
);
372 TCHECK(*(u_int32_t
*)tptr
);
374 ipaddr_string((u_int32_t
*)tptr
));
375 tptr
+= sizeof(u_int32_t
);
378 if (lsapp
->lsa_p_metric
) {
379 if (lsa_length
< sizeof (u_int32_t
))
381 lsa_length
-= sizeof (u_int32_t
);
382 TCHECK(*(u_int32_t
*)tptr
);
383 printf(" RefLSID: %s",
384 ipaddr_string((u_int32_t
*)tptr
));
385 tptr
+= sizeof(u_int32_t
);
391 llsap
= &lsap
->lsa_un
.un_llsa
;
392 if (lsa_length
< sizeof (llsap
->llsa_priandopt
))
394 lsa_length
-= sizeof (llsap
->llsa_priandopt
);
395 TCHECK(llsap
->llsa_priandopt
);
396 printf("\n\t Options [%s]",
397 bittok2str(ospf6_option_values
, "none",
398 EXTRACT_32BITS(&llsap
->llsa_options
)));
400 if (lsa_length
< sizeof (llsap
->llsa_lladdr
) + sizeof (llsap
->llsa_nprefix
))
402 lsa_length
-= sizeof (llsap
->llsa_lladdr
) + sizeof (llsap
->llsa_nprefix
);
403 prefixes
= EXTRACT_32BITS(&llsap
->llsa_nprefix
);
404 printf("\n\t Priority %d, Link-local address %s, Prefixes %d:",
405 llsap
->llsa_priority
,
406 ip6addr_string(&llsap
->llsa_lladdr
),
409 tptr
= (u_int8_t
*)llsap
->llsa_prefix
;
410 while (prefixes
> 0) {
411 bytelen
= ospf6_print_lsaprefix(tptr
, lsa_length
);
415 lsa_length
-= bytelen
;
420 case LS_TYPE_INTRA_AP
| LS_SCOPE_AREA
:
421 /* Intra-Area-Prefix LSA */
422 if (lsa_length
< sizeof (lsap
->lsa_un
.un_intra_ap
.intra_ap_rtid
))
424 lsa_length
-= sizeof (lsap
->lsa_un
.un_intra_ap
.intra_ap_rtid
);
425 TCHECK(lsap
->lsa_un
.un_intra_ap
.intra_ap_rtid
);
427 EXTRACT_16BITS(&lsap
->lsa_un
.un_intra_ap
.intra_ap_lstype
),
428 &lsap
->lsa_un
.un_intra_ap
.intra_ap_lsid
);
430 if (lsa_length
< sizeof (lsap
->lsa_un
.un_intra_ap
.intra_ap_nprefix
))
432 lsa_length
-= sizeof (lsap
->lsa_un
.un_intra_ap
.intra_ap_nprefix
);
433 TCHECK(lsap
->lsa_un
.un_intra_ap
.intra_ap_nprefix
);
434 prefixes
= EXTRACT_16BITS(&lsap
->lsa_un
.un_intra_ap
.intra_ap_nprefix
);
435 printf("\n\t Prefixes %d:", prefixes
);
437 tptr
= (u_int8_t
*)lsap
->lsa_un
.un_intra_ap
.intra_ap_prefix
;
438 while (prefixes
> 0) {
439 bytelen
= ospf6_print_lsaprefix(tptr
, lsa_length
);
443 lsa_length
-= bytelen
;
448 case LS_TYPE_GRACE
| LS_SCOPE_LINKLOCAL
:
449 if (ospf_print_grace_lsa(tptr
, lsa_length
) == -1) {
454 case LS_TYPE_INTRA_ATE
| LS_SCOPE_LINKLOCAL
:
455 if (ospf_print_te_lsa(tptr
, lsa_length
) == -1) {
461 if(!print_unknown_data(tptr
,
475 ospf6_decode_v3(register const struct ospf6hdr
*op
,
476 register const u_char
*dataend
)
478 register const rtrid_t
*ap
;
479 register const struct lsr6
*lsrp
;
480 register const struct lsa6_hdr
*lshp
;
481 register const struct lsa6
*lsap
;
484 switch (op
->ospf6_type
) {
486 case OSPF_TYPE_HELLO
:
487 printf("\n\tOptions [%s]",
488 bittok2str(ospf6_option_values
, "none",
489 EXTRACT_32BITS(&op
->ospf6_hello
.hello_options
)));
491 TCHECK(op
->ospf6_hello
.hello_deadint
);
492 printf("\n\t Hello Timer %us, Dead Timer %us, Interface-ID %s, Priority %u",
493 EXTRACT_16BITS(&op
->ospf6_hello
.hello_helloint
),
494 EXTRACT_16BITS(&op
->ospf6_hello
.hello_deadint
),
495 ipaddr_string(&op
->ospf6_hello
.hello_ifid
),
496 op
->ospf6_hello
.hello_priority
);
498 TCHECK(op
->ospf6_hello
.hello_dr
);
499 if (op
->ospf6_hello
.hello_dr
!= 0)
500 printf("\n\t Designated Router %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(", Backup Designated Router %s",
505 ipaddr_string(&op
->ospf6_hello
.hello_bdr
));
507 printf("\n\t Neighbor List:");
508 ap
= op
->ospf6_hello
.hello_neighbor
;
509 while ((u_char
*)ap
< dataend
) {
511 printf("\n\t %s", ipaddr_string(ap
));
518 TCHECK(op
->ospf6_db
.db_options
);
519 printf("\n\tOptions [%s]",
520 bittok2str(ospf6_option_values
, "none",
521 EXTRACT_32BITS(&op
->ospf6_db
.db_options
)));
522 TCHECK(op
->ospf6_db
.db_flags
);
523 printf(", DD Flags [%s]",
524 bittok2str(ospf6_dd_flag_values
,"none",op
->ospf6_db
.db_flags
));
526 TCHECK(op
->ospf6_db
.db_seq
);
527 printf(", MTU %u, DD-Sequence 0x%08x",
528 EXTRACT_16BITS(&op
->ospf6_db
.db_mtu
),
529 EXTRACT_32BITS(&op
->ospf6_db
.db_seq
));
531 /* Print all the LS adv's */
532 lshp
= op
->ospf6_db
.db_lshdr
;
533 while (!ospf6_print_lshdr(lshp
)) {
538 case OSPF_TYPE_LS_REQ
:
540 lsrp
= op
->ospf6_lsr
;
541 while ((u_char
*)lsrp
< dataend
) {
543 printf("\n\t Advertising Router %s",
544 ipaddr_string(&lsrp
->ls_router
));
545 ospf6_print_ls_type(EXTRACT_16BITS(&lsrp
->ls_type
),
552 case OSPF_TYPE_LS_UPDATE
:
554 lsap
= op
->ospf6_lsu
.lsu_lsa
;
555 TCHECK(op
->ospf6_lsu
.lsu_count
);
556 i
= EXTRACT_32BITS(&op
->ospf6_lsu
.lsu_count
);
558 if (ospf6_print_lsa(lsap
))
560 lsap
= (struct lsa6
*)((u_char
*)lsap
+
561 EXTRACT_16BITS(&lsap
->ls_hdr
.ls_length
));
567 case OSPF_TYPE_LS_ACK
:
569 lshp
= op
->ospf6_lsa
.lsa_lshdr
;
571 while (!ospf6_print_lshdr(lshp
)) {
586 ospf6_print(register const u_char
*bp
, register u_int length
)
588 register const struct ospf6hdr
*op
;
589 register const u_char
*dataend
;
590 register const char *cp
;
592 op
= (struct ospf6hdr
*)bp
;
594 /* If the type is valid translate it, or just print the type */
595 /* value. If it's not valid, say so and return */
596 TCHECK(op
->ospf6_type
);
597 cp
= tok2str(ospf6_type_values
, "unknown LS-type", op
->ospf6_type
);
598 printf("OSPFv%u, %s, length %d", op
->ospf6_version
, cp
, length
);
603 if(!vflag
) { /* non verbose - so lets bail out here */
607 TCHECK(op
->ospf6_len
);
608 if (length
!= EXTRACT_16BITS(&op
->ospf6_len
)) {
609 printf(" [len %d]", EXTRACT_16BITS(&op
->ospf6_len
));
612 dataend
= bp
+ length
;
614 /* Print the routerid if it is not the same as the source */
615 TCHECK(op
->ospf6_routerid
);
616 printf("\n\tRouter-ID %s", ipaddr_string(&op
->ospf6_routerid
));
618 TCHECK(op
->ospf6_areaid
);
619 if (op
->ospf6_areaid
!= 0)
620 printf(", Area %s", ipaddr_string(&op
->ospf6_areaid
));
622 printf(", Backbone Area");
623 TCHECK(op
->ospf6_instanceid
);
624 if (op
->ospf6_instanceid
)
625 printf(", Instance %u", op
->ospf6_instanceid
);
627 /* Do rest according to version. */
628 switch (op
->ospf6_version
) {
632 if (ospf6_decode_v3(op
, dataend
))
637 printf(" ospf [version %d]", op
->ospf6_version
);
639 } /* end switch on version */