GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/tcpdump/print-ospf.c Lines: 0 265 0.0 %
Date: 2017-11-13 Branches: 0 257 0.0 %

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