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 "interface.h" |
||
32 | #include "addrtoname.h" |
||
33 | #include "extract.h" |
||
34 | #include "gmpls.h" |
||
35 | |||
36 | #include "ospf.h" |
||
37 | |||
38 | static const char tstr[] = " [|ospf2]"; |
||
39 | |||
40 | static const struct tok ospf_option_values[] = { |
||
41 | { OSPF_OPTION_T, "MultiTopology" }, /* draft-ietf-ospf-mt-09 */ |
||
42 | { OSPF_OPTION_E, "External" }, |
||
43 | { OSPF_OPTION_MC, "Multicast" }, |
||
44 | { OSPF_OPTION_NP, "NSSA" }, |
||
45 | { OSPF_OPTION_L, "LLS" }, |
||
46 | { OSPF_OPTION_DC, "Demand Circuit" }, |
||
47 | { OSPF_OPTION_O, "Opaque" }, |
||
48 | { OSPF_OPTION_DN, "Up/Down" }, |
||
49 | { 0, NULL } |
||
50 | }; |
||
51 | |||
52 | static const struct tok ospf_authtype_values[] = { |
||
53 | { OSPF_AUTH_NONE, "none" }, |
||
54 | { OSPF_AUTH_SIMPLE, "simple" }, |
||
55 | { OSPF_AUTH_MD5, "MD5" }, |
||
56 | { 0, NULL } |
||
57 | }; |
||
58 | |||
59 | static const struct tok ospf_rla_flag_values[] = { |
||
60 | { RLA_FLAG_B, "ABR" }, |
||
61 | { RLA_FLAG_E, "ASBR" }, |
||
62 | { RLA_FLAG_W1, "Virtual" }, |
||
63 | { RLA_FLAG_W2, "W2" }, |
||
64 | { 0, NULL } |
||
65 | }; |
||
66 | |||
67 | static const struct tok type2str[] = { |
||
68 | { OSPF_TYPE_UMD, "UMD" }, |
||
69 | { OSPF_TYPE_HELLO, "Hello" }, |
||
70 | { OSPF_TYPE_DD, "Database Description" }, |
||
71 | { OSPF_TYPE_LS_REQ, "LS-Request" }, |
||
72 | { OSPF_TYPE_LS_UPDATE, "LS-Update" }, |
||
73 | { OSPF_TYPE_LS_ACK, "LS-Ack" }, |
||
74 | { 0, NULL } |
||
75 | }; |
||
76 | |||
77 | static const struct tok lsa_values[] = { |
||
78 | { LS_TYPE_ROUTER, "Router" }, |
||
79 | { LS_TYPE_NETWORK, "Network" }, |
||
80 | { LS_TYPE_SUM_IP, "Summary" }, |
||
81 | { LS_TYPE_SUM_ABR, "ASBR Summary" }, |
||
82 | { LS_TYPE_ASE, "External" }, |
||
83 | { LS_TYPE_GROUP, "Multicast Group" }, |
||
84 | { LS_TYPE_NSSA, "NSSA" }, |
||
85 | { LS_TYPE_OPAQUE_LL, "Link Local Opaque" }, |
||
86 | { LS_TYPE_OPAQUE_AL, "Area Local Opaque" }, |
||
87 | { LS_TYPE_OPAQUE_DW, "Domain Wide Opaque" }, |
||
88 | { 0, NULL } |
||
89 | }; |
||
90 | |||
91 | static const struct tok ospf_dd_flag_values[] = { |
||
92 | { OSPF_DB_INIT, "Init" }, |
||
93 | { OSPF_DB_MORE, "More" }, |
||
94 | { OSPF_DB_MASTER, "Master" }, |
||
95 | { OSPF_DB_RESYNC, "OOBResync" }, |
||
96 | { 0, NULL } |
||
97 | }; |
||
98 | |||
99 | static const struct tok lsa_opaque_values[] = { |
||
100 | { LS_OPAQUE_TYPE_TE, "Traffic Engineering" }, |
||
101 | { LS_OPAQUE_TYPE_GRACE, "Graceful restart" }, |
||
102 | { LS_OPAQUE_TYPE_RI, "Router Information" }, |
||
103 | { 0, NULL } |
||
104 | }; |
||
105 | |||
106 | static const struct tok lsa_opaque_te_tlv_values[] = { |
||
107 | { LS_OPAQUE_TE_TLV_ROUTER, "Router Address" }, |
||
108 | { LS_OPAQUE_TE_TLV_LINK, "Link" }, |
||
109 | { 0, NULL } |
||
110 | }; |
||
111 | |||
112 | static const struct tok lsa_opaque_te_link_tlv_subtlv_values[] = { |
||
113 | { LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE, "Link Type" }, |
||
114 | { LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID, "Link ID" }, |
||
115 | { LS_OPAQUE_TE_LINK_SUBTLV_LOCAL_IP, "Local Interface IP address" }, |
||
116 | { LS_OPAQUE_TE_LINK_SUBTLV_REMOTE_IP, "Remote Interface IP address" }, |
||
117 | { LS_OPAQUE_TE_LINK_SUBTLV_TE_METRIC, "Traffic Engineering Metric" }, |
||
118 | { LS_OPAQUE_TE_LINK_SUBTLV_MAX_BW, "Maximum Bandwidth" }, |
||
119 | { LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW, "Maximum Reservable Bandwidth" }, |
||
120 | { LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW, "Unreserved Bandwidth" }, |
||
121 | { LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP, "Administrative Group" }, |
||
122 | { LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID, "Link Local/Remote Identifier" }, |
||
123 | { LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE, "Link Protection Type" }, |
||
124 | { LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR, "Interface Switching Capability" }, |
||
125 | { LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP, "Shared Risk Link Group" }, |
||
126 | { LS_OPAQUE_TE_LINK_SUBTLV_BW_CONSTRAINTS, "Bandwidth Constraints" }, |
||
127 | { 0, NULL } |
||
128 | }; |
||
129 | |||
130 | static const struct tok lsa_opaque_grace_tlv_values[] = { |
||
131 | { LS_OPAQUE_GRACE_TLV_PERIOD, "Grace Period" }, |
||
132 | { LS_OPAQUE_GRACE_TLV_REASON, "Graceful restart Reason" }, |
||
133 | { LS_OPAQUE_GRACE_TLV_INT_ADDRESS, "IPv4 interface address" }, |
||
134 | { 0, NULL } |
||
135 | }; |
||
136 | |||
137 | static const struct tok lsa_opaque_grace_tlv_reason_values[] = { |
||
138 | { LS_OPAQUE_GRACE_TLV_REASON_UNKNOWN, "Unknown" }, |
||
139 | { LS_OPAQUE_GRACE_TLV_REASON_SW_RESTART, "Software Restart" }, |
||
140 | { LS_OPAQUE_GRACE_TLV_REASON_SW_UPGRADE, "Software Reload/Upgrade" }, |
||
141 | { LS_OPAQUE_GRACE_TLV_REASON_CP_SWITCH, "Control Processor Switch" }, |
||
142 | { 0, NULL } |
||
143 | }; |
||
144 | |||
145 | static const struct tok lsa_opaque_te_tlv_link_type_sub_tlv_values[] = { |
||
146 | { LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_PTP, "Point-to-point" }, |
||
147 | { LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_MA, "Multi-Access" }, |
||
148 | { 0, NULL } |
||
149 | }; |
||
150 | |||
151 | static const struct tok lsa_opaque_ri_tlv_values[] = { |
||
152 | { LS_OPAQUE_RI_TLV_CAP, "Router Capabilities" }, |
||
153 | { 0, NULL } |
||
154 | }; |
||
155 | |||
156 | static const struct tok lsa_opaque_ri_tlv_cap_values[] = { |
||
157 | { 1, "Reserved" }, |
||
158 | { 2, "Reserved" }, |
||
159 | { 4, "Reserved" }, |
||
160 | { 8, "Reserved" }, |
||
161 | { 16, "graceful restart capable" }, |
||
162 | { 32, "graceful restart helper" }, |
||
163 | { 64, "Stub router support" }, |
||
164 | { 128, "Traffic engineering" }, |
||
165 | { 256, "p2p over LAN" }, |
||
166 | { 512, "path computation server" }, |
||
167 | { 0, NULL } |
||
168 | }; |
||
169 | |||
170 | static const struct tok ospf_lls_tlv_values[] = { |
||
171 | { OSPF_LLS_EO, "Extended Options" }, |
||
172 | { OSPF_LLS_MD5, "MD5 Authentication" }, |
||
173 | { 0, NULL } |
||
174 | }; |
||
175 | |||
176 | static const struct tok ospf_lls_eo_options[] = { |
||
177 | { OSPF_LLS_EO_LR, "LSDB resync" }, |
||
178 | { OSPF_LLS_EO_RS, "Restart" }, |
||
179 | { 0, NULL } |
||
180 | }; |
||
181 | |||
182 | int |
||
183 | ospf_print_grace_lsa(netdissect_options *ndo, |
||
184 | const uint8_t *tptr, u_int ls_length) |
||
185 | { |
||
186 | u_int tlv_type, tlv_length; |
||
187 | |||
188 | |||
189 | while (ls_length > 0) { |
||
190 | ND_TCHECK2(*tptr, 4); |
||
191 | if (ls_length < 4) { |
||
192 | ND_PRINT((ndo, "\n\t Remaining LS length %u < 4", ls_length)); |
||
193 | return -1; |
||
194 | } |
||
195 | tlv_type = EXTRACT_16BITS(tptr); |
||
196 | tlv_length = EXTRACT_16BITS(tptr+2); |
||
197 | tptr+=4; |
||
198 | ls_length-=4; |
||
199 | |||
200 | ND_PRINT((ndo, "\n\t %s TLV (%u), length %u, value: ", |
||
201 | tok2str(lsa_opaque_grace_tlv_values,"unknown",tlv_type), |
||
202 | tlv_type, |
||
203 | tlv_length)); |
||
204 | |||
205 | if (tlv_length > ls_length) { |
||
206 | ND_PRINT((ndo, "\n\t Bogus length %u > %u", tlv_length, |
||
207 | ls_length)); |
||
208 | return -1; |
||
209 | } |
||
210 | |||
211 | /* Infinite loop protection. */ |
||
212 | if (tlv_type == 0 || tlv_length ==0) { |
||
213 | return -1; |
||
214 | } |
||
215 | |||
216 | ND_TCHECK2(*tptr, tlv_length); |
||
217 | switch(tlv_type) { |
||
218 | |||
219 | case LS_OPAQUE_GRACE_TLV_PERIOD: |
||
220 | if (tlv_length != 4) { |
||
221 | ND_PRINT((ndo, "\n\t Bogus length %u != 4", tlv_length)); |
||
222 | return -1; |
||
223 | } |
||
224 | ND_PRINT((ndo, "%us", EXTRACT_32BITS(tptr))); |
||
225 | break; |
||
226 | |||
227 | case LS_OPAQUE_GRACE_TLV_REASON: |
||
228 | if (tlv_length != 1) { |
||
229 | ND_PRINT((ndo, "\n\t Bogus length %u != 1", tlv_length)); |
||
230 | return -1; |
||
231 | } |
||
232 | ND_PRINT((ndo, "%s (%u)", |
||
233 | tok2str(lsa_opaque_grace_tlv_reason_values, "Unknown", *tptr), |
||
234 | *tptr)); |
||
235 | break; |
||
236 | |||
237 | case LS_OPAQUE_GRACE_TLV_INT_ADDRESS: |
||
238 | if (tlv_length != 4) { |
||
239 | ND_PRINT((ndo, "\n\t Bogus length %u != 4", tlv_length)); |
||
240 | return -1; |
||
241 | } |
||
242 | ND_PRINT((ndo, "%s", ipaddr_string(ndo, tptr))); |
||
243 | break; |
||
244 | |||
245 | default: |
||
246 | if (ndo->ndo_vflag <= 1) { |
||
247 | if (!print_unknown_data(ndo, tptr, "\n\t ", tlv_length)) |
||
248 | return -1; |
||
249 | } |
||
250 | break; |
||
251 | |||
252 | } |
||
253 | /* in OSPF everything has to be 32-bit aligned, including TLVs */ |
||
254 | if (tlv_length%4 != 0) |
||
255 | tlv_length+=4-(tlv_length%4); |
||
256 | ls_length-=tlv_length; |
||
257 | tptr+=tlv_length; |
||
258 | } |
||
259 | |||
260 | return 0; |
||
261 | trunc: |
||
262 | return -1; |
||
263 | } |
||
264 | |||
265 | int |
||
266 | ospf_print_te_lsa(netdissect_options *ndo, |
||
267 | const uint8_t *tptr, u_int ls_length) |
||
268 | { |
||
269 | u_int tlv_type, tlv_length, subtlv_type, subtlv_length; |
||
270 | u_int priority_level, te_class, count_srlg; |
||
271 | union { /* int to float conversion buffer for several subTLVs */ |
||
272 | float f; |
||
273 | uint32_t i; |
||
274 | } bw; |
||
275 | |||
276 | while (ls_length != 0) { |
||
277 | ND_TCHECK2(*tptr, 4); |
||
278 | if (ls_length < 4) { |
||
279 | ND_PRINT((ndo, "\n\t Remaining LS length %u < 4", ls_length)); |
||
280 | return -1; |
||
281 | } |
||
282 | tlv_type = EXTRACT_16BITS(tptr); |
||
283 | tlv_length = EXTRACT_16BITS(tptr+2); |
||
284 | tptr+=4; |
||
285 | ls_length-=4; |
||
286 | |||
287 | ND_PRINT((ndo, "\n\t %s TLV (%u), length: %u", |
||
288 | tok2str(lsa_opaque_te_tlv_values,"unknown",tlv_type), |
||
289 | tlv_type, |
||
290 | tlv_length)); |
||
291 | |||
292 | if (tlv_length > ls_length) { |
||
293 | ND_PRINT((ndo, "\n\t Bogus length %u > %u", tlv_length, |
||
294 | ls_length)); |
||
295 | return -1; |
||
296 | } |
||
297 | |||
298 | /* Infinite loop protection. */ |
||
299 | if (tlv_type == 0 || tlv_length ==0) { |
||
300 | return -1; |
||
301 | } |
||
302 | |||
303 | switch(tlv_type) { |
||
304 | case LS_OPAQUE_TE_TLV_LINK: |
||
305 | while (tlv_length >= sizeof(subtlv_type) + sizeof(subtlv_length)) { |
||
306 | if (tlv_length < 4) { |
||
307 | ND_PRINT((ndo, "\n\t Remaining TLV length %u < 4", |
||
308 | tlv_length)); |
||
309 | return -1; |
||
310 | } |
||
311 | ND_TCHECK2(*tptr, 4); |
||
312 | subtlv_type = EXTRACT_16BITS(tptr); |
||
313 | subtlv_length = EXTRACT_16BITS(tptr+2); |
||
314 | tptr+=4; |
||
315 | tlv_length-=4; |
||
316 | |||
317 | ND_PRINT((ndo, "\n\t %s subTLV (%u), length: %u", |
||
318 | tok2str(lsa_opaque_te_link_tlv_subtlv_values,"unknown",subtlv_type), |
||
319 | subtlv_type, |
||
320 | subtlv_length)); |
||
321 | |||
322 | ND_TCHECK2(*tptr, subtlv_length); |
||
323 | switch(subtlv_type) { |
||
324 | case LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP: |
||
325 | ND_PRINT((ndo, ", 0x%08x", EXTRACT_32BITS(tptr))); |
||
326 | break; |
||
327 | case LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID: |
||
328 | case LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID: |
||
329 | ND_PRINT((ndo, ", %s (0x%08x)", |
||
330 | ipaddr_string(ndo, tptr), |
||
331 | EXTRACT_32BITS(tptr))); |
||
332 | if (subtlv_length == 8) /* rfc4203 */ |
||
333 | ND_PRINT((ndo, ", %s (0x%08x)", |
||
334 | ipaddr_string(ndo, tptr+4), |
||
335 | EXTRACT_32BITS(tptr + 4))); |
||
336 | break; |
||
337 | case LS_OPAQUE_TE_LINK_SUBTLV_LOCAL_IP: |
||
338 | case LS_OPAQUE_TE_LINK_SUBTLV_REMOTE_IP: |
||
339 | ND_PRINT((ndo, ", %s", ipaddr_string(ndo, tptr))); |
||
340 | break; |
||
341 | case LS_OPAQUE_TE_LINK_SUBTLV_MAX_BW: |
||
342 | case LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW: |
||
343 | bw.i = EXTRACT_32BITS(tptr); |
||
344 | ND_PRINT((ndo, ", %.3f Mbps", bw.f * 8 / 1000000)); |
||
345 | break; |
||
346 | case LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW: |
||
347 | for (te_class = 0; te_class < 8; te_class++) { |
||
348 | bw.i = EXTRACT_32BITS(tptr+te_class*4); |
||
349 | ND_PRINT((ndo, "\n\t\tTE-Class %u: %.3f Mbps", |
||
350 | te_class, |
||
351 | bw.f * 8 / 1000000)); |
||
352 | } |
||
353 | break; |
||
354 | case LS_OPAQUE_TE_LINK_SUBTLV_BW_CONSTRAINTS: |
||
355 | ND_PRINT((ndo, "\n\t\tBandwidth Constraints Model ID: %s (%u)", |
||
356 | tok2str(diffserv_te_bc_values, "unknown", *tptr), |
||
357 | *tptr)); |
||
358 | /* decode BCs until the subTLV ends */ |
||
359 | for (te_class = 0; te_class < (subtlv_length-4)/4; te_class++) { |
||
360 | bw.i = EXTRACT_32BITS(tptr+4+te_class*4); |
||
361 | ND_PRINT((ndo, "\n\t\t Bandwidth constraint CT%u: %.3f Mbps", |
||
362 | te_class, |
||
363 | bw.f * 8 / 1000000)); |
||
364 | } |
||
365 | break; |
||
366 | case LS_OPAQUE_TE_LINK_SUBTLV_TE_METRIC: |
||
367 | ND_PRINT((ndo, ", Metric %u", EXTRACT_32BITS(tptr))); |
||
368 | break; |
||
369 | case LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE: |
||
370 | ND_PRINT((ndo, ", %s, Priority %u", |
||
371 | bittok2str(gmpls_link_prot_values, "none", *tptr), |
||
372 | *(tptr + 1))); |
||
373 | break; |
||
374 | case LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR: |
||
375 | ND_PRINT((ndo, "\n\t\tInterface Switching Capability: %s", |
||
376 | tok2str(gmpls_switch_cap_values, "Unknown", *(tptr)))); |
||
377 | ND_PRINT((ndo, "\n\t\tLSP Encoding: %s\n\t\tMax LSP Bandwidth:", |
||
378 | tok2str(gmpls_encoding_values, "Unknown", *(tptr + 1)))); |
||
379 | for (priority_level = 0; priority_level < 8; priority_level++) { |
||
380 | bw.i = EXTRACT_32BITS(tptr+4+(priority_level*4)); |
||
381 | ND_PRINT((ndo, "\n\t\t priority level %d: %.3f Mbps", |
||
382 | priority_level, |
||
383 | bw.f * 8 / 1000000)); |
||
384 | } |
||
385 | break; |
||
386 | case LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE: |
||
387 | ND_PRINT((ndo, ", %s (%u)", |
||
388 | tok2str(lsa_opaque_te_tlv_link_type_sub_tlv_values,"unknown",*tptr), |
||
389 | *tptr)); |
||
390 | break; |
||
391 | |||
392 | case LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP: |
||
393 | count_srlg = subtlv_length / 4; |
||
394 | if (count_srlg != 0) |
||
395 | ND_PRINT((ndo, "\n\t\t Shared risk group: ")); |
||
396 | while (count_srlg > 0) { |
||
397 | bw.i = EXTRACT_32BITS(tptr); |
||
398 | ND_PRINT((ndo, "%d", bw.i)); |
||
399 | tptr+=4; |
||
400 | count_srlg--; |
||
401 | if (count_srlg > 0) |
||
402 | ND_PRINT((ndo, ", ")); |
||
403 | } |
||
404 | break; |
||
405 | |||
406 | default: |
||
407 | if (ndo->ndo_vflag <= 1) { |
||
408 | if (!print_unknown_data(ndo, tptr, "\n\t\t", subtlv_length)) |
||
409 | return -1; |
||
410 | } |
||
411 | break; |
||
412 | } |
||
413 | /* in OSPF everything has to be 32-bit aligned, including subTLVs */ |
||
414 | if (subtlv_length%4 != 0) |
||
415 | subtlv_length+=4-(subtlv_length%4); |
||
416 | |||
417 | tlv_length-=subtlv_length; |
||
418 | tptr+=subtlv_length; |
||
419 | |||
420 | } |
||
421 | break; |
||
422 | |||
423 | case LS_OPAQUE_TE_TLV_ROUTER: |
||
424 | if (tlv_length < 4) { |
||
425 | ND_PRINT((ndo, "\n\t TLV length %u < 4", tlv_length)); |
||
426 | return -1; |
||
427 | } |
||
428 | ND_TCHECK2(*tptr, 4); |
||
429 | ND_PRINT((ndo, ", %s", ipaddr_string(ndo, tptr))); |
||
430 | break; |
||
431 | |||
432 | default: |
||
433 | if (ndo->ndo_vflag <= 1) { |
||
434 | if (!print_unknown_data(ndo, tptr, "\n\t ", tlv_length)) |
||
435 | return -1; |
||
436 | } |
||
437 | break; |
||
438 | } |
||
439 | /* in OSPF everything has to be 32-bit aligned, including TLVs */ |
||
440 | if (tlv_length%4 != 0) |
||
441 | tlv_length+=4-(tlv_length%4); |
||
442 | ls_length-=tlv_length; |
||
443 | tptr+=tlv_length; |
||
444 | } |
||
445 | return 0; |
||
446 | trunc: |
||
447 | return -1; |
||
448 | } |
||
449 | |||
450 | static int |
||
451 | ospf_print_lshdr(netdissect_options *ndo, |
||
452 | register const struct lsa_hdr *lshp) |
||
453 | { |
||
454 | u_int ls_length; |
||
455 | |||
456 | ND_TCHECK(lshp->ls_length); |
||
457 | ls_length = EXTRACT_16BITS(&lshp->ls_length); |
||
458 | if (ls_length < sizeof(struct lsa_hdr)) { |
||
459 | ND_PRINT((ndo, "\n\t Bogus length %u < header (%lu)", ls_length, |
||
460 | (unsigned long)sizeof(struct lsa_hdr))); |
||
461 | return(-1); |
||
462 | } |
||
463 | |||
464 | ND_TCHECK(lshp->ls_seq); /* XXX - ls_length check checked this */ |
||
465 | ND_PRINT((ndo, "\n\t Advertising Router %s, seq 0x%08x, age %us, length %u", |
||
466 | ipaddr_string(ndo, &lshp->ls_router), |
||
467 | EXTRACT_32BITS(&lshp->ls_seq), |
||
468 | EXTRACT_16BITS(&lshp->ls_age), |
||
469 | ls_length - (u_int)sizeof(struct lsa_hdr))); |
||
470 | |||
471 | ND_TCHECK(lshp->ls_type); /* XXX - ls_length check checked this */ |
||
472 | switch (lshp->ls_type) { |
||
473 | /* the LSA header for opaque LSAs was slightly changed */ |
||
474 | case LS_TYPE_OPAQUE_LL: |
||
475 | case LS_TYPE_OPAQUE_AL: |
||
476 | case LS_TYPE_OPAQUE_DW: |
||
477 | ND_PRINT((ndo, "\n\t %s LSA (%d), Opaque-Type %s LSA (%u), Opaque-ID %u", |
||
478 | tok2str(lsa_values,"unknown",lshp->ls_type), |
||
479 | lshp->ls_type, |
||
480 | |||
481 | tok2str(lsa_opaque_values, |
||
482 | "unknown", |
||
483 | *(&lshp->un_lsa_id.opaque_field.opaque_type)), |
||
484 | *(&lshp->un_lsa_id.opaque_field.opaque_type), |
||
485 | EXTRACT_24BITS(&lshp->un_lsa_id.opaque_field.opaque_id) |
||
486 | |||
487 | )); |
||
488 | break; |
||
489 | |||
490 | /* all other LSA types use regular style LSA headers */ |
||
491 | default: |
||
492 | ND_PRINT((ndo, "\n\t %s LSA (%d), LSA-ID: %s", |
||
493 | tok2str(lsa_values,"unknown",lshp->ls_type), |
||
494 | lshp->ls_type, |
||
495 | ipaddr_string(ndo, &lshp->un_lsa_id.lsa_id))); |
||
496 | break; |
||
497 | } |
||
498 | |||
499 | ND_TCHECK(lshp->ls_options); /* XXX - ls_length check checked this */ |
||
500 | ND_PRINT((ndo, "\n\t Options: [%s]", bittok2str(ospf_option_values, "none", lshp->ls_options))); |
||
501 | |||
502 | return (ls_length); |
||
503 | trunc: |
||
504 | return (-1); |
||
505 | } |
||
506 | |||
507 | /* draft-ietf-ospf-mt-09 */ |
||
508 | static const struct tok ospf_topology_values[] = { |
||
509 | { 0, "default " }, |
||
510 | { 1, "multicast " }, |
||
511 | { 2, "management " }, |
||
512 | { 0, NULL } |
||
513 | }; |
||
514 | |||
515 | /* |
||
516 | * Print all the per-topology metrics. |
||
517 | */ |
||
518 | static void |
||
519 | ospf_print_tos_metrics(netdissect_options *ndo, |
||
520 | const union un_tos *tos) |
||
521 | { |
||
522 | int metric_count; |
||
523 | int toscount; |
||
524 | |||
525 | toscount = tos->link.link_tos_count+1; |
||
526 | metric_count = 0; |
||
527 | |||
528 | /* |
||
529 | * All but the first metric contain a valid topology id. |
||
530 | */ |
||
531 | while (toscount) { |
||
532 | ND_PRINT((ndo, "\n\t\ttopology %s(%u), metric %u", |
||
533 | tok2str(ospf_topology_values, "", |
||
534 | metric_count ? tos->metrics.tos_type : 0), |
||
535 | metric_count ? tos->metrics.tos_type : 0, |
||
536 | EXTRACT_16BITS(&tos->metrics.tos_metric))); |
||
537 | metric_count++; |
||
538 | tos++; |
||
539 | toscount--; |
||
540 | } |
||
541 | } |
||
542 | |||
543 | /* |
||
544 | * Print a single link state advertisement. If truncated or if LSA length |
||
545 | * field is less than the length of the LSA header, return NULl, else |
||
546 | * return pointer to data past end of LSA. |
||
547 | */ |
||
548 | static const uint8_t * |
||
549 | ospf_print_lsa(netdissect_options *ndo, |
||
550 | register const struct lsa *lsap) |
||
551 | { |
||
552 | register const uint8_t *ls_end; |
||
553 | register const struct rlalink *rlp; |
||
554 | register const struct in_addr *ap; |
||
555 | register const struct aslametric *almp; |
||
556 | register const struct mcla *mcp; |
||
557 | register const uint32_t *lp; |
||
558 | register int j, tlv_type, tlv_length, topology; |
||
559 | register int ls_length; |
||
560 | const uint8_t *tptr; |
||
561 | |||
562 | tptr = (uint8_t *)lsap->lsa_un.un_unknown; /* squelch compiler warnings */ |
||
563 | ls_length = ospf_print_lshdr(ndo, &lsap->ls_hdr); |
||
564 | if (ls_length == -1) |
||
565 | return(NULL); |
||
566 | ls_end = (uint8_t *)lsap + ls_length; |
||
567 | ls_length -= sizeof(struct lsa_hdr); |
||
568 | |||
569 | switch (lsap->ls_hdr.ls_type) { |
||
570 | |||
571 | case LS_TYPE_ROUTER: |
||
572 | ND_TCHECK(lsap->lsa_un.un_rla.rla_flags); |
||
573 | ND_PRINT((ndo, "\n\t Router LSA Options: [%s]", |
||
574 | bittok2str(ospf_rla_flag_values, "none", lsap->lsa_un.un_rla.rla_flags))); |
||
575 | |||
576 | ND_TCHECK(lsap->lsa_un.un_rla.rla_count); |
||
577 | j = EXTRACT_16BITS(&lsap->lsa_un.un_rla.rla_count); |
||
578 | ND_TCHECK(lsap->lsa_un.un_rla.rla_link); |
||
579 | rlp = lsap->lsa_un.un_rla.rla_link; |
||
580 | while (j--) { |
||
581 | ND_TCHECK(*rlp); |
||
582 | switch (rlp->un_tos.link.link_type) { |
||
583 | |||
584 | case RLA_TYPE_VIRTUAL: |
||
585 | ND_PRINT((ndo, "\n\t Virtual Link: Neighbor Router-ID: %s, Interface Address: %s", |
||
586 | ipaddr_string(ndo, &rlp->link_id), |
||
587 | ipaddr_string(ndo, &rlp->link_data))); |
||
588 | break; |
||
589 | |||
590 | case RLA_TYPE_ROUTER: |
||
591 | ND_PRINT((ndo, "\n\t Neighbor Router-ID: %s, Interface Address: %s", |
||
592 | ipaddr_string(ndo, &rlp->link_id), |
||
593 | ipaddr_string(ndo, &rlp->link_data))); |
||
594 | break; |
||
595 | |||
596 | case RLA_TYPE_TRANSIT: |
||
597 | ND_PRINT((ndo, "\n\t Neighbor Network-ID: %s, Interface Address: %s", |
||
598 | ipaddr_string(ndo, &rlp->link_id), |
||
599 | ipaddr_string(ndo, &rlp->link_data))); |
||
600 | break; |
||
601 | |||
602 | case RLA_TYPE_STUB: |
||
603 | ND_PRINT((ndo, "\n\t Stub Network: %s, Mask: %s", |
||
604 | ipaddr_string(ndo, &rlp->link_id), |
||
605 | ipaddr_string(ndo, &rlp->link_data))); |
||
606 | break; |
||
607 | |||
608 | default: |
||
609 | ND_PRINT((ndo, "\n\t Unknown Router Link Type (%u)", |
||
610 | rlp->un_tos.link.link_type)); |
||
611 | return (ls_end); |
||
612 | } |
||
613 | |||
614 | ospf_print_tos_metrics(ndo, &rlp->un_tos); |
||
615 | |||
616 | rlp = (struct rlalink *)((u_char *)(rlp + 1) + |
||
617 | ((rlp->un_tos.link.link_tos_count) * sizeof(union un_tos))); |
||
618 | } |
||
619 | break; |
||
620 | |||
621 | case LS_TYPE_NETWORK: |
||
622 | ND_TCHECK(lsap->lsa_un.un_nla.nla_mask); |
||
623 | ND_PRINT((ndo, "\n\t Mask %s\n\t Connected Routers:", |
||
624 | ipaddr_string(ndo, &lsap->lsa_un.un_nla.nla_mask))); |
||
625 | ap = lsap->lsa_un.un_nla.nla_router; |
||
626 | while ((u_char *)ap < ls_end) { |
||
627 | ND_TCHECK(*ap); |
||
628 | ND_PRINT((ndo, "\n\t %s", ipaddr_string(ndo, ap))); |
||
629 | ++ap; |
||
630 | } |
||
631 | break; |
||
632 | |||
633 | case LS_TYPE_SUM_IP: |
||
634 | ND_TCHECK(lsap->lsa_un.un_nla.nla_mask); |
||
635 | ND_PRINT((ndo, "\n\t Mask %s", |
||
636 | ipaddr_string(ndo, &lsap->lsa_un.un_sla.sla_mask))); |
||
637 | ND_TCHECK(lsap->lsa_un.un_sla.sla_tosmetric); |
||
638 | lp = lsap->lsa_un.un_sla.sla_tosmetric; |
||
639 | while ((u_char *)lp < ls_end) { |
||
640 | register uint32_t ul; |
||
641 | |||
642 | ND_TCHECK(*lp); |
||
643 | ul = EXTRACT_32BITS(lp); |
||
644 | topology = (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS; |
||
645 | ND_PRINT((ndo, "\n\t\ttopology %s(%u) metric %d", |
||
646 | tok2str(ospf_topology_values, "", topology), |
||
647 | topology, |
||
648 | ul & SLA_MASK_METRIC)); |
||
649 | ++lp; |
||
650 | } |
||
651 | break; |
||
652 | |||
653 | case LS_TYPE_SUM_ABR: |
||
654 | ND_TCHECK(lsap->lsa_un.un_sla.sla_tosmetric); |
||
655 | lp = lsap->lsa_un.un_sla.sla_tosmetric; |
||
656 | while ((u_char *)lp < ls_end) { |
||
657 | register uint32_t ul; |
||
658 | |||
659 | ND_TCHECK(*lp); |
||
660 | ul = EXTRACT_32BITS(lp); |
||
661 | topology = (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS; |
||
662 | ND_PRINT((ndo, "\n\t\ttopology %s(%u) metric %d", |
||
663 | tok2str(ospf_topology_values, "", topology), |
||
664 | topology, |
||
665 | ul & SLA_MASK_METRIC)); |
||
666 | ++lp; |
||
667 | } |
||
668 | break; |
||
669 | |||
670 | case LS_TYPE_ASE: |
||
671 | case LS_TYPE_NSSA: /* fall through - those LSAs share the same format */ |
||
672 | ND_TCHECK(lsap->lsa_un.un_nla.nla_mask); |
||
673 | ND_PRINT((ndo, "\n\t Mask %s", |
||
674 | ipaddr_string(ndo, &lsap->lsa_un.un_asla.asla_mask))); |
||
675 | |||
676 | ND_TCHECK(lsap->lsa_un.un_sla.sla_tosmetric); |
||
677 | almp = lsap->lsa_un.un_asla.asla_metric; |
||
678 | while ((u_char *)almp < ls_end) { |
||
679 | register uint32_t ul; |
||
680 | |||
681 | ND_TCHECK(almp->asla_tosmetric); |
||
682 | ul = EXTRACT_32BITS(&almp->asla_tosmetric); |
||
683 | topology = ((ul & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS); |
||
684 | ND_PRINT((ndo, "\n\t\ttopology %s(%u), type %d, metric", |
||
685 | tok2str(ospf_topology_values, "", topology), |
||
686 | topology, |
||
687 | (ul & ASLA_FLAG_EXTERNAL) ? 2 : 1)); |
||
688 | if ((ul & ASLA_MASK_METRIC) == 0xffffff) |
||
689 | ND_PRINT((ndo, " infinite")); |
||
690 | else |
||
691 | ND_PRINT((ndo, " %d", (ul & ASLA_MASK_METRIC))); |
||
692 | |||
693 | ND_TCHECK(almp->asla_forward); |
||
694 | if (almp->asla_forward.s_addr) { |
||
695 | ND_PRINT((ndo, ", forward %s", ipaddr_string(ndo, &almp->asla_forward))); |
||
696 | } |
||
697 | ND_TCHECK(almp->asla_tag); |
||
698 | if (almp->asla_tag.s_addr) { |
||
699 | ND_PRINT((ndo, ", tag %s", ipaddr_string(ndo, &almp->asla_tag))); |
||
700 | } |
||
701 | ++almp; |
||
702 | } |
||
703 | break; |
||
704 | |||
705 | case LS_TYPE_GROUP: |
||
706 | /* Multicast extensions as of 23 July 1991 */ |
||
707 | mcp = lsap->lsa_un.un_mcla; |
||
708 | while ((u_char *)mcp < ls_end) { |
||
709 | ND_TCHECK(mcp->mcla_vid); |
||
710 | switch (EXTRACT_32BITS(&mcp->mcla_vtype)) { |
||
711 | |||
712 | case MCLA_VERTEX_ROUTER: |
||
713 | ND_PRINT((ndo, "\n\t Router Router-ID %s", |
||
714 | ipaddr_string(ndo, &mcp->mcla_vid))); |
||
715 | break; |
||
716 | |||
717 | case MCLA_VERTEX_NETWORK: |
||
718 | ND_PRINT((ndo, "\n\t Network Designated Router %s", |
||
719 | ipaddr_string(ndo, &mcp->mcla_vid))); |
||
720 | break; |
||
721 | |||
722 | default: |
||
723 | ND_PRINT((ndo, "\n\t unknown VertexType (%u)", |
||
724 | EXTRACT_32BITS(&mcp->mcla_vtype))); |
||
725 | break; |
||
726 | } |
||
727 | ++mcp; |
||
728 | } |
||
729 | break; |
||
730 | |||
731 | case LS_TYPE_OPAQUE_LL: /* fall through */ |
||
732 | case LS_TYPE_OPAQUE_AL: |
||
733 | case LS_TYPE_OPAQUE_DW: |
||
734 | |||
735 | switch (*(&lsap->ls_hdr.un_lsa_id.opaque_field.opaque_type)) { |
||
736 | case LS_OPAQUE_TYPE_RI: |
||
737 | tptr = (uint8_t *)(&lsap->lsa_un.un_ri_tlv.type); |
||
738 | |||
739 | while (ls_length != 0) { |
||
740 | ND_TCHECK2(*tptr, 4); |
||
741 | if (ls_length < 4) { |
||
742 | ND_PRINT((ndo, "\n\t Remaining LS length %u < 4", ls_length)); |
||
743 | return(ls_end); |
||
744 | } |
||
745 | tlv_type = EXTRACT_16BITS(tptr); |
||
746 | tlv_length = EXTRACT_16BITS(tptr+2); |
||
747 | tptr+=4; |
||
748 | ls_length-=4; |
||
749 | |||
750 | ND_PRINT((ndo, "\n\t %s TLV (%u), length: %u, value: ", |
||
751 | tok2str(lsa_opaque_ri_tlv_values,"unknown",tlv_type), |
||
752 | tlv_type, |
||
753 | tlv_length)); |
||
754 | |||
755 | if (tlv_length > ls_length) { |
||
756 | ND_PRINT((ndo, "\n\t Bogus length %u > %u", tlv_length, |
||
757 | ls_length)); |
||
758 | return(ls_end); |
||
759 | } |
||
760 | ND_TCHECK2(*tptr, tlv_length); |
||
761 | switch(tlv_type) { |
||
762 | |||
763 | case LS_OPAQUE_RI_TLV_CAP: |
||
764 | if (tlv_length != 4) { |
||
765 | ND_PRINT((ndo, "\n\t Bogus length %u != 4", tlv_length)); |
||
766 | return(ls_end); |
||
767 | } |
||
768 | ND_PRINT((ndo, "Capabilities: %s", |
||
769 | bittok2str(lsa_opaque_ri_tlv_cap_values, "Unknown", EXTRACT_32BITS(tptr)))); |
||
770 | break; |
||
771 | default: |
||
772 | if (ndo->ndo_vflag <= 1) { |
||
773 | if (!print_unknown_data(ndo, tptr, "\n\t ", tlv_length)) |
||
774 | return(ls_end); |
||
775 | } |
||
776 | break; |
||
777 | |||
778 | } |
||
779 | tptr+=tlv_length; |
||
780 | ls_length-=tlv_length; |
||
781 | } |
||
782 | break; |
||
783 | |||
784 | case LS_OPAQUE_TYPE_GRACE: |
||
785 | if (ospf_print_grace_lsa(ndo, (uint8_t *)(&lsap->lsa_un.un_grace_tlv.type), |
||
786 | ls_length) == -1) { |
||
787 | return(ls_end); |
||
788 | } |
||
789 | break; |
||
790 | |||
791 | case LS_OPAQUE_TYPE_TE: |
||
792 | if (ospf_print_te_lsa(ndo, (uint8_t *)(&lsap->lsa_un.un_te_lsa_tlv.type), |
||
793 | ls_length) == -1) { |
||
794 | return(ls_end); |
||
795 | } |
||
796 | break; |
||
797 | |||
798 | default: |
||
799 | if (ndo->ndo_vflag <= 1) { |
||
800 | if (!print_unknown_data(ndo, (uint8_t *)lsap->lsa_un.un_unknown, |
||
801 | "\n\t ", ls_length)) |
||
802 | return(ls_end); |
||
803 | } |
||
804 | break; |
||
805 | } |
||
806 | } |
||
807 | |||
808 | /* do we want to see an additionally hexdump ? */ |
||
809 | if (ndo->ndo_vflag> 1) |
||
810 | if (!print_unknown_data(ndo, (uint8_t *)lsap->lsa_un.un_unknown, |
||
811 | "\n\t ", ls_length)) { |
||
812 | return(ls_end); |
||
813 | } |
||
814 | |||
815 | return (ls_end); |
||
816 | trunc: |
||
817 | return (NULL); |
||
818 | } |
||
819 | |||
820 | static int |
||
821 | ospf_decode_lls(netdissect_options *ndo, |
||
822 | register const struct ospfhdr *op, register u_int length) |
||
823 | { |
||
824 | register const u_char *dptr; |
||
825 | register const u_char *dataend; |
||
826 | register u_int length2; |
||
827 | register uint16_t lls_type, lls_len; |
||
828 | register uint32_t lls_flags; |
||
829 | |||
830 | switch (op->ospf_type) { |
||
831 | |||
832 | case OSPF_TYPE_HELLO: |
||
833 | if (!(op->ospf_hello.hello_options & OSPF_OPTION_L)) |
||
834 | return (0); |
||
835 | break; |
||
836 | |||
837 | case OSPF_TYPE_DD: |
||
838 | if (!(op->ospf_db.db_options & OSPF_OPTION_L)) |
||
839 | return (0); |
||
840 | break; |
||
841 | |||
842 | default: |
||
843 | return (0); |
||
844 | } |
||
845 | |||
846 | /* dig deeper if LLS data is available; see RFC4813 */ |
||
847 | length2 = EXTRACT_16BITS(&op->ospf_len); |
||
848 | dptr = (u_char *)op + length2; |
||
849 | dataend = (u_char *)op + length; |
||
850 | |||
851 | if (EXTRACT_16BITS(&op->ospf_authtype) == OSPF_AUTH_MD5) { |
||
852 | dptr = dptr + op->ospf_authdata[3]; |
||
853 | length2 += op->ospf_authdata[3]; |
||
854 | } |
||
855 | if (length2 >= length) { |
||
856 | ND_PRINT((ndo, "\n\t[LLS truncated]")); |
||
857 | return (1); |
||
858 | } |
||
859 | ND_TCHECK2(*dptr, 2); |
||
860 | ND_PRINT((ndo, "\n\t LLS: checksum: 0x%04x", (u_int)EXTRACT_16BITS(dptr))); |
||
861 | |||
862 | dptr += 2; |
||
863 | ND_TCHECK2(*dptr, 2); |
||
864 | length2 = EXTRACT_16BITS(dptr); |
||
865 | ND_PRINT((ndo, ", length: %u", length2)); |
||
866 | |||
867 | dptr += 2; |
||
868 | ND_TCHECK(*dptr); |
||
869 | while (dptr < dataend) { |
||
870 | ND_TCHECK2(*dptr, 2); |
||
871 | lls_type = EXTRACT_16BITS(dptr); |
||
872 | ND_PRINT((ndo, "\n\t %s (%u)", |
||
873 | tok2str(ospf_lls_tlv_values,"Unknown TLV",lls_type), |
||
874 | lls_type)); |
||
875 | dptr += 2; |
||
876 | ND_TCHECK2(*dptr, 2); |
||
877 | lls_len = EXTRACT_16BITS(dptr); |
||
878 | ND_PRINT((ndo, ", length: %u", lls_len)); |
||
879 | dptr += 2; |
||
880 | switch (lls_type) { |
||
881 | |||
882 | case OSPF_LLS_EO: |
||
883 | if (lls_len != 4) { |
||
884 | ND_PRINT((ndo, " [should be 4]")); |
||
885 | lls_len = 4; |
||
886 | } |
||
887 | ND_TCHECK2(*dptr, 4); |
||
888 | lls_flags = EXTRACT_32BITS(dptr); |
||
889 | ND_PRINT((ndo, "\n\t Options: 0x%08x [%s]", lls_flags, |
||
890 | bittok2str(ospf_lls_eo_options, "?", lls_flags))); |
||
891 | |||
892 | break; |
||
893 | |||
894 | case OSPF_LLS_MD5: |
||
895 | if (lls_len != 20) { |
||
896 | ND_PRINT((ndo, " [should be 20]")); |
||
897 | lls_len = 20; |
||
898 | } |
||
899 | ND_TCHECK2(*dptr, 4); |
||
900 | ND_PRINT((ndo, "\n\t Sequence number: 0x%08x", EXTRACT_32BITS(dptr))); |
||
901 | break; |
||
902 | } |
||
903 | |||
904 | dptr += lls_len; |
||
905 | } |
||
906 | |||
907 | return (0); |
||
908 | trunc: |
||
909 | return (1); |
||
910 | } |
||
911 | |||
912 | static int |
||
913 | ospf_decode_v2(netdissect_options *ndo, |
||
914 | register const struct ospfhdr *op, register const u_char *dataend) |
||
915 | { |
||
916 | register const struct in_addr *ap; |
||
917 | register const struct lsr *lsrp; |
||
918 | register const struct lsa_hdr *lshp; |
||
919 | register const struct lsa *lsap; |
||
920 | register uint32_t lsa_count,lsa_count_max; |
||
921 | |||
922 | switch (op->ospf_type) { |
||
923 | |||
924 | case OSPF_TYPE_UMD: |
||
925 | /* |
||
926 | * Rob Coltun's special monitoring packets; |
||
927 | * do nothing |
||
928 | */ |
||
929 | break; |
||
930 | |||
931 | case OSPF_TYPE_HELLO: |
||
932 | ND_PRINT((ndo, "\n\tOptions [%s]", |
||
933 | bittok2str(ospf_option_values,"none",op->ospf_hello.hello_options))); |
||
934 | |||
935 | ND_TCHECK(op->ospf_hello.hello_deadint); |
||
936 | ND_PRINT((ndo, "\n\t Hello Timer %us, Dead Timer %us, Mask %s, Priority %u", |
||
937 | EXTRACT_16BITS(&op->ospf_hello.hello_helloint), |
||
938 | EXTRACT_32BITS(&op->ospf_hello.hello_deadint), |
||
939 | ipaddr_string(ndo, &op->ospf_hello.hello_mask), |
||
940 | op->ospf_hello.hello_priority)); |
||
941 | |||
942 | ND_TCHECK(op->ospf_hello.hello_dr); |
||
943 | if (op->ospf_hello.hello_dr.s_addr != 0) |
||
944 | ND_PRINT((ndo, "\n\t Designated Router %s", |
||
945 | ipaddr_string(ndo, &op->ospf_hello.hello_dr))); |
||
946 | |||
947 | ND_TCHECK(op->ospf_hello.hello_bdr); |
||
948 | if (op->ospf_hello.hello_bdr.s_addr != 0) |
||
949 | ND_PRINT((ndo, ", Backup Designated Router %s", |
||
950 | ipaddr_string(ndo, &op->ospf_hello.hello_bdr))); |
||
951 | |||
952 | ap = op->ospf_hello.hello_neighbor; |
||
953 | if ((u_char *)ap < dataend) |
||
954 | ND_PRINT((ndo, "\n\t Neighbor List:")); |
||
955 | while ((u_char *)ap < dataend) { |
||
956 | ND_TCHECK(*ap); |
||
957 | ND_PRINT((ndo, "\n\t %s", ipaddr_string(ndo, ap))); |
||
958 | ++ap; |
||
959 | } |
||
960 | break; /* HELLO */ |
||
961 | |||
962 | case OSPF_TYPE_DD: |
||
963 | ND_TCHECK(op->ospf_db.db_options); |
||
964 | ND_PRINT((ndo, "\n\tOptions [%s]", |
||
965 | bittok2str(ospf_option_values, "none", op->ospf_db.db_options))); |
||
966 | ND_TCHECK(op->ospf_db.db_flags); |
||
967 | ND_PRINT((ndo, ", DD Flags [%s]", |
||
968 | bittok2str(ospf_dd_flag_values, "none", op->ospf_db.db_flags))); |
||
969 | ND_TCHECK(op->ospf_db.db_ifmtu); |
||
970 | if (op->ospf_db.db_ifmtu) { |
||
971 | ND_PRINT((ndo, ", MTU: %u", EXTRACT_16BITS(&op->ospf_db.db_ifmtu))); |
||
972 | } |
||
973 | ND_TCHECK(op->ospf_db.db_seq); |
||
974 | ND_PRINT((ndo, ", Sequence: 0x%08x", EXTRACT_32BITS(&op->ospf_db.db_seq))); |
||
975 | |||
976 | /* Print all the LS adv's */ |
||
977 | lshp = op->ospf_db.db_lshdr; |
||
978 | while (((u_char *)lshp < dataend) && ospf_print_lshdr(ndo, lshp) != -1) { |
||
979 | ++lshp; |
||
980 | } |
||
981 | break; |
||
982 | |||
983 | case OSPF_TYPE_LS_REQ: |
||
984 | lsrp = op->ospf_lsr; |
||
985 | while ((u_char *)lsrp < dataend) { |
||
986 | ND_TCHECK(*lsrp); |
||
987 | |||
988 | ND_PRINT((ndo, "\n\t Advertising Router: %s, %s LSA (%u)", |
||
989 | ipaddr_string(ndo, &lsrp->ls_router), |
||
990 | tok2str(lsa_values,"unknown",EXTRACT_32BITS(lsrp->ls_type)), |
||
991 | EXTRACT_32BITS(&lsrp->ls_type))); |
||
992 | |||
993 | switch (EXTRACT_32BITS(lsrp->ls_type)) { |
||
994 | /* the LSA header for opaque LSAs was slightly changed */ |
||
995 | case LS_TYPE_OPAQUE_LL: |
||
996 | case LS_TYPE_OPAQUE_AL: |
||
997 | case LS_TYPE_OPAQUE_DW: |
||
998 | ND_PRINT((ndo, ", Opaque-Type: %s LSA (%u), Opaque-ID: %u", |
||
999 | tok2str(lsa_opaque_values, "unknown",lsrp->un_ls_stateid.opaque_field.opaque_type), |
||
1000 | lsrp->un_ls_stateid.opaque_field.opaque_type, |
||
1001 | EXTRACT_24BITS(&lsrp->un_ls_stateid.opaque_field.opaque_id))); |
||
1002 | break; |
||
1003 | default: |
||
1004 | ND_PRINT((ndo, ", LSA-ID: %s", |
||
1005 | ipaddr_string(ndo, &lsrp->un_ls_stateid.ls_stateid))); |
||
1006 | break; |
||
1007 | } |
||
1008 | |||
1009 | ++lsrp; |
||
1010 | } |
||
1011 | break; |
||
1012 | |||
1013 | case OSPF_TYPE_LS_UPDATE: |
||
1014 | lsap = op->ospf_lsu.lsu_lsa; |
||
1015 | ND_TCHECK(op->ospf_lsu.lsu_count); |
||
1016 | lsa_count_max = EXTRACT_32BITS(&op->ospf_lsu.lsu_count); |
||
1017 | ND_PRINT((ndo, ", %d LSA%s", lsa_count_max, PLURAL_SUFFIX(lsa_count_max))); |
||
1018 | for (lsa_count=1;lsa_count <= lsa_count_max;lsa_count++) { |
||
1019 | ND_PRINT((ndo, "\n\t LSA #%u", lsa_count)); |
||
1020 | lsap = (const struct lsa *)ospf_print_lsa(ndo, lsap); |
||
1021 | if (lsap == NULL) |
||
1022 | goto trunc; |
||
1023 | } |
||
1024 | break; |
||
1025 | |||
1026 | case OSPF_TYPE_LS_ACK: |
||
1027 | lshp = op->ospf_lsa.lsa_lshdr; |
||
1028 | while (ospf_print_lshdr(ndo, lshp) != -1) { |
||
1029 | ++lshp; |
||
1030 | } |
||
1031 | break; |
||
1032 | |||
1033 | default: |
||
1034 | break; |
||
1035 | } |
||
1036 | return (0); |
||
1037 | trunc: |
||
1038 | return (1); |
||
1039 | } |
||
1040 | |||
1041 | void |
||
1042 | ospf_print(netdissect_options *ndo, |
||
1043 | register const u_char *bp, register u_int length, |
||
1044 | const u_char *bp2 _U_) |
||
1045 | { |
||
1046 | register const struct ospfhdr *op; |
||
1047 | register const u_char *dataend; |
||
1048 | register const char *cp; |
||
1049 | |||
1050 | op = (struct ospfhdr *)bp; |
||
1051 | |||
1052 | /* XXX Before we do anything else, strip off the MD5 trailer */ |
||
1053 | ND_TCHECK(op->ospf_authtype); |
||
1054 | if (EXTRACT_16BITS(&op->ospf_authtype) == OSPF_AUTH_MD5) { |
||
1055 | length -= OSPF_AUTH_MD5_LEN; |
||
1056 | ndo->ndo_snapend -= OSPF_AUTH_MD5_LEN; |
||
1057 | } |
||
1058 | |||
1059 | /* If the type is valid translate it, or just print the type */ |
||
1060 | /* value. If it's not valid, say so and return */ |
||
1061 | ND_TCHECK(op->ospf_type); |
||
1062 | cp = tok2str(type2str, "unknown LS-type", op->ospf_type); |
||
1063 | ND_PRINT((ndo, "OSPFv%u, %s, length %u", op->ospf_version, cp, length)); |
||
1064 | if (*cp == 'u') |
||
1065 | return; |
||
1066 | |||
1067 | if (!ndo->ndo_vflag) { /* non verbose - so lets bail out here */ |
||
1068 | return; |
||
1069 | } |
||
1070 | |||
1071 | ND_TCHECK(op->ospf_len); |
||
1072 | if (length != EXTRACT_16BITS(&op->ospf_len)) { |
||
1073 | ND_PRINT((ndo, " [len %d]", EXTRACT_16BITS(&op->ospf_len))); |
||
1074 | } |
||
1075 | |||
1076 | if (length > EXTRACT_16BITS(&op->ospf_len)) { |
||
1077 | dataend = bp + EXTRACT_16BITS(&op->ospf_len); |
||
1078 | } else { |
||
1079 | dataend = bp + length; |
||
1080 | } |
||
1081 | |||
1082 | ND_TCHECK(op->ospf_routerid); |
||
1083 | ND_PRINT((ndo, "\n\tRouter-ID %s", ipaddr_string(ndo, &op->ospf_routerid))); |
||
1084 | |||
1085 | ND_TCHECK(op->ospf_areaid); |
||
1086 | if (op->ospf_areaid.s_addr != 0) |
||
1087 | ND_PRINT((ndo, ", Area %s", ipaddr_string(ndo, &op->ospf_areaid))); |
||
1088 | else |
||
1089 | ND_PRINT((ndo, ", Backbone Area")); |
||
1090 | |||
1091 | if (ndo->ndo_vflag) { |
||
1092 | /* Print authentication data (should we really do this?) */ |
||
1093 | ND_TCHECK2(op->ospf_authdata[0], sizeof(op->ospf_authdata)); |
||
1094 | |||
1095 | ND_PRINT((ndo, ", Authentication Type: %s (%u)", |
||
1096 | tok2str(ospf_authtype_values, "unknown", EXTRACT_16BITS(&op->ospf_authtype)), |
||
1097 | EXTRACT_16BITS(&op->ospf_authtype))); |
||
1098 | |||
1099 | switch (EXTRACT_16BITS(&op->ospf_authtype)) { |
||
1100 | |||
1101 | case OSPF_AUTH_NONE: |
||
1102 | break; |
||
1103 | |||
1104 | case OSPF_AUTH_SIMPLE: |
||
1105 | ND_PRINT((ndo, "\n\tSimple text password: ")); |
||
1106 | safeputs(ndo, op->ospf_authdata, OSPF_AUTH_SIMPLE_LEN); |
||
1107 | break; |
||
1108 | |||
1109 | case OSPF_AUTH_MD5: |
||
1110 | ND_PRINT((ndo, "\n\tKey-ID: %u, Auth-Length: %u, Crypto Sequence Number: 0x%08x", |
||
1111 | *((op->ospf_authdata) + 2), |
||
1112 | *((op->ospf_authdata) + 3), |
||
1113 | EXTRACT_32BITS((op->ospf_authdata) + 4))); |
||
1114 | break; |
||
1115 | |||
1116 | default: |
||
1117 | return; |
||
1118 | } |
||
1119 | } |
||
1120 | /* Do rest according to version. */ |
||
1121 | switch (op->ospf_version) { |
||
1122 | |||
1123 | case 2: |
||
1124 | /* ospf version 2 */ |
||
1125 | if (ospf_decode_v2(ndo, op, dataend)) |
||
1126 | goto trunc; |
||
1127 | if (length > EXTRACT_16BITS(&op->ospf_len)) { |
||
1128 | if (ospf_decode_lls(ndo, op, length)) |
||
1129 | goto trunc; |
||
1130 | } |
||
1131 | break; |
||
1132 | |||
1133 | default: |
||
1134 | ND_PRINT((ndo, " ospf [version %d]", op->ospf_version)); |
||
1135 | break; |
||
1136 | } /* end switch on version */ |
||
1137 | |||
1138 | return; |
||
1139 | trunc: |
||
1140 | ND_PRINT((ndo, "%s", tstr)); |
||
1141 | } |