xref: /openbsd-src/usr.sbin/tcpdump/print-bgp.c (revision 824adb5411e4389b29bae28eba5c2c2bbd147f34)
1 /*	$OpenBSD: print-bgp.c,v 1.30 2021/06/17 15:59:23 job 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 subtype;
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 	/* 70: RFC7313 */ "ENHANCED_ROUTE_REFRESH"
193 };
194 
195 #define bgp_capcode(x) \
196 	num_or_str(bgp_capcode, sizeof(bgp_capcode)/sizeof(bgp_capcode[0]), (x))
197 
198 #define BGP_NOTIFY_MAJOR_CEASE		6
199 static const char *bgpnotify_major[] = {
200 	NULL, "Message Header Error",
201 	"OPEN Message Error", "UPDATE Message Error",
202 	"Hold Timer Expired", "Finite State Machine Error",
203 	"Cease", "ROUTE_REFRESH Message Error",
204 };
205 #define bgp_notify_major(x) \
206 	num_or_str(bgpnotify_major, \
207 		sizeof(bgpnotify_major)/sizeof(bgpnotify_major[0]), (x))
208 
209 static const char *bgpnotify_minor_msg[] = {
210 	NULL, "Connection Not Synchronized",
211 	"Bad Message Length", "Bad Message Type",
212 };
213 
214 static const char *bgpnotify_minor_open[] = {
215 	NULL, "Unsupported Version Number",
216 	"Bad Peer AS", "Bad BGP Identifier",
217 	"Unsupported Optional Parameter", "Authentication Failure",
218 	"Unacceptable Hold Time", "Unsupported Capability",
219 };
220 
221 static const char *bgpnotify_minor_update[] = {
222 	NULL, "Malformed Attribute List",
223 	"Unrecognized Well-known Attribute", "Missing Well-known Attribute",
224 	"Attribute Flags Error", "Attribute Length Error",
225 	"Invalid ORIGIN Attribute", "AS Routing Loop",
226 	"Invalid NEXT_HOP Attribute", "Optional Attribute Error",
227 	"Invalid Network Field", "Malformed AS_PATH",
228 };
229 
230 static const char *bgpnotify_minor_holdtime[] = {
231 	NULL,
232 };
233 
234 /* RFC 6608 */
235 static const char *bgpnotify_minor_fsm[] = {
236 	"Unspecified Error", "In OpenSent State", "In OpenConfirm State",
237 	"In Established State",
238 };
239 
240 /* RFC 4486 */
241 #define BGP_NOTIFY_MINOR_CEASE_MAXPRFX  1
242 /* RFC 8203 */
243 #define BGP_NOTIFY_MINOR_CEASE_SHUT			2
244 #define BGP_NOTIFY_MINOR_CEASE_RESET			4
245 #define BGP_NOTIFY_MINOR_CEASE_ADMIN_SHUTDOWN_LEN	255
246 static const char *bgpnotify_minor_cease[] = {
247 	NULL, "Maximum Number of Prefixes Reached", "Administrative Shutdown",
248 	"Peer De-configured", "Administrative Reset", "Connection Rejected",
249 	"Other Configuration Change", "Connection Collision Resolution",
250 	"Out of Resources",
251 };
252 
253 /* RFC 7313 */
254 static const char *bgpnotify_minor_err[] = {
255 	NULL, "Invalid Message Length",
256 };
257 
258 static const char **bgpnotify_minor[] = {
259 	NULL, bgpnotify_minor_msg, bgpnotify_minor_open, bgpnotify_minor_update,
260 	bgpnotify_minor_holdtime, bgpnotify_minor_fsm, bgpnotify_minor_cease,
261 	bgpnotify_minor_err,
262 };
263 static const int bgpnotify_minor_siz[] = {
264 	0,
265 	sizeof(bgpnotify_minor_msg)/sizeof(bgpnotify_minor_msg[0]),
266 	sizeof(bgpnotify_minor_open)/sizeof(bgpnotify_minor_open[0]),
267 	sizeof(bgpnotify_minor_update)/sizeof(bgpnotify_minor_update[0]),
268 	sizeof(bgpnotify_minor_holdtime)/sizeof(bgpnotify_minor_holdtime[0]),
269 	sizeof(bgpnotify_minor_fsm)/sizeof(bgpnotify_minor_fsm[0]),
270 	sizeof(bgpnotify_minor_cease)/sizeof(bgpnotify_minor_cease[0]),
271 	sizeof(bgpnotify_minor_err)/sizeof(bgpnotify_minor_err[0]),
272 };
273 
274 static const char *bgpattr_origin[] = {
275 	"IGP", "EGP", "INCOMPLETE",
276 };
277 #define bgp_attr_origin(x) \
278 	num_or_str(bgpattr_origin, \
279 		sizeof(bgpattr_origin)/sizeof(bgpattr_origin[0]), (x))
280 
281 static const char *bgpattr_type[] = {
282 	NULL, "ORIGIN", "AS_PATH", "NEXT_HOP",
283 	"MULTI_EXIT_DISC", "LOCAL_PREF", "ATOMIC_AGGREGATE", "AGGREGATOR",
284 	"COMMUNITIES", "ORIGINATOR_ID", "CLUSTER_LIST", "DPA",
285 	"ADVERTISERS", "RCID_PATH", "MP_REACH_NLRI", "MP_UNREACH_NLRI",
286 	"EXTD_COMMUNITIES", "AS4_PATH", "AGGREGATOR4", NULL, NULL, NULL,
287 	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
288 	"LARGE_COMMUNITIES",
289 };
290 #define bgp_attr_type(x) \
291 	num_or_str(bgpattr_type, \
292 		sizeof(bgpattr_type)/sizeof(bgpattr_type[0]), (x))
293 
294 /* Subsequent address family identifier, RFC2283 section 7 */
295 static const char *bgpattr_nlri_safi[] = {
296 	"Reserved", "Unicast", "Multicast", "Unicast+Multicast",
297 	"labeled Unicast", /* MPLS BGP RFC3107 */
298 	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 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
302 	/* 64-66: MPLS BGP RFC3107 */
303 	"Tunnel", "VPLS", "MDT",
304 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
305 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
306 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
307 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
308 	/* 128-129: RFC4364 + RFC6513 */
309 	"L3VPN Unicast", "L3VPN Multicast",
310 };
311 #define bgp_attr_nlri_safi(x) \
312 	num_or_str(bgpattr_nlri_safi, \
313 		sizeof(bgpattr_nlri_safi)/sizeof(bgpattr_nlri_safi[0]), (x))
314 
315 /* well-known community */
316 #define BGP_COMMUNITY_NO_EXPORT			0xffffff01
317 #define BGP_COMMUNITY_NO_ADVERT			0xffffff02
318 #define BGP_COMMUNITY_NO_EXPORT_SUBCONFED	0xffffff03
319 #define BGP_COMMUNITY_NO_PEER			0xffffff04
320 
321 static const char *afnumber[] = AFNUM_NAME_STR;
322 #define af_name(x) \
323 	(((x) == 65535) ? afnumber[0] : \
324 		num_or_str(afnumber, \
325 			sizeof(afnumber)/sizeof(afnumber[0]), (x)))
326 
327 static const char *refreshtype[] = {
328 	"Request", "BoRR", "EoRR"
329 };
330 #define refresh_subtype(x) \
331 	num_or_str(refreshtype, sizeof(refreshtype)/sizeof(refreshtype[0]), (x))
332 
333 static const char *
334 num_or_str(const char **table, size_t siz, int value)
335 {
336 	static char buf[20];
337 	if (value < 0 || siz <= value || table[value] == NULL) {
338 		snprintf(buf, sizeof(buf), "#%d", value);
339 		return buf;
340 	} else
341 		return table[value];
342 }
343 
344 static const char *
345 bgp_notify_minor(int major, int minor)
346 {
347 	static const char **table;
348 	int siz;
349 	static char buf[20];
350 	const char *p;
351 
352 	if (0 <= major
353 	 && major < sizeof(bgpnotify_minor)/sizeof(bgpnotify_minor[0])
354 	 && bgpnotify_minor[major]) {
355 		table = bgpnotify_minor[major];
356 		siz = bgpnotify_minor_siz[major];
357 		if (0 <= minor && minor < siz && table[minor])
358 			p = table[minor];
359 		else
360 			p = NULL;
361 	} else
362 		p = NULL;
363 	if (p == NULL) {
364 		snprintf(buf, sizeof(buf), "#%d", minor);
365 		return buf;
366 	} else
367 		return p;
368 }
369 
370 static int
371 decode_prefix4(const u_char *pd, char *buf, u_int buflen)
372 {
373 	struct in_addr addr;
374 	u_int plen;
375 	int n;
376 
377 	TCHECK(pd[0]);
378 	plen = pd[0]; /*
379 		       * prefix length is in bits; packet only contains
380 		       * enough bytes of address to contain this many bits
381 		       */
382 	plen = pd[0];
383 	if (32 < plen)
384 		return -1;
385 	memset(&addr, 0, sizeof(addr));
386 	TCHECK2(pd[1], (plen + 7) / 8);
387 	memcpy(&addr, &pd[1], (plen + 7) / 8);
388 	if (plen % 8) {
389 		((u_char *)&addr)[(plen + 7) / 8 - 1] &=
390 			((0xff00 >> (plen % 8)) & 0xff);
391 	}
392 	n = snprintf(buf, buflen, "%s/%u", getname((u_char *)&addr), plen);
393 	if (n < 0 || n >= buflen)
394 		return -1;
395 
396 	return 1 + (plen + 7) / 8;
397 
398 trunc:
399 	return -2;
400 }
401 
402 static int
403 decode_prefix6(const u_char *pd, char *buf, u_int buflen)
404 {
405 	struct in6_addr addr;
406 	u_int plen;
407 	int n;
408 
409 	TCHECK(pd[0]);
410 	plen = pd[0];
411 	if (128 < plen)
412 		return -1;
413 
414 	memset(&addr, 0, sizeof(addr));
415 	TCHECK2(pd[1], (plen + 7) / 8);
416 	memcpy(&addr, &pd[1], (plen + 7) / 8);
417 	if (plen % 8) {
418 		addr.s6_addr[(plen + 7) / 8 - 1] &=
419 			((0xff00 >> (plen % 8)) & 0xff);
420 	}
421 
422 	n = snprintf(buf, buflen, "%s/%u", getname6((u_char *)&addr), plen);
423 	if (n < 0 || n >= buflen)
424 		return -1;
425 
426 	return 1 + (plen + 7) / 8;
427 
428 trunc:
429 	return -2;
430 }
431 
432 static int
433 bgp_attr_print(const struct bgp_attr *attr, const u_char *dat, int len)
434 {
435 	int i;
436 	u_int16_t af;
437 	u_int8_t safi, snpa;
438 	int advance;
439 	int tlen, asn_bytes;
440 	const u_char *p;
441 	char buf[HOST_NAME_MAX+1 + 100];
442 
443 	p = dat;
444 	tlen = len;
445 	asn_bytes = 0;
446 
447 	switch (attr->bgpa_type) {
448 	case BGPTYPE_ORIGIN:
449 		if (len != 1)
450 			printf(" invalid len");
451 		else {
452 			TCHECK(p[0]);
453 			printf(" %s", bgp_attr_origin(p[0]));
454 		}
455 		break;
456 	case BGPTYPE_AS4_PATH:
457 		asn_bytes = 4;
458 		/* FALLTHROUGH */
459 	case BGPTYPE_AS_PATH:
460 	/*
461 	 * 2-byte speakers will receive AS4_PATH as well AS_PATH (2-byte).
462 	 * 4-byte speakers will only receive AS_PATH but it will be 4-byte.
463 	 * To identify which is the case, compare the length of the path
464 	 * segment value in bytes, with the path segment length from the
465 	 * message (counted in # of AS)
466 	 */
467 
468 		if (len % 2) {
469 			printf(" invalid len");
470 			break;
471 		}
472 		if (!len) {
473 			/* valid: local originated routes to IBGP peers */
474 			printf(" empty");
475 			break;
476 		}
477 		while (p < dat + len) {
478 			TCHECK2(p[0], 2);
479 			if (asn_bytes == 0) {
480 				if (p[1] == 0) {
481 				/* invalid: segment contains one or more AS */
482 					printf(" malformed");
483 					break;
484 				}
485 				asn_bytes = (len-2)/p[1];
486 			}
487 			printf("%s",
488 			    tok2str(bgp_as_path_segment_open_values,
489 			    "?", p[0]));
490 			for (i = 0; i < p[1] * asn_bytes; i += asn_bytes) {
491 				TCHECK2(p[2 + i], asn_bytes);
492 				printf("%s", i == 0 ? "" : " ");
493 				if (asn_bytes == 2 || EXTRACT_16BITS(&p[2 + i]))
494 					printf("%u%s",
495 					    EXTRACT_16BITS(&p[2 + i]),
496 					    asn_bytes == 4 ? "." : "");
497 				if (asn_bytes == 4)
498 					printf("%u",
499 					    EXTRACT_16BITS(&p[2 + i + 2]));
500 			}
501 			printf("%s",
502 			    tok2str(bgp_as_path_segment_close_values,
503 			    "?", p[0]));
504 			p += 2 + p[1] * asn_bytes;
505 		}
506 		break;
507 	case BGPTYPE_NEXT_HOP:
508 		if (len != 4)
509 			printf(" invalid len");
510 		else {
511 			TCHECK2(p[0], 4);
512 			printf(" %s", getname(p));
513 		}
514 		break;
515 	case BGPTYPE_MULTI_EXIT_DISC:
516 	case BGPTYPE_LOCAL_PREF:
517 		if (len != 4)
518 			printf(" invalid len");
519 		else {
520 			TCHECK2(p[0], 4);
521 			printf(" %u", EXTRACT_32BITS(p));
522 		}
523 		break;
524 	case BGPTYPE_ATOMIC_AGGREGATE:
525 		if (len != 0)
526 			printf(" invalid len");
527 		break;
528 	case BGPTYPE_AGGREGATOR4:
529 	case BGPTYPE_AGGREGATOR:
530 	/*
531 	 * like AS_PATH/AS4_PATH, AGGREGATOR can contain
532 	 * either 2-byte or 4-byte ASN, and AGGREGATOR4
533 	 * always contains 4-byte ASN.
534 	 */
535 		if (len != 6 && len != 8) {
536 			printf(" invalid len");
537 			break;
538 		}
539 		TCHECK2(p[0], len);
540 		printf(" AS #");
541 		if (len == 6 || EXTRACT_16BITS(p))
542 			printf("%u%s", EXTRACT_16BITS(p), len == 8 ? "." : "");
543 		if (len == 8)
544 			printf("%u", EXTRACT_16BITS(p+2));
545 		printf(", origin %s", getname(p+len-4));
546 		break;
547 	case BGPTYPE_COMMUNITIES:
548 		if (len % 4) {
549 			printf(" invalid len");
550 			break;
551 		}
552 		while (tlen>0) {
553 			u_int32_t comm;
554 			TCHECK2(p[0], 4);
555 			comm = EXTRACT_32BITS(p);
556 			switch (comm) {
557 			case BGP_COMMUNITY_NO_EXPORT:
558 				printf(" NO_EXPORT");
559 				break;
560 			case BGP_COMMUNITY_NO_ADVERT:
561 				printf(" NO_ADVERTISE");
562 				break;
563 			case BGP_COMMUNITY_NO_EXPORT_SUBCONFED:
564 				printf(" NO_EXPORT_SUBCONFED");
565 				break;
566 			case BGP_COMMUNITY_NO_PEER:
567 				printf(" NO_PEER");
568 				break;
569 			default:
570 				printf(" %d:%d",
571 					(comm >> 16) & 0xffff, comm & 0xffff);
572 				break;
573 			}
574 			tlen -= 4;
575 			p += 4;
576 		}
577 		break;
578 	case BGPTYPE_LARGE_COMMUNITIES:
579 		if (len == 0 || len % 12) {
580 			printf(" invalid len");
581 			break;
582 		}
583 		while (tlen>0) {
584 			TCHECK2(p[0], 12);
585 			printf(" %u:%u:%u",
586 			EXTRACT_32BITS(p),
587 			EXTRACT_32BITS(p + 4),
588 			EXTRACT_32BITS(p + 8));
589 			tlen -= 12;
590 			p += 12;
591 		}
592 		break;
593 	case BGPTYPE_ORIGINATOR_ID:
594 		if (len != 4) {
595 			printf(" invalid len");
596 			break;
597                 }
598 		TCHECK2(p[0], 4);
599 		printf("%s",getname(p));
600 		break;
601 	case BGPTYPE_CLUSTER_LIST:
602 		if (len % 4) {
603 			printf(" invalid len");
604 			break;
605 		}
606 		while (tlen>0) {
607 			TCHECK2(p[0], 4);
608 			printf(" %s%s",
609 			    getname(p),
610 			    (tlen>4) ? ", " : "");
611 			tlen -=4;
612 			p +=4;
613 		}
614 		break;
615 	case BGPTYPE_MP_REACH_NLRI:
616 		TCHECK2(p[0], BGP_MP_NLRI_MINSIZE);
617 		af = EXTRACT_16BITS(p);
618 		safi = p[2];
619 		if (safi >= 128)
620 			printf(" %s vendor specific %u,", af_name(af), safi);
621 		else {
622 			printf(" %s %s,", af_name(af),
623 				bgp_attr_nlri_safi(safi));
624 		}
625 		p += 3;
626 
627 		if (af != AFNUM_INET && af != AFNUM_INET6)
628 			break;
629 
630 		TCHECK(p[0]);
631 		tlen = p[0];
632 		if (tlen) {
633 			printf(" nexthop");
634 			i = 0;
635 			while (i < tlen) {
636 				switch (af) {
637 				case AFNUM_INET:
638 					TCHECK2(p[1+i], sizeof(struct in_addr));
639 					printf(" %s", getname(p + 1 + i));
640 					i += sizeof(struct in_addr);
641 					break;
642 				case AFNUM_INET6:
643 					TCHECK2(p[1+i], sizeof(struct in6_addr));
644 					printf(" %s", getname6(p + 1 + i));
645 					i += sizeof(struct in6_addr);
646 					break;
647 				default:
648 					printf(" (unknown af)");
649 					i = tlen;	/*exit loop*/
650 					break;
651 				}
652 			}
653 			printf(",");
654 		}
655 		p += 1 + tlen;
656 
657 		TCHECK(p[0]);
658 		snpa = p[0];
659 		p++;
660 		if (snpa) {
661 			printf(" %u snpa", snpa);
662 			for (/*nothing*/; snpa > 0; snpa--) {
663 				TCHECK(p[0]);
664 				printf("(%d bytes)", p[0]);
665 				p += p[0] + 1;
666 			}
667 			printf(",");
668 		}
669 
670 		printf(" NLRI");
671 		while (len - (p - dat) > 0) {
672 			switch (af) {
673 			case AFNUM_INET:
674 				advance = decode_prefix4(p, buf, sizeof(buf));
675 				break;
676 			case AFNUM_INET6:
677 				advance = decode_prefix6(p, buf, sizeof(buf));
678 				break;
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 			case AFNUM_INET6:
714 				advance = decode_prefix6(p, buf, sizeof(buf));
715 				break;
716 			default:
717 				printf(" (unknown af)");
718 				advance = 0;
719 				p = dat + len;
720 				break;
721 			}
722 
723 			if (advance <= 0)
724 				break;
725 
726 			printf(" %s", buf);
727 			p += advance;
728 		}
729 		break;
730 	default:
731 		break;
732 	}
733 	return 1;
734 
735 trunc:
736 	return 0;
737 }
738 
739 static void
740 bgp_open_capa_print(const u_char *opt, int length)
741 {
742 	int i,cap_type,cap_len,tcap_len,cap_offset;
743 
744 	i = 0;
745 	while (i < length) {
746 		TCHECK2(opt[i], 2);
747 
748 		cap_type=opt[i];
749 		cap_len=opt[i+1];
750 		printf("%sCAP %s", i == 0 ? "(" : " ", 		/* ) */
751 		    bgp_capcode(cap_type));
752 
753 		/* can we print the capability? */
754 		TCHECK2(opt[i+2],cap_len);
755 		i += 2;
756 
757 		switch(cap_type) {
758 		case BGP_CAPCODE_MP:
759 			if (cap_len != 4) {
760 				printf(" BAD ENCODING");
761 				break;
762 			}
763 			printf(" [%s %s]",
764 			    af_name(EXTRACT_16BITS(opt+i)),
765 			    bgp_attr_nlri_safi(opt[i+3]));
766 			break;
767 		case BGP_CAPCODE_REFRESH:
768 			if (cap_len != 0) {
769 				printf(" BAD ENCODING");
770 				break;
771 			}
772 			break;
773 		case BGP_CAPCODE_RESTART:
774 			if (cap_len < 2 || (cap_len - 2) % 4) {
775 				printf(" BAD ENCODING");
776 				break;
777 			}
778 			printf(" [%s], Time %us",
779 			    ((opt[i])&0x80) ? "R" : "none",
780 			    EXTRACT_16BITS(opt+i)&0xfff);
781 			tcap_len=cap_len - 2;
782 			cap_offset=2;
783 			while(tcap_len>=4) {
784 				printf(" (%s %s)%s",
785 				    af_name(EXTRACT_16BITS(opt+i+cap_offset)),
786 				    bgp_attr_nlri_safi(opt[i+cap_offset+2]),
787 				    ((opt[i+cap_offset+3])&0x80) ?
788 					" forwarding state preserved" : "" );
789 				tcap_len-=4;
790 				cap_offset+=4;
791 			}
792 			break;
793 		case BGP_CAPCODE_AS4:
794 			if (cap_len != 4) {
795 				printf(" BAD ENCODING");
796 				break;
797 			}
798 			printf(" #");
799 			if (EXTRACT_16BITS(opt+i))
800 				printf("%u.",
801 				    EXTRACT_16BITS(opt+i));
802 			printf("%u",
803 			    EXTRACT_16BITS(opt+i+2));
804 			break;
805 		default:
806 			printf(" len %d", cap_len);
807 			break;
808 		}
809 		i += cap_len;
810 		if (i + cap_len < length)
811 			printf(",");
812 	}
813 	/* ( */
814 	printf(")");
815 	return;
816 trunc:
817 	printf("[|BGP]");
818 }
819 
820 static void
821 bgp_open_print(const u_char *dat, int length)
822 {
823 	struct bgp_open bgpo;
824 	struct bgp_opt bgpopt;
825 	const u_char *opt;
826 	int i;
827 
828 	TCHECK2(dat[0], BGP_OPEN_SIZE);
829 	memcpy(&bgpo, dat, BGP_OPEN_SIZE);
830 
831 	printf(": Version %d,", bgpo.bgpo_version);
832 	printf(" AS #%u,", ntohs(bgpo.bgpo_myas));
833 	printf(" Holdtime %u,", ntohs(bgpo.bgpo_holdtime));
834 	printf(" ID %s,", getname((u_char *)&bgpo.bgpo_id));
835 	printf(" Option length %u", bgpo.bgpo_optlen);
836 
837 	/* sanity checking */
838 	if ((length < bgpo.bgpo_optlen+BGP_OPEN_SIZE) || (!bgpo.bgpo_optlen))
839 		return;
840 
841 	/* ugly! */
842 	opt = &((const struct bgp_open *)dat)->bgpo_optlen;
843 	opt++;
844 
845 	i = 0;
846 	while (i < bgpo.bgpo_optlen) {
847 		TCHECK2(opt[i], BGP_OPT_SIZE);
848 		memcpy(&bgpopt, &opt[i], BGP_OPT_SIZE);
849 		if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) {
850 			printf(" [|opt %d %d]", bgpopt.bgpopt_len, bgpopt.bgpopt_type);
851 			break;
852 		}
853 
854 		if (i == 0)
855 			printf(" (");		/* ) */
856 		else
857 			printf(" ");
858 
859 		switch(bgpopt.bgpopt_type) {
860 		case BGP_OPT_CAP:
861 			bgp_open_capa_print(opt + i + BGP_OPT_SIZE,
862 			    bgpopt.bgpopt_len);
863 			break;
864 		default:
865 			printf(" (option %s, len=%u)",
866 			    bgp_opttype(bgpopt.bgpopt_type),
867 			    bgpopt.bgpopt_len);
868 			break;
869 		}
870 
871 		i += BGP_OPT_SIZE + bgpopt.bgpopt_len;
872 	}
873 	/* ( */
874 	printf(")");
875 	return;
876 trunc:
877 	printf("[|BGP]");
878 }
879 
880 static void
881 bgp_update_print(const u_char *dat, int length)
882 {
883 	struct bgp bgp;
884 	struct bgp_attr bgpa;
885 	const u_char *p;
886 	int len;
887 	int i;
888 	int newline;
889 
890 	TCHECK2(dat[0], BGP_SIZE);
891 	memcpy(&bgp, dat, BGP_SIZE);
892 	p = dat + BGP_SIZE;	/*XXX*/
893 	printf(":");
894 
895 	/* Unfeasible routes */
896 	len = EXTRACT_16BITS(p);
897 	if (len) {
898 		/*
899 		 * Without keeping state from the original NLRI message,
900 		 * it's not possible to tell if this a v4 or v6 route,
901 		 * so do not try to decode it.
902 		 */
903 		printf(" (Withdrawn routes: %d bytes)", len);
904 	}
905 	p += 2 + len;
906 
907 	TCHECK2(p[0], 2);
908 	len = EXTRACT_16BITS(p);
909 
910 	if (len == 0 && length == BGP_UPDATE_MINSIZE) {
911 		printf(" End-of-Rib Marker (empty NLRI)");
912 		return;
913 	}
914 
915 	if (len) {
916 		/* do something more useful!*/
917 		i = 2;
918 		printf(" (Path attributes:");	/* ) */
919 		newline = 0;
920 		while (i < 2 + len) {
921 			int alen, aoff;
922 
923 			TCHECK2(p[i], sizeof(bgpa));
924 			memcpy(&bgpa, &p[i], sizeof(bgpa));
925 			alen = bgp_attr_len(&bgpa);
926 			aoff = bgp_attr_off(&bgpa);
927 
928 			if (vflag && newline)
929 				printf("\n\t\t");
930 			else
931 				printf(" ");
932 			printf("(");		/* ) */
933 			printf("%s", bgp_attr_type(bgpa.bgpa_type));
934 			if (bgpa.bgpa_flags) {
935 				printf("[%s%s%s%s",
936 					bgpa.bgpa_flags & 0x80 ? "O" : "",
937 					bgpa.bgpa_flags & 0x40 ? "T" : "",
938 					bgpa.bgpa_flags & 0x20 ? "P" : "",
939 					bgpa.bgpa_flags & 0x10 ? "E" : "");
940 				if (bgpa.bgpa_flags & 0xf)
941 					printf("+%x", bgpa.bgpa_flags & 0xf);
942 				printf("]");
943 			}
944 
945 			if (!bgp_attr_print(&bgpa, &p[i + aoff], alen))
946 				goto trunc;
947 			newline = 1;
948 
949 			/* ( */
950 			printf(")");
951 
952 			i += aoff + alen;
953 		}
954 
955 		/* ( */
956 		printf(")");
957 	}
958 	p += 2 + len;
959 
960 	if (len && dat + length > p)
961 		printf("\n\t\t");
962 	if (dat + length > p) {
963 		printf("(NLRI:");	/* ) */
964 		while (dat + length > p) {
965 			char buf[HOST_NAME_MAX+1 + 100];
966 			i = decode_prefix4(p, buf, sizeof(buf));
967 			if (i == -1) {
968 				printf(" (illegal prefix length)");
969 				break;
970 			} else if (i == -2)
971 				goto trunc;
972 			printf(" %s", buf);
973 			p += i;
974 		}
975 
976 		/* ( */
977 		printf(")");
978 	}
979 	return;
980 trunc:
981 	printf("[|BGP]");
982 }
983 
984 static void
985 bgp_notification_print(const u_char *dat, int length)
986 {
987 	struct bgp_notification bgpn;
988 	u_int16_t af;
989 	u_int8_t safi;
990 	const u_char *p;
991 	size_t shutdown_comm_length;
992 	char shutstring[BGP_NOTIFY_MINOR_CEASE_ADMIN_SHUTDOWN_LEN + 1];
993 
994 	TCHECK2(dat[0], BGP_NOTIFICATION_SIZE);
995 	memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE);
996 
997 	/* sanity checking */
998 	if (length < BGP_NOTIFICATION_SIZE)
999 		return;
1000 
1001 	printf(": error %s,", bgp_notify_major(bgpn.bgpn_major));
1002 	printf(" subcode %s",
1003 		bgp_notify_minor(bgpn.bgpn_major, bgpn.bgpn_minor));
1004 
1005 	if (bgpn.bgpn_major == BGP_NOTIFY_MAJOR_CEASE) {
1006 		/*
1007 		 * RFC 4486: optional maxprefix subtype of 7 bytes
1008 		 * may contain AFI, SAFI and MAXPREFIXES
1009 		 */
1010 		if(bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_MAXPRFX &&
1011 		    length >= BGP_NOTIFICATION_SIZE + 7) {
1012 
1013 			p = dat + BGP_NOTIFICATION_SIZE;
1014 			TCHECK2(*p, 7);
1015 
1016 			af = EXTRACT_16BITS(p);
1017 			safi = p[2];
1018 			printf(" %s %s,", af_name(af),
1019 			    bgp_attr_nlri_safi(safi));
1020 
1021 			printf(" Max Prefixes: %u", EXTRACT_32BITS(p+3));
1022 		}
1023 
1024 		/*
1025 		 * RFC 8203 describes a method to send a message intended
1026 		 * for human consumption regarding the Administrative
1027 		 * Shutdown or Reset event. This is called the "Shutdown
1028 		 * Communication". The communication is UTF-8 encoded
1029 		 * and may be no longer than 128 bytes.
1030 		 */
1031 		if ((bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_SHUT ||
1032 		    bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_RESET) &&
1033 		    (length >= BGP_NOTIFICATION_SIZE + 1)) {
1034 			p = dat + BGP_NOTIFICATION_SIZE;
1035 			TCHECK2(*p, 1);
1036 			shutdown_comm_length = *p;
1037 
1038 			/* sanity checking */
1039 			if (shutdown_comm_length == 0)
1040 				return;
1041 			if (shutdown_comm_length >
1042 			    BGP_NOTIFY_MINOR_CEASE_ADMIN_SHUTDOWN_LEN)
1043 				goto trunc;
1044 			if (length < (shutdown_comm_length + 1 +
1045 			    BGP_NOTIFICATION_SIZE))
1046 				goto trunc;
1047 			TCHECK2(*(p+1), shutdown_comm_length);
1048 
1049 			/* a proper shutdown communication */
1050 			printf(", Shutdown Communication [len %zu]: \"",
1051 			    shutdown_comm_length);
1052 			memset(shutstring, 0, sizeof(shutstring));
1053 			memcpy(shutstring, p+1, shutdown_comm_length);
1054 			safeputs(shutstring);
1055 			printf("\"");
1056 		}
1057 	}
1058 
1059 	return;
1060 
1061 trunc:
1062 	printf("[|BGP]");
1063 }
1064 
1065 static void
1066 bgp_route_refresh_print(const u_char *dat, int length)
1067 {
1068 	const struct bgp_route_refresh *bgp_route_refresh_header;
1069 
1070 	TCHECK2(dat[0], BGP_ROUTE_REFRESH_SIZE);
1071 
1072 	/* sanity checking */
1073 	if (length<BGP_ROUTE_REFRESH_SIZE)
1074 		return;
1075 
1076 	bgp_route_refresh_header = (const struct bgp_route_refresh *)dat;
1077 
1078 	printf(" %s (%s %s)",
1079 	    refresh_subtype(bgp_route_refresh_header->subtype),
1080 	    af_name(EXTRACT_16BITS(&bgp_route_refresh_header->afi)),
1081 	    bgp_attr_nlri_safi(bgp_route_refresh_header->safi));
1082 
1083 	return;
1084 trunc:
1085 	printf("[|BGP]");
1086 }
1087 
1088 static int
1089 bgp_header_print(const u_char *dat, int length)
1090 {
1091 	struct bgp bgp;
1092 
1093 	TCHECK2(dat[0], BGP_SIZE);
1094 	memcpy(&bgp, dat, BGP_SIZE);
1095 	printf("(%s", bgp_type(bgp.bgp_type));		/* ) */
1096 
1097 	switch (bgp.bgp_type) {
1098 	case BGP_OPEN:
1099 		bgp_open_print(dat, length);
1100 		break;
1101 	case BGP_UPDATE:
1102 		bgp_update_print(dat, length);
1103 		break;
1104 	case BGP_NOTIFICATION:
1105 		bgp_notification_print(dat, length);
1106 		break;
1107 	case BGP_KEEPALIVE:
1108 		break;
1109 	case BGP_ROUTE_REFRESH:
1110 		bgp_route_refresh_print(dat, length);
1111 	default:
1112 		TCHECK2(*dat, length);
1113 		break;
1114 	}
1115 
1116 	/* ( */
1117 	printf(")");
1118 	return 1;
1119 trunc:
1120 	printf("[|BGP]");
1121 	return 0;
1122 }
1123 
1124 void
1125 bgp_print(const u_char *dat, int length)
1126 {
1127 	const u_char *p;
1128 	const u_char *ep;
1129 	const u_char *start;
1130 	const u_char marker[] = {
1131 		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1132 		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1133 	};
1134 	struct bgp bgp;
1135 	u_int16_t hlen;
1136 	int newline;
1137 
1138 	ep = dat + length;
1139 	if (snapend < dat + length)
1140 		ep = snapend;
1141 
1142 	printf(": BGP");
1143 
1144 	p = dat;
1145 	newline = 0;
1146 	start = p;
1147 	while (p < ep) {
1148 		if (!TTEST2(p[0], 1))
1149 			break;
1150 		if (p[0] != 0xff) {
1151 			p++;
1152 			continue;
1153 		}
1154 
1155 		if (!TTEST2(p[0], sizeof(marker)))
1156 			break;
1157 		if (memcmp(p, marker, sizeof(marker)) != 0) {
1158 			p++;
1159 			continue;
1160 		}
1161 
1162 		/* found BGP header */
1163 		TCHECK2(p[0], BGP_SIZE);	/*XXX*/
1164 		memcpy(&bgp, p, BGP_SIZE);
1165 
1166 		if (start != p)
1167 			printf(" [|BGP]");
1168 
1169 		hlen = ntohs(bgp.bgp_len);
1170 		if (vflag && newline)
1171 			printf("\n\t");
1172 		else
1173 			printf(" ");
1174 		if (hlen < BGP_SIZE) {
1175 			printf("\n[|BGP Bogus header length %u < %u]",
1176 			    hlen, BGP_SIZE);
1177 			break;
1178 		}
1179 		if (TTEST2(p[0], hlen)) {
1180 			if (!bgp_header_print(p, hlen))
1181 				return;
1182 			newline = 1;
1183 			p += hlen;
1184 			start = p;
1185 		} else {
1186 			printf("[|BGP %s]", bgp_type(bgp.bgp_type));
1187 			break;
1188 		}
1189 	}
1190 
1191 	return;
1192 
1193 trunc:
1194 	printf(" [|BGP]");
1195 }
1196