xref: /freebsd/contrib/tcpdump/print-bgp.c (revision 2546665afcaf0d53dc2c7058fee96354b3680f5a)
1 /*
2  * Copyright (C) 1999 WIDE Project.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the project nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * Extensively modified by Hannes Gredler (hannes@juniper.net) for more
30  * complete BGP support.
31  */
32 
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36 
37 #ifndef lint
38 static const char rcsid[] _U_ =
39      "@(#) $Header: /tcpdump/master/tcpdump/print-bgp.c,v 1.72.2.4 2004/03/24 00:04:04 guy Exp $";
40 #endif
41 
42 #include <tcpdump-stdinc.h>
43 
44 #include <stdio.h>
45 #include <string.h>
46 
47 #include "interface.h"
48 #include "addrtoname.h"
49 #include "extract.h"
50 
51 struct bgp {
52 	u_int8_t bgp_marker[16];
53 	u_int16_t bgp_len;
54 	u_int8_t bgp_type;
55 };
56 #define BGP_SIZE		19	/* unaligned */
57 
58 #define BGP_OPEN		1
59 #define BGP_UPDATE		2
60 #define BGP_NOTIFICATION	3
61 #define BGP_KEEPALIVE		4
62 #define BGP_ROUTE_REFRESH       5
63 
64 static struct tok bgp_msg_values[] = {
65     { BGP_OPEN,                 "Open"},
66     { BGP_UPDATE,               "Update"},
67     { BGP_NOTIFICATION,         "Notification"},
68     { BGP_KEEPALIVE,            "Keepalive"},
69     { BGP_ROUTE_REFRESH,        "Route Refresh"},
70     { 0, NULL}
71 };
72 
73 struct bgp_open {
74 	u_int8_t bgpo_marker[16];
75 	u_int16_t bgpo_len;
76 	u_int8_t bgpo_type;
77 	u_int8_t bgpo_version;
78 	u_int16_t bgpo_myas;
79 	u_int16_t bgpo_holdtime;
80 	u_int32_t bgpo_id;
81 	u_int8_t bgpo_optlen;
82 	/* options should follow */
83 };
84 #define BGP_OPEN_SIZE		29	/* unaligned */
85 
86 struct bgp_opt {
87 	u_int8_t bgpopt_type;
88 	u_int8_t bgpopt_len;
89 	/* variable length */
90 };
91 #define BGP_OPT_SIZE		2	/* some compilers may pad to 4 bytes */
92 
93 struct bgp_notification {
94 	u_int8_t bgpn_marker[16];
95 	u_int16_t bgpn_len;
96 	u_int8_t bgpn_type;
97 	u_int8_t bgpn_major;
98 	u_int8_t bgpn_minor;
99 };
100 #define BGP_NOTIFICATION_SIZE		21	/* unaligned */
101 
102 struct bgp_route_refresh {
103     u_int8_t  bgp_marker[16];
104     u_int16_t len;
105     u_int8_t  type;
106     u_int8_t  afi[2]; /* the compiler messes this structure up               */
107     u_int8_t  res;    /* when doing misaligned sequences of int8 and int16   */
108     u_int8_t  safi;   /* afi should be int16 - so we have to access it using */
109 };                    /* EXTRACT_16BITS(&bgp_route_refresh->afi) (sigh)      */
110 #define BGP_ROUTE_REFRESH_SIZE          23
111 
112 struct bgp_attr {
113 	u_int8_t bgpa_flags;
114 	u_int8_t bgpa_type;
115 	union {
116 		u_int8_t len;
117 		u_int16_t elen;
118 	} bgpa_len;
119 #define bgp_attr_len(p) \
120 	(((p)->bgpa_flags & 0x10) ? \
121 		EXTRACT_16BITS(&(p)->bgpa_len.elen) : (p)->bgpa_len.len)
122 #define bgp_attr_off(p) \
123 	(((p)->bgpa_flags & 0x10) ? 4 : 3)
124 };
125 
126 #define BGPTYPE_ORIGIN			1
127 #define BGPTYPE_AS_PATH			2
128 #define BGPTYPE_NEXT_HOP		3
129 #define BGPTYPE_MULTI_EXIT_DISC		4
130 #define BGPTYPE_LOCAL_PREF		5
131 #define BGPTYPE_ATOMIC_AGGREGATE	6
132 #define BGPTYPE_AGGREGATOR		7
133 #define	BGPTYPE_COMMUNITIES		8	/* RFC1997 */
134 #define	BGPTYPE_ORIGINATOR_ID		9	/* RFC1998 */
135 #define	BGPTYPE_CLUSTER_LIST		10	/* RFC1998 */
136 #define	BGPTYPE_DPA			11	/* draft-ietf-idr-bgp-dpa */
137 #define	BGPTYPE_ADVERTISERS		12	/* RFC1863 */
138 #define	BGPTYPE_RCID_PATH		13	/* RFC1863 */
139 #define BGPTYPE_MP_REACH_NLRI		14	/* RFC2283 */
140 #define BGPTYPE_MP_UNREACH_NLRI		15	/* RFC2283 */
141 #define BGPTYPE_EXTD_COMMUNITIES        16      /* draft-ietf-idr-bgp-ext-communities */
142 
143 static struct tok bgp_attr_values[] = {
144     { BGPTYPE_ORIGIN,           "Origin"},
145     { BGPTYPE_AS_PATH,          "AS Path"},
146     { BGPTYPE_NEXT_HOP,         "Next Hop"},
147     { BGPTYPE_MULTI_EXIT_DISC,  "Multi Exit Discriminator"},
148     { BGPTYPE_LOCAL_PREF,       "Local Preference"},
149     { BGPTYPE_ATOMIC_AGGREGATE, "Atomic Aggregate"},
150     { BGPTYPE_AGGREGATOR,       "Aggregator"},
151     { BGPTYPE_COMMUNITIES,      "Community"},
152     { BGPTYPE_ORIGINATOR_ID,    "Originator ID"},
153     { BGPTYPE_CLUSTER_LIST,     "Cluster List"},
154     { BGPTYPE_DPA,              "DPA"},
155     { BGPTYPE_ADVERTISERS,      "Advertisers"},
156     { BGPTYPE_RCID_PATH,        "RCID Path / Cluster ID"},
157     { BGPTYPE_MP_REACH_NLRI,    "Multi-Protocol Reach NLRI"},
158     { BGPTYPE_MP_UNREACH_NLRI,  "Multi-Protocol Unreach NLRI"},
159     { BGPTYPE_EXTD_COMMUNITIES, "Extended Community"},
160     { 255,                      "Reserved for development"},
161     { 0, NULL}
162 };
163 
164 #define BGP_AS_SET             1
165 #define BGP_AS_SEQUENCE        2
166 #define BGP_CONFED_AS_SEQUENCE 3 /* draft-ietf-idr-rfc3065bis-01 */
167 #define BGP_CONFED_AS_SET      4 /* draft-ietf-idr-rfc3065bis-01  */
168 
169 static struct tok bgp_as_path_segment_open_values[] = {
170     { BGP_AS_SEQUENCE,         ""},
171     { BGP_AS_SET,              "{ "},
172     { BGP_CONFED_AS_SEQUENCE,  "( "},
173     { BGP_CONFED_AS_SET,       "({ "},
174     { 0, NULL}
175 };
176 
177 static struct tok bgp_as_path_segment_close_values[] = {
178     { BGP_AS_SEQUENCE,         ""},
179     { BGP_AS_SET,              "}"},
180     { BGP_CONFED_AS_SEQUENCE,  ")"},
181     { BGP_CONFED_AS_SET,       "})"},
182     { 0, NULL}
183 };
184 
185 #define BGP_OPT_AUTH                    1
186 #define BGP_OPT_CAP                     2
187 
188 
189 static struct tok bgp_opt_values[] = {
190     { BGP_OPT_AUTH,             "Authentication Information"},
191     { BGP_OPT_CAP,              "Capabilities Advertisement"},
192     { 0, NULL}
193 };
194 
195 #define BGP_CAPCODE_MP                  1
196 #define BGP_CAPCODE_RR                  2
197 #define BGP_CAPCODE_RESTART            64 /* draft-ietf-idr-restart-05  */
198 #define BGP_CAPCODE_RR_CISCO          128
199 
200 static struct tok bgp_capcode_values[] = {
201     { BGP_CAPCODE_MP,           "Multiprotocol Extensions"},
202     { BGP_CAPCODE_RR,           "Route Refresh"},
203     { BGP_CAPCODE_RESTART,      "Graceful Restart"},
204     { BGP_CAPCODE_RR_CISCO,     "Route Refresh (Cisco)"},
205     { 0, NULL}
206 };
207 
208 #define BGP_NOTIFY_MAJOR_MSG            1
209 #define BGP_NOTIFY_MAJOR_OPEN           2
210 #define BGP_NOTIFY_MAJOR_UPDATE         3
211 #define BGP_NOTIFY_MAJOR_HOLDTIME       4
212 #define BGP_NOTIFY_MAJOR_FSM            5
213 #define BGP_NOTIFY_MAJOR_CEASE          6
214 #define BGP_NOTIFY_MAJOR_CAP            7
215 
216 static struct tok bgp_notify_major_values[] = {
217     { BGP_NOTIFY_MAJOR_MSG,     "Message Header Error"},
218     { BGP_NOTIFY_MAJOR_OPEN,    "OPEN Message Error"},
219     { BGP_NOTIFY_MAJOR_UPDATE,  "UPDATE Message Error"},
220     { BGP_NOTIFY_MAJOR_HOLDTIME,"Hold Timer Expired"},
221     { BGP_NOTIFY_MAJOR_FSM,     "Finite State Machine Error"},
222     { BGP_NOTIFY_MAJOR_CEASE,   "Cease"},
223     { BGP_NOTIFY_MAJOR_CAP,     "Capability Message Error"},
224     { 0, NULL}
225 };
226 
227 /* draft-ietf-idr-cease-subcode-02 */
228 #define BGP_NOTIFY_MINOR_CEASE_MAXPRFX  1
229 static struct tok bgp_notify_minor_cease_values[] = {
230     { BGP_NOTIFY_MINOR_CEASE_MAXPRFX, "Maximum Number of Prefixes Reached"},
231     { 2,                        "Administratively Shutdown"},
232     { 3,                        "Peer Unconfigured"},
233     { 4,                        "Administratively Reset"},
234     { 5,                        "Connection Rejected"},
235     { 6,                        "Other Configuration Change"},
236     { 7,                        "Connection Collision Resolution"},
237     { 0, NULL}
238 };
239 
240 static struct tok bgp_notify_minor_msg_values[] = {
241     { 1,                        "Connection Not Synchronized"},
242     { 2,                        "Bad Message Length"},
243     { 3,                        "Bad Message Type"},
244     { 0, NULL}
245 };
246 
247 static struct tok bgp_notify_minor_open_values[] = {
248     { 1,                        "Unsupported Version Number"},
249     { 2,                        "Bad Peer AS"},
250     { 3,                        "Bad BGP Identifier"},
251     { 4,                        "Unsupported Optional Parameter"},
252     { 5,                        "Authentication Failure"},
253     { 6,                        "Unacceptable Hold Time"},
254     { 0, NULL}
255 };
256 
257 static struct tok bgp_notify_minor_update_values[] = {
258     { 1,                        "Malformed Attribute List"},
259     { 2,                        "Unrecognized Well-known Attribute"},
260     { 3,                        "Missing Well-known Attribute"},
261     { 4,                        "Attribute Flags Error"},
262     { 5,                        "Attribute Length Error"},
263     { 6,                        "Invalid ORIGIN Attribute"},
264     { 7,                        "AS Routing Loop"},
265     { 8,                        "Invalid NEXT_HOP Attribute"},
266     { 9,                        "Optional Attribute Error"},
267     { 10,                       "Invalid Network Field"},
268     { 11,                       "Malformed AS_PATH"},
269     { 0, NULL}
270 };
271 
272 static struct tok bgp_notify_minor_cap_values[] = {
273     { 1,                        "Invalid Action Value" },
274     { 2,                        "Invalid Capability Length" },
275     { 3,                        "Malformed Capability Value" },
276     { 4,                        "Unsupported Capability Code" },
277     { 0, NULL }
278 };
279 
280 static struct tok bgp_origin_values[] = {
281     { 0,                        "IGP"},
282     { 1,                        "EGP"},
283     { 2,                        "Incomplete"},
284     { 0, NULL}
285 };
286 
287 /* Subsequent address family identifier, RFC2283 section 7 */
288 #define SAFNUM_RES                      0
289 #define SAFNUM_UNICAST                  1
290 #define SAFNUM_MULTICAST                2
291 #define SAFNUM_UNIMULTICAST             3
292 /* labeled BGP RFC3107 */
293 #define SAFNUM_LABUNICAST               4
294 /* Section 4.3.4 of draft-rosen-rfc2547bis-03.txt  */
295 #define SAFNUM_VPNUNICAST               128
296 #define SAFNUM_VPNMULTICAST             129
297 #define SAFNUM_VPNUNIMULTICAST          130
298 /* draft-marques-ppvpn-rt-constrain-01.txt */
299 #define SAFNUM_RT_ROUTING_INFO          132
300 
301 #define BGP_VPN_RD_LEN                  8
302 
303 static struct tok bgp_safi_values[] = {
304     { SAFNUM_RES,               "Reserved"},
305     { SAFNUM_UNICAST,           "Unicast"},
306     { SAFNUM_MULTICAST,         "Multicast"},
307     { SAFNUM_UNIMULTICAST,      "Unicast+Multicast"},
308     { SAFNUM_LABUNICAST,        "labeled Unicast"},
309     { SAFNUM_VPNUNICAST,        "labeled VPN Unicast"},
310     { SAFNUM_VPNMULTICAST,      "labeled VPN Multicast"},
311     { SAFNUM_VPNUNIMULTICAST,   "labeled VPN Unicast+Multicast"},
312     { SAFNUM_RT_ROUTING_INFO,   "Route Target Routing Information"},
313     { 0, NULL }
314 };
315 
316 /* well-known community */
317 #define BGP_COMMUNITY_NO_EXPORT			0xffffff01
318 #define BGP_COMMUNITY_NO_ADVERT			0xffffff02
319 #define BGP_COMMUNITY_NO_EXPORT_SUBCONFED	0xffffff03
320 
321 /* RFC1700 address family numbers */
322 #define AFNUM_INET	1
323 #define AFNUM_INET6	2
324 #define AFNUM_NSAP	3
325 #define AFNUM_HDLC	4
326 #define AFNUM_BBN1822	5
327 #define AFNUM_802	6
328 #define AFNUM_E163	7
329 #define AFNUM_E164	8
330 #define AFNUM_F69	9
331 #define AFNUM_X121	10
332 #define AFNUM_IPX	11
333 #define AFNUM_ATALK	12
334 #define AFNUM_DECNET	13
335 #define AFNUM_BANYAN	14
336 #define AFNUM_E164NSAP	15
337 /* draft-kompella-ppvpn-l2vpn */
338 #define AFNUM_L2VPN     196 /* still to be approved by IANA */
339 
340 static struct tok bgp_afi_values[] = {
341     { 0,                      "Reserved"},
342     { AFNUM_INET,             "IPv4"},
343     { AFNUM_INET6,            "IPv6"},
344     { AFNUM_NSAP,             "NSAP"},
345     { AFNUM_HDLC,             "HDLC"},
346     { AFNUM_BBN1822,          "BBN 1822"},
347     { AFNUM_802,              "802"},
348     { AFNUM_E163,             "E.163"},
349     { AFNUM_E164,             "E.164"},
350     { AFNUM_F69,              "F.69"},
351     { AFNUM_X121,             "X.121"},
352     { AFNUM_IPX,              "Novell IPX"},
353     { AFNUM_ATALK,            "Appletalk"},
354     { AFNUM_DECNET,           "Decnet IV"},
355     { AFNUM_BANYAN,           "Banyan Vines"},
356     { AFNUM_E164NSAP,         "E.164 with NSAP subaddress"},
357     { AFNUM_L2VPN,            "Layer-2 VPN"},
358     { 0, NULL},
359 };
360 
361 /* Extended community type - draft-ietf-idr-bgp-ext-communities-05 */
362 #define BGP_EXT_COM_RT_0        0x0002  /* Route Target,Format AS(2bytes):AN(4bytes) */
363 #define BGP_EXT_COM_RT_1        0x0102  /* Route Target,Format IP address:AN(2bytes) */
364 #define BGP_EXT_COM_RT_2        0x0202  /* Route Target,Format AN(4bytes):local(2bytes) */
365 #define BGP_EXT_COM_RO_0        0x0003  /* Route Origin,Format AS(2bytes):AN(4bytes) */
366 #define BGP_EXT_COM_RO_1        0x0103  /* Route Origin,Format IP address:AN(2bytes) */
367 #define BGP_EXT_COM_RO_2        0x0203  /* Route Origin,Format AN(4bytes):local(2bytes) */
368 #define BGP_EXT_COM_LINKBAND    0x4004  /* Link Bandwidth,Format AS(2B):Bandwidth(4B) */
369                                         /* rfc2547 bgp-mpls-vpns */
370 
371 #define BGP_EXT_COM_VPN_ORIGIN  0x0005  /* OSPF Domain ID / VPN of Origin  - draft-rosen-vpns-ospf-bgp-mpls */
372 #define BGP_EXT_COM_VPN_ORIGIN2 0x0105  /* duplicate - keep for backwards compatability */
373 #define BGP_EXT_COM_VPN_ORIGIN3 0x0205  /* duplicate - keep for backwards compatability */
374 #define BGP_EXT_COM_VPN_ORIGIN4 0x8005  /* duplicate - keep for backwards compatability */
375 
376 #define BGP_EXT_COM_OSPF_RTYPE  0x0306  /* OSPF Route Type,Format Area(4B):RouteType(1B):Options(1B) */
377 #define BGP_EXT_COM_OSPF_RTYPE2 0x8000  /* duplicate - keep for backwards compatability */
378 
379 #define BGP_EXT_COM_OSPF_RID    0x0107  /* OSPF Router ID,Format RouterID(4B):Unused(2B) */
380 #define BGP_EXT_COM_OSPF_RID2   0x8001  /* duplicate - keep for backwards compatability */
381 
382 #define BGP_EXT_COM_L2INFO      0x800a  /* draft-kompella-ppvpn-l2vpn */
383 
384 static struct tok bgp_extd_comm_flag_values[] = {
385     { 0x8000,                  "vendor-specific"},
386     { 0x4000,                  "non-transitive"},
387     { 0, NULL},
388 };
389 
390 static struct tok bgp_extd_comm_subtype_values[] = {
391     { BGP_EXT_COM_RT_0,        "target"},
392     { BGP_EXT_COM_RT_1,        "target"},
393     { BGP_EXT_COM_RT_2,        "target"},
394     { BGP_EXT_COM_RO_0,        "origin"},
395     { BGP_EXT_COM_RO_1,        "origin"},
396     { BGP_EXT_COM_RO_2,        "origin"},
397     { BGP_EXT_COM_LINKBAND,    "link-BW"},
398     { BGP_EXT_COM_VPN_ORIGIN,  "ospf-domain"},
399     { BGP_EXT_COM_VPN_ORIGIN2, "ospf-domain"},
400     { BGP_EXT_COM_VPN_ORIGIN3, "ospf-domain"},
401     { BGP_EXT_COM_VPN_ORIGIN4, "ospf-domain"},
402     { BGP_EXT_COM_OSPF_RTYPE,  "ospf-route-type"},
403     { BGP_EXT_COM_OSPF_RTYPE2, "ospf-route-type"},
404     { BGP_EXT_COM_OSPF_RID,    "ospf-router-id"},
405     { BGP_EXT_COM_OSPF_RID2,   "ospf-router-id"},
406     { BGP_EXT_COM_L2INFO,      "layer2-info"},
407     { 0, NULL},
408 };
409 
410 /* OSPF codes for  BGP_EXT_COM_OSPF_RTYPE draft-rosen-vpns-ospf-bgp-mpls  */
411 #define BGP_OSPF_RTYPE_RTR      1 /* OSPF Router LSA */
412 #define BGP_OSPF_RTYPE_NET      2 /* OSPF Network LSA */
413 #define BGP_OSPF_RTYPE_SUM      3 /* OSPF Summary LSA */
414 #define BGP_OSPF_RTYPE_EXT      5 /* OSPF External LSA, note that ASBR doesn't apply to MPLS-VPN */
415 #define BGP_OSPF_RTYPE_NSSA     7 /* OSPF NSSA External*/
416 #define BGP_OSPF_RTYPE_SHAM     129 /* OSPF-MPLS-VPN Sham link */
417 #define BGP_OSPF_RTYPE_METRIC_TYPE 0x1 /* LSB of RTYPE Options Field */
418 
419 static struct tok bgp_extd_comm_ospf_rtype_values[] = {
420   { BGP_OSPF_RTYPE_RTR, "Router" },
421   { BGP_OSPF_RTYPE_NET, "Network" },
422   { BGP_OSPF_RTYPE_SUM, "Summary" },
423   { BGP_OSPF_RTYPE_EXT, "External" },
424   { BGP_OSPF_RTYPE_NSSA,"NSSA External" },
425   { BGP_OSPF_RTYPE_SHAM,"MPLS-VPN Sham" },
426   { 0, NULL },
427 };
428 
429 static struct tok bgp_l2vpn_encaps_values[] = {
430     { 0,                      "Reserved"},
431     { 1,                      "Frame Relay"},
432     { 2,                      "ATM AAL5 VCC transport"},
433     { 3,                      "ATM transparent cell transport"},
434     { 4,                      "Ethernet VLAN"},
435     { 5,                      "Ethernet"},
436     { 6,                      "Cisco-HDLC"},
437     { 7,                      "PPP"},
438     { 8,                      "CEM"},
439     { 9,                      "ATM VCC cell transport"},
440     { 10,                     "ATM VPC cell transport"},
441     { 11,                     "MPLS"},
442     { 12,                     "VPLS"},
443     { 64,                     "IP-interworking"},
444     { 0, NULL},
445 };
446 
447 static int
448 decode_prefix4(const u_char *pptr, char *buf, u_int buflen)
449 {
450 	struct in_addr addr;
451 	u_int plen;
452 
453 	TCHECK(pptr[0]);
454 	plen = pptr[0];
455 	if (32 < plen)
456 		return -1;
457 
458 	memset(&addr, 0, sizeof(addr));
459 	TCHECK2(pptr[1], (plen + 7) / 8);
460 	memcpy(&addr, &pptr[1], (plen + 7) / 8);
461 	if (plen % 8) {
462 		((u_char *)&addr)[(plen + 7) / 8 - 1] &=
463 			((0xff00 >> (plen % 8)) & 0xff);
464 	}
465 	snprintf(buf, buflen, "%s/%d", getname((u_char *)&addr), plen);
466 	return 1 + (plen + 7) / 8;
467 
468 trunc:
469 	return -2;
470 }
471 
472 static int
473 decode_labeled_prefix4(const u_char *pptr, char *buf, u_int buflen)
474 {
475 	struct in_addr addr;
476 	u_int plen;
477 
478 	TCHECK(pptr[0]);
479 	plen = pptr[0];   /* get prefix length */
480 
481         /* this is one of the weirdnesses of rfc3107
482            the label length (actually the label + COS bits)
483            is added to the prefix length;
484            we also do only read out just one label -
485            there is no real application for advertisement of
486            stacked labels in a a single BGP message
487         */
488 
489         plen-=24; /* adjust prefixlen - labellength */
490 
491 	if (32 < plen)
492 		return -1;
493 
494 	memset(&addr, 0, sizeof(addr));
495 	TCHECK2(pptr[4], (plen + 7) / 8);
496 	memcpy(&addr, &pptr[4], (plen + 7) / 8);
497 	if (plen % 8) {
498 		((u_char *)&addr)[(plen + 7) / 8 - 1] &=
499 			((0xff00 >> (plen % 8)) & 0xff);
500 	}
501         /* the label may get offsetted by 4 bits so lets shift it right */
502 	snprintf(buf, buflen, "%s/%d, label:%u %s",
503                  getname((u_char *)&addr),
504                  plen,
505                  EXTRACT_24BITS(pptr+1)>>4,
506                  ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
507 
508 	return 4 + (plen + 7) / 8;
509 
510 trunc:
511 	return -2;
512 }
513 
514 /* RDs and RTs share the same semantics
515  * we use bgp_vpn_rd_print for
516  * printing route targets inside a NLRI */
517 static char *
518 bgp_vpn_rd_print (const u_char *pptr) {
519 
520    /* allocate space for the following string
521     * xxx.xxx.xxx.xxx:xxxxx
522     * 21 bytes plus one termination byte */
523     static char rd[22];
524     char *pos = rd;
525 
526     /* ok lets load the RD format */
527     switch (EXTRACT_16BITS(pptr)) {
528 
529         /* AS:IP-address fmt*/
530     case 0:
531         snprintf(pos, sizeof(rd) - (pos - rd), "%u:%u.%u.%u.%u",
532             EXTRACT_16BITS(pptr+2), *(pptr+4), *(pptr+5), *(pptr+6), *(pptr+7));
533         break;
534         /* IP-address:AS fmt*/
535 
536     case 1:
537         snprintf(pos, sizeof(rd) - (pos - rd), "%u.%u.%u.%u:%u",
538             *(pptr+2), *(pptr+3), *(pptr+4), *(pptr+5), EXTRACT_16BITS(pptr+6));
539         break;
540 
541         /* 4-byte-AS:number fmt*/
542     case 2:
543         snprintf(pos, sizeof(rd) - (pos - rd), "%u:%u",
544             EXTRACT_32BITS(pptr+2), EXTRACT_16BITS(pptr+6));
545         break;
546     default:
547         snprintf(pos, sizeof(rd) - (pos - rd), "unknown RD format");
548         break;
549     }
550     pos += strlen(pos);
551     *(pos) = '\0';
552     return (rd);
553 }
554 
555 static int
556 decode_rt_routing_info(const u_char *pptr, char *buf, u_int buflen)
557 {
558 	u_int8_t route_target[8];
559 	u_int plen;
560 
561 	TCHECK(pptr[0]);
562 	plen = pptr[0];   /* get prefix length */
563 
564         plen-=32; /* adjust prefix length */
565 
566 	if (0 < plen)
567 		return -1;
568 
569 	memset(&route_target, 0, sizeof(route_target));
570 	TCHECK2(pptr[1], (plen + 7) / 8);
571 	memcpy(&route_target, &pptr[1], (plen + 7) / 8);
572 	if (plen % 8) {
573 		((u_char *)&route_target)[(plen + 7) / 8 - 1] &=
574 			((0xff00 >> (plen % 8)) & 0xff);
575 	}
576 	snprintf(buf, buflen, "origin AS: %u, route target %s",
577                  EXTRACT_32BITS(pptr+1),
578                  bgp_vpn_rd_print((u_char *)&route_target));
579 
580 	return 5 + (plen + 7) / 8;
581 
582 trunc:
583 	return -2;
584 }
585 
586 static int
587 decode_labeled_vpn_prefix4(const u_char *pptr, char *buf, u_int buflen)
588 {
589 	struct in_addr addr;
590 	u_int plen;
591 
592 	TCHECK(pptr[0]);
593 	plen = pptr[0];   /* get prefix length */
594 
595         plen-=(24+64); /* adjust prefixlen - labellength - RD len*/
596 
597 	if (32 < plen)
598 		return -1;
599 
600 	memset(&addr, 0, sizeof(addr));
601 	TCHECK2(pptr[12], (plen + 7) / 8);
602 	memcpy(&addr, &pptr[12], (plen + 7) / 8);
603 	if (plen % 8) {
604 		((u_char *)&addr)[(plen + 7) / 8 - 1] &=
605 			((0xff00 >> (plen % 8)) & 0xff);
606 	}
607         /* the label may get offsetted by 4 bits so lets shift it right */
608 	snprintf(buf, buflen, "RD: %s, %s/%d, label:%u %s",
609                  bgp_vpn_rd_print(pptr+4),
610                  getname((u_char *)&addr),
611                  plen,
612                  EXTRACT_24BITS(pptr+1)>>4,
613                  ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
614 
615 	return 12 + (plen + 7) / 8;
616 
617 trunc:
618 	return -2;
619 }
620 
621 static int
622 decode_labeled_vpn_l2(const u_char *pptr, char *buf, u_int buflen)
623 {
624         int plen,tlen,strlen,tlv_type,tlv_len,ttlv_len;
625 
626 	TCHECK2(pptr[0], 2);
627         plen=EXTRACT_16BITS(pptr);
628         tlen=plen;
629         pptr+=2;
630 	TCHECK2(pptr[0],15);
631         strlen=snprintf(buf, buflen, "RD: %s, CE-ID: %u, Label-Block Offset: %u, Label Base %u",
632                         bgp_vpn_rd_print(pptr),
633                         EXTRACT_16BITS(pptr+8),
634                         EXTRACT_16BITS(pptr+10),
635                         EXTRACT_24BITS(pptr+12)>>4); /* the label is offsetted by 4 bits so lets shift it right */
636         pptr+=15;
637         tlen-=15;
638 
639         /* ok now the variable part - lets read out TLVs*/
640         while (tlen>0) {
641             if (tlen < 3)
642                 return -1;
643             TCHECK2(pptr[0], 3);
644             tlv_type=*pptr++;
645             tlv_len=EXTRACT_16BITS(pptr);
646             ttlv_len=tlv_len;
647             pptr+=2;
648 
649             switch(tlv_type) {
650             case 1:
651                 strlen+=snprintf(buf+strlen,buflen-strlen, "\n\t\tcircuit status vector (%u) length: %u: 0x",
652                                  tlv_type,
653                                  tlv_len);
654                 ttlv_len=ttlv_len/8+1; /* how many bytes do we need to read ? */
655                 while (ttlv_len>0) {
656                     TCHECK(pptr[0]);
657                     strlen+=snprintf(buf+strlen,buflen-strlen, "%02x",*pptr++);
658                     ttlv_len--;
659                 }
660                 break;
661             default:
662                 snprintf(buf+strlen,buflen-strlen, "\n\t\tunknown TLV #%u, length: %u",
663                          tlv_type,
664                          tlv_len);
665                 break;
666             }
667             tlen-=(tlv_len<<3); /* the tlv-length is expressed in bits so lets shift it tright */
668         }
669         return plen+2;
670 
671 trunc:
672         return -2;
673 }
674 
675 #ifdef INET6
676 static int
677 decode_prefix6(const u_char *pd, char *buf, u_int buflen)
678 {
679 	struct in6_addr addr;
680 	u_int plen;
681 
682 	TCHECK(pd[0]);
683 	plen = pd[0];
684 	if (128 < plen)
685 		return -1;
686 
687 	memset(&addr, 0, sizeof(addr));
688 	TCHECK2(pd[1], (plen + 7) / 8);
689 	memcpy(&addr, &pd[1], (plen + 7) / 8);
690 	if (plen % 8) {
691 		addr.s6_addr[(plen + 7) / 8 - 1] &=
692 			((0xff00 >> (plen % 8)) & 0xff);
693 	}
694 	snprintf(buf, buflen, "%s/%d", getname6((u_char *)&addr), plen);
695 	return 1 + (plen + 7) / 8;
696 
697 trunc:
698 	return -2;
699 }
700 
701 static int
702 decode_labeled_prefix6(const u_char *pptr, char *buf, u_int buflen)
703 {
704 	struct in6_addr addr;
705 	u_int plen;
706 
707 	TCHECK(pptr[0]);
708 	plen = pptr[0]; /* get prefix length */
709         plen-=24; /* adjust prefixlen - labellength */
710 
711 	if (128 < plen)
712 		return -1;
713 
714 	memset(&addr, 0, sizeof(addr));
715 	TCHECK2(pptr[4], (plen + 7) / 8);
716 	memcpy(&addr, &pptr[4], (plen + 7) / 8);
717 	if (plen % 8) {
718 		addr.s6_addr[(plen + 7) / 8 - 1] &=
719 			((0xff00 >> (plen % 8)) & 0xff);
720 	}
721         /* the label may get offsetted by 4 bits so lets shift it right */
722 	snprintf(buf, buflen, "%s/%d, label:%u %s",
723                  getname6((u_char *)&addr),
724                  plen,
725                  EXTRACT_24BITS(pptr+1)>>4,
726                  ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
727 
728 	return 4 + (plen + 7) / 8;
729 
730 trunc:
731 	return -2;
732 }
733 
734 static int
735 decode_labeled_vpn_prefix6(const u_char *pptr, char *buf, u_int buflen)
736 {
737 	struct in6_addr addr;
738 	u_int plen;
739 
740 	TCHECK(pptr[0]);
741 	plen = pptr[0];   /* get prefix length */
742 
743         plen-=(24+64); /* adjust prefixlen - labellength - RD len*/
744 
745 	if (128 < plen)
746 		return -1;
747 
748 	memset(&addr, 0, sizeof(addr));
749 	TCHECK2(pptr[12], (plen + 7) / 8);
750 	memcpy(&addr, &pptr[12], (plen + 7) / 8);
751 	if (plen % 8) {
752 		addr.s6_addr[(plen + 7) / 8 - 1] &=
753 			((0xff00 >> (plen % 8)) & 0xff);
754 	}
755         /* the label may get offsetted by 4 bits so lets shift it right */
756 	snprintf(buf, buflen, "RD: %s, %s/%d, label:%u %s",
757                  bgp_vpn_rd_print(pptr+4),
758                  getname6((u_char *)&addr),
759                  plen,
760                  EXTRACT_24BITS(pptr+1)>>4,
761                  ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
762 
763 	return 12 + (plen + 7) / 8;
764 
765 trunc:
766 	return -2;
767 }
768 #endif
769 
770 static int
771 bgp_attr_print(const struct bgp_attr *attr, const u_char *pptr, int len)
772 {
773 	int i;
774 	u_int16_t af;
775 	u_int8_t safi, snpa;
776         union { /* copy buffer for bandwidth values */
777             float f;
778             u_int32_t i;
779         } bw;
780 	int advance;
781 	int tlen;
782 	const u_char *tptr;
783 	char buf[MAXHOSTNAMELEN + 100];
784 
785         tptr = pptr;
786         tlen=len;
787 
788 	switch (attr->bgpa_type) {
789 	case BGPTYPE_ORIGIN:
790 		if (len != 1)
791 			printf("invalid len");
792 		else {
793 			TCHECK(*tptr);
794 			printf("%s", tok2str(bgp_origin_values, "Unknown Origin Typecode", tptr[0]));
795 		}
796 		break;
797 	case BGPTYPE_AS_PATH:
798 		if (len % 2) {
799 			printf("invalid len");
800 			break;
801 		}
802                 if (!len) {
803 			printf("empty");
804 			break;
805                 }
806 
807 		while (tptr < pptr + len) {
808 			TCHECK(tptr[0]);
809                         printf("%s", tok2str(bgp_as_path_segment_open_values, "?", tptr[0]));
810                         for (i = 0; i < tptr[1] * 2; i += 2) {
811                             TCHECK2(tptr[2 + i], 2);
812                             printf("%u ", EXTRACT_16BITS(&tptr[2 + i]));
813                         }
814 			TCHECK(tptr[0]);
815                         printf("%s", tok2str(bgp_as_path_segment_close_values, "?", tptr[0]));
816                         TCHECK(tptr[1]);
817                         tptr += 2 + tptr[1] * 2;
818 		}
819 		break;
820 	case BGPTYPE_NEXT_HOP:
821 		if (len != 4)
822 			printf("invalid len");
823 		else {
824 			TCHECK2(tptr[0], 4);
825 			printf("%s", getname(tptr));
826 		}
827 		break;
828 	case BGPTYPE_MULTI_EXIT_DISC:
829 	case BGPTYPE_LOCAL_PREF:
830 		if (len != 4)
831 			printf("invalid len");
832 		else {
833 			TCHECK2(tptr[0], 4);
834 			printf("%u", EXTRACT_32BITS(tptr));
835 		}
836 		break;
837 	case BGPTYPE_ATOMIC_AGGREGATE:
838 		if (len != 0)
839 			printf("invalid len");
840 		break;
841 	case BGPTYPE_AGGREGATOR:
842 		if (len != 6) {
843 			printf("invalid len");
844 			break;
845 		}
846 		TCHECK2(tptr[0], 6);
847 		printf(" AS #%u, origin %s", EXTRACT_16BITS(tptr),
848 			getname(tptr + 2));
849 		break;
850 	case BGPTYPE_COMMUNITIES:
851 		if (len % 4) {
852 			printf("invalid len");
853 			break;
854 		}
855 		while (tlen>0) {
856 			u_int32_t comm;
857 			TCHECK2(tptr[0], 4);
858 			comm = EXTRACT_32BITS(tptr);
859 			switch (comm) {
860 			case BGP_COMMUNITY_NO_EXPORT:
861 				printf(" NO_EXPORT");
862 				break;
863 			case BGP_COMMUNITY_NO_ADVERT:
864 				printf(" NO_ADVERTISE");
865 				break;
866 			case BGP_COMMUNITY_NO_EXPORT_SUBCONFED:
867 				printf(" NO_EXPORT_SUBCONFED");
868 				break;
869 			default:
870 				printf("%u:%u%s",
871                                        (comm >> 16) & 0xffff,
872                                        comm & 0xffff,
873                                        (tlen>4) ? ", " : "");
874 				break;
875 			}
876                         tlen -=4;
877                         tptr +=4;
878 		}
879 		break;
880         case BGPTYPE_ORIGINATOR_ID:
881 		if (len != 4) {
882 			printf("invalid len");
883 			break;
884 		}
885 		TCHECK2(tptr[0], 4);
886                 printf("%s",getname(tptr));
887                 break;
888         case BGPTYPE_CLUSTER_LIST:
889 		if (len % 4) {
890 			printf("invalid len");
891 			break;
892 		}
893                 while (tlen>0) {
894 			TCHECK2(tptr[0], 4);
895                         printf("%s%s",
896                                getname(tptr),
897                                 (tlen>4) ? ", " : "");
898                         tlen -=4;
899                         tptr +=4;
900                 }
901                 break;
902 	case BGPTYPE_MP_REACH_NLRI:
903 		TCHECK2(tptr[0], 3);
904 		af = EXTRACT_16BITS(tptr);
905 		safi = tptr[2];
906 
907                 printf("\n\t    AFI: %s (%u), %sSAFI: %s (%u)",
908                        tok2str(bgp_afi_values, "Unknown AFI", af),
909                        af,
910                        (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
911                        tok2str(bgp_safi_values, "Unknown SAFI", safi),
912                        safi);
913 
914 		if (af == AFNUM_INET || af==AFNUM_L2VPN)
915 			;
916 #ifdef INET6
917 		else if (af == AFNUM_INET6)
918 			;
919 #endif
920 		else {
921                     printf("\n\t    no AFI %u decoder",af);
922                     if (vflag <= 1)
923                         print_unknown_data(tptr,"\n\t    ",tlen);
924                     break;
925                 }
926 
927                 tptr +=3;
928 
929 		TCHECK(tptr[0]);
930 		tlen = tptr[0];
931                 tptr++;
932 
933 		if (tlen) {
934 			printf("\n\t    nexthop: ");
935 			while (tlen > 0) {
936 				switch (af) {
937 				case AFNUM_INET:
938                                     switch(safi) {
939                                     case SAFNUM_UNICAST:
940                                     case SAFNUM_MULTICAST:
941                                     case SAFNUM_UNIMULTICAST:
942                                     case SAFNUM_LABUNICAST:
943                                     case SAFNUM_RT_ROUTING_INFO:
944 					if (tlen < (int)sizeof(struct in_addr)) {
945 					    printf("invalid len");
946 					    tlen = 0;
947 					} else {
948 					    TCHECK2(tptr[0], sizeof(struct in_addr));
949 					    printf("%s",getname(tptr));
950 					    tlen -= sizeof(struct in_addr);
951 					    tptr += sizeof(struct in_addr);
952 					}
953 					break;
954                                     case SAFNUM_VPNUNICAST:
955                                     case SAFNUM_VPNMULTICAST:
956                                     case SAFNUM_VPNUNIMULTICAST:
957 					if (tlen < (int)(sizeof(struct in_addr)+BGP_VPN_RD_LEN)) {
958 					    printf("invalid len");
959 					    tlen = 0;
960 					} else {
961 					    TCHECK2(tptr[0], sizeof(struct in_addr)+BGP_VPN_RD_LEN);
962 					    printf("RD: %s, %s",
963                                                bgp_vpn_rd_print(tptr),
964                                                getname(tptr+BGP_VPN_RD_LEN));
965 					    tlen -= (sizeof(struct in_addr)+BGP_VPN_RD_LEN);
966 					    tptr += (sizeof(struct in_addr)+BGP_VPN_RD_LEN);
967 					}
968                                         break;
969                                     default:
970                                         TCHECK2(tptr[0], tlen);
971                                         printf("no SAFI %u decoder",safi);
972                                         if (vflag <= 1)
973                                             print_unknown_data(tptr,"\n\t    ",tlen);
974                                         tptr += tlen;
975                                         tlen = 0;
976                                         break;
977                                     }
978                                     break;
979 #ifdef INET6
980 				case AFNUM_INET6:
981                                     switch(safi) {
982                                     case SAFNUM_UNICAST:
983                                     case SAFNUM_MULTICAST:
984                                     case SAFNUM_UNIMULTICAST:
985                                     case SAFNUM_LABUNICAST:
986                                     case SAFNUM_RT_ROUTING_INFO:
987 					if (tlen < (int)sizeof(struct in6_addr)) {
988 					    printf("invalid len");
989 					    tlen = 0;
990 					} else {
991 					    TCHECK2(tptr[0], sizeof(struct in6_addr));
992 					    printf("%s", getname6(tptr));
993 					    tlen -= sizeof(struct in6_addr);
994 					    tptr += sizeof(struct in6_addr);
995 					}
996                                         break;
997                                     case SAFNUM_VPNUNICAST:
998                                     case SAFNUM_VPNMULTICAST:
999                                     case SAFNUM_VPNUNIMULTICAST:
1000 					if (tlen < (int)(sizeof(struct in6_addr)+BGP_VPN_RD_LEN)) {
1001 					    printf("invalid len");
1002 					    tlen = 0;
1003 					} else {
1004 					    TCHECK2(tptr[0], sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
1005 					    printf("RD: %s, %s",
1006                                                bgp_vpn_rd_print(tptr),
1007                                                getname6(tptr+BGP_VPN_RD_LEN));
1008 					    tlen -= (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
1009 					    tptr += (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
1010 					}
1011                                         break;
1012                                     default:
1013                                         TCHECK2(tptr[0], tlen);
1014                                         printf("no SAFI %u decoder",safi);
1015                                         if (vflag <= 1)
1016                                             print_unknown_data(tptr,"\n\t    ",tlen);
1017                                         tptr += tlen;
1018                                         tlen = 0;
1019                                         break;
1020                                     }
1021                                     break;
1022 #endif
1023                                 case AFNUM_L2VPN:
1024                                    switch(safi) {
1025                                     case SAFNUM_VPNUNICAST:
1026                                     case SAFNUM_VPNMULTICAST:
1027                                     case SAFNUM_VPNUNIMULTICAST:
1028 					if (tlen < (int)sizeof(struct in_addr)) {
1029 					    printf("invalid len");
1030 					    tlen = 0;
1031 					} else {
1032 					    TCHECK2(tptr[0], sizeof(struct in_addr));
1033 					    printf("%s", getname(tptr));
1034 					    tlen -= (sizeof(struct in_addr));
1035 					    tptr += (sizeof(struct in_addr));
1036 					}
1037                                         break;
1038                                    default:
1039                                         TCHECK2(tptr[0], tlen);
1040                                         printf("no SAFI %u decoder",safi);
1041                                         if (vflag <= 1)
1042                                             print_unknown_data(tptr,"\n\t    ",tlen);
1043                                         tptr += tlen;
1044                                         tlen = 0;
1045                                         break;
1046                                    }
1047                                    break;
1048 
1049 				default:
1050                                     TCHECK2(tptr[0], tlen);
1051                                     printf("no AFI %u decoder",af);
1052                                     if (vflag <= 1)
1053                                       print_unknown_data(tptr,"\n\t    ",tlen);
1054                                     tptr += tlen;
1055                                     tlen = 0;
1056                                     break;
1057 				}
1058 			}
1059 		}
1060 		tptr += tlen;
1061 
1062 		TCHECK(tptr[0]);
1063 		snpa = tptr[0];
1064 		tptr++;
1065 
1066 		if (snpa) {
1067 			printf("\n\t    %u SNPA", snpa);
1068 			for (/*nothing*/; snpa > 0; snpa--) {
1069 				TCHECK(tptr[0]);
1070 				printf("\n\t      %d bytes", tptr[0]);
1071 				tptr += tptr[0] + 1;
1072 			}
1073 		} else {
1074 			printf(", no SNPA");
1075                 }
1076 
1077 		while (len - (tptr - pptr) > 0) {
1078 			switch (af) {
1079 			case AFNUM_INET:
1080                             switch (safi) {
1081                             case SAFNUM_UNICAST:
1082                             case SAFNUM_MULTICAST:
1083                             case SAFNUM_UNIMULTICAST:
1084                                 advance = decode_prefix4(tptr, buf, sizeof(buf));
1085 				if (advance == -1)
1086                                         printf("\n\t    (illegal prefix length)");
1087 	                        else if (advance == -2)
1088                                         goto trunc;
1089 	                        else
1090                                 	printf("\n\t      %s", buf);
1091                                 break;
1092                             case SAFNUM_LABUNICAST:
1093                                 advance = decode_labeled_prefix4(tptr, buf, sizeof(buf));
1094 				if (advance == -1)
1095                                         printf("\n\t    (illegal prefix length)");
1096 	                        else if (advance == -2)
1097                                         goto trunc;
1098 	                        else
1099                                         printf("\n\t      %s", buf);
1100                                 break;
1101                             case SAFNUM_VPNUNICAST:
1102                             case SAFNUM_VPNMULTICAST:
1103                             case SAFNUM_VPNUNIMULTICAST:
1104                                 advance = decode_labeled_vpn_prefix4(tptr, buf, sizeof(buf));
1105 				if (advance == -1)
1106                                         printf("\n\t    (illegal prefix length)");
1107 	                        else if (advance == -2)
1108                                         goto trunc;
1109 	                        else
1110                                         printf("\n\t      %s", buf);
1111                                 break;
1112                             case SAFNUM_RT_ROUTING_INFO:
1113                                 advance = decode_rt_routing_info(tptr, buf, sizeof(buf));
1114 				if (advance == -1)
1115                                         printf("\n\t    (illegal prefix length)");
1116 	                        else if (advance == -2)
1117                                         goto trunc;
1118 	                        else
1119                                         printf("\n\t      %s", buf);
1120                                 break;
1121                             default:
1122                                 TCHECK2(*(tptr-3),tlen);
1123                                 printf("\n\t      no SAFI %u decoder",safi);
1124                                 if (vflag <= 1)
1125                                     print_unknown_data(tptr-3,"\n\t    ",tlen);
1126                                 advance = 0;
1127 				tptr = pptr + len;
1128 				break;
1129                             }
1130                             break;
1131 #ifdef INET6
1132 			case AFNUM_INET6:
1133                             switch (safi) {
1134                             case SAFNUM_UNICAST:
1135                             case SAFNUM_MULTICAST:
1136                             case SAFNUM_UNIMULTICAST:
1137 				advance = decode_prefix6(tptr, buf, sizeof(buf));
1138 				if (advance == -1)
1139 					printf("\n\t    (illegal prefix length)");
1140 				else if (advance == -2)
1141 					goto trunc;
1142 	                        else
1143 					printf("\n\t      %s", buf);
1144 				break;
1145                             case SAFNUM_LABUNICAST:
1146                                 advance = decode_labeled_prefix6(tptr, buf, sizeof(buf));
1147 				if (advance == -1)
1148 					printf("\n\t    (illegal prefix length)");
1149 				else if (advance == -2)
1150 					goto trunc;
1151 	                        else
1152 					printf("\n\t      %s", buf);
1153                                 break;
1154                             case SAFNUM_VPNUNICAST:
1155                             case SAFNUM_VPNMULTICAST:
1156                             case SAFNUM_VPNUNIMULTICAST:
1157                                 advance = decode_labeled_vpn_prefix6(tptr, buf, sizeof(buf));
1158 				if (advance == -1)
1159 					printf("\n\t    (illegal prefix length)");
1160 				else if (advance == -2)
1161 					goto trunc;
1162 	                        else
1163 					printf("\n\t      %s", buf);
1164                                 break;
1165                             case SAFNUM_RT_ROUTING_INFO:
1166                                 advance = decode_rt_routing_info(tptr, buf, sizeof(buf));
1167 				if (advance == -1)
1168 					printf("\n\t    (illegal prefix length)");
1169 				else if (advance == -2)
1170 					goto trunc;
1171 	                        else
1172 					printf("\n\t      %s", buf);
1173                                 break;
1174                             default:
1175                                 TCHECK2(*(tptr-3),tlen);
1176                                 printf("\n\t      no SAFI %u decoder ",safi);
1177                                 if (vflag <= 1)
1178                                     print_unknown_data(tptr-3,"\n\t    ",tlen);
1179                                 advance = 0;
1180 				tptr = pptr + len;
1181 				break;
1182                             }
1183                             break;
1184 #endif
1185                         case AFNUM_L2VPN:
1186                             switch(safi) {
1187                             case SAFNUM_VPNUNICAST:
1188                             case SAFNUM_VPNMULTICAST:
1189                             case SAFNUM_VPNUNIMULTICAST:
1190 				advance = decode_labeled_vpn_l2(tptr, buf, sizeof(buf));
1191 				if (advance == -1)
1192 					printf("\n\t    (illegal length)");
1193 				else if (advance == -2)
1194 					goto trunc;
1195 	                        else
1196                                         printf("\n\t      %s", buf);
1197                                 break;
1198                             default:
1199                                 TCHECK2(*tptr,tlen);
1200                                 printf("no SAFI %u decoder",safi);
1201                                 if (vflag <= 1)
1202                                     print_unknown_data(tptr,"\n\t    ",tlen);
1203                                 advance = 0;
1204 				tptr = pptr + len;
1205                                 break;
1206                             }
1207                             break;
1208 
1209 
1210 			default:
1211                             TCHECK2(*(tptr-3),tlen);
1212                             printf("\n\t      no AFI %u decoder ",af);
1213                             if (vflag <= 1)
1214                                     print_unknown_data(tptr-3,"\n\t    ",tlen);
1215                             advance = 0;
1216                             tptr = pptr + len;
1217                             break;
1218 			}
1219 			tptr += advance;
1220 		}
1221 		break;
1222 
1223 	case BGPTYPE_MP_UNREACH_NLRI:
1224 		TCHECK2(tptr[0], 3);
1225 		af = EXTRACT_16BITS(tptr);
1226 		safi = tptr[2];
1227 
1228                 printf("\n\t    AFI: %s (%u), %sSAFI: %s (%u)",
1229                        tok2str(bgp_afi_values, "Unknown AFI", af),
1230                        af,
1231                        (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
1232                        tok2str(bgp_safi_values, "Unknown SAFI", safi),
1233                        safi);
1234 
1235 		tptr += 3;
1236 
1237 		while (len - (tptr - pptr) > 0) {
1238 			switch (af) {
1239 			case AFNUM_INET:
1240                             switch (safi) {
1241                             case SAFNUM_UNICAST:
1242                             case SAFNUM_MULTICAST:
1243                             case SAFNUM_UNIMULTICAST:
1244                                 advance = decode_prefix4(tptr, buf, sizeof(buf));
1245 				if (advance == -1)
1246                                         printf("\n\t    (illegal prefix length)");
1247 	                        else if (advance == -2)
1248                                         goto trunc;
1249 	                        else
1250                                 	printf("\n\t      %s", buf);
1251                                 break;
1252                             case SAFNUM_LABUNICAST:
1253                                 advance = decode_labeled_prefix4(tptr, buf, sizeof(buf));
1254 				if (advance == -1)
1255                                         printf("\n\t    (illegal prefix length)");
1256 	                        else if (advance == -2)
1257                                         goto trunc;
1258 	                        else
1259                                         printf("\n\t      %s", buf);
1260                                 break;
1261                             case SAFNUM_VPNUNICAST:
1262                             case SAFNUM_VPNMULTICAST:
1263                             case SAFNUM_VPNUNIMULTICAST:
1264                                 advance = decode_labeled_vpn_prefix4(tptr, buf, sizeof(buf));
1265 				if (advance == -1)
1266                                         printf("\n\t    (illegal prefix length)");
1267 	                        else if (advance == -2)
1268                                         goto trunc;
1269 	                        else
1270                                         printf("\n\t      %s", buf);
1271                                 break;
1272                             default:
1273                                 TCHECK2(*(tptr-3),tlen);
1274                                 printf("\n\t      no SAFI %u decoder",safi);
1275                                 if (vflag <= 1)
1276                                     print_unknown_data(tptr-3,"\n\t    ",tlen);
1277                                 advance = 0;
1278 				tptr = pptr + len;
1279 				break;
1280                             }
1281                             break;
1282 
1283 #ifdef INET6
1284 			case AFNUM_INET6:
1285                             switch (safi) {
1286                             case SAFNUM_UNICAST:
1287                             case SAFNUM_MULTICAST:
1288                             case SAFNUM_UNIMULTICAST:
1289 				advance = decode_prefix6(tptr, buf, sizeof(buf));
1290 				if (advance == -1)
1291 					printf("\n\t    (illegal prefix length)");
1292 				else if (advance == -2)
1293 					goto trunc;
1294 	                        else
1295 					printf("\n\t      %s", buf);
1296 				break;
1297                             case SAFNUM_LABUNICAST:
1298                                 advance = decode_labeled_prefix6(tptr, buf, sizeof(buf));
1299 				if (advance == -1)
1300 					printf("\n\t    (illegal prefix length)");
1301 				else if (advance == -2)
1302 					goto trunc;
1303 	                        else
1304                                         printf("\n\t      %s", buf);
1305                                 break;
1306                             case SAFNUM_VPNUNICAST:
1307                             case SAFNUM_VPNMULTICAST:
1308                             case SAFNUM_VPNUNIMULTICAST:
1309                                 advance = decode_labeled_vpn_prefix6(tptr, buf, sizeof(buf));
1310 				if (advance == -1)
1311 					printf("\n\t    (illegal prefix length)");
1312 				else if (advance == -2)
1313 					goto trunc;
1314 	                        else
1315                                         printf("\n\t      %s", buf);
1316                                 break;
1317                             default:
1318                                 TCHECK2(*(tptr-3),tlen);
1319                                 printf("\n\t      no SAFI %u decoder",safi);
1320                                 if (vflag <= 1)
1321                                     print_unknown_data(tptr-3,"\n\t    ",tlen);
1322                                 advance = 0;
1323 				tptr = pptr + len;
1324 				break;
1325                             }
1326                             break;
1327 #endif
1328 
1329                         case AFNUM_L2VPN:
1330                             switch(safi) {
1331                             case SAFNUM_VPNUNICAST:
1332                             case SAFNUM_VPNMULTICAST:
1333                             case SAFNUM_VPNUNIMULTICAST:
1334 				advance = decode_labeled_vpn_l2(tptr, buf, sizeof(buf));
1335 				if (advance == -1)
1336 					printf("\n\t    (illegal length)");
1337 				else if (advance == -2)
1338 					goto trunc;
1339 	                        else
1340                                         printf("\n\t      %s", buf);
1341                                 break;
1342                             default:
1343                                 TCHECK2(*(tptr-3),tlen);
1344                                 printf("no SAFI %u decoder",safi);
1345                                 if (vflag <= 1)
1346                                     print_unknown_data(tptr-3,"\n\t    ",tlen);
1347                                 advance = 0;
1348 				tptr = pptr + len;
1349                                 break;
1350                             }
1351                             break;
1352 
1353 			default:
1354 				TCHECK2(*(tptr-3),tlen);
1355 				printf("\n\t    no AFI %u decoder",af);
1356                                 if (vflag <= 1)
1357                                     print_unknown_data(tptr-3,"\n\t    ",tlen);
1358 				advance = 0;
1359 				tptr = pptr + len;
1360 				break;
1361 			}
1362 
1363 			tptr += advance;
1364 		}
1365 		break;
1366         case BGPTYPE_EXTD_COMMUNITIES:
1367 		if (len % 8) {
1368 			printf("invalid len");
1369 			break;
1370 		}
1371                 while (tlen>0) {
1372                     u_int16_t extd_comm;
1373 
1374                     TCHECK2(tptr[0], 2);
1375                     extd_comm=EXTRACT_16BITS(tptr);
1376 
1377 		    printf("\n\t    %s (0x%04x), Flags [%s]",
1378 			   tok2str(bgp_extd_comm_subtype_values, "unknown extd community typecode", extd_comm),
1379 			   extd_comm,
1380 			   bittok2str(bgp_extd_comm_flag_values, "none", extd_comm));
1381 
1382                     TCHECK2(*(tptr+2), 6);
1383                     switch(extd_comm) {
1384                     case BGP_EXT_COM_RT_0:
1385                     case BGP_EXT_COM_RO_0:
1386                         printf(": %u:%s",
1387                                EXTRACT_16BITS(tptr+2),
1388                                getname(tptr+4));
1389                         break;
1390                     case BGP_EXT_COM_RT_1:
1391                     case BGP_EXT_COM_RO_1:
1392                         printf(": %s:%u",
1393                                getname(tptr+2),
1394                                EXTRACT_16BITS(tptr+6));
1395                         break;
1396                     case BGP_EXT_COM_RT_2:
1397                     case BGP_EXT_COM_RO_2:
1398                         printf(": %u:%u",
1399                                EXTRACT_32BITS(tptr+2),
1400                                EXTRACT_16BITS(tptr+6));
1401                         break;
1402                     case BGP_EXT_COM_LINKBAND:
1403 		        bw.i = EXTRACT_32BITS(tptr+2);
1404                         printf(": bandwidth: %.3f Mbps",
1405                                bw.f*8/1000000);
1406                         break;
1407                     case BGP_EXT_COM_VPN_ORIGIN:
1408                     case BGP_EXT_COM_VPN_ORIGIN2:
1409                     case BGP_EXT_COM_VPN_ORIGIN3:
1410                     case BGP_EXT_COM_VPN_ORIGIN4:
1411                     case BGP_EXT_COM_OSPF_RID:
1412                     case BGP_EXT_COM_OSPF_RID2:
1413                         printf("%s", getname(tptr+2));
1414                         break;
1415                     case BGP_EXT_COM_OSPF_RTYPE:
1416                     case BGP_EXT_COM_OSPF_RTYPE2:
1417                         printf(": area:%s, router-type:%s, metric-type:%s%s",
1418                                getname(tptr+2),
1419                                tok2str(bgp_extd_comm_ospf_rtype_values,
1420                                        "unknown (0x%02x)",
1421                                        *(tptr+6)),
1422                                (*(tptr+7) &  BGP_OSPF_RTYPE_METRIC_TYPE) ? "E2" : "",
1423                                (*(tptr+6) == (BGP_OSPF_RTYPE_EXT ||BGP_OSPF_RTYPE_NSSA )) ? "E1" : "");
1424                         break;
1425                     case BGP_EXT_COM_L2INFO:
1426                         printf(": %s Control Flags [0x%02x]:MTU %u",
1427                                tok2str(bgp_l2vpn_encaps_values,
1428                                        "unknown encaps",
1429                                        *(tptr+2)),
1430                                        *(tptr+3),
1431                                EXTRACT_16BITS(tptr+4));
1432                         break;
1433                     default:
1434                         print_unknown_data(tptr,"\n\t      ",8);
1435                         break;
1436                     }
1437                     tlen -=8;
1438                     tptr +=8;
1439                 }
1440                 break;
1441 
1442 	default:
1443 	    TCHECK2(*pptr,len);
1444             printf("\n\t    no Attribute %u decoder",attr->bgpa_type); /* we have no decoder for the attribute */
1445             if (vflag <= 1)
1446                 print_unknown_data(pptr,"\n\t    ",len);
1447             break;
1448 	}
1449         if (vflag > 1 && len) /* omit zero length attributes*/
1450             print_unknown_data(pptr,"\n\t    ",len);
1451         return 1;
1452 
1453 trunc:
1454         return 0;
1455 }
1456 
1457 static void
1458 bgp_open_print(const u_char *dat, int length)
1459 {
1460 	struct bgp_open bgpo;
1461 	struct bgp_opt bgpopt;
1462 	int hlen;
1463 	const u_char *opt;
1464 	int i,cap_type,cap_len,tcap_len,cap_offset;
1465 
1466 	TCHECK2(dat[0], BGP_OPEN_SIZE);
1467 	memcpy(&bgpo, dat, BGP_OPEN_SIZE);
1468 	hlen = ntohs(bgpo.bgpo_len);
1469 
1470 	printf("\n\t  Version %d, ", bgpo.bgpo_version);
1471 	printf("my AS %u, ", ntohs(bgpo.bgpo_myas));
1472 	printf("Holdtime %us, ", ntohs(bgpo.bgpo_holdtime));
1473 	printf("ID %s", getname((u_char *)&bgpo.bgpo_id));
1474 	printf("\n\t  Optional parameters, length: %u", bgpo.bgpo_optlen);
1475 
1476         /* some little sanity checking */
1477         if (length < bgpo.bgpo_optlen+BGP_OPEN_SIZE)
1478             return;
1479 
1480 	/* ugly! */
1481 	opt = &((const struct bgp_open *)dat)->bgpo_optlen;
1482 	opt++;
1483 
1484 	i = 0;
1485 	while (i < bgpo.bgpo_optlen) {
1486 		TCHECK2(opt[i], BGP_OPT_SIZE);
1487 		memcpy(&bgpopt, &opt[i], BGP_OPT_SIZE);
1488 		if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) {
1489                         printf("\n\t     Option %d, length: %u", bgpopt.bgpopt_type, bgpopt.bgpopt_len);
1490 			break;
1491 		}
1492 
1493 		printf("\n\t    Option %s (%u), length: %u",
1494                        tok2str(bgp_opt_values,"Unknown", bgpopt.bgpopt_type),
1495                        bgpopt.bgpopt_type,
1496                        bgpopt.bgpopt_len);
1497 
1498                 /* now lets decode the options we know*/
1499                 switch(bgpopt.bgpopt_type) {
1500                 case BGP_OPT_CAP:
1501                     cap_type=opt[i+BGP_OPT_SIZE];
1502                     cap_len=opt[i+BGP_OPT_SIZE+1];
1503                     tcap_len=cap_len;
1504                     printf("\n\t      %s, length: %u",
1505                            tok2str(bgp_capcode_values,"Unknown", cap_type),
1506                            cap_len);
1507                     switch(cap_type) {
1508                     case BGP_CAPCODE_MP:
1509                         printf("\n\t\tAFI %s (%u), SAFI %s (%u)",
1510                                tok2str(bgp_afi_values,"Unknown", EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+2)),
1511                                EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+2),
1512                                tok2str(bgp_safi_values,"Unknown", opt[i+BGP_OPT_SIZE+5]),
1513                                opt[i+BGP_OPT_SIZE+5]);
1514                         break;
1515                     case BGP_CAPCODE_RESTART:
1516                         printf("\n\t\tRestart Flags: [%s], Restart Time %us",
1517                                ((opt[i+BGP_OPT_SIZE+2])&0x80) ? "R" : "none",
1518                                EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+2)&0xfff);
1519                         tcap_len-=2;
1520                         cap_offset=4;
1521                         while(tcap_len>=4) {
1522                             printf("\n\t\t  AFI %s (%u), SAFI %s (%u), Forwarding state preserved: %s",
1523                                    tok2str(bgp_afi_values,"Unknown", EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+cap_offset)),
1524                                    EXTRACT_16BITS(opt+i+BGP_OPT_SIZE+cap_offset),
1525                                    tok2str(bgp_safi_values,"Unknown", opt[i+BGP_OPT_SIZE+cap_offset+2]),
1526                                    opt[i+BGP_OPT_SIZE+cap_offset+2],
1527                                    ((opt[i+BGP_OPT_SIZE+cap_offset+3])&0x80) ? "yes" : "no" );
1528                             tcap_len-=4;
1529                             cap_offset+=4;
1530                         }
1531                         break;
1532                     case BGP_CAPCODE_RR:
1533                     case BGP_CAPCODE_RR_CISCO:
1534                         break;
1535                     default:
1536                         printf("\n\t\tno decoder for Capability %u",
1537                                cap_type);
1538                         if (vflag <= 1)
1539                             print_unknown_data(&opt[i+BGP_OPT_SIZE+2],"\n\t\t",cap_len);
1540                         break;
1541                     }
1542                     if (vflag > 1)
1543                         print_unknown_data(&opt[i+BGP_OPT_SIZE+2],"\n\t\t",cap_len);
1544                     break;
1545                 case BGP_OPT_AUTH:
1546                 default:
1547                        printf("\n\t      no decoder for option %u",
1548                            bgpopt.bgpopt_type);
1549                        break;
1550                 }
1551 
1552 		i += BGP_OPT_SIZE + bgpopt.bgpopt_len;
1553 	}
1554 	return;
1555 trunc:
1556 	printf("[|BGP]");
1557 }
1558 
1559 static void
1560 bgp_update_print(const u_char *dat, int length)
1561 {
1562 	struct bgp bgp;
1563 	struct bgp_attr bgpa;
1564 	int hlen;
1565 	const u_char *p;
1566 	int len;
1567 	int i;
1568 
1569 	TCHECK2(dat[0], BGP_SIZE);
1570 	memcpy(&bgp, dat, BGP_SIZE);
1571 	hlen = ntohs(bgp.bgp_len);
1572 	p = dat + BGP_SIZE;	/*XXX*/
1573 
1574 	/* Unfeasible routes */
1575 	len = EXTRACT_16BITS(p);
1576 	if (len) {
1577 		/*
1578 		 * Without keeping state from the original NLRI message,
1579 		 * it's not possible to tell if this a v4 or v6 route,
1580 		 * so only try to decode it if we're not v6 enabled.
1581 	         */
1582 #ifdef INET6
1583 		printf("\n\t  Withdrawn routes: %d bytes", len);
1584 #else
1585 		char buf[MAXHOSTNAMELEN + 100];
1586 		int wpfx;
1587 
1588 		TCHECK2(p[2], len);
1589 		i = 2;
1590 
1591 		printf("\n\t  Withdrawn routes:");
1592 
1593 		while(i < 2 + len) {
1594 			wpfx = decode_prefix4(&p[i], buf, sizeof(buf));
1595 			if (wpfx == -1) {
1596 				printf("\n\t    (illegal prefix length)");
1597 				break;
1598 			} else if (wpfx == -2)
1599 				goto trunc;
1600 			else {
1601 				i += wpfx;
1602 				printf("\n\t    %s", buf);
1603 			}
1604 		}
1605 #endif
1606 	}
1607 	p += 2 + len;
1608 
1609 	TCHECK2(p[0], 2);
1610 	len = EXTRACT_16BITS(p);
1611 	if (len) {
1612 		/* do something more useful!*/
1613 		i = 2;
1614 		while (i < 2 + len) {
1615 			int alen, aoff;
1616 
1617 			TCHECK2(p[i], sizeof(bgpa));
1618 			memcpy(&bgpa, &p[i], sizeof(bgpa));
1619 			alen = bgp_attr_len(&bgpa);
1620 			aoff = bgp_attr_off(&bgpa);
1621 
1622 		       printf("\n\t  %s (%u), length: %u",
1623                               tok2str(bgp_attr_values, "Unknown Attribute", bgpa.bgpa_type),
1624                               bgpa.bgpa_type,
1625                               alen);
1626 
1627 			if (bgpa.bgpa_flags) {
1628 				printf(", Flags [%s%s%s%s",
1629 					bgpa.bgpa_flags & 0x80 ? "O" : "",
1630 					bgpa.bgpa_flags & 0x40 ? "T" : "",
1631 					bgpa.bgpa_flags & 0x20 ? "P" : "",
1632 					bgpa.bgpa_flags & 0x10 ? "E" : "");
1633 				if (bgpa.bgpa_flags & 0xf)
1634 					printf("+%x", bgpa.bgpa_flags & 0xf);
1635 				printf("]: ");
1636 			}
1637 			if (!bgp_attr_print(&bgpa, &p[i + aoff], alen))
1638 				goto trunc;
1639 			i += aoff + alen;
1640 		}
1641 	}
1642 	p += 2 + len;
1643 
1644 	if (dat + length > p) {
1645             printf("\n\t  Updated routes:");
1646 		while (dat + length > p) {
1647 			char buf[MAXHOSTNAMELEN + 100];
1648 			i = decode_prefix4(p, buf, sizeof(buf));
1649 			if (i == -1)
1650 				printf("\n\t    (illegal prefix length)");
1651 			else if (i == -2)
1652 				goto trunc;
1653 			else {
1654 				printf("\n\t    %s", buf);
1655 				p += i;
1656 			}
1657 		}
1658 	}
1659 	return;
1660 trunc:
1661 	printf("[|BGP]");
1662 }
1663 
1664 static void
1665 bgp_notification_print(const u_char *dat, int length)
1666 {
1667 	struct bgp_notification bgpn;
1668 	int hlen;
1669 	const u_char *tptr;
1670 
1671 	TCHECK2(dat[0], BGP_NOTIFICATION_SIZE);
1672 	memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE);
1673 	hlen = ntohs(bgpn.bgpn_len);
1674 
1675         /* some little sanity checking */
1676         if (length<BGP_NOTIFICATION_SIZE)
1677             return;
1678 
1679 	printf(", %s (%u)",
1680 	       tok2str(bgp_notify_major_values, "Unknown Error", bgpn.bgpn_major),
1681 	       bgpn.bgpn_major);
1682 
1683         switch (bgpn.bgpn_major) {
1684 
1685         case BGP_NOTIFY_MAJOR_MSG:
1686             printf(", subcode %s (%u)",
1687 		   tok2str(bgp_notify_minor_msg_values, "Unknown", bgpn.bgpn_minor),
1688 		   bgpn.bgpn_minor);
1689             break;
1690         case BGP_NOTIFY_MAJOR_OPEN:
1691             printf(", subcode %s (%u)",
1692 		   tok2str(bgp_notify_minor_open_values, "Unknown", bgpn.bgpn_minor),
1693 		   bgpn.bgpn_minor);
1694             break;
1695         case BGP_NOTIFY_MAJOR_UPDATE:
1696             printf(", subcode %s (%u)",
1697 		   tok2str(bgp_notify_minor_update_values, "Unknown", bgpn.bgpn_minor),
1698 		   bgpn.bgpn_minor);
1699             break;
1700         case BGP_NOTIFY_MAJOR_CAP:
1701             printf(" subcode %s (%u)",
1702 		   tok2str(bgp_notify_minor_cap_values, "Unknown", bgpn.bgpn_minor),
1703 		   bgpn.bgpn_minor);
1704         case BGP_NOTIFY_MAJOR_CEASE:
1705             printf(", subcode %s (%u)",
1706 		   tok2str(bgp_notify_minor_cease_values, "Unknown", bgpn.bgpn_minor),
1707 		   bgpn.bgpn_minor);
1708 
1709 	    /* draft-ietf-idr-cease-subcode-02 mentions optionally 7 bytes
1710              * for the maxprefix subtype, which may contain AFI, SAFI and MAXPREFIXES
1711              */
1712 	    if(bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_MAXPRFX && length >= BGP_NOTIFICATION_SIZE + 7) {
1713 		tptr = dat + BGP_NOTIFICATION_SIZE;
1714 		TCHECK2(*tptr, 7);
1715 		printf(", AFI %s (%u), SAFI %s (%u), Max Prefixes: %u",
1716 		       tok2str(bgp_afi_values, "Unknown", EXTRACT_16BITS(tptr)),
1717 		       EXTRACT_16BITS(tptr),
1718 		       tok2str(bgp_safi_values, "Unknown", *(tptr+2)),
1719 		       *(tptr+2),
1720 		       EXTRACT_32BITS(tptr+3));
1721 	    }
1722             break;
1723         default:
1724             break;
1725         }
1726 
1727 	return;
1728 trunc:
1729 	printf("[|BGP]");
1730 }
1731 
1732 static void
1733 bgp_route_refresh_print(const u_char *pptr, int len) {
1734 
1735         const struct bgp_route_refresh *bgp_route_refresh_header;
1736         bgp_route_refresh_header = (const struct bgp_route_refresh *)pptr;
1737 
1738         printf("\n\t  AFI %s (%u), SAFI %s (%u)",
1739                tok2str(bgp_afi_values,"Unknown",
1740                        EXTRACT_16BITS(&bgp_route_refresh_header->afi)), /* this stinks but the compiler pads the structure weird */
1741                EXTRACT_16BITS(&bgp_route_refresh_header->afi),
1742                tok2str(bgp_safi_values,"Unknown",
1743                        bgp_route_refresh_header->safi),
1744                bgp_route_refresh_header->safi);
1745 
1746         if (vflag > 1)
1747             print_unknown_data(pptr,"\n\t  ", len);
1748 
1749         return;
1750 }
1751 
1752 static int
1753 bgp_header_print(const u_char *dat, int length)
1754 {
1755 	struct bgp bgp;
1756 
1757 	TCHECK2(dat[0], BGP_SIZE);
1758 	memcpy(&bgp, dat, BGP_SIZE);
1759 	printf("\n\t%s Message (%u), length: %u",
1760                tok2str(bgp_msg_values, "Unknown", bgp.bgp_type),
1761                bgp.bgp_type,
1762                length);
1763 
1764 	switch (bgp.bgp_type) {
1765 	case BGP_OPEN:
1766 		bgp_open_print(dat, length);
1767 		break;
1768 	case BGP_UPDATE:
1769 		bgp_update_print(dat, length);
1770 		break;
1771 	case BGP_NOTIFICATION:
1772 		bgp_notification_print(dat, length);
1773 		break;
1774         case BGP_KEEPALIVE:
1775                 break;
1776         case BGP_ROUTE_REFRESH:
1777                 bgp_route_refresh_print(dat, length);
1778                 break;
1779         default:
1780             /* we have no decoder for the BGP message */
1781             printf("\n\t  no Message %u decoder",bgp.bgp_type);
1782             print_unknown_data(dat,"\n\t  ",length);
1783                 break;
1784 	}
1785 	return 1;
1786 trunc:
1787 	printf("[|BGP]");
1788 	return 0;
1789 }
1790 
1791 void
1792 bgp_print(const u_char *dat, int length)
1793 {
1794 	const u_char *p;
1795 	const u_char *ep;
1796 	const u_char *start;
1797 	const u_char marker[] = {
1798 		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1799 		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1800 	};
1801 	struct bgp bgp;
1802 	u_int16_t hlen;
1803 
1804 	ep = dat + length;
1805 	if (snapend < dat + length)
1806 		ep = snapend;
1807 
1808 	printf(": BGP, length: %u",length);
1809 
1810         if (vflag < 1) /* lets be less chatty */
1811                 return;
1812 
1813 	p = dat;
1814 	start = p;
1815 	while (p < snapend) {
1816 		if (!TTEST2(p[0], 1))
1817 			break;
1818 		if (p[0] != 0xff) {
1819 			p++;
1820 			continue;
1821 		}
1822 
1823 		if (!TTEST2(p[0], sizeof(marker)))
1824 			break;
1825 		if (memcmp(p, marker, sizeof(marker)) != 0) {
1826 			p++;
1827 			continue;
1828 		}
1829 
1830 		/* found BGP header */
1831 		TCHECK2(p[0], BGP_SIZE);	/*XXX*/
1832 		memcpy(&bgp, p, BGP_SIZE);
1833 
1834 		if (start != p)
1835 			printf(" [|BGP]");
1836 
1837 		hlen = ntohs(bgp.bgp_len);
1838 		if (hlen < BGP_SIZE) {
1839 			printf("\n[|BGP Bogus header length %u < %u]", hlen,
1840 			    BGP_SIZE);
1841 			break;
1842 		}
1843 
1844 		if (TTEST2(p[0], hlen)) {
1845 			if (!bgp_header_print(p, hlen))
1846 				return;
1847 			p += hlen;
1848 			start = p;
1849 		} else {
1850 			printf("\n[|BGP %s]", tok2str(bgp_msg_values, "Unknown Message Type",bgp.bgp_type));
1851 			break;
1852 		}
1853 	}
1854 
1855 	return;
1856 
1857 trunc:
1858 	printf(" [|BGP]");
1859 }
1860