GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/tcpdump/print-bgp.c Lines: 0 463 0.0 %
Date: 2017-11-07 Branches: 0 429 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: print-bgp.c,v 1.25 2017/08/30 09:23:00 otto Exp $	*/
2
3
/*
4
 * Copyright (C) 1999 WIDE Project.
5
 * All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in the
14
 *    documentation and/or other materials provided with the distribution.
15
 * 3. Neither the name of the project nor the names of its contributors
16
 *    may be used to endorse or promote products derived from this software
17
 *    without specific prior written permission.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
 * SUCH DAMAGE.
30
 */
31
32
#include <sys/time.h>
33
#include <sys/types.h>
34
#include <sys/socket.h>
35
36
#include <netinet/in.h>
37
38
#include <errno.h>
39
#include <stdio.h>
40
#include <string.h>
41
#include <netdb.h>
42
#include <limits.h>
43
44
#include "interface.h"
45
#include "addrtoname.h"
46
#include "extract.h"
47
#include "afnum.h"
48
49
struct bgp {
50
	u_int8_t bgp_marker[16];
51
	u_int16_t bgp_len;
52
	u_int8_t bgp_type;
53
};
54
#define BGP_SIZE		19	/* unaligned */
55
56
#define BGP_OPEN		1
57
#define BGP_UPDATE		2
58
#define BGP_NOTIFICATION	3
59
#define BGP_KEEPALIVE		4
60
#define BGP_ROUTE_REFRESH	5
61
62
struct bgp_open {
63
	u_int8_t bgpo_marker[16];
64
	u_int16_t bgpo_len;
65
	u_int8_t bgpo_type;
66
	u_int8_t bgpo_version;
67
	u_int16_t bgpo_myas;
68
	u_int16_t bgpo_holdtime;
69
	u_int32_t bgpo_id;
70
	u_int8_t bgpo_optlen;
71
	/* options should follow */
72
};
73
#define BGP_OPEN_SIZE		29	/* unaligned */
74
75
struct bgp_opt {
76
	u_int8_t bgpopt_type;
77
	u_int8_t bgpopt_len;
78
	/* variable length */
79
};
80
#define BGP_OPT_CAP		2
81
#define BGP_OPT_SIZE		2	/* some compilers may pad to 4 bytes */
82
83
#define BGP_UPDATE_MINSIZE	23
84
85
struct bgp_notification {
86
	u_int8_t bgpn_marker[16];
87
	u_int16_t bgpn_len;
88
	u_int8_t bgpn_type;
89
	u_int8_t bgpn_major;
90
	u_int8_t bgpn_minor;
91
	/* data should follow */
92
};
93
#define BGP_NOTIFICATION_SIZE		21	/* unaligned */
94
95
struct bgp_route_refresh {
96
	u_int8_t bgp_marker[16];
97
	u_int16_t len;
98
	u_int8_t type;
99
	u_int8_t afi[2]; /* unaligned; should be u_int16_t */
100
	u_int8_t res;
101
	u_int8_t safi;
102
};
103
#define BGP_ROUTE_REFRESH_SIZE          23
104
105
struct bgp_attr {
106
	u_int8_t bgpa_flags;
107
	u_int8_t bgpa_type;
108
	union {
109
		u_int8_t len;
110
		u_int16_t elen;
111
	} bgpa_len;
112
#define bgp_attr_len(p) \
113
	(((p)->bgpa_flags & 0x10) ? \
114
		ntohs((p)->bgpa_len.elen) : (p)->bgpa_len.len)
115
#define bgp_attr_off(p) \
116
	(((p)->bgpa_flags & 0x10) ? 4 : 3)
117
};
118
119
#define BGPTYPE_ORIGIN			1
120
#define BGPTYPE_AS_PATH			2
121
#define BGPTYPE_NEXT_HOP		3
122
#define BGPTYPE_MULTI_EXIT_DISC		4
123
#define BGPTYPE_LOCAL_PREF		5
124
#define BGPTYPE_ATOMIC_AGGREGATE	6
125
#define BGPTYPE_AGGREGATOR		7
126
#define	BGPTYPE_COMMUNITIES		8	/* RFC1997 */
127
#define	BGPTYPE_ORIGINATOR_ID		9	/* RFC1998 */
128
#define	BGPTYPE_CLUSTER_LIST		10	/* RFC1998 */
129
#define	BGPTYPE_DPA			11	/* draft-ietf-idr-bgp-dpa */
130
#define	BGPTYPE_ADVERTISERS		12	/* RFC1863 */
131
#define	BGPTYPE_RCID_PATH		13	/* RFC1863 */
132
#define BGPTYPE_MP_REACH_NLRI		14	/* RFC2283 */
133
#define BGPTYPE_MP_UNREACH_NLRI		15	/* RFC2283 */
134
#define BGPTYPE_EXTD_COMMUNITIES	16	/* RFC4360 */
135
#define BGPTYPE_AS4_PATH		17	/* RFC4893 */
136
#define BGPTYPE_AGGREGATOR4		18	/* RFC4893 */
137
#define BGPTYPE_LARGE_COMMUNITIES	32	/* draft-ietf-idr-large-community */
138
139
#define BGP_AS_SET             1
140
#define BGP_AS_SEQUENCE        2
141
#define BGP_CONFED_AS_SEQUENCE 3 /* draft-ietf-idr-rfc3065bis-01 */
142
#define BGP_CONFED_AS_SET      4 /* draft-ietf-idr-rfc3065bis-01  */
143
144
static struct tok bgp_as_path_segment_open_values[] = {
145
	{ BGP_AS_SET,			" {" },
146
	{ BGP_AS_SEQUENCE,		" " },
147
	{ BGP_CONFED_AS_SEQUENCE,	" (" },
148
	{ BGP_CONFED_AS_SET,		" ({" },
149
	{ 0, NULL},
150
};
151
152
static struct tok bgp_as_path_segment_close_values[] = {
153
	{ BGP_AS_SET,			"}" },
154
	{ BGP_AS_SEQUENCE,		"" },
155
	{ BGP_CONFED_AS_SEQUENCE,	")" },
156
	{ BGP_CONFED_AS_SET,		"})" },
157
	{ 0, NULL},
158
};
159
160
#define BGP_MP_NLRI_MINSIZE		3
161
162
static const char *bgptype[] = {
163
	NULL, "OPEN", "UPDATE", "NOTIFICATION", "KEEPALIVE", "ROUTE-REFRESH",
164
};
165
#define bgp_type(x) num_or_str(bgptype, sizeof(bgptype)/sizeof(bgptype[0]), (x))
166
167
static const char *bgpopt_type[] = {
168
	NULL, "Authentication Information", "Capabilities Advertisement",
169
};
170
#define bgp_opttype(x) \
171
	num_or_str(bgpopt_type, sizeof(bgpopt_type)/sizeof(bgpopt_type[0]), (x))
172
173
#define BGP_CAPCODE_MP			1
174
#define BGP_CAPCODE_REFRESH		2
175
#define BGP_CAPCODE_RESTART		64 /* draft-ietf-idr-restart-05  */
176
#define BGP_CAPCODE_AS4			65 /* RFC4893 */
177
178
static const char *bgp_capcode[] = {
179
	NULL, "MULTI_PROTOCOL", "ROUTE_REFRESH",
180
	/* 3: RFC5291 */ "OUTBOUND_ROUTE_FILTERING",
181
	/* 4: RFC3107 */ "MULTIPLE_ROUTES",
182
	/* 5: RFC5549 */ "EXTENDED_NEXTHOP_ENCODING",
183
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
184
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
185
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
186
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
187
	/* 64: RFC4724 */ "GRACEFUL_RESTART",
188
	/* 65: RFC4893 */ "AS4", 0,
189
	/* 67: [Chen] */ "DYNAMIC_CAPABILITY",
190
	/* 68: [Appanna] */ "MULTISESSION",
191
	/* 69: [draft-ietf-idr-add-paths] */ "ADD-PATH",
192
};
193
194
#define bgp_capcode(x) \
195
	num_or_str(bgp_capcode, sizeof(bgp_capcode)/sizeof(bgp_capcode[0]), (x))
196
197
#define BGP_NOTIFY_MAJOR_CEASE		6
198
static const char *bgpnotify_major[] = {
199
	NULL, "Message Header Error",
200
	"OPEN Message Error", "UPDATE Message Error",
201
	"Hold Timer Expired", "Finite State Machine Error",
202
	"Cease", "Capability Message Error",
203
};
204
#define bgp_notify_major(x) \
205
	num_or_str(bgpnotify_major, \
206
		sizeof(bgpnotify_major)/sizeof(bgpnotify_major[0]), (x))
207
208
static const char *bgpnotify_minor_msg[] = {
209
	NULL, "Connection Not Synchronized",
210
	"Bad Message Length", "Bad Message Type",
211
};
212
213
static const char *bgpnotify_minor_open[] = {
214
	NULL, "Unsupported Version Number",
215
	"Bad Peer AS", "Bad BGP Identifier",
216
	"Unsupported Optional Parameter", "Authentication Failure",
217
	"Unacceptable Hold Time", "Unsupported Capability",
218
};
219
220
static const char *bgpnotify_minor_update[] = {
221
	NULL, "Malformed Attribute List",
222
	"Unrecognized Well-known Attribute", "Missing Well-known Attribute",
223
	"Attribute Flags Error", "Attribute Length Error",
224
	"Invalid ORIGIN Attribute", "AS Routing Loop",
225
	"Invalid NEXT_HOP Attribute", "Optional Attribute Error",
226
	"Invalid Network Field", "Malformed AS_PATH",
227
};
228
229
static const char *bgpnotify_minor_holdtime[] = {
230
	NULL,
231
};
232
233
/* RFC 6608 */
234
static const char *bgpnotify_minor_fsm[] = {
235
	"Unspecified Error", "In OpenSent State", "In OpenConfirm State",
236
	"In Established State",
237
};
238
239
/* RFC 4486 */
240
#define BGP_NOTIFY_MINOR_CEASE_MAXPRFX  1
241
/* RFC 8203 */
242
#define BGP_NOTIFY_MINOR_CEASE_SHUT			2
243
#define BGP_NOTIFY_MINOR_CEASE_RESET			4
244
#define BGP_NOTIFY_MINOR_CEASE_ADMIN_SHUTDOWN_LEN	128
245
static const char *bgpnotify_minor_cease[] = {
246
	NULL, "Maximum Number of Prefixes Reached", "Administrative Shutdown",
247
	"Peer De-configured", "Administrative Reset", "Connection Rejected",
248
	"Other Configuration Change", "Connection Collision Resolution",
249
	"Out of Resources",
250
};
251
252
/* RFC 7313 */
253
static const char *bgpnotify_minor_err[] = {
254
	NULL, "Invalid Message Length",
255
};
256
257
static const char **bgpnotify_minor[] = {
258
	NULL, bgpnotify_minor_msg, bgpnotify_minor_open, bgpnotify_minor_update,
259
	bgpnotify_minor_holdtime, bgpnotify_minor_fsm, bgpnotify_minor_cease,
260
	bgpnotify_minor_err,
261
};
262
static const int bgpnotify_minor_siz[] = {
263
	0,
264
	sizeof(bgpnotify_minor_msg)/sizeof(bgpnotify_minor_msg[0]),
265
	sizeof(bgpnotify_minor_open)/sizeof(bgpnotify_minor_open[0]),
266
	sizeof(bgpnotify_minor_update)/sizeof(bgpnotify_minor_update[0]),
267
	sizeof(bgpnotify_minor_holdtime)/sizeof(bgpnotify_minor_holdtime[0]),
268
	sizeof(bgpnotify_minor_fsm)/sizeof(bgpnotify_minor_fsm[0]),
269
	sizeof(bgpnotify_minor_cease)/sizeof(bgpnotify_minor_cease[0]),
270
	sizeof(bgpnotify_minor_err)/sizeof(bgpnotify_minor_err[0]),
271
};
272
273
static const char *bgpattr_origin[] = {
274
	"IGP", "EGP", "INCOMPLETE",
275
};
276
#define bgp_attr_origin(x) \
277
	num_or_str(bgpattr_origin, \
278
		sizeof(bgpattr_origin)/sizeof(bgpattr_origin[0]), (x))
279
280
static const char *bgpattr_type[] = {
281
	NULL, "ORIGIN", "AS_PATH", "NEXT_HOP",
282
	"MULTI_EXIT_DISC", "LOCAL_PREF", "ATOMIC_AGGREGATE", "AGGREGATOR",
283
	"COMMUNITIES", "ORIGINATOR_ID", "CLUSTER_LIST", "DPA",
284
	"ADVERTISERS", "RCID_PATH", "MP_REACH_NLRI", "MP_UNREACH_NLRI",
285
	"EXTD_COMMUNITIES", "AS4_PATH", "AGGREGATOR4", NULL, NULL, NULL,
286
	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
287
	"LARGE_COMMUNITIES",
288
};
289
#define bgp_attr_type(x) \
290
	num_or_str(bgpattr_type, \
291
		sizeof(bgpattr_type)/sizeof(bgpattr_type[0]), (x))
292
293
/* Subsequent address family identifier, RFC2283 section 7 */
294
static const char *bgpattr_nlri_safi[] = {
295
	"Reserved", "Unicast", "Multicast", "Unicast+Multicast",
296
	"labeled Unicast", /* MPLS BGP RFC3107 */
297
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
298
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
299
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
300
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
301
	/* 64-66: MPLS BGP RFC3107 */
302
	"Tunnel", "VPLS", "MDT",
303
};
304
#define bgp_attr_nlri_safi(x) \
305
	num_or_str(bgpattr_nlri_safi, \
306
		sizeof(bgpattr_nlri_safi)/sizeof(bgpattr_nlri_safi[0]), (x))
307
308
/* well-known community */
309
#define BGP_COMMUNITY_NO_EXPORT			0xffffff01
310
#define BGP_COMMUNITY_NO_ADVERT			0xffffff02
311
#define BGP_COMMUNITY_NO_EXPORT_SUBCONFED	0xffffff03
312
#define BGP_COMMUNITY_NO_PEER			0xffffff04
313
314
static const char *afnumber[] = AFNUM_NAME_STR;
315
#define af_name(x) \
316
	(((x) == 65535) ? afnumber[0] : \
317
		num_or_str(afnumber, \
318
			sizeof(afnumber)/sizeof(afnumber[0]), (x)))
319
320
321
static const char *
322
num_or_str(const char **table, size_t siz, int value)
323
{
324
	static char buf[20];
325
	if (value < 0 || siz <= value || table[value] == NULL) {
326
		snprintf(buf, sizeof(buf), "#%d", value);
327
		return buf;
328
	} else
329
		return table[value];
330
}
331
332
static const char *
333
bgp_notify_minor(int major, int minor)
334
{
335
	static const char **table;
336
	int siz;
337
	static char buf[20];
338
	const char *p;
339
340
	if (0 <= major
341
	 && major < sizeof(bgpnotify_minor)/sizeof(bgpnotify_minor[0])
342
	 && bgpnotify_minor[major]) {
343
		table = bgpnotify_minor[major];
344
		siz = bgpnotify_minor_siz[major];
345
		if (0 <= minor && minor < siz && table[minor])
346
			p = table[minor];
347
		else
348
			p = NULL;
349
	} else
350
		p = NULL;
351
	if (p == NULL) {
352
		snprintf(buf, sizeof(buf), "#%d", minor);
353
		return buf;
354
	} else
355
		return p;
356
}
357
358
static int
359
decode_prefix4(const u_char *pd, char *buf, u_int buflen)
360
{
361
	struct in_addr addr;
362
	u_int plen;
363
	int n;
364
365
	TCHECK(pd[0]);
366
	plen = pd[0]; /*
367
		       * prefix length is in bits; packet only contains
368
		       * enough bytes of address to contain this many bits
369
		       */
370
	plen = pd[0];
371
	if (32 < plen)
372
		return -1;
373
	memset(&addr, 0, sizeof(addr));
374
	TCHECK2(pd[1], (plen + 7) / 8);
375
	memcpy(&addr, &pd[1], (plen + 7) / 8);
376
	if (plen % 8) {
377
		((u_char *)&addr)[(plen + 7) / 8 - 1] &=
378
			((0xff00 >> (plen % 8)) & 0xff);
379
	}
380
	n = snprintf(buf, buflen, "%s/%u", getname((u_char *)&addr), plen);
381
	if (n == -1 || n >= buflen)
382
		return -1;
383
384
	return 1 + (plen + 7) / 8;
385
386
trunc:
387
	return -2;
388
}
389
390
#ifdef INET6
391
static int
392
decode_prefix6(const u_char *pd, char *buf, u_int buflen)
393
{
394
	struct in6_addr addr;
395
	u_int plen;
396
	int n;
397
398
	TCHECK(pd[0]);
399
	plen = pd[0];
400
	if (128 < plen)
401
		return -1;
402
403
	memset(&addr, 0, sizeof(addr));
404
	TCHECK2(pd[1], (plen + 7) / 8);
405
	memcpy(&addr, &pd[1], (plen + 7) / 8);
406
	if (plen % 8) {
407
		addr.s6_addr[(plen + 7) / 8 - 1] &=
408
			((0xff00 >> (plen % 8)) & 0xff);
409
	}
410
411
	n = snprintf(buf, buflen, "%s/%u", getname6((u_char *)&addr), plen);
412
	if (n == -1 || n >= buflen)
413
		return -1;
414
415
	return 1 + (plen + 7) / 8;
416
417
trunc:
418
	return -2;
419
}
420
#endif
421
422
static int
423
bgp_attr_print(const struct bgp_attr *attr, const u_char *dat, int len)
424
{
425
	int i;
426
	u_int16_t af;
427
	u_int8_t safi, snpa;
428
	int advance;
429
	int tlen, asn_bytes;
430
	const u_char *p;
431
	char buf[HOST_NAME_MAX+1 + 100];
432
433
	p = dat;
434
	tlen = len;
435
	asn_bytes = 0;
436
437
	switch (attr->bgpa_type) {
438
	case BGPTYPE_ORIGIN:
439
		if (len != 1)
440
			printf(" invalid len");
441
		else {
442
			TCHECK(p[0]);
443
			printf(" %s", bgp_attr_origin(p[0]));
444
		}
445
		break;
446
	case BGPTYPE_AS4_PATH:
447
		asn_bytes = 4;
448
		/* FALLTHROUGH */
449
	case BGPTYPE_AS_PATH:
450
	/*
451
	 * 2-byte speakers will receive AS4_PATH as well AS_PATH (2-byte).
452
	 * 4-byte speakers will only receive AS_PATH but it will be 4-byte.
453
	 * To identify which is the case, compare the length of the path
454
	 * segment value in bytes, with the path segment length from the
455
	 * message (counted in # of AS)
456
	 */
457
458
		if (len % 2) {
459
			printf(" invalid len");
460
			break;
461
		}
462
		if (!len) {
463
			/* valid: local originated routes to IBGP peers */
464
			printf(" empty");
465
			break;
466
		}
467
		while (p < dat + len) {
468
			TCHECK2(p[0], 2);
469
			if (asn_bytes == 0) {
470
				if (p[1] == 0) {
471
				/* invalid: segment contains one or more AS */
472
					printf(" malformed");
473
					break;
474
				}
475
				asn_bytes = (len-2)/p[1];
476
			}
477
			printf("%s",
478
			    tok2str(bgp_as_path_segment_open_values,
479
			    "?", p[0]));
480
			for (i = 0; i < p[1] * asn_bytes; i += asn_bytes) {
481
				TCHECK2(p[2 + i], asn_bytes);
482
				printf("%s", i == 0 ? "" : " ");
483
				if (asn_bytes == 2 || EXTRACT_16BITS(&p[2 + i]))
484
					printf("%u%s",
485
					    EXTRACT_16BITS(&p[2 + i]),
486
					    asn_bytes == 4 ? "." : "");
487
				if (asn_bytes == 4)
488
					printf("%u",
489
					    EXTRACT_16BITS(&p[2 + i + 2]));
490
			}
491
			printf("%s",
492
			    tok2str(bgp_as_path_segment_close_values,
493
			    "?", p[0]));
494
			p += 2 + p[1] * asn_bytes;
495
		}
496
		break;
497
	case BGPTYPE_NEXT_HOP:
498
		if (len != 4)
499
			printf(" invalid len");
500
		else {
501
			TCHECK2(p[0], 4);
502
			printf(" %s", getname(p));
503
		}
504
		break;
505
	case BGPTYPE_MULTI_EXIT_DISC:
506
	case BGPTYPE_LOCAL_PREF:
507
		if (len != 4)
508
			printf(" invalid len");
509
		else {
510
			TCHECK2(p[0], 4);
511
			printf(" %u", EXTRACT_32BITS(p));
512
		}
513
		break;
514
	case BGPTYPE_ATOMIC_AGGREGATE:
515
		if (len != 0)
516
			printf(" invalid len");
517
		break;
518
	case BGPTYPE_AGGREGATOR4:
519
	case BGPTYPE_AGGREGATOR:
520
	/*
521
	 * like AS_PATH/AS4_PATH, AGGREGATOR can contain
522
	 * either 2-byte or 4-byte ASN, and AGGREGATOR4
523
	 * always contains 4-byte ASN.
524
	 */
525
		if (len != 6 && len != 8) {
526
			printf(" invalid len");
527
			break;
528
		}
529
		TCHECK2(p[0], len);
530
		printf(" AS #");
531
		if (len == 6 || EXTRACT_16BITS(p))
532
			printf("%u%s", EXTRACT_16BITS(p), len == 8 ? "." : "");
533
		if (len == 8)
534
			printf("%u", EXTRACT_16BITS(p+2));
535
		printf(", origin %s", getname(p+len-4));
536
		break;
537
	case BGPTYPE_COMMUNITIES:
538
		if (len % 4) {
539
			printf(" invalid len");
540
			break;
541
		}
542
		while (tlen>0) {
543
			u_int32_t comm;
544
			TCHECK2(p[0], 4);
545
			comm = EXTRACT_32BITS(p);
546
			switch (comm) {
547
			case BGP_COMMUNITY_NO_EXPORT:
548
				printf(" NO_EXPORT");
549
				break;
550
			case BGP_COMMUNITY_NO_ADVERT:
551
				printf(" NO_ADVERTISE");
552
				break;
553
			case BGP_COMMUNITY_NO_EXPORT_SUBCONFED:
554
				printf(" NO_EXPORT_SUBCONFED");
555
				break;
556
			case BGP_COMMUNITY_NO_PEER:
557
				printf(" NO_PEER");
558
				break;
559
			default:
560
				printf(" %d:%d",
561
					(comm >> 16) & 0xffff, comm & 0xffff);
562
				break;
563
			}
564
			tlen -= 4;
565
			p += 4;
566
		}
567
		break;
568
	case BGPTYPE_LARGE_COMMUNITIES:
569
		if (len == 0 || len % 12) {
570
			printf(" invalid len");
571
			break;
572
		}
573
		while (tlen>0) {
574
			TCHECK2(p[0], 12);
575
			printf(" %u:%u:%u",
576
			EXTRACT_32BITS(p),
577
			EXTRACT_32BITS(p + 4),
578
			EXTRACT_32BITS(p + 8));
579
			tlen -= 12;
580
			p += 12;
581
		}
582
		break;
583
	case BGPTYPE_ORIGINATOR_ID:
584
		if (len != 4) {
585
			printf(" invalid len");
586
			break;
587
                }
588
		TCHECK2(p[0], 4);
589
		printf("%s",getname(p));
590
		break;
591
	case BGPTYPE_CLUSTER_LIST:
592
		if (len % 4) {
593
			printf(" invalid len");
594
			break;
595
		}
596
		while (tlen>0) {
597
			TCHECK2(p[0], 4);
598
			printf(" %s%s",
599
			    getname(p),
600
			    (tlen>4) ? ", " : "");
601
			tlen -=4;
602
			p +=4;
603
		}
604
		break;
605
	case BGPTYPE_MP_REACH_NLRI:
606
		TCHECK2(p[0], BGP_MP_NLRI_MINSIZE);
607
		af = EXTRACT_16BITS(p);
608
		safi = p[2];
609
		if (safi >= 128)
610
			printf(" %s vendor specific %u,", af_name(af), safi);
611
		else {
612
			printf(" %s %s,", af_name(af),
613
				bgp_attr_nlri_safi(safi));
614
		}
615
		p += 3;
616
617
		if (af == AFNUM_INET)
618
			;
619
#ifdef INET6
620
		else if (af == AFNUM_INET6)
621
			;
622
#endif
623
		else
624
			break;
625
626
		TCHECK(p[0]);
627
		tlen = p[0];
628
		if (tlen) {
629
			printf(" nexthop");
630
			i = 0;
631
			while (i < tlen) {
632
				switch (af) {
633
				case AFNUM_INET:
634
					TCHECK2(p[1+i], sizeof(struct in_addr));
635
					printf(" %s", getname(p + 1 + i));
636
					i += sizeof(struct in_addr);
637
					break;
638
#ifdef INET6
639
				case AFNUM_INET6:
640
					TCHECK2(p[1+i], sizeof(struct in6_addr));
641
					printf(" %s", getname6(p + 1 + i));
642
					i += sizeof(struct in6_addr);
643
					break;
644
#endif
645
				default:
646
					printf(" (unknown af)");
647
					i = tlen;	/*exit loop*/
648
					break;
649
				}
650
			}
651
			printf(",");
652
		}
653
		p += 1 + tlen;
654
655
		TCHECK(p[0]);
656
		snpa = p[0];
657
		p++;
658
		if (snpa) {
659
			printf(" %u snpa", snpa);
660
			for (/*nothing*/; snpa > 0; snpa--) {
661
				TCHECK(p[0]);
662
				printf("(%d bytes)", p[0]);
663
				p += p[0] + 1;
664
			}
665
			printf(",");
666
		}
667
668
		printf(" NLRI");
669
		while (len - (p - dat) > 0) {
670
			switch (af) {
671
			case AFNUM_INET:
672
				advance = decode_prefix4(p, buf, sizeof(buf));
673
				break;
674
#ifdef INET6
675
			case AFNUM_INET6:
676
				advance = decode_prefix6(p, buf, sizeof(buf));
677
				break;
678
#endif
679
			default:
680
				printf(" (unknown af)");
681
				advance = 0;
682
				p = dat + len;
683
				break;
684
			}
685
686
			if (advance <= 0)
687
				break;
688
689
			printf(" %s", buf);
690
			p += advance;
691
		}
692
693
		break;
694
695
	case BGPTYPE_MP_UNREACH_NLRI:
696
		TCHECK2(p[0], BGP_MP_NLRI_MINSIZE);
697
		af = EXTRACT_16BITS(p);
698
		safi = p[2];
699
		if (safi >= 128)
700
			printf(" %s vendor specific %u,", af_name(af), safi);
701
		else {
702
			printf(" %s %s,", af_name(af),
703
				bgp_attr_nlri_safi(safi));
704
		}
705
		p += 3;
706
707
		printf(" Withdraw");
708
		while (len - (p - dat) > 0) {
709
			switch (af) {
710
			case AFNUM_INET:
711
				advance = decode_prefix4(p, buf, sizeof(buf));
712
				break;
713
#ifdef INET6
714
			case AFNUM_INET6:
715
				advance = decode_prefix6(p, buf, sizeof(buf));
716
				break;
717
#endif
718
			default:
719
				printf(" (unknown af)");
720
				advance = 0;
721
				p = dat + len;
722
				break;
723
			}
724
725
			if (advance <= 0)
726
				break;
727
728
			printf(" %s", buf);
729
			p += advance;
730
		}
731
		break;
732
	default:
733
		break;
734
	}
735
	return 1;
736
737
trunc:
738
	return 0;
739
}
740
741
static void
742
bgp_open_capa_print(const u_char *opt, int length)
743
{
744
	int i,cap_type,cap_len,tcap_len,cap_offset;
745
746
	i = 0;
747
	while (i < length) {
748
		TCHECK2(opt[i], 2);
749
750
		cap_type=opt[i];
751
		cap_len=opt[i+1];
752
		printf("%sCAP %s", i == 0 ? "(" : " ", 		/* ) */
753
		    bgp_capcode(cap_type));
754
755
		/* can we print the capability? */
756
		TCHECK2(opt[i+2],cap_len);
757
		i += 2;
758
759
		switch(cap_type) {
760
		case BGP_CAPCODE_MP:
761
			if (cap_len != 4) {
762
				printf(" BAD ENCODING");
763
				break;
764
			}
765
			printf(" [%s %s]",
766
			    af_name(EXTRACT_16BITS(opt+i)),
767
			    bgp_attr_nlri_safi(opt[i+3]));
768
			break;
769
		case BGP_CAPCODE_REFRESH:
770
			if (cap_len != 0) {
771
				printf(" BAD ENCODING");
772
				break;
773
			}
774
			break;
775
		case BGP_CAPCODE_RESTART:
776
			if (cap_len < 2 || (cap_len - 2) % 4) {
777
				printf(" BAD ENCODING");
778
				break;
779
			}
780
			printf(" [%s], Time %us",
781
			    ((opt[i])&0x80) ? "R" : "none",
782
			    EXTRACT_16BITS(opt+i)&0xfff);
783
			tcap_len=cap_len - 2;
784
			cap_offset=2;
785
			while(tcap_len>=4) {
786
				printf(" (%s %s)%s",
787
				    af_name(EXTRACT_16BITS(opt+i+cap_offset)),
788
				    bgp_attr_nlri_safi(opt[i+cap_offset+2]),
789
				    ((opt[i+cap_offset+3])&0x80) ?
790
					" forwarding state preserved" : "" );
791
				tcap_len-=4;
792
				cap_offset+=4;
793
			}
794
			break;
795
		case BGP_CAPCODE_AS4:
796
			if (cap_len != 4) {
797
				printf(" BAD ENCODING");
798
				break;
799
			}
800
			printf(" #");
801
			if (EXTRACT_16BITS(opt+i))
802
				printf("%u.",
803
				    EXTRACT_16BITS(opt+i));
804
			printf("%u",
805
			    EXTRACT_16BITS(opt+i+2));
806
			break;
807
		default:
808
			printf(" len %d", cap_len);
809
			break;
810
		}
811
		i += cap_len;
812
		if (i + cap_len < length)
813
			printf(",");
814
	}
815
	/* ( */
816
	printf(")");
817
	return;
818
trunc:
819
	printf("[|BGP]");
820
}
821
822
static void
823
bgp_open_print(const u_char *dat, int length)
824
{
825
	struct bgp_open bgpo;
826
	struct bgp_opt bgpopt;
827
	const u_char *opt;
828
	int i;
829
830
	TCHECK2(dat[0], BGP_OPEN_SIZE);
831
	memcpy(&bgpo, dat, BGP_OPEN_SIZE);
832
833
	printf(": Version %d,", bgpo.bgpo_version);
834
	printf(" AS #%u,", ntohs(bgpo.bgpo_myas));
835
	printf(" Holdtime %u,", ntohs(bgpo.bgpo_holdtime));
836
	printf(" ID %s,", getname((u_char *)&bgpo.bgpo_id));
837
	printf(" Option length %u", bgpo.bgpo_optlen);
838
839
	/* sanity checking */
840
	if ((length < bgpo.bgpo_optlen+BGP_OPEN_SIZE) || (!bgpo.bgpo_optlen))
841
		return;
842
843
	/* ugly! */
844
	opt = &((const struct bgp_open *)dat)->bgpo_optlen;
845
	opt++;
846
847
	i = 0;
848
	while (i < bgpo.bgpo_optlen) {
849
		TCHECK2(opt[i], BGP_OPT_SIZE);
850
		memcpy(&bgpopt, &opt[i], BGP_OPT_SIZE);
851
		if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) {
852
			printf(" [|opt %d %d]", bgpopt.bgpopt_len, bgpopt.bgpopt_type);
853
			break;
854
		}
855
856
		if (i == 0)
857
			printf(" (");		/* ) */
858
		else
859
			printf(" ");
860
861
		switch(bgpopt.bgpopt_type) {
862
		case BGP_OPT_CAP:
863
			bgp_open_capa_print(opt + i + BGP_OPT_SIZE,
864
			    bgpopt.bgpopt_len);
865
			break;
866
		default:
867
			printf(" (option %s, len=%u)",
868
			    bgp_opttype(bgpopt.bgpopt_type),
869
			    bgpopt.bgpopt_len);
870
			break;
871
		}
872
873
		i += BGP_OPT_SIZE + bgpopt.bgpopt_len;
874
	}
875
	/* ( */
876
	printf(")");
877
	return;
878
trunc:
879
	printf("[|BGP]");
880
}
881
882
static void
883
bgp_update_print(const u_char *dat, int length)
884
{
885
	struct bgp bgp;
886
	struct bgp_attr bgpa;
887
	const u_char *p;
888
	int len;
889
	int i;
890
	int newline;
891
892
	TCHECK2(dat[0], BGP_SIZE);
893
	memcpy(&bgp, dat, BGP_SIZE);
894
	p = dat + BGP_SIZE;	/*XXX*/
895
	printf(":");
896
897
	/* Unfeasible routes */
898
	len = EXTRACT_16BITS(p);
899
	if (len) {
900
		/*
901
		 * Without keeping state from the original NLRI message,
902
		 * it's not possible to tell if this a v4 or v6 route,
903
		 * so only try to decode it if we're not v6 enabled.
904
	         */
905
#ifdef INET6
906
		printf(" (Withdrawn routes: %d bytes)", len);
907
#else
908
		char buf[HOST_NAME_MAX+1 + 100];
909
		int wpfx;
910
911
		TCHECK2(p[2], len);
912
 		i = 2;
913
914
		printf(" (Withdrawn routes:");
915
916
		while(i < 2 + len) {
917
			wpfx = decode_prefix4(&p[i], buf, sizeof(buf));
918
			if (wpfx == -1) {
919
				printf(" (illegal prefix length)");
920
				break;
921
			} else if (wpfx == -2)
922
				goto trunc;
923
			i += wpfx;
924
			printf(" %s", buf);
925
		}
926
		printf(")");
927
#endif
928
	}
929
	p += 2 + len;
930
931
	TCHECK2(p[0], 2);
932
	len = EXTRACT_16BITS(p);
933
934
	if (len == 0 && length == BGP_UPDATE_MINSIZE) {
935
		printf(" End-of-Rib Marker (empty NLRI)");
936
		return;
937
	}
938
939
	if (len) {
940
		/* do something more useful!*/
941
		i = 2;
942
		printf(" (Path attributes:");	/* ) */
943
		newline = 0;
944
		while (i < 2 + len) {
945
			int alen, aoff;
946
947
			TCHECK2(p[i], sizeof(bgpa));
948
			memcpy(&bgpa, &p[i], sizeof(bgpa));
949
			alen = bgp_attr_len(&bgpa);
950
			aoff = bgp_attr_off(&bgpa);
951
952
			if (vflag && newline)
953
				printf("\n\t\t");
954
			else
955
				printf(" ");
956
			printf("(");		/* ) */
957
			printf("%s", bgp_attr_type(bgpa.bgpa_type));
958
			if (bgpa.bgpa_flags) {
959
				printf("[%s%s%s%s",
960
					bgpa.bgpa_flags & 0x80 ? "O" : "",
961
					bgpa.bgpa_flags & 0x40 ? "T" : "",
962
					bgpa.bgpa_flags & 0x20 ? "P" : "",
963
					bgpa.bgpa_flags & 0x10 ? "E" : "");
964
				if (bgpa.bgpa_flags & 0xf)
965
					printf("+%x", bgpa.bgpa_flags & 0xf);
966
				printf("]");
967
			}
968
969
			if (!bgp_attr_print(&bgpa, &p[i + aoff], alen))
970
				goto trunc;
971
			newline = 1;
972
973
			/* ( */
974
			printf(")");
975
976
			i += aoff + alen;
977
		}
978
979
		/* ( */
980
		printf(")");
981
	}
982
	p += 2 + len;
983
984
	if (len && dat + length > p)
985
		printf("\n\t\t");
986
	if (dat + length > p) {
987
		printf("(NLRI:");	/* ) */
988
		while (dat + length > p) {
989
			char buf[HOST_NAME_MAX+1 + 100];
990
			i = decode_prefix4(p, buf, sizeof(buf));
991
			if (i == -1) {
992
				printf(" (illegal prefix length)");
993
				break;
994
			} else if (i == -2)
995
				goto trunc;
996
			printf(" %s", buf);
997
			p += i;
998
		}
999
1000
		/* ( */
1001
		printf(")");
1002
	}
1003
	return;
1004
trunc:
1005
	printf("[|BGP]");
1006
}
1007
1008
static void
1009
bgp_notification_print(const u_char *dat, int length)
1010
{
1011
	struct bgp_notification bgpn;
1012
	u_int16_t af;
1013
	u_int8_t safi;
1014
	const u_char *p;
1015
	uint8_t shutdown_comm_length;
1016
	char shutstring[BGP_NOTIFY_MINOR_CEASE_ADMIN_SHUTDOWN_LEN + 1];
1017
1018
	TCHECK2(dat[0], BGP_NOTIFICATION_SIZE);
1019
	memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE);
1020
1021
	/* sanity checking */
1022
	if (length<BGP_NOTIFICATION_SIZE)
1023
		return;
1024
1025
	printf(": error %s,", bgp_notify_major(bgpn.bgpn_major));
1026
	printf(" subcode %s",
1027
		bgp_notify_minor(bgpn.bgpn_major, bgpn.bgpn_minor));
1028
1029
	if (bgpn.bgpn_major == BGP_NOTIFY_MAJOR_CEASE) {
1030
		/*
1031
		 * RFC 4486: optional maxprefix subtype of 7 bytes
1032
		 * may contain AFI, SAFI and MAXPREFIXES
1033
		 */
1034
		if(bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_MAXPRFX &&
1035
		    length >= BGP_NOTIFICATION_SIZE + 7) {
1036
1037
			p = dat + BGP_NOTIFICATION_SIZE;
1038
			TCHECK2(*p, 7);
1039
1040
			af = EXTRACT_16BITS(p);
1041
			safi = p[2];
1042
			printf(" %s %s,", af_name(af),
1043
			    bgp_attr_nlri_safi(safi));
1044
1045
			printf(" Max Prefixes: %u", EXTRACT_32BITS(p+3));
1046
		}
1047
1048
		/*
1049
		 * RFC 8203 describes a method to send a message intended
1050
		 * for human consumption regarding the Administrative
1051
		 * Shutdown or Reset event. This is called the "Shutdown
1052
		 * Communication". The communication is UTF-8 encoded
1053
		 * and may be no longer than 128 bytes.
1054
		 */
1055
		if ((bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_SHUT ||
1056
		    bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_RESET) &&
1057
		    (length >= BGP_NOTIFICATION_SIZE + 1)) {
1058
			p = dat + BGP_NOTIFICATION_SIZE;
1059
			TCHECK2(*p, 1);
1060
			shutdown_comm_length = *(p);
1061
1062
			/* sanity checking */
1063
			if (shutdown_comm_length == 0)
1064
				return;
1065
			if (shutdown_comm_length >
1066
			    BGP_NOTIFY_MINOR_CEASE_ADMIN_SHUTDOWN_LEN)
1067
				return;
1068
			if (length < (shutdown_comm_length + 1 + BGP_NOTIFICATION_SIZE))
1069
				return;
1070
			TCHECK2(*(p+1), shutdown_comm_length);
1071
1072
			/* a proper shutdown communication */
1073
			printf(", Shutdown Communication [len %u]: \"",
1074
			    shutdown_comm_length);
1075
			memset(shutstring, 0, BGP_NOTIFY_MINOR_CEASE_ADMIN_SHUTDOWN_LEN + 1);
1076
			memcpy(shutstring, p+1, shutdown_comm_length);
1077
			safeputs(shutstring);
1078
			printf("\"");
1079
		}
1080
	}
1081
1082
	return;
1083
1084
trunc:
1085
	printf("[|BGP]");
1086
}
1087
1088
static void
1089
bgp_route_refresh_print(const u_char *dat, int length)
1090
{
1091
	const struct bgp_route_refresh *bgp_route_refresh_header;
1092
1093
	TCHECK2(dat[0], BGP_ROUTE_REFRESH_SIZE);
1094
1095
	/* sanity checking */
1096
	if (length<BGP_ROUTE_REFRESH_SIZE)
1097
		return;
1098
1099
	bgp_route_refresh_header = (const struct bgp_route_refresh *)dat;
1100
1101
	printf(" (%s %s)",
1102
	    af_name(EXTRACT_16BITS(&bgp_route_refresh_header->afi)),
1103
	    bgp_attr_nlri_safi(bgp_route_refresh_header->safi));
1104
1105
	return;
1106
trunc:
1107
	printf("[|BGP]");
1108
}
1109
1110
static int
1111
bgp_header_print(const u_char *dat, int length)
1112
{
1113
	struct bgp bgp;
1114
1115
	TCHECK2(dat[0], BGP_SIZE);
1116
	memcpy(&bgp, dat, BGP_SIZE);
1117
	printf("(%s", bgp_type(bgp.bgp_type));		/* ) */
1118
1119
	switch (bgp.bgp_type) {
1120
	case BGP_OPEN:
1121
		bgp_open_print(dat, length);
1122
		break;
1123
	case BGP_UPDATE:
1124
		bgp_update_print(dat, length);
1125
		break;
1126
	case BGP_NOTIFICATION:
1127
		bgp_notification_print(dat, length);
1128
		break;
1129
	case BGP_KEEPALIVE:
1130
		break;
1131
	case BGP_ROUTE_REFRESH:
1132
		bgp_route_refresh_print(dat, length);
1133
	default:
1134
		TCHECK2(*dat, length);
1135
		break;
1136
	}
1137
1138
	/* ( */
1139
	printf(")");
1140
	return 1;
1141
trunc:
1142
	printf("[|BGP]");
1143
	return 0;
1144
}
1145
1146
void
1147
bgp_print(const u_char *dat, int length)
1148
{
1149
	const u_char *p;
1150
	const u_char *ep;
1151
	const u_char *start;
1152
	const u_char marker[] = {
1153
		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1154
		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1155
	};
1156
	struct bgp bgp;
1157
	u_int16_t hlen;
1158
	int newline;
1159
1160
	ep = dat + length;
1161
	if (snapend < dat + length)
1162
		ep = snapend;
1163
1164
	printf(": BGP");
1165
1166
	p = dat;
1167
	newline = 0;
1168
	start = p;
1169
	while (p < ep) {
1170
		if (!TTEST2(p[0], 1))
1171
			break;
1172
		if (p[0] != 0xff) {
1173
			p++;
1174
			continue;
1175
		}
1176
1177
		if (!TTEST2(p[0], sizeof(marker)))
1178
			break;
1179
		if (memcmp(p, marker, sizeof(marker)) != 0) {
1180
			p++;
1181
			continue;
1182
		}
1183
1184
		/* found BGP header */
1185
		TCHECK2(p[0], BGP_SIZE);	/*XXX*/
1186
		memcpy(&bgp, p, BGP_SIZE);
1187
1188
		if (start != p)
1189
			printf(" [|BGP]");
1190
1191
		hlen = ntohs(bgp.bgp_len);
1192
		if (vflag && newline)
1193
			printf("\n\t");
1194
		else
1195
			printf(" ");
1196
		if (hlen < BGP_SIZE) {
1197
			printf("\n[|BGP Bogus header length %u < %u]",
1198
			    hlen, BGP_SIZE);
1199
			break;
1200
		}
1201
		if (TTEST2(p[0], hlen)) {
1202
			if (!bgp_header_print(p, hlen))
1203
				return;
1204
			newline = 1;
1205
			p += hlen;
1206
			start = p;
1207
		} else {
1208
			printf("[|BGP %s]", bgp_type(bgp.bgp_type));
1209
			break;
1210
		}
1211
	}
1212
1213
	return;
1214
1215
trunc:
1216
	printf(" [|BGP]");
1217
}