]> The Tcpdump Group git mirrors - tcpdump/blob - print-ospf.c
92945b3929f66b85840a5bcb2ea609e4a023917f
[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.25 1999-10-17 21:37:14 mcr Exp $ (LBL)";
27 #endif
28
29 #include <sys/param.h>
30 #include <sys/time.h>
31 #include <sys/socket.h>
32
33 #include <netinet/in.h>
34 #include <netinet/in_systm.h>
35 #include <netinet/ip.h>
36
37 #include <ctype.h>
38 #include <stdio.h>
39
40 #include "interface.h"
41 #include "addrtoname.h"
42
43 #include "ospf.h"
44
45 struct bits {
46 u_int32_t bit;
47 const char *str;
48 };
49
50 static const struct bits ospf_option_bits[] = {
51 { OSPF_OPTION_T, "T" },
52 { OSPF_OPTION_E, "E" },
53 { OSPF_OPTION_MC, "MC" },
54 { 0, NULL }
55 };
56
57 static const struct bits ospf_rla_flag_bits[] = {
58 { RLA_FLAG_B, "B" },
59 { RLA_FLAG_E, "E" },
60 { RLA_FLAG_W1, "W1" },
61 { RLA_FLAG_W2, "W2" },
62 { 0, NULL }
63 };
64
65 static struct tok type2str[] = {
66 { OSPF_TYPE_UMD, "umd" },
67 { OSPF_TYPE_HELLO, "hello" },
68 { OSPF_TYPE_DB, "dd" },
69 { OSPF_TYPE_LSR, "ls_req" },
70 { OSPF_TYPE_LSU, "ls_upd" },
71 { OSPF_TYPE_LSA, "ls_ack" },
72 { 0, NULL }
73 };
74
75 static char tstr[] = " [|ospf]";
76
77 /* Forwards */
78 static inline void ospf_print_seqage(u_int32_t, time_t);
79 static inline void ospf_print_bits(const struct bits *, u_char);
80 static void ospf_print_ls_type(u_int, const struct in_addr *,
81 const struct in_addr *, const char *);
82 static int ospf_print_lshdr(const struct lsa_hdr *);
83 static int ospf_print_lsa(const struct lsa *);
84 static int ospf_decode_v2(const struct ospfhdr *, const u_char *);
85
86 static inline void
87 ospf_print_seqage(register u_int32_t seq, register time_t us)
88 {
89 register time_t sec = us % 60;
90 register time_t mins = (us / 60) % 60;
91 register time_t hour = us / 3600;
92
93 printf(" S %X age ", seq);
94 if (hour)
95 printf("%u:%02u:%02u",
96 (u_int32_t) hour, (u_int32_t) mins, (u_int32_t) sec);
97 else if (mins)
98 printf("%u:%02u", (u_int32_t) mins, (u_int32_t) sec);
99 else
100 printf("%u", (u_int32_t) sec);
101 }
102
103
104 static inline void
105 ospf_print_bits(register const struct bits *bp, register u_char options)
106 {
107 register char sep = ' ';
108
109 do {
110 if (options & bp->bit) {
111 printf("%c%s", sep, bp->str);
112 sep = '/';
113 }
114 } while ((++bp)->bit);
115 }
116
117 static void
118 ospf_print_ls_type(register u_int ls_type,
119 register const struct in_addr *ls_stateid,
120 register const struct in_addr *ls_router, register const char *fmt)
121 {
122
123 switch (ls_type) {
124
125 case LS_TYPE_ROUTER:
126 printf(" rtr %s ", ipaddr_string(ls_router));
127 break;
128
129 case LS_TYPE_NETWORK:
130 printf(" net dr %s if %s",
131 ipaddr_string(ls_router),
132 ipaddr_string(ls_stateid));
133 break;
134
135 case LS_TYPE_SUM_IP:
136 printf(" sum %s abr %s",
137 ipaddr_string(ls_stateid),
138 ipaddr_string(ls_router));
139 break;
140
141 case LS_TYPE_SUM_ABR:
142 printf(" abr %s rtr %s",
143 ipaddr_string(ls_router),
144 ipaddr_string(ls_stateid));
145 break;
146
147 case LS_TYPE_ASE:
148 printf(" ase %s asbr %s",
149 ipaddr_string(ls_stateid),
150 ipaddr_string(ls_router));
151 break;
152
153 case LS_TYPE_GROUP:
154 printf(" group %s rtr %s",
155 ipaddr_string(ls_stateid),
156 ipaddr_string(ls_router));
157 break;
158
159 default:
160 putchar(' ');
161 printf(fmt, ls_type);
162 break;
163 }
164 }
165
166 static int
167 ospf_print_lshdr(register const struct lsa_hdr *lshp)
168 {
169
170 TCHECK(lshp->ls_type);
171 printf(" {"); /* } (ctags) */
172
173 TCHECK(lshp->ls_options);
174 ospf_print_bits(ospf_option_bits, lshp->ls_options);
175 TCHECK(lshp->ls_seq);
176 ospf_print_seqage(ntohl(lshp->ls_seq), ntohs(lshp->ls_age));
177 ospf_print_ls_type(lshp->ls_type, &lshp->ls_stateid, &lshp->ls_router,
178 "ls_type %d");
179
180 return (0);
181 trunc:
182 return (1);
183 }
184
185
186 /*
187 * Print a single link state advertisement. If truncated return 1, else 0.
188 */
189 static int
190 ospf_print_lsa(register const struct lsa *lsap)
191 {
192 register const u_char *ls_end;
193 register const struct rlalink *rlp;
194 register const struct tos_metric *tosp;
195 register const struct in_addr *ap;
196 register const struct aslametric *almp;
197 register const struct mcla *mcp;
198 register const u_int32_t *lp;
199 register int j, k;
200
201 if (ospf_print_lshdr(&lsap->ls_hdr))
202 return (1);
203 TCHECK(lsap->ls_hdr.ls_length);
204 ls_end = (u_char *)lsap + ntohs(lsap->ls_hdr.ls_length);
205 switch (lsap->ls_hdr.ls_type) {
206
207 case LS_TYPE_ROUTER:
208 TCHECK(lsap->lsa_un.un_rla.rla_flags);
209 ospf_print_bits(ospf_rla_flag_bits,
210 lsap->lsa_un.un_rla.rla_flags);
211
212 TCHECK(lsap->lsa_un.un_rla.rla_count);
213 j = ntohs(lsap->lsa_un.un_rla.rla_count);
214 TCHECK(lsap->lsa_un.un_rla.rla_link);
215 rlp = lsap->lsa_un.un_rla.rla_link;
216 while (j--) {
217 TCHECK(*rlp);
218 printf(" {"); /* } (ctags) */
219 switch (rlp->link_type) {
220
221 case RLA_TYPE_VIRTUAL:
222 printf(" virt");
223 /* Fall through */
224
225 case RLA_TYPE_ROUTER:
226 printf(" nbrid %s if %s",
227 ipaddr_string(&rlp->link_id),
228 ipaddr_string(&rlp->link_data));
229 break;
230
231 case RLA_TYPE_TRANSIT:
232 printf(" dr %s if %s",
233 ipaddr_string(&rlp->link_id),
234 ipaddr_string(&rlp->link_data));
235 break;
236
237 case RLA_TYPE_STUB:
238 printf(" net %s mask %s",
239 ipaddr_string(&rlp->link_id),
240 ipaddr_string(&rlp->link_data));
241 break;
242
243 default:
244 /* { (ctags) */
245 printf(" ??RouterLinksType %d?? }",
246 rlp->link_type);
247 return (0);
248 }
249 printf(" tos 0 metric %d", ntohs(rlp->link_tos0metric));
250 tosp = (struct tos_metric *)
251 ((sizeof rlp->link_tos0metric) + (u_char *) rlp);
252 for (k = 0; k < (int) rlp->link_toscount; ++k, ++tosp) {
253 TCHECK(*tosp);
254 printf(" tos %d metric %d",
255 tosp->tos_type,
256 ntohs(tosp->tos_metric));
257 }
258 /* { (ctags) */
259 printf(" }");
260 rlp = (struct rlalink *)((u_char *)(rlp + 1) +
261 ((rlp->link_toscount) * sizeof(*tosp)));
262 }
263 break;
264
265 case LS_TYPE_NETWORK:
266 TCHECK(lsap->lsa_un.un_nla.nla_mask);
267 printf(" mask %s rtrs",
268 ipaddr_string(&lsap->lsa_un.un_nla.nla_mask));
269 ap = lsap->lsa_un.un_nla.nla_router;
270 while ((u_char *)ap < ls_end) {
271 TCHECK(*ap);
272 printf(" %s", ipaddr_string(ap));
273 ++ap;
274 }
275 break;
276
277 case LS_TYPE_SUM_IP:
278 TCHECK(lsap->lsa_un.un_nla.nla_mask);
279 printf(" mask %s",
280 ipaddr_string(&lsap->lsa_un.un_sla.sla_mask));
281 /* Fall through */
282
283 case LS_TYPE_SUM_ABR:
284 TCHECK(lsap->lsa_un.un_sla.sla_tosmetric);
285 lp = lsap->lsa_un.un_sla.sla_tosmetric;
286 while ((u_char *)lp < ls_end) {
287 register u_int32_t ul;
288
289 TCHECK(*lp);
290 ul = ntohl(*lp);
291 printf(" tos %d metric %d",
292 (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS,
293 ul & SLA_MASK_METRIC);
294 ++lp;
295 }
296 break;
297
298 case LS_TYPE_ASE:
299 TCHECK(lsap->lsa_un.un_nla.nla_mask);
300 printf(" mask %s",
301 ipaddr_string(&lsap->lsa_un.un_asla.asla_mask));
302
303 TCHECK(lsap->lsa_un.un_sla.sla_tosmetric);
304 almp = lsap->lsa_un.un_asla.asla_metric;
305 while ((u_char *)almp < ls_end) {
306 register u_int32_t ul;
307
308 TCHECK(almp->asla_tosmetric);
309 ul = ntohl(almp->asla_tosmetric);
310 printf(" type %d tos %d metric %d",
311 (ul & ASLA_FLAG_EXTERNAL) ? 2 : 1,
312 (ul & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS,
313 (ul & ASLA_MASK_METRIC));
314 TCHECK(almp->asla_forward);
315 if (almp->asla_forward.s_addr) {
316 printf(" forward %s",
317 ipaddr_string(&almp->asla_forward));
318 }
319 TCHECK(almp->asla_tag);
320 if (almp->asla_tag.s_addr) {
321 printf(" tag %s",
322 ipaddr_string(&almp->asla_tag));
323 }
324 ++almp;
325 }
326 break;
327
328 case LS_TYPE_GROUP:
329 /* Multicast extensions as of 23 July 1991 */
330 mcp = lsap->lsa_un.un_mcla;
331 while ((u_char *)mcp < ls_end) {
332 TCHECK(mcp->mcla_vid);
333 switch (ntohl(mcp->mcla_vtype)) {
334
335 case MCLA_VERTEX_ROUTER:
336 printf(" rtr rtrid %s",
337 ipaddr_string(&mcp->mcla_vid));
338 break;
339
340 case MCLA_VERTEX_NETWORK:
341 printf(" net dr %s",
342 ipaddr_string(&mcp->mcla_vid));
343 break;
344
345 default:
346 printf(" ??VertexType %u??",
347 (u_int32_t)ntohl(mcp->mcla_vtype));
348 break;
349 }
350 ++mcp;
351 }
352 }
353
354 /* { (ctags) */
355 fputs(" }", stdout);
356 return (0);
357 trunc:
358 fputs(" }", stdout);
359 return (1);
360 }
361
362 static int
363 ospf_decode_v2(register const struct ospfhdr *op,
364 register const u_char *dataend)
365 {
366 register const struct in_addr *ap;
367 register const struct lsr *lsrp;
368 register const struct lsa_hdr *lshp;
369 register const struct lsa *lsap;
370 register char sep;
371 register int i;
372
373 switch (op->ospf_type) {
374
375 case OSPF_TYPE_UMD:
376 /*
377 * Rob Coltun's special monitoring packets;
378 * do nothing
379 */
380 break;
381
382 case OSPF_TYPE_HELLO:
383 if (vflag) {
384 TCHECK(op->ospf_hello.hello_deadint);
385 ospf_print_bits(ospf_option_bits,
386 op->ospf_hello.hello_options);
387 printf(" mask %s int %d pri %d dead %u",
388 ipaddr_string(&op->ospf_hello.hello_mask),
389 ntohs(op->ospf_hello.hello_helloint),
390 op->ospf_hello.hello_priority,
391 (u_int32_t)ntohl(op->ospf_hello.hello_deadint));
392 }
393 TCHECK(op->ospf_hello.hello_dr);
394 if (op->ospf_hello.hello_dr.s_addr != 0)
395 printf(" dr %s",
396 ipaddr_string(&op->ospf_hello.hello_dr));
397 TCHECK(op->ospf_hello.hello_bdr);
398 if (op->ospf_hello.hello_bdr.s_addr != 0)
399 printf(" bdr %s",
400 ipaddr_string(&op->ospf_hello.hello_bdr));
401 if (vflag) {
402 printf(" nbrs");
403 ap = op->ospf_hello.hello_neighbor;
404 while ((u_char *)ap < dataend) {
405 TCHECK(*ap);
406 printf(" %s", ipaddr_string(ap));
407 ++ap;
408 }
409 }
410 break; /* HELLO */
411
412 case OSPF_TYPE_DB:
413 TCHECK(op->ospf_db.db_options);
414 ospf_print_bits(ospf_option_bits, op->ospf_db.db_options);
415 sep = ' ';
416 TCHECK(op->ospf_db.db_flags);
417 if (op->ospf_db.db_flags & OSPF_DB_INIT) {
418 printf("%cI", sep);
419 sep = '/';
420 }
421 if (op->ospf_db.db_flags & OSPF_DB_MORE) {
422 printf("%cM", sep);
423 sep = '/';
424 }
425 if (op->ospf_db.db_flags & OSPF_DB_MASTER) {
426 printf("%cMS", sep);
427 sep = '/';
428 }
429 TCHECK(op->ospf_db.db_seq);
430 printf(" S %X", (u_int32_t)ntohl(op->ospf_db.db_seq));
431
432 if (vflag) {
433 /* Print all the LS adv's */
434 lshp = op->ospf_db.db_lshdr;
435
436 while (!ospf_print_lshdr(lshp)) {
437 /* { (ctags) */
438 printf(" }");
439 ++lshp;
440 }
441 }
442 break;
443
444 case OSPF_TYPE_LSR:
445 if (vflag) {
446 lsrp = op->ospf_lsr;
447 while ((u_char *)lsrp < dataend) {
448 TCHECK(*lsrp);
449 printf(" {"); /* } (ctags) */
450 ospf_print_ls_type(ntohl(lsrp->ls_type),
451 &lsrp->ls_stateid,
452 &lsrp->ls_router,
453 "LinkStateType %d");
454 /* { (ctags) */
455 printf(" }");
456 ++lsrp;
457 }
458 }
459 break;
460
461 case OSPF_TYPE_LSU:
462 if (vflag) {
463 lsap = op->ospf_lsu.lsu_lsa;
464 TCHECK(op->ospf_lsu.lsu_count);
465 i = ntohl(op->ospf_lsu.lsu_count);
466 while (i--) {
467 if (ospf_print_lsa(lsap))
468 goto trunc;
469 lsap = (struct lsa *)((u_char *)lsap +
470 ntohs(lsap->ls_hdr.ls_length));
471 }
472 }
473 break;
474
475
476 case OSPF_TYPE_LSA:
477 if (vflag) {
478 lshp = op->ospf_lsa.lsa_lshdr;
479
480 while (!ospf_print_lshdr(lshp)) {
481 /* { (ctags) */
482 printf(" }");
483 ++lshp;
484 }
485 }
486 break;
487
488 default:
489 printf("v2 type %d", op->ospf_type);
490 break;
491 }
492 return (0);
493 trunc:
494 return (1);
495 }
496
497 void
498 ospf_print(register const u_char *bp, register u_int length,
499 register const u_char *bp2)
500 {
501 register const struct ospfhdr *op;
502 register const struct ip *ip;
503 register const u_char *dataend;
504 register const char *cp;
505
506 op = (struct ospfhdr *)bp;
507 ip = (struct ip *)bp2;
508 /* Print the source and destination address */
509 (void) printf("%s > %s:",
510 ipaddr_string(&ip->ip_src),
511 ipaddr_string(&ip->ip_dst));
512
513 /* XXX Before we do anything else, strip off the MD5 trailer */
514 TCHECK(op->ospf_authtype);
515 if (ntohs(op->ospf_authtype) == OSPF_AUTH_MD5) {
516 length -= OSPF_AUTH_MD5_LEN;
517 snapend -= OSPF_AUTH_MD5_LEN;
518 }
519
520 /* If the type is valid translate it, or just print the type */
521 /* value. If it's not valid, say so and return */
522 TCHECK(op->ospf_type);
523 cp = tok2str(type2str, "type%d", op->ospf_type);
524 printf(" OSPFv%d-%s %d:", op->ospf_version, cp, length);
525 if (*cp == 't')
526 return;
527
528 TCHECK(op->ospf_len);
529 if (length != ntohs(op->ospf_len)) {
530 printf(" [len %d]", ntohs(op->ospf_len));
531 return;
532 }
533 dataend = bp + length;
534
535 /* Print the routerid if it is not the same as the source */
536 TCHECK(op->ospf_routerid);
537 if (ip->ip_src.s_addr != op->ospf_routerid.s_addr)
538 printf(" rtrid %s", ipaddr_string(&op->ospf_routerid));
539
540 TCHECK(op->ospf_areaid);
541 if (op->ospf_areaid.s_addr != 0)
542 printf(" area %s", ipaddr_string(&op->ospf_areaid));
543 else
544 printf(" backbone");
545
546 if (vflag) {
547 /* Print authentication data (should we really do this?) */
548 TCHECK2(op->ospf_authdata[0], sizeof(op->ospf_authdata));
549 switch (ntohs(op->ospf_authtype)) {
550
551 case OSPF_AUTH_NONE:
552 break;
553
554 case OSPF_AUTH_SIMPLE:
555 printf(" auth \"");
556 (void)fn_printn(op->ospf_authdata,
557 sizeof(op->ospf_authdata), NULL);
558 printf("\"");
559 break;
560
561 case OSPF_AUTH_MD5:
562 printf(" auth MD5");
563 break;
564
565 default:
566 printf(" ??authtype-%d??", ntohs(op->ospf_authtype));
567 return;
568 }
569 }
570 /* Do rest according to version. */
571 switch (op->ospf_version) {
572
573 case 2:
574 /* ospf version 2 */
575 if (ospf_decode_v2(op, dataend))
576 goto trunc;
577 break;
578
579 default:
580 printf(" ospf [version %d]", op->ospf_version);
581 break;
582 } /* end switch on version */
583
584 return;
585 trunc:
586 fputs(tstr, stdout);
587 }