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 static void ospf6_print_ls_type(u_int
, const rtrid_t
*);
122 static int ospf6_print_lshdr(const struct lsa6_hdr
*);
123 static int ospf6_print_lsa(const struct lsa6
*);
124 static int ospf6_decode_v3(const struct ospf6hdr
*, const u_char
*);
128 ospf6_print_ls_type(register u_int ls_type
, register const rtrid_t
*ls_stateid
)
130 printf("\n\t %s LSA (%d), %s Scope%s, LSA-ID %s",
131 tok2str(ospf6_lsa_values
, "Unknown", ls_type
& LS_TYPE_MASK
),
132 ls_type
& LS_TYPE_MASK
,
133 tok2str(ospf6_ls_scope_values
, "Unknown", ls_type
& LS_SCOPE_MASK
),
134 ls_type
&0x8000 ? ", transitive" : "", /* U-bit */
135 ipaddr_string(ls_stateid
));
139 ospf6_print_lshdr(register const struct lsa6_hdr
*lshp
)
142 TCHECK(lshp
->ls_type
);
143 TCHECK(lshp
->ls_seq
);
145 printf("\n\t Advertising Router %s, seq 0x%08x, age %us, length %u",
146 ipaddr_string(&lshp
->ls_router
),
147 EXTRACT_32BITS(&lshp
->ls_seq
),
148 EXTRACT_16BITS(&lshp
->ls_age
),
149 EXTRACT_16BITS(&lshp
->ls_length
)-(u_int
)sizeof(struct lsa6_hdr
));
151 ospf6_print_ls_type(EXTRACT_16BITS(&lshp
->ls_type
), &lshp
->ls_stateid
);
159 ospf6_print_lsaprefix(const u_int8_t
*tptr
, u_int lsa_length
)
161 const struct lsa6_prefix
*lsapp
= (struct lsa6_prefix
*)tptr
;
163 struct in6_addr prefix
;
165 if (lsa_length
< sizeof (*lsapp
) - 4)
167 lsa_length
-= sizeof (*lsapp
) - 4;
168 TCHECK2(*lsapp
, sizeof (*lsapp
) - 4);
169 wordlen
= (lsapp
->lsa_p_len
+ 31) / 32;
170 if (wordlen
* 4 > sizeof(struct in6_addr
)) {
171 printf(" bogus prefixlen /%d", lsapp
->lsa_p_len
);
174 if (lsa_length
< wordlen
* 4)
176 lsa_length
-= wordlen
* 4;
177 TCHECK2(lsapp
->lsa_p_prefix
, wordlen
* 4);
178 memset(&prefix
, 0, sizeof(prefix
));
179 memcpy(&prefix
, lsapp
->lsa_p_prefix
, wordlen
* 4);
180 printf("\n\t\t%s/%d", ip6addr_string(&prefix
),
182 if (lsapp
->lsa_p_opt
) {
183 printf(", Options [%s]",
184 bittok2str(ospf6_lsa_prefix_option_values
,
185 "none", lsapp
->lsa_p_opt
));
187 printf(", metric %u", EXTRACT_16BITS(&lsapp
->lsa_p_metric
));
188 return sizeof(*lsapp
) - 4 + wordlen
* 4;
196 * Print a single link state advertisement. If truncated return 1, else 0.
199 ospf6_print_lsa(register const struct lsa6
*lsap
)
201 register const struct rlalink6
*rlp
;
203 register const struct tos_metric
*tosp
;
205 register const rtrid_t
*ap
;
207 register const struct aslametric
*almp
;
208 register const struct mcla
*mcp
;
210 register const struct llsa
*llsap
;
211 register const struct lsa6_prefix
*lsapp
;
213 register const u_int32_t
*lp
;
215 register u_int prefixes
;
216 register int bytelen
;
217 register u_int length
, lsa_length
;
219 const u_int8_t
*tptr
;
221 if (ospf6_print_lshdr(&lsap
->ls_hdr
))
223 TCHECK(lsap
->ls_hdr
.ls_length
);
224 length
= EXTRACT_16BITS(&lsap
->ls_hdr
.ls_length
);
227 * The LSA length includes the length of the header;
228 * it must have a value that's at least that length.
229 * If it does, find the length of what follows the
232 if (length
< sizeof(struct lsa6_hdr
))
234 lsa_length
= length
- sizeof(struct lsa6_hdr
);
235 tptr
= (u_int8_t
*)lsap
+sizeof(struct lsa6_hdr
);
237 switch (EXTRACT_16BITS(&lsap
->ls_hdr
.ls_type
)) {
238 case LS_TYPE_ROUTER
| LS_SCOPE_AREA
:
239 if (lsa_length
< sizeof (lsap
->lsa_un
.un_rla
.rla_options
))
241 lsa_length
-= sizeof (lsap
->lsa_un
.un_rla
.rla_options
);
242 TCHECK(lsap
->lsa_un
.un_rla
.rla_options
);
243 printf("\n\t Options [%s]",
244 bittok2str(ospf6_option_values
, "none",
245 EXTRACT_32BITS(&lsap
->lsa_un
.un_rla
.rla_options
)));
246 printf(", RLA-Flags [%s]",
247 bittok2str(ospf6_rla_flag_values
, "none",
248 lsap
->lsa_un
.un_rla
.rla_flags
));
250 rlp
= lsap
->lsa_un
.un_rla
.rla_link
;
251 while (lsa_length
!= 0) {
252 if (lsa_length
< sizeof (*rlp
))
254 lsa_length
-= sizeof (*rlp
);
256 switch (rlp
->link_type
) {
258 case RLA_TYPE_VIRTUAL
:
259 printf("\n\t Virtual Link: Neighbor Router-ID %s"
260 "\n\t Neighbor Interface-ID %s, Interface %s",
261 ipaddr_string(&rlp
->link_nrtid
),
262 ipaddr_string(&rlp
->link_nifid
),
263 ipaddr_string(&rlp
->link_ifid
));
266 case RLA_TYPE_ROUTER
:
267 printf("\n\t Neighbor Router-ID %s"
268 "\n\t Neighbor Interface-ID %s, Interface %s",
269 ipaddr_string(&rlp
->link_nrtid
),
270 ipaddr_string(&rlp
->link_nifid
),
271 ipaddr_string(&rlp
->link_ifid
));
274 case RLA_TYPE_TRANSIT
:
275 printf("\n\t Neighbor Network-ID %s"
276 "\n\t Neighbor Interface-ID %s, Interface %s",
277 ipaddr_string(&rlp
->link_nrtid
),
278 ipaddr_string(&rlp
->link_nifid
),
279 ipaddr_string(&rlp
->link_ifid
));
283 printf("\n\t Unknown Router Links Type 0x%02x",
287 printf(", metric %d", EXTRACT_16BITS(&rlp
->link_metric
));
292 case LS_TYPE_NETWORK
| LS_SCOPE_AREA
:
293 if (lsa_length
< sizeof (lsap
->lsa_un
.un_nla
.nla_options
))
295 lsa_length
-= sizeof (lsap
->lsa_un
.un_nla
.nla_options
);
296 TCHECK(lsap
->lsa_un
.un_nla
.nla_options
);
297 printf("\n\t Options [%s]",
298 bittok2str(ospf6_option_values
, "none",
299 EXTRACT_32BITS(&lsap
->lsa_un
.un_nla
.nla_options
)));
301 printf("\n\t Connected Routers:");
302 ap
= lsap
->lsa_un
.un_nla
.nla_router
;
303 while (lsa_length
!= 0) {
304 if (lsa_length
< sizeof (*ap
))
306 lsa_length
-= sizeof (*ap
);
308 printf("\n\t\t%s", ipaddr_string(ap
));
313 case LS_TYPE_INTER_AP
| LS_SCOPE_AREA
:
314 if (lsa_length
< sizeof (lsap
->lsa_un
.un_inter_ap
.inter_ap_metric
))
316 lsa_length
-= sizeof (lsap
->lsa_un
.un_inter_ap
.inter_ap_metric
);
317 TCHECK(lsap
->lsa_un
.un_inter_ap
.inter_ap_metric
);
318 printf(", metric %u",
319 EXTRACT_32BITS(&lsap
->lsa_un
.un_inter_ap
.inter_ap_metric
) & SLA_MASK_METRIC
);
321 tptr
= (u_int8_t
*)lsap
->lsa_un
.un_inter_ap
.inter_ap_prefix
;
322 while (lsa_length
!= 0) {
323 bytelen
= ospf6_print_lsaprefix(tptr
, lsa_length
);
326 lsa_length
-= bytelen
;
331 case LS_TYPE_ASE
| LS_SCOPE_AS
:
332 if (lsa_length
< sizeof (lsap
->lsa_un
.un_asla
.asla_metric
))
334 lsa_length
-= sizeof (lsap
->lsa_un
.un_asla
.asla_metric
);
335 TCHECK(lsap
->lsa_un
.un_asla
.asla_metric
);
336 flags32
= EXTRACT_32BITS(&lsap
->lsa_un
.un_asla
.asla_metric
);
337 printf("\n\t Flags [%s]",
338 bittok2str(ospf6_asla_flag_values
, "none", flags32
));
340 EXTRACT_32BITS(&lsap
->lsa_un
.un_asla
.asla_metric
) &
343 tptr
= (u_int8_t
*)lsap
->lsa_un
.un_asla
.asla_prefix
;
344 lsapp
= (struct lsa6_prefix
*)tptr
;
345 bytelen
= ospf6_print_lsaprefix(tptr
, lsa_length
);
348 lsa_length
-= bytelen
;
351 if ((flags32
& ASLA_FLAG_FWDADDR
) != 0) {
352 struct in6_addr
*fwdaddr6
;
354 fwdaddr6
= (struct in6_addr
*)tptr
;
355 if (lsa_length
< sizeof (*fwdaddr6
))
357 lsa_length
-= sizeof (*fwdaddr6
);
359 printf(" forward %s",
360 ip6addr_string(fwdaddr6
));
361 tptr
+= sizeof(*fwdaddr6
);
364 if ((flags32
& ASLA_FLAG_ROUTETAG
) != 0) {
365 if (lsa_length
< sizeof (u_int32_t
))
367 lsa_length
-= sizeof (u_int32_t
);
368 TCHECK(*(u_int32_t
*)tptr
);
370 ipaddr_string((u_int32_t
*)tptr
));
371 tptr
+= sizeof(u_int32_t
);
374 if (lsapp
->lsa_p_metric
) {
375 if (lsa_length
< sizeof (u_int32_t
))
377 lsa_length
-= sizeof (u_int32_t
);
378 TCHECK(*(u_int32_t
*)tptr
);
379 printf(" RefLSID: %s",
380 ipaddr_string((u_int32_t
*)tptr
));
381 tptr
+= sizeof(u_int32_t
);
387 llsap
= &lsap
->lsa_un
.un_llsa
;
388 if (lsa_length
< sizeof (llsap
->llsa_priandopt
))
390 lsa_length
-= sizeof (llsap
->llsa_priandopt
);
391 TCHECK(llsap
->llsa_priandopt
);
392 printf("\n\t Options [%s]",
393 bittok2str(ospf6_option_values
, "none",
394 EXTRACT_32BITS(&llsap
->llsa_options
)));
396 if (lsa_length
< sizeof (llsap
->llsa_lladdr
) + sizeof (llsap
->llsa_nprefix
))
398 lsa_length
-= sizeof (llsap
->llsa_lladdr
) + sizeof (llsap
->llsa_nprefix
);
399 prefixes
= EXTRACT_32BITS(&llsap
->llsa_nprefix
);
400 printf("\n\t Priority %d, Link-local address %s, Prefixes %d:",
401 llsap
->llsa_priority
,
402 ip6addr_string(&llsap
->llsa_lladdr
),
405 tptr
= (u_int8_t
*)llsap
->llsa_prefix
;
406 while (prefixes
> 0) {
407 bytelen
= ospf6_print_lsaprefix(tptr
, lsa_length
);
411 lsa_length
-= bytelen
;
416 case LS_TYPE_INTRA_AP
| LS_SCOPE_AREA
:
417 /* Intra-Area-Prefix LSA */
418 if (lsa_length
< sizeof (lsap
->lsa_un
.un_intra_ap
.intra_ap_rtid
))
420 lsa_length
-= sizeof (lsap
->lsa_un
.un_intra_ap
.intra_ap_rtid
);
421 TCHECK(lsap
->lsa_un
.un_intra_ap
.intra_ap_rtid
);
423 EXTRACT_16BITS(&lsap
->lsa_un
.un_intra_ap
.intra_ap_lstype
),
424 &lsap
->lsa_un
.un_intra_ap
.intra_ap_lsid
);
426 if (lsa_length
< sizeof (lsap
->lsa_un
.un_intra_ap
.intra_ap_nprefix
))
428 lsa_length
-= sizeof (lsap
->lsa_un
.un_intra_ap
.intra_ap_nprefix
);
429 TCHECK(lsap
->lsa_un
.un_intra_ap
.intra_ap_nprefix
);
430 prefixes
= EXTRACT_16BITS(&lsap
->lsa_un
.un_intra_ap
.intra_ap_nprefix
);
431 printf("\n\t Prefixes %d:", prefixes
);
433 tptr
= (u_int8_t
*)lsap
->lsa_un
.un_intra_ap
.intra_ap_prefix
;
434 while (prefixes
> 0) {
435 bytelen
= ospf6_print_lsaprefix(tptr
, lsa_length
);
439 lsa_length
-= bytelen
;
444 case LS_TYPE_GRACE
| LS_SCOPE_LINKLOCAL
:
445 if (ospf_print_grace_lsa(tptr
, lsa_length
) == -1) {
450 case LS_TYPE_INTRA_ATE
| LS_SCOPE_LINKLOCAL
:
451 if (ospf_print_te_lsa(tptr
, lsa_length
) == -1) {
457 if(!print_unknown_data(tptr
,
471 ospf6_decode_v3(register const struct ospf6hdr
*op
,
472 register const u_char
*dataend
)
474 register const rtrid_t
*ap
;
475 register const struct lsr6
*lsrp
;
476 register const struct lsa6_hdr
*lshp
;
477 register const struct lsa6
*lsap
;
480 switch (op
->ospf6_type
) {
482 case OSPF_TYPE_HELLO
:
483 printf("\n\tOptions [%s]",
484 bittok2str(ospf6_option_values
, "none",
485 EXTRACT_32BITS(&op
->ospf6_hello
.hello_options
)));
487 TCHECK(op
->ospf6_hello
.hello_deadint
);
488 printf("\n\t Hello Timer %us, Dead Timer %us, Interface-ID %s, Priority %u",
489 EXTRACT_16BITS(&op
->ospf6_hello
.hello_helloint
),
490 EXTRACT_16BITS(&op
->ospf6_hello
.hello_deadint
),
491 ipaddr_string(&op
->ospf6_hello
.hello_ifid
),
492 op
->ospf6_hello
.hello_priority
);
494 TCHECK(op
->ospf6_hello
.hello_dr
);
495 if (op
->ospf6_hello
.hello_dr
!= 0)
496 printf("\n\t Designated Router %s",
497 ipaddr_string(&op
->ospf6_hello
.hello_dr
));
498 TCHECK(op
->ospf6_hello
.hello_bdr
);
499 if (op
->ospf6_hello
.hello_bdr
!= 0)
500 printf(", Backup Designated Router %s",
501 ipaddr_string(&op
->ospf6_hello
.hello_bdr
));
503 printf("\n\t Neighbor List:");
504 ap
= op
->ospf6_hello
.hello_neighbor
;
505 while ((u_char
*)ap
< dataend
) {
507 printf("\n\t %s", ipaddr_string(ap
));
514 TCHECK(op
->ospf6_db
.db_options
);
515 printf("\n\tOptions [%s]",
516 bittok2str(ospf6_option_values
, "none",
517 EXTRACT_32BITS(&op
->ospf6_db
.db_options
)));
518 TCHECK(op
->ospf6_db
.db_flags
);
519 printf(", DD Flags [%s]",
520 bittok2str(ospf6_dd_flag_values
,"none",op
->ospf6_db
.db_flags
));
522 TCHECK(op
->ospf6_db
.db_seq
);
523 printf(", MTU %u, DD-Sequence 0x%08x",
524 EXTRACT_16BITS(&op
->ospf6_db
.db_mtu
),
525 EXTRACT_32BITS(&op
->ospf6_db
.db_seq
));
527 /* Print all the LS adv's */
528 lshp
= op
->ospf6_db
.db_lshdr
;
529 while (!ospf6_print_lshdr(lshp
)) {
534 case OSPF_TYPE_LS_REQ
:
536 lsrp
= op
->ospf6_lsr
;
537 while ((u_char
*)lsrp
< dataend
) {
539 printf("\n\t Advertising Router %s",
540 ipaddr_string(&lsrp
->ls_router
));
541 ospf6_print_ls_type(EXTRACT_16BITS(&lsrp
->ls_type
),
548 case OSPF_TYPE_LS_UPDATE
:
550 lsap
= op
->ospf6_lsu
.lsu_lsa
;
551 TCHECK(op
->ospf6_lsu
.lsu_count
);
552 i
= EXTRACT_32BITS(&op
->ospf6_lsu
.lsu_count
);
554 if (ospf6_print_lsa(lsap
))
556 lsap
= (struct lsa6
*)((u_char
*)lsap
+
557 EXTRACT_16BITS(&lsap
->ls_hdr
.ls_length
));
563 case OSPF_TYPE_LS_ACK
:
565 lshp
= op
->ospf6_lsa
.lsa_lshdr
;
567 while (!ospf6_print_lshdr(lshp
)) {
582 ospf6_print(register const u_char
*bp
, register u_int length
)
584 register const struct ospf6hdr
*op
;
585 register const u_char
*dataend
;
586 register const char *cp
;
588 op
= (struct ospf6hdr
*)bp
;
590 /* If the type is valid translate it, or just print the type */
591 /* value. If it's not valid, say so and return */
592 TCHECK(op
->ospf6_type
);
593 cp
= tok2str(ospf6_type_values
, "unknown LS-type", op
->ospf6_type
);
594 printf("OSPFv%u, %s, length %d", op
->ospf6_version
, cp
, length
);
599 if(!vflag
) { /* non verbose - so lets bail out here */
603 TCHECK(op
->ospf6_len
);
604 if (length
!= EXTRACT_16BITS(&op
->ospf6_len
)) {
605 printf(" [len %d]", EXTRACT_16BITS(&op
->ospf6_len
));
608 dataend
= bp
+ length
;
610 /* Print the routerid if it is not the same as the source */
611 TCHECK(op
->ospf6_routerid
);
612 printf("\n\tRouter-ID %s", ipaddr_string(&op
->ospf6_routerid
));
614 TCHECK(op
->ospf6_areaid
);
615 if (op
->ospf6_areaid
!= 0)
616 printf(", Area %s", ipaddr_string(&op
->ospf6_areaid
));
618 printf(", Backbone Area");
619 TCHECK(op
->ospf6_instanceid
);
620 if (op
->ospf6_instanceid
)
621 printf(", Instance %u", op
->ospf6_instanceid
);
623 /* Do rest according to version. */
624 switch (op
->ospf6_version
) {
628 if (ospf6_decode_v3(op
, dataend
))
633 printf(" ospf [version %d]", op
->ospf6_version
);
635 } /* end switch on version */