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