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