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