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