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