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