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