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