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/* \summary: Border Gateway Protocol (BGP) printer */
34
35#ifdef HAVE_CONFIG_H
36#include "config.h"
37#endif
38
39#include <netdissect-stdinc.h>
40
41#include <stdio.h>
42#include <string.h>
43
44#include "netdissect.h"
45#include "addrtoname.h"
46#include "extract.h"
47#include "af.h"
48#include "l2vpn.h"
49
50struct bgp {
51	uint8_t bgp_marker[16];
52	uint16_t bgp_len;
53	uint8_t bgp_type;
54};
55#define BGP_SIZE		19	/* unaligned */
56
57#define BGP_OPEN		1
58#define BGP_UPDATE		2
59#define BGP_NOTIFICATION	3
60#define BGP_KEEPALIVE		4
61#define BGP_ROUTE_REFRESH       5
62
63static const struct tok bgp_msg_values[] = {
64    { BGP_OPEN,                 "Open"},
65    { BGP_UPDATE,               "Update"},
66    { BGP_NOTIFICATION,         "Notification"},
67    { BGP_KEEPALIVE,            "Keepalive"},
68    { BGP_ROUTE_REFRESH,        "Route Refresh"},
69    { 0, NULL}
70};
71
72struct bgp_open {
73	uint8_t bgpo_marker[16];
74	uint16_t bgpo_len;
75	uint8_t bgpo_type;
76	uint8_t bgpo_version;
77	uint16_t bgpo_myas;
78	uint16_t bgpo_holdtime;
79	uint32_t bgpo_id;
80	uint8_t bgpo_optlen;
81	/* options should follow */
82};
83#define BGP_OPEN_SIZE		29	/* unaligned */
84
85struct bgp_opt {
86	uint8_t bgpopt_type;
87	uint8_t bgpopt_len;
88	/* variable length */
89};
90#define BGP_OPT_SIZE		2	/* some compilers may pad to 4 bytes */
91#define BGP_CAP_HEADER_SIZE	2	/* some compilers may pad to 4 bytes */
92
93struct bgp_notification {
94	uint8_t bgpn_marker[16];
95	uint16_t bgpn_len;
96	uint8_t bgpn_type;
97	uint8_t bgpn_major;
98	uint8_t bgpn_minor;
99};
100#define BGP_NOTIFICATION_SIZE		21	/* unaligned */
101
102struct bgp_route_refresh {
103    uint8_t  bgp_marker[16];
104    uint16_t len;
105    uint8_t  type;
106    uint8_t  afi[2]; /* the compiler messes this structure up               */
107    uint8_t  res;    /* when doing misaligned sequences of int8 and int16   */
108    uint8_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#define bgp_attr_lenlen(flags, p) \
113	(((flags) & 0x10) ? 2 : 1)
114#define bgp_attr_len(flags, p) \
115	(((flags) & 0x10) ? EXTRACT_16BITS(p) : *(p))
116
117#define BGPTYPE_ORIGIN			1
118#define BGPTYPE_AS_PATH			2
119#define BGPTYPE_NEXT_HOP		3
120#define BGPTYPE_MULTI_EXIT_DISC		4
121#define BGPTYPE_LOCAL_PREF		5
122#define BGPTYPE_ATOMIC_AGGREGATE	6
123#define BGPTYPE_AGGREGATOR		7
124#define	BGPTYPE_COMMUNITIES		8	/* RFC1997 */
125#define	BGPTYPE_ORIGINATOR_ID		9	/* RFC4456 */
126#define	BGPTYPE_CLUSTER_LIST		10	/* RFC4456 */
127#define	BGPTYPE_DPA			11	/* deprecated, draft-ietf-idr-bgp-dpa */
128#define	BGPTYPE_ADVERTISERS		12	/* deprecated RFC1863 */
129#define	BGPTYPE_RCID_PATH		13	/* deprecated RFC1863 */
130#define BGPTYPE_MP_REACH_NLRI		14	/* RFC4760 */
131#define BGPTYPE_MP_UNREACH_NLRI		15	/* RFC4760 */
132#define BGPTYPE_EXTD_COMMUNITIES        16      /* RFC4360 */
133#define BGPTYPE_AS4_PATH	        17      /* RFC6793 */
134#define BGPTYPE_AGGREGATOR4		18      /* RFC6793 */
135#define BGPTYPE_PMSI_TUNNEL             22      /* RFC6514 */
136#define BGPTYPE_TUNNEL_ENCAP            23      /* RFC5512 */
137#define BGPTYPE_TRAFFIC_ENG             24      /* RFC5543 */
138#define BGPTYPE_IPV6_EXTD_COMMUNITIES   25      /* RFC5701 */
139#define BGPTYPE_AIGP                    26      /* RFC7311 */
140#define BGPTYPE_PE_DISTINGUISHER_LABEL  27      /* RFC6514 */
141#define BGPTYPE_ENTROPY_LABEL           28      /* RFC6790 */
142#define BGPTYPE_LARGE_COMMUNITY		32	/* draft-ietf-idr-large-community-05 */
143#define BGPTYPE_ATTR_SET               128      /* RFC6368 */
144
145#define BGP_MP_NLRI_MINSIZE              3       /* End of RIB Marker detection */
146
147static const struct tok bgp_attr_values[] = {
148    { BGPTYPE_ORIGIN,           "Origin"},
149    { BGPTYPE_AS_PATH,          "AS Path"},
150    { BGPTYPE_AS4_PATH,         "AS4 Path"},
151    { BGPTYPE_NEXT_HOP,         "Next Hop"},
152    { BGPTYPE_MULTI_EXIT_DISC,  "Multi Exit Discriminator"},
153    { BGPTYPE_LOCAL_PREF,       "Local Preference"},
154    { BGPTYPE_ATOMIC_AGGREGATE, "Atomic Aggregate"},
155    { BGPTYPE_AGGREGATOR,       "Aggregator"},
156    { BGPTYPE_AGGREGATOR4,      "Aggregator4"},
157    { BGPTYPE_COMMUNITIES,      "Community"},
158    { BGPTYPE_ORIGINATOR_ID,    "Originator ID"},
159    { BGPTYPE_CLUSTER_LIST,     "Cluster List"},
160    { BGPTYPE_DPA,              "DPA"},
161    { BGPTYPE_ADVERTISERS,      "Advertisers"},
162    { BGPTYPE_RCID_PATH,        "RCID Path / Cluster ID"},
163    { BGPTYPE_MP_REACH_NLRI,    "Multi-Protocol Reach NLRI"},
164    { BGPTYPE_MP_UNREACH_NLRI,  "Multi-Protocol Unreach NLRI"},
165    { BGPTYPE_EXTD_COMMUNITIES, "Extended Community"},
166    { BGPTYPE_PMSI_TUNNEL,      "PMSI Tunnel"},
167    { BGPTYPE_TUNNEL_ENCAP,     "Tunnel Encapsulation"},
168    { BGPTYPE_TRAFFIC_ENG,      "Traffic Engineering"},
169    { BGPTYPE_IPV6_EXTD_COMMUNITIES, "IPv6 Extended Community"},
170    { BGPTYPE_AIGP,             "Accumulated IGP Metric"},
171    { BGPTYPE_PE_DISTINGUISHER_LABEL, "PE Distinguisher Label"},
172    { BGPTYPE_ENTROPY_LABEL,    "Entropy Label"},
173    { BGPTYPE_LARGE_COMMUNITY,  "Large Community"},
174    { BGPTYPE_ATTR_SET,         "Attribute Set"},
175    { 255,                      "Reserved for development"},
176    { 0, NULL}
177};
178
179#define BGP_AS_SET             1
180#define BGP_AS_SEQUENCE        2
181#define BGP_CONFED_AS_SEQUENCE 3 /* draft-ietf-idr-rfc3065bis-01 */
182#define BGP_CONFED_AS_SET      4 /* draft-ietf-idr-rfc3065bis-01  */
183
184#define BGP_AS_SEG_TYPE_MIN    BGP_AS_SET
185#define BGP_AS_SEG_TYPE_MAX    BGP_CONFED_AS_SET
186
187static const struct tok bgp_as_path_segment_open_values[] = {
188    { BGP_AS_SEQUENCE,         ""},
189    { BGP_AS_SET,              "{ "},
190    { BGP_CONFED_AS_SEQUENCE,  "( "},
191    { BGP_CONFED_AS_SET,       "({ "},
192    { 0, NULL}
193};
194
195static const struct tok bgp_as_path_segment_close_values[] = {
196    { BGP_AS_SEQUENCE,         ""},
197    { BGP_AS_SET,              "}"},
198    { BGP_CONFED_AS_SEQUENCE,  ")"},
199    { BGP_CONFED_AS_SET,       "})"},
200    { 0, NULL}
201};
202
203#define BGP_OPT_AUTH                    1
204#define BGP_OPT_CAP                     2
205
206static const struct tok bgp_opt_values[] = {
207    { BGP_OPT_AUTH,             "Authentication Information"},
208    { BGP_OPT_CAP,              "Capabilities Advertisement"},
209    { 0, NULL}
210};
211
212#define BGP_CAPCODE_MP                  1 /* RFC2858 */
213#define BGP_CAPCODE_RR                  2 /* RFC2918 */
214#define BGP_CAPCODE_ORF                 3 /* RFC5291 */
215#define BGP_CAPCODE_MR                  4 /* RFC3107 */
216#define BGP_CAPCODE_EXT_NH              5 /* RFC5549 */
217#define BGP_CAPCODE_RESTART            64 /* RFC4724  */
218#define BGP_CAPCODE_AS_NEW             65 /* RFC6793 */
219#define BGP_CAPCODE_DYN_CAP            67 /* draft-ietf-idr-dynamic-cap */
220#define BGP_CAPCODE_MULTISESS          68 /* draft-ietf-idr-bgp-multisession */
221#define BGP_CAPCODE_ADD_PATH           69 /* RFC7911 */
222#define BGP_CAPCODE_ENH_RR             70 /* draft-keyur-bgp-enhanced-route-refresh */
223#define BGP_CAPCODE_RR_CISCO          128
224
225static const struct tok bgp_capcode_values[] = {
226    { BGP_CAPCODE_MP,           "Multiprotocol Extensions"},
227    { BGP_CAPCODE_RR,           "Route Refresh"},
228    { BGP_CAPCODE_ORF,          "Cooperative Route Filtering"},
229    { BGP_CAPCODE_MR,           "Multiple Routes to a Destination"},
230    { BGP_CAPCODE_EXT_NH,       "Extended Next Hop Encoding"},
231    { BGP_CAPCODE_RESTART,      "Graceful Restart"},
232    { BGP_CAPCODE_AS_NEW,       "32-Bit AS Number"},
233    { BGP_CAPCODE_DYN_CAP,      "Dynamic Capability"},
234    { BGP_CAPCODE_MULTISESS,    "Multisession BGP"},
235    { BGP_CAPCODE_ADD_PATH,     "Multiple Paths"},
236    { BGP_CAPCODE_ENH_RR,       "Enhanced Route Refresh"},
237    { BGP_CAPCODE_RR_CISCO,     "Route Refresh (Cisco)"},
238    { 0, NULL}
239};
240
241#define BGP_NOTIFY_MAJOR_MSG            1
242#define BGP_NOTIFY_MAJOR_OPEN           2
243#define BGP_NOTIFY_MAJOR_UPDATE         3
244#define BGP_NOTIFY_MAJOR_HOLDTIME       4
245#define BGP_NOTIFY_MAJOR_FSM            5
246#define BGP_NOTIFY_MAJOR_CEASE          6
247#define BGP_NOTIFY_MAJOR_CAP            7
248
249static const struct tok bgp_notify_major_values[] = {
250    { BGP_NOTIFY_MAJOR_MSG,     "Message Header Error"},
251    { BGP_NOTIFY_MAJOR_OPEN,    "OPEN Message Error"},
252    { BGP_NOTIFY_MAJOR_UPDATE,  "UPDATE Message Error"},
253    { BGP_NOTIFY_MAJOR_HOLDTIME,"Hold Timer Expired"},
254    { BGP_NOTIFY_MAJOR_FSM,     "Finite State Machine Error"},
255    { BGP_NOTIFY_MAJOR_CEASE,   "Cease"},
256    { BGP_NOTIFY_MAJOR_CAP,     "Capability Message Error"},
257    { 0, NULL}
258};
259
260/* draft-ietf-idr-cease-subcode-02 */
261#define BGP_NOTIFY_MINOR_CEASE_MAXPRFX  1
262static const struct tok bgp_notify_minor_cease_values[] = {
263    { BGP_NOTIFY_MINOR_CEASE_MAXPRFX, "Maximum Number of Prefixes Reached"},
264    { 2,                        "Administratively Shutdown"},
265    { 3,                        "Peer Unconfigured"},
266    { 4,                        "Administratively Reset"},
267    { 5,                        "Connection Rejected"},
268    { 6,                        "Other Configuration Change"},
269    { 7,                        "Connection Collision Resolution"},
270    { 0, NULL}
271};
272
273static const struct tok bgp_notify_minor_msg_values[] = {
274    { 1,                        "Connection Not Synchronized"},
275    { 2,                        "Bad Message Length"},
276    { 3,                        "Bad Message Type"},
277    { 0, NULL}
278};
279
280static const struct tok bgp_notify_minor_open_values[] = {
281    { 1,                        "Unsupported Version Number"},
282    { 2,                        "Bad Peer AS"},
283    { 3,                        "Bad BGP Identifier"},
284    { 4,                        "Unsupported Optional Parameter"},
285    { 5,                        "Authentication Failure"},
286    { 6,                        "Unacceptable Hold Time"},
287    { 7,                        "Capability Message Error"},
288    { 0, NULL}
289};
290
291static const struct tok bgp_notify_minor_update_values[] = {
292    { 1,                        "Malformed Attribute List"},
293    { 2,                        "Unrecognized Well-known Attribute"},
294    { 3,                        "Missing Well-known Attribute"},
295    { 4,                        "Attribute Flags Error"},
296    { 5,                        "Attribute Length Error"},
297    { 6,                        "Invalid ORIGIN Attribute"},
298    { 7,                        "AS Routing Loop"},
299    { 8,                        "Invalid NEXT_HOP Attribute"},
300    { 9,                        "Optional Attribute Error"},
301    { 10,                       "Invalid Network Field"},
302    { 11,                       "Malformed AS_PATH"},
303    { 0, NULL}
304};
305
306static const struct tok bgp_notify_minor_fsm_values[] = {
307    { 1,                        "In OpenSent State"},
308    { 2,                        "In OpenConfirm State"},
309    { 3,                        "In Established State"},
310    { 0, NULL }
311};
312
313static const struct tok bgp_notify_minor_cap_values[] = {
314    { 1,                        "Invalid Action Value" },
315    { 2,                        "Invalid Capability Length" },
316    { 3,                        "Malformed Capability Value" },
317    { 4,                        "Unsupported Capability Code" },
318    { 0, NULL }
319};
320
321static const struct tok bgp_origin_values[] = {
322    { 0,                        "IGP"},
323    { 1,                        "EGP"},
324    { 2,                        "Incomplete"},
325    { 0, NULL}
326};
327
328#define BGP_PMSI_TUNNEL_RSVP_P2MP 1
329#define BGP_PMSI_TUNNEL_LDP_P2MP  2
330#define BGP_PMSI_TUNNEL_PIM_SSM   3
331#define BGP_PMSI_TUNNEL_PIM_SM    4
332#define BGP_PMSI_TUNNEL_PIM_BIDIR 5
333#define BGP_PMSI_TUNNEL_INGRESS   6
334#define BGP_PMSI_TUNNEL_LDP_MP2MP 7
335
336static const struct tok bgp_pmsi_tunnel_values[] = {
337    { BGP_PMSI_TUNNEL_RSVP_P2MP, "RSVP-TE P2MP LSP"},
338    { BGP_PMSI_TUNNEL_LDP_P2MP, "LDP P2MP LSP"},
339    { BGP_PMSI_TUNNEL_PIM_SSM, "PIM-SSM Tree"},
340    { BGP_PMSI_TUNNEL_PIM_SM, "PIM-SM Tree"},
341    { BGP_PMSI_TUNNEL_PIM_BIDIR, "PIM-Bidir Tree"},
342    { BGP_PMSI_TUNNEL_INGRESS, "Ingress Replication"},
343    { BGP_PMSI_TUNNEL_LDP_MP2MP, "LDP MP2MP LSP"},
344    { 0, NULL}
345};
346
347static const struct tok bgp_pmsi_flag_values[] = {
348    { 0x01, "Leaf Information required"},
349    { 0, NULL}
350};
351
352#define BGP_AIGP_TLV 1
353
354static const struct tok bgp_aigp_values[] = {
355    { BGP_AIGP_TLV, "AIGP"},
356    { 0, NULL}
357};
358
359/* Subsequent address family identifier, RFC2283 section 7 */
360#define SAFNUM_RES                      0
361#define SAFNUM_UNICAST                  1
362#define SAFNUM_MULTICAST                2
363#define SAFNUM_UNIMULTICAST             3       /* deprecated now */
364/* labeled BGP RFC3107 */
365#define SAFNUM_LABUNICAST               4
366/* RFC6514 */
367#define SAFNUM_MULTICAST_VPN            5
368/* draft-nalawade-kapoor-tunnel-safi */
369#define SAFNUM_TUNNEL                   64
370/* RFC4761 */
371#define SAFNUM_VPLS                     65
372/* RFC6037 */
373#define SAFNUM_MDT                      66
374/* RFC4364 */
375#define SAFNUM_VPNUNICAST               128
376/* RFC6513 */
377#define SAFNUM_VPNMULTICAST             129
378#define SAFNUM_VPNUNIMULTICAST          130     /* deprecated now */
379/* RFC4684 */
380#define SAFNUM_RT_ROUTING_INFO          132
381
382#define BGP_VPN_RD_LEN                  8
383
384static const struct tok bgp_safi_values[] = {
385    { SAFNUM_RES,               "Reserved"},
386    { SAFNUM_UNICAST,           "Unicast"},
387    { SAFNUM_MULTICAST,         "Multicast"},
388    { SAFNUM_UNIMULTICAST,      "Unicast+Multicast"},
389    { SAFNUM_LABUNICAST,        "labeled Unicast"},
390    { SAFNUM_TUNNEL,            "Tunnel"},
391    { SAFNUM_VPLS,              "VPLS"},
392    { SAFNUM_MDT,               "MDT"},
393    { SAFNUM_VPNUNICAST,        "labeled VPN Unicast"},
394    { SAFNUM_VPNMULTICAST,      "labeled VPN Multicast"},
395    { SAFNUM_VPNUNIMULTICAST,   "labeled VPN Unicast+Multicast"},
396    { SAFNUM_RT_ROUTING_INFO,   "Route Target Routing Information"},
397    { SAFNUM_MULTICAST_VPN,     "Multicast VPN"},
398    { 0, NULL }
399};
400
401/* well-known community */
402#define BGP_COMMUNITY_NO_EXPORT			0xffffff01
403#define BGP_COMMUNITY_NO_ADVERT			0xffffff02
404#define BGP_COMMUNITY_NO_EXPORT_SUBCONFED	0xffffff03
405
406/* Extended community type - draft-ietf-idr-bgp-ext-communities-05 */
407#define BGP_EXT_COM_RT_0        0x0002  /* Route Target,Format AS(2bytes):AN(4bytes) */
408#define BGP_EXT_COM_RT_1        0x0102  /* Route Target,Format IP address:AN(2bytes) */
409#define BGP_EXT_COM_RT_2        0x0202  /* Route Target,Format AN(4bytes):local(2bytes) */
410#define BGP_EXT_COM_RO_0        0x0003  /* Route Origin,Format AS(2bytes):AN(4bytes) */
411#define BGP_EXT_COM_RO_1        0x0103  /* Route Origin,Format IP address:AN(2bytes) */
412#define BGP_EXT_COM_RO_2        0x0203  /* Route Origin,Format AN(4bytes):local(2bytes) */
413#define BGP_EXT_COM_LINKBAND    0x4004  /* Link Bandwidth,Format AS(2B):Bandwidth(4B) */
414                                        /* rfc2547 bgp-mpls-vpns */
415#define BGP_EXT_COM_VPN_ORIGIN  0x0005  /* OSPF Domain ID / VPN of Origin  - draft-rosen-vpns-ospf-bgp-mpls */
416#define BGP_EXT_COM_VPN_ORIGIN2 0x0105  /* duplicate - keep for backwards compatability */
417#define BGP_EXT_COM_VPN_ORIGIN3 0x0205  /* duplicate - keep for backwards compatability */
418#define BGP_EXT_COM_VPN_ORIGIN4 0x8005  /* duplicate - keep for backwards compatability */
419
420#define BGP_EXT_COM_OSPF_RTYPE  0x0306  /* OSPF Route Type,Format Area(4B):RouteType(1B):Options(1B) */
421#define BGP_EXT_COM_OSPF_RTYPE2 0x8000  /* duplicate - keep for backwards compatability */
422
423#define BGP_EXT_COM_OSPF_RID    0x0107  /* OSPF Router ID,Format RouterID(4B):Unused(2B) */
424#define BGP_EXT_COM_OSPF_RID2   0x8001  /* duplicate - keep for backwards compatability */
425
426#define BGP_EXT_COM_L2INFO      0x800a  /* draft-kompella-ppvpn-l2vpn */
427
428#define BGP_EXT_COM_SOURCE_AS   0x0009  /* RFC-ietf-l3vpn-2547bis-mcast-bgp-08.txt */
429#define BGP_EXT_COM_VRF_RT_IMP  0x010b  /* RFC-ietf-l3vpn-2547bis-mcast-bgp-08.txt */
430#define BGP_EXT_COM_L2VPN_RT_0  0x000a  /* L2VPN Identifier,Format AS(2bytes):AN(4bytes) */
431#define BGP_EXT_COM_L2VPN_RT_1  0xF10a  /* L2VPN Identifier,Format IP address:AN(2bytes) */
432
433/* http://www.cisco.com/en/US/tech/tk436/tk428/technologies_tech_note09186a00801eb09a.shtml  */
434#define BGP_EXT_COM_EIGRP_GEN   0x8800
435#define BGP_EXT_COM_EIGRP_METRIC_AS_DELAY  0x8801
436#define BGP_EXT_COM_EIGRP_METRIC_REL_NH_BW 0x8802
437#define BGP_EXT_COM_EIGRP_METRIC_LOAD_MTU  0x8803
438#define BGP_EXT_COM_EIGRP_EXT_REMAS_REMID  0x8804
439#define BGP_EXT_COM_EIGRP_EXT_REMPROTO_REMMETRIC 0x8805
440
441static const struct tok bgp_extd_comm_flag_values[] = {
442    { 0x8000,                  "vendor-specific"},
443    { 0x4000,                  "non-transitive"},
444    { 0, NULL},
445};
446
447static const struct tok bgp_extd_comm_subtype_values[] = {
448    { BGP_EXT_COM_RT_0,        "target"},
449    { BGP_EXT_COM_RT_1,        "target"},
450    { BGP_EXT_COM_RT_2,        "target"},
451    { BGP_EXT_COM_RO_0,        "origin"},
452    { BGP_EXT_COM_RO_1,        "origin"},
453    { BGP_EXT_COM_RO_2,        "origin"},
454    { BGP_EXT_COM_LINKBAND,    "link-BW"},
455    { BGP_EXT_COM_VPN_ORIGIN,  "ospf-domain"},
456    { BGP_EXT_COM_VPN_ORIGIN2, "ospf-domain"},
457    { BGP_EXT_COM_VPN_ORIGIN3, "ospf-domain"},
458    { BGP_EXT_COM_VPN_ORIGIN4, "ospf-domain"},
459    { BGP_EXT_COM_OSPF_RTYPE,  "ospf-route-type"},
460    { BGP_EXT_COM_OSPF_RTYPE2, "ospf-route-type"},
461    { BGP_EXT_COM_OSPF_RID,    "ospf-router-id"},
462    { BGP_EXT_COM_OSPF_RID2,   "ospf-router-id"},
463    { BGP_EXT_COM_L2INFO,      "layer2-info"},
464    { BGP_EXT_COM_EIGRP_GEN , "eigrp-general-route (flag, tag)" },
465    { BGP_EXT_COM_EIGRP_METRIC_AS_DELAY , "eigrp-route-metric (AS, delay)" },
466    { BGP_EXT_COM_EIGRP_METRIC_REL_NH_BW , "eigrp-route-metric (reliability, nexthop, bandwidth)" },
467    { BGP_EXT_COM_EIGRP_METRIC_LOAD_MTU , "eigrp-route-metric (load, MTU)" },
468    { BGP_EXT_COM_EIGRP_EXT_REMAS_REMID , "eigrp-external-route (remote-AS, remote-ID)" },
469    { BGP_EXT_COM_EIGRP_EXT_REMPROTO_REMMETRIC , "eigrp-external-route (remote-proto, remote-metric)" },
470    { BGP_EXT_COM_SOURCE_AS, "source-AS" },
471    { BGP_EXT_COM_VRF_RT_IMP, "vrf-route-import"},
472    { BGP_EXT_COM_L2VPN_RT_0, "l2vpn-id"},
473    { BGP_EXT_COM_L2VPN_RT_1, "l2vpn-id"},
474    { 0, NULL},
475};
476
477/* OSPF codes for  BGP_EXT_COM_OSPF_RTYPE draft-rosen-vpns-ospf-bgp-mpls  */
478#define BGP_OSPF_RTYPE_RTR      1 /* OSPF Router LSA */
479#define BGP_OSPF_RTYPE_NET      2 /* OSPF Network LSA */
480#define BGP_OSPF_RTYPE_SUM      3 /* OSPF Summary LSA */
481#define BGP_OSPF_RTYPE_EXT      5 /* OSPF External LSA, note that ASBR doesn't apply to MPLS-VPN */
482#define BGP_OSPF_RTYPE_NSSA     7 /* OSPF NSSA External*/
483#define BGP_OSPF_RTYPE_SHAM     129 /* OSPF-MPLS-VPN Sham link */
484#define BGP_OSPF_RTYPE_METRIC_TYPE 0x1 /* LSB of RTYPE Options Field */
485
486static const struct tok bgp_extd_comm_ospf_rtype_values[] = {
487  { BGP_OSPF_RTYPE_RTR, "Router" },
488  { BGP_OSPF_RTYPE_NET, "Network" },
489  { BGP_OSPF_RTYPE_SUM, "Summary" },
490  { BGP_OSPF_RTYPE_EXT, "External" },
491  { BGP_OSPF_RTYPE_NSSA,"NSSA External" },
492  { BGP_OSPF_RTYPE_SHAM,"MPLS-VPN Sham" },
493  { 0, NULL },
494};
495
496/* ADD-PATH Send/Receive field values */
497static const struct tok bgp_add_path_recvsend[] = {
498  { 1, "Receive" },
499  { 2, "Send" },
500  { 3, "Both" },
501  { 0, NULL },
502};
503
504static char astostr[20];
505
506/*
507 * as_printf
508 *
509 * Convert an AS number into a string and return string pointer.
510 *
511 * Depending on bflag is set or not, AS number is converted into ASDOT notation
512 * or plain number notation.
513 *
514 */
515static char *
516as_printf(netdissect_options *ndo,
517          char *str, int size, u_int asnum)
518{
519	if (!ndo->ndo_bflag || asnum <= 0xFFFF) {
520		snprintf(str, size, "%u", asnum);
521	} else {
522		snprintf(str, size, "%u.%u", asnum >> 16, asnum & 0xFFFF);
523	}
524	return str;
525}
526
527#define ITEMCHECK(minlen) if (itemlen < minlen) goto badtlv;
528
529int
530decode_prefix4(netdissect_options *ndo,
531               const u_char *pptr, u_int itemlen, char *buf, u_int buflen)
532{
533	struct in_addr addr;
534	u_int plen, plenbytes;
535
536	ND_TCHECK(pptr[0]);
537	ITEMCHECK(1);
538	plen = pptr[0];
539	if (32 < plen)
540		return -1;
541	itemlen -= 1;
542
543	memset(&addr, 0, sizeof(addr));
544	plenbytes = (plen + 7) / 8;
545	ND_TCHECK2(pptr[1], plenbytes);
546	ITEMCHECK(plenbytes);
547	memcpy(&addr, &pptr[1], plenbytes);
548	if (plen % 8) {
549		((u_char *)&addr)[plenbytes - 1] &=
550			((0xff00 >> (plen % 8)) & 0xff);
551	}
552	snprintf(buf, buflen, "%s/%d", ipaddr_string(ndo, &addr), plen);
553	return 1 + plenbytes;
554
555trunc:
556	return -2;
557
558badtlv:
559	return -3;
560}
561
562static int
563decode_labeled_prefix4(netdissect_options *ndo,
564                       const u_char *pptr, u_int itemlen, char *buf, u_int buflen)
565{
566	struct in_addr addr;
567	u_int plen, plenbytes;
568
569	/* prefix length and label = 4 bytes */
570	ND_TCHECK2(pptr[0], 4);
571	ITEMCHECK(4);
572	plen = pptr[0];   /* get prefix length */
573
574        /* this is one of the weirdnesses of rfc3107
575           the label length (actually the label + COS bits)
576           is added to the prefix length;
577           we also do only read out just one label -
578           there is no real application for advertisement of
579           stacked labels in a single BGP message
580        */
581
582	if (24 > plen)
583		return -1;
584
585        plen-=24; /* adjust prefixlen - labellength */
586
587	if (32 < plen)
588		return -1;
589	itemlen -= 4;
590
591	memset(&addr, 0, sizeof(addr));
592	plenbytes = (plen + 7) / 8;
593	ND_TCHECK2(pptr[4], plenbytes);
594	ITEMCHECK(plenbytes);
595	memcpy(&addr, &pptr[4], plenbytes);
596	if (plen % 8) {
597		((u_char *)&addr)[plenbytes - 1] &=
598			((0xff00 >> (plen % 8)) & 0xff);
599	}
600        /* the label may get offsetted by 4 bits so lets shift it right */
601	snprintf(buf, buflen, "%s/%d, label:%u %s",
602                 ipaddr_string(ndo, &addr),
603                 plen,
604                 EXTRACT_24BITS(pptr+1)>>4,
605                 ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
606
607	return 4 + plenbytes;
608
609trunc:
610	return -2;
611
612badtlv:
613	return -3;
614}
615
616/*
617 * bgp_vpn_ip_print
618 *
619 * print an ipv4 or ipv6 address into a buffer dependend on address length.
620 */
621static char *
622bgp_vpn_ip_print(netdissect_options *ndo,
623                 const u_char *pptr, u_int addr_length)
624{
625
626    /* worst case string is s fully formatted v6 address */
627    static char addr[sizeof("1234:5678:89ab:cdef:1234:5678:89ab:cdef")];
628    char *pos = addr;
629
630    switch(addr_length) {
631    case (sizeof(struct in_addr) << 3): /* 32 */
632        ND_TCHECK2(pptr[0], sizeof(struct in_addr));
633        snprintf(pos, sizeof(addr), "%s", ipaddr_string(ndo, pptr));
634        break;
635    case (sizeof(struct in6_addr) << 3): /* 128 */
636        ND_TCHECK2(pptr[0], sizeof(struct in6_addr));
637        snprintf(pos, sizeof(addr), "%s", ip6addr_string(ndo, pptr));
638        break;
639    default:
640        snprintf(pos, sizeof(addr), "bogus address length %u", addr_length);
641        break;
642    }
643    pos += strlen(pos);
644
645trunc:
646    *(pos) = '\0';
647    return (addr);
648}
649
650/*
651 * bgp_vpn_sg_print
652 *
653 * print an multicast s,g entry into a buffer.
654 * the s,g entry is encoded like this.
655 *
656 * +-----------------------------------+
657 * | Multicast Source Length (1 octet) |
658 * +-----------------------------------+
659 * |   Multicast Source (Variable)     |
660 * +-----------------------------------+
661 * |  Multicast Group Length (1 octet) |
662 * +-----------------------------------+
663 * |  Multicast Group   (Variable)     |
664 * +-----------------------------------+
665 *
666 * return the number of bytes read from the wire.
667 */
668static int
669bgp_vpn_sg_print(netdissect_options *ndo,
670                 const u_char *pptr, char *buf, u_int buflen)
671{
672    uint8_t addr_length;
673    u_int total_length, offset;
674
675    total_length = 0;
676
677    /* Source address length, encoded in bits */
678    ND_TCHECK2(pptr[0], 1);
679    addr_length =  *pptr++;
680
681    /* Source address */
682    ND_TCHECK2(pptr[0], (addr_length >> 3));
683    total_length += (addr_length >> 3) + 1;
684    offset = strlen(buf);
685    if (addr_length) {
686        snprintf(buf + offset, buflen - offset, ", Source %s",
687                 bgp_vpn_ip_print(ndo, pptr, addr_length));
688        pptr += (addr_length >> 3);
689    }
690
691    /* Group address length, encoded in bits */
692    ND_TCHECK2(pptr[0], 1);
693    addr_length =  *pptr++;
694
695    /* Group address */
696    ND_TCHECK2(pptr[0], (addr_length >> 3));
697    total_length += (addr_length >> 3) + 1;
698    offset = strlen(buf);
699    if (addr_length) {
700        snprintf(buf + offset, buflen - offset, ", Group %s",
701                 bgp_vpn_ip_print(ndo, pptr, addr_length));
702        pptr += (addr_length >> 3);
703    }
704
705trunc:
706    return (total_length);
707}
708
709/* RDs and RTs share the same semantics
710 * we use bgp_vpn_rd_print for
711 * printing route targets inside a NLRI */
712char *
713bgp_vpn_rd_print(netdissect_options *ndo,
714                 const u_char *pptr)
715{
716   /* allocate space for the largest possible string */
717    static char rd[sizeof("xxxxxxxxxx:xxxxx (xxx.xxx.xxx.xxx:xxxxx)")];
718    char *pos = rd;
719
720    /* ok lets load the RD format */
721    switch (EXTRACT_16BITS(pptr)) {
722
723        /* 2-byte-AS:number fmt*/
724    case 0:
725        snprintf(pos, sizeof(rd) - (pos - rd), "%u:%u (= %u.%u.%u.%u)",
726                 EXTRACT_16BITS(pptr+2),
727                 EXTRACT_32BITS(pptr+4),
728                 *(pptr+4), *(pptr+5), *(pptr+6), *(pptr+7));
729        break;
730        /* IP-address:AS fmt*/
731
732    case 1:
733        snprintf(pos, sizeof(rd) - (pos - rd), "%u.%u.%u.%u:%u",
734            *(pptr+2), *(pptr+3), *(pptr+4), *(pptr+5), EXTRACT_16BITS(pptr+6));
735        break;
736
737        /* 4-byte-AS:number fmt*/
738    case 2:
739	snprintf(pos, sizeof(rd) - (pos - rd), "%s:%u (%u.%u.%u.%u:%u)",
740	    as_printf(ndo, astostr, sizeof(astostr), EXTRACT_32BITS(pptr+2)),
741	    EXTRACT_16BITS(pptr+6), *(pptr+2), *(pptr+3), *(pptr+4),
742	    *(pptr+5), EXTRACT_16BITS(pptr+6));
743        break;
744    default:
745        snprintf(pos, sizeof(rd) - (pos - rd), "unknown RD format");
746        break;
747    }
748    pos += strlen(pos);
749    *(pos) = '\0';
750    return (rd);
751}
752
753static int
754decode_rt_routing_info(netdissect_options *ndo,
755                       const u_char *pptr, char *buf, u_int buflen)
756{
757	uint8_t route_target[8];
758	u_int plen;
759
760	ND_TCHECK(pptr[0]);
761	plen = pptr[0];   /* get prefix length */
762
763	if (0 == plen) {
764		snprintf(buf, buflen, "default route target");
765		return 1;
766	}
767
768	if (32 > plen)
769		return -1;
770
771        plen-=32; /* adjust prefix length */
772
773	if (64 < plen)
774		return -1;
775
776	memset(&route_target, 0, sizeof(route_target));
777	ND_TCHECK2(pptr[1], (plen + 7) / 8);
778	memcpy(&route_target, &pptr[1], (plen + 7) / 8);
779	if (plen % 8) {
780		((u_char *)&route_target)[(plen + 7) / 8 - 1] &=
781			((0xff00 >> (plen % 8)) & 0xff);
782	}
783	snprintf(buf, buflen, "origin AS: %s, route target %s",
784	    as_printf(ndo, astostr, sizeof(astostr), EXTRACT_32BITS(pptr+1)),
785	    bgp_vpn_rd_print(ndo, (u_char *)&route_target));
786
787	return 5 + (plen + 7) / 8;
788
789trunc:
790	return -2;
791}
792
793static int
794decode_labeled_vpn_prefix4(netdissect_options *ndo,
795                           const u_char *pptr, char *buf, u_int buflen)
796{
797	struct in_addr addr;
798	u_int plen;
799
800	ND_TCHECK(pptr[0]);
801	plen = pptr[0];   /* get prefix length */
802
803	if ((24+64) > plen)
804		return -1;
805
806        plen-=(24+64); /* adjust prefixlen - labellength - RD len*/
807
808	if (32 < plen)
809		return -1;
810
811	memset(&addr, 0, sizeof(addr));
812	ND_TCHECK2(pptr[12], (plen + 7) / 8);
813	memcpy(&addr, &pptr[12], (plen + 7) / 8);
814	if (plen % 8) {
815		((u_char *)&addr)[(plen + 7) / 8 - 1] &=
816			((0xff00 >> (plen % 8)) & 0xff);
817	}
818        /* the label may get offsetted by 4 bits so lets shift it right */
819	snprintf(buf, buflen, "RD: %s, %s/%d, label:%u %s",
820                 bgp_vpn_rd_print(ndo, pptr+4),
821                 ipaddr_string(ndo, &addr),
822                 plen,
823                 EXTRACT_24BITS(pptr+1)>>4,
824                 ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
825
826	return 12 + (plen + 7) / 8;
827
828trunc:
829	return -2;
830}
831
832/*
833 * +-------------------------------+
834 * |                               |
835 * |  RD:IPv4-address (12 octets)  |
836 * |                               |
837 * +-------------------------------+
838 * |  MDT Group-address (4 octets) |
839 * +-------------------------------+
840 */
841
842#define MDT_VPN_NLRI_LEN 16
843
844static int
845decode_mdt_vpn_nlri(netdissect_options *ndo,
846                    const u_char *pptr, char *buf, u_int buflen)
847{
848
849    const u_char *rd;
850    const u_char *vpn_ip;
851
852    ND_TCHECK(pptr[0]);
853
854    /* if the NLRI is not predefined length, quit.*/
855    if (*pptr != MDT_VPN_NLRI_LEN * 8)
856	return -1;
857    pptr++;
858
859    /* RD */
860    ND_TCHECK2(pptr[0], 8);
861    rd = pptr;
862    pptr+=8;
863
864    /* IPv4 address */
865    ND_TCHECK2(pptr[0], sizeof(struct in_addr));
866    vpn_ip = pptr;
867    pptr+=sizeof(struct in_addr);
868
869    /* MDT Group Address */
870    ND_TCHECK2(pptr[0], sizeof(struct in_addr));
871
872    snprintf(buf, buflen, "RD: %s, VPN IP Address: %s, MC Group Address: %s",
873	     bgp_vpn_rd_print(ndo, rd), ipaddr_string(ndo, vpn_ip), ipaddr_string(ndo, pptr));
874
875    return MDT_VPN_NLRI_LEN + 1;
876
877 trunc:
878
879return -2;
880}
881
882#define BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_I_PMSI   1
883#define BGP_MULTICAST_VPN_ROUTE_TYPE_INTER_AS_I_PMSI   2
884#define BGP_MULTICAST_VPN_ROUTE_TYPE_S_PMSI            3
885#define BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_SEG_LEAF 4
886#define BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_ACTIVE     5
887#define BGP_MULTICAST_VPN_ROUTE_TYPE_SHARED_TREE_JOIN  6
888#define BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_TREE_JOIN  7
889
890static const struct tok bgp_multicast_vpn_route_type_values[] = {
891    { BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_I_PMSI, "Intra-AS I-PMSI"},
892    { BGP_MULTICAST_VPN_ROUTE_TYPE_INTER_AS_I_PMSI, "Inter-AS I-PMSI"},
893    { BGP_MULTICAST_VPN_ROUTE_TYPE_S_PMSI, "S-PMSI"},
894    { BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_SEG_LEAF, "Intra-AS Segment-Leaf"},
895    { BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_ACTIVE, "Source-Active"},
896    { BGP_MULTICAST_VPN_ROUTE_TYPE_SHARED_TREE_JOIN, "Shared Tree Join"},
897    { BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_TREE_JOIN, "Source Tree Join"},
898};
899
900static int
901decode_multicast_vpn(netdissect_options *ndo,
902                     const u_char *pptr, char *buf, u_int buflen)
903{
904        uint8_t route_type, route_length, addr_length, sg_length;
905        u_int offset;
906
907	ND_TCHECK2(pptr[0], 2);
908        route_type = *pptr++;
909        route_length = *pptr++;
910
911        snprintf(buf, buflen, "Route-Type: %s (%u), length: %u",
912                 tok2str(bgp_multicast_vpn_route_type_values,
913                         "Unknown", route_type),
914                 route_type, route_length);
915
916        switch(route_type) {
917        case BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_I_PMSI:
918            ND_TCHECK2(pptr[0], BGP_VPN_RD_LEN);
919            offset = strlen(buf);
920            snprintf(buf + offset, buflen - offset, ", RD: %s, Originator %s",
921                     bgp_vpn_rd_print(ndo, pptr),
922                     bgp_vpn_ip_print(ndo, pptr + BGP_VPN_RD_LEN,
923                                      (route_length - BGP_VPN_RD_LEN) << 3));
924            break;
925        case BGP_MULTICAST_VPN_ROUTE_TYPE_INTER_AS_I_PMSI:
926            ND_TCHECK2(pptr[0], BGP_VPN_RD_LEN + 4);
927            offset = strlen(buf);
928	    snprintf(buf + offset, buflen - offset, ", RD: %s, Source-AS %s",
929		bgp_vpn_rd_print(ndo, pptr),
930		as_printf(ndo, astostr, sizeof(astostr),
931		EXTRACT_32BITS(pptr + BGP_VPN_RD_LEN)));
932            break;
933
934        case BGP_MULTICAST_VPN_ROUTE_TYPE_S_PMSI:
935            ND_TCHECK2(pptr[0], BGP_VPN_RD_LEN);
936            offset = strlen(buf);
937            snprintf(buf + offset, buflen - offset, ", RD: %s",
938                     bgp_vpn_rd_print(ndo, pptr));
939            pptr += BGP_VPN_RD_LEN;
940
941            sg_length = bgp_vpn_sg_print(ndo, pptr, buf, buflen);
942            addr_length =  route_length - sg_length;
943
944            ND_TCHECK2(pptr[0], addr_length);
945            offset = strlen(buf);
946            snprintf(buf + offset, buflen - offset, ", Originator %s",
947                     bgp_vpn_ip_print(ndo, pptr, addr_length << 3));
948            break;
949
950        case BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_ACTIVE:
951            ND_TCHECK2(pptr[0], BGP_VPN_RD_LEN);
952            offset = strlen(buf);
953            snprintf(buf + offset, buflen - offset, ", RD: %s",
954                     bgp_vpn_rd_print(ndo, pptr));
955            pptr += BGP_VPN_RD_LEN;
956
957            bgp_vpn_sg_print(ndo, pptr, buf, buflen);
958            break;
959
960        case BGP_MULTICAST_VPN_ROUTE_TYPE_SHARED_TREE_JOIN: /* fall through */
961        case BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_TREE_JOIN:
962            ND_TCHECK2(pptr[0], BGP_VPN_RD_LEN);
963            offset = strlen(buf);
964	    snprintf(buf + offset, buflen - offset, ", RD: %s, Source-AS %s",
965		bgp_vpn_rd_print(ndo, pptr),
966		as_printf(ndo, astostr, sizeof(astostr),
967		EXTRACT_32BITS(pptr + BGP_VPN_RD_LEN)));
968            pptr += BGP_VPN_RD_LEN;
969
970            bgp_vpn_sg_print(ndo, pptr, buf, buflen);
971            break;
972
973            /*
974             * no per route-type printing yet.
975             */
976        case BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_SEG_LEAF:
977        default:
978            break;
979        }
980
981        return route_length + 2;
982
983trunc:
984	return -2;
985}
986
987/*
988 * As I remember, some versions of systems have an snprintf() that
989 * returns -1 if the buffer would have overflowed.  If the return
990 * value is negative, set buflen to 0, to indicate that we've filled
991 * the buffer up.
992 *
993 * If the return value is greater than buflen, that means that
994 * the buffer would have overflowed; again, set buflen to 0 in
995 * that case.
996 */
997#define UPDATE_BUF_BUFLEN(buf, buflen, stringlen) \
998    if (stringlen<0) \
999       	buflen=0; \
1000    else if ((u_int)stringlen>buflen) \
1001        buflen=0; \
1002    else { \
1003        buflen-=stringlen; \
1004	buf+=stringlen; \
1005    }
1006
1007static int
1008decode_labeled_vpn_l2(netdissect_options *ndo,
1009                      const u_char *pptr, char *buf, u_int buflen)
1010{
1011        int plen,tlen,stringlen,tlv_type,tlv_len,ttlv_len;
1012
1013	ND_TCHECK2(pptr[0], 2);
1014        plen=EXTRACT_16BITS(pptr);
1015        tlen=plen;
1016        pptr+=2;
1017	/* Old and new L2VPN NLRI share AFI/SAFI
1018         *   -> Assume a 12 Byte-length NLRI is auto-discovery-only
1019         *      and > 17 as old format. Complain for the middle case
1020         */
1021        if (plen==12) {
1022	    /* assume AD-only with RD, BGPNH */
1023	    ND_TCHECK2(pptr[0],12);
1024	    buf[0]='\0';
1025	    stringlen=snprintf(buf, buflen, "RD: %s, BGPNH: %s",
1026			       bgp_vpn_rd_print(ndo, pptr),
1027			       ipaddr_string(ndo, pptr+8)
1028			       );
1029	    UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
1030	    pptr+=12;
1031	    tlen-=12;
1032	    return plen;
1033        } else if (plen>17) {
1034	    /* assume old format */
1035	    /* RD, ID, LBLKOFF, LBLBASE */
1036
1037	    ND_TCHECK2(pptr[0],15);
1038	    buf[0]='\0';
1039	    stringlen=snprintf(buf, buflen, "RD: %s, CE-ID: %u, Label-Block Offset: %u, Label Base %u",
1040			       bgp_vpn_rd_print(ndo, pptr),
1041			       EXTRACT_16BITS(pptr+8),
1042			       EXTRACT_16BITS(pptr+10),
1043			       EXTRACT_24BITS(pptr+12)>>4); /* the label is offsetted by 4 bits so lets shift it right */
1044	    UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
1045	    pptr+=15;
1046	    tlen-=15;
1047
1048	    /* ok now the variable part - lets read out TLVs*/
1049	    while (tlen>0) {
1050		if (tlen < 3)
1051		    return -1;
1052		ND_TCHECK2(pptr[0], 3);
1053		tlv_type=*pptr++;
1054		tlv_len=EXTRACT_16BITS(pptr);
1055		ttlv_len=tlv_len;
1056		pptr+=2;
1057
1058		switch(tlv_type) {
1059		case 1:
1060		    if (buflen!=0) {
1061			stringlen=snprintf(buf,buflen, "\n\t\tcircuit status vector (%u) length: %u: 0x",
1062					   tlv_type,
1063					   tlv_len);
1064			UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
1065		    }
1066		    ttlv_len=ttlv_len/8+1; /* how many bytes do we need to read ? */
1067		    while (ttlv_len>0) {
1068			ND_TCHECK(pptr[0]);
1069			if (buflen!=0) {
1070			    stringlen=snprintf(buf,buflen, "%02x",*pptr++);
1071			    UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
1072			}
1073			ttlv_len--;
1074		    }
1075		    break;
1076		default:
1077		    if (buflen!=0) {
1078			stringlen=snprintf(buf,buflen, "\n\t\tunknown TLV #%u, length: %u",
1079					   tlv_type,
1080					   tlv_len);
1081			UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
1082		    }
1083		    break;
1084		}
1085		tlen-=(tlv_len<<3); /* the tlv-length is expressed in bits so lets shift it right */
1086	    }
1087	    return plen+2;
1088
1089        } else {
1090	    /* complain bitterly ? */
1091	    /* fall through */
1092            goto trunc;
1093        }
1094
1095trunc:
1096        return -2;
1097}
1098
1099int
1100decode_prefix6(netdissect_options *ndo,
1101               const u_char *pd, u_int itemlen, char *buf, u_int buflen)
1102{
1103	struct in6_addr addr;
1104	u_int plen, plenbytes;
1105
1106	ND_TCHECK(pd[0]);
1107	ITEMCHECK(1);
1108	plen = pd[0];
1109	if (128 < plen)
1110		return -1;
1111	itemlen -= 1;
1112
1113	memset(&addr, 0, sizeof(addr));
1114	plenbytes = (plen + 7) / 8;
1115	ND_TCHECK2(pd[1], plenbytes);
1116	ITEMCHECK(plenbytes);
1117	memcpy(&addr, &pd[1], plenbytes);
1118	if (plen % 8) {
1119		addr.s6_addr[plenbytes - 1] &=
1120			((0xff00 >> (plen % 8)) & 0xff);
1121	}
1122	snprintf(buf, buflen, "%s/%d", ip6addr_string(ndo, &addr), plen);
1123	return 1 + plenbytes;
1124
1125trunc:
1126	return -2;
1127
1128badtlv:
1129	return -3;
1130}
1131
1132static int
1133decode_labeled_prefix6(netdissect_options *ndo,
1134                       const u_char *pptr, u_int itemlen, char *buf, u_int buflen)
1135{
1136	struct in6_addr addr;
1137	u_int plen, plenbytes;
1138
1139	/* prefix length and label = 4 bytes */
1140	ND_TCHECK2(pptr[0], 4);
1141	ITEMCHECK(4);
1142	plen = pptr[0]; /* get prefix length */
1143
1144	if (24 > plen)
1145		return -1;
1146
1147        plen-=24; /* adjust prefixlen - labellength */
1148
1149	if (128 < plen)
1150		return -1;
1151	itemlen -= 4;
1152
1153	memset(&addr, 0, sizeof(addr));
1154	plenbytes = (plen + 7) / 8;
1155	ND_TCHECK2(pptr[4], plenbytes);
1156	memcpy(&addr, &pptr[4], plenbytes);
1157	if (plen % 8) {
1158		addr.s6_addr[plenbytes - 1] &=
1159			((0xff00 >> (plen % 8)) & 0xff);
1160	}
1161        /* the label may get offsetted by 4 bits so lets shift it right */
1162	snprintf(buf, buflen, "%s/%d, label:%u %s",
1163                 ip6addr_string(ndo, &addr),
1164                 plen,
1165                 EXTRACT_24BITS(pptr+1)>>4,
1166                 ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
1167
1168	return 4 + plenbytes;
1169
1170trunc:
1171	return -2;
1172
1173badtlv:
1174	return -3;
1175}
1176
1177static int
1178decode_labeled_vpn_prefix6(netdissect_options *ndo,
1179                           const u_char *pptr, char *buf, u_int buflen)
1180{
1181	struct in6_addr addr;
1182	u_int plen;
1183
1184	ND_TCHECK(pptr[0]);
1185	plen = pptr[0];   /* get prefix length */
1186
1187	if ((24+64) > plen)
1188		return -1;
1189
1190        plen-=(24+64); /* adjust prefixlen - labellength - RD len*/
1191
1192	if (128 < plen)
1193		return -1;
1194
1195	memset(&addr, 0, sizeof(addr));
1196	ND_TCHECK2(pptr[12], (plen + 7) / 8);
1197	memcpy(&addr, &pptr[12], (plen + 7) / 8);
1198	if (plen % 8) {
1199		addr.s6_addr[(plen + 7) / 8 - 1] &=
1200			((0xff00 >> (plen % 8)) & 0xff);
1201	}
1202        /* the label may get offsetted by 4 bits so lets shift it right */
1203	snprintf(buf, buflen, "RD: %s, %s/%d, label:%u %s",
1204                 bgp_vpn_rd_print(ndo, pptr+4),
1205                 ip6addr_string(ndo, &addr),
1206                 plen,
1207                 EXTRACT_24BITS(pptr+1)>>4,
1208                 ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
1209
1210	return 12 + (plen + 7) / 8;
1211
1212trunc:
1213	return -2;
1214}
1215
1216static int
1217decode_clnp_prefix(netdissect_options *ndo,
1218                   const u_char *pptr, char *buf, u_int buflen)
1219{
1220        uint8_t addr[19];
1221	u_int plen;
1222
1223	ND_TCHECK(pptr[0]);
1224	plen = pptr[0]; /* get prefix length */
1225
1226	if (152 < plen)
1227		return -1;
1228
1229	memset(&addr, 0, sizeof(addr));
1230	ND_TCHECK2(pptr[4], (plen + 7) / 8);
1231	memcpy(&addr, &pptr[4], (plen + 7) / 8);
1232	if (plen % 8) {
1233		addr[(plen + 7) / 8 - 1] &=
1234			((0xff00 >> (plen % 8)) & 0xff);
1235	}
1236	snprintf(buf, buflen, "%s/%d",
1237                 isonsap_string(ndo, addr,(plen + 7) / 8),
1238                 plen);
1239
1240	return 1 + (plen + 7) / 8;
1241
1242trunc:
1243	return -2;
1244}
1245
1246static int
1247decode_labeled_vpn_clnp_prefix(netdissect_options *ndo,
1248                               const u_char *pptr, char *buf, u_int buflen)
1249{
1250        uint8_t addr[19];
1251	u_int plen;
1252
1253	ND_TCHECK(pptr[0]);
1254	plen = pptr[0];   /* get prefix length */
1255
1256	if ((24+64) > plen)
1257		return -1;
1258
1259        plen-=(24+64); /* adjust prefixlen - labellength - RD len*/
1260
1261	if (152 < plen)
1262		return -1;
1263
1264	memset(&addr, 0, sizeof(addr));
1265	ND_TCHECK2(pptr[12], (plen + 7) / 8);
1266	memcpy(&addr, &pptr[12], (plen + 7) / 8);
1267	if (plen % 8) {
1268		addr[(plen + 7) / 8 - 1] &=
1269			((0xff00 >> (plen % 8)) & 0xff);
1270	}
1271        /* the label may get offsetted by 4 bits so lets shift it right */
1272	snprintf(buf, buflen, "RD: %s, %s/%d, label:%u %s",
1273                 bgp_vpn_rd_print(ndo, pptr+4),
1274                 isonsap_string(ndo, addr,(plen + 7) / 8),
1275                 plen,
1276                 EXTRACT_24BITS(pptr+1)>>4,
1277                 ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
1278
1279	return 12 + (plen + 7) / 8;
1280
1281trunc:
1282	return -2;
1283}
1284
1285/*
1286 * bgp_attr_get_as_size
1287 *
1288 * Try to find the size of the ASs encoded in an as-path. It is not obvious, as
1289 * both Old speakers that do not support 4 byte AS, and the new speakers that do
1290 * support, exchange AS-Path with the same path-attribute type value 0x02.
1291 */
1292static int
1293bgp_attr_get_as_size(netdissect_options *ndo,
1294                     uint8_t bgpa_type, const u_char *pptr, int len)
1295{
1296    const u_char *tptr = pptr;
1297
1298    /*
1299     * If the path attribute is the optional AS4 path type, then we already
1300     * know, that ASs must be encoded in 4 byte format.
1301     */
1302    if (bgpa_type == BGPTYPE_AS4_PATH) {
1303        return 4;
1304    }
1305
1306    /*
1307     * Let us assume that ASs are of 2 bytes in size, and check if the AS-Path
1308     * TLV is good. If not, ask the caller to try with AS encoded as 4 bytes
1309     * each.
1310     */
1311    while (tptr < pptr + len) {
1312        ND_TCHECK(tptr[0]);
1313
1314        /*
1315         * If we do not find a valid segment type, our guess might be wrong.
1316         */
1317        if (tptr[0] < BGP_AS_SEG_TYPE_MIN || tptr[0] > BGP_AS_SEG_TYPE_MAX) {
1318            goto trunc;
1319        }
1320        ND_TCHECK(tptr[1]);
1321        tptr += 2 + tptr[1] * 2;
1322    }
1323
1324    /*
1325     * If we correctly reached end of the AS path attribute data content,
1326     * then most likely ASs were indeed encoded as 2 bytes.
1327     */
1328    if (tptr == pptr + len) {
1329        return 2;
1330    }
1331
1332trunc:
1333
1334    /*
1335     * We can come here, either we did not have enough data, or if we
1336     * try to decode 4 byte ASs in 2 byte format. Either way, return 4,
1337     * so that calller can try to decode each AS as of 4 bytes. If indeed
1338     * there was not enough data, it will crib and end the parse anyways.
1339     */
1340   return 4;
1341}
1342
1343static int
1344bgp_attr_print(netdissect_options *ndo,
1345               u_int atype, const u_char *pptr, u_int len)
1346{
1347	int i;
1348	uint16_t af;
1349	uint8_t safi, snpa, nhlen;
1350        union { /* copy buffer for bandwidth values */
1351            float f;
1352            uint32_t i;
1353        } bw;
1354	int advance;
1355	u_int tlen;
1356	const u_char *tptr;
1357	char buf[MAXHOSTNAMELEN + 100];
1358        int  as_size;
1359
1360        tptr = pptr;
1361        tlen=len;
1362
1363	switch (atype) {
1364	case BGPTYPE_ORIGIN:
1365		if (len != 1)
1366			ND_PRINT((ndo, "invalid len"));
1367		else {
1368			ND_TCHECK(*tptr);
1369			ND_PRINT((ndo, "%s", tok2str(bgp_origin_values,
1370						"Unknown Origin Typecode",
1371						tptr[0])));
1372		}
1373		break;
1374
1375        /*
1376         * Process AS4 byte path and AS2 byte path attributes here.
1377         */
1378	case BGPTYPE_AS4_PATH:
1379	case BGPTYPE_AS_PATH:
1380		if (len % 2) {
1381			ND_PRINT((ndo, "invalid len"));
1382			break;
1383		}
1384                if (!len) {
1385			ND_PRINT((ndo, "empty"));
1386			break;
1387                }
1388
1389                /*
1390                 * BGP updates exchanged between New speakers that support 4
1391                 * byte AS, ASs are always encoded in 4 bytes. There is no
1392                 * definitive way to find this, just by the packet's
1393                 * contents. So, check for packet's TLV's sanity assuming
1394                 * 2 bytes first, and it does not pass, assume that ASs are
1395                 * encoded in 4 bytes format and move on.
1396                 */
1397                as_size = bgp_attr_get_as_size(ndo, atype, pptr, len);
1398
1399		while (tptr < pptr + len) {
1400			ND_TCHECK(tptr[0]);
1401                        ND_PRINT((ndo, "%s", tok2str(bgp_as_path_segment_open_values,
1402						"?", tptr[0])));
1403                        for (i = 0; i < tptr[1] * as_size; i += as_size) {
1404                            ND_TCHECK2(tptr[2 + i], as_size);
1405			    ND_PRINT((ndo, "%s ",
1406				as_printf(ndo, astostr, sizeof(astostr),
1407				as_size == 2 ?
1408				EXTRACT_16BITS(&tptr[2 + i]) :
1409				EXTRACT_32BITS(&tptr[2 + i]))));
1410                        }
1411			ND_TCHECK(tptr[0]);
1412                        ND_PRINT((ndo, "%s", tok2str(bgp_as_path_segment_close_values,
1413						"?", tptr[0])));
1414                        ND_TCHECK(tptr[1]);
1415                        tptr += 2 + tptr[1] * as_size;
1416		}
1417		break;
1418	case BGPTYPE_NEXT_HOP:
1419		if (len != 4)
1420			ND_PRINT((ndo, "invalid len"));
1421		else {
1422			ND_TCHECK2(tptr[0], 4);
1423			ND_PRINT((ndo, "%s", ipaddr_string(ndo, tptr)));
1424		}
1425		break;
1426	case BGPTYPE_MULTI_EXIT_DISC:
1427	case BGPTYPE_LOCAL_PREF:
1428		if (len != 4)
1429			ND_PRINT((ndo, "invalid len"));
1430		else {
1431			ND_TCHECK2(tptr[0], 4);
1432			ND_PRINT((ndo, "%u", EXTRACT_32BITS(tptr)));
1433		}
1434		break;
1435	case BGPTYPE_ATOMIC_AGGREGATE:
1436		if (len != 0)
1437			ND_PRINT((ndo, "invalid len"));
1438		break;
1439        case BGPTYPE_AGGREGATOR:
1440
1441                /*
1442                 * Depending on the AS encoded is of 2 bytes or of 4 bytes,
1443                 * the length of this PA can be either 6 bytes or 8 bytes.
1444                 */
1445                if (len != 6 && len != 8) {
1446                    ND_PRINT((ndo, "invalid len"));
1447                    break;
1448                }
1449                ND_TCHECK2(tptr[0], len);
1450                if (len == 6) {
1451		    ND_PRINT((ndo, " AS #%s, origin %s",
1452			as_printf(ndo, astostr, sizeof(astostr), EXTRACT_16BITS(tptr)),
1453			ipaddr_string(ndo, tptr + 2)));
1454                } else {
1455		    ND_PRINT((ndo, " AS #%s, origin %s",
1456			as_printf(ndo, astostr, sizeof(astostr),
1457			EXTRACT_32BITS(tptr)), ipaddr_string(ndo, tptr + 4)));
1458                }
1459                break;
1460	case BGPTYPE_AGGREGATOR4:
1461		if (len != 8) {
1462			ND_PRINT((ndo, "invalid len"));
1463			break;
1464		}
1465		ND_TCHECK2(tptr[0], 8);
1466		ND_PRINT((ndo, " AS #%s, origin %s",
1467	   	    as_printf(ndo, astostr, sizeof(astostr), EXTRACT_32BITS(tptr)),
1468		    ipaddr_string(ndo, tptr + 4)));
1469		break;
1470	case BGPTYPE_COMMUNITIES:
1471		if (len % 4) {
1472			ND_PRINT((ndo, "invalid len"));
1473			break;
1474		}
1475		while (tlen>0) {
1476			uint32_t comm;
1477			ND_TCHECK2(tptr[0], 4);
1478			comm = EXTRACT_32BITS(tptr);
1479			switch (comm) {
1480			case BGP_COMMUNITY_NO_EXPORT:
1481				ND_PRINT((ndo, " NO_EXPORT"));
1482				break;
1483			case BGP_COMMUNITY_NO_ADVERT:
1484				ND_PRINT((ndo, " NO_ADVERTISE"));
1485				break;
1486			case BGP_COMMUNITY_NO_EXPORT_SUBCONFED:
1487				ND_PRINT((ndo, " NO_EXPORT_SUBCONFED"));
1488				break;
1489			default:
1490				ND_PRINT((ndo, "%u:%u%s",
1491                                       (comm >> 16) & 0xffff,
1492                                       comm & 0xffff,
1493                                       (tlen>4) ? ", " : ""));
1494				break;
1495			}
1496                        tlen -=4;
1497                        tptr +=4;
1498		}
1499		break;
1500        case BGPTYPE_ORIGINATOR_ID:
1501		if (len != 4) {
1502			ND_PRINT((ndo, "invalid len"));
1503			break;
1504		}
1505		ND_TCHECK2(tptr[0], 4);
1506                ND_PRINT((ndo, "%s",ipaddr_string(ndo, tptr)));
1507                break;
1508        case BGPTYPE_CLUSTER_LIST:
1509		if (len % 4) {
1510			ND_PRINT((ndo, "invalid len"));
1511			break;
1512		}
1513                while (tlen>0) {
1514			ND_TCHECK2(tptr[0], 4);
1515                        ND_PRINT((ndo, "%s%s",
1516                               ipaddr_string(ndo, tptr),
1517                                (tlen>4) ? ", " : ""));
1518                        tlen -=4;
1519                        tptr +=4;
1520                }
1521                break;
1522	case BGPTYPE_MP_REACH_NLRI:
1523		ND_TCHECK2(tptr[0], 3);
1524		af = EXTRACT_16BITS(tptr);
1525		safi = tptr[2];
1526
1527                ND_PRINT((ndo, "\n\t    AFI: %s (%u), %sSAFI: %s (%u)",
1528                       tok2str(af_values, "Unknown AFI", af),
1529                       af,
1530                       (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
1531                       tok2str(bgp_safi_values, "Unknown SAFI", safi),
1532                       safi));
1533
1534                switch(af<<8 | safi) {
1535                case (AFNUM_INET<<8 | SAFNUM_UNICAST):
1536                case (AFNUM_INET<<8 | SAFNUM_MULTICAST):
1537                case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST):
1538                case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
1539                case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO):
1540                case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST):
1541                case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST):
1542                case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST):
1543                case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN):
1544		case (AFNUM_INET<<8 | SAFNUM_MDT):
1545                case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
1546                case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
1547                case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST):
1548                case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
1549                case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST):
1550                case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST):
1551                case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST):
1552                case (AFNUM_NSAP<<8 | SAFNUM_UNICAST):
1553                case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST):
1554                case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST):
1555                case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST):
1556                case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST):
1557                case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST):
1558                case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
1559                case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST):
1560                case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
1561                case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
1562                    break;
1563                default:
1564                    ND_TCHECK2(tptr[0], tlen);
1565                    ND_PRINT((ndo, "\n\t    no AFI %u / SAFI %u decoder", af, safi));
1566                    if (ndo->ndo_vflag <= 1)
1567                        print_unknown_data(ndo, tptr, "\n\t    ", tlen);
1568                    goto done;
1569                    break;
1570                }
1571
1572                tptr +=3;
1573
1574		ND_TCHECK(tptr[0]);
1575		nhlen = tptr[0];
1576                tlen = nhlen;
1577                tptr++;
1578
1579		if (tlen) {
1580                    int nnh = 0;
1581                    ND_PRINT((ndo, "\n\t    nexthop: "));
1582                    while (tlen > 0) {
1583                        if ( nnh++ > 0 ) {
1584                            ND_PRINT((ndo,  ", " ));
1585                        }
1586                        switch(af<<8 | safi) {
1587                        case (AFNUM_INET<<8 | SAFNUM_UNICAST):
1588                        case (AFNUM_INET<<8 | SAFNUM_MULTICAST):
1589                        case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST):
1590                        case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
1591                        case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO):
1592                        case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN):
1593                        case (AFNUM_INET<<8 | SAFNUM_MDT):
1594			    if (tlen < (int)sizeof(struct in_addr)) {
1595                                ND_PRINT((ndo, "invalid len"));
1596                                tlen = 0;
1597                            } else {
1598                                ND_TCHECK2(tptr[0], sizeof(struct in_addr));
1599                                ND_PRINT((ndo, "%s",ipaddr_string(ndo, tptr)));
1600                                tlen -= sizeof(struct in_addr);
1601                                tptr += sizeof(struct in_addr);
1602                            }
1603                            break;
1604                        case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST):
1605                        case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST):
1606                        case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST):
1607                            if (tlen < (int)(sizeof(struct in_addr)+BGP_VPN_RD_LEN)) {
1608                                ND_PRINT((ndo, "invalid len"));
1609                                tlen = 0;
1610                            } else {
1611                                ND_TCHECK2(tptr[0], sizeof(struct in_addr)+BGP_VPN_RD_LEN);
1612                                ND_PRINT((ndo, "RD: %s, %s",
1613                                       bgp_vpn_rd_print(ndo, tptr),
1614                                       ipaddr_string(ndo, tptr+BGP_VPN_RD_LEN)));
1615                                tlen -= (sizeof(struct in_addr)+BGP_VPN_RD_LEN);
1616                                tptr += (sizeof(struct in_addr)+BGP_VPN_RD_LEN);
1617                            }
1618                            break;
1619                        case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
1620                        case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
1621                        case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST):
1622                        case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
1623                            if (tlen < (int)sizeof(struct in6_addr)) {
1624                                ND_PRINT((ndo, "invalid len"));
1625                                tlen = 0;
1626                            } else {
1627                                ND_TCHECK2(tptr[0], sizeof(struct in6_addr));
1628                                ND_PRINT((ndo, "%s", ip6addr_string(ndo, tptr)));
1629                                tlen -= sizeof(struct in6_addr);
1630                                tptr += sizeof(struct in6_addr);
1631                            }
1632                            break;
1633                        case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST):
1634                        case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST):
1635                        case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST):
1636                            if (tlen < (int)(sizeof(struct in6_addr)+BGP_VPN_RD_LEN)) {
1637                                ND_PRINT((ndo, "invalid len"));
1638                                tlen = 0;
1639                            } else {
1640                                ND_TCHECK2(tptr[0], sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
1641                                ND_PRINT((ndo, "RD: %s, %s",
1642                                       bgp_vpn_rd_print(ndo, tptr),
1643                                       ip6addr_string(ndo, tptr+BGP_VPN_RD_LEN)));
1644                                tlen -= (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
1645                                tptr += (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
1646                            }
1647                            break;
1648                        case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
1649                        case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
1650                        case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST):
1651                        case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
1652                            if (tlen < (int)sizeof(struct in_addr)) {
1653                                ND_PRINT((ndo, "invalid len"));
1654                                tlen = 0;
1655                            } else {
1656                                ND_TCHECK2(tptr[0], sizeof(struct in_addr));
1657                                ND_PRINT((ndo, "%s", ipaddr_string(ndo, tptr)));
1658                                tlen -= (sizeof(struct in_addr));
1659                                tptr += (sizeof(struct in_addr));
1660                            }
1661                            break;
1662                        case (AFNUM_NSAP<<8 | SAFNUM_UNICAST):
1663                        case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST):
1664                        case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST):
1665                            ND_TCHECK2(tptr[0], tlen);
1666                            ND_PRINT((ndo, "%s", isonsap_string(ndo, tptr, tlen)));
1667                            tptr += tlen;
1668                            tlen = 0;
1669                            break;
1670
1671                        case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST):
1672                        case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST):
1673                        case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST):
1674                            if (tlen < BGP_VPN_RD_LEN+1) {
1675                                ND_PRINT((ndo, "invalid len"));
1676                                tlen = 0;
1677                            } else {
1678                                ND_TCHECK2(tptr[0], tlen);
1679                                ND_PRINT((ndo, "RD: %s, %s",
1680                                       bgp_vpn_rd_print(ndo, tptr),
1681                                       isonsap_string(ndo, tptr+BGP_VPN_RD_LEN,tlen-BGP_VPN_RD_LEN)));
1682                                /* rfc986 mapped IPv4 address ? */
1683                                if (EXTRACT_32BITS(tptr+BGP_VPN_RD_LEN) ==  0x47000601)
1684                                    ND_PRINT((ndo, " = %s", ipaddr_string(ndo, tptr+BGP_VPN_RD_LEN+4)));
1685                                /* rfc1888 mapped IPv6 address ? */
1686                                else if (EXTRACT_24BITS(tptr+BGP_VPN_RD_LEN) ==  0x350000)
1687                                    ND_PRINT((ndo, " = %s", ip6addr_string(ndo, tptr+BGP_VPN_RD_LEN+3)));
1688                                tptr += tlen;
1689                                tlen = 0;
1690                            }
1691                            break;
1692                        default:
1693                            ND_TCHECK2(tptr[0], tlen);
1694                            ND_PRINT((ndo, "no AFI %u/SAFI %u decoder", af, safi));
1695                            if (ndo->ndo_vflag <= 1)
1696                                print_unknown_data(ndo, tptr, "\n\t    ", tlen);
1697                            tptr += tlen;
1698                            tlen = 0;
1699                            goto done;
1700                            break;
1701                        }
1702                    }
1703		}
1704		ND_PRINT((ndo, ", nh-length: %u", nhlen));
1705		tptr += tlen;
1706
1707		ND_TCHECK(tptr[0]);
1708		snpa = tptr[0];
1709		tptr++;
1710
1711		if (snpa) {
1712			ND_PRINT((ndo, "\n\t    %u SNPA", snpa));
1713			for (/*nothing*/; snpa > 0; snpa--) {
1714				ND_TCHECK(tptr[0]);
1715				ND_PRINT((ndo, "\n\t      %d bytes", tptr[0]));
1716				tptr += tptr[0] + 1;
1717			}
1718		} else {
1719			ND_PRINT((ndo, ", no SNPA"));
1720                }
1721
1722		while (len - (tptr - pptr) > 0) {
1723                    switch (af<<8 | safi) {
1724                    case (AFNUM_INET<<8 | SAFNUM_UNICAST):
1725                    case (AFNUM_INET<<8 | SAFNUM_MULTICAST):
1726                    case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST):
1727                        advance = decode_prefix4(ndo, tptr, len, buf, sizeof(buf));
1728                        if (advance == -1)
1729                            ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1730                        else if (advance == -2)
1731                            goto trunc;
1732                        else if (advance == -3)
1733                            break; /* bytes left, but not enough */
1734                        else
1735                            ND_PRINT((ndo, "\n\t      %s", buf));
1736                        break;
1737                    case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
1738                        advance = decode_labeled_prefix4(ndo, tptr, len, buf, sizeof(buf));
1739                        if (advance == -1)
1740                            ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1741                        else if (advance == -2)
1742                            goto trunc;
1743                        else if (advance == -3)
1744                            break; /* bytes left, but not enough */
1745                        else
1746                            ND_PRINT((ndo, "\n\t      %s", buf));
1747                        break;
1748                    case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST):
1749                    case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST):
1750                    case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST):
1751                        advance = decode_labeled_vpn_prefix4(ndo, tptr, buf, sizeof(buf));
1752                        if (advance == -1)
1753                            ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1754                        else if (advance == -2)
1755                            goto trunc;
1756                        else
1757                            ND_PRINT((ndo, "\n\t      %s", buf));
1758                        break;
1759                    case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO):
1760                        advance = decode_rt_routing_info(ndo, tptr, buf, sizeof(buf));
1761                        if (advance == -1)
1762                            ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1763                        else if (advance == -2)
1764                            goto trunc;
1765                        else
1766                            ND_PRINT((ndo, "\n\t      %s", buf));
1767                        break;
1768                    case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN): /* fall through */
1769                    case (AFNUM_INET6<<8 | SAFNUM_MULTICAST_VPN):
1770                        advance = decode_multicast_vpn(ndo, tptr, buf, sizeof(buf));
1771                        if (advance == -1)
1772                            ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1773                        else if (advance == -2)
1774                            goto trunc;
1775                        else
1776                            ND_PRINT((ndo, "\n\t      %s", buf));
1777                        break;
1778
1779		    case (AFNUM_INET<<8 | SAFNUM_MDT):
1780		      advance = decode_mdt_vpn_nlri(ndo, tptr, buf, sizeof(buf));
1781		      if (advance == -1)
1782                            ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1783                        else if (advance == -2)
1784                            goto trunc;
1785                        else
1786                            ND_PRINT((ndo, "\n\t      %s", buf));
1787		       break;
1788                    case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
1789                    case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
1790                    case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST):
1791                        advance = decode_prefix6(ndo, tptr, len, buf, sizeof(buf));
1792                        if (advance == -1)
1793                            ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1794                        else if (advance == -2)
1795                            goto trunc;
1796                        else if (advance == -3)
1797                            break; /* bytes left, but not enough */
1798                        else
1799                            ND_PRINT((ndo, "\n\t      %s", buf));
1800                        break;
1801                    case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
1802                        advance = decode_labeled_prefix6(ndo, tptr, len, buf, sizeof(buf));
1803                        if (advance == -1)
1804                            ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1805                        else if (advance == -2)
1806                            goto trunc;
1807                        else if (advance == -3)
1808                            break; /* bytes left, but not enough */
1809                        else
1810                            ND_PRINT((ndo, "\n\t      %s", buf));
1811                        break;
1812                    case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST):
1813                    case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST):
1814                    case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST):
1815                        advance = decode_labeled_vpn_prefix6(ndo, tptr, buf, sizeof(buf));
1816                        if (advance == -1)
1817                            ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1818                        else if (advance == -2)
1819                            goto trunc;
1820                        else
1821                            ND_PRINT((ndo, "\n\t      %s", buf));
1822                        break;
1823                    case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
1824                    case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
1825                    case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST):
1826                    case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
1827                        advance = decode_labeled_vpn_l2(ndo, tptr, buf, sizeof(buf));
1828                        if (advance == -1)
1829                            ND_PRINT((ndo, "\n\t    (illegal length)"));
1830                        else if (advance == -2)
1831                            goto trunc;
1832                        else
1833                            ND_PRINT((ndo, "\n\t      %s", buf));
1834                        break;
1835                    case (AFNUM_NSAP<<8 | SAFNUM_UNICAST):
1836                    case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST):
1837                    case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST):
1838                        advance = decode_clnp_prefix(ndo, tptr, buf, sizeof(buf));
1839                        if (advance == -1)
1840                            ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1841                        else if (advance == -2)
1842                            goto trunc;
1843                        else
1844                            ND_PRINT((ndo, "\n\t      %s", buf));
1845                        break;
1846                    case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST):
1847                    case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST):
1848                    case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST):
1849                        advance = decode_labeled_vpn_clnp_prefix(ndo, tptr, buf, sizeof(buf));
1850                        if (advance == -1)
1851                            ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1852                        else if (advance == -2)
1853                            goto trunc;
1854                        else
1855                            ND_PRINT((ndo, "\n\t      %s", buf));
1856                        break;
1857                    default:
1858                        ND_TCHECK2(*tptr,tlen);
1859                        ND_PRINT((ndo, "\n\t    no AFI %u / SAFI %u decoder", af, safi));
1860                        if (ndo->ndo_vflag <= 1)
1861                            print_unknown_data(ndo, tptr, "\n\t    ", tlen);
1862                        advance = 0;
1863                        tptr = pptr + len;
1864                        break;
1865                    }
1866                    if (advance < 0)
1867                        break;
1868                    tptr += advance;
1869		}
1870        done:
1871		break;
1872
1873	case BGPTYPE_MP_UNREACH_NLRI:
1874		ND_TCHECK2(tptr[0], BGP_MP_NLRI_MINSIZE);
1875		af = EXTRACT_16BITS(tptr);
1876		safi = tptr[2];
1877
1878                ND_PRINT((ndo, "\n\t    AFI: %s (%u), %sSAFI: %s (%u)",
1879                       tok2str(af_values, "Unknown AFI", af),
1880                       af,
1881                       (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */
1882                       tok2str(bgp_safi_values, "Unknown SAFI", safi),
1883                       safi));
1884
1885                if (len == BGP_MP_NLRI_MINSIZE)
1886                    ND_PRINT((ndo, "\n\t      End-of-Rib Marker (empty NLRI)"));
1887
1888		tptr += 3;
1889
1890		while (len - (tptr - pptr) > 0) {
1891                    switch (af<<8 | safi) {
1892                    case (AFNUM_INET<<8 | SAFNUM_UNICAST):
1893                    case (AFNUM_INET<<8 | SAFNUM_MULTICAST):
1894                    case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST):
1895                        advance = decode_prefix4(ndo, tptr, len, buf, sizeof(buf));
1896                        if (advance == -1)
1897                            ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1898                        else if (advance == -2)
1899                            goto trunc;
1900                        else if (advance == -3)
1901                            break; /* bytes left, but not enough */
1902                        else
1903                            ND_PRINT((ndo, "\n\t      %s", buf));
1904                        break;
1905                    case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
1906                        advance = decode_labeled_prefix4(ndo, tptr, len, buf, sizeof(buf));
1907                        if (advance == -1)
1908                            ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1909                        else if (advance == -2)
1910                            goto trunc;
1911                        else if (advance == -3)
1912                            break; /* bytes left, but not enough */
1913                        else
1914                            ND_PRINT((ndo, "\n\t      %s", buf));
1915                        break;
1916                    case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST):
1917                    case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST):
1918                    case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST):
1919                        advance = decode_labeled_vpn_prefix4(ndo, tptr, buf, sizeof(buf));
1920                        if (advance == -1)
1921                            ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1922                        else if (advance == -2)
1923                            goto trunc;
1924                        else
1925                            ND_PRINT((ndo, "\n\t      %s", buf));
1926                        break;
1927                    case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
1928                    case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
1929                    case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST):
1930                        advance = decode_prefix6(ndo, tptr, len, buf, sizeof(buf));
1931                        if (advance == -1)
1932                            ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1933                        else if (advance == -2)
1934                            goto trunc;
1935                        else if (advance == -3)
1936                            break; /* bytes left, but not enough */
1937                        else
1938                            ND_PRINT((ndo, "\n\t      %s", buf));
1939                        break;
1940                    case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
1941                        advance = decode_labeled_prefix6(ndo, tptr, len, buf, sizeof(buf));
1942                        if (advance == -1)
1943                            ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1944                        else if (advance == -2)
1945                            goto trunc;
1946                        else if (advance == -3)
1947                            break; /* bytes left, but not enough */
1948                        else
1949                            ND_PRINT((ndo, "\n\t      %s", buf));
1950                        break;
1951                    case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST):
1952                    case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST):
1953                    case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST):
1954                        advance = decode_labeled_vpn_prefix6(ndo, tptr, buf, sizeof(buf));
1955                        if (advance == -1)
1956                            ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1957                        else if (advance == -2)
1958                            goto trunc;
1959                        else
1960                            ND_PRINT((ndo, "\n\t      %s", buf));
1961                        break;
1962                    case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
1963                    case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
1964                    case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST):
1965                    case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST):
1966                        advance = decode_labeled_vpn_l2(ndo, tptr, buf, sizeof(buf));
1967                        if (advance == -1)
1968                            ND_PRINT((ndo, "\n\t    (illegal length)"));
1969                        else if (advance == -2)
1970                            goto trunc;
1971                        else
1972                            ND_PRINT((ndo, "\n\t      %s", buf));
1973                        break;
1974                    case (AFNUM_NSAP<<8 | SAFNUM_UNICAST):
1975                    case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST):
1976                    case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST):
1977                        advance = decode_clnp_prefix(ndo, tptr, buf, sizeof(buf));
1978                        if (advance == -1)
1979                            ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1980                        else if (advance == -2)
1981                            goto trunc;
1982                        else
1983                            ND_PRINT((ndo, "\n\t      %s", buf));
1984                        break;
1985                    case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST):
1986                    case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST):
1987                    case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST):
1988                        advance = decode_labeled_vpn_clnp_prefix(ndo, tptr, buf, sizeof(buf));
1989                        if (advance == -1)
1990                            ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
1991                        else if (advance == -2)
1992                            goto trunc;
1993                        else
1994                            ND_PRINT((ndo, "\n\t      %s", buf));
1995                        break;
1996		    case (AFNUM_INET<<8 | SAFNUM_MDT):
1997		      advance = decode_mdt_vpn_nlri(ndo, tptr, buf, sizeof(buf));
1998		      if (advance == -1)
1999                            ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
2000                        else if (advance == -2)
2001                            goto trunc;
2002                        else
2003                            ND_PRINT((ndo, "\n\t      %s", buf));
2004		       break;
2005                    case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN): /* fall through */
2006                    case (AFNUM_INET6<<8 | SAFNUM_MULTICAST_VPN):
2007                        advance = decode_multicast_vpn(ndo, tptr, buf, sizeof(buf));
2008                        if (advance == -1)
2009                            ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
2010                        else if (advance == -2)
2011                            goto trunc;
2012                        else
2013                            ND_PRINT((ndo, "\n\t      %s", buf));
2014                        break;
2015                    default:
2016                        ND_TCHECK2(*(tptr-3),tlen);
2017                        ND_PRINT((ndo, "no AFI %u / SAFI %u decoder", af, safi));
2018                        if (ndo->ndo_vflag <= 1)
2019                            print_unknown_data(ndo, tptr-3, "\n\t    ", tlen);
2020                        advance = 0;
2021                        tptr = pptr + len;
2022                        break;
2023                    }
2024                    if (advance < 0)
2025                        break;
2026                    tptr += advance;
2027		}
2028		break;
2029        case BGPTYPE_EXTD_COMMUNITIES:
2030		if (len % 8) {
2031			ND_PRINT((ndo, "invalid len"));
2032			break;
2033		}
2034                while (tlen>0) {
2035                    uint16_t extd_comm;
2036
2037                    ND_TCHECK2(tptr[0], 2);
2038                    extd_comm=EXTRACT_16BITS(tptr);
2039
2040		    ND_PRINT((ndo, "\n\t    %s (0x%04x), Flags [%s]",
2041			   tok2str(bgp_extd_comm_subtype_values,
2042				      "unknown extd community typecode",
2043				      extd_comm),
2044			   extd_comm,
2045			   bittok2str(bgp_extd_comm_flag_values, "none", extd_comm)));
2046
2047                    ND_TCHECK2(*(tptr+2), 6);
2048                    switch(extd_comm) {
2049                    case BGP_EXT_COM_RT_0:
2050                    case BGP_EXT_COM_RO_0:
2051                    case BGP_EXT_COM_L2VPN_RT_0:
2052                        ND_PRINT((ndo, ": %u:%u (= %s)",
2053                               EXTRACT_16BITS(tptr+2),
2054                               EXTRACT_32BITS(tptr+4),
2055                               ipaddr_string(ndo, tptr+4)));
2056                        break;
2057                    case BGP_EXT_COM_RT_1:
2058                    case BGP_EXT_COM_RO_1:
2059                    case BGP_EXT_COM_L2VPN_RT_1:
2060                    case BGP_EXT_COM_VRF_RT_IMP:
2061                        ND_PRINT((ndo, ": %s:%u",
2062                               ipaddr_string(ndo, tptr+2),
2063                               EXTRACT_16BITS(tptr+6)));
2064                        break;
2065                    case BGP_EXT_COM_RT_2:
2066                    case BGP_EXT_COM_RO_2:
2067			ND_PRINT((ndo, ": %s:%u",
2068			    as_printf(ndo, astostr, sizeof(astostr),
2069			    EXTRACT_32BITS(tptr+2)), EXTRACT_16BITS(tptr+6)));
2070			break;
2071                    case BGP_EXT_COM_LINKBAND:
2072		        bw.i = EXTRACT_32BITS(tptr+2);
2073                        ND_PRINT((ndo, ": bandwidth: %.3f Mbps",
2074                               bw.f*8/1000000));
2075                        break;
2076                    case BGP_EXT_COM_VPN_ORIGIN:
2077                    case BGP_EXT_COM_VPN_ORIGIN2:
2078                    case BGP_EXT_COM_VPN_ORIGIN3:
2079                    case BGP_EXT_COM_VPN_ORIGIN4:
2080                    case BGP_EXT_COM_OSPF_RID:
2081                    case BGP_EXT_COM_OSPF_RID2:
2082                        ND_PRINT((ndo, "%s", ipaddr_string(ndo, tptr+2)));
2083                        break;
2084                    case BGP_EXT_COM_OSPF_RTYPE:
2085                    case BGP_EXT_COM_OSPF_RTYPE2:
2086                        ND_PRINT((ndo, ": area:%s, router-type:%s, metric-type:%s%s",
2087                               ipaddr_string(ndo, tptr+2),
2088                               tok2str(bgp_extd_comm_ospf_rtype_values,
2089					  "unknown (0x%02x)",
2090					  *(tptr+6)),
2091                               (*(tptr+7) &  BGP_OSPF_RTYPE_METRIC_TYPE) ? "E2" : "",
2092                               ((*(tptr+6) == BGP_OSPF_RTYPE_EXT) || (*(tptr+6) == BGP_OSPF_RTYPE_NSSA)) ? "E1" : ""));
2093                        break;
2094                    case BGP_EXT_COM_L2INFO:
2095                        ND_PRINT((ndo, ": %s Control Flags [0x%02x]:MTU %u",
2096                               tok2str(l2vpn_encaps_values,
2097					  "unknown encaps",
2098					  *(tptr+2)),
2099                                       *(tptr+3),
2100                               EXTRACT_16BITS(tptr+4)));
2101                        break;
2102                    case BGP_EXT_COM_SOURCE_AS:
2103                        ND_PRINT((ndo, ": AS %u", EXTRACT_16BITS(tptr+2)));
2104                        break;
2105                    default:
2106                        ND_TCHECK2(*tptr,8);
2107                        print_unknown_data(ndo, tptr, "\n\t      ", 8);
2108                        break;
2109                    }
2110                    tlen -=8;
2111                    tptr +=8;
2112                }
2113                break;
2114
2115        case BGPTYPE_PMSI_TUNNEL:
2116        {
2117                uint8_t tunnel_type, flags;
2118
2119                tunnel_type = *(tptr+1);
2120                flags = *tptr;
2121                tlen = len;
2122
2123                ND_TCHECK2(tptr[0], 5);
2124                ND_PRINT((ndo, "\n\t    Tunnel-type %s (%u), Flags [%s], MPLS Label %u",
2125                       tok2str(bgp_pmsi_tunnel_values, "Unknown", tunnel_type),
2126                       tunnel_type,
2127                       bittok2str(bgp_pmsi_flag_values, "none", flags),
2128                       EXTRACT_24BITS(tptr+2)>>4));
2129
2130                tptr +=5;
2131                tlen -= 5;
2132
2133                switch (tunnel_type) {
2134                case BGP_PMSI_TUNNEL_PIM_SM: /* fall through */
2135                case BGP_PMSI_TUNNEL_PIM_BIDIR:
2136                    ND_TCHECK2(tptr[0], 8);
2137                    ND_PRINT((ndo, "\n\t      Sender %s, P-Group %s",
2138                           ipaddr_string(ndo, tptr),
2139                           ipaddr_string(ndo, tptr+4)));
2140                    break;
2141
2142                case BGP_PMSI_TUNNEL_PIM_SSM:
2143                    ND_TCHECK2(tptr[0], 8);
2144                    ND_PRINT((ndo, "\n\t      Root-Node %s, P-Group %s",
2145                           ipaddr_string(ndo, tptr),
2146                           ipaddr_string(ndo, tptr+4)));
2147                    break;
2148                case BGP_PMSI_TUNNEL_INGRESS:
2149                    ND_TCHECK2(tptr[0], 4);
2150                    ND_PRINT((ndo, "\n\t      Tunnel-Endpoint %s",
2151                           ipaddr_string(ndo, tptr)));
2152                    break;
2153                case BGP_PMSI_TUNNEL_LDP_P2MP: /* fall through */
2154                case BGP_PMSI_TUNNEL_LDP_MP2MP:
2155                    ND_TCHECK2(tptr[0], 8);
2156                    ND_PRINT((ndo, "\n\t      Root-Node %s, LSP-ID 0x%08x",
2157                           ipaddr_string(ndo, tptr),
2158                           EXTRACT_32BITS(tptr+4)));
2159                    break;
2160                case BGP_PMSI_TUNNEL_RSVP_P2MP:
2161                    ND_TCHECK2(tptr[0], 8);
2162                    ND_PRINT((ndo, "\n\t      Extended-Tunnel-ID %s, P2MP-ID 0x%08x",
2163                           ipaddr_string(ndo, tptr),
2164                           EXTRACT_32BITS(tptr+4)));
2165                    break;
2166                default:
2167                    if (ndo->ndo_vflag <= 1) {
2168                        print_unknown_data(ndo, tptr, "\n\t      ", tlen);
2169                    }
2170                }
2171                break;
2172        }
2173	case BGPTYPE_AIGP:
2174	{
2175		uint8_t type;
2176		uint16_t length;
2177
2178		ND_TCHECK2(tptr[0], 3);
2179
2180		tlen = len;
2181
2182		while (tlen >= 3) {
2183
2184		    type = *tptr;
2185		    length = EXTRACT_16BITS(tptr+1);
2186
2187		    ND_PRINT((ndo, "\n\t    %s TLV (%u), length %u",
2188			      tok2str(bgp_aigp_values, "Unknown", type),
2189			      type, length));
2190
2191		    /*
2192		     * Check if we can read the TLV data.
2193		     */
2194		    ND_TCHECK2(tptr[3], length - 3);
2195
2196		    switch (type) {
2197
2198		    case BGP_AIGP_TLV:
2199		        ND_TCHECK2(tptr[3], 8);
2200			ND_PRINT((ndo, ", metric %" PRIu64,
2201				  EXTRACT_64BITS(tptr+3)));
2202			break;
2203
2204		    default:
2205			if (ndo->ndo_vflag <= 1) {
2206			    print_unknown_data(ndo, tptr+3,"\n\t      ", length-3);
2207			}
2208		    }
2209
2210		    tptr += length;
2211		    tlen -= length;
2212		}
2213		break;
2214	}
2215        case BGPTYPE_ATTR_SET:
2216                ND_TCHECK2(tptr[0], 4);
2217                if (len < 4)
2218                	goto trunc;
2219		ND_PRINT((ndo, "\n\t    Origin AS: %s",
2220		    as_printf(ndo, astostr, sizeof(astostr), EXTRACT_32BITS(tptr))));
2221		tptr+=4;
2222                len -=4;
2223
2224                while (len) {
2225                    u_int aflags, alenlen, alen;
2226
2227                    ND_TCHECK2(tptr[0], 2);
2228                    if (len < 2)
2229                        goto trunc;
2230                    aflags = *tptr;
2231                    atype = *(tptr + 1);
2232                    tptr += 2;
2233                    len -= 2;
2234                    alenlen = bgp_attr_lenlen(aflags, tptr);
2235                    ND_TCHECK2(tptr[0], alenlen);
2236                    if (len < alenlen)
2237                        goto trunc;
2238                    alen = bgp_attr_len(aflags, tptr);
2239                    tptr += alenlen;
2240                    len -= alenlen;
2241
2242                    ND_PRINT((ndo, "\n\t      %s (%u), length: %u",
2243                           tok2str(bgp_attr_values,
2244                                      "Unknown Attribute", atype),
2245                           atype,
2246                           alen));
2247
2248                    if (aflags) {
2249                        ND_PRINT((ndo, ", Flags [%s%s%s%s",
2250                               aflags & 0x80 ? "O" : "",
2251                               aflags & 0x40 ? "T" : "",
2252                               aflags & 0x20 ? "P" : "",
2253                               aflags & 0x10 ? "E" : ""));
2254                        if (aflags & 0xf)
2255                            ND_PRINT((ndo, "+%x", aflags & 0xf));
2256                        ND_PRINT((ndo, "]: "));
2257                    }
2258                    /* FIXME check for recursion */
2259                    if (!bgp_attr_print(ndo, atype, tptr, alen))
2260                        return 0;
2261                    tptr += alen;
2262                    len -= alen;
2263		}
2264                break;
2265
2266	case BGPTYPE_LARGE_COMMUNITY:
2267		if (len == 0 || len % 12) {
2268			ND_PRINT((ndo, "invalid len"));
2269			break;
2270		}
2271		ND_PRINT((ndo, "\n\t    "));
2272		while (len > 0) {
2273			ND_TCHECK2(*tptr, 12);
2274			ND_PRINT((ndo, "%u:%u:%u%s",
2275				 EXTRACT_32BITS(tptr),
2276				 EXTRACT_32BITS(tptr + 4),
2277				 EXTRACT_32BITS(tptr + 8),
2278				 (len > 12) ? ", " : ""));
2279                        tptr += 12;
2280                        len -= 12;
2281		}
2282		break;
2283	default:
2284	    ND_TCHECK2(*pptr,len);
2285            ND_PRINT((ndo, "\n\t    no Attribute %u decoder", atype)); /* we have no decoder for the attribute */
2286            if (ndo->ndo_vflag <= 1)
2287                print_unknown_data(ndo, pptr, "\n\t    ", len);
2288            break;
2289	}
2290        if (ndo->ndo_vflag > 1 && len) { /* omit zero length attributes*/
2291            ND_TCHECK2(*pptr,len);
2292            print_unknown_data(ndo, pptr, "\n\t    ", len);
2293        }
2294        return 1;
2295
2296trunc:
2297        return 0;
2298}
2299
2300static void
2301bgp_capabilities_print(netdissect_options *ndo,
2302                       const u_char *opt, int caps_len)
2303{
2304	int cap_type, cap_len, tcap_len, cap_offset;
2305        int i = 0;
2306
2307        while (i < caps_len) {
2308                ND_TCHECK2(opt[i], BGP_CAP_HEADER_SIZE);
2309                cap_type=opt[i];
2310                cap_len=opt[i+1];
2311                tcap_len=cap_len;
2312                ND_PRINT((ndo, "\n\t      %s (%u), length: %u",
2313                       tok2str(bgp_capcode_values, "Unknown",
2314                                  cap_type),
2315                       cap_type,
2316                       cap_len));
2317                ND_TCHECK2(opt[i+2], cap_len);
2318                switch (cap_type) {
2319                case BGP_CAPCODE_MP:
2320                    ND_PRINT((ndo, "\n\t\tAFI %s (%u), SAFI %s (%u)",
2321                           tok2str(af_values, "Unknown",
2322                                      EXTRACT_16BITS(opt+i+2)),
2323                           EXTRACT_16BITS(opt+i+2),
2324                           tok2str(bgp_safi_values, "Unknown",
2325                                      opt[i+5]),
2326                           opt[i+5]));
2327                    break;
2328                case BGP_CAPCODE_RESTART:
2329                    ND_PRINT((ndo, "\n\t\tRestart Flags: [%s], Restart Time %us",
2330                           ((opt[i+2])&0x80) ? "R" : "none",
2331                           EXTRACT_16BITS(opt+i+2)&0xfff));
2332                    tcap_len-=2;
2333                    cap_offset=4;
2334                    while(tcap_len>=4) {
2335                        ND_PRINT((ndo, "\n\t\t  AFI %s (%u), SAFI %s (%u), Forwarding state preserved: %s",
2336                               tok2str(af_values,"Unknown",
2337                                          EXTRACT_16BITS(opt+i+cap_offset)),
2338                               EXTRACT_16BITS(opt+i+cap_offset),
2339                               tok2str(bgp_safi_values,"Unknown",
2340                                          opt[i+cap_offset+2]),
2341                               opt[i+cap_offset+2],
2342                               ((opt[i+cap_offset+3])&0x80) ? "yes" : "no" ));
2343                        tcap_len-=4;
2344                        cap_offset+=4;
2345                    }
2346                    break;
2347                case BGP_CAPCODE_RR:
2348                case BGP_CAPCODE_RR_CISCO:
2349                    break;
2350                case BGP_CAPCODE_AS_NEW:
2351
2352                    /*
2353                     * Extract the 4 byte AS number encoded.
2354                     */
2355                    if (cap_len == 4) {
2356                        ND_PRINT((ndo, "\n\t\t 4 Byte AS %s",
2357                            as_printf(ndo, astostr, sizeof(astostr),
2358                            EXTRACT_32BITS(opt + i + 2))));
2359                    }
2360                    break;
2361                case BGP_CAPCODE_ADD_PATH:
2362                    cap_offset=2;
2363                    if (tcap_len == 0) {
2364                        ND_PRINT((ndo, " (bogus)")); /* length */
2365                        break;
2366                    }
2367                    while (tcap_len > 0) {
2368                        if (tcap_len < 4) {
2369                            ND_PRINT((ndo, "\n\t\t(invalid)"));
2370                            break;
2371                        }
2372                        ND_PRINT((ndo, "\n\t\tAFI %s (%u), SAFI %s (%u), Send/Receive: %s",
2373                                  tok2str(af_values,"Unknown",EXTRACT_16BITS(opt+i+cap_offset)),
2374                                  EXTRACT_16BITS(opt+i+cap_offset),
2375                                  tok2str(bgp_safi_values,"Unknown",opt[i+cap_offset+2]),
2376                                  opt[i+cap_offset+2],
2377                                  tok2str(bgp_add_path_recvsend,"Bogus (0x%02x)",opt[i+cap_offset+3])
2378                        ));
2379                        tcap_len-=4;
2380                        cap_offset+=4;
2381                    }
2382                    break;
2383                default:
2384                    ND_PRINT((ndo, "\n\t\tno decoder for Capability %u",
2385                           cap_type));
2386                    if (ndo->ndo_vflag <= 1)
2387                        print_unknown_data(ndo, &opt[i+2], "\n\t\t", cap_len);
2388                    break;
2389                }
2390                if (ndo->ndo_vflag > 1 && cap_len > 0) {
2391                    print_unknown_data(ndo, &opt[i+2], "\n\t\t", cap_len);
2392                }
2393                i += BGP_CAP_HEADER_SIZE + cap_len;
2394        }
2395        return;
2396
2397trunc:
2398	ND_PRINT((ndo, "[|BGP]"));
2399}
2400
2401static void
2402bgp_open_print(netdissect_options *ndo,
2403               const u_char *dat, int length)
2404{
2405	struct bgp_open bgpo;
2406	struct bgp_opt bgpopt;
2407	const u_char *opt;
2408	int i;
2409
2410	ND_TCHECK2(dat[0], BGP_OPEN_SIZE);
2411	memcpy(&bgpo, dat, BGP_OPEN_SIZE);
2412
2413	ND_PRINT((ndo, "\n\t  Version %d, ", bgpo.bgpo_version));
2414	ND_PRINT((ndo, "my AS %s, ",
2415	    as_printf(ndo, astostr, sizeof(astostr), ntohs(bgpo.bgpo_myas))));
2416	ND_PRINT((ndo, "Holdtime %us, ", ntohs(bgpo.bgpo_holdtime)));
2417	ND_PRINT((ndo, "ID %s", ipaddr_string(ndo, &bgpo.bgpo_id)));
2418	ND_PRINT((ndo, "\n\t  Optional parameters, length: %u", bgpo.bgpo_optlen));
2419
2420        /* some little sanity checking */
2421        if (length < bgpo.bgpo_optlen+BGP_OPEN_SIZE)
2422            return;
2423
2424	/* ugly! */
2425	opt = &((const struct bgp_open *)dat)->bgpo_optlen;
2426	opt++;
2427
2428	i = 0;
2429	while (i < bgpo.bgpo_optlen) {
2430		ND_TCHECK2(opt[i], BGP_OPT_SIZE);
2431		memcpy(&bgpopt, &opt[i], BGP_OPT_SIZE);
2432		if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) {
2433			ND_PRINT((ndo, "\n\t     Option %d, length: %u", bgpopt.bgpopt_type, bgpopt.bgpopt_len));
2434			break;
2435		}
2436
2437		ND_PRINT((ndo, "\n\t    Option %s (%u), length: %u",
2438		       tok2str(bgp_opt_values,"Unknown",
2439				  bgpopt.bgpopt_type),
2440		       bgpopt.bgpopt_type,
2441		       bgpopt.bgpopt_len));
2442
2443		/* now let's decode the options we know*/
2444		switch(bgpopt.bgpopt_type) {
2445
2446		case BGP_OPT_CAP:
2447			bgp_capabilities_print(ndo, &opt[i+BGP_OPT_SIZE],
2448			    bgpopt.bgpopt_len);
2449			break;
2450
2451		case BGP_OPT_AUTH:
2452		default:
2453		       ND_PRINT((ndo, "\n\t      no decoder for option %u",
2454			   bgpopt.bgpopt_type));
2455		       break;
2456		}
2457		i += BGP_OPT_SIZE + bgpopt.bgpopt_len;
2458	}
2459	return;
2460trunc:
2461	ND_PRINT((ndo, "[|BGP]"));
2462}
2463
2464static void
2465bgp_update_print(netdissect_options *ndo,
2466                 const u_char *dat, int length)
2467{
2468	struct bgp bgp;
2469	const u_char *p;
2470	int withdrawn_routes_len;
2471	int len;
2472	int i;
2473
2474	ND_TCHECK2(dat[0], BGP_SIZE);
2475	if (length < BGP_SIZE)
2476		goto trunc;
2477	memcpy(&bgp, dat, BGP_SIZE);
2478	p = dat + BGP_SIZE;	/*XXX*/
2479	length -= BGP_SIZE;
2480
2481	/* Unfeasible routes */
2482	ND_TCHECK2(p[0], 2);
2483	if (length < 2)
2484		goto trunc;
2485	withdrawn_routes_len = EXTRACT_16BITS(p);
2486	p += 2;
2487	length -= 2;
2488	if (withdrawn_routes_len) {
2489		/*
2490		 * Without keeping state from the original NLRI message,
2491		 * it's not possible to tell if this a v4 or v6 route,
2492		 * so only try to decode it if we're not v6 enabled.
2493	         */
2494		ND_TCHECK2(p[0], withdrawn_routes_len);
2495		if (length < withdrawn_routes_len)
2496			goto trunc;
2497		ND_PRINT((ndo, "\n\t  Withdrawn routes: %d bytes", withdrawn_routes_len));
2498		p += withdrawn_routes_len;
2499		length -= withdrawn_routes_len;
2500	}
2501
2502	ND_TCHECK2(p[0], 2);
2503	if (length < 2)
2504		goto trunc;
2505	len = EXTRACT_16BITS(p);
2506	p += 2;
2507	length -= 2;
2508
2509        if (withdrawn_routes_len == 0 && len == 0 && length == 0) {
2510            /* No withdrawn routes, no path attributes, no NLRI */
2511            ND_PRINT((ndo, "\n\t  End-of-Rib Marker (empty NLRI)"));
2512            return;
2513        }
2514
2515	if (len) {
2516		/* do something more useful!*/
2517		while (len) {
2518			int aflags, atype, alenlen, alen;
2519
2520			ND_TCHECK2(p[0], 2);
2521			if (len < 2)
2522			    goto trunc;
2523			if (length < 2)
2524			    goto trunc;
2525			aflags = *p;
2526			atype = *(p + 1);
2527			p += 2;
2528			len -= 2;
2529			length -= 2;
2530			alenlen = bgp_attr_lenlen(aflags, p);
2531			ND_TCHECK2(p[0], alenlen);
2532			if (len < alenlen)
2533			    goto trunc;
2534			if (length < alenlen)
2535			    goto trunc;
2536			alen = bgp_attr_len(aflags, p);
2537			p += alenlen;
2538			len -= alenlen;
2539			length -= alenlen;
2540
2541			ND_PRINT((ndo, "\n\t  %s (%u), length: %u",
2542                              tok2str(bgp_attr_values, "Unknown Attribute",
2543					 atype),
2544                              atype,
2545                              alen));
2546
2547			if (aflags) {
2548				ND_PRINT((ndo, ", Flags [%s%s%s%s",
2549					aflags & 0x80 ? "O" : "",
2550					aflags & 0x40 ? "T" : "",
2551					aflags & 0x20 ? "P" : "",
2552					aflags & 0x10 ? "E" : ""));
2553				if (aflags & 0xf)
2554					ND_PRINT((ndo, "+%x", aflags & 0xf));
2555				ND_PRINT((ndo, "]: "));
2556			}
2557			if (len < alen)
2558				goto trunc;
2559			if (length < alen)
2560				goto trunc;
2561			if (!bgp_attr_print(ndo, atype, p, alen))
2562				goto trunc;
2563			p += alen;
2564			len -= alen;
2565			length -= alen;
2566		}
2567	}
2568
2569	if (length) {
2570		/*
2571		 * XXX - what if they're using the "Advertisement of
2572		 * Multiple Paths in BGP" feature:
2573		 *
2574		 * https://datatracker.ietf.org/doc/draft-ietf-idr-add-paths/
2575		 *
2576		 * http://tools.ietf.org/html/draft-ietf-idr-add-paths-06
2577		 */
2578		ND_PRINT((ndo, "\n\t  Updated routes:"));
2579		while (length) {
2580			char buf[MAXHOSTNAMELEN + 100];
2581			i = decode_prefix4(ndo, p, length, buf, sizeof(buf));
2582			if (i == -1) {
2583				ND_PRINT((ndo, "\n\t    (illegal prefix length)"));
2584				break;
2585			} else if (i == -2)
2586				goto trunc;
2587			else if (i == -3)
2588				goto trunc; /* bytes left, but not enough */
2589			else {
2590				ND_PRINT((ndo, "\n\t    %s", buf));
2591				p += i;
2592				length -= i;
2593			}
2594		}
2595	}
2596	return;
2597trunc:
2598	ND_PRINT((ndo, "[|BGP]"));
2599}
2600
2601static void
2602bgp_notification_print(netdissect_options *ndo,
2603                       const u_char *dat, int length)
2604{
2605	struct bgp_notification bgpn;
2606	const u_char *tptr;
2607
2608	ND_TCHECK2(dat[0], BGP_NOTIFICATION_SIZE);
2609	memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE);
2610
2611        /* some little sanity checking */
2612        if (length<BGP_NOTIFICATION_SIZE)
2613            return;
2614
2615	ND_PRINT((ndo, ", %s (%u)",
2616	       tok2str(bgp_notify_major_values, "Unknown Error",
2617			  bgpn.bgpn_major),
2618	       bgpn.bgpn_major));
2619
2620        switch (bgpn.bgpn_major) {
2621
2622        case BGP_NOTIFY_MAJOR_MSG:
2623            ND_PRINT((ndo, ", subcode %s (%u)",
2624		   tok2str(bgp_notify_minor_msg_values, "Unknown",
2625			      bgpn.bgpn_minor),
2626		   bgpn.bgpn_minor));
2627            break;
2628        case BGP_NOTIFY_MAJOR_OPEN:
2629            ND_PRINT((ndo, ", subcode %s (%u)",
2630		   tok2str(bgp_notify_minor_open_values, "Unknown",
2631			      bgpn.bgpn_minor),
2632		   bgpn.bgpn_minor));
2633            break;
2634        case BGP_NOTIFY_MAJOR_UPDATE:
2635            ND_PRINT((ndo, ", subcode %s (%u)",
2636		   tok2str(bgp_notify_minor_update_values, "Unknown",
2637			      bgpn.bgpn_minor),
2638		   bgpn.bgpn_minor));
2639            break;
2640        case BGP_NOTIFY_MAJOR_FSM:
2641            ND_PRINT((ndo, " subcode %s (%u)",
2642		   tok2str(bgp_notify_minor_fsm_values, "Unknown",
2643			      bgpn.bgpn_minor),
2644		   bgpn.bgpn_minor));
2645            break;
2646        case BGP_NOTIFY_MAJOR_CAP:
2647            ND_PRINT((ndo, " subcode %s (%u)",
2648		   tok2str(bgp_notify_minor_cap_values, "Unknown",
2649			      bgpn.bgpn_minor),
2650		   bgpn.bgpn_minor));
2651            break;
2652        case BGP_NOTIFY_MAJOR_CEASE:
2653            ND_PRINT((ndo, ", subcode %s (%u)",
2654		   tok2str(bgp_notify_minor_cease_values, "Unknown",
2655			      bgpn.bgpn_minor),
2656		   bgpn.bgpn_minor));
2657
2658	    /* draft-ietf-idr-cease-subcode-02 mentions optionally 7 bytes
2659             * for the maxprefix subtype, which may contain AFI, SAFI and MAXPREFIXES
2660             */
2661	    if(bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_MAXPRFX && length >= BGP_NOTIFICATION_SIZE + 7) {
2662		tptr = dat + BGP_NOTIFICATION_SIZE;
2663		ND_TCHECK2(*tptr, 7);
2664		ND_PRINT((ndo, ", AFI %s (%u), SAFI %s (%u), Max Prefixes: %u",
2665		       tok2str(af_values, "Unknown",
2666				  EXTRACT_16BITS(tptr)),
2667		       EXTRACT_16BITS(tptr),
2668		       tok2str(bgp_safi_values, "Unknown", *(tptr+2)),
2669		       *(tptr+2),
2670		       EXTRACT_32BITS(tptr+3)));
2671	    }
2672            break;
2673        default:
2674            break;
2675        }
2676
2677	return;
2678trunc:
2679	ND_PRINT((ndo, "[|BGP]"));
2680}
2681
2682static void
2683bgp_route_refresh_print(netdissect_options *ndo,
2684                        const u_char *pptr, int len)
2685{
2686        const struct bgp_route_refresh *bgp_route_refresh_header;
2687
2688	ND_TCHECK2(pptr[0], BGP_ROUTE_REFRESH_SIZE);
2689
2690        /* some little sanity checking */
2691        if (len<BGP_ROUTE_REFRESH_SIZE)
2692            return;
2693
2694        bgp_route_refresh_header = (const struct bgp_route_refresh *)pptr;
2695
2696        ND_PRINT((ndo, "\n\t  AFI %s (%u), SAFI %s (%u)",
2697               tok2str(af_values,"Unknown",
2698			  /* this stinks but the compiler pads the structure
2699			   * weird */
2700			  EXTRACT_16BITS(&bgp_route_refresh_header->afi)),
2701               EXTRACT_16BITS(&bgp_route_refresh_header->afi),
2702               tok2str(bgp_safi_values,"Unknown",
2703			  bgp_route_refresh_header->safi),
2704               bgp_route_refresh_header->safi));
2705
2706        if (ndo->ndo_vflag > 1) {
2707            ND_TCHECK2(*pptr, len);
2708            print_unknown_data(ndo, pptr, "\n\t  ", len);
2709        }
2710
2711        return;
2712trunc:
2713	ND_PRINT((ndo, "[|BGP]"));
2714}
2715
2716static int
2717bgp_header_print(netdissect_options *ndo,
2718                 const u_char *dat, int length)
2719{
2720	struct bgp bgp;
2721
2722	ND_TCHECK2(dat[0], BGP_SIZE);
2723	memcpy(&bgp, dat, BGP_SIZE);
2724	ND_PRINT((ndo, "\n\t%s Message (%u), length: %u",
2725               tok2str(bgp_msg_values, "Unknown", bgp.bgp_type),
2726               bgp.bgp_type,
2727               length));
2728
2729	switch (bgp.bgp_type) {
2730	case BGP_OPEN:
2731		bgp_open_print(ndo, dat, length);
2732		break;
2733	case BGP_UPDATE:
2734		bgp_update_print(ndo, dat, length);
2735		break;
2736	case BGP_NOTIFICATION:
2737		bgp_notification_print(ndo, dat, length);
2738		break;
2739        case BGP_KEEPALIVE:
2740                break;
2741        case BGP_ROUTE_REFRESH:
2742                bgp_route_refresh_print(ndo, dat, length);
2743                break;
2744        default:
2745                /* we have no decoder for the BGP message */
2746                ND_TCHECK2(*dat, length);
2747                ND_PRINT((ndo, "\n\t  no Message %u decoder", bgp.bgp_type));
2748                print_unknown_data(ndo, dat, "\n\t  ", length);
2749                break;
2750	}
2751	return 1;
2752trunc:
2753	ND_PRINT((ndo, "[|BGP]"));
2754	return 0;
2755}
2756
2757void
2758bgp_print(netdissect_options *ndo,
2759          const u_char *dat, int length)
2760{
2761	const u_char *p;
2762	const u_char *ep;
2763	const u_char *start;
2764	const u_char marker[] = {
2765		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2766		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2767	};
2768	struct bgp bgp;
2769	uint16_t hlen;
2770
2771	ep = dat + length;
2772	if (ndo->ndo_snapend < dat + length)
2773		ep = ndo->ndo_snapend;
2774
2775	ND_PRINT((ndo, ": BGP"));
2776
2777        if (ndo->ndo_vflag < 1) /* lets be less chatty */
2778                return;
2779
2780	p = dat;
2781	start = p;
2782	while (p < ep) {
2783		if (!ND_TTEST2(p[0], 1))
2784			break;
2785		if (p[0] != 0xff) {
2786			p++;
2787			continue;
2788		}
2789
2790		if (!ND_TTEST2(p[0], sizeof(marker)))
2791			break;
2792		if (memcmp(p, marker, sizeof(marker)) != 0) {
2793			p++;
2794			continue;
2795		}
2796
2797		/* found BGP header */
2798		ND_TCHECK2(p[0], BGP_SIZE);	/*XXX*/
2799		memcpy(&bgp, p, BGP_SIZE);
2800
2801		if (start != p)
2802			ND_PRINT((ndo, " [|BGP]"));
2803
2804		hlen = ntohs(bgp.bgp_len);
2805		if (hlen < BGP_SIZE) {
2806			ND_PRINT((ndo, "\n[|BGP Bogus header length %u < %u]", hlen,
2807			    BGP_SIZE));
2808			break;
2809		}
2810
2811		if (ND_TTEST2(p[0], hlen)) {
2812			if (!bgp_header_print(ndo, p, hlen))
2813				return;
2814			p += hlen;
2815			start = p;
2816		} else {
2817			ND_PRINT((ndo, "\n[|BGP %s]",
2818			       tok2str(bgp_msg_values,
2819					  "Unknown Message Type",
2820					  bgp.bgp_type)));
2821			break;
2822		}
2823	}
2824
2825	return;
2826
2827trunc:
2828	ND_PRINT((ndo, " [|BGP]"));
2829}
2830
2831/*
2832 * Local Variables:
2833 * c-style: whitesmith
2834 * c-basic-offset: 4
2835 * End:
2836 */
2837