141c99275SPeter Avalos /*
241c99275SPeter Avalos * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997
341c99275SPeter Avalos * The Regents of the University of California. All rights reserved.
441c99275SPeter Avalos *
541c99275SPeter Avalos * Redistribution and use in source and binary forms, with or without
641c99275SPeter Avalos * modification, are permitted provided that: (1) source code distributions
741c99275SPeter Avalos * retain the above copyright notice and this paragraph in its entirety, (2)
841c99275SPeter Avalos * distributions including binary code include the above copyright notice and
941c99275SPeter Avalos * this paragraph in its entirety in the documentation or other materials
1041c99275SPeter Avalos * provided with the distribution, and (3) all advertising materials mentioning
1141c99275SPeter Avalos * features or use of this software display the following acknowledgement:
1241c99275SPeter Avalos * ``This product includes software developed by the University of California,
1341c99275SPeter Avalos * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1441c99275SPeter Avalos * the University nor the names of its contributors may be used to endorse
1541c99275SPeter Avalos * or promote products derived from this software without specific prior
1641c99275SPeter Avalos * written permission.
1741c99275SPeter Avalos * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1841c99275SPeter Avalos * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1941c99275SPeter Avalos * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2041c99275SPeter Avalos *
2141c99275SPeter Avalos * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu)
2241c99275SPeter Avalos */
2341c99275SPeter Avalos
24411677aeSAaron LI /* \summary: IPv6 Open Shortest Path First (OSPFv3) printer */
2541c99275SPeter Avalos
2641c99275SPeter Avalos #ifdef HAVE_CONFIG_H
27*ed775ee7SAntonio Huete Jimenez #include <config.h>
2841c99275SPeter Avalos #endif
2941c99275SPeter Avalos
30*ed775ee7SAntonio Huete Jimenez #include "netdissect-stdinc.h"
3141c99275SPeter Avalos
3241c99275SPeter Avalos #include <string.h>
3341c99275SPeter Avalos
34411677aeSAaron LI #include "netdissect.h"
3541c99275SPeter Avalos #include "addrtoname.h"
3641c99275SPeter Avalos #include "extract.h"
3741c99275SPeter Avalos
38ea7b4bf5SPeter Avalos #include "ospf.h"
39411677aeSAaron LI
40411677aeSAaron LI #define OSPF_TYPE_HELLO 1 /* Hello */
41411677aeSAaron LI #define OSPF_TYPE_DD 2 /* Database Description */
42411677aeSAaron LI #define OSPF_TYPE_LS_REQ 3 /* Link State Request */
43411677aeSAaron LI #define OSPF_TYPE_LS_UPDATE 4 /* Link State Update */
44411677aeSAaron LI #define OSPF_TYPE_LS_ACK 5 /* Link State Ack */
45411677aeSAaron LI
46411677aeSAaron LI /* Options *_options */
47411677aeSAaron LI #define OSPF6_OPTION_V6 0x01 /* V6 bit: A bit for peeping tom */
48411677aeSAaron LI #define OSPF6_OPTION_E 0x02 /* E bit: External routes advertised */
49411677aeSAaron LI #define OSPF6_OPTION_MC 0x04 /* MC bit: Multicast capable */
50411677aeSAaron LI #define OSPF6_OPTION_N 0x08 /* N bit: For type-7 LSA */
51411677aeSAaron LI #define OSPF6_OPTION_R 0x10 /* R bit: Router bit */
52411677aeSAaron LI #define OSPF6_OPTION_DC 0x20 /* DC bit: Demand circuits */
53411677aeSAaron LI /* The field is actually 24-bit (RFC5340 Section A.2). */
54411677aeSAaron LI #define OSPF6_OPTION_AF 0x0100 /* AF bit: Multiple address families */
55411677aeSAaron LI #define OSPF6_OPTION_L 0x0200 /* L bit: Link-local signaling (LLS) */
56411677aeSAaron LI #define OSPF6_OPTION_AT 0x0400 /* AT bit: Authentication trailer */
57411677aeSAaron LI
58411677aeSAaron LI
59411677aeSAaron LI /* db_flags */
60411677aeSAaron LI #define OSPF6_DB_INIT 0x04 /* */
61411677aeSAaron LI #define OSPF6_DB_MORE 0x02
62411677aeSAaron LI #define OSPF6_DB_MASTER 0x01
63411677aeSAaron LI #define OSPF6_DB_M6 0x10 /* IPv6 MTU */
64411677aeSAaron LI
65411677aeSAaron LI /* ls_type */
66411677aeSAaron LI #define LS_TYPE_ROUTER 1 /* router link */
67411677aeSAaron LI #define LS_TYPE_NETWORK 2 /* network link */
68411677aeSAaron LI #define LS_TYPE_INTER_AP 3 /* Inter-Area-Prefix */
69411677aeSAaron LI #define LS_TYPE_INTER_AR 4 /* Inter-Area-Router */
70411677aeSAaron LI #define LS_TYPE_ASE 5 /* ASE */
71411677aeSAaron LI #define LS_TYPE_GROUP 6 /* Group membership */
72411677aeSAaron LI #define LS_TYPE_NSSA 7 /* NSSA */
73411677aeSAaron LI #define LS_TYPE_LINK 8 /* Link LSA */
74411677aeSAaron LI #define LS_TYPE_INTRA_AP 9 /* Intra-Area-Prefix */
75411677aeSAaron LI #define LS_TYPE_INTRA_ATE 10 /* Intra-Area-TE */
76411677aeSAaron LI #define LS_TYPE_GRACE 11 /* Grace LSA */
77411677aeSAaron LI #define LS_TYPE_RI 12 /* Router information */
78411677aeSAaron LI #define LS_TYPE_INTER_ASTE 13 /* Inter-AS-TE */
79411677aeSAaron LI #define LS_TYPE_L1VPN 14 /* L1VPN */
80411677aeSAaron LI #define LS_TYPE_MASK 0x1fff
81411677aeSAaron LI
82411677aeSAaron LI #define LS_SCOPE_LINKLOCAL 0x0000
83411677aeSAaron LI #define LS_SCOPE_AREA 0x2000
84411677aeSAaron LI #define LS_SCOPE_AS 0x4000
85411677aeSAaron LI #define LS_SCOPE_MASK 0x6000
86411677aeSAaron LI #define LS_SCOPE_U 0x8000
87411677aeSAaron LI
88411677aeSAaron LI /* rla_link.link_type */
89411677aeSAaron LI #define RLA_TYPE_ROUTER 1 /* point-to-point to another router */
90411677aeSAaron LI #define RLA_TYPE_TRANSIT 2 /* connection to transit network */
91411677aeSAaron LI #define RLA_TYPE_VIRTUAL 4 /* virtual link */
92411677aeSAaron LI
93411677aeSAaron LI /* rla_flags */
94411677aeSAaron LI #define RLA_FLAG_B 0x01
95411677aeSAaron LI #define RLA_FLAG_E 0x02
96411677aeSAaron LI #define RLA_FLAG_V 0x04
97411677aeSAaron LI #define RLA_FLAG_W 0x08
98*ed775ee7SAntonio Huete Jimenez #define RLA_FLAG_Nt 0x10
99411677aeSAaron LI
100411677aeSAaron LI /* lsa_prefix options */
101411677aeSAaron LI #define LSA_PREFIX_OPT_NU 0x01
102411677aeSAaron LI #define LSA_PREFIX_OPT_LA 0x02
103411677aeSAaron LI #define LSA_PREFIX_OPT_MC 0x04
104411677aeSAaron LI #define LSA_PREFIX_OPT_P 0x08
105411677aeSAaron LI #define LSA_PREFIX_OPT_DN 0x10
106*ed775ee7SAntonio Huete Jimenez #define LSA_PREFIX_OPT_N 0x20
107411677aeSAaron LI
108411677aeSAaron LI /* sla_tosmetric breakdown */
109411677aeSAaron LI #define SLA_MASK_TOS 0x7f000000
110411677aeSAaron LI #define SLA_MASK_METRIC 0x00ffffff
111411677aeSAaron LI #define SLA_SHIFT_TOS 24
112411677aeSAaron LI
113411677aeSAaron LI /* asla_metric */
114411677aeSAaron LI #define ASLA_FLAG_FWDADDR 0x02000000
115411677aeSAaron LI #define ASLA_FLAG_ROUTETAG 0x01000000
116411677aeSAaron LI #define ASLA_MASK_METRIC 0x00ffffff
117411677aeSAaron LI
118411677aeSAaron LI /* RFC6506 Section 4.1 */
119411677aeSAaron LI #define OSPF6_AT_HDRLEN 16U
120411677aeSAaron LI #define OSPF6_AUTH_TYPE_HMAC 0x0001
121411677aeSAaron LI
122*ed775ee7SAntonio Huete Jimenez typedef nd_uint32_t rtrid_t;
123411677aeSAaron LI
124411677aeSAaron LI /* link state advertisement header */
125411677aeSAaron LI struct lsa6_hdr {
126*ed775ee7SAntonio Huete Jimenez nd_uint16_t ls_age;
127*ed775ee7SAntonio Huete Jimenez nd_uint16_t ls_type;
128411677aeSAaron LI rtrid_t ls_stateid;
129411677aeSAaron LI rtrid_t ls_router;
130*ed775ee7SAntonio Huete Jimenez nd_uint32_t ls_seq;
131*ed775ee7SAntonio Huete Jimenez nd_uint16_t ls_chksum;
132*ed775ee7SAntonio Huete Jimenez nd_uint16_t ls_length;
133411677aeSAaron LI };
134411677aeSAaron LI
135411677aeSAaron LI /* Length of an IPv6 address, in bytes. */
136411677aeSAaron LI #define IPV6_ADDR_LEN_BYTES (128/8)
137411677aeSAaron LI
138411677aeSAaron LI struct lsa6_prefix {
139*ed775ee7SAntonio Huete Jimenez nd_uint8_t lsa_p_len;
140*ed775ee7SAntonio Huete Jimenez nd_uint8_t lsa_p_opt;
141*ed775ee7SAntonio Huete Jimenez nd_uint16_t lsa_p_metric;
142*ed775ee7SAntonio Huete Jimenez nd_byte lsa_p_prefix[IPV6_ADDR_LEN_BYTES]; /* maximum length */
143411677aeSAaron LI };
144411677aeSAaron LI
145411677aeSAaron LI /* link state advertisement */
146411677aeSAaron LI struct lsa6 {
147411677aeSAaron LI struct lsa6_hdr ls_hdr;
148411677aeSAaron LI
149411677aeSAaron LI /* Link state types */
150411677aeSAaron LI union {
151411677aeSAaron LI /* Router links advertisements */
152411677aeSAaron LI struct {
153411677aeSAaron LI union {
154*ed775ee7SAntonio Huete Jimenez nd_uint8_t flg;
155*ed775ee7SAntonio Huete Jimenez nd_uint32_t opt;
156411677aeSAaron LI } rla_flgandopt;
157411677aeSAaron LI #define rla_flags rla_flgandopt.flg
158411677aeSAaron LI #define rla_options rla_flgandopt.opt
159411677aeSAaron LI struct rlalink6 {
160*ed775ee7SAntonio Huete Jimenez nd_uint8_t link_type;
161*ed775ee7SAntonio Huete Jimenez nd_byte link_zero;
162*ed775ee7SAntonio Huete Jimenez nd_uint16_t link_metric;
163*ed775ee7SAntonio Huete Jimenez nd_uint32_t link_ifid;
164*ed775ee7SAntonio Huete Jimenez nd_uint32_t link_nifid;
165411677aeSAaron LI rtrid_t link_nrtid;
166411677aeSAaron LI } rla_link[1]; /* may repeat */
167411677aeSAaron LI } un_rla;
168411677aeSAaron LI
169411677aeSAaron LI /* Network links advertisements */
170411677aeSAaron LI struct {
171*ed775ee7SAntonio Huete Jimenez nd_uint32_t nla_options;
172411677aeSAaron LI rtrid_t nla_router[1]; /* may repeat */
173411677aeSAaron LI } un_nla;
174411677aeSAaron LI
175411677aeSAaron LI /* Inter Area Prefix LSA */
176411677aeSAaron LI struct {
177*ed775ee7SAntonio Huete Jimenez nd_uint32_t inter_ap_metric;
178411677aeSAaron LI struct lsa6_prefix inter_ap_prefix[1];
179411677aeSAaron LI } un_inter_ap;
180411677aeSAaron LI
181411677aeSAaron LI /* AS external links advertisements */
182411677aeSAaron LI struct {
183*ed775ee7SAntonio Huete Jimenez nd_uint32_t asla_metric;
184411677aeSAaron LI struct lsa6_prefix asla_prefix[1];
185411677aeSAaron LI /* some optional fields follow */
186411677aeSAaron LI } un_asla;
187411677aeSAaron LI
188411677aeSAaron LI #if 0
189411677aeSAaron LI /* Summary links advertisements */
190411677aeSAaron LI struct {
191*ed775ee7SAntonio Huete Jimenez nd_ipv4 sla_mask;
192*ed775ee7SAntonio Huete Jimenez nd_uint32_t sla_tosmetric[1]; /* may repeat */
193411677aeSAaron LI } un_sla;
194411677aeSAaron LI
195411677aeSAaron LI /* Multicast group membership */
196411677aeSAaron LI struct mcla {
197*ed775ee7SAntonio Huete Jimenez nd_uint32_t mcla_vtype;
198*ed775ee7SAntonio Huete Jimenez nd_ipv4 mcla_vid;
199411677aeSAaron LI } un_mcla[1];
200411677aeSAaron LI #endif
201411677aeSAaron LI
202411677aeSAaron LI /* Type 7 LSA */
203411677aeSAaron LI
204411677aeSAaron LI /* Link LSA */
205411677aeSAaron LI struct llsa {
206411677aeSAaron LI union {
207*ed775ee7SAntonio Huete Jimenez nd_uint8_t pri;
208*ed775ee7SAntonio Huete Jimenez nd_uint32_t opt;
209411677aeSAaron LI } llsa_priandopt;
210411677aeSAaron LI #define llsa_priority llsa_priandopt.pri
211411677aeSAaron LI #define llsa_options llsa_priandopt.opt
212*ed775ee7SAntonio Huete Jimenez nd_ipv6 llsa_lladdr;
213*ed775ee7SAntonio Huete Jimenez nd_uint32_t llsa_nprefix;
214411677aeSAaron LI struct lsa6_prefix llsa_prefix[1];
215411677aeSAaron LI } un_llsa;
216411677aeSAaron LI
217411677aeSAaron LI /* Intra-Area-Prefix */
218411677aeSAaron LI struct {
219*ed775ee7SAntonio Huete Jimenez nd_uint16_t intra_ap_nprefix;
220*ed775ee7SAntonio Huete Jimenez nd_uint16_t intra_ap_lstype;
221411677aeSAaron LI rtrid_t intra_ap_lsid;
222411677aeSAaron LI rtrid_t intra_ap_rtid;
223411677aeSAaron LI struct lsa6_prefix intra_ap_prefix[1];
224411677aeSAaron LI } un_intra_ap;
225411677aeSAaron LI } lsa_un;
226411677aeSAaron LI };
227411677aeSAaron LI
228411677aeSAaron LI /*
229411677aeSAaron LI * the main header
230411677aeSAaron LI */
231411677aeSAaron LI struct ospf6hdr {
232*ed775ee7SAntonio Huete Jimenez nd_uint8_t ospf6_version;
233*ed775ee7SAntonio Huete Jimenez nd_uint8_t ospf6_type;
234*ed775ee7SAntonio Huete Jimenez nd_uint16_t ospf6_len;
235411677aeSAaron LI rtrid_t ospf6_routerid;
236411677aeSAaron LI rtrid_t ospf6_areaid;
237*ed775ee7SAntonio Huete Jimenez nd_uint16_t ospf6_chksum;
238*ed775ee7SAntonio Huete Jimenez nd_uint8_t ospf6_instanceid;
239*ed775ee7SAntonio Huete Jimenez nd_uint8_t ospf6_rsvd;
240411677aeSAaron LI };
241411677aeSAaron LI
242411677aeSAaron LI /*
243411677aeSAaron LI * The OSPF6 header length is 16 bytes, regardless of how your compiler
244411677aeSAaron LI * might choose to pad the above structure.
245411677aeSAaron LI */
246411677aeSAaron LI #define OSPF6HDR_LEN 16
247411677aeSAaron LI
248411677aeSAaron LI /* Hello packet */
249411677aeSAaron LI struct hello6 {
250*ed775ee7SAntonio Huete Jimenez nd_uint32_t hello_ifid;
251411677aeSAaron LI union {
252*ed775ee7SAntonio Huete Jimenez nd_uint8_t pri;
253*ed775ee7SAntonio Huete Jimenez nd_uint32_t opt;
254411677aeSAaron LI } hello_priandopt;
255411677aeSAaron LI #define hello_priority hello_priandopt.pri
256411677aeSAaron LI #define hello_options hello_priandopt.opt
257*ed775ee7SAntonio Huete Jimenez nd_uint16_t hello_helloint;
258*ed775ee7SAntonio Huete Jimenez nd_uint16_t hello_deadint;
259411677aeSAaron LI rtrid_t hello_dr;
260411677aeSAaron LI rtrid_t hello_bdr;
261411677aeSAaron LI rtrid_t hello_neighbor[1]; /* may repeat */
262411677aeSAaron LI };
263411677aeSAaron LI
264411677aeSAaron LI /* Database Description packet */
265411677aeSAaron LI struct dd6 {
266*ed775ee7SAntonio Huete Jimenez nd_uint32_t db_options;
267*ed775ee7SAntonio Huete Jimenez nd_uint16_t db_mtu;
268*ed775ee7SAntonio Huete Jimenez nd_uint8_t db_mbz;
269*ed775ee7SAntonio Huete Jimenez nd_uint8_t db_flags;
270*ed775ee7SAntonio Huete Jimenez nd_uint32_t db_seq;
271411677aeSAaron LI struct lsa6_hdr db_lshdr[1]; /* may repeat */
272411677aeSAaron LI };
273411677aeSAaron LI
274411677aeSAaron LI /* Link State Request */
275411677aeSAaron LI struct lsr6 {
276*ed775ee7SAntonio Huete Jimenez nd_uint16_t ls_mbz;
277*ed775ee7SAntonio Huete Jimenez nd_uint16_t ls_type;
278411677aeSAaron LI rtrid_t ls_stateid;
279411677aeSAaron LI rtrid_t ls_router;
280411677aeSAaron LI };
281411677aeSAaron LI
282411677aeSAaron LI /* Link State Update */
283411677aeSAaron LI struct lsu6 {
284*ed775ee7SAntonio Huete Jimenez nd_uint32_t lsu_count;
285411677aeSAaron LI struct lsa6 lsu_lsa[1]; /* may repeat */
286411677aeSAaron LI };
287411677aeSAaron LI
28841c99275SPeter Avalos
289ea7b4bf5SPeter Avalos static const struct tok ospf6_option_values[] = {
29041c99275SPeter Avalos { OSPF6_OPTION_V6, "V6" },
291ea7b4bf5SPeter Avalos { OSPF6_OPTION_E, "External" },
292411677aeSAaron LI { OSPF6_OPTION_MC, "Deprecated" },
293ea7b4bf5SPeter Avalos { OSPF6_OPTION_N, "NSSA" },
294ea7b4bf5SPeter Avalos { OSPF6_OPTION_R, "Router" },
295ea7b4bf5SPeter Avalos { OSPF6_OPTION_DC, "Demand Circuit" },
296411677aeSAaron LI { OSPF6_OPTION_AF, "AFs Support" },
297411677aeSAaron LI { OSPF6_OPTION_L, "LLS" },
298411677aeSAaron LI { OSPF6_OPTION_AT, "Authentication Trailer" },
29941c99275SPeter Avalos { 0, NULL }
30041c99275SPeter Avalos };
30141c99275SPeter Avalos
302ea7b4bf5SPeter Avalos static const struct tok ospf6_rla_flag_values[] = {
303ea7b4bf5SPeter Avalos { RLA_FLAG_B, "ABR" },
304ea7b4bf5SPeter Avalos { RLA_FLAG_E, "External" },
305ea7b4bf5SPeter Avalos { RLA_FLAG_V, "Virtual-Link Endpoint" },
306*ed775ee7SAntonio Huete Jimenez { RLA_FLAG_W, "Deprecated" },
307*ed775ee7SAntonio Huete Jimenez { RLA_FLAG_Nt, "NSSA Translator" },
30841c99275SPeter Avalos { 0, NULL }
30941c99275SPeter Avalos };
31041c99275SPeter Avalos
311ea7b4bf5SPeter Avalos static const struct tok ospf6_asla_flag_values[] = {
312ea7b4bf5SPeter Avalos { ASLA_FLAG_EXTERNAL, "External Type 2" },
313411677aeSAaron LI { ASLA_FLAG_FWDADDR, "Forwarding" },
314ea7b4bf5SPeter Avalos { ASLA_FLAG_ROUTETAG, "Tag" },
31541c99275SPeter Avalos { 0, NULL }
31641c99275SPeter Avalos };
31741c99275SPeter Avalos
318411677aeSAaron LI static const struct tok ospf6_type_values[] = {
319ea7b4bf5SPeter Avalos { OSPF_TYPE_HELLO, "Hello" },
320ea7b4bf5SPeter Avalos { OSPF_TYPE_DD, "Database Description" },
321ea7b4bf5SPeter Avalos { OSPF_TYPE_LS_REQ, "LS-Request" },
322ea7b4bf5SPeter Avalos { OSPF_TYPE_LS_UPDATE, "LS-Update" },
323ea7b4bf5SPeter Avalos { OSPF_TYPE_LS_ACK, "LS-Ack" },
32441c99275SPeter Avalos { 0, NULL }
32541c99275SPeter Avalos };
32641c99275SPeter Avalos
327411677aeSAaron LI static const struct tok ospf6_lsa_values[] = {
328ea7b4bf5SPeter Avalos { LS_TYPE_ROUTER, "Router" },
329ea7b4bf5SPeter Avalos { LS_TYPE_NETWORK, "Network" },
330ea7b4bf5SPeter Avalos { LS_TYPE_INTER_AP, "Inter-Area Prefix" },
331ea7b4bf5SPeter Avalos { LS_TYPE_INTER_AR, "Inter-Area Router" },
332ea7b4bf5SPeter Avalos { LS_TYPE_ASE, "External" },
333411677aeSAaron LI { LS_TYPE_GROUP, "Deprecated" },
334ea7b4bf5SPeter Avalos { LS_TYPE_NSSA, "NSSA" },
335ea7b4bf5SPeter Avalos { LS_TYPE_LINK, "Link" },
336ea7b4bf5SPeter Avalos { LS_TYPE_INTRA_AP, "Intra-Area Prefix" },
337ea7b4bf5SPeter Avalos { LS_TYPE_INTRA_ATE, "Intra-Area TE" },
338ea7b4bf5SPeter Avalos { LS_TYPE_GRACE, "Grace" },
339411677aeSAaron LI { LS_TYPE_RI, "Router Information" },
340411677aeSAaron LI { LS_TYPE_INTER_ASTE, "Inter-AS-TE" },
341411677aeSAaron LI { LS_TYPE_L1VPN, "Layer 1 VPN" },
342ea7b4bf5SPeter Avalos { 0, NULL }
343ea7b4bf5SPeter Avalos };
344ea7b4bf5SPeter Avalos
345411677aeSAaron LI static const struct tok ospf6_ls_scope_values[] = {
346ea7b4bf5SPeter Avalos { LS_SCOPE_LINKLOCAL, "Link Local" },
347ea7b4bf5SPeter Avalos { LS_SCOPE_AREA, "Area Local" },
348ea7b4bf5SPeter Avalos { LS_SCOPE_AS, "Domain Wide" },
349ea7b4bf5SPeter Avalos { 0, NULL }
350ea7b4bf5SPeter Avalos };
351ea7b4bf5SPeter Avalos
352411677aeSAaron LI static const struct tok ospf6_dd_flag_values[] = {
353ea7b4bf5SPeter Avalos { OSPF6_DB_INIT, "Init" },
354ea7b4bf5SPeter Avalos { OSPF6_DB_MORE, "More" },
355ea7b4bf5SPeter Avalos { OSPF6_DB_MASTER, "Master" },
356411677aeSAaron LI { OSPF6_DB_M6, "IPv6 MTU" },
357ea7b4bf5SPeter Avalos { 0, NULL }
358ea7b4bf5SPeter Avalos };
359ea7b4bf5SPeter Avalos
360411677aeSAaron LI static const struct tok ospf6_lsa_prefix_option_values[] = {
361ea7b4bf5SPeter Avalos { LSA_PREFIX_OPT_NU, "No Unicast" },
362ea7b4bf5SPeter Avalos { LSA_PREFIX_OPT_LA, "Local address" },
363411677aeSAaron LI { LSA_PREFIX_OPT_MC, "Deprecated" },
364ea7b4bf5SPeter Avalos { LSA_PREFIX_OPT_P, "Propagate" },
365ea7b4bf5SPeter Avalos { LSA_PREFIX_OPT_DN, "Down" },
366*ed775ee7SAntonio Huete Jimenez { LSA_PREFIX_OPT_N, "N-bit" },
367ea7b4bf5SPeter Avalos { 0, NULL }
368ea7b4bf5SPeter Avalos };
369ea7b4bf5SPeter Avalos
370411677aeSAaron LI static const struct tok ospf6_auth_type_str[] = {
371411677aeSAaron LI { OSPF6_AUTH_TYPE_HMAC, "HMAC" },
372411677aeSAaron LI { 0, NULL }
373411677aeSAaron LI };
37441c99275SPeter Avalos
37541c99275SPeter Avalos static void
ospf6_print_ls_type(netdissect_options * ndo,u_int ls_type,const rtrid_t * ls_stateid)376411677aeSAaron LI ospf6_print_ls_type(netdissect_options *ndo,
377*ed775ee7SAntonio Huete Jimenez u_int ls_type, const rtrid_t *ls_stateid)
37841c99275SPeter Avalos {
379*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t %s LSA (%u), %s Scope%s, LSA-ID %s",
380ea7b4bf5SPeter Avalos tok2str(ospf6_lsa_values, "Unknown", ls_type & LS_TYPE_MASK),
381ea7b4bf5SPeter Avalos ls_type & LS_TYPE_MASK,
382ea7b4bf5SPeter Avalos tok2str(ospf6_ls_scope_values, "Unknown", ls_type & LS_SCOPE_MASK),
383ea7b4bf5SPeter Avalos ls_type &0x8000 ? ", transitive" : "", /* U-bit */
384*ed775ee7SAntonio Huete Jimenez GET_IPADDR_STRING((const u_char *)ls_stateid));
38541c99275SPeter Avalos }
38641c99275SPeter Avalos
38741c99275SPeter Avalos static int
ospf6_print_lshdr(netdissect_options * ndo,const struct lsa6_hdr * lshp,const u_char * dataend)388411677aeSAaron LI ospf6_print_lshdr(netdissect_options *ndo,
389*ed775ee7SAntonio Huete Jimenez const struct lsa6_hdr *lshp, const u_char *dataend)
39041c99275SPeter Avalos {
391411677aeSAaron LI if ((const u_char *)(lshp + 1) > dataend)
392411677aeSAaron LI goto trunc;
39341c99275SPeter Avalos
394*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t Advertising Router %s, seq 0x%08x, age %us, length %zu",
395*ed775ee7SAntonio Huete Jimenez GET_IPADDR_STRING(lshp->ls_router),
396*ed775ee7SAntonio Huete Jimenez GET_BE_U_4(lshp->ls_seq),
397*ed775ee7SAntonio Huete Jimenez GET_BE_U_2(lshp->ls_age),
398*ed775ee7SAntonio Huete Jimenez GET_BE_U_2(lshp->ls_length)-sizeof(struct lsa6_hdr));
399ea7b4bf5SPeter Avalos
400*ed775ee7SAntonio Huete Jimenez ospf6_print_ls_type(ndo, GET_BE_U_2(lshp->ls_type),
401*ed775ee7SAntonio Huete Jimenez &lshp->ls_stateid);
40241c99275SPeter Avalos
40341c99275SPeter Avalos return (0);
40441c99275SPeter Avalos trunc:
40541c99275SPeter Avalos return (1);
40641c99275SPeter Avalos }
40741c99275SPeter Avalos
40841c99275SPeter Avalos static int
ospf6_print_lsaprefix(netdissect_options * ndo,const uint8_t * tptr,u_int lsa_length)409411677aeSAaron LI ospf6_print_lsaprefix(netdissect_options *ndo,
410411677aeSAaron LI const uint8_t *tptr, u_int lsa_length)
41141c99275SPeter Avalos {
412411677aeSAaron LI const struct lsa6_prefix *lsapp = (const struct lsa6_prefix *)tptr;
413ea7b4bf5SPeter Avalos u_int wordlen;
414*ed775ee7SAntonio Huete Jimenez nd_ipv6 prefix;
41541c99275SPeter Avalos
416411677aeSAaron LI if (lsa_length < sizeof (*lsapp) - IPV6_ADDR_LEN_BYTES)
4176263709fSPeter Avalos goto trunc;
418411677aeSAaron LI lsa_length -= sizeof (*lsapp) - IPV6_ADDR_LEN_BYTES;
419*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(lsapp, sizeof(*lsapp) - IPV6_ADDR_LEN_BYTES);
420*ed775ee7SAntonio Huete Jimenez wordlen = (GET_U_1(lsapp->lsa_p_len) + 31) / 32;
421*ed775ee7SAntonio Huete Jimenez if (wordlen * 4 > sizeof(nd_ipv6)) {
422*ed775ee7SAntonio Huete Jimenez ND_PRINT(" bogus prefixlen /%u", GET_U_1(lsapp->lsa_p_len));
42341c99275SPeter Avalos goto trunc;
42441c99275SPeter Avalos }
4256263709fSPeter Avalos if (lsa_length < wordlen * 4)
4266263709fSPeter Avalos goto trunc;
4276263709fSPeter Avalos lsa_length -= wordlen * 4;
428*ed775ee7SAntonio Huete Jimenez memset(prefix, 0, sizeof(prefix));
429*ed775ee7SAntonio Huete Jimenez GET_CPY_BYTES(prefix, lsapp->lsa_p_prefix, wordlen * 4);
430*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t\t%s/%u", ip6addr_string(ndo, prefix), /* local buffer, not packet data; don't use GET_IP6ADDR_STRING() */
431*ed775ee7SAntonio Huete Jimenez GET_U_1(lsapp->lsa_p_len));
432*ed775ee7SAntonio Huete Jimenez if (GET_U_1(lsapp->lsa_p_opt)) {
433*ed775ee7SAntonio Huete Jimenez ND_PRINT(", Options [%s]",
434ea7b4bf5SPeter Avalos bittok2str(ospf6_lsa_prefix_option_values,
435*ed775ee7SAntonio Huete Jimenez "none", GET_U_1(lsapp->lsa_p_opt)));
436ea7b4bf5SPeter Avalos }
437*ed775ee7SAntonio Huete Jimenez ND_PRINT(", metric %u", GET_BE_U_2(lsapp->lsa_p_metric));
438411677aeSAaron LI return sizeof(*lsapp) - IPV6_ADDR_LEN_BYTES + wordlen * 4;
43941c99275SPeter Avalos
44041c99275SPeter Avalos trunc:
44141c99275SPeter Avalos return -1;
44241c99275SPeter Avalos }
44341c99275SPeter Avalos
44441c99275SPeter Avalos
44541c99275SPeter Avalos /*
44641c99275SPeter Avalos * Print a single link state advertisement. If truncated return 1, else 0.
44741c99275SPeter Avalos */
44841c99275SPeter Avalos static int
ospf6_print_lsa(netdissect_options * ndo,const struct lsa6 * lsap,const u_char * dataend)449411677aeSAaron LI ospf6_print_lsa(netdissect_options *ndo,
450*ed775ee7SAntonio Huete Jimenez const struct lsa6 *lsap, const u_char *dataend)
45141c99275SPeter Avalos {
452*ed775ee7SAntonio Huete Jimenez const struct rlalink6 *rlp;
45341c99275SPeter Avalos #if 0
454*ed775ee7SAntonio Huete Jimenez const struct tos_metric *tosp;
45541c99275SPeter Avalos #endif
456*ed775ee7SAntonio Huete Jimenez const rtrid_t *ap;
45741c99275SPeter Avalos #if 0
458*ed775ee7SAntonio Huete Jimenez const struct aslametric *almp;
459*ed775ee7SAntonio Huete Jimenez const struct mcla *mcp;
46041c99275SPeter Avalos #endif
461*ed775ee7SAntonio Huete Jimenez const struct llsa *llsap;
462*ed775ee7SAntonio Huete Jimenez const struct lsa6_prefix *lsapp;
46341c99275SPeter Avalos #if 0
464*ed775ee7SAntonio Huete Jimenez const uint32_t *lp;
46541c99275SPeter Avalos #endif
466*ed775ee7SAntonio Huete Jimenez u_int prefixes;
467*ed775ee7SAntonio Huete Jimenez int bytelen;
468*ed775ee7SAntonio Huete Jimenez u_int length, lsa_length;
469411677aeSAaron LI uint32_t flags32;
470411677aeSAaron LI const uint8_t *tptr;
47141c99275SPeter Avalos
472411677aeSAaron LI if (ospf6_print_lshdr(ndo, &lsap->ls_hdr, dataend))
47341c99275SPeter Avalos return (1);
474*ed775ee7SAntonio Huete Jimenez length = GET_BE_U_2(lsap->ls_hdr.ls_length);
4756263709fSPeter Avalos
4766263709fSPeter Avalos /*
4776263709fSPeter Avalos * The LSA length includes the length of the header;
4786263709fSPeter Avalos * it must have a value that's at least that length.
4796263709fSPeter Avalos * If it does, find the length of what follows the
4806263709fSPeter Avalos * header.
4816263709fSPeter Avalos */
482411677aeSAaron LI if (length < sizeof(struct lsa6_hdr) || (const u_char *)lsap + length > dataend)
4836263709fSPeter Avalos return (1);
484ea7b4bf5SPeter Avalos lsa_length = length - sizeof(struct lsa6_hdr);
485411677aeSAaron LI tptr = (const uint8_t *)lsap+sizeof(struct lsa6_hdr);
486ea7b4bf5SPeter Avalos
487*ed775ee7SAntonio Huete Jimenez switch (GET_BE_U_2(lsap->ls_hdr.ls_type)) {
48841c99275SPeter Avalos case LS_TYPE_ROUTER | LS_SCOPE_AREA:
4896263709fSPeter Avalos if (lsa_length < sizeof (lsap->lsa_un.un_rla.rla_options))
4906263709fSPeter Avalos return (1);
4916263709fSPeter Avalos lsa_length -= sizeof (lsap->lsa_un.un_rla.rla_options);
492*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t Options [%s]",
493ea7b4bf5SPeter Avalos bittok2str(ospf6_option_values, "none",
494*ed775ee7SAntonio Huete Jimenez GET_BE_U_4(lsap->lsa_un.un_rla.rla_options)));
495*ed775ee7SAntonio Huete Jimenez ND_PRINT(", RLA-Flags [%s]",
496ea7b4bf5SPeter Avalos bittok2str(ospf6_rla_flag_values, "none",
497*ed775ee7SAntonio Huete Jimenez GET_U_1(lsap->lsa_un.un_rla.rla_flags)));
498ea7b4bf5SPeter Avalos
49941c99275SPeter Avalos rlp = lsap->lsa_un.un_rla.rla_link;
5006263709fSPeter Avalos while (lsa_length != 0) {
5016263709fSPeter Avalos if (lsa_length < sizeof (*rlp))
5026263709fSPeter Avalos return (1);
5036263709fSPeter Avalos lsa_length -= sizeof (*rlp);
504*ed775ee7SAntonio Huete Jimenez ND_TCHECK_SIZE(rlp);
505*ed775ee7SAntonio Huete Jimenez switch (GET_U_1(rlp->link_type)) {
50641c99275SPeter Avalos
50741c99275SPeter Avalos case RLA_TYPE_VIRTUAL:
508*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t Virtual Link: Neighbor Router-ID %s"
509ea7b4bf5SPeter Avalos "\n\t Neighbor Interface-ID %s, Interface %s",
510*ed775ee7SAntonio Huete Jimenez GET_IPADDR_STRING(rlp->link_nrtid),
511*ed775ee7SAntonio Huete Jimenez GET_IPADDR_STRING(rlp->link_nifid),
512*ed775ee7SAntonio Huete Jimenez GET_IPADDR_STRING(rlp->link_ifid));
513ea7b4bf5SPeter Avalos break;
51441c99275SPeter Avalos
51541c99275SPeter Avalos case RLA_TYPE_ROUTER:
516*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t Neighbor Router-ID %s"
517ea7b4bf5SPeter Avalos "\n\t Neighbor Interface-ID %s, Interface %s",
518*ed775ee7SAntonio Huete Jimenez GET_IPADDR_STRING(rlp->link_nrtid),
519*ed775ee7SAntonio Huete Jimenez GET_IPADDR_STRING(rlp->link_nifid),
520*ed775ee7SAntonio Huete Jimenez GET_IPADDR_STRING(rlp->link_ifid));
52141c99275SPeter Avalos break;
52241c99275SPeter Avalos
52341c99275SPeter Avalos case RLA_TYPE_TRANSIT:
524*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t Neighbor Network-ID %s"
525ea7b4bf5SPeter Avalos "\n\t Neighbor Interface-ID %s, Interface %s",
526*ed775ee7SAntonio Huete Jimenez GET_IPADDR_STRING(rlp->link_nrtid),
527*ed775ee7SAntonio Huete Jimenez GET_IPADDR_STRING(rlp->link_nifid),
528*ed775ee7SAntonio Huete Jimenez GET_IPADDR_STRING(rlp->link_ifid));
52941c99275SPeter Avalos break;
53041c99275SPeter Avalos
53141c99275SPeter Avalos default:
532*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t Unknown Router Links Type 0x%02x",
533*ed775ee7SAntonio Huete Jimenez GET_U_1(rlp->link_type));
53441c99275SPeter Avalos return (0);
53541c99275SPeter Avalos }
536*ed775ee7SAntonio Huete Jimenez ND_PRINT(", metric %u", GET_BE_U_2(rlp->link_metric));
53741c99275SPeter Avalos rlp++;
53841c99275SPeter Avalos }
53941c99275SPeter Avalos break;
54041c99275SPeter Avalos
54141c99275SPeter Avalos case LS_TYPE_NETWORK | LS_SCOPE_AREA:
5426263709fSPeter Avalos if (lsa_length < sizeof (lsap->lsa_un.un_nla.nla_options))
5436263709fSPeter Avalos return (1);
5446263709fSPeter Avalos lsa_length -= sizeof (lsap->lsa_un.un_nla.nla_options);
545*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t Options [%s]",
546ea7b4bf5SPeter Avalos bittok2str(ospf6_option_values, "none",
547*ed775ee7SAntonio Huete Jimenez GET_BE_U_4(lsap->lsa_un.un_nla.nla_options)));
5486263709fSPeter Avalos
549*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t Connected Routers:");
55041c99275SPeter Avalos ap = lsap->lsa_un.un_nla.nla_router;
5516263709fSPeter Avalos while (lsa_length != 0) {
5526263709fSPeter Avalos if (lsa_length < sizeof (*ap))
5536263709fSPeter Avalos return (1);
5546263709fSPeter Avalos lsa_length -= sizeof (*ap);
555*ed775ee7SAntonio Huete Jimenez ND_TCHECK_SIZE(ap);
556*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t\t%s", GET_IPADDR_STRING(*ap));
55741c99275SPeter Avalos ++ap;
55841c99275SPeter Avalos }
55941c99275SPeter Avalos break;
56041c99275SPeter Avalos
56141c99275SPeter Avalos case LS_TYPE_INTER_AP | LS_SCOPE_AREA:
5626263709fSPeter Avalos if (lsa_length < sizeof (lsap->lsa_un.un_inter_ap.inter_ap_metric))
5636263709fSPeter Avalos return (1);
5646263709fSPeter Avalos lsa_length -= sizeof (lsap->lsa_un.un_inter_ap.inter_ap_metric);
565*ed775ee7SAntonio Huete Jimenez ND_PRINT(", metric %u",
566*ed775ee7SAntonio Huete Jimenez GET_BE_U_4(lsap->lsa_un.un_inter_ap.inter_ap_metric) & SLA_MASK_METRIC);
5676263709fSPeter Avalos
568411677aeSAaron LI tptr = (const uint8_t *)lsap->lsa_un.un_inter_ap.inter_ap_prefix;
5696263709fSPeter Avalos while (lsa_length != 0) {
570411677aeSAaron LI bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length);
5716263709fSPeter Avalos if (bytelen < 0)
57241c99275SPeter Avalos goto trunc;
573*ed775ee7SAntonio Huete Jimenez /*
574*ed775ee7SAntonio Huete Jimenez * ospf6_print_lsaprefix() will return -1 if
575*ed775ee7SAntonio Huete Jimenez * the length is too high, so this will not
576*ed775ee7SAntonio Huete Jimenez * underflow.
577*ed775ee7SAntonio Huete Jimenez */
5786263709fSPeter Avalos lsa_length -= bytelen;
5796263709fSPeter Avalos tptr += bytelen;
58041c99275SPeter Avalos }
58141c99275SPeter Avalos break;
5826263709fSPeter Avalos
5836263709fSPeter Avalos case LS_TYPE_ASE | LS_SCOPE_AS:
5846263709fSPeter Avalos if (lsa_length < sizeof (lsap->lsa_un.un_asla.asla_metric))
5856263709fSPeter Avalos return (1);
5866263709fSPeter Avalos lsa_length -= sizeof (lsap->lsa_un.un_asla.asla_metric);
587*ed775ee7SAntonio Huete Jimenez flags32 = GET_BE_U_4(lsap->lsa_un.un_asla.asla_metric);
588*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t Flags [%s]",
589*ed775ee7SAntonio Huete Jimenez bittok2str(ospf6_asla_flag_values, "none", flags32));
590*ed775ee7SAntonio Huete Jimenez ND_PRINT(" metric %u",
591*ed775ee7SAntonio Huete Jimenez GET_BE_U_4(lsap->lsa_un.un_asla.asla_metric) &
592*ed775ee7SAntonio Huete Jimenez ASLA_MASK_METRIC);
5936263709fSPeter Avalos
594411677aeSAaron LI tptr = (const uint8_t *)lsap->lsa_un.un_asla.asla_prefix;
595411677aeSAaron LI lsapp = (const struct lsa6_prefix *)tptr;
596411677aeSAaron LI bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length);
597ea7b4bf5SPeter Avalos if (bytelen < 0)
59841c99275SPeter Avalos goto trunc;
599*ed775ee7SAntonio Huete Jimenez /*
600*ed775ee7SAntonio Huete Jimenez * ospf6_print_lsaprefix() will return -1 if
601*ed775ee7SAntonio Huete Jimenez * the length is too high, so this will not
602*ed775ee7SAntonio Huete Jimenez * underflow.
603*ed775ee7SAntonio Huete Jimenez */
6046263709fSPeter Avalos lsa_length -= bytelen;
6056263709fSPeter Avalos tptr += bytelen;
60641c99275SPeter Avalos
60741c99275SPeter Avalos if ((flags32 & ASLA_FLAG_FWDADDR) != 0) {
608*ed775ee7SAntonio Huete Jimenez if (lsa_length < sizeof (nd_ipv6))
6096263709fSPeter Avalos return (1);
610*ed775ee7SAntonio Huete Jimenez lsa_length -= sizeof (nd_ipv6);
611*ed775ee7SAntonio Huete Jimenez ND_PRINT(" forward %s",
612*ed775ee7SAntonio Huete Jimenez GET_IP6ADDR_STRING(tptr));
613*ed775ee7SAntonio Huete Jimenez tptr += sizeof(nd_ipv6);
61441c99275SPeter Avalos }
61541c99275SPeter Avalos
61641c99275SPeter Avalos if ((flags32 & ASLA_FLAG_ROUTETAG) != 0) {
617411677aeSAaron LI if (lsa_length < sizeof (uint32_t))
6186263709fSPeter Avalos return (1);
619411677aeSAaron LI lsa_length -= sizeof (uint32_t);
620*ed775ee7SAntonio Huete Jimenez ND_PRINT(" tag %s",
621*ed775ee7SAntonio Huete Jimenez GET_IPADDR_STRING(tptr));
622411677aeSAaron LI tptr += sizeof(uint32_t);
62341c99275SPeter Avalos }
62441c99275SPeter Avalos
625*ed775ee7SAntonio Huete Jimenez if (GET_U_1(lsapp->lsa_p_metric)) {
626411677aeSAaron LI if (lsa_length < sizeof (uint32_t))
6276263709fSPeter Avalos return (1);
628411677aeSAaron LI lsa_length -= sizeof (uint32_t);
629*ed775ee7SAntonio Huete Jimenez ND_PRINT(" RefLSID: %s",
630*ed775ee7SAntonio Huete Jimenez GET_IPADDR_STRING(tptr));
631411677aeSAaron LI tptr += sizeof(uint32_t);
63241c99275SPeter Avalos }
63341c99275SPeter Avalos break;
63441c99275SPeter Avalos
63541c99275SPeter Avalos case LS_TYPE_LINK:
63641c99275SPeter Avalos /* Link LSA */
63741c99275SPeter Avalos llsap = &lsap->lsa_un.un_llsa;
6386263709fSPeter Avalos if (lsa_length < sizeof (llsap->llsa_priandopt))
6396263709fSPeter Avalos return (1);
6406263709fSPeter Avalos lsa_length -= sizeof (llsap->llsa_priandopt);
641*ed775ee7SAntonio Huete Jimenez ND_TCHECK_SIZE(&llsap->llsa_priandopt);
642*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t Options [%s]",
643ea7b4bf5SPeter Avalos bittok2str(ospf6_option_values, "none",
644*ed775ee7SAntonio Huete Jimenez GET_BE_U_4(llsap->llsa_options)));
6456263709fSPeter Avalos
6466263709fSPeter Avalos if (lsa_length < sizeof (llsap->llsa_lladdr) + sizeof (llsap->llsa_nprefix))
6476263709fSPeter Avalos return (1);
6486263709fSPeter Avalos lsa_length -= sizeof (llsap->llsa_lladdr) + sizeof (llsap->llsa_nprefix);
649*ed775ee7SAntonio Huete Jimenez prefixes = GET_BE_U_4(llsap->llsa_nprefix);
650*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t Priority %u, Link-local address %s, Prefixes %u:",
651*ed775ee7SAntonio Huete Jimenez GET_U_1(llsap->llsa_priority),
652*ed775ee7SAntonio Huete Jimenez GET_IP6ADDR_STRING(llsap->llsa_lladdr),
653*ed775ee7SAntonio Huete Jimenez prefixes);
654ea7b4bf5SPeter Avalos
655411677aeSAaron LI tptr = (const uint8_t *)llsap->llsa_prefix;
656ea7b4bf5SPeter Avalos while (prefixes > 0) {
657411677aeSAaron LI bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length);
6586263709fSPeter Avalos if (bytelen < 0)
65941c99275SPeter Avalos goto trunc;
660ea7b4bf5SPeter Avalos prefixes--;
661*ed775ee7SAntonio Huete Jimenez /*
662*ed775ee7SAntonio Huete Jimenez * ospf6_print_lsaprefix() will return -1 if
663*ed775ee7SAntonio Huete Jimenez * the length is too high, so this will not
664*ed775ee7SAntonio Huete Jimenez * underflow.
665*ed775ee7SAntonio Huete Jimenez */
6666263709fSPeter Avalos lsa_length -= bytelen;
667ea7b4bf5SPeter Avalos tptr += bytelen;
66841c99275SPeter Avalos }
66941c99275SPeter Avalos break;
67041c99275SPeter Avalos
67141c99275SPeter Avalos case LS_TYPE_INTRA_AP | LS_SCOPE_AREA:
67241c99275SPeter Avalos /* Intra-Area-Prefix LSA */
6736263709fSPeter Avalos if (lsa_length < sizeof (lsap->lsa_un.un_intra_ap.intra_ap_rtid))
6746263709fSPeter Avalos return (1);
6756263709fSPeter Avalos lsa_length -= sizeof (lsap->lsa_un.un_intra_ap.intra_ap_rtid);
676*ed775ee7SAntonio Huete Jimenez ND_TCHECK_4(lsap->lsa_un.un_intra_ap.intra_ap_rtid);
677411677aeSAaron LI ospf6_print_ls_type(ndo,
678*ed775ee7SAntonio Huete Jimenez GET_BE_U_2(lsap->lsa_un.un_intra_ap.intra_ap_lstype),
679ea7b4bf5SPeter Avalos &lsap->lsa_un.un_intra_ap.intra_ap_lsid);
6806263709fSPeter Avalos
6816263709fSPeter Avalos if (lsa_length < sizeof (lsap->lsa_un.un_intra_ap.intra_ap_nprefix))
6826263709fSPeter Avalos return (1);
6836263709fSPeter Avalos lsa_length -= sizeof (lsap->lsa_un.un_intra_ap.intra_ap_nprefix);
684*ed775ee7SAntonio Huete Jimenez prefixes = GET_BE_U_2(lsap->lsa_un.un_intra_ap.intra_ap_nprefix);
685*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t Prefixes %u:", prefixes);
68641c99275SPeter Avalos
687411677aeSAaron LI tptr = (const uint8_t *)lsap->lsa_un.un_intra_ap.intra_ap_prefix;
688ea7b4bf5SPeter Avalos while (prefixes > 0) {
689411677aeSAaron LI bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length);
6906263709fSPeter Avalos if (bytelen < 0)
69141c99275SPeter Avalos goto trunc;
692ea7b4bf5SPeter Avalos prefixes--;
693*ed775ee7SAntonio Huete Jimenez /*
694*ed775ee7SAntonio Huete Jimenez * ospf6_print_lsaprefix() will return -1 if
695*ed775ee7SAntonio Huete Jimenez * the length is too high, so this will not
696*ed775ee7SAntonio Huete Jimenez * underflow.
697*ed775ee7SAntonio Huete Jimenez */
6986263709fSPeter Avalos lsa_length -= bytelen;
699ea7b4bf5SPeter Avalos tptr += bytelen;
700ea7b4bf5SPeter Avalos }
701ea7b4bf5SPeter Avalos break;
702ea7b4bf5SPeter Avalos
703ea7b4bf5SPeter Avalos case LS_TYPE_GRACE | LS_SCOPE_LINKLOCAL:
704*ed775ee7SAntonio Huete Jimenez if (ospf_grace_lsa_print(ndo, tptr, lsa_length) == -1) {
705ea7b4bf5SPeter Avalos return 1;
706ea7b4bf5SPeter Avalos }
707ea7b4bf5SPeter Avalos break;
708ea7b4bf5SPeter Avalos
709ea7b4bf5SPeter Avalos case LS_TYPE_INTRA_ATE | LS_SCOPE_LINKLOCAL:
710*ed775ee7SAntonio Huete Jimenez if (ospf_te_lsa_print(ndo, tptr, lsa_length) == -1) {
711ea7b4bf5SPeter Avalos return 1;
71241c99275SPeter Avalos }
71341c99275SPeter Avalos break;
71441c99275SPeter Avalos
71541c99275SPeter Avalos default:
716411677aeSAaron LI if(!print_unknown_data(ndo,tptr,
717ea7b4bf5SPeter Avalos "\n\t ",
718ea7b4bf5SPeter Avalos lsa_length)) {
719ea7b4bf5SPeter Avalos return (1);
720ea7b4bf5SPeter Avalos }
7216263709fSPeter Avalos break;
72241c99275SPeter Avalos }
72341c99275SPeter Avalos
72441c99275SPeter Avalos return (0);
72541c99275SPeter Avalos trunc:
72641c99275SPeter Avalos return (1);
72741c99275SPeter Avalos }
72841c99275SPeter Avalos
72941c99275SPeter Avalos static int
ospf6_decode_v3(netdissect_options * ndo,const struct ospf6hdr * op,const u_char * dataend)730411677aeSAaron LI ospf6_decode_v3(netdissect_options *ndo,
731*ed775ee7SAntonio Huete Jimenez const struct ospf6hdr *op,
732*ed775ee7SAntonio Huete Jimenez const u_char *dataend)
73341c99275SPeter Avalos {
734*ed775ee7SAntonio Huete Jimenez const rtrid_t *ap;
735*ed775ee7SAntonio Huete Jimenez const struct lsr6 *lsrp;
736*ed775ee7SAntonio Huete Jimenez const struct lsa6_hdr *lshp;
737*ed775ee7SAntonio Huete Jimenez const struct lsa6 *lsap;
738*ed775ee7SAntonio Huete Jimenez int i;
73941c99275SPeter Avalos
740*ed775ee7SAntonio Huete Jimenez switch (GET_U_1(op->ospf6_type)) {
74141c99275SPeter Avalos
742411677aeSAaron LI case OSPF_TYPE_HELLO: {
743*ed775ee7SAntonio Huete Jimenez const struct hello6 *hellop = (const struct hello6 *)((const uint8_t *)op + OSPF6HDR_LEN);
744411677aeSAaron LI
745*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\tOptions [%s]",
746ea7b4bf5SPeter Avalos bittok2str(ospf6_option_values, "none",
747*ed775ee7SAntonio Huete Jimenez GET_BE_U_4(hellop->hello_options)));
748ea7b4bf5SPeter Avalos
749*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t Hello Timer %us, Dead Timer %us, Interface-ID %s, Priority %u",
750*ed775ee7SAntonio Huete Jimenez GET_BE_U_2(hellop->hello_helloint),
751*ed775ee7SAntonio Huete Jimenez GET_BE_U_2(hellop->hello_deadint),
752*ed775ee7SAntonio Huete Jimenez GET_IPADDR_STRING(hellop->hello_ifid),
753*ed775ee7SAntonio Huete Jimenez GET_U_1(hellop->hello_priority));
754ea7b4bf5SPeter Avalos
755*ed775ee7SAntonio Huete Jimenez if (GET_BE_U_4(hellop->hello_dr) != 0)
756*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t Designated Router %s",
757*ed775ee7SAntonio Huete Jimenez GET_IPADDR_STRING(hellop->hello_dr));
758*ed775ee7SAntonio Huete Jimenez if (GET_BE_U_4(hellop->hello_bdr) != 0)
759*ed775ee7SAntonio Huete Jimenez ND_PRINT(", Backup Designated Router %s",
760*ed775ee7SAntonio Huete Jimenez GET_IPADDR_STRING(hellop->hello_bdr));
761411677aeSAaron LI if (ndo->ndo_vflag > 1) {
762*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t Neighbor List:");
763411677aeSAaron LI ap = hellop->hello_neighbor;
764411677aeSAaron LI while ((const u_char *)ap < dataend) {
765*ed775ee7SAntonio Huete Jimenez ND_TCHECK_SIZE(ap);
766*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t %s", GET_IPADDR_STRING(*ap));
76741c99275SPeter Avalos ++ap;
76841c99275SPeter Avalos }
76941c99275SPeter Avalos }
77041c99275SPeter Avalos break; /* HELLO */
771411677aeSAaron LI }
77241c99275SPeter Avalos
773411677aeSAaron LI case OSPF_TYPE_DD: {
774*ed775ee7SAntonio Huete Jimenez const struct dd6 *ddp = (const struct dd6 *)((const uint8_t *)op + OSPF6HDR_LEN);
775411677aeSAaron LI
776*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\tOptions [%s]",
777ea7b4bf5SPeter Avalos bittok2str(ospf6_option_values, "none",
778*ed775ee7SAntonio Huete Jimenez GET_BE_U_4(ddp->db_options)));
779*ed775ee7SAntonio Huete Jimenez ND_PRINT(", DD Flags [%s]",
780*ed775ee7SAntonio Huete Jimenez bittok2str(ospf6_dd_flag_values,"none",GET_U_1(ddp->db_flags)));
781ea7b4bf5SPeter Avalos
782*ed775ee7SAntonio Huete Jimenez ND_PRINT(", MTU %u, DD-Sequence 0x%08x",
783*ed775ee7SAntonio Huete Jimenez GET_BE_U_2(ddp->db_mtu),
784*ed775ee7SAntonio Huete Jimenez GET_BE_U_4(ddp->db_seq));
785411677aeSAaron LI if (ndo->ndo_vflag > 1) {
78641c99275SPeter Avalos /* Print all the LS adv's */
787411677aeSAaron LI lshp = ddp->db_lshdr;
788411677aeSAaron LI while ((const u_char *)lshp < dataend) {
789411677aeSAaron LI if (ospf6_print_lshdr(ndo, lshp++, dataend))
790411677aeSAaron LI goto trunc;
791411677aeSAaron LI }
79241c99275SPeter Avalos }
79341c99275SPeter Avalos break;
794411677aeSAaron LI }
79541c99275SPeter Avalos
796ea7b4bf5SPeter Avalos case OSPF_TYPE_LS_REQ:
797411677aeSAaron LI if (ndo->ndo_vflag > 1) {
798411677aeSAaron LI lsrp = (const struct lsr6 *)((const uint8_t *)op + OSPF6HDR_LEN);
799411677aeSAaron LI while ((const u_char *)lsrp < dataend) {
800*ed775ee7SAntonio Huete Jimenez ND_TCHECK_SIZE(lsrp);
801*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\t Advertising Router %s",
802*ed775ee7SAntonio Huete Jimenez GET_IPADDR_STRING(lsrp->ls_router));
803*ed775ee7SAntonio Huete Jimenez ospf6_print_ls_type(ndo,
804*ed775ee7SAntonio Huete Jimenez GET_BE_U_2(lsrp->ls_type),
805ea7b4bf5SPeter Avalos &lsrp->ls_stateid);
80641c99275SPeter Avalos ++lsrp;
80741c99275SPeter Avalos }
80841c99275SPeter Avalos }
80941c99275SPeter Avalos break;
81041c99275SPeter Avalos
811ea7b4bf5SPeter Avalos case OSPF_TYPE_LS_UPDATE:
812411677aeSAaron LI if (ndo->ndo_vflag > 1) {
813*ed775ee7SAntonio Huete Jimenez const struct lsu6 *lsup = (const struct lsu6 *)((const uint8_t *)op + OSPF6HDR_LEN);
814411677aeSAaron LI
815*ed775ee7SAntonio Huete Jimenez i = GET_BE_U_4(lsup->lsu_count);
816411677aeSAaron LI lsap = lsup->lsu_lsa;
817411677aeSAaron LI while ((const u_char *)lsap < dataend && i--) {
818411677aeSAaron LI if (ospf6_print_lsa(ndo, lsap, dataend))
81941c99275SPeter Avalos goto trunc;
820411677aeSAaron LI lsap = (const struct lsa6 *)((const u_char *)lsap +
821*ed775ee7SAntonio Huete Jimenez GET_BE_U_2(lsap->ls_hdr.ls_length));
82241c99275SPeter Avalos }
82341c99275SPeter Avalos }
82441c99275SPeter Avalos break;
82541c99275SPeter Avalos
826ea7b4bf5SPeter Avalos case OSPF_TYPE_LS_ACK:
827411677aeSAaron LI if (ndo->ndo_vflag > 1) {
828411677aeSAaron LI lshp = (const struct lsa6_hdr *)((const uint8_t *)op + OSPF6HDR_LEN);
829411677aeSAaron LI while ((const u_char *)lshp < dataend) {
830411677aeSAaron LI if (ospf6_print_lshdr(ndo, lshp++, dataend))
831411677aeSAaron LI goto trunc;
83241c99275SPeter Avalos }
83341c99275SPeter Avalos }
83441c99275SPeter Avalos break;
83541c99275SPeter Avalos
83641c99275SPeter Avalos default:
83741c99275SPeter Avalos break;
83841c99275SPeter Avalos }
83941c99275SPeter Avalos return (0);
84041c99275SPeter Avalos trunc:
84141c99275SPeter Avalos return (1);
84241c99275SPeter Avalos }
84341c99275SPeter Avalos
844411677aeSAaron LI /* RFC5613 Section 2.2 (w/o the TLVs) */
845411677aeSAaron LI static int
ospf6_print_lls(netdissect_options * ndo,const u_char * cp,const u_int len)846411677aeSAaron LI ospf6_print_lls(netdissect_options *ndo,
847411677aeSAaron LI const u_char *cp, const u_int len)
848411677aeSAaron LI {
849411677aeSAaron LI uint16_t llsdatalen;
850411677aeSAaron LI
851411677aeSAaron LI if (len == 0)
852411677aeSAaron LI return 0;
853411677aeSAaron LI if (len < OSPF_LLS_HDRLEN)
854411677aeSAaron LI goto trunc;
855411677aeSAaron LI /* Checksum */
856*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\tLLS Checksum 0x%04x", GET_BE_U_2(cp));
857411677aeSAaron LI cp += 2;
858411677aeSAaron LI /* LLS Data Length */
859*ed775ee7SAntonio Huete Jimenez llsdatalen = GET_BE_U_2(cp);
860*ed775ee7SAntonio Huete Jimenez ND_PRINT(", Data Length %u", llsdatalen);
861411677aeSAaron LI if (llsdatalen < OSPF_LLS_HDRLEN || llsdatalen > len)
862411677aeSAaron LI goto trunc;
863411677aeSAaron LI cp += 2;
864411677aeSAaron LI /* LLS TLVs */
865*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(cp, llsdatalen - OSPF_LLS_HDRLEN);
866411677aeSAaron LI /* FIXME: code in print-ospf.c can be reused to decode the TLVs */
867411677aeSAaron LI
868411677aeSAaron LI return llsdatalen;
869411677aeSAaron LI trunc:
870411677aeSAaron LI return -1;
871411677aeSAaron LI }
872411677aeSAaron LI
873411677aeSAaron LI /* RFC6506 Section 4.1 */
874411677aeSAaron LI static int
ospf6_decode_at(netdissect_options * ndo,const u_char * cp,const u_int len)875411677aeSAaron LI ospf6_decode_at(netdissect_options *ndo,
876411677aeSAaron LI const u_char *cp, const u_int len)
877411677aeSAaron LI {
878411677aeSAaron LI uint16_t authdatalen;
879411677aeSAaron LI
880411677aeSAaron LI if (len == 0)
881411677aeSAaron LI return 0;
882411677aeSAaron LI if (len < OSPF6_AT_HDRLEN)
883411677aeSAaron LI goto trunc;
884411677aeSAaron LI /* Authentication Type */
885*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\tAuthentication Type %s",
886*ed775ee7SAntonio Huete Jimenez tok2str(ospf6_auth_type_str, "unknown (0x%04x)", GET_BE_U_2(cp)));
887411677aeSAaron LI cp += 2;
888411677aeSAaron LI /* Auth Data Len */
889*ed775ee7SAntonio Huete Jimenez authdatalen = GET_BE_U_2(cp);
890*ed775ee7SAntonio Huete Jimenez ND_PRINT(", Length %u", authdatalen);
891411677aeSAaron LI if (authdatalen < OSPF6_AT_HDRLEN || authdatalen > len)
892411677aeSAaron LI goto trunc;
893411677aeSAaron LI cp += 2;
894411677aeSAaron LI /* Reserved */
895411677aeSAaron LI cp += 2;
896411677aeSAaron LI /* Security Association ID */
897*ed775ee7SAntonio Huete Jimenez ND_PRINT(", SAID %u", GET_BE_U_2(cp));
898411677aeSAaron LI cp += 2;
899411677aeSAaron LI /* Cryptographic Sequence Number (High-Order 32 Bits) */
900*ed775ee7SAntonio Huete Jimenez ND_PRINT(", CSN 0x%08x", GET_BE_U_4(cp));
901411677aeSAaron LI cp += 4;
902411677aeSAaron LI /* Cryptographic Sequence Number (Low-Order 32 Bits) */
903*ed775ee7SAntonio Huete Jimenez ND_PRINT(":%08x", GET_BE_U_4(cp));
904411677aeSAaron LI cp += 4;
905411677aeSAaron LI /* Authentication Data */
906*ed775ee7SAntonio Huete Jimenez ND_TCHECK_LEN(cp, authdatalen - OSPF6_AT_HDRLEN);
907411677aeSAaron LI if (ndo->ndo_vflag > 1)
908411677aeSAaron LI print_unknown_data(ndo,cp, "\n\tAuthentication Data ", authdatalen - OSPF6_AT_HDRLEN);
909411677aeSAaron LI return 0;
910411677aeSAaron LI
911411677aeSAaron LI trunc:
912411677aeSAaron LI return 1;
913411677aeSAaron LI }
914411677aeSAaron LI
915411677aeSAaron LI /* The trailing data may include LLS and/or AT data (in this specific order).
916411677aeSAaron LI * LLS data may be present only in Hello and DBDesc packets with the L-bit set.
917411677aeSAaron LI * AT data may be present in Hello and DBDesc packets with the AT-bit set or in
918411677aeSAaron LI * any other packet type, thus decode the AT data regardless of the AT-bit.
919411677aeSAaron LI */
920411677aeSAaron LI static int
ospf6_decode_v3_trailer(netdissect_options * ndo,const struct ospf6hdr * op,const u_char * cp,const unsigned len)921411677aeSAaron LI ospf6_decode_v3_trailer(netdissect_options *ndo,
922411677aeSAaron LI const struct ospf6hdr *op, const u_char *cp, const unsigned len)
923411677aeSAaron LI {
924*ed775ee7SAntonio Huete Jimenez uint8_t type;
925411677aeSAaron LI int llslen = 0;
926411677aeSAaron LI int lls_hello = 0;
927411677aeSAaron LI int lls_dd = 0;
928411677aeSAaron LI
929*ed775ee7SAntonio Huete Jimenez type = GET_U_1(op->ospf6_type);
930*ed775ee7SAntonio Huete Jimenez if (type == OSPF_TYPE_HELLO) {
931411677aeSAaron LI const struct hello6 *hellop = (const struct hello6 *)((const uint8_t *)op + OSPF6HDR_LEN);
932*ed775ee7SAntonio Huete Jimenez if (GET_BE_U_4(hellop->hello_options) & OSPF6_OPTION_L)
933411677aeSAaron LI lls_hello = 1;
934*ed775ee7SAntonio Huete Jimenez } else if (type == OSPF_TYPE_DD) {
935411677aeSAaron LI const struct dd6 *ddp = (const struct dd6 *)((const uint8_t *)op + OSPF6HDR_LEN);
936*ed775ee7SAntonio Huete Jimenez if (GET_BE_U_4(ddp->db_options) & OSPF6_OPTION_L)
937411677aeSAaron LI lls_dd = 1;
938411677aeSAaron LI }
939411677aeSAaron LI if ((lls_hello || lls_dd) && (llslen = ospf6_print_lls(ndo, cp, len)) < 0)
940411677aeSAaron LI goto trunc;
941411677aeSAaron LI return ospf6_decode_at(ndo, cp + llslen, len - llslen);
942411677aeSAaron LI
943411677aeSAaron LI trunc:
944411677aeSAaron LI return 1;
945411677aeSAaron LI }
946411677aeSAaron LI
94741c99275SPeter Avalos void
ospf6_print(netdissect_options * ndo,const u_char * bp,u_int length)948411677aeSAaron LI ospf6_print(netdissect_options *ndo,
949*ed775ee7SAntonio Huete Jimenez const u_char *bp, u_int length)
95041c99275SPeter Avalos {
951*ed775ee7SAntonio Huete Jimenez const struct ospf6hdr *op;
952*ed775ee7SAntonio Huete Jimenez const u_char *dataend;
953*ed775ee7SAntonio Huete Jimenez const char *cp;
954411677aeSAaron LI uint16_t datalen;
95541c99275SPeter Avalos
956*ed775ee7SAntonio Huete Jimenez ndo->ndo_protocol = "ospf3";
957411677aeSAaron LI op = (const struct ospf6hdr *)bp;
95841c99275SPeter Avalos
95941c99275SPeter Avalos /* If the type is valid translate it, or just print the type */
96041c99275SPeter Avalos /* value. If it's not valid, say so and return */
961*ed775ee7SAntonio Huete Jimenez cp = tok2str(ospf6_type_values, "unknown packet type (%u)",
962*ed775ee7SAntonio Huete Jimenez GET_U_1(op->ospf6_type));
963*ed775ee7SAntonio Huete Jimenez ND_PRINT("OSPFv%u, %s, length %u", GET_U_1(op->ospf6_version), cp,
964*ed775ee7SAntonio Huete Jimenez length);
965ea7b4bf5SPeter Avalos if (*cp == 'u') {
96641c99275SPeter Avalos return;
967ea7b4bf5SPeter Avalos }
968ea7b4bf5SPeter Avalos
969411677aeSAaron LI if(!ndo->ndo_vflag) { /* non verbose - so lets bail out here */
970ea7b4bf5SPeter Avalos return;
971ea7b4bf5SPeter Avalos }
97241c99275SPeter Avalos
973411677aeSAaron LI /* OSPFv3 data always comes first and optional trailing data may follow. */
974*ed775ee7SAntonio Huete Jimenez datalen = GET_BE_U_2(op->ospf6_len);
975411677aeSAaron LI if (datalen > length) {
976*ed775ee7SAntonio Huete Jimenez ND_PRINT(" [len %u]", datalen);
97741c99275SPeter Avalos return;
97841c99275SPeter Avalos }
979411677aeSAaron LI dataend = bp + datalen;
98041c99275SPeter Avalos
981*ed775ee7SAntonio Huete Jimenez ND_PRINT("\n\tRouter-ID %s", GET_IPADDR_STRING(op->ospf6_routerid));
98241c99275SPeter Avalos
983*ed775ee7SAntonio Huete Jimenez if (GET_BE_U_4(op->ospf6_areaid) != 0)
984*ed775ee7SAntonio Huete Jimenez ND_PRINT(", Area %s", GET_IPADDR_STRING(op->ospf6_areaid));
98541c99275SPeter Avalos else
986*ed775ee7SAntonio Huete Jimenez ND_PRINT(", Backbone Area");
987*ed775ee7SAntonio Huete Jimenez if (GET_U_1(op->ospf6_instanceid))
988*ed775ee7SAntonio Huete Jimenez ND_PRINT(", Instance %u", GET_U_1(op->ospf6_instanceid));
98941c99275SPeter Avalos
99041c99275SPeter Avalos /* Do rest according to version. */
991*ed775ee7SAntonio Huete Jimenez switch (GET_U_1(op->ospf6_version)) {
99241c99275SPeter Avalos
99341c99275SPeter Avalos case 3:
99441c99275SPeter Avalos /* ospf version 3 */
995411677aeSAaron LI if (ospf6_decode_v3(ndo, op, dataend) ||
996411677aeSAaron LI ospf6_decode_v3_trailer(ndo, op, dataend, length - datalen))
99741c99275SPeter Avalos goto trunc;
99841c99275SPeter Avalos break;
99941c99275SPeter Avalos } /* end switch on version */
100041c99275SPeter Avalos
100141c99275SPeter Avalos return;
100241c99275SPeter Avalos trunc:
1003*ed775ee7SAntonio Huete Jimenez nd_print_trunc(ndo);
100441c99275SPeter Avalos }
1005