print-ospf6.c revision 1.12 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 (at) mitchell.cit.cornell.edu)
22 */
23
24 #include <sys/cdefs.h>
25 #ifndef lint
26 __RCSID("$NetBSD: print-ospf6.c,v 1.12 2024/09/02 16:15:32 christos Exp $");
27 #endif
28
29 /* \summary: IPv6 Open Shortest Path First (OSPFv3) printer */
30
31 #include <config.h>
32
33 #include "netdissect-stdinc.h"
34
35 #include <string.h>
36
37 #include "netdissect.h"
38 #include "addrtoname.h"
39 #include "extract.h"
40
41 #include "ospf.h"
42
43 #define OSPF_TYPE_HELLO 1 /* Hello */
44 #define OSPF_TYPE_DD 2 /* Database Description */
45 #define OSPF_TYPE_LS_REQ 3 /* Link State Request */
46 #define OSPF_TYPE_LS_UPDATE 4 /* Link State Update */
47 #define OSPF_TYPE_LS_ACK 5 /* Link State Ack */
48
49 /* Options *_options */
50 #define OSPF6_OPTION_V6 0x01 /* V6 bit: A bit for peeping tom */
51 #define OSPF6_OPTION_E 0x02 /* E bit: External routes advertised */
52 #define OSPF6_OPTION_MC 0x04 /* MC bit: Multicast capable */
53 #define OSPF6_OPTION_N 0x08 /* N bit: For type-7 LSA */
54 #define OSPF6_OPTION_R 0x10 /* R bit: Router bit */
55 #define OSPF6_OPTION_DC 0x20 /* DC bit: Demand circuits */
56 /* The field is actually 24-bit (RFC5340 Section A.2). */
57 #define OSPF6_OPTION_AF 0x0100 /* AF bit: Multiple address families */
58 #define OSPF6_OPTION_L 0x0200 /* L bit: Link-local signaling (LLS) */
59 #define OSPF6_OPTION_AT 0x0400 /* AT bit: Authentication trailer */
60
61
62 /* db_flags */
63 #define OSPF6_DB_INIT 0x04 /* */
64 #define OSPF6_DB_MORE 0x02
65 #define OSPF6_DB_MASTER 0x01
66 #define OSPF6_DB_M6 0x10 /* IPv6 MTU */
67
68 /* ls_type */
69 #define LS_TYPE_ROUTER 1 /* router link */
70 #define LS_TYPE_NETWORK 2 /* network link */
71 #define LS_TYPE_INTER_AP 3 /* Inter-Area-Prefix */
72 #define LS_TYPE_INTER_AR 4 /* Inter-Area-Router */
73 #define LS_TYPE_ASE 5 /* ASE */
74 #define LS_TYPE_GROUP 6 /* Group membership */
75 #define LS_TYPE_NSSA 7 /* NSSA */
76 #define LS_TYPE_LINK 8 /* Link LSA */
77 #define LS_TYPE_INTRA_AP 9 /* Intra-Area-Prefix */
78 #define LS_TYPE_INTRA_ATE 10 /* Intra-Area-TE */
79 #define LS_TYPE_GRACE 11 /* Grace LSA */
80 #define LS_TYPE_RI 12 /* Router information */
81 #define LS_TYPE_INTER_ASTE 13 /* Inter-AS-TE */
82 #define LS_TYPE_L1VPN 14 /* L1VPN */
83 #define LS_TYPE_MASK 0x1fff
84
85 #define LS_SCOPE_LINKLOCAL 0x0000
86 #define LS_SCOPE_AREA 0x2000
87 #define LS_SCOPE_AS 0x4000
88 #define LS_SCOPE_MASK 0x6000
89 #define LS_SCOPE_U 0x8000
90
91 /* rla_link.link_type */
92 #define RLA_TYPE_ROUTER 1 /* point-to-point to another router */
93 #define RLA_TYPE_TRANSIT 2 /* connection to transit network */
94 #define RLA_TYPE_VIRTUAL 4 /* virtual link */
95
96 /* rla_flags */
97 #define RLA_FLAG_B 0x01
98 #define RLA_FLAG_E 0x02
99 #define RLA_FLAG_V 0x04
100 #define RLA_FLAG_W 0x08
101 #define RLA_FLAG_Nt 0x10
102
103 /* lsa_prefix options */
104 #define LSA_PREFIX_OPT_NU 0x01
105 #define LSA_PREFIX_OPT_LA 0x02
106 #define LSA_PREFIX_OPT_MC 0x04
107 #define LSA_PREFIX_OPT_P 0x08
108 #define LSA_PREFIX_OPT_DN 0x10
109 #define LSA_PREFIX_OPT_N 0x20
110
111 /* sla_tosmetric breakdown */
112 #define SLA_MASK_TOS 0x7f000000
113 #define SLA_MASK_METRIC 0x00ffffff
114 #define SLA_SHIFT_TOS 24
115
116 /* asla_metric */
117 #define ASLA_FLAG_FWDADDR 0x02000000
118 #define ASLA_FLAG_ROUTETAG 0x01000000
119 #define ASLA_MASK_METRIC 0x00ffffff
120
121 /* RFC6506 Section 4.1 */
122 #define OSPF6_AT_HDRLEN 16U
123 #define OSPF6_AUTH_TYPE_HMAC 0x0001
124
125 typedef nd_uint32_t rtrid_t;
126
127 /* link state advertisement header */
128 struct lsa6_hdr {
129 nd_uint16_t ls_age;
130 nd_uint16_t ls_type;
131 rtrid_t ls_stateid;
132 rtrid_t ls_router;
133 nd_uint32_t ls_seq;
134 nd_uint16_t ls_chksum;
135 nd_uint16_t ls_length;
136 };
137
138 /* Length of an IPv6 address, in bytes. */
139 #define IPV6_ADDR_LEN_BYTES (128/8)
140
141 struct lsa6_prefix {
142 nd_uint8_t lsa_p_len;
143 nd_uint8_t lsa_p_opt;
144 nd_uint16_t lsa_p_metric;
145 nd_byte lsa_p_prefix[IPV6_ADDR_LEN_BYTES]; /* maximum length */
146 };
147
148 /* link state advertisement */
149 struct lsa6 {
150 struct lsa6_hdr ls_hdr;
151
152 /* Link state types */
153 union {
154 /* Router links advertisements */
155 struct {
156 union {
157 nd_uint8_t flg;
158 nd_uint32_t opt;
159 } rla_flgandopt;
160 #define rla_flags rla_flgandopt.flg
161 #define rla_options rla_flgandopt.opt
162 struct rlalink6 {
163 nd_uint8_t link_type;
164 nd_byte link_zero;
165 nd_uint16_t link_metric;
166 nd_uint32_t link_ifid;
167 nd_uint32_t link_nifid;
168 rtrid_t link_nrtid;
169 } rla_link[1]; /* may repeat */
170 } un_rla;
171
172 /* Network links advertisements */
173 struct {
174 nd_uint32_t nla_options;
175 rtrid_t nla_router[1]; /* may repeat */
176 } un_nla;
177
178 /* Inter Area Prefix LSA */
179 struct {
180 nd_uint32_t inter_ap_metric;
181 struct lsa6_prefix inter_ap_prefix[1];
182 } un_inter_ap;
183
184 /* AS external links advertisements */
185 struct {
186 nd_uint32_t asla_metric;
187 struct lsa6_prefix asla_prefix[1];
188 /* some optional fields follow */
189 } un_asla;
190
191 #if 0
192 /* Summary links advertisements */
193 struct {
194 nd_ipv4 sla_mask;
195 nd_uint32_t sla_tosmetric[1]; /* may repeat */
196 } un_sla;
197
198 /* Multicast group membership */
199 struct mcla {
200 nd_uint32_t mcla_vtype;
201 nd_ipv4 mcla_vid;
202 } un_mcla[1];
203 #endif
204
205 /* Type 7 LSA */
206
207 /* Link LSA */
208 struct llsa {
209 union {
210 nd_uint8_t pri;
211 nd_uint32_t opt;
212 } llsa_priandopt;
213 #define llsa_priority llsa_priandopt.pri
214 #define llsa_options llsa_priandopt.opt
215 nd_ipv6 llsa_lladdr;
216 nd_uint32_t llsa_nprefix;
217 struct lsa6_prefix llsa_prefix[1];
218 } un_llsa;
219
220 /* Intra-Area-Prefix */
221 struct {
222 nd_uint16_t intra_ap_nprefix;
223 nd_uint16_t intra_ap_lstype;
224 rtrid_t intra_ap_lsid;
225 rtrid_t intra_ap_rtid;
226 struct lsa6_prefix intra_ap_prefix[1];
227 } un_intra_ap;
228 } lsa_un;
229 };
230
231 /*
232 * the main header
233 */
234 struct ospf6hdr {
235 nd_uint8_t ospf6_version;
236 nd_uint8_t ospf6_type;
237 nd_uint16_t ospf6_len;
238 rtrid_t ospf6_routerid;
239 rtrid_t ospf6_areaid;
240 nd_uint16_t ospf6_chksum;
241 nd_uint8_t ospf6_instanceid;
242 nd_uint8_t ospf6_rsvd;
243 };
244
245 /*
246 * The OSPF6 header length is 16 bytes, regardless of how your compiler
247 * might choose to pad the above structure.
248 */
249 #define OSPF6HDR_LEN 16
250
251 /* Hello packet */
252 struct hello6 {
253 nd_uint32_t hello_ifid;
254 union {
255 nd_uint8_t pri;
256 nd_uint32_t opt;
257 } hello_priandopt;
258 #define hello_priority hello_priandopt.pri
259 #define hello_options hello_priandopt.opt
260 nd_uint16_t hello_helloint;
261 nd_uint16_t hello_deadint;
262 rtrid_t hello_dr;
263 rtrid_t hello_bdr;
264 rtrid_t hello_neighbor[1]; /* may repeat */
265 };
266
267 /* Database Description packet */
268 struct dd6 {
269 nd_uint32_t db_options;
270 nd_uint16_t db_mtu;
271 nd_uint8_t db_mbz;
272 nd_uint8_t db_flags;
273 nd_uint32_t db_seq;
274 struct lsa6_hdr db_lshdr[1]; /* may repeat */
275 };
276
277 /* Link State Request */
278 struct lsr6 {
279 nd_uint16_t ls_mbz;
280 nd_uint16_t ls_type;
281 rtrid_t ls_stateid;
282 rtrid_t ls_router;
283 };
284
285 /* Link State Update */
286 struct lsu6 {
287 nd_uint32_t lsu_count;
288 struct lsa6 lsu_lsa[1]; /* may repeat */
289 };
290
291
292 static const struct tok ospf6_option_values[] = {
293 { OSPF6_OPTION_V6, "V6" },
294 { OSPF6_OPTION_E, "External" },
295 { OSPF6_OPTION_MC, "Deprecated" },
296 { OSPF6_OPTION_N, "NSSA" },
297 { OSPF6_OPTION_R, "Router" },
298 { OSPF6_OPTION_DC, "Demand Circuit" },
299 { OSPF6_OPTION_AF, "AFs Support" },
300 { OSPF6_OPTION_L, "LLS" },
301 { OSPF6_OPTION_AT, "Authentication Trailer" },
302 { 0, NULL }
303 };
304
305 static const struct tok ospf6_rla_flag_values[] = {
306 { RLA_FLAG_B, "ABR" },
307 { RLA_FLAG_E, "External" },
308 { RLA_FLAG_V, "Virtual-Link Endpoint" },
309 { RLA_FLAG_W, "Deprecated" },
310 { RLA_FLAG_Nt, "NSSA Translator" },
311 { 0, NULL }
312 };
313
314 static const struct tok ospf6_asla_flag_values[] = {
315 { ASLA_FLAG_EXTERNAL, "External Type 2" },
316 { ASLA_FLAG_FWDADDR, "Forwarding" },
317 { ASLA_FLAG_ROUTETAG, "Tag" },
318 { 0, NULL }
319 };
320
321 static const struct tok ospf6_type_values[] = {
322 { OSPF_TYPE_HELLO, "Hello" },
323 { OSPF_TYPE_DD, "Database Description" },
324 { OSPF_TYPE_LS_REQ, "LS-Request" },
325 { OSPF_TYPE_LS_UPDATE, "LS-Update" },
326 { OSPF_TYPE_LS_ACK, "LS-Ack" },
327 { 0, NULL }
328 };
329
330 static const struct tok ospf6_lsa_values[] = {
331 { LS_TYPE_ROUTER, "Router" },
332 { LS_TYPE_NETWORK, "Network" },
333 { LS_TYPE_INTER_AP, "Inter-Area Prefix" },
334 { LS_TYPE_INTER_AR, "Inter-Area Router" },
335 { LS_TYPE_ASE, "External" },
336 { LS_TYPE_GROUP, "Deprecated" },
337 { LS_TYPE_NSSA, "NSSA" },
338 { LS_TYPE_LINK, "Link" },
339 { LS_TYPE_INTRA_AP, "Intra-Area Prefix" },
340 { LS_TYPE_INTRA_ATE, "Intra-Area TE" },
341 { LS_TYPE_GRACE, "Grace" },
342 { LS_TYPE_RI, "Router Information" },
343 { LS_TYPE_INTER_ASTE, "Inter-AS-TE" },
344 { LS_TYPE_L1VPN, "Layer 1 VPN" },
345 { 0, NULL }
346 };
347
348 static const struct tok ospf6_ls_scope_values[] = {
349 { LS_SCOPE_LINKLOCAL, "Link Local" },
350 { LS_SCOPE_AREA, "Area Local" },
351 { LS_SCOPE_AS, "Domain Wide" },
352 { 0, NULL }
353 };
354
355 static const struct tok ospf6_dd_flag_values[] = {
356 { OSPF6_DB_INIT, "Init" },
357 { OSPF6_DB_MORE, "More" },
358 { OSPF6_DB_MASTER, "Master" },
359 { OSPF6_DB_M6, "IPv6 MTU" },
360 { 0, NULL }
361 };
362
363 static const struct tok ospf6_lsa_prefix_option_values[] = {
364 { LSA_PREFIX_OPT_NU, "No Unicast" },
365 { LSA_PREFIX_OPT_LA, "Local address" },
366 { LSA_PREFIX_OPT_MC, "Deprecated" },
367 { LSA_PREFIX_OPT_P, "Propagate" },
368 { LSA_PREFIX_OPT_DN, "Down" },
369 { LSA_PREFIX_OPT_N, "N-bit" },
370 { 0, NULL }
371 };
372
373 static const struct tok ospf6_auth_type_str[] = {
374 { OSPF6_AUTH_TYPE_HMAC, "HMAC" },
375 { 0, NULL }
376 };
377
378 static void
379 ospf6_print_ls_type(netdissect_options *ndo,
380 u_int ls_type, const rtrid_t *ls_stateid)
381 {
382 ND_PRINT("\n\t %s LSA (%u), %s Scope%s, LSA-ID %s",
383 tok2str(ospf6_lsa_values, "Unknown", ls_type & LS_TYPE_MASK),
384 ls_type & LS_TYPE_MASK,
385 tok2str(ospf6_ls_scope_values, "Unknown", ls_type & LS_SCOPE_MASK),
386 ls_type &0x8000 ? ", transitive" : "", /* U-bit */
387 GET_IPADDR_STRING(ls_stateid));
388 }
389
390 UNALIGNED_OK
391 static int
392 ospf6_print_lshdr(netdissect_options *ndo,
393 const struct lsa6_hdr *lshp, const u_char *dataend)
394 {
395 u_int ls_length;
396
397 if ((const u_char *)(lshp + 1) > dataend)
398 goto trunc;
399
400 ls_length = GET_BE_U_2(lshp->ls_length);
401 if (ls_length < sizeof(struct lsa_hdr)) {
402 ND_PRINT("\n\t Bogus length %u < header (%zu)", ls_length,
403 sizeof(struct lsa_hdr));
404 goto trunc;
405 }
406
407 ND_PRINT("\n\t Advertising Router %s, seq 0x%08x, age %us, length %zu",
408 GET_IPADDR_STRING(lshp->ls_router),
409 GET_BE_U_4(lshp->ls_seq),
410 GET_BE_U_2(lshp->ls_age),
411 ls_length-sizeof(struct lsa6_hdr));
412
413 ospf6_print_ls_type(ndo, GET_BE_U_2(lshp->ls_type),
414 &lshp->ls_stateid);
415
416 return (0);
417 trunc:
418 return (1);
419 }
420
421 static int
422 ospf6_print_lsaprefix(netdissect_options *ndo,
423 const uint8_t *tptr, u_int lsa_length)
424 {
425 const struct lsa6_prefix *lsapp = (const struct lsa6_prefix *)tptr;
426 u_int wordlen;
427 nd_ipv6 prefix;
428
429 if (lsa_length < sizeof (*lsapp) - IPV6_ADDR_LEN_BYTES)
430 goto trunc;
431 lsa_length -= sizeof (*lsapp) - IPV6_ADDR_LEN_BYTES;
432 ND_TCHECK_LEN(lsapp, sizeof(*lsapp) - IPV6_ADDR_LEN_BYTES);
433 wordlen = (GET_U_1(lsapp->lsa_p_len) + 31) / 32;
434 if (wordlen * 4 > sizeof(nd_ipv6)) {
435 ND_PRINT(" bogus prefixlen /%u", GET_U_1(lsapp->lsa_p_len));
436 goto trunc;
437 }
438 if (lsa_length < wordlen * 4)
439 goto trunc;
440 lsa_length -= wordlen * 4;
441 memset(prefix, 0, sizeof(prefix));
442 GET_CPY_BYTES(prefix, lsapp->lsa_p_prefix, wordlen * 4);
443 ND_PRINT("\n\t\t%s/%u", ip6addr_string(ndo, prefix), /* local buffer, not packet data; don't use GET_IP6ADDR_STRING() */
444 GET_U_1(lsapp->lsa_p_len));
445 if (GET_U_1(lsapp->lsa_p_opt)) {
446 ND_PRINT(", Options [%s]",
447 bittok2str(ospf6_lsa_prefix_option_values,
448 "none", GET_U_1(lsapp->lsa_p_opt)));
449 }
450 ND_PRINT(", metric %u", GET_BE_U_2(lsapp->lsa_p_metric));
451 return sizeof(*lsapp) - IPV6_ADDR_LEN_BYTES + wordlen * 4;
452
453 trunc:
454 return -1;
455 }
456
457
458 /*
459 * Print a single link state advertisement. If truncated return 1, else 0.
460 */
461 UNALIGNED_OK
462 static int
463 ospf6_print_lsa(netdissect_options *ndo,
464 const struct lsa6 *lsap, const u_char *dataend)
465 {
466 const struct rlalink6 *rlp;
467 #if 0
468 const struct tos_metric *tosp;
469 #endif
470 const rtrid_t *ap;
471 #if 0
472 const struct aslametric *almp;
473 const struct mcla *mcp;
474 #endif
475 const struct llsa *llsap;
476 const struct lsa6_prefix *lsapp;
477 #if 0
478 const uint32_t *lp;
479 #endif
480 u_int prefixes;
481 int bytelen;
482 u_int length, lsa_length;
483 uint32_t flags32;
484 const uint8_t *tptr;
485
486 if (ospf6_print_lshdr(ndo, &lsap->ls_hdr, dataend))
487 return (1);
488 length = GET_BE_U_2(lsap->ls_hdr.ls_length);
489
490 /*
491 * The LSA length includes the length of the header;
492 * it must have a value that's at least that length.
493 * If it does, find the length of what follows the
494 * header.
495 */
496 if (length < sizeof(struct lsa6_hdr) || (const u_char *)lsap + length > dataend)
497 return (1);
498 lsa_length = length - sizeof(struct lsa6_hdr);
499 tptr = (const uint8_t *)lsap+sizeof(struct lsa6_hdr);
500
501 switch (GET_BE_U_2(lsap->ls_hdr.ls_type)) {
502 case LS_TYPE_ROUTER | LS_SCOPE_AREA:
503 if (lsa_length < sizeof (lsap->lsa_un.un_rla.rla_options))
504 return (1);
505 lsa_length -= sizeof (lsap->lsa_un.un_rla.rla_options);
506 ND_PRINT("\n\t Options [%s]",
507 bittok2str(ospf6_option_values, "none",
508 GET_BE_U_4(lsap->lsa_un.un_rla.rla_options)));
509 ND_PRINT(", RLA-Flags [%s]",
510 bittok2str(ospf6_rla_flag_values, "none",
511 GET_U_1(lsap->lsa_un.un_rla.rla_flags)));
512
513 rlp = lsap->lsa_un.un_rla.rla_link;
514 while (lsa_length != 0) {
515 if (lsa_length < sizeof (*rlp))
516 return (1);
517 lsa_length -= sizeof (*rlp);
518 ND_TCHECK_SIZE(rlp);
519 switch (GET_U_1(rlp->link_type)) {
520
521 case RLA_TYPE_VIRTUAL:
522 ND_PRINT("\n\t Virtual Link: Neighbor Router-ID %s"
523 "\n\t Neighbor Interface-ID %s, Interface %s",
524 GET_IPADDR_STRING(rlp->link_nrtid),
525 GET_IPADDR_STRING(rlp->link_nifid),
526 GET_IPADDR_STRING(rlp->link_ifid));
527 break;
528
529 case RLA_TYPE_ROUTER:
530 ND_PRINT("\n\t Neighbor Router-ID %s"
531 "\n\t Neighbor Interface-ID %s, Interface %s",
532 GET_IPADDR_STRING(rlp->link_nrtid),
533 GET_IPADDR_STRING(rlp->link_nifid),
534 GET_IPADDR_STRING(rlp->link_ifid));
535 break;
536
537 case RLA_TYPE_TRANSIT:
538 ND_PRINT("\n\t Neighbor Network-ID %s"
539 "\n\t Neighbor Interface-ID %s, Interface %s",
540 GET_IPADDR_STRING(rlp->link_nrtid),
541 GET_IPADDR_STRING(rlp->link_nifid),
542 GET_IPADDR_STRING(rlp->link_ifid));
543 break;
544
545 default:
546 ND_PRINT("\n\t Unknown Router Links Type 0x%02x",
547 GET_U_1(rlp->link_type));
548 return (0);
549 }
550 ND_PRINT(", metric %u", GET_BE_U_2(rlp->link_metric));
551 rlp++;
552 }
553 break;
554
555 case LS_TYPE_NETWORK | LS_SCOPE_AREA:
556 if (lsa_length < sizeof (lsap->lsa_un.un_nla.nla_options))
557 return (1);
558 lsa_length -= sizeof (lsap->lsa_un.un_nla.nla_options);
559 ND_PRINT("\n\t Options [%s]",
560 bittok2str(ospf6_option_values, "none",
561 GET_BE_U_4(lsap->lsa_un.un_nla.nla_options)));
562
563 ND_PRINT("\n\t Connected Routers:");
564 ap = lsap->lsa_un.un_nla.nla_router;
565 while (lsa_length != 0) {
566 if (lsa_length < sizeof (*ap))
567 return (1);
568 lsa_length -= sizeof (*ap);
569 ND_PRINT("\n\t\t%s", GET_IPADDR_STRING(ap));
570 ++ap;
571 }
572 break;
573
574 case LS_TYPE_INTER_AP | LS_SCOPE_AREA:
575 if (lsa_length < sizeof (lsap->lsa_un.un_inter_ap.inter_ap_metric))
576 return (1);
577 lsa_length -= sizeof (lsap->lsa_un.un_inter_ap.inter_ap_metric);
578 ND_PRINT(", metric %u",
579 GET_BE_U_4(lsap->lsa_un.un_inter_ap.inter_ap_metric) & SLA_MASK_METRIC);
580
581 tptr = (const uint8_t *)lsap->lsa_un.un_inter_ap.inter_ap_prefix;
582 while (lsa_length != 0) {
583 bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length);
584 if (bytelen < 0)
585 goto trunc;
586 /*
587 * ospf6_print_lsaprefix() will return -1 if
588 * the length is too high, so this will not
589 * underflow.
590 */
591 lsa_length -= bytelen;
592 tptr += bytelen;
593 }
594 break;
595
596 case LS_TYPE_ASE | LS_SCOPE_AS:
597 if (lsa_length < sizeof (lsap->lsa_un.un_asla.asla_metric))
598 return (1);
599 lsa_length -= sizeof (lsap->lsa_un.un_asla.asla_metric);
600 flags32 = GET_BE_U_4(lsap->lsa_un.un_asla.asla_metric);
601 ND_PRINT("\n\t Flags [%s]",
602 bittok2str(ospf6_asla_flag_values, "none", flags32));
603 ND_PRINT(" metric %u",
604 GET_BE_U_4(lsap->lsa_un.un_asla.asla_metric) &
605 ASLA_MASK_METRIC);
606
607 tptr = (const uint8_t *)lsap->lsa_un.un_asla.asla_prefix;
608 lsapp = (const struct lsa6_prefix *)tptr;
609 bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length);
610 if (bytelen < 0)
611 goto trunc;
612 /*
613 * ospf6_print_lsaprefix() will return -1 if
614 * the length is too high, so this will not
615 * underflow.
616 */
617 lsa_length -= bytelen;
618 tptr += bytelen;
619
620 if ((flags32 & ASLA_FLAG_FWDADDR) != 0) {
621 if (lsa_length < sizeof (nd_ipv6))
622 return (1);
623 lsa_length -= sizeof (nd_ipv6);
624 ND_PRINT(" forward %s",
625 GET_IP6ADDR_STRING(tptr));
626 tptr += sizeof(nd_ipv6);
627 }
628
629 if ((flags32 & ASLA_FLAG_ROUTETAG) != 0) {
630 if (lsa_length < sizeof (uint32_t))
631 return (1);
632 lsa_length -= sizeof (uint32_t);
633 ND_PRINT(" tag %s",
634 GET_IPADDR_STRING(tptr));
635 tptr += sizeof(uint32_t);
636 }
637
638 if (GET_U_1(lsapp->lsa_p_metric)) {
639 if (lsa_length < sizeof (uint32_t))
640 return (1);
641 lsa_length -= sizeof (uint32_t);
642 ND_PRINT(" RefLSID: %s",
643 GET_IPADDR_STRING(tptr));
644 tptr += sizeof(uint32_t);
645 }
646 break;
647
648 case LS_TYPE_LINK:
649 /* Link LSA */
650 llsap = &lsap->lsa_un.un_llsa;
651 if (lsa_length < sizeof (llsap->llsa_priandopt))
652 return (1);
653 lsa_length -= sizeof (llsap->llsa_priandopt);
654 ND_TCHECK_SIZE(&llsap->llsa_priandopt);
655 ND_PRINT("\n\t Options [%s]",
656 bittok2str(ospf6_option_values, "none",
657 GET_BE_U_4(llsap->llsa_options)));
658
659 if (lsa_length < sizeof (llsap->llsa_lladdr) + sizeof (llsap->llsa_nprefix))
660 return (1);
661 lsa_length -= sizeof (llsap->llsa_lladdr) + sizeof (llsap->llsa_nprefix);
662 prefixes = GET_BE_U_4(llsap->llsa_nprefix);
663 ND_PRINT("\n\t Priority %u, Link-local address %s, Prefixes %u:",
664 GET_U_1(llsap->llsa_priority),
665 GET_IP6ADDR_STRING(llsap->llsa_lladdr),
666 prefixes);
667
668 tptr = (const uint8_t *)llsap->llsa_prefix;
669 while (prefixes > 0) {
670 bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length);
671 if (bytelen < 0)
672 goto trunc;
673 prefixes--;
674 /*
675 * ospf6_print_lsaprefix() will return -1 if
676 * the length is too high, so this will not
677 * underflow.
678 */
679 lsa_length -= bytelen;
680 tptr += bytelen;
681 }
682 break;
683
684 case LS_TYPE_INTRA_AP | LS_SCOPE_AREA:
685 /* Intra-Area-Prefix LSA */
686 if (lsa_length < sizeof (lsap->lsa_un.un_intra_ap.intra_ap_rtid))
687 return (1);
688 lsa_length -= sizeof (lsap->lsa_un.un_intra_ap.intra_ap_rtid);
689 ND_TCHECK_4(lsap->lsa_un.un_intra_ap.intra_ap_rtid);
690 ospf6_print_ls_type(ndo,
691 GET_BE_U_2(lsap->lsa_un.un_intra_ap.intra_ap_lstype),
692 &lsap->lsa_un.un_intra_ap.intra_ap_lsid);
693
694 if (lsa_length < sizeof (lsap->lsa_un.un_intra_ap.intra_ap_nprefix))
695 return (1);
696 lsa_length -= sizeof (lsap->lsa_un.un_intra_ap.intra_ap_nprefix);
697 prefixes = GET_BE_U_2(lsap->lsa_un.un_intra_ap.intra_ap_nprefix);
698 ND_PRINT("\n\t Prefixes %u:", prefixes);
699
700 tptr = (const uint8_t *)lsap->lsa_un.un_intra_ap.intra_ap_prefix;
701 while (prefixes > 0) {
702 bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length);
703 if (bytelen < 0)
704 goto trunc;
705 prefixes--;
706 /*
707 * ospf6_print_lsaprefix() will return -1 if
708 * the length is too high, so this will not
709 * underflow.
710 */
711 lsa_length -= bytelen;
712 tptr += bytelen;
713 }
714 break;
715
716 case LS_TYPE_GRACE | LS_SCOPE_LINKLOCAL:
717 if (ospf_grace_lsa_print(ndo, tptr, lsa_length) == -1) {
718 return 1;
719 }
720 break;
721
722 case LS_TYPE_INTRA_ATE | LS_SCOPE_LINKLOCAL:
723 if (ospf_te_lsa_print(ndo, tptr, lsa_length) == -1) {
724 return 1;
725 }
726 break;
727
728 default:
729 if(!print_unknown_data(ndo,tptr,
730 "\n\t ",
731 lsa_length)) {
732 return (1);
733 }
734 break;
735 }
736
737 return (0);
738 trunc:
739 return (1);
740 }
741
742 UNALIGNED_OK
743 static int
744 ospf6_decode_v3(netdissect_options *ndo,
745 const struct ospf6hdr *op,
746 const u_char *dataend)
747 {
748 const rtrid_t *ap;
749 const struct lsr6 *lsrp;
750 const struct lsa6_hdr *lshp;
751 const struct lsa6 *lsap;
752 uint32_t i;
753
754 switch (GET_U_1(op->ospf6_type)) {
755
756 case OSPF_TYPE_HELLO: {
757 const struct hello6 *hellop = (const struct hello6 *)((const uint8_t *)op + OSPF6HDR_LEN);
758
759 ND_PRINT("\n\tOptions [%s]",
760 bittok2str(ospf6_option_values, "none",
761 GET_BE_U_4(hellop->hello_options)));
762
763 ND_PRINT("\n\t Hello Timer %us, Dead Timer %us, Interface-ID %s, Priority %u",
764 GET_BE_U_2(hellop->hello_helloint),
765 GET_BE_U_2(hellop->hello_deadint),
766 GET_IPADDR_STRING(hellop->hello_ifid),
767 GET_U_1(hellop->hello_priority));
768
769 if (GET_BE_U_4(hellop->hello_dr) != 0)
770 ND_PRINT("\n\t Designated Router %s",
771 GET_IPADDR_STRING(hellop->hello_dr));
772 if (GET_BE_U_4(hellop->hello_bdr) != 0)
773 ND_PRINT(", Backup Designated Router %s",
774 GET_IPADDR_STRING(hellop->hello_bdr));
775 if (ndo->ndo_vflag > 1) {
776 ND_PRINT("\n\t Neighbor List:");
777 ap = hellop->hello_neighbor;
778 while ((const u_char *)ap < dataend) {
779 ND_PRINT("\n\t %s", GET_IPADDR_STRING(ap));
780 ++ap;
781 }
782 }
783 break; /* HELLO */
784 }
785
786 case OSPF_TYPE_DD: {
787 const struct dd6 *ddp = (const struct dd6 *)((const uint8_t *)op + OSPF6HDR_LEN);
788
789 ND_PRINT("\n\tOptions [%s]",
790 bittok2str(ospf6_option_values, "none",
791 GET_BE_U_4(ddp->db_options)));
792 ND_PRINT(", DD Flags [%s]",
793 bittok2str(ospf6_dd_flag_values,"none",GET_U_1(ddp->db_flags)));
794
795 ND_PRINT(", MTU %u, DD-Sequence 0x%08x",
796 GET_BE_U_2(ddp->db_mtu),
797 GET_BE_U_4(ddp->db_seq));
798 if (ndo->ndo_vflag > 1) {
799 /* Print all the LS adv's */
800 lshp = ddp->db_lshdr;
801 while ((const u_char *)lshp < dataend) {
802 if (ospf6_print_lshdr(ndo, lshp++, dataend))
803 goto trunc;
804 }
805 }
806 break;
807 }
808
809 case OSPF_TYPE_LS_REQ:
810 if (ndo->ndo_vflag > 1) {
811 lsrp = (const struct lsr6 *)((const uint8_t *)op + OSPF6HDR_LEN);
812 while ((const u_char *)lsrp < dataend) {
813 ND_TCHECK_SIZE(lsrp);
814 ND_PRINT("\n\t Advertising Router %s",
815 GET_IPADDR_STRING(lsrp->ls_router));
816 ospf6_print_ls_type(ndo,
817 GET_BE_U_2(lsrp->ls_type),
818 &lsrp->ls_stateid);
819 ++lsrp;
820 }
821 }
822 break;
823
824 case OSPF_TYPE_LS_UPDATE:
825 if (ndo->ndo_vflag > 1) {
826 const struct lsu6 *lsup = (const struct lsu6 *)((const uint8_t *)op + OSPF6HDR_LEN);
827
828 i = GET_BE_U_4(lsup->lsu_count);
829 lsap = lsup->lsu_lsa;
830 while ((const u_char *)lsap < dataend && i--) {
831 if (ospf6_print_lsa(ndo, lsap, dataend))
832 goto trunc;
833 lsap = (const struct lsa6 *)((const u_char *)lsap +
834 GET_BE_U_2(lsap->ls_hdr.ls_length));
835 }
836 }
837 break;
838
839 case OSPF_TYPE_LS_ACK:
840 if (ndo->ndo_vflag > 1) {
841 lshp = (const struct lsa6_hdr *)((const uint8_t *)op + OSPF6HDR_LEN);
842 while ((const u_char *)lshp < dataend) {
843 if (ospf6_print_lshdr(ndo, lshp++, dataend))
844 goto trunc;
845 }
846 }
847 break;
848
849 default:
850 break;
851 }
852 return (0);
853 trunc:
854 return (1);
855 }
856
857 /* RFC5613 Section 2.2 (w/o the TLVs) */
858 static int
859 ospf6_print_lls(netdissect_options *ndo,
860 const u_char *cp, const u_int len)
861 {
862 uint16_t llsdatalen;
863
864 if (len == 0)
865 return 0;
866 if (len < OSPF_LLS_HDRLEN)
867 goto trunc;
868 /* Checksum */
869 ND_PRINT("\n\tLLS Checksum 0x%04x", GET_BE_U_2(cp));
870 cp += 2;
871 /* LLS Data Length */
872 llsdatalen = GET_BE_U_2(cp);
873 ND_PRINT(", Data Length %u", llsdatalen);
874 if (llsdatalen < OSPF_LLS_HDRLEN || llsdatalen > len)
875 goto trunc;
876 cp += 2;
877 /* LLS TLVs */
878 ND_TCHECK_LEN(cp, llsdatalen - OSPF_LLS_HDRLEN);
879 /* FIXME: code in print-ospf.c can be reused to decode the TLVs */
880
881 return llsdatalen;
882 trunc:
883 return -1;
884 }
885
886 /* RFC6506 Section 4.1 */
887 static int
888 ospf6_decode_at(netdissect_options *ndo,
889 const u_char *cp, const u_int len)
890 {
891 uint16_t authdatalen;
892
893 if (len == 0)
894 return 0;
895 if (len < OSPF6_AT_HDRLEN)
896 goto trunc;
897 /* Authentication Type */
898 ND_PRINT("\n\tAuthentication Type %s",
899 tok2str(ospf6_auth_type_str, "unknown (0x%04x)", GET_BE_U_2(cp)));
900 cp += 2;
901 /* Auth Data Len */
902 authdatalen = GET_BE_U_2(cp);
903 ND_PRINT(", Length %u", authdatalen);
904 if (authdatalen < OSPF6_AT_HDRLEN || authdatalen > len)
905 goto trunc;
906 cp += 2;
907 /* Reserved */
908 cp += 2;
909 /* Security Association ID */
910 ND_PRINT(", SAID %u", GET_BE_U_2(cp));
911 cp += 2;
912 /* Cryptographic Sequence Number (High-Order 32 Bits) */
913 ND_PRINT(", CSN 0x%08x", GET_BE_U_4(cp));
914 cp += 4;
915 /* Cryptographic Sequence Number (Low-Order 32 Bits) */
916 ND_PRINT(":%08x", GET_BE_U_4(cp));
917 cp += 4;
918 /* Authentication Data */
919 ND_TCHECK_LEN(cp, authdatalen - OSPF6_AT_HDRLEN);
920 if (ndo->ndo_vflag > 1)
921 print_unknown_data(ndo,cp, "\n\tAuthentication Data ", authdatalen - OSPF6_AT_HDRLEN);
922 return 0;
923
924 trunc:
925 return 1;
926 }
927
928 /* The trailing data may include LLS and/or AT data (in this specific order).
929 * LLS data may be present only in Hello and DBDesc packets with the L-bit set.
930 * AT data may be present in Hello and DBDesc packets with the AT-bit set or in
931 * any other packet type, thus decode the AT data regardless of the AT-bit.
932 */
933 UNALIGNED_OK
934 static int
935 ospf6_decode_v3_trailer(netdissect_options *ndo,
936 const struct ospf6hdr *op, const u_char *cp, const unsigned len)
937 {
938 uint8_t type;
939 int llslen = 0;
940 int lls_hello = 0;
941 int lls_dd = 0;
942
943 type = GET_U_1(op->ospf6_type);
944 if (type == OSPF_TYPE_HELLO) {
945 const struct hello6 *hellop = (const struct hello6 *)((const uint8_t *)op + OSPF6HDR_LEN);
946 if (GET_BE_U_4(hellop->hello_options) & OSPF6_OPTION_L)
947 lls_hello = 1;
948 } else if (type == OSPF_TYPE_DD) {
949 const struct dd6 *ddp = (const struct dd6 *)((const uint8_t *)op + OSPF6HDR_LEN);
950 if (GET_BE_U_4(ddp->db_options) & OSPF6_OPTION_L)
951 lls_dd = 1;
952 }
953 if ((lls_hello || lls_dd) && (llslen = ospf6_print_lls(ndo, cp, len)) < 0)
954 goto trunc;
955 return ospf6_decode_at(ndo, cp + llslen, len - llslen);
956
957 trunc:
958 return 1;
959 }
960
961 UNALIGNED_OK
962 void
963 ospf6_print(netdissect_options *ndo,
964 const u_char *bp, u_int length)
965 {
966 const struct ospf6hdr *op;
967 const u_char *dataend;
968 const char *cp;
969 uint16_t datalen;
970
971 ndo->ndo_protocol = "ospf3";
972 op = (const struct ospf6hdr *)bp;
973
974 /* If the type is valid translate it, or just print the type */
975 /* value. If it's not valid, say so and return */
976 cp = tok2str(ospf6_type_values, "unknown packet type (%u)",
977 GET_U_1(op->ospf6_type));
978 ND_PRINT("OSPFv%u, %s, length %u", GET_U_1(op->ospf6_version), cp,
979 length);
980 if (*cp == 'u') {
981 return;
982 }
983
984 if(!ndo->ndo_vflag) { /* non verbose - so lets bail out here */
985 return;
986 }
987
988 /* OSPFv3 data always comes first and optional trailing data may follow. */
989 datalen = GET_BE_U_2(op->ospf6_len);
990 if (datalen > length) {
991 ND_PRINT(" [len %u]", datalen);
992 return;
993 }
994 dataend = bp + datalen;
995
996 ND_PRINT("\n\tRouter-ID %s", GET_IPADDR_STRING(op->ospf6_routerid));
997
998 if (GET_BE_U_4(op->ospf6_areaid) != 0)
999 ND_PRINT(", Area %s", GET_IPADDR_STRING(op->ospf6_areaid));
1000 else
1001 ND_PRINT(", Backbone Area");
1002 if (GET_U_1(op->ospf6_instanceid))
1003 ND_PRINT(", Instance %u", GET_U_1(op->ospf6_instanceid));
1004
1005 /* Do rest according to version. */
1006 switch (GET_U_1(op->ospf6_version)) {
1007
1008 case 3:
1009 /* ospf version 3 */
1010 if (ospf6_decode_v3(ndo, op, dataend) ||
1011 ospf6_decode_v3_trailer(ndo, op, dataend, length - datalen))
1012 goto trunc;
1013 break;
1014 } /* end switch on version */
1015
1016 return;
1017 trunc:
1018 nd_print_trunc(ndo);
1019 }
1020