]> The Tcpdump Group git mirrors - tcpdump/blob - print-ospf.c
The "__attribute__((packed))" tag on structures causes some files not to
[tcpdump] / print-ospf.c
1 /*
2 * Copyright (c) 1992, 1993, 1994, 1995, 1996, 1997
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 *
21 * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu)
22 */
23
24 #ifndef lint
25 static const char rcsid[] =
26 "@(#) $Header: /tcpdump/master/tcpdump/print-ospf.c,v 1.35 2002-12-11 07:14:06 guy Exp $ (LBL)";
27 #endif
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <tcpdump-stdinc.h>
34
35 #include <stdio.h>
36
37 #include "interface.h"
38 #include "addrtoname.h"
39 #include "extract.h"
40
41 #include "ospf.h"
42
43 #include "ip.h"
44
45 static struct tok ospf_option_values[] = {
46 { OSPF_OPTION_T, "TOS" },
47 { OSPF_OPTION_E, "External" },
48 { OSPF_OPTION_MC, "Multicast" },
49 { OSPF_OPTION_NP, "NSSA" },
50 { OSPF_OPTION_EA, "Advertise External" },
51 { OSPF_OPTION_DC, "Demand Circuit" },
52 { OSPF_OPTION_O, "Opaque" },
53 { 0, NULL }
54 };
55
56 static struct tok ospf_rla_flag_values[] = {
57 { RLA_FLAG_B, "ABR" },
58 { RLA_FLAG_E, "ASBR" },
59 { RLA_FLAG_W1, "Virtual" },
60 { RLA_FLAG_W2, "W2" },
61 { 0, NULL }
62 };
63
64 static struct tok type2str[] = {
65 { OSPF_TYPE_UMD, "UMD" },
66 { OSPF_TYPE_HELLO, "Hello" },
67 { OSPF_TYPE_DD, "Database Description" },
68 { OSPF_TYPE_LS_REQ, "LS-Request" },
69 { OSPF_TYPE_LS_UPDATE, "LS-Update" },
70 { OSPF_TYPE_LS_ACK, "LS-Ack" },
71 { 0, NULL }
72 };
73
74 static struct tok lsa_values[] = {
75 { LS_TYPE_ROUTER, "Router" },
76 { LS_TYPE_NETWORK, "Network" },
77 { LS_TYPE_SUM_IP, "Summary" },
78 { LS_TYPE_SUM_ABR, "ASBR Summary" },
79 { LS_TYPE_ASE, "External" },
80 { LS_TYPE_GROUP, "Multicast Group" },
81 { LS_TYPE_NSSA, "NSSA" },
82 { LS_TYPE_OPAQUE_LL, "Link Local Opaque" },
83 { LS_TYPE_OPAQUE_AL, "Area Local Opaque" },
84 { LS_TYPE_OPAQUE_DW, "Domain Wide Opaque" },
85 { 0, NULL }
86 };
87
88 static struct tok ospf_dd_flag_values[] = {
89 { OSPF_DB_INIT, "Init" },
90 { OSPF_DB_MORE, "More" },
91 { OSPF_DB_MASTER, "Master" },
92 { 0, NULL }
93 };
94
95 static char tstr[] = " [|ospf]";
96
97 #ifdef WIN32
98 #define inline __inline
99 #endif /* WIN32 */
100
101 static int ospf_print_lshdr(const struct lsa_hdr *);
102 static int ospf_print_lsa(const struct lsa *);
103 static int ospf_decode_v2(const struct ospfhdr *, const u_char *);
104
105 static int
106 ospf_print_lshdr(register const struct lsa_hdr *lshp) {
107
108 TCHECK(lshp->ls_type);
109 TCHECK(lshp->ls_options);
110
111 printf("\n\t %s LSA (%d), LSA-ID: %s, Advertising Router: %s, seq 0x%08x, age %us",
112 tok2str(lsa_values,"unknown",lshp->ls_type),
113 lshp->ls_type,
114 ipaddr_string(&lshp->ls_stateid),
115 ipaddr_string(&lshp->ls_router),
116 EXTRACT_32BITS(&lshp->ls_seq),
117 EXTRACT_16BITS(&lshp->ls_age));
118 printf("\n\t Options: %s", bittok2str(ospf_option_values,"none",lshp->ls_options));
119
120 return (0);
121 trunc:
122 return (1);
123 }
124
125 /*
126 * Print a single link state advertisement. If truncated return 1, else 0.
127 */
128 static int
129 ospf_print_lsa(register const struct lsa *lsap)
130 {
131 register const u_char *ls_end;
132 register const struct rlalink *rlp;
133 register const struct tos_metric *tosp;
134 register const struct in_addr *ap;
135 register const struct aslametric *almp;
136 register const struct mcla *mcp;
137 register const u_int32_t *lp;
138 register int j, k;
139
140 printf("\n\t %s LSA (%d), LSA-ID: %s, Advertising Router: %s, seq 0x%08x, age %us",
141 tok2str(lsa_values,"unknown",lsap->ls_hdr.ls_type),
142 lsap->ls_hdr.ls_type,
143 ipaddr_string(&lsap->ls_hdr.ls_stateid),
144 ipaddr_string(&lsap->ls_hdr.ls_router),
145 EXTRACT_32BITS(&lsap->ls_hdr.ls_seq),
146 EXTRACT_16BITS(&lsap->ls_hdr.ls_age));
147 printf("\n\t Options: %s", bittok2str(ospf_option_values,"none",lsap->ls_hdr.ls_options));
148
149 TCHECK(lsap->ls_hdr.ls_length);
150 ls_end = (u_char *)lsap + EXTRACT_16BITS(&lsap->ls_hdr.ls_length);
151 switch (lsap->ls_hdr.ls_type) {
152
153 case LS_TYPE_ROUTER:
154 TCHECK(lsap->lsa_un.un_rla.rla_flags);
155 printf("\n\t Router LSA Options: %s", bittok2str(ospf_rla_flag_values,"unknown (%u)",lsap->lsa_un.un_rla.rla_flags));
156
157 TCHECK(lsap->lsa_un.un_rla.rla_count);
158 j = EXTRACT_16BITS(&lsap->lsa_un.un_rla.rla_count);
159 TCHECK(lsap->lsa_un.un_rla.rla_link);
160 rlp = lsap->lsa_un.un_rla.rla_link;
161 while (j--) {
162 TCHECK(*rlp);
163 switch (rlp->link_type) {
164
165 case RLA_TYPE_VIRTUAL:
166 printf("\n\t Virtual Link: Neighbor-Router-ID: %s, Interface-IP: %s",
167 ipaddr_string(&rlp->link_id),
168 ipaddr_string(&rlp->link_data));
169 break;
170
171 case RLA_TYPE_ROUTER:
172 printf("\n\t Neighbor-Router-ID: %s, Interface-IP: %s",
173 ipaddr_string(&rlp->link_id),
174 ipaddr_string(&rlp->link_data));
175 break;
176
177 case RLA_TYPE_TRANSIT:
178 printf("\n\t Neighbor-Network-ID: %s, Interface-IP: %s",
179 ipaddr_string(&rlp->link_id),
180 ipaddr_string(&rlp->link_data));
181 break;
182
183 case RLA_TYPE_STUB:
184 printf("\n\t Stub-Network: %s, mask: %s",
185 ipaddr_string(&rlp->link_id),
186 ipaddr_string(&rlp->link_data));
187 break;
188
189 default:
190 printf("\n\t unknown Router Links Type (%u)",
191 rlp->link_type);
192 return (0);
193 }
194 printf(", tos 0, metric: %d", EXTRACT_16BITS(&rlp->link_tos0metric));
195 tosp = (struct tos_metric *)
196 ((sizeof rlp->link_tos0metric) + (u_char *) rlp);
197 for (k = 0; k < (int) rlp->link_toscount; ++k, ++tosp) {
198 TCHECK(*tosp);
199 printf(", tos %d, metric: %d",
200 tosp->tos_type,
201 EXTRACT_16BITS(&tosp->tos_metric));
202 }
203 rlp = (struct rlalink *)((u_char *)(rlp + 1) +
204 ((rlp->link_toscount) * sizeof(*tosp)));
205 }
206 break;
207
208 case LS_TYPE_NETWORK:
209 TCHECK(lsap->lsa_un.un_nla.nla_mask);
210 printf("\n\t mask %s rtrs",
211 ipaddr_string(&lsap->lsa_un.un_nla.nla_mask));
212 ap = lsap->lsa_un.un_nla.nla_router;
213 while ((u_char *)ap < ls_end) {
214 TCHECK(*ap);
215 printf(" %s", ipaddr_string(ap));
216 ++ap;
217 }
218 break;
219
220 case LS_TYPE_SUM_IP:
221 TCHECK(lsap->lsa_un.un_nla.nla_mask);
222 printf("\n\t mask %s",
223 ipaddr_string(&lsap->lsa_un.un_sla.sla_mask));
224 TCHECK(lsap->lsa_un.un_sla.sla_tosmetric);
225 lp = lsap->lsa_un.un_sla.sla_tosmetric;
226 /* suppress tos if its not supported */
227 if(!((lsap->ls_hdr.ls_options)&OSPF_OPTION_T)) {
228 printf(", metric: %u", EXTRACT_32BITS(lp)&SLA_MASK_METRIC);
229 break;
230 }
231 while ((u_char *)lp < ls_end) {
232 register u_int32_t ul;
233
234 TCHECK(*lp);
235 ul = EXTRACT_32BITS(lp);
236 printf(", tos %d metric %d",
237 (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS,
238 ul & SLA_MASK_METRIC);
239 ++lp;
240 }
241 break;
242
243 case LS_TYPE_SUM_ABR:
244 TCHECK(lsap->lsa_un.un_sla.sla_tosmetric);
245 lp = lsap->lsa_un.un_sla.sla_tosmetric;
246 /* suppress tos if its not supported */
247 if(!((lsap->ls_hdr.ls_options)&OSPF_OPTION_T)) {
248 printf(", metric: %u", EXTRACT_32BITS(lp)&SLA_MASK_METRIC);
249 break;
250 }
251 while ((u_char *)lp < ls_end) {
252 register u_int32_t ul;
253
254 TCHECK(*lp);
255 ul = EXTRACT_32BITS(lp);
256 printf(", tos %d metric %d",
257 (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS,
258 ul & SLA_MASK_METRIC);
259 ++lp;
260 }
261 break;
262
263 case LS_TYPE_ASE:
264 TCHECK(lsap->lsa_un.un_nla.nla_mask);
265 printf("\n\t mask %s",
266 ipaddr_string(&lsap->lsa_un.un_asla.asla_mask));
267
268 TCHECK(lsap->lsa_un.un_sla.sla_tosmetric);
269 almp = lsap->lsa_un.un_asla.asla_metric;
270 while ((u_char *)almp < ls_end) {
271 register u_int32_t ul;
272
273 TCHECK(almp->asla_tosmetric);
274 ul = EXTRACT_32BITS(&almp->asla_tosmetric);
275 printf(", type %d, tos %d metric:",
276 (ul & ASLA_FLAG_EXTERNAL) ? 2 : 1,
277 (ul & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS);
278 if ((ul & ASLA_MASK_METRIC)==0xffffff)
279 printf(" infinite");
280 else
281 printf(" %d", (ul & ASLA_MASK_METRIC));
282
283 TCHECK(almp->asla_forward);
284 if (almp->asla_forward.s_addr) {
285 printf(", forward %s",
286 ipaddr_string(&almp->asla_forward));
287 }
288 TCHECK(almp->asla_tag);
289 if (almp->asla_tag.s_addr) {
290 printf(", tag %s",
291 ipaddr_string(&almp->asla_tag));
292 }
293 ++almp;
294 }
295 break;
296
297 case LS_TYPE_GROUP:
298 /* Multicast extensions as of 23 July 1991 */
299 mcp = lsap->lsa_un.un_mcla;
300 while ((u_char *)mcp < ls_end) {
301 TCHECK(mcp->mcla_vid);
302 switch (EXTRACT_32BITS(&mcp->mcla_vtype)) {
303
304 case MCLA_VERTEX_ROUTER:
305 printf("\n\t Router Router-ID %s",
306 ipaddr_string(&mcp->mcla_vid));
307 break;
308
309 case MCLA_VERTEX_NETWORK:
310 printf("\n\t Network Designated Router %s",
311 ipaddr_string(&mcp->mcla_vid));
312 break;
313
314 default:
315 printf("\n\t unknown VertexType (%u)",
316 EXTRACT_32BITS(&mcp->mcla_vtype));
317 break;
318 }
319 ++mcp;
320 }
321 }
322
323 return (0);
324 trunc:
325 return (1);
326 }
327
328 static int
329 ospf_decode_v2(register const struct ospfhdr *op,
330 register const u_char *dataend)
331 {
332 register const struct in_addr *ap;
333 register const struct lsr *lsrp;
334 register const struct lsa_hdr *lshp;
335 register const struct lsa *lsap;
336 register int lsa_count;
337
338 switch (op->ospf_type) {
339
340 case OSPF_TYPE_UMD:
341 /*
342 * Rob Coltun's special monitoring packets;
343 * do nothing
344 */
345 break;
346
347 case OSPF_TYPE_HELLO:
348 TCHECK(op->ospf_hello.hello_deadint);
349 printf("\n\t Hello Timer: %us, Dead Timer %us, mask: %s, Priority: %u",
350 EXTRACT_16BITS(&op->ospf_hello.hello_helloint),
351 EXTRACT_32BITS(&op->ospf_hello.hello_deadint),
352 ipaddr_string(&op->ospf_hello.hello_mask),
353 op->ospf_hello.hello_priority);
354
355 printf("\n\t Options: %s",
356 bittok2str(ospf_option_values,"none",op->ospf_hello.hello_options));
357
358 TCHECK(op->ospf_hello.hello_dr);
359 if (op->ospf_hello.hello_dr.s_addr != 0)
360 printf("\n\t Designated Router %s",
361 ipaddr_string(&op->ospf_hello.hello_dr));
362
363 TCHECK(op->ospf_hello.hello_bdr);
364 if (op->ospf_hello.hello_bdr.s_addr != 0)
365 printf(", Backup Designated Router %s",
366 ipaddr_string(&op->ospf_hello.hello_bdr));
367
368 ap = op->ospf_hello.hello_neighbor;
369 if ((u_char *)ap < dataend)
370 printf("\n\t Neighbor List:");
371 while ((u_char *)ap < dataend) {
372 TCHECK(*ap);
373 printf("\n\t %s", ipaddr_string(ap));
374 ++ap;
375 }
376 break; /* HELLO */
377
378 case OSPF_TYPE_DD:
379 TCHECK(op->ospf_db.db_options);
380 printf("\n\t Options: %s",
381 bittok2str(ospf_option_values,"none",op->ospf_db.db_options));
382 TCHECK(op->ospf_db.db_flags);
383 printf("\n\t DD Flags: %s",
384 bittok2str(ospf_dd_flag_values,"none",op->ospf_db.db_flags));
385
386 if (vflag) {
387 /* Print all the LS adv's */
388 lshp = op->ospf_db.db_lshdr;
389 while (!ospf_print_lshdr(lshp)) {
390 ++lshp;
391 }
392 }
393 break;
394
395 case OSPF_TYPE_LS_REQ:
396 lsrp = op->ospf_lsr;
397 while ((u_char *)lsrp < dataend) {
398 TCHECK(*lsrp);
399
400 printf("\n\t %s LSA (%d), LSA-ID: %s, Advertising Router: %s",
401 tok2str(lsa_values,"unknown",lsrp->ls_type),
402 lsrp->ls_type,
403 ipaddr_string(&lsrp->ls_stateid),
404 ipaddr_string(&lsrp->ls_router));
405 ++lsrp;
406 }
407 break;
408
409 case OSPF_TYPE_LS_UPDATE:
410 lsap = op->ospf_lsu.lsu_lsa;
411 TCHECK(op->ospf_lsu.lsu_count);
412 lsa_count = EXTRACT_32BITS(&op->ospf_lsu.lsu_count);
413 printf(", %d LSA%s",lsa_count, lsa_count > 1 ? "s" : "");
414 while (lsa_count--) {
415 if (ospf_print_lsa(lsap))
416 goto trunc;
417 lsap = (struct lsa *)((u_char *)lsap +
418 EXTRACT_16BITS(&lsap->ls_hdr.ls_length));
419 }
420 break;
421
422 case OSPF_TYPE_LS_ACK:
423 lshp = op->ospf_lsa.lsa_lshdr;
424 while (!ospf_print_lshdr(lshp)) {
425 ++lshp;
426 }
427 break;
428
429 default:
430 printf("v2 type (%d)", op->ospf_type);
431 break;
432 }
433 return (0);
434 trunc:
435 return (1);
436 }
437
438 void
439 ospf_print(register const u_char *bp, register u_int length,
440 register const u_char *bp2)
441 {
442 register const struct ospfhdr *op;
443 register const struct ip *ip;
444 register const u_char *dataend;
445 register const char *cp;
446
447 op = (struct ospfhdr *)bp;
448 ip = (struct ip *)bp2;
449
450 /* XXX Before we do anything else, strip off the MD5 trailer */
451 TCHECK(op->ospf_authtype);
452 if (EXTRACT_16BITS(&op->ospf_authtype) == OSPF_AUTH_MD5) {
453 length -= OSPF_AUTH_MD5_LEN;
454 snapend -= OSPF_AUTH_MD5_LEN;
455 }
456
457 /* If the type is valid translate it, or just print the type */
458 /* value. If it's not valid, say so and return */
459 TCHECK(op->ospf_type);
460 cp = tok2str(type2str, "unknown LS-Type %d", op->ospf_type);
461 printf("OSPFv%d %s length: %d", op->ospf_version, cp, length);
462 if (*cp == 'u')
463 return;
464
465 if(!vflag) /* non verbose - so lets bail out here */
466 return;
467
468 TCHECK(op->ospf_len);
469 if (length != EXTRACT_16BITS(&op->ospf_len)) {
470 printf(" [len %d]", EXTRACT_16BITS(&op->ospf_len));
471 return;
472 }
473 dataend = bp + length;
474
475 /* Print the routerid if it is not the same as the source */
476 TCHECK(op->ospf_routerid);
477 if (ip->ip_src.s_addr != op->ospf_routerid.s_addr)
478 printf("\n\tRouter-ID: %s", ipaddr_string(&op->ospf_routerid));
479
480 TCHECK(op->ospf_areaid);
481 if (op->ospf_areaid.s_addr != 0)
482 printf(", Area %s", ipaddr_string(&op->ospf_areaid));
483 else
484 printf(", Backbone Area");
485
486 if (vflag) {
487 /* Print authentication data (should we really do this?) */
488 TCHECK2(op->ospf_authdata[0], sizeof(op->ospf_authdata));
489 switch (EXTRACT_16BITS(&op->ospf_authtype)) {
490
491 case OSPF_AUTH_NONE:
492 break;
493
494 case OSPF_AUTH_SIMPLE:
495 printf(", simple Authentication \"");
496 (void)fn_printn(op->ospf_authdata,
497 sizeof(op->ospf_authdata), NULL);
498 printf("\"");
499 break;
500
501 case OSPF_AUTH_MD5:
502 printf(", MD5 Authentication");
503 break;
504
505 default:
506 printf(", unknown Authentication Type %d", EXTRACT_16BITS(&op->ospf_authtype));
507 return;
508 }
509 }
510 /* Do rest according to version. */
511 switch (op->ospf_version) {
512
513 case 2:
514 /* ospf version 2 */
515 if (ospf_decode_v2(op, dataend))
516 goto trunc;
517 break;
518
519 default:
520 printf(" ospf [version %d]", op->ospf_version);
521 break;
522 } /* end switch on version */
523
524 return;
525 trunc:
526 fputs(tstr, stdout);
527 }