xref: /openbsd-src/usr.sbin/tcpdump/print-bgp.c (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
1 /*	$OpenBSD: print-bgp.c,v 1.16 2014/01/12 11:26:48 deraadt Exp $	*/
2 
3 /*
4  * Copyright (C) 1999 WIDE Project.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the project nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include <sys/param.h>
33 #include <sys/time.h>
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 
37 #include <netinet/in.h>
38 
39 #include <errno.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <netdb.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[MAXHOSTNAMELEN + 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 			printf(" empty");
445 			break;
446 		}
447 		while (p < dat + len) {
448 			TCHECK(p[0]);
449 			if (asn_bytes == 0) {
450 				asn_bytes = (len-2)/p[1];
451 			}
452 			printf("%s",
453 			    tok2str(bgp_as_path_segment_open_values,
454 			    "?", p[0]));
455 
456 			for (i = 0; i < p[1] * asn_bytes; i += asn_bytes) {
457 				TCHECK2(p[2 + i], asn_bytes);
458 				printf("%s", i == 0 ? "" : " ");
459 				if (asn_bytes == 2 || EXTRACT_16BITS(&p[2 + i]))
460 					printf("%u%s",
461 					    EXTRACT_16BITS(&p[2 + i]),
462 					    asn_bytes == 4 ? "." : "");
463 				if (asn_bytes == 4)
464 					printf("%u",
465 					    EXTRACT_16BITS(&p[2 + i + 2]));
466 			}
467 			TCHECK(p[0]);
468 			printf("%s",
469 			    tok2str(bgp_as_path_segment_close_values,
470 			    "?", p[0]));
471 			TCHECK(p[1]);
472 			p += 2 + p[1] * asn_bytes;
473 		}
474 		break;
475 	case BGPTYPE_NEXT_HOP:
476 		if (len != 4)
477 			printf(" invalid len");
478 		else {
479 			TCHECK2(p[0], 4);
480 			printf(" %s", getname(p));
481 		}
482 		break;
483 	case BGPTYPE_MULTI_EXIT_DISC:
484 	case BGPTYPE_LOCAL_PREF:
485 		if (len != 4)
486 			printf(" invalid len");
487 		else {
488 			TCHECK2(p[0], 4);
489 			printf(" %u", EXTRACT_32BITS(p));
490 		}
491 		break;
492 	case BGPTYPE_ATOMIC_AGGREGATE:
493 		if (len != 0)
494 			printf(" invalid len");
495 		break;
496 	case BGPTYPE_AGGREGATOR4:
497 	case BGPTYPE_AGGREGATOR:
498 	/*
499 	 * like AS_PATH/AS4_PATH, AGGREGATOR can contain
500 	 * either 2-byte or 4-byte ASN, and AGGREGATOR4
501 	 * always contains 4-byte ASN.
502 	 */
503 		if (len != 6 && len != 8) {
504 			printf(" invalid len");
505 			break;
506 		}
507 		TCHECK2(p[0], len);
508 		printf(" AS #");
509 		if (len == 6 || EXTRACT_16BITS(p))
510 			printf("%u%s", EXTRACT_16BITS(p), len == 8 ? "." : "");
511 		if (len == 8)
512 			printf("%u", EXTRACT_16BITS(p+2));
513 		printf(", origin %s", getname(p+len-4));
514 		break;
515 	case BGPTYPE_COMMUNITIES:
516 		if (len % 4) {
517 			printf(" invalid len");
518 			break;
519 		}
520 		while (tlen>0) {
521 			u_int32_t comm;
522 			TCHECK2(p[0], 4);
523 			comm = EXTRACT_32BITS(p);
524 			switch (comm) {
525 			case BGP_COMMUNITY_NO_EXPORT:
526 				printf(" NO_EXPORT");
527 				break;
528 			case BGP_COMMUNITY_NO_ADVERT:
529 				printf(" NO_ADVERTISE");
530 				break;
531 			case BGP_COMMUNITY_NO_EXPORT_SUBCONFED:
532 				printf(" NO_EXPORT_SUBCONFED");
533 				break;
534 			case BGP_COMMUNITY_NO_PEER:
535 				printf(" NO_PEER");
536 				break;
537 			default:
538 				printf(" %d:%d",
539 					(comm >> 16) & 0xffff, comm & 0xffff);
540 				break;
541 			}
542 			tlen -= 4;
543 			p += 4;
544 		}
545 		break;
546 	case BGPTYPE_ORIGINATOR_ID:
547 		if (len != 4) {
548 			printf(" invalid len");
549 			break;
550                 }
551 		TCHECK2(p[0], 4);
552 		printf("%s",getname(p));
553 		break;
554 	case BGPTYPE_CLUSTER_LIST:
555 		if (len % 4) {
556 			printf(" invalid len");
557 			break;
558 		}
559 		while (tlen>0) {
560 			TCHECK2(p[0], 4);
561 			printf(" %s%s",
562 			    getname(p),
563 			    (tlen>4) ? ", " : "");
564 			tlen -=4;
565 			p +=4;
566 		}
567 		break;
568 	case BGPTYPE_MP_REACH_NLRI:
569 		TCHECK2(p[0], BGP_MP_NLRI_MINSIZE);
570 		af = EXTRACT_16BITS(p);
571 		safi = p[2];
572 		if (safi >= 128)
573 			printf(" %s vendor specific %u,", af_name(af), safi);
574 		else {
575 			printf(" %s %s,", af_name(af),
576 				bgp_attr_nlri_safi(safi));
577 		}
578 		p += 3;
579 
580 		if (af == AFNUM_INET)
581 			;
582 #ifdef INET6
583 		else if (af == AFNUM_INET6)
584 			;
585 #endif
586 		else
587 			break;
588 
589 		TCHECK(p[0]);
590 		tlen = p[0];
591 		if (tlen) {
592 			printf(" nexthop");
593 			i = 0;
594 			while (i < tlen) {
595 				switch (af) {
596 				case AFNUM_INET:
597 					TCHECK2(p[1+i], sizeof(struct in_addr));
598 					printf(" %s", getname(p + 1 + i));
599 					i += sizeof(struct in_addr);
600 					break;
601 #ifdef INET6
602 				case AFNUM_INET6:
603 					TCHECK2(p[1+i], sizeof(struct in6_addr));
604 					printf(" %s", getname6(p + 1 + i));
605 					i += sizeof(struct in6_addr);
606 					break;
607 #endif
608 				default:
609 					printf(" (unknown af)");
610 					i = tlen;	/*exit loop*/
611 					break;
612 				}
613 			}
614 			printf(",");
615 		}
616 		p += 1 + tlen;
617 
618 		TCHECK(p[0]);
619 		snpa = p[0];
620 		p++;
621 		if (snpa) {
622 			printf(" %u snpa", snpa);
623 			for (/*nothing*/; snpa > 0; snpa--) {
624 				TCHECK(p[0]);
625 				printf("(%d bytes)", p[0]);
626 				p += p[0] + 1;
627 			}
628 			printf(",");
629 		}
630 
631 		printf(" NLRI");
632 		while (len - (p - dat) > 0) {
633 			switch (af) {
634 			case AFNUM_INET:
635 				advance = decode_prefix4(p, buf, sizeof(buf));
636 				break;
637 #ifdef INET6
638 			case AFNUM_INET6:
639 				advance = decode_prefix6(p, buf, sizeof(buf));
640 				break;
641 #endif
642 			default:
643 				printf(" (unknown af)");
644 				advance = 0;
645 				p = dat + len;
646 				break;
647 			}
648 
649 			if (advance <= 0)
650 				break;
651 
652 			printf(" %s", buf);
653 			p += advance;
654 		}
655 
656 		break;
657 
658 	case BGPTYPE_MP_UNREACH_NLRI:
659 		TCHECK2(p[0], BGP_MP_NLRI_MINSIZE);
660 		af = EXTRACT_16BITS(p);
661 		safi = p[2];
662 		if (safi >= 128)
663 			printf(" %s vendor specific %u,", af_name(af), safi);
664 		else {
665 			printf(" %s %s,", af_name(af),
666 				bgp_attr_nlri_safi(safi));
667 		}
668 		p += 3;
669 
670 		printf(" Withdraw");
671 		while (len - (p - dat) > 0) {
672 			switch (af) {
673 			case AFNUM_INET:
674 				advance = decode_prefix4(p, buf, sizeof(buf));
675 				break;
676 #ifdef INET6
677 			case AFNUM_INET6:
678 				advance = decode_prefix6(p, buf, sizeof(buf));
679 				break;
680 #endif
681 			default:
682 				printf(" (unknown af)");
683 				advance = 0;
684 				p = dat + len;
685 				break;
686 			}
687 
688 			if (advance <= 0)
689 				break;
690 
691 			printf(" %s", buf);
692 			p += advance;
693 		}
694 		break;
695 	default:
696 		break;
697 	}
698 	return 1;
699 
700 trunc:
701 	return 0;
702 }
703 
704 static void
705 bgp_open_capa_print(const u_char *opt, int length)
706 {
707 	int i,cap_type,cap_len,tcap_len,cap_offset;
708 
709 	i = 0;
710 	while (i < length) {
711 		TCHECK2(opt[i], 2);
712 
713 		cap_type=opt[i];
714 		cap_len=opt[i+1];
715 		printf("%sCAP %s", i == 0 ? "(" : " ", 		/* ) */
716 		    bgp_capcode(cap_type));
717 
718 		/* can we print the capability? */
719 		TCHECK2(opt[i+2],cap_len);
720 		i += 2;
721 
722 		switch(cap_type) {
723 		case BGP_CAPCODE_MP:
724 			if (cap_len != 4) {
725 				printf(" BAD ENCODING");
726 				break;
727 			}
728 			printf(" [%s %s]",
729 			    af_name(EXTRACT_16BITS(opt+i)),
730 			    bgp_attr_nlri_safi(opt[i+3]));
731 			break;
732 		case BGP_CAPCODE_REFRESH:
733 			if (cap_len != 0) {
734 				printf(" BAD ENCODING");
735 				break;
736 			}
737 			break;
738 		case BGP_CAPCODE_RESTART:
739 			if (cap_len < 2 || (cap_len - 2) % 4) {
740 				printf(" BAD ENCODING");
741 				break;
742 			}
743 			printf(" [%s], Time %us",
744 			    ((opt[i])&0x80) ? "R" : "none",
745 			    EXTRACT_16BITS(opt+i)&0xfff);
746 			tcap_len=cap_len - 2;
747 			cap_offset=2;
748 			while(tcap_len>=4) {
749 				printf(" (%s %s)%s",
750 				    af_name(EXTRACT_16BITS(opt+i+cap_offset)),
751 				    bgp_attr_nlri_safi(opt[i+cap_offset+2]),
752 				    ((opt[i+cap_offset+3])&0x80) ?
753 					" forwarding state preserved" : "" );
754 				tcap_len-=4;
755 				cap_offset+=4;
756 			}
757 			break;
758 		case BGP_CAPCODE_AS4:
759 			if (cap_len != 4) {
760 				printf(" BAD ENCODING");
761 				break;
762 			}
763 			printf(" #");
764 			if (EXTRACT_16BITS(opt+i))
765 				printf("%u.",
766 				    EXTRACT_16BITS(opt+i));
767 			printf("%u",
768 			    EXTRACT_16BITS(opt+i+2));
769 			break;
770 		default:
771 			printf(" len %d", cap_len);
772 			break;
773 		}
774 		i += cap_len;
775 		if (i + cap_len < length)
776 			printf(",");
777 	}
778 	/* ( */
779 	printf(")");
780 	return;
781 trunc:
782 	printf("[|BGP]");
783 }
784 
785 static void
786 bgp_open_print(const u_char *dat, int length)
787 {
788 	struct bgp_open bgpo;
789 	struct bgp_opt bgpopt;
790 	const u_char *opt;
791 	int i;
792 
793 	TCHECK2(dat[0], BGP_OPEN_SIZE);
794 	memcpy(&bgpo, dat, BGP_OPEN_SIZE);
795 
796 	printf(": Version %d,", bgpo.bgpo_version);
797 	printf(" AS #%u,", ntohs(bgpo.bgpo_myas));
798 	printf(" Holdtime %u,", ntohs(bgpo.bgpo_holdtime));
799 	printf(" ID %s,", getname((u_char *)&bgpo.bgpo_id));
800 	printf(" Option length %u", bgpo.bgpo_optlen);
801 
802 	/* sanity checking */
803 	if ((length < bgpo.bgpo_optlen+BGP_OPEN_SIZE) || (!bgpo.bgpo_optlen))
804 		return;
805 
806 	/* ugly! */
807 	opt = &((const struct bgp_open *)dat)->bgpo_optlen;
808 	opt++;
809 
810 	i = 0;
811 	while (i < bgpo.bgpo_optlen) {
812 		TCHECK2(opt[i], BGP_OPT_SIZE);
813 		memcpy(&bgpopt, &opt[i], BGP_OPT_SIZE);
814 		if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) {
815 			printf(" [|opt %d %d]", bgpopt.bgpopt_len, bgpopt.bgpopt_type);
816 			break;
817 		}
818 
819 		if (i == 0)
820 			printf(" (");		/* ) */
821 		else
822 			printf(" ");
823 
824 		switch(bgpopt.bgpopt_type) {
825 		case BGP_OPT_CAP:
826 			bgp_open_capa_print(opt + i + BGP_OPT_SIZE,
827 			    bgpopt.bgpopt_len);
828 			break;
829 		default:
830 			printf(" (option %s, len=%u)",
831 			    bgp_opttype(bgpopt.bgpopt_type),
832 			    bgpopt.bgpopt_len);
833 			break;
834 		}
835 
836 		i += BGP_OPT_SIZE + bgpopt.bgpopt_len;
837 	}
838 	/* ( */
839 	printf(")");
840 	return;
841 trunc:
842 	printf("[|BGP]");
843 }
844 
845 static void
846 bgp_update_print(const u_char *dat, int length)
847 {
848 	struct bgp bgp;
849 	struct bgp_attr bgpa;
850 	const u_char *p;
851 	int len;
852 	int i;
853 	int newline;
854 
855 	TCHECK2(dat[0], BGP_SIZE);
856 	memcpy(&bgp, dat, BGP_SIZE);
857 	p = dat + BGP_SIZE;	/*XXX*/
858 	printf(":");
859 
860 	/* Unfeasible routes */
861 	len = EXTRACT_16BITS(p);
862 	if (len) {
863 		/*
864 		 * Without keeping state from the original NLRI message,
865 		 * it's not possible to tell if this a v4 or v6 route,
866 		 * so only try to decode it if we're not v6 enabled.
867 	         */
868 #ifdef INET6
869 		printf(" (Withdrawn routes: %d bytes)", len);
870 #else
871 		char buf[MAXHOSTNAMELEN + 100];
872 		int wpfx;
873 
874 		TCHECK2(p[2], len);
875  		i = 2;
876 
877 		printf(" (Withdrawn routes:");
878 
879 		while(i < 2 + len) {
880 			wpfx = decode_prefix4(&p[i], buf, sizeof(buf));
881 			if (wpfx == -1) {
882 				printf(" (illegal prefix length)");
883 				break;
884 			} else if (wpfx == -2)
885 				goto trunc;
886 			i += wpfx;
887 			printf(" %s", buf);
888 		}
889 		printf(")");
890 #endif
891 	}
892 	p += 2 + len;
893 
894 	TCHECK2(p[0], 2);
895 	len = EXTRACT_16BITS(p);
896 
897 	if (len == 0 && length == BGP_UPDATE_MINSIZE) {
898 		printf(" End-of-Rib Marker (empty NLRI)");
899 		return;
900 	}
901 
902 	if (len) {
903 		/* do something more useful!*/
904 		i = 2;
905 		printf(" (Path attributes:");	/* ) */
906 		newline = 0;
907 		while (i < 2 + len) {
908 			int alen, aoff;
909 
910 			TCHECK2(p[i], sizeof(bgpa));
911 			memcpy(&bgpa, &p[i], sizeof(bgpa));
912 			alen = bgp_attr_len(&bgpa);
913 			aoff = bgp_attr_off(&bgpa);
914 
915 			if (vflag && newline)
916 				printf("\n\t\t");
917 			else
918 				printf(" ");
919 			printf("(");		/* ) */
920 			printf("%s", bgp_attr_type(bgpa.bgpa_type));
921 			if (bgpa.bgpa_flags) {
922 				printf("[%s%s%s%s",
923 					bgpa.bgpa_flags & 0x80 ? "O" : "",
924 					bgpa.bgpa_flags & 0x40 ? "T" : "",
925 					bgpa.bgpa_flags & 0x20 ? "P" : "",
926 					bgpa.bgpa_flags & 0x10 ? "E" : "");
927 				if (bgpa.bgpa_flags & 0xf)
928 					printf("+%x", bgpa.bgpa_flags & 0xf);
929 				printf("]");
930 			}
931 
932 			if (!bgp_attr_print(&bgpa, &p[i + aoff], alen))
933 				goto trunc;
934 			newline = 1;
935 
936 			/* ( */
937 			printf(")");
938 
939 			i += aoff + alen;
940 		}
941 
942 		/* ( */
943 		printf(")");
944 	}
945 	p += 2 + len;
946 
947 	if (len && dat + length > p)
948 		printf("\n\t\t");
949 	if (dat + length > p) {
950 		printf("(NLRI:");	/* ) */
951 		while (dat + length > p) {
952 			char buf[MAXHOSTNAMELEN + 100];
953 			i = decode_prefix4(p, buf, sizeof(buf));
954 			if (i == -1) {
955 				printf(" (illegal prefix length)");
956 				break;
957 			} else if (i == -2)
958 				goto trunc;
959 			printf(" %s", buf);
960 			p += i;
961 		}
962 
963 		/* ( */
964 		printf(")");
965 	}
966 	return;
967 trunc:
968 	printf("[|BGP]");
969 }
970 
971 static void
972 bgp_notification_print(const u_char *dat, int length)
973 {
974 	struct bgp_notification bgpn;
975 	u_int16_t af;
976 	u_int8_t safi;
977 	const u_char *p;
978 
979 	TCHECK2(dat[0], BGP_NOTIFICATION_SIZE);
980 	memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE);
981 
982 	/* sanity checking */
983 	if (length<BGP_NOTIFICATION_SIZE)
984 		return;
985 
986 	printf(": error %s,", bgp_notify_major(bgpn.bgpn_major));
987 	printf(" subcode %s",
988 		bgp_notify_minor(bgpn.bgpn_major, bgpn.bgpn_minor));
989 
990 	if (bgpn.bgpn_major == BGP_NOTIFY_MAJOR_CEASE) {
991 		/*
992 		 * RFC 4486: optional maxprefix subtype of 7 bytes
993 		 * may contain AFI, SAFI and MAXPREFIXES
994 		 */
995 		if(bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_MAXPRFX &&
996 		    length >= BGP_NOTIFICATION_SIZE + 7) {
997 
998 			p = dat + BGP_NOTIFICATION_SIZE;
999 			TCHECK2(*p, 7);
1000 
1001 			af = EXTRACT_16BITS(p);
1002 			safi = p[2];
1003 			printf(" %s %s,", af_name(af),
1004 			    bgp_attr_nlri_safi(safi));
1005 
1006 			printf(" Max Prefixes: %u", EXTRACT_32BITS(p+3));
1007 		}
1008 	}
1009 
1010 	return;
1011 trunc:
1012 	printf("[|BGP]");
1013 }
1014 
1015 static void
1016 bgp_route_refresh_print(const u_char *dat, int length)
1017 {
1018 	const struct bgp_route_refresh *bgp_route_refresh_header;
1019 
1020 	TCHECK2(dat[0], BGP_ROUTE_REFRESH_SIZE);
1021 
1022 	/* sanity checking */
1023 	if (length<BGP_ROUTE_REFRESH_SIZE)
1024 		return;
1025 
1026 	bgp_route_refresh_header = (const struct bgp_route_refresh *)dat;
1027 
1028 	printf(" (%s %s)",
1029 	    af_name(EXTRACT_16BITS(&bgp_route_refresh_header->afi)),
1030 	    bgp_attr_nlri_safi(bgp_route_refresh_header->safi));
1031 
1032 	return;
1033 trunc:
1034 	printf("[|BGP]");
1035 }
1036 
1037 static int
1038 bgp_header_print(const u_char *dat, int length)
1039 {
1040 	struct bgp bgp;
1041 
1042 	TCHECK2(dat[0], BGP_SIZE);
1043 	memcpy(&bgp, dat, BGP_SIZE);
1044 	printf("(%s", bgp_type(bgp.bgp_type));		/* ) */
1045 
1046 	switch (bgp.bgp_type) {
1047 	case BGP_OPEN:
1048 		bgp_open_print(dat, length);
1049 		break;
1050 	case BGP_UPDATE:
1051 		bgp_update_print(dat, length);
1052 		break;
1053 	case BGP_NOTIFICATION:
1054 		bgp_notification_print(dat, length);
1055 		break;
1056 	case BGP_KEEPALIVE:
1057 		break;
1058 	case BGP_ROUTE_REFRESH:
1059 		bgp_route_refresh_print(dat, length);
1060 	default:
1061 		TCHECK2(*dat, length);
1062 		break;
1063 	}
1064 
1065 	/* ( */
1066 	printf(")");
1067 	return 1;
1068 trunc:
1069 	printf("[|BGP]");
1070 	return 0;
1071 }
1072 
1073 void
1074 bgp_print(const u_char *dat, int length)
1075 {
1076 	const u_char *p;
1077 	const u_char *ep;
1078 	const u_char *start;
1079 	const u_char marker[] = {
1080 		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1081 		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1082 	};
1083 	struct bgp bgp;
1084 	u_int16_t hlen;
1085 	int newline;
1086 
1087 	ep = dat + length;
1088 	if (snapend < dat + length)
1089 		ep = snapend;
1090 
1091 	printf(": BGP");
1092 
1093 	p = dat;
1094 	newline = 0;
1095 	start = p;
1096 	while (p < ep) {
1097 		if (!TTEST2(p[0], 1))
1098 			break;
1099 		if (p[0] != 0xff) {
1100 			p++;
1101 			continue;
1102 		}
1103 
1104 		if (!TTEST2(p[0], sizeof(marker)))
1105 			break;
1106 		if (memcmp(p, marker, sizeof(marker)) != 0) {
1107 			p++;
1108 			continue;
1109 		}
1110 
1111 		/* found BGP header */
1112 		TCHECK2(p[0], BGP_SIZE);	/*XXX*/
1113 		memcpy(&bgp, p, BGP_SIZE);
1114 
1115 		if (start != p)
1116 			printf(" [|BGP]");
1117 
1118 		hlen = ntohs(bgp.bgp_len);
1119 		if (vflag && newline)
1120 			printf("\n\t");
1121 		else
1122 			printf(" ");
1123 		if (hlen < BGP_SIZE) {
1124 			printf("\n[|BGP Bogus header length %u < %u]",
1125 			    hlen, BGP_SIZE);
1126 			break;
1127 		}
1128 		if (TTEST2(p[0], hlen)) {
1129 			if (!bgp_header_print(p, hlen))
1130 				return;
1131 			newline = 1;
1132 			p += hlen;
1133 			start = p;
1134 		} else {
1135 			printf("[|BGP %s]", bgp_type(bgp.bgp_type));
1136 			break;
1137 		}
1138 	}
1139 
1140 	return;
1141 
1142 trunc:
1143 	printf(" [|BGP]");
1144 }
1145