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