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