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