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