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