156893Sfenner/* 256893Sfenner * Copyright (C) 1999 WIDE Project. 356893Sfenner * All rights reserved. 4127668Sbms * 556893Sfenner * Redistribution and use in source and binary forms, with or without 656893Sfenner * modification, are permitted provided that the following conditions 756893Sfenner * are met: 856893Sfenner * 1. Redistributions of source code must retain the above copyright 956893Sfenner * notice, this list of conditions and the following disclaimer. 1056893Sfenner * 2. Redistributions in binary form must reproduce the above copyright 1156893Sfenner * notice, this list of conditions and the following disclaimer in the 1256893Sfenner * documentation and/or other materials provided with the distribution. 1356893Sfenner * 3. Neither the name of the project nor the names of its contributors 1456893Sfenner * may be used to endorse or promote products derived from this software 1556893Sfenner * without specific prior written permission. 16127668Sbms * 1756893Sfenner * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 1856893Sfenner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1956893Sfenner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2056893Sfenner * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 2156893Sfenner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2256893Sfenner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2356893Sfenner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2456893Sfenner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2556893Sfenner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2656893Sfenner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2756893Sfenner * SUCH DAMAGE. 28127668Sbms * 29127668Sbms * Extensively modified by Hannes Gredler (hannes@juniper.net) for more 30127668Sbms * complete BGP support. 3156893Sfenner */ 3256893Sfenner 3356893Sfenner#ifdef HAVE_CONFIG_H 3456893Sfenner#include "config.h" 3556893Sfenner#endif 3656893Sfenner 3756893Sfenner#ifndef lint 38127668Sbmsstatic const char rcsid[] _U_ = 39214478Srpaulo "@(#) $Header: /tcpdump/master/tcpdump/print-bgp.c,v 1.118 2007-12-07 15:54:52 hannes Exp $"; 4056893Sfenner#endif 4156893Sfenner 42127668Sbms#include <tcpdump-stdinc.h> 4356893Sfenner 4456893Sfenner#include <stdio.h> 4556893Sfenner#include <string.h> 4656893Sfenner 4756893Sfenner#include "interface.h" 48146773Ssam#include "decode_prefix.h" 4956893Sfenner#include "addrtoname.h" 5075115Sfenner#include "extract.h" 51146773Ssam#include "bgp.h" 52190207Srpaulo#include "af.h" 53146773Ssam#include "l2vpn.h" 5456893Sfenner 5556893Sfennerstruct bgp { 5656893Sfenner u_int8_t bgp_marker[16]; 5756893Sfenner u_int16_t bgp_len; 5856893Sfenner u_int8_t bgp_type; 5956893Sfenner}; 6056893Sfenner#define BGP_SIZE 19 /* unaligned */ 6156893Sfenner 6256893Sfenner#define BGP_OPEN 1 6356893Sfenner#define BGP_UPDATE 2 6456893Sfenner#define BGP_NOTIFICATION 3 6556893Sfenner#define BGP_KEEPALIVE 4 66127668Sbms#define BGP_ROUTE_REFRESH 5 6756893Sfenner 68127668Sbmsstatic struct tok bgp_msg_values[] = { 69127668Sbms { BGP_OPEN, "Open"}, 70127668Sbms { BGP_UPDATE, "Update"}, 71127668Sbms { BGP_NOTIFICATION, "Notification"}, 72127668Sbms { BGP_KEEPALIVE, "Keepalive"}, 73127668Sbms { BGP_ROUTE_REFRESH, "Route Refresh"}, 74127668Sbms { 0, NULL} 75127668Sbms}; 76127668Sbms 7756893Sfennerstruct bgp_open { 7856893Sfenner u_int8_t bgpo_marker[16]; 7956893Sfenner u_int16_t bgpo_len; 8056893Sfenner u_int8_t bgpo_type; 8156893Sfenner u_int8_t bgpo_version; 8256893Sfenner u_int16_t bgpo_myas; 8356893Sfenner u_int16_t bgpo_holdtime; 8456893Sfenner u_int32_t bgpo_id; 8556893Sfenner u_int8_t bgpo_optlen; 8656893Sfenner /* options should follow */ 8756893Sfenner}; 8898524Sfenner#define BGP_OPEN_SIZE 29 /* unaligned */ 8956893Sfenner 9056893Sfennerstruct bgp_opt { 9156893Sfenner u_int8_t bgpopt_type; 9256893Sfenner u_int8_t bgpopt_len; 9356893Sfenner /* variable length */ 9456893Sfenner}; 9598524Sfenner#define BGP_OPT_SIZE 2 /* some compilers may pad to 4 bytes */ 96241235Sdelphij#define BGP_CAP_HEADER_SIZE 2 /* some compilers may pad to 4 bytes */ 9756893Sfenner 9856893Sfennerstruct bgp_notification { 9956893Sfenner u_int8_t bgpn_marker[16]; 10056893Sfenner u_int16_t bgpn_len; 10156893Sfenner u_int8_t bgpn_type; 10256893Sfenner u_int8_t bgpn_major; 10356893Sfenner u_int8_t bgpn_minor; 10456893Sfenner}; 10598524Sfenner#define BGP_NOTIFICATION_SIZE 21 /* unaligned */ 10656893Sfenner 107127668Sbmsstruct bgp_route_refresh { 108127668Sbms u_int8_t bgp_marker[16]; 109127668Sbms u_int16_t len; 110127668Sbms u_int8_t type; 111127668Sbms u_int8_t afi[2]; /* the compiler messes this structure up */ 112127668Sbms u_int8_t res; /* when doing misaligned sequences of int8 and int16 */ 113127668Sbms u_int8_t safi; /* afi should be int16 - so we have to access it using */ 114127668Sbms}; /* EXTRACT_16BITS(&bgp_route_refresh->afi) (sigh) */ 115127668Sbms#define BGP_ROUTE_REFRESH_SIZE 23 116127668Sbms 117241235Sdelphij#define bgp_attr_lenlen(flags, p) \ 118241235Sdelphij (((flags) & 0x10) ? 2 : 1) 119241235Sdelphij#define bgp_attr_len(flags, p) \ 120241235Sdelphij (((flags) & 0x10) ? EXTRACT_16BITS(p) : *(p)) 12156893Sfenner 12256893Sfenner#define BGPTYPE_ORIGIN 1 12356893Sfenner#define BGPTYPE_AS_PATH 2 12456893Sfenner#define BGPTYPE_NEXT_HOP 3 12556893Sfenner#define BGPTYPE_MULTI_EXIT_DISC 4 12656893Sfenner#define BGPTYPE_LOCAL_PREF 5 12756893Sfenner#define BGPTYPE_ATOMIC_AGGREGATE 6 12856893Sfenner#define BGPTYPE_AGGREGATOR 7 12956893Sfenner#define BGPTYPE_COMMUNITIES 8 /* RFC1997 */ 13056893Sfenner#define BGPTYPE_ORIGINATOR_ID 9 /* RFC1998 */ 13156893Sfenner#define BGPTYPE_CLUSTER_LIST 10 /* RFC1998 */ 132127668Sbms#define BGPTYPE_DPA 11 /* draft-ietf-idr-bgp-dpa */ 13356893Sfenner#define BGPTYPE_ADVERTISERS 12 /* RFC1863 */ 13456893Sfenner#define BGPTYPE_RCID_PATH 13 /* RFC1863 */ 13556893Sfenner#define BGPTYPE_MP_REACH_NLRI 14 /* RFC2283 */ 13656893Sfenner#define BGPTYPE_MP_UNREACH_NLRI 15 /* RFC2283 */ 137127668Sbms#define BGPTYPE_EXTD_COMMUNITIES 16 /* draft-ietf-idr-bgp-ext-communities */ 138190207Srpaulo#define BGPTYPE_AS4_PATH 17 /* RFC4893 */ 139190207Srpaulo#define BGPTYPE_AGGREGATOR4 18 /* RFC4893 */ 140190207Srpaulo#define BGPTYPE_PMSI_TUNNEL 22 /* draft-ietf-l3vpn-2547bis-mcast-bgp-02.txt */ 141146773Ssam#define BGPTYPE_ATTR_SET 128 /* draft-marques-ppvpn-ibgp */ 14256893Sfenner 143146773Ssam#define BGP_MP_NLRI_MINSIZE 3 /* End of RIB Marker detection */ 144146773Ssam 145127668Sbmsstatic struct tok bgp_attr_values[] = { 146127668Sbms { BGPTYPE_ORIGIN, "Origin"}, 147127668Sbms { BGPTYPE_AS_PATH, "AS Path"}, 148190207Srpaulo { BGPTYPE_AS4_PATH, "AS4 Path"}, 149127668Sbms { BGPTYPE_NEXT_HOP, "Next Hop"}, 150127668Sbms { BGPTYPE_MULTI_EXIT_DISC, "Multi Exit Discriminator"}, 151127668Sbms { BGPTYPE_LOCAL_PREF, "Local Preference"}, 152127668Sbms { BGPTYPE_ATOMIC_AGGREGATE, "Atomic Aggregate"}, 153127668Sbms { BGPTYPE_AGGREGATOR, "Aggregator"}, 154190207Srpaulo { BGPTYPE_AGGREGATOR4, "Aggregator4"}, 155127668Sbms { BGPTYPE_COMMUNITIES, "Community"}, 156127668Sbms { BGPTYPE_ORIGINATOR_ID, "Originator ID"}, 157127668Sbms { BGPTYPE_CLUSTER_LIST, "Cluster List"}, 158127668Sbms { BGPTYPE_DPA, "DPA"}, 159127668Sbms { BGPTYPE_ADVERTISERS, "Advertisers"}, 160127668Sbms { BGPTYPE_RCID_PATH, "RCID Path / Cluster ID"}, 161127668Sbms { BGPTYPE_MP_REACH_NLRI, "Multi-Protocol Reach NLRI"}, 162127668Sbms { BGPTYPE_MP_UNREACH_NLRI, "Multi-Protocol Unreach NLRI"}, 163127668Sbms { BGPTYPE_EXTD_COMMUNITIES, "Extended Community"}, 164190207Srpaulo { BGPTYPE_PMSI_TUNNEL, "PMSI Tunnel"}, 165146773Ssam { BGPTYPE_ATTR_SET, "Attribute Set"}, 166127668Sbms { 255, "Reserved for development"}, 167127668Sbms { 0, NULL} 168127668Sbms}; 16956893Sfenner 170127668Sbms#define BGP_AS_SET 1 171127668Sbms#define BGP_AS_SEQUENCE 2 172127668Sbms#define BGP_CONFED_AS_SEQUENCE 3 /* draft-ietf-idr-rfc3065bis-01 */ 173127668Sbms#define BGP_CONFED_AS_SET 4 /* draft-ietf-idr-rfc3065bis-01 */ 174127668Sbms 175190207Srpaulo#define BGP_AS_SEG_TYPE_MIN BGP_AS_SET 176190207Srpaulo#define BGP_AS_SEG_TYPE_MAX BGP_CONFED_AS_SET 177190207Srpaulo 178127668Sbmsstatic struct tok bgp_as_path_segment_open_values[] = { 179127668Sbms { BGP_AS_SEQUENCE, ""}, 180127668Sbms { BGP_AS_SET, "{ "}, 181127668Sbms { BGP_CONFED_AS_SEQUENCE, "( "}, 182127668Sbms { BGP_CONFED_AS_SET, "({ "}, 183127668Sbms { 0, NULL} 18456893Sfenner}; 18556893Sfenner 186127668Sbmsstatic struct tok bgp_as_path_segment_close_values[] = { 187127668Sbms { BGP_AS_SEQUENCE, ""}, 188127668Sbms { BGP_AS_SET, "}"}, 189127668Sbms { BGP_CONFED_AS_SEQUENCE, ")"}, 190127668Sbms { BGP_CONFED_AS_SET, "})"}, 191127668Sbms { 0, NULL} 19256893Sfenner}; 19356893Sfenner 194127668Sbms#define BGP_OPT_AUTH 1 195127668Sbms#define BGP_OPT_CAP 2 196127668Sbms 197127668Sbms 198127668Sbmsstatic struct tok bgp_opt_values[] = { 199127668Sbms { BGP_OPT_AUTH, "Authentication Information"}, 200127668Sbms { BGP_OPT_CAP, "Capabilities Advertisement"}, 201127668Sbms { 0, NULL} 20256893Sfenner}; 20356893Sfenner 204127668Sbms#define BGP_CAPCODE_MP 1 205127668Sbms#define BGP_CAPCODE_RR 2 206146773Ssam#define BGP_CAPCODE_ORF 3 /* XXX */ 207127668Sbms#define BGP_CAPCODE_RESTART 64 /* draft-ietf-idr-restart-05 */ 208146773Ssam#define BGP_CAPCODE_AS_NEW 65 /* XXX */ 209146773Ssam#define BGP_CAPCODE_DYN_CAP 67 /* XXX */ 210127668Sbms#define BGP_CAPCODE_RR_CISCO 128 211127668Sbms 212127668Sbmsstatic struct tok bgp_capcode_values[] = { 213127668Sbms { BGP_CAPCODE_MP, "Multiprotocol Extensions"}, 214127668Sbms { BGP_CAPCODE_RR, "Route Refresh"}, 215146773Ssam { BGP_CAPCODE_ORF, "Cooperative Route Filtering"}, 216127668Sbms { BGP_CAPCODE_RESTART, "Graceful Restart"}, 217146773Ssam { BGP_CAPCODE_AS_NEW, "32-Bit AS Number"}, 218146773Ssam { BGP_CAPCODE_DYN_CAP, "Dynamic Capability"}, 219127668Sbms { BGP_CAPCODE_RR_CISCO, "Route Refresh (Cisco)"}, 220127668Sbms { 0, NULL} 22156893Sfenner}; 22256893Sfenner 223127668Sbms#define BGP_NOTIFY_MAJOR_MSG 1 224127668Sbms#define BGP_NOTIFY_MAJOR_OPEN 2 225127668Sbms#define BGP_NOTIFY_MAJOR_UPDATE 3 226127668Sbms#define BGP_NOTIFY_MAJOR_HOLDTIME 4 227127668Sbms#define BGP_NOTIFY_MAJOR_FSM 5 228127668Sbms#define BGP_NOTIFY_MAJOR_CEASE 6 229127668Sbms#define BGP_NOTIFY_MAJOR_CAP 7 230127668Sbms 231127668Sbmsstatic struct tok bgp_notify_major_values[] = { 232127668Sbms { BGP_NOTIFY_MAJOR_MSG, "Message Header Error"}, 233127668Sbms { BGP_NOTIFY_MAJOR_OPEN, "OPEN Message Error"}, 234127668Sbms { BGP_NOTIFY_MAJOR_UPDATE, "UPDATE Message Error"}, 235127668Sbms { BGP_NOTIFY_MAJOR_HOLDTIME,"Hold Timer Expired"}, 236127668Sbms { BGP_NOTIFY_MAJOR_FSM, "Finite State Machine Error"}, 237127668Sbms { BGP_NOTIFY_MAJOR_CEASE, "Cease"}, 238127668Sbms { BGP_NOTIFY_MAJOR_CAP, "Capability Message Error"}, 239127668Sbms { 0, NULL} 24056893Sfenner}; 24156893Sfenner 242127668Sbms/* draft-ietf-idr-cease-subcode-02 */ 243127668Sbms#define BGP_NOTIFY_MINOR_CEASE_MAXPRFX 1 244127668Sbmsstatic struct tok bgp_notify_minor_cease_values[] = { 245127668Sbms { BGP_NOTIFY_MINOR_CEASE_MAXPRFX, "Maximum Number of Prefixes Reached"}, 246127668Sbms { 2, "Administratively Shutdown"}, 247127668Sbms { 3, "Peer Unconfigured"}, 248127668Sbms { 4, "Administratively Reset"}, 249127668Sbms { 5, "Connection Rejected"}, 250127668Sbms { 6, "Other Configuration Change"}, 251127668Sbms { 7, "Connection Collision Resolution"}, 252127668Sbms { 0, NULL} 25356893Sfenner}; 25456893Sfenner 255127668Sbmsstatic struct tok bgp_notify_minor_msg_values[] = { 256127668Sbms { 1, "Connection Not Synchronized"}, 257127668Sbms { 2, "Bad Message Length"}, 258127668Sbms { 3, "Bad Message Type"}, 259127668Sbms { 0, NULL} 26056893Sfenner}; 261127668Sbms 262127668Sbmsstatic struct tok bgp_notify_minor_open_values[] = { 263127668Sbms { 1, "Unsupported Version Number"}, 264127668Sbms { 2, "Bad Peer AS"}, 265127668Sbms { 3, "Bad BGP Identifier"}, 266127668Sbms { 4, "Unsupported Optional Parameter"}, 267127668Sbms { 5, "Authentication Failure"}, 268127668Sbms { 6, "Unacceptable Hold Time"}, 269190207Srpaulo { 7, "Capability Message Error"}, 270127668Sbms { 0, NULL} 27156893Sfenner}; 27256893Sfenner 273127668Sbmsstatic struct tok bgp_notify_minor_update_values[] = { 274127668Sbms { 1, "Malformed Attribute List"}, 275127668Sbms { 2, "Unrecognized Well-known Attribute"}, 276127668Sbms { 3, "Missing Well-known Attribute"}, 277127668Sbms { 4, "Attribute Flags Error"}, 278127668Sbms { 5, "Attribute Length Error"}, 279127668Sbms { 6, "Invalid ORIGIN Attribute"}, 280127668Sbms { 7, "AS Routing Loop"}, 281127668Sbms { 8, "Invalid NEXT_HOP Attribute"}, 282127668Sbms { 9, "Optional Attribute Error"}, 283127668Sbms { 10, "Invalid Network Field"}, 284127668Sbms { 11, "Malformed AS_PATH"}, 285127668Sbms { 0, NULL} 28656893Sfenner}; 28756893Sfenner 288127668Sbmsstatic struct tok bgp_notify_minor_cap_values[] = { 289127668Sbms { 1, "Invalid Action Value" }, 290127668Sbms { 2, "Invalid Capability Length" }, 291127668Sbms { 3, "Malformed Capability Value" }, 292127668Sbms { 4, "Unsupported Capability Code" }, 293127668Sbms { 0, NULL } 29456893Sfenner}; 29556893Sfenner 296127668Sbmsstatic struct tok bgp_origin_values[] = { 297127668Sbms { 0, "IGP"}, 298127668Sbms { 1, "EGP"}, 299127668Sbms { 2, "Incomplete"}, 300127668Sbms { 0, NULL} 301127668Sbms}; 302127668Sbms 303190207Srpaulo#define BGP_PMSI_TUNNEL_RSVP_P2MP 1 304190207Srpaulo#define BGP_PMSI_TUNNEL_LDP_P2MP 2 305190207Srpaulo#define BGP_PMSI_TUNNEL_PIM_SSM 3 306190207Srpaulo#define BGP_PMSI_TUNNEL_PIM_SM 4 307190207Srpaulo#define BGP_PMSI_TUNNEL_PIM_BIDIR 5 308190207Srpaulo#define BGP_PMSI_TUNNEL_INGRESS 6 309190207Srpaulo#define BGP_PMSI_TUNNEL_LDP_MP2MP 7 310190207Srpaulo 311190207Srpaulostatic struct tok bgp_pmsi_tunnel_values[] = { 312190207Srpaulo { BGP_PMSI_TUNNEL_RSVP_P2MP, "RSVP-TE P2MP LSP"}, 313190207Srpaulo { BGP_PMSI_TUNNEL_LDP_P2MP, "LDP P2MP LSP"}, 314190207Srpaulo { BGP_PMSI_TUNNEL_PIM_SSM, "PIM-SSM Tree"}, 315190207Srpaulo { BGP_PMSI_TUNNEL_PIM_SM, "PIM-SM Tree"}, 316190207Srpaulo { BGP_PMSI_TUNNEL_PIM_BIDIR, "PIM-Bidir Tree"}, 317190207Srpaulo { BGP_PMSI_TUNNEL_INGRESS, "Ingress Replication"}, 318190207Srpaulo { BGP_PMSI_TUNNEL_LDP_MP2MP, "LDP MP2MP LSP"}, 319190207Srpaulo { 0, NULL} 320190207Srpaulo}; 321190207Srpaulo 322190207Srpaulostatic struct tok bgp_pmsi_flag_values[] = { 323190207Srpaulo { 0x01, "Leaf Information required"}, 324190207Srpaulo { 0, NULL} 325190207Srpaulo}; 326190207Srpaulo 327190207Srpaulo 32856893Sfenner/* Subsequent address family identifier, RFC2283 section 7 */ 329127668Sbms#define SAFNUM_RES 0 330127668Sbms#define SAFNUM_UNICAST 1 331127668Sbms#define SAFNUM_MULTICAST 2 332127668Sbms#define SAFNUM_UNIMULTICAST 3 333127668Sbms/* labeled BGP RFC3107 */ 334127668Sbms#define SAFNUM_LABUNICAST 4 335190207Srpaulo/* draft-ietf-l3vpn-2547bis-mcast-bgp-02.txt */ 336190207Srpaulo#define SAFNUM_MULTICAST_VPN 5 337146773Ssam#define SAFNUM_TUNNEL 64 /* XXX */ 338146773Ssam#define SAFNUM_VPLS 65 /* XXX */ 339214478Srpaulo/* draft-nalawade-idr-mdt-safi-03 */ 340214478Srpaulo#define SAFNUM_MDT 66 341127668Sbms/* Section 4.3.4 of draft-rosen-rfc2547bis-03.txt */ 342127668Sbms#define SAFNUM_VPNUNICAST 128 343127668Sbms#define SAFNUM_VPNMULTICAST 129 344127668Sbms#define SAFNUM_VPNUNIMULTICAST 130 345127668Sbms/* draft-marques-ppvpn-rt-constrain-01.txt */ 346127668Sbms#define SAFNUM_RT_ROUTING_INFO 132 347127668Sbms 348127668Sbms#define BGP_VPN_RD_LEN 8 349127668Sbms 350127668Sbmsstatic struct tok bgp_safi_values[] = { 351127668Sbms { SAFNUM_RES, "Reserved"}, 352127668Sbms { SAFNUM_UNICAST, "Unicast"}, 353127668Sbms { SAFNUM_MULTICAST, "Multicast"}, 354127668Sbms { SAFNUM_UNIMULTICAST, "Unicast+Multicast"}, 355127668Sbms { SAFNUM_LABUNICAST, "labeled Unicast"}, 356146773Ssam { SAFNUM_TUNNEL, "Tunnel"}, 357146773Ssam { SAFNUM_VPLS, "VPLS"}, 358146773Ssam { SAFNUM_MDT, "MDT"}, 359127668Sbms { SAFNUM_VPNUNICAST, "labeled VPN Unicast"}, 360127668Sbms { SAFNUM_VPNMULTICAST, "labeled VPN Multicast"}, 361127668Sbms { SAFNUM_VPNUNIMULTICAST, "labeled VPN Unicast+Multicast"}, 362190207Srpaulo { SAFNUM_RT_ROUTING_INFO, "Route Target Routing Information"}, 363190207Srpaulo { SAFNUM_MULTICAST_VPN, "Multicast VPN"}, 364127668Sbms { 0, NULL } 36556893Sfenner}; 36656893Sfenner 36756893Sfenner/* well-known community */ 36856893Sfenner#define BGP_COMMUNITY_NO_EXPORT 0xffffff01 36956893Sfenner#define BGP_COMMUNITY_NO_ADVERT 0xffffff02 37056893Sfenner#define BGP_COMMUNITY_NO_EXPORT_SUBCONFED 0xffffff03 37156893Sfenner 372127668Sbms/* Extended community type - draft-ietf-idr-bgp-ext-communities-05 */ 373127668Sbms#define BGP_EXT_COM_RT_0 0x0002 /* Route Target,Format AS(2bytes):AN(4bytes) */ 374127668Sbms#define BGP_EXT_COM_RT_1 0x0102 /* Route Target,Format IP address:AN(2bytes) */ 375127668Sbms#define BGP_EXT_COM_RT_2 0x0202 /* Route Target,Format AN(4bytes):local(2bytes) */ 376127668Sbms#define BGP_EXT_COM_RO_0 0x0003 /* Route Origin,Format AS(2bytes):AN(4bytes) */ 377127668Sbms#define BGP_EXT_COM_RO_1 0x0103 /* Route Origin,Format IP address:AN(2bytes) */ 378127668Sbms#define BGP_EXT_COM_RO_2 0x0203 /* Route Origin,Format AN(4bytes):local(2bytes) */ 379127668Sbms#define BGP_EXT_COM_LINKBAND 0x4004 /* Link Bandwidth,Format AS(2B):Bandwidth(4B) */ 380127668Sbms /* rfc2547 bgp-mpls-vpns */ 381127668Sbms#define BGP_EXT_COM_VPN_ORIGIN 0x0005 /* OSPF Domain ID / VPN of Origin - draft-rosen-vpns-ospf-bgp-mpls */ 382127668Sbms#define BGP_EXT_COM_VPN_ORIGIN2 0x0105 /* duplicate - keep for backwards compatability */ 383127668Sbms#define BGP_EXT_COM_VPN_ORIGIN3 0x0205 /* duplicate - keep for backwards compatability */ 384127668Sbms#define BGP_EXT_COM_VPN_ORIGIN4 0x8005 /* duplicate - keep for backwards compatability */ 385127668Sbms 386127668Sbms#define BGP_EXT_COM_OSPF_RTYPE 0x0306 /* OSPF Route Type,Format Area(4B):RouteType(1B):Options(1B) */ 387127668Sbms#define BGP_EXT_COM_OSPF_RTYPE2 0x8000 /* duplicate - keep for backwards compatability */ 388127668Sbms 389127668Sbms#define BGP_EXT_COM_OSPF_RID 0x0107 /* OSPF Router ID,Format RouterID(4B):Unused(2B) */ 390127668Sbms#define BGP_EXT_COM_OSPF_RID2 0x8001 /* duplicate - keep for backwards compatability */ 391127668Sbms 392127668Sbms#define BGP_EXT_COM_L2INFO 0x800a /* draft-kompella-ppvpn-l2vpn */ 393127668Sbms 394235530Sdelphij#define BGP_EXT_COM_SOURCE_AS 0x0009 /* RFC-ietf-l3vpn-2547bis-mcast-bgp-08.txt */ 395235530Sdelphij#define BGP_EXT_COM_VRF_RT_IMP 0x010b /* RFC-ietf-l3vpn-2547bis-mcast-bgp-08.txt */ 396235530Sdelphij#define BGP_EXT_COM_L2VPN_RT_0 0x000a /* L2VPN Identifier,Format AS(2bytes):AN(4bytes) */ 397235530Sdelphij#define BGP_EXT_COM_L2VPN_RT_1 0xF10a /* L2VPN Identifier,Format IP address:AN(2bytes) */ 398190207Srpaulo 399235530Sdelphij 400172683Smlaier/* http://www.cisco.com/en/US/tech/tk436/tk428/technologies_tech_note09186a00801eb09a.shtml */ 401172683Smlaier#define BGP_EXT_COM_EIGRP_GEN 0x8800 402172683Smlaier#define BGP_EXT_COM_EIGRP_METRIC_AS_DELAY 0x8801 403172683Smlaier#define BGP_EXT_COM_EIGRP_METRIC_REL_NH_BW 0x8802 404172683Smlaier#define BGP_EXT_COM_EIGRP_METRIC_LOAD_MTU 0x8803 405172683Smlaier#define BGP_EXT_COM_EIGRP_EXT_REMAS_REMID 0x8804 406172683Smlaier#define BGP_EXT_COM_EIGRP_EXT_REMPROTO_REMMETRIC 0x8805 407172683Smlaier 408127668Sbmsstatic struct tok bgp_extd_comm_flag_values[] = { 409127668Sbms { 0x8000, "vendor-specific"}, 410127668Sbms { 0x4000, "non-transitive"}, 411127668Sbms { 0, NULL}, 412127668Sbms}; 413127668Sbms 414127668Sbmsstatic struct tok bgp_extd_comm_subtype_values[] = { 415127668Sbms { BGP_EXT_COM_RT_0, "target"}, 416127668Sbms { BGP_EXT_COM_RT_1, "target"}, 417127668Sbms { BGP_EXT_COM_RT_2, "target"}, 418127668Sbms { BGP_EXT_COM_RO_0, "origin"}, 419127668Sbms { BGP_EXT_COM_RO_1, "origin"}, 420127668Sbms { BGP_EXT_COM_RO_2, "origin"}, 421127668Sbms { BGP_EXT_COM_LINKBAND, "link-BW"}, 422127668Sbms { BGP_EXT_COM_VPN_ORIGIN, "ospf-domain"}, 423127668Sbms { BGP_EXT_COM_VPN_ORIGIN2, "ospf-domain"}, 424127668Sbms { BGP_EXT_COM_VPN_ORIGIN3, "ospf-domain"}, 425127668Sbms { BGP_EXT_COM_VPN_ORIGIN4, "ospf-domain"}, 426127668Sbms { BGP_EXT_COM_OSPF_RTYPE, "ospf-route-type"}, 427127668Sbms { BGP_EXT_COM_OSPF_RTYPE2, "ospf-route-type"}, 428127668Sbms { BGP_EXT_COM_OSPF_RID, "ospf-router-id"}, 429127668Sbms { BGP_EXT_COM_OSPF_RID2, "ospf-router-id"}, 430127668Sbms { BGP_EXT_COM_L2INFO, "layer2-info"}, 431172683Smlaier { BGP_EXT_COM_EIGRP_GEN , "eigrp-general-route (flag, tag)" }, 432172683Smlaier { BGP_EXT_COM_EIGRP_METRIC_AS_DELAY , "eigrp-route-metric (AS, delay)" }, 433172683Smlaier { BGP_EXT_COM_EIGRP_METRIC_REL_NH_BW , "eigrp-route-metric (reliability, nexthop, bandwidth)" }, 434172683Smlaier { BGP_EXT_COM_EIGRP_METRIC_LOAD_MTU , "eigrp-route-metric (load, MTU)" }, 435172683Smlaier { BGP_EXT_COM_EIGRP_EXT_REMAS_REMID , "eigrp-external-route (remote-AS, remote-ID)" }, 436172683Smlaier { BGP_EXT_COM_EIGRP_EXT_REMPROTO_REMMETRIC , "eigrp-external-route (remote-proto, remote-metric)" }, 437190207Srpaulo { BGP_EXT_COM_SOURCE_AS, "source-AS" }, 438190207Srpaulo { BGP_EXT_COM_VRF_RT_IMP, "vrf-route-import"}, 439235530Sdelphij { BGP_EXT_COM_L2VPN_RT_0, "l2vpn-id"}, 440235530Sdelphij { BGP_EXT_COM_L2VPN_RT_1, "l2vpn-id"}, 441127668Sbms { 0, NULL}, 442127668Sbms}; 443127668Sbms 444127668Sbms/* OSPF codes for BGP_EXT_COM_OSPF_RTYPE draft-rosen-vpns-ospf-bgp-mpls */ 445127668Sbms#define BGP_OSPF_RTYPE_RTR 1 /* OSPF Router LSA */ 446127668Sbms#define BGP_OSPF_RTYPE_NET 2 /* OSPF Network LSA */ 447127668Sbms#define BGP_OSPF_RTYPE_SUM 3 /* OSPF Summary LSA */ 448127668Sbms#define BGP_OSPF_RTYPE_EXT 5 /* OSPF External LSA, note that ASBR doesn't apply to MPLS-VPN */ 449127668Sbms#define BGP_OSPF_RTYPE_NSSA 7 /* OSPF NSSA External*/ 450127668Sbms#define BGP_OSPF_RTYPE_SHAM 129 /* OSPF-MPLS-VPN Sham link */ 451127668Sbms#define BGP_OSPF_RTYPE_METRIC_TYPE 0x1 /* LSB of RTYPE Options Field */ 452127668Sbms 453127668Sbmsstatic struct tok bgp_extd_comm_ospf_rtype_values[] = { 454127668Sbms { BGP_OSPF_RTYPE_RTR, "Router" }, 455127668Sbms { BGP_OSPF_RTYPE_NET, "Network" }, 456127668Sbms { BGP_OSPF_RTYPE_SUM, "Summary" }, 457127668Sbms { BGP_OSPF_RTYPE_EXT, "External" }, 458127668Sbms { BGP_OSPF_RTYPE_NSSA,"NSSA External" }, 459127668Sbms { BGP_OSPF_RTYPE_SHAM,"MPLS-VPN Sham" }, 460127668Sbms { 0, NULL }, 461127668Sbms}; 462127668Sbms 463214478Srpaulo#define TOKBUFSIZE 128 464214478Srpaulostatic char astostr[20]; 465214478Srpaulo 466214478Srpaulo/* 467214478Srpaulo * as_printf 468214478Srpaulo * 469214478Srpaulo * Convert an AS number into a string and return string pointer. 470214478Srpaulo * 471214478Srpaulo * Bepending on bflag is set or not, AS number is converted into ASDOT notation 472214478Srpaulo * or plain number notation. 473214478Srpaulo * 474214478Srpaulo */ 475214478Srpaulostatic char * 476214478Srpauloas_printf (char *str, int size, u_int asnum) 477214478Srpaulo{ 478214478Srpaulo if (!bflag || asnum <= 0xFFFF) { 479214478Srpaulo snprintf(str, size, "%u", asnum); 480214478Srpaulo } else { 481214478Srpaulo snprintf(str, size, "%u.%u", asnum >> 16, asnum & 0xFFFF); 482214478Srpaulo } 483214478Srpaulo return str; 484214478Srpaulo} 485214478Srpaulo 486241235Sdelphij#define ITEMCHECK(minlen) if (itemlen < minlen) goto badtlv; 487241235Sdelphij 488146773Ssamint 489241235Sdelphijdecode_prefix4(const u_char *pptr, u_int itemlen, char *buf, u_int buflen) 49056893Sfenner{ 491127668Sbms struct in_addr addr; 492241235Sdelphij u_int plen, plenbytes; 493127668Sbms 494127668Sbms TCHECK(pptr[0]); 495241235Sdelphij ITEMCHECK(1); 496127668Sbms plen = pptr[0]; 497127668Sbms if (32 < plen) 498127668Sbms return -1; 499241235Sdelphij itemlen -= 1; 500127668Sbms 501127668Sbms memset(&addr, 0, sizeof(addr)); 502241235Sdelphij plenbytes = (plen + 7) / 8; 503241235Sdelphij TCHECK2(pptr[1], plenbytes); 504241235Sdelphij ITEMCHECK(plenbytes); 505241235Sdelphij memcpy(&addr, &pptr[1], plenbytes); 506127668Sbms if (plen % 8) { 507241235Sdelphij ((u_char *)&addr)[plenbytes - 1] &= 508127668Sbms ((0xff00 >> (plen % 8)) & 0xff); 509127668Sbms } 510127668Sbms snprintf(buf, buflen, "%s/%d", getname((u_char *)&addr), plen); 511241235Sdelphij return 1 + plenbytes; 512127668Sbms 513127668Sbmstrunc: 514127668Sbms return -2; 515241235Sdelphij 516241235Sdelphijbadtlv: 517241235Sdelphij return -3; 51856893Sfenner} 51956893Sfenner 520127668Sbmsstatic int 521241235Sdelphijdecode_labeled_prefix4(const u_char *pptr, u_int itemlen, char *buf, u_int buflen) 52256893Sfenner{ 523127668Sbms struct in_addr addr; 524241235Sdelphij u_int plen, plenbytes; 52556893Sfenner 526241235Sdelphij /* prefix length and label = 4 bytes */ 527241235Sdelphij TCHECK2(pptr[0], 4); 528241235Sdelphij ITEMCHECK(4); 529127668Sbms plen = pptr[0]; /* get prefix length */ 530127668Sbms 531127668Sbms /* this is one of the weirdnesses of rfc3107 532127668Sbms the label length (actually the label + COS bits) 533127668Sbms is added to the prefix length; 534127668Sbms we also do only read out just one label - 535127668Sbms there is no real application for advertisement of 536127668Sbms stacked labels in a a single BGP message 537127668Sbms */ 538127668Sbms 539172683Smlaier if (24 > plen) 540172683Smlaier return -1; 541172683Smlaier 542127668Sbms plen-=24; /* adjust prefixlen - labellength */ 543127668Sbms 544127668Sbms if (32 < plen) 545127668Sbms return -1; 546241235Sdelphij itemlen -= 4; 547127668Sbms 548127668Sbms memset(&addr, 0, sizeof(addr)); 549241235Sdelphij plenbytes = (plen + 7) / 8; 550241235Sdelphij TCHECK2(pptr[4], plenbytes); 551241235Sdelphij ITEMCHECK(plenbytes); 552241235Sdelphij memcpy(&addr, &pptr[4], plenbytes); 553127668Sbms if (plen % 8) { 554241235Sdelphij ((u_char *)&addr)[plenbytes - 1] &= 555127668Sbms ((0xff00 >> (plen % 8)) & 0xff); 556127668Sbms } 557127668Sbms /* the label may get offsetted by 4 bits so lets shift it right */ 558127668Sbms snprintf(buf, buflen, "%s/%d, label:%u %s", 559127668Sbms getname((u_char *)&addr), 560127668Sbms plen, 561127668Sbms EXTRACT_24BITS(pptr+1)>>4, 562127668Sbms ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" ); 563127668Sbms 564241235Sdelphij return 4 + plenbytes; 565127668Sbms 566127668Sbmstrunc: 567127668Sbms return -2; 568241235Sdelphij 569241235Sdelphijbadtlv: 570241235Sdelphij return -3; 57156893Sfenner} 57256893Sfenner 573190207Srpaulo/* 574190207Srpaulo * bgp_vpn_ip_print 575190207Srpaulo * 576190207Srpaulo * print an ipv4 or ipv6 address into a buffer dependend on address length. 577190207Srpaulo */ 578190207Srpaulostatic char * 579190207Srpaulobgp_vpn_ip_print (const u_char *pptr, u_int addr_length) { 580190207Srpaulo 581190207Srpaulo /* worst case string is s fully formatted v6 address */ 582190207Srpaulo static char addr[sizeof("1234:5678:89ab:cdef:1234:5678:89ab:cdef")]; 583190207Srpaulo char *pos = addr; 584190207Srpaulo 585190207Srpaulo switch(addr_length) { 586190207Srpaulo case (sizeof(struct in_addr) << 3): /* 32 */ 587190207Srpaulo TCHECK2(pptr[0], sizeof(struct in_addr)); 588190207Srpaulo snprintf(pos, sizeof(addr), "%s", ipaddr_string(pptr)); 589190207Srpaulo break; 590190207Srpaulo#ifdef INET6 591190207Srpaulo case (sizeof(struct in6_addr) << 3): /* 128 */ 592190207Srpaulo TCHECK2(pptr[0], sizeof(struct in6_addr)); 593190207Srpaulo snprintf(pos, sizeof(addr), "%s", ip6addr_string(pptr)); 594190207Srpaulo break; 595190207Srpaulo#endif 596190207Srpaulo default: 597190207Srpaulo snprintf(pos, sizeof(addr), "bogus address length %u", addr_length); 598190207Srpaulo break; 599190207Srpaulo } 600190207Srpaulo pos += strlen(pos); 601190207Srpaulo 602190207Srpaulotrunc: 603190207Srpaulo *(pos) = '\0'; 604190207Srpaulo return (addr); 605190207Srpaulo} 606190207Srpaulo 607190207Srpaulo/* 608190207Srpaulo * bgp_vpn_sg_print 609190207Srpaulo * 610190207Srpaulo * print an multicast s,g entry into a buffer. 611190207Srpaulo * the s,g entry is encoded like this. 612190207Srpaulo * 613190207Srpaulo * +-----------------------------------+ 614190207Srpaulo * | Multicast Source Length (1 octet) | 615190207Srpaulo * +-----------------------------------+ 616190207Srpaulo * | Multicast Source (Variable) | 617190207Srpaulo * +-----------------------------------+ 618190207Srpaulo * | Multicast Group Length (1 octet) | 619190207Srpaulo * +-----------------------------------+ 620190207Srpaulo * | Multicast Group (Variable) | 621190207Srpaulo * +-----------------------------------+ 622190207Srpaulo * 623190207Srpaulo * return the number of bytes read from the wire. 624190207Srpaulo */ 625190207Srpaulostatic int 626190207Srpaulobgp_vpn_sg_print (const u_char *pptr, char *buf, u_int buflen) { 627190207Srpaulo 628190207Srpaulo u_int8_t addr_length; 629190207Srpaulo u_int total_length, offset; 630190207Srpaulo 631190207Srpaulo total_length = 0; 632190207Srpaulo 633190207Srpaulo /* Source address length, encoded in bits */ 634190207Srpaulo TCHECK2(pptr[0], 1); 635190207Srpaulo addr_length = *pptr++; 636190207Srpaulo 637190207Srpaulo /* Source address */ 638190207Srpaulo TCHECK2(pptr[0], (addr_length >> 3)); 639190207Srpaulo total_length += (addr_length >> 3) + 1; 640190207Srpaulo offset = strlen(buf); 641190207Srpaulo if (addr_length) { 642190207Srpaulo snprintf(buf + offset, buflen - offset, ", Source %s", 643190207Srpaulo bgp_vpn_ip_print(pptr, addr_length)); 644190207Srpaulo pptr += (addr_length >> 3); 645190207Srpaulo } 646190207Srpaulo 647190207Srpaulo /* Group address length, encoded in bits */ 648190207Srpaulo TCHECK2(pptr[0], 1); 649190207Srpaulo addr_length = *pptr++; 650190207Srpaulo 651190207Srpaulo /* Group address */ 652190207Srpaulo TCHECK2(pptr[0], (addr_length >> 3)); 653190207Srpaulo total_length += (addr_length >> 3) + 1; 654190207Srpaulo offset = strlen(buf); 655190207Srpaulo if (addr_length) { 656190207Srpaulo snprintf(buf + offset, buflen - offset, ", Group %s", 657190207Srpaulo bgp_vpn_ip_print(pptr, addr_length)); 658190207Srpaulo pptr += (addr_length >> 3); 659190207Srpaulo } 660190207Srpaulo 661190207Srpaulotrunc: 662190207Srpaulo return (total_length); 663190207Srpaulo} 664190207Srpaulo 665190207Srpaulo 666127668Sbms/* RDs and RTs share the same semantics 667127668Sbms * we use bgp_vpn_rd_print for 668127668Sbms * printing route targets inside a NLRI */ 669146773Ssamchar * 670127668Sbmsbgp_vpn_rd_print (const u_char *pptr) { 671127668Sbms 672146773Ssam /* allocate space for the largest possible string */ 673146773Ssam static char rd[sizeof("xxxxxxxxxx:xxxxx (xxx.xxx.xxx.xxx:xxxxx)")]; 674127668Sbms char *pos = rd; 675127668Sbms 676127668Sbms /* ok lets load the RD format */ 677127668Sbms switch (EXTRACT_16BITS(pptr)) { 678127668Sbms 679190207Srpaulo /* 2-byte-AS:number fmt*/ 680127668Sbms case 0: 681190207Srpaulo snprintf(pos, sizeof(rd) - (pos - rd), "%u:%u (= %u.%u.%u.%u)", 682190207Srpaulo EXTRACT_16BITS(pptr+2), 683190207Srpaulo EXTRACT_32BITS(pptr+4), 684190207Srpaulo *(pptr+4), *(pptr+5), *(pptr+6), *(pptr+7)); 685127668Sbms break; 686127668Sbms /* IP-address:AS fmt*/ 687127668Sbms 688127668Sbms case 1: 689127668Sbms snprintf(pos, sizeof(rd) - (pos - rd), "%u.%u.%u.%u:%u", 690127668Sbms *(pptr+2), *(pptr+3), *(pptr+4), *(pptr+5), EXTRACT_16BITS(pptr+6)); 691127668Sbms break; 692127668Sbms 693127668Sbms /* 4-byte-AS:number fmt*/ 694127668Sbms case 2: 695214478Srpaulo snprintf(pos, sizeof(rd) - (pos - rd), "%s:%u (%u.%u.%u.%u:%u)", 696214478Srpaulo as_printf(astostr, sizeof(astostr), EXTRACT_32BITS(pptr+2)), 697214478Srpaulo EXTRACT_16BITS(pptr+6), *(pptr+2), *(pptr+3), *(pptr+4), 698214478Srpaulo *(pptr+5), EXTRACT_16BITS(pptr+6)); 699127668Sbms break; 700127668Sbms default: 701127668Sbms snprintf(pos, sizeof(rd) - (pos - rd), "unknown RD format"); 702127668Sbms break; 703127668Sbms } 704127668Sbms pos += strlen(pos); 705127668Sbms *(pos) = '\0'; 706127668Sbms return (rd); 707127668Sbms} 708127668Sbms 70956893Sfennerstatic int 710127668Sbmsdecode_rt_routing_info(const u_char *pptr, char *buf, u_int buflen) 71156893Sfenner{ 712127668Sbms u_int8_t route_target[8]; 713127668Sbms u_int plen; 714127668Sbms 715127668Sbms TCHECK(pptr[0]); 716127668Sbms plen = pptr[0]; /* get prefix length */ 717127668Sbms 718172683Smlaier if (0 == plen) 719172683Smlaier return 1; /* default route target */ 720172683Smlaier 721172683Smlaier if (32 > plen) 722172683Smlaier return -1; 723172683Smlaier 724127668Sbms plen-=32; /* adjust prefix length */ 725127668Sbms 726172683Smlaier if (64 < plen) 727127668Sbms return -1; 728127668Sbms 729127668Sbms memset(&route_target, 0, sizeof(route_target)); 730127668Sbms TCHECK2(pptr[1], (plen + 7) / 8); 731127668Sbms memcpy(&route_target, &pptr[1], (plen + 7) / 8); 732127668Sbms if (plen % 8) { 733127668Sbms ((u_char *)&route_target)[(plen + 7) / 8 - 1] &= 734127668Sbms ((0xff00 >> (plen % 8)) & 0xff); 735127668Sbms } 736214478Srpaulo snprintf(buf, buflen, "origin AS: %s, route target %s", 737214478Srpaulo as_printf(astostr, sizeof(astostr), EXTRACT_32BITS(pptr+1)), 738214478Srpaulo bgp_vpn_rd_print((u_char *)&route_target)); 739127668Sbms 740127668Sbms return 5 + (plen + 7) / 8; 741127668Sbms 742127668Sbmstrunc: 743127668Sbms return -2; 744127668Sbms} 745127668Sbms 746127668Sbmsstatic int 747127668Sbmsdecode_labeled_vpn_prefix4(const u_char *pptr, char *buf, u_int buflen) 748127668Sbms{ 74956893Sfenner struct in_addr addr; 75098524Sfenner u_int plen; 75156893Sfenner 752127668Sbms TCHECK(pptr[0]); 753127668Sbms plen = pptr[0]; /* get prefix length */ 754127668Sbms 755172683Smlaier if ((24+64) > plen) 756172683Smlaier return -1; 757172683Smlaier 758127668Sbms plen-=(24+64); /* adjust prefixlen - labellength - RD len*/ 759127668Sbms 760127668Sbms if (32 < plen) 76156893Sfenner return -1; 76256893Sfenner 76356893Sfenner memset(&addr, 0, sizeof(addr)); 764127668Sbms TCHECK2(pptr[12], (plen + 7) / 8); 765127668Sbms memcpy(&addr, &pptr[12], (plen + 7) / 8); 76656893Sfenner if (plen % 8) { 76756893Sfenner ((u_char *)&addr)[(plen + 7) / 8 - 1] &= 76856893Sfenner ((0xff00 >> (plen % 8)) & 0xff); 76956893Sfenner } 770127668Sbms /* the label may get offsetted by 4 bits so lets shift it right */ 771127668Sbms snprintf(buf, buflen, "RD: %s, %s/%d, label:%u %s", 772127668Sbms bgp_vpn_rd_print(pptr+4), 773127668Sbms getname((u_char *)&addr), 774127668Sbms plen, 775127668Sbms EXTRACT_24BITS(pptr+1)>>4, 776127668Sbms ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" ); 777127668Sbms 778127668Sbms return 12 + (plen + 7) / 8; 779127668Sbms 780127668Sbmstrunc: 781127668Sbms return -2; 78256893Sfenner} 78356893Sfenner 784214478Srpaulo/* 785214478Srpaulo * +-------------------------------+ 786214478Srpaulo * | | 787214478Srpaulo * | RD:IPv4-address (12 octets) | 788214478Srpaulo * | | 789214478Srpaulo * +-------------------------------+ 790214478Srpaulo * | MDT Group-address (4 octets) | 791214478Srpaulo * +-------------------------------+ 792214478Srpaulo */ 793214478Srpaulo 794214478Srpaulo#define MDT_VPN_NLRI_LEN 16 795214478Srpaulo 796214478Srpaulostatic int 797214478Srpaulodecode_mdt_vpn_nlri(const u_char *pptr, char *buf, u_int buflen) 798214478Srpaulo{ 799214478Srpaulo 800214478Srpaulo const u_char *rd; 801214478Srpaulo const u_char *vpn_ip; 802214478Srpaulo 803214478Srpaulo TCHECK(pptr[0]); 804214478Srpaulo 805214478Srpaulo /* if the NLRI is not predefined length, quit.*/ 806214478Srpaulo if (*pptr != MDT_VPN_NLRI_LEN * NBBY) 807214478Srpaulo return -1; 808214478Srpaulo pptr++; 809214478Srpaulo 810214478Srpaulo /* RD */ 811214478Srpaulo TCHECK2(pptr[0], 8); 812214478Srpaulo rd = pptr; 813214478Srpaulo pptr+=8; 814214478Srpaulo 815214478Srpaulo /* IPv4 address */ 816214478Srpaulo TCHECK2(pptr[0], sizeof(struct in_addr)); 817214478Srpaulo vpn_ip = pptr; 818214478Srpaulo pptr+=sizeof(struct in_addr); 819214478Srpaulo 820214478Srpaulo /* MDT Group Address */ 821214478Srpaulo TCHECK2(pptr[0], sizeof(struct in_addr)); 822214478Srpaulo 823214478Srpaulo snprintf(buf, buflen, "RD: %s, VPN IP Address: %s, MC Group Address: %s", 824214478Srpaulo bgp_vpn_rd_print(rd), ipaddr_string(vpn_ip), ipaddr_string(pptr)); 825214478Srpaulo 826214478Srpaulo return MDT_VPN_NLRI_LEN + 1; 827214478Srpaulo 828214478Srpaulo trunc: 829214478Srpaulo 830214478Srpauloreturn -2; 831214478Srpaulo} 832214478Srpaulo 833190207Srpaulo#define BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_I_PMSI 1 834190207Srpaulo#define BGP_MULTICAST_VPN_ROUTE_TYPE_INTER_AS_I_PMSI 2 835190207Srpaulo#define BGP_MULTICAST_VPN_ROUTE_TYPE_S_PMSI 3 836190207Srpaulo#define BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_SEG_LEAF 4 837190207Srpaulo#define BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_ACTIVE 5 838190207Srpaulo#define BGP_MULTICAST_VPN_ROUTE_TYPE_SHARED_TREE_JOIN 6 839190207Srpaulo#define BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_TREE_JOIN 7 840190207Srpaulo 841190207Srpaulostatic struct tok bgp_multicast_vpn_route_type_values[] = { 842190207Srpaulo { BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_I_PMSI, "Intra-AS I-PMSI"}, 843190207Srpaulo { BGP_MULTICAST_VPN_ROUTE_TYPE_INTER_AS_I_PMSI, "Inter-AS I-PMSI"}, 844190207Srpaulo { BGP_MULTICAST_VPN_ROUTE_TYPE_S_PMSI, "S-PMSI"}, 845190207Srpaulo { BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_SEG_LEAF, "Intra-AS Segment-Leaf"}, 846190207Srpaulo { BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_ACTIVE, "Source-Active"}, 847190207Srpaulo { BGP_MULTICAST_VPN_ROUTE_TYPE_SHARED_TREE_JOIN, "Shared Tree Join"}, 848190207Srpaulo { BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_TREE_JOIN, "Source Tree Join"}, 849190207Srpaulo}; 850190207Srpaulo 851190207Srpaulostatic int 852190207Srpaulodecode_multicast_vpn(const u_char *pptr, char *buf, u_int buflen) 853190207Srpaulo{ 854190207Srpaulo u_int8_t route_type, route_length, addr_length, sg_length; 855190207Srpaulo u_int offset; 856190207Srpaulo 857190207Srpaulo TCHECK2(pptr[0], 2); 858190207Srpaulo route_type = *pptr++; 859190207Srpaulo route_length = *pptr++; 860190207Srpaulo 861190207Srpaulo snprintf(buf, buflen, "Route-Type: %s (%u), length: %u", 862190207Srpaulo tok2str(bgp_multicast_vpn_route_type_values, 863190207Srpaulo "Unknown", route_type), 864190207Srpaulo route_type, route_length); 865190207Srpaulo 866190207Srpaulo switch(route_type) { 867190207Srpaulo case BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_I_PMSI: 868190207Srpaulo TCHECK2(pptr[0], BGP_VPN_RD_LEN); 869190207Srpaulo offset = strlen(buf); 870190207Srpaulo snprintf(buf + offset, buflen - offset, ", RD: %s, Originator %s", 871190207Srpaulo bgp_vpn_rd_print(pptr), 872190207Srpaulo bgp_vpn_ip_print(pptr + BGP_VPN_RD_LEN, 873190207Srpaulo (route_length - BGP_VPN_RD_LEN) << 3)); 874190207Srpaulo break; 875190207Srpaulo case BGP_MULTICAST_VPN_ROUTE_TYPE_INTER_AS_I_PMSI: 876190207Srpaulo TCHECK2(pptr[0], BGP_VPN_RD_LEN + 4); 877190207Srpaulo offset = strlen(buf); 878214478Srpaulo snprintf(buf + offset, buflen - offset, ", RD: %s, Source-AS %s", 879214478Srpaulo bgp_vpn_rd_print(pptr), 880214478Srpaulo as_printf(astostr, sizeof(astostr), 881214478Srpaulo EXTRACT_32BITS(pptr + BGP_VPN_RD_LEN))); 882190207Srpaulo break; 883190207Srpaulo 884190207Srpaulo case BGP_MULTICAST_VPN_ROUTE_TYPE_S_PMSI: 885190207Srpaulo TCHECK2(pptr[0], BGP_VPN_RD_LEN); 886190207Srpaulo offset = strlen(buf); 887190207Srpaulo snprintf(buf + offset, buflen - offset, ", RD: %s", 888190207Srpaulo bgp_vpn_rd_print(pptr)); 889190207Srpaulo pptr += BGP_VPN_RD_LEN; 890190207Srpaulo 891190207Srpaulo sg_length = bgp_vpn_sg_print(pptr, buf, buflen); 892190207Srpaulo addr_length = route_length - sg_length; 893190207Srpaulo 894190207Srpaulo TCHECK2(pptr[0], addr_length); 895190207Srpaulo offset = strlen(buf); 896190207Srpaulo snprintf(buf + offset, buflen - offset, ", Originator %s", 897190207Srpaulo bgp_vpn_ip_print(pptr, addr_length << 3)); 898190207Srpaulo break; 899190207Srpaulo 900190207Srpaulo case BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_ACTIVE: 901190207Srpaulo TCHECK2(pptr[0], BGP_VPN_RD_LEN); 902190207Srpaulo offset = strlen(buf); 903190207Srpaulo snprintf(buf + offset, buflen - offset, ", RD: %s", 904190207Srpaulo bgp_vpn_rd_print(pptr)); 905190207Srpaulo pptr += BGP_VPN_RD_LEN; 906190207Srpaulo 907190207Srpaulo bgp_vpn_sg_print(pptr, buf, buflen); 908190207Srpaulo break; 909190207Srpaulo 910190207Srpaulo case BGP_MULTICAST_VPN_ROUTE_TYPE_SHARED_TREE_JOIN: /* fall through */ 911190207Srpaulo case BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_TREE_JOIN: 912190207Srpaulo TCHECK2(pptr[0], BGP_VPN_RD_LEN); 913190207Srpaulo offset = strlen(buf); 914214478Srpaulo snprintf(buf + offset, buflen - offset, ", RD: %s, Source-AS %s", 915214478Srpaulo bgp_vpn_rd_print(pptr), 916214478Srpaulo as_printf(astostr, sizeof(astostr), 917214478Srpaulo EXTRACT_32BITS(pptr + BGP_VPN_RD_LEN))); 918190207Srpaulo pptr += BGP_VPN_RD_LEN; 919190207Srpaulo 920190207Srpaulo bgp_vpn_sg_print(pptr, buf, buflen); 921190207Srpaulo break; 922190207Srpaulo 923190207Srpaulo /* 924190207Srpaulo * no per route-type printing yet. 925190207Srpaulo */ 926190207Srpaulo case BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_SEG_LEAF: 927190207Srpaulo default: 928190207Srpaulo break; 929190207Srpaulo } 930190207Srpaulo 931190207Srpaulo return route_length + 2; 932190207Srpaulo 933190207Srpaulotrunc: 934190207Srpaulo return -2; 935190207Srpaulo} 936190207Srpaulo 937171682Ssimon/* 938171682Ssimon * As I remember, some versions of systems have an snprintf() that 939171682Ssimon * returns -1 if the buffer would have overflowed. If the return 940171682Ssimon * value is negative, set buflen to 0, to indicate that we've filled 941171682Ssimon * the buffer up. 942171682Ssimon * 943171682Ssimon * If the return value is greater than buflen, that means that 944171682Ssimon * the buffer would have overflowed; again, set buflen to 0 in 945171682Ssimon * that case. 946171682Ssimon */ 947171682Ssimon#define UPDATE_BUF_BUFLEN(buf, buflen, strlen) \ 948171682Ssimon if (strlen<0) \ 949171682Ssimon buflen=0; \ 950171682Ssimon else if ((u_int)strlen>buflen) \ 951171682Ssimon buflen=0; \ 952171682Ssimon else { \ 953171682Ssimon buflen-=strlen; \ 954171682Ssimon buf+=strlen; \ 955171682Ssimon } 956171682Ssimon 957127668Sbmsstatic int 958127668Sbmsdecode_labeled_vpn_l2(const u_char *pptr, char *buf, u_int buflen) 959127668Sbms{ 960127668Sbms int plen,tlen,strlen,tlv_type,tlv_len,ttlv_len; 961127668Sbms 962127668Sbms TCHECK2(pptr[0], 2); 963127668Sbms plen=EXTRACT_16BITS(pptr); 964127668Sbms tlen=plen; 965127668Sbms pptr+=2; 966235530Sdelphij /* Old and new L2VPN NLRI share AFI/SAFI 967235530Sdelphij * -> Assume a 12 Byte-length NLRI is auto-discovery-only 968235530Sdelphij * and > 17 as old format. Complain for the middle case 969235530Sdelphij */ 970235530Sdelphij if (plen==12) { 971235530Sdelphij /* assume AD-only with RD, BGPNH */ 972235530Sdelphij TCHECK2(pptr[0],12); 973235530Sdelphij buf[0]='\0'; 974235530Sdelphij strlen=snprintf(buf, buflen, "RD: %s, BGPNH: %s", 975235530Sdelphij bgp_vpn_rd_print(pptr), 976235530Sdelphij /* need something like getname() here */ 977235530Sdelphij getname(pptr+8) 978235530Sdelphij ); 979235530Sdelphij UPDATE_BUF_BUFLEN(buf, buflen, strlen); 980235530Sdelphij pptr+=12; 981235530Sdelphij tlen-=12; 982235530Sdelphij return plen; 983235530Sdelphij } else if (plen>17) { 984235530Sdelphij /* assume old format */ 985235530Sdelphij /* RD, ID, LBLKOFF, LBLBASE */ 986127668Sbms 987235530Sdelphij TCHECK2(pptr[0],15); 988235530Sdelphij buf[0]='\0'; 989235530Sdelphij strlen=snprintf(buf, buflen, "RD: %s, CE-ID: %u, Label-Block Offset: %u, Label Base %u", 990235530Sdelphij bgp_vpn_rd_print(pptr), 991235530Sdelphij EXTRACT_16BITS(pptr+8), 992235530Sdelphij EXTRACT_16BITS(pptr+10), 993235530Sdelphij EXTRACT_24BITS(pptr+12)>>4); /* the label is offsetted by 4 bits so lets shift it right */ 994235530Sdelphij UPDATE_BUF_BUFLEN(buf, buflen, strlen); 995235530Sdelphij pptr+=15; 996235530Sdelphij tlen-=15; 997127668Sbms 998235530Sdelphij /* ok now the variable part - lets read out TLVs*/ 999235530Sdelphij while (tlen>0) { 1000235530Sdelphij if (tlen < 3) 1001235530Sdelphij return -1; 1002235530Sdelphij TCHECK2(pptr[0], 3); 1003235530Sdelphij tlv_type=*pptr++; 1004235530Sdelphij tlv_len=EXTRACT_16BITS(pptr); 1005235530Sdelphij ttlv_len=tlv_len; 1006235530Sdelphij pptr+=2; 1007235530Sdelphij 1008235530Sdelphij switch(tlv_type) { 1009235530Sdelphij case 1: 1010235530Sdelphij if (buflen!=0) { 1011235530Sdelphij strlen=snprintf(buf,buflen, "\n\t\tcircuit status vector (%u) length: %u: 0x", 1012235530Sdelphij tlv_type, 1013235530Sdelphij tlv_len); 1014235530Sdelphij UPDATE_BUF_BUFLEN(buf, buflen, strlen); 1015235530Sdelphij } 1016235530Sdelphij ttlv_len=ttlv_len/8+1; /* how many bytes do we need to read ? */ 1017235530Sdelphij while (ttlv_len>0) { 1018235530Sdelphij TCHECK(pptr[0]); 1019235530Sdelphij if (buflen!=0) { 1020235530Sdelphij strlen=snprintf(buf,buflen, "%02x",*pptr++); 1021235530Sdelphij UPDATE_BUF_BUFLEN(buf, buflen, strlen); 1022235530Sdelphij } 1023235530Sdelphij ttlv_len--; 1024235530Sdelphij } 1025235530Sdelphij break; 1026235530Sdelphij default: 1027235530Sdelphij if (buflen!=0) { 1028235530Sdelphij strlen=snprintf(buf,buflen, "\n\t\tunknown TLV #%u, length: %u", 1029235530Sdelphij tlv_type, 1030235530Sdelphij tlv_len); 1031235530Sdelphij UPDATE_BUF_BUFLEN(buf, buflen, strlen); 1032235530Sdelphij } 1033235530Sdelphij break; 1034235530Sdelphij } 1035235530Sdelphij tlen-=(tlv_len<<3); /* the tlv-length is expressed in bits so lets shift it right */ 1036235530Sdelphij } 1037235530Sdelphij return plen+2; 1038235530Sdelphij 1039235530Sdelphij } else { 1040235530Sdelphij /* complain bitterly ? */ 1041235530Sdelphij /* fall through */ 1042235530Sdelphij goto trunc; 1043127668Sbms } 1044127668Sbms 1045127668Sbmstrunc: 1046127668Sbms return -2; 1047127668Sbms} 1048127668Sbms 104956893Sfenner#ifdef INET6 1050146773Ssamint 1051241235Sdelphijdecode_prefix6(const u_char *pd, u_int itemlen, char *buf, u_int buflen) 105256893Sfenner{ 105356893Sfenner struct in6_addr addr; 1054241235Sdelphij u_int plen, plenbytes; 105556893Sfenner 1056127668Sbms TCHECK(pd[0]); 1057241235Sdelphij ITEMCHECK(1); 105856893Sfenner plen = pd[0]; 1059127668Sbms if (128 < plen) 106056893Sfenner return -1; 1061241235Sdelphij itemlen -= 1; 106256893Sfenner 106356893Sfenner memset(&addr, 0, sizeof(addr)); 1064241235Sdelphij plenbytes = (plen + 7) / 8; 1065241235Sdelphij TCHECK2(pd[1], plenbytes); 1066241235Sdelphij ITEMCHECK(plenbytes); 1067241235Sdelphij memcpy(&addr, &pd[1], plenbytes); 106856893Sfenner if (plen % 8) { 1069241235Sdelphij addr.s6_addr[plenbytes - 1] &= 107056893Sfenner ((0xff00 >> (plen % 8)) & 0xff); 107156893Sfenner } 107298524Sfenner snprintf(buf, buflen, "%s/%d", getname6((u_char *)&addr), plen); 1073241235Sdelphij return 1 + plenbytes; 1074127668Sbms 1075127668Sbmstrunc: 1076127668Sbms return -2; 1077241235Sdelphij 1078241235Sdelphijbadtlv: 1079241235Sdelphij return -3; 108056893Sfenner} 1081127668Sbms 1082127668Sbmsstatic int 1083241235Sdelphijdecode_labeled_prefix6(const u_char *pptr, u_int itemlen, char *buf, u_int buflen) 1084127668Sbms{ 1085127668Sbms struct in6_addr addr; 1086241235Sdelphij u_int plen, plenbytes; 1087127668Sbms 1088241235Sdelphij /* prefix length and label = 4 bytes */ 1089241235Sdelphij TCHECK2(pptr[0], 4); 1090241235Sdelphij ITEMCHECK(4); 1091127668Sbms plen = pptr[0]; /* get prefix length */ 1092172683Smlaier 1093172683Smlaier if (24 > plen) 1094172683Smlaier return -1; 1095172683Smlaier 1096127668Sbms plen-=24; /* adjust prefixlen - labellength */ 1097127668Sbms 1098127668Sbms if (128 < plen) 1099127668Sbms return -1; 1100241235Sdelphij itemlen -= 4; 1101127668Sbms 1102127668Sbms memset(&addr, 0, sizeof(addr)); 1103241235Sdelphij plenbytes = (plen + 7) / 8; 1104241235Sdelphij TCHECK2(pptr[4], plenbytes); 1105241235Sdelphij memcpy(&addr, &pptr[4], plenbytes); 1106127668Sbms if (plen % 8) { 1107241235Sdelphij addr.s6_addr[plenbytes - 1] &= 1108127668Sbms ((0xff00 >> (plen % 8)) & 0xff); 1109127668Sbms } 1110127668Sbms /* the label may get offsetted by 4 bits so lets shift it right */ 1111127668Sbms snprintf(buf, buflen, "%s/%d, label:%u %s", 1112127668Sbms getname6((u_char *)&addr), 1113127668Sbms plen, 1114127668Sbms EXTRACT_24BITS(pptr+1)>>4, 1115127668Sbms ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" ); 1116127668Sbms 1117241235Sdelphij return 4 + plenbytes; 1118127668Sbms 1119127668Sbmstrunc: 1120127668Sbms return -2; 1121241235Sdelphij 1122241235Sdelphijbadtlv: 1123241235Sdelphij return -3; 1124127668Sbms} 1125127668Sbms 1126127668Sbmsstatic int 1127127668Sbmsdecode_labeled_vpn_prefix6(const u_char *pptr, char *buf, u_int buflen) 1128127668Sbms{ 1129127668Sbms struct in6_addr addr; 1130127668Sbms u_int plen; 1131127668Sbms 1132127668Sbms TCHECK(pptr[0]); 1133127668Sbms plen = pptr[0]; /* get prefix length */ 1134127668Sbms 1135172683Smlaier if ((24+64) > plen) 1136172683Smlaier return -1; 1137172683Smlaier 1138127668Sbms plen-=(24+64); /* adjust prefixlen - labellength - RD len*/ 1139127668Sbms 1140127668Sbms if (128 < plen) 1141127668Sbms return -1; 1142127668Sbms 1143127668Sbms memset(&addr, 0, sizeof(addr)); 1144127668Sbms TCHECK2(pptr[12], (plen + 7) / 8); 1145127668Sbms memcpy(&addr, &pptr[12], (plen + 7) / 8); 1146127668Sbms if (plen % 8) { 1147127668Sbms addr.s6_addr[(plen + 7) / 8 - 1] &= 1148127668Sbms ((0xff00 >> (plen % 8)) & 0xff); 1149127668Sbms } 1150127668Sbms /* the label may get offsetted by 4 bits so lets shift it right */ 1151127668Sbms snprintf(buf, buflen, "RD: %s, %s/%d, label:%u %s", 1152127668Sbms bgp_vpn_rd_print(pptr+4), 1153127668Sbms getname6((u_char *)&addr), 1154127668Sbms plen, 1155127668Sbms EXTRACT_24BITS(pptr+1)>>4, 1156127668Sbms ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" ); 1157127668Sbms 1158127668Sbms return 12 + (plen + 7) / 8; 1159127668Sbms 1160127668Sbmstrunc: 1161127668Sbms return -2; 1162127668Sbms} 116356893Sfenner#endif 116456893Sfenner 1165127668Sbmsstatic int 1166147899Ssamdecode_clnp_prefix(const u_char *pptr, char *buf, u_int buflen) 1167146773Ssam{ 1168146773Ssam u_int8_t addr[19]; 1169146773Ssam u_int plen; 1170146773Ssam 1171146773Ssam TCHECK(pptr[0]); 1172146773Ssam plen = pptr[0]; /* get prefix length */ 1173146773Ssam 1174146773Ssam if (152 < plen) 1175146773Ssam return -1; 1176146773Ssam 1177146773Ssam memset(&addr, 0, sizeof(addr)); 1178146773Ssam TCHECK2(pptr[4], (plen + 7) / 8); 1179146773Ssam memcpy(&addr, &pptr[4], (plen + 7) / 8); 1180146773Ssam if (plen % 8) { 1181146773Ssam addr[(plen + 7) / 8 - 1] &= 1182146773Ssam ((0xff00 >> (plen % 8)) & 0xff); 1183146773Ssam } 1184147899Ssam snprintf(buf, buflen, "%s/%d", 1185147899Ssam isonsap_string(addr,(plen + 7) / 8), 1186147899Ssam plen); 1187146773Ssam 1188147899Ssam return 1 + (plen + 7) / 8; 1189146773Ssam 1190146773Ssamtrunc: 1191146773Ssam return -2; 1192146773Ssam} 1193146773Ssam 1194146773Ssamstatic int 1195146773Ssamdecode_labeled_vpn_clnp_prefix(const u_char *pptr, char *buf, u_int buflen) 1196146773Ssam{ 1197146773Ssam u_int8_t addr[19]; 1198146773Ssam u_int plen; 1199146773Ssam 1200146773Ssam TCHECK(pptr[0]); 1201146773Ssam plen = pptr[0]; /* get prefix length */ 1202146773Ssam 1203172683Smlaier if ((24+64) > plen) 1204172683Smlaier return -1; 1205172683Smlaier 1206146773Ssam plen-=(24+64); /* adjust prefixlen - labellength - RD len*/ 1207146773Ssam 1208146773Ssam if (152 < plen) 1209146773Ssam return -1; 1210146773Ssam 1211146773Ssam memset(&addr, 0, sizeof(addr)); 1212146773Ssam TCHECK2(pptr[12], (plen + 7) / 8); 1213146773Ssam memcpy(&addr, &pptr[12], (plen + 7) / 8); 1214146773Ssam if (plen % 8) { 1215146773Ssam addr[(plen + 7) / 8 - 1] &= 1216146773Ssam ((0xff00 >> (plen % 8)) & 0xff); 1217146773Ssam } 1218146773Ssam /* the label may get offsetted by 4 bits so lets shift it right */ 1219146773Ssam snprintf(buf, buflen, "RD: %s, %s/%d, label:%u %s", 1220146773Ssam bgp_vpn_rd_print(pptr+4), 1221147899Ssam isonsap_string(addr,(plen + 7) / 8), 1222146773Ssam plen, 1223146773Ssam EXTRACT_24BITS(pptr+1)>>4, 1224146773Ssam ((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" ); 1225146773Ssam 1226146773Ssam return 12 + (plen + 7) / 8; 1227146773Ssam 1228146773Ssamtrunc: 1229146773Ssam return -2; 1230146773Ssam} 1231146773Ssam 1232190207Srpaulo/* 1233190207Srpaulo * bgp_attr_get_as_size 1234190207Srpaulo * 1235190207Srpaulo * Try to find the size of the ASs encoded in an as-path. It is not obvious, as 1236190207Srpaulo * both Old speakers that do not support 4 byte AS, and the new speakers that do 1237190207Srpaulo * support, exchange AS-Path with the same path-attribute type value 0x02. 1238190207Srpaulo */ 1239146773Ssamstatic int 1240190207Srpaulobgp_attr_get_as_size (u_int8_t bgpa_type, const u_char *pptr, int len) 1241190207Srpaulo{ 1242190207Srpaulo const u_char *tptr = pptr; 1243190207Srpaulo 1244190207Srpaulo /* 1245190207Srpaulo * If the path attribute is the optional AS4 path type, then we already 1246190207Srpaulo * know, that ASs must be encoded in 4 byte format. 1247190207Srpaulo */ 1248190207Srpaulo if (bgpa_type == BGPTYPE_AS4_PATH) { 1249190207Srpaulo return 4; 1250190207Srpaulo } 1251190207Srpaulo 1252190207Srpaulo /* 1253190207Srpaulo * Let us assume that ASs are of 2 bytes in size, and check if the AS-Path 1254190207Srpaulo * TLV is good. If not, ask the caller to try with AS encoded as 4 bytes 1255190207Srpaulo * each. 1256190207Srpaulo */ 1257190207Srpaulo while (tptr < pptr + len) { 1258190207Srpaulo TCHECK(tptr[0]); 1259190207Srpaulo 1260190207Srpaulo /* 1261190207Srpaulo * If we do not find a valid segment type, our guess might be wrong. 1262190207Srpaulo */ 1263190207Srpaulo if (tptr[0] < BGP_AS_SEG_TYPE_MIN || tptr[0] > BGP_AS_SEG_TYPE_MAX) { 1264190207Srpaulo goto trunc; 1265190207Srpaulo } 1266190207Srpaulo TCHECK(tptr[1]); 1267190207Srpaulo tptr += 2 + tptr[1] * 2; 1268190207Srpaulo } 1269190207Srpaulo 1270190207Srpaulo /* 1271190207Srpaulo * If we correctly reached end of the AS path attribute data content, 1272190207Srpaulo * then most likely ASs were indeed encoded as 2 bytes. 1273190207Srpaulo */ 1274190207Srpaulo if (tptr == pptr + len) { 1275190207Srpaulo return 2; 1276190207Srpaulo } 1277190207Srpaulo 1278190207Srpaulotrunc: 1279190207Srpaulo 1280190207Srpaulo /* 1281190207Srpaulo * We can come here, either we did not have enough data, or if we 1282190207Srpaulo * try to decode 4 byte ASs in 2 byte format. Either way, return 4, 1283190207Srpaulo * so that calller can try to decode each AS as of 4 bytes. If indeed 1284190207Srpaulo * there was not enough data, it will crib and end the parse anyways. 1285190207Srpaulo */ 1286190207Srpaulo return 4; 1287190207Srpaulo} 1288190207Srpaulo 1289190207Srpaulostatic int 1290241235Sdelphijbgp_attr_print(u_int atype, const u_char *pptr, u_int len) 129156893Sfenner{ 129256893Sfenner int i; 129356893Sfenner u_int16_t af; 1294147899Ssam u_int8_t safi, snpa, nhlen; 1295127668Sbms union { /* copy buffer for bandwidth values */ 1296127668Sbms float f; 1297127668Sbms u_int32_t i; 1298127668Sbms } bw; 129956893Sfenner int advance; 1300241235Sdelphij u_int tlen; 1301127668Sbms const u_char *tptr; 130275115Sfenner char buf[MAXHOSTNAMELEN + 100]; 1303146773Ssam char tokbuf[TOKBUFSIZE]; 1304190207Srpaulo int as_size; 130556893Sfenner 1306127668Sbms tptr = pptr; 1307127668Sbms tlen=len; 130856893Sfenner 1309241235Sdelphij switch (atype) { 131056893Sfenner case BGPTYPE_ORIGIN: 131156893Sfenner if (len != 1) 1312127668Sbms printf("invalid len"); 1313127668Sbms else { 1314127668Sbms TCHECK(*tptr); 1315146773Ssam printf("%s", tok2strbuf(bgp_origin_values, 1316146773Ssam "Unknown Origin Typecode", 1317146773Ssam tptr[0], 1318146773Ssam tokbuf, sizeof(tokbuf))); 1319127668Sbms } 132056893Sfenner break; 1321146773Ssam 1322190207Srpaulo 1323190207Srpaulo /* 1324190207Srpaulo * Process AS4 byte path and AS2 byte path attributes here. 1325190207Srpaulo */ 1326190207Srpaulo case BGPTYPE_AS4_PATH: 132756893Sfenner case BGPTYPE_AS_PATH: 132856893Sfenner if (len % 2) { 1329127668Sbms printf("invalid len"); 133056893Sfenner break; 133156893Sfenner } 1332127668Sbms if (!len) { 1333127668Sbms printf("empty"); 1334127668Sbms break; 1335127668Sbms } 1336127668Sbms 1337190207Srpaulo /* 1338190207Srpaulo * BGP updates exchanged between New speakers that support 4 1339190207Srpaulo * byte AS, ASs are always encoded in 4 bytes. There is no 1340190207Srpaulo * definitive way to find this, just by the packet's 1341190207Srpaulo * contents. So, check for packet's TLV's sanity assuming 1342190207Srpaulo * 2 bytes first, and it does not pass, assume that ASs are 1343190207Srpaulo * encoded in 4 bytes format and move on. 1344190207Srpaulo */ 1345241235Sdelphij as_size = bgp_attr_get_as_size(atype, pptr, len); 1346190207Srpaulo 1347127668Sbms while (tptr < pptr + len) { 1348127668Sbms TCHECK(tptr[0]); 1349146773Ssam printf("%s", tok2strbuf(bgp_as_path_segment_open_values, 1350146773Ssam "?", tptr[0], 1351146773Ssam tokbuf, sizeof(tokbuf))); 1352190207Srpaulo for (i = 0; i < tptr[1] * as_size; i += as_size) { 1353190207Srpaulo TCHECK2(tptr[2 + i], as_size); 1354214478Srpaulo printf("%s ", 1355214478Srpaulo as_printf(astostr, sizeof(astostr), 1356214478Srpaulo as_size == 2 ? 1357214478Srpaulo EXTRACT_16BITS(&tptr[2 + i]) : 1358214478Srpaulo EXTRACT_32BITS(&tptr[2 + i]))); 1359127668Sbms } 1360127668Sbms TCHECK(tptr[0]); 1361146773Ssam printf("%s", tok2strbuf(bgp_as_path_segment_close_values, 1362146773Ssam "?", tptr[0], 1363146773Ssam tokbuf, sizeof(tokbuf))); 1364127668Sbms TCHECK(tptr[1]); 1365190207Srpaulo tptr += 2 + tptr[1] * as_size; 136656893Sfenner } 136756893Sfenner break; 136856893Sfenner case BGPTYPE_NEXT_HOP: 136956893Sfenner if (len != 4) 1370127668Sbms printf("invalid len"); 1371127668Sbms else { 1372127668Sbms TCHECK2(tptr[0], 4); 1373127668Sbms printf("%s", getname(tptr)); 1374127668Sbms } 137556893Sfenner break; 137656893Sfenner case BGPTYPE_MULTI_EXIT_DISC: 137756893Sfenner case BGPTYPE_LOCAL_PREF: 137856893Sfenner if (len != 4) 1379127668Sbms printf("invalid len"); 1380127668Sbms else { 1381127668Sbms TCHECK2(tptr[0], 4); 1382127668Sbms printf("%u", EXTRACT_32BITS(tptr)); 1383127668Sbms } 138456893Sfenner break; 138556893Sfenner case BGPTYPE_ATOMIC_AGGREGATE: 138656893Sfenner if (len != 0) 1387127668Sbms printf("invalid len"); 138856893Sfenner break; 1389214478Srpaulo case BGPTYPE_AGGREGATOR: 1390214478Srpaulo 1391214478Srpaulo /* 1392214478Srpaulo * Depending on the AS encoded is of 2 bytes or of 4 bytes, 1393214478Srpaulo * the length of this PA can be either 6 bytes or 8 bytes. 1394214478Srpaulo */ 1395214478Srpaulo if (len != 6 && len != 8) { 1396214478Srpaulo printf("invalid len"); 1397214478Srpaulo break; 1398214478Srpaulo } 1399214478Srpaulo TCHECK2(tptr[0], len); 1400214478Srpaulo if (len == 6) { 1401214478Srpaulo printf(" AS #%s, origin %s", 1402214478Srpaulo as_printf(astostr, sizeof(astostr), EXTRACT_16BITS(tptr)), 1403127668Sbms getname(tptr + 2)); 1404214478Srpaulo } else { 1405214478Srpaulo printf(" AS #%s, origin %s", 1406214478Srpaulo as_printf(astostr, sizeof(astostr), 1407214478Srpaulo EXTRACT_32BITS(tptr)), getname(tptr + 4)); 1408214478Srpaulo } 1409214478Srpaulo break; 1410190207Srpaulo case BGPTYPE_AGGREGATOR4: 1411190207Srpaulo if (len != 8) { 1412190207Srpaulo printf("invalid len"); 1413190207Srpaulo break; 1414190207Srpaulo } 1415190207Srpaulo TCHECK2(tptr[0], 8); 1416214478Srpaulo printf(" AS #%s, origin %s", 1417214478Srpaulo as_printf(astostr, sizeof(astostr), EXTRACT_32BITS(tptr)), 1418214478Srpaulo getname(tptr + 4)); 1419190207Srpaulo break; 142056893Sfenner case BGPTYPE_COMMUNITIES: 142156893Sfenner if (len % 4) { 1422127668Sbms printf("invalid len"); 142356893Sfenner break; 142456893Sfenner } 1425127668Sbms while (tlen>0) { 142656893Sfenner u_int32_t comm; 1427127668Sbms TCHECK2(tptr[0], 4); 1428127668Sbms comm = EXTRACT_32BITS(tptr); 142956893Sfenner switch (comm) { 143056893Sfenner case BGP_COMMUNITY_NO_EXPORT: 143156893Sfenner printf(" NO_EXPORT"); 143256893Sfenner break; 143356893Sfenner case BGP_COMMUNITY_NO_ADVERT: 143456893Sfenner printf(" NO_ADVERTISE"); 143556893Sfenner break; 143656893Sfenner case BGP_COMMUNITY_NO_EXPORT_SUBCONFED: 143756893Sfenner printf(" NO_EXPORT_SUBCONFED"); 143856893Sfenner break; 143956893Sfenner default: 1440127668Sbms printf("%u:%u%s", 1441127668Sbms (comm >> 16) & 0xffff, 1442127668Sbms comm & 0xffff, 1443127668Sbms (tlen>4) ? ", " : ""); 144456893Sfenner break; 144556893Sfenner } 1446127668Sbms tlen -=4; 1447127668Sbms tptr +=4; 144856893Sfenner } 144956893Sfenner break; 1450127668Sbms case BGPTYPE_ORIGINATOR_ID: 1451127668Sbms if (len != 4) { 1452127668Sbms printf("invalid len"); 1453127668Sbms break; 1454127668Sbms } 1455127668Sbms TCHECK2(tptr[0], 4); 1456127668Sbms printf("%s",getname(tptr)); 1457127668Sbms break; 1458127668Sbms case BGPTYPE_CLUSTER_LIST: 1459127668Sbms if (len % 4) { 1460127668Sbms printf("invalid len"); 1461127668Sbms break; 1462127668Sbms } 1463127668Sbms while (tlen>0) { 1464127668Sbms TCHECK2(tptr[0], 4); 1465127668Sbms printf("%s%s", 1466127668Sbms getname(tptr), 1467127668Sbms (tlen>4) ? ", " : ""); 1468127668Sbms tlen -=4; 1469127668Sbms tptr +=4; 1470127668Sbms } 1471127668Sbms break; 147256893Sfenner case BGPTYPE_MP_REACH_NLRI: 1473127668Sbms TCHECK2(tptr[0], 3); 1474127668Sbms af = EXTRACT_16BITS(tptr); 1475127668Sbms safi = tptr[2]; 1476127668Sbms 1477127668Sbms printf("\n\t AFI: %s (%u), %sSAFI: %s (%u)", 1478172683Smlaier tok2strbuf(af_values, "Unknown AFI", af, 1479146773Ssam tokbuf, sizeof(tokbuf)), 1480127668Sbms af, 1481127668Sbms (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */ 1482146773Ssam tok2strbuf(bgp_safi_values, "Unknown SAFI", safi, 1483146773Ssam tokbuf, sizeof(tokbuf)), 1484127668Sbms safi); 148556893Sfenner 1486146773Ssam switch(af<<8 | safi) { 1487146773Ssam case (AFNUM_INET<<8 | SAFNUM_UNICAST): 1488146773Ssam case (AFNUM_INET<<8 | SAFNUM_MULTICAST): 1489146773Ssam case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST): 1490146773Ssam case (AFNUM_INET<<8 | SAFNUM_LABUNICAST): 1491146773Ssam case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO): 1492146773Ssam case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST): 1493146773Ssam case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST): 1494146773Ssam case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST): 1495190207Srpaulo case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN): 1496214478Srpaulo case (AFNUM_INET<<8 | SAFNUM_MDT): 149756893Sfenner#ifdef INET6 1498146773Ssam case (AFNUM_INET6<<8 | SAFNUM_UNICAST): 1499146773Ssam case (AFNUM_INET6<<8 | SAFNUM_MULTICAST): 1500146773Ssam case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST): 1501146773Ssam case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST): 1502146773Ssam case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST): 1503146773Ssam case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST): 1504146773Ssam case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST): 150556893Sfenner#endif 1506146773Ssam case (AFNUM_NSAP<<8 | SAFNUM_UNICAST): 1507146773Ssam case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST): 1508146773Ssam case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST): 1509146773Ssam case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST): 1510146773Ssam case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST): 1511146773Ssam case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST): 1512146773Ssam case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST): 1513146773Ssam case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST): 1514146773Ssam case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST): 1515172683Smlaier case (AFNUM_VPLS<<8 | SAFNUM_VPLS): 1516146773Ssam break; 1517146773Ssam default: 1518147899Ssam TCHECK2(tptr[0], tlen); 1519146773Ssam printf("\n\t no AFI %u / SAFI %u decoder",af,safi); 1520127668Sbms if (vflag <= 1) 1521127668Sbms print_unknown_data(tptr,"\n\t ",tlen); 1522146773Ssam goto done; 1523127668Sbms break; 1524127668Sbms } 152556893Sfenner 1526127668Sbms tptr +=3; 1527127668Sbms 1528127668Sbms TCHECK(tptr[0]); 1529147899Ssam nhlen = tptr[0]; 1530147899Ssam tlen = nhlen; 1531127668Sbms tptr++; 1532127668Sbms 153356893Sfenner if (tlen) { 1534251158Sdelphij int nnh = 0; 1535146773Ssam printf("\n\t nexthop: "); 1536146773Ssam while (tlen > 0) { 1537251158Sdelphij if ( nnh++ > 0 ) { 1538251158Sdelphij printf( ", " ); 1539251158Sdelphij } 1540146773Ssam switch(af<<8 | safi) { 1541146773Ssam case (AFNUM_INET<<8 | SAFNUM_UNICAST): 1542146773Ssam case (AFNUM_INET<<8 | SAFNUM_MULTICAST): 1543146773Ssam case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST): 1544146773Ssam case (AFNUM_INET<<8 | SAFNUM_LABUNICAST): 1545146773Ssam case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO): 1546190207Srpaulo case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN): 1547214478Srpaulo case (AFNUM_INET<<8 | SAFNUM_MDT): 1548214478Srpaulo if (tlen < (int)sizeof(struct in_addr)) { 1549146773Ssam printf("invalid len"); 1550146773Ssam tlen = 0; 1551146773Ssam } else { 1552146773Ssam TCHECK2(tptr[0], sizeof(struct in_addr)); 1553146773Ssam printf("%s",getname(tptr)); 1554146773Ssam tlen -= sizeof(struct in_addr); 1555146773Ssam tptr += sizeof(struct in_addr); 1556146773Ssam } 1557146773Ssam break; 1558146773Ssam case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST): 1559146773Ssam case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST): 1560146773Ssam case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST): 1561146773Ssam if (tlen < (int)(sizeof(struct in_addr)+BGP_VPN_RD_LEN)) { 1562146773Ssam printf("invalid len"); 1563146773Ssam tlen = 0; 1564146773Ssam } else { 1565146773Ssam TCHECK2(tptr[0], sizeof(struct in_addr)+BGP_VPN_RD_LEN); 1566146773Ssam printf("RD: %s, %s", 1567146773Ssam bgp_vpn_rd_print(tptr), 1568146773Ssam getname(tptr+BGP_VPN_RD_LEN)); 1569146773Ssam tlen -= (sizeof(struct in_addr)+BGP_VPN_RD_LEN); 1570146773Ssam tptr += (sizeof(struct in_addr)+BGP_VPN_RD_LEN); 1571146773Ssam } 1572146773Ssam break; 157356893Sfenner#ifdef INET6 1574146773Ssam case (AFNUM_INET6<<8 | SAFNUM_UNICAST): 1575146773Ssam case (AFNUM_INET6<<8 | SAFNUM_MULTICAST): 1576146773Ssam case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST): 1577146773Ssam case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST): 1578146773Ssam if (tlen < (int)sizeof(struct in6_addr)) { 1579146773Ssam printf("invalid len"); 1580146773Ssam tlen = 0; 1581146773Ssam } else { 1582146773Ssam TCHECK2(tptr[0], sizeof(struct in6_addr)); 1583146773Ssam printf("%s", getname6(tptr)); 1584146773Ssam tlen -= sizeof(struct in6_addr); 1585146773Ssam tptr += sizeof(struct in6_addr); 1586146773Ssam } 1587146773Ssam break; 1588146773Ssam case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST): 1589146773Ssam case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST): 1590146773Ssam case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST): 1591146773Ssam if (tlen < (int)(sizeof(struct in6_addr)+BGP_VPN_RD_LEN)) { 1592146773Ssam printf("invalid len"); 1593146773Ssam tlen = 0; 1594146773Ssam } else { 1595146773Ssam TCHECK2(tptr[0], sizeof(struct in6_addr)+BGP_VPN_RD_LEN); 1596146773Ssam printf("RD: %s, %s", 1597146773Ssam bgp_vpn_rd_print(tptr), 1598146773Ssam getname6(tptr+BGP_VPN_RD_LEN)); 1599146773Ssam tlen -= (sizeof(struct in6_addr)+BGP_VPN_RD_LEN); 1600146773Ssam tptr += (sizeof(struct in6_addr)+BGP_VPN_RD_LEN); 1601146773Ssam } 1602146773Ssam break; 160356893Sfenner#endif 1604172683Smlaier case (AFNUM_VPLS<<8 | SAFNUM_VPLS): 1605146773Ssam case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST): 1606146773Ssam case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST): 1607146773Ssam case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST): 1608146773Ssam if (tlen < (int)sizeof(struct in_addr)) { 1609146773Ssam printf("invalid len"); 1610146773Ssam tlen = 0; 1611146773Ssam } else { 1612146773Ssam TCHECK2(tptr[0], sizeof(struct in_addr)); 1613146773Ssam printf("%s", getname(tptr)); 1614146773Ssam tlen -= (sizeof(struct in_addr)); 1615146773Ssam tptr += (sizeof(struct in_addr)); 1616146773Ssam } 1617146773Ssam break; 1618146773Ssam case (AFNUM_NSAP<<8 | SAFNUM_UNICAST): 1619146773Ssam case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST): 1620146773Ssam case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST): 1621146773Ssam TCHECK2(tptr[0], tlen); 1622146773Ssam printf("%s",isonsap_string(tptr,tlen)); 1623146773Ssam tptr += tlen; 1624146773Ssam tlen = 0; 1625146773Ssam break; 1626127668Sbms 1627146773Ssam case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST): 1628146773Ssam case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST): 1629146773Ssam case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST): 1630146773Ssam if (tlen < BGP_VPN_RD_LEN+1) { 1631146773Ssam printf("invalid len"); 1632146773Ssam tlen = 0; 1633146773Ssam } else { 1634146773Ssam TCHECK2(tptr[0], tlen); 1635146773Ssam printf("RD: %s, %s", 1636146773Ssam bgp_vpn_rd_print(tptr), 1637146773Ssam isonsap_string(tptr+BGP_VPN_RD_LEN,tlen-BGP_VPN_RD_LEN)); 1638146773Ssam /* rfc986 mapped IPv4 address ? */ 1639146773Ssam if (EXTRACT_32BITS(tptr+BGP_VPN_RD_LEN) == 0x47000601) 1640146773Ssam printf(" = %s", getname(tptr+BGP_VPN_RD_LEN+4)); 1641146773Ssam#ifdef INET6 1642146773Ssam /* rfc1888 mapped IPv6 address ? */ 1643146773Ssam else if (EXTRACT_24BITS(tptr+BGP_VPN_RD_LEN) == 0x350000) 1644146773Ssam printf(" = %s", getname6(tptr+BGP_VPN_RD_LEN+3)); 1645146773Ssam#endif 1646146773Ssam tptr += tlen; 1647146773Ssam tlen = 0; 1648146773Ssam } 1649146773Ssam break; 1650146773Ssam default: 1651146773Ssam TCHECK2(tptr[0], tlen); 1652146773Ssam printf("no AFI %u/SAFI %u decoder",af,safi); 1653146773Ssam if (vflag <= 1) 1654146773Ssam print_unknown_data(tptr,"\n\t ",tlen); 1655146773Ssam tptr += tlen; 1656146773Ssam tlen = 0; 1657146773Ssam goto done; 1658146773Ssam break; 1659146773Ssam } 1660146773Ssam } 166156893Sfenner } 1662147899Ssam printf(", nh-length: %u", nhlen); 1663127668Sbms tptr += tlen; 166456893Sfenner 1665127668Sbms TCHECK(tptr[0]); 1666127668Sbms snpa = tptr[0]; 1667127668Sbms tptr++; 1668127668Sbms 166956893Sfenner if (snpa) { 1670127668Sbms printf("\n\t %u SNPA", snpa); 167156893Sfenner for (/*nothing*/; snpa > 0; snpa--) { 1672127668Sbms TCHECK(tptr[0]); 1673127668Sbms printf("\n\t %d bytes", tptr[0]); 1674127668Sbms tptr += tptr[0] + 1; 167556893Sfenner } 1676127668Sbms } else { 1677127668Sbms printf(", no SNPA"); 1678127668Sbms } 167956893Sfenner 1680127668Sbms while (len - (tptr - pptr) > 0) { 1681146773Ssam switch (af<<8 | safi) { 1682146773Ssam case (AFNUM_INET<<8 | SAFNUM_UNICAST): 1683146773Ssam case (AFNUM_INET<<8 | SAFNUM_MULTICAST): 1684146773Ssam case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST): 1685241235Sdelphij advance = decode_prefix4(tptr, len, buf, sizeof(buf)); 1686146773Ssam if (advance == -1) 1687146773Ssam printf("\n\t (illegal prefix length)"); 1688146773Ssam else if (advance == -2) 1689146773Ssam goto trunc; 1690241235Sdelphij else if (advance == -3) 1691241235Sdelphij break; /* bytes left, but not enough */ 1692146773Ssam else 1693146773Ssam printf("\n\t %s", buf); 1694146773Ssam break; 1695146773Ssam case (AFNUM_INET<<8 | SAFNUM_LABUNICAST): 1696241235Sdelphij advance = decode_labeled_prefix4(tptr, len, buf, sizeof(buf)); 1697146773Ssam if (advance == -1) 1698146773Ssam printf("\n\t (illegal prefix length)"); 1699146773Ssam else if (advance == -2) 1700146773Ssam goto trunc; 1701241235Sdelphij else if (advance == -3) 1702241235Sdelphij break; /* bytes left, but not enough */ 1703146773Ssam else 1704146773Ssam printf("\n\t %s", buf); 1705146773Ssam break; 1706146773Ssam case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST): 1707146773Ssam case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST): 1708146773Ssam case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST): 1709146773Ssam advance = decode_labeled_vpn_prefix4(tptr, buf, sizeof(buf)); 1710146773Ssam if (advance == -1) 1711146773Ssam printf("\n\t (illegal prefix length)"); 1712146773Ssam else if (advance == -2) 1713146773Ssam goto trunc; 1714146773Ssam else 1715146773Ssam printf("\n\t %s", buf); 1716146773Ssam break; 1717146773Ssam case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO): 1718146773Ssam advance = decode_rt_routing_info(tptr, buf, sizeof(buf)); 1719146773Ssam if (advance == -1) 1720146773Ssam printf("\n\t (illegal prefix length)"); 1721146773Ssam else if (advance == -2) 1722146773Ssam goto trunc; 1723146773Ssam else 1724146773Ssam printf("\n\t %s", buf); 1725146773Ssam break; 1726190207Srpaulo case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN): /* fall through */ 1727190207Srpaulo case (AFNUM_INET6<<8 | SAFNUM_MULTICAST_VPN): 1728190207Srpaulo advance = decode_multicast_vpn(tptr, buf, sizeof(buf)); 1729190207Srpaulo if (advance == -1) 1730190207Srpaulo printf("\n\t (illegal prefix length)"); 1731190207Srpaulo else if (advance == -2) 1732190207Srpaulo goto trunc; 1733190207Srpaulo else 1734190207Srpaulo printf("\n\t %s", buf); 1735190207Srpaulo break; 1736214478Srpaulo 1737214478Srpaulo case (AFNUM_INET<<8 | SAFNUM_MDT): 1738214478Srpaulo advance = decode_mdt_vpn_nlri(tptr, buf, sizeof(buf)); 1739214478Srpaulo if (advance == -1) 1740214478Srpaulo printf("\n\t (illegal prefix length)"); 1741214478Srpaulo else if (advance == -2) 1742214478Srpaulo goto trunc; 1743214478Srpaulo else 1744214478Srpaulo printf("\n\t %s", buf); 1745214478Srpaulo break; 174656893Sfenner#ifdef INET6 1747146773Ssam case (AFNUM_INET6<<8 | SAFNUM_UNICAST): 1748146773Ssam case (AFNUM_INET6<<8 | SAFNUM_MULTICAST): 1749146773Ssam case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST): 1750241235Sdelphij advance = decode_prefix6(tptr, len, buf, sizeof(buf)); 1751146773Ssam if (advance == -1) 1752146773Ssam printf("\n\t (illegal prefix length)"); 1753146773Ssam else if (advance == -2) 1754146773Ssam goto trunc; 1755241235Sdelphij else if (advance == -3) 1756241235Sdelphij break; /* bytes left, but not enough */ 1757146773Ssam else 1758146773Ssam printf("\n\t %s", buf); 1759146773Ssam break; 1760146773Ssam case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST): 1761241235Sdelphij advance = decode_labeled_prefix6(tptr, len, buf, sizeof(buf)); 1762146773Ssam if (advance == -1) 1763146773Ssam printf("\n\t (illegal prefix length)"); 1764146773Ssam else if (advance == -2) 1765146773Ssam goto trunc; 1766241235Sdelphij else if (advance == -3) 1767241235Sdelphij break; /* bytes left, but not enough */ 1768146773Ssam else 1769146773Ssam printf("\n\t %s", buf); 1770146773Ssam break; 1771146773Ssam case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST): 1772146773Ssam case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST): 1773146773Ssam case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST): 1774146773Ssam advance = decode_labeled_vpn_prefix6(tptr, buf, sizeof(buf)); 1775146773Ssam if (advance == -1) 1776146773Ssam printf("\n\t (illegal prefix length)"); 1777146773Ssam else if (advance == -2) 1778146773Ssam goto trunc; 1779146773Ssam else 1780146773Ssam printf("\n\t %s", buf); 1781146773Ssam break; 178256893Sfenner#endif 1783172683Smlaier case (AFNUM_VPLS<<8 | SAFNUM_VPLS): 1784146773Ssam case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST): 1785146773Ssam case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST): 1786146773Ssam case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST): 1787146773Ssam advance = decode_labeled_vpn_l2(tptr, buf, sizeof(buf)); 1788146773Ssam if (advance == -1) 1789146773Ssam printf("\n\t (illegal length)"); 1790146773Ssam else if (advance == -2) 1791146773Ssam goto trunc; 1792146773Ssam else 1793146773Ssam printf("\n\t %s", buf); 1794146773Ssam break; 1795146773Ssam case (AFNUM_NSAP<<8 | SAFNUM_UNICAST): 1796146773Ssam case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST): 1797146773Ssam case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST): 1798147899Ssam advance = decode_clnp_prefix(tptr, buf, sizeof(buf)); 1799146773Ssam if (advance == -1) 1800146773Ssam printf("\n\t (illegal prefix length)"); 1801146773Ssam else if (advance == -2) 1802146773Ssam goto trunc; 1803146773Ssam else 1804146773Ssam printf("\n\t %s", buf); 1805146773Ssam break; 1806146773Ssam case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST): 1807146773Ssam case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST): 1808146773Ssam case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST): 1809146773Ssam advance = decode_labeled_vpn_clnp_prefix(tptr, buf, sizeof(buf)); 1810146773Ssam if (advance == -1) 1811146773Ssam printf("\n\t (illegal prefix length)"); 1812146773Ssam else if (advance == -2) 1813146773Ssam goto trunc; 1814146773Ssam else 1815146773Ssam printf("\n\t %s", buf); 1816146773Ssam break; 1817146773Ssam default: 1818146773Ssam TCHECK2(*tptr,tlen); 1819146773Ssam printf("\n\t no AFI %u / SAFI %u decoder",af,safi); 1820146773Ssam if (vflag <= 1) 1821146773Ssam print_unknown_data(tptr,"\n\t ",tlen); 1822146773Ssam advance = 0; 1823146773Ssam tptr = pptr + len; 1824146773Ssam break; 1825146773Ssam } 1826147899Ssam if (advance < 0) 1827147899Ssam break; 1828146773Ssam tptr += advance; 182956893Sfenner } 1830146773Ssam done: 183156893Sfenner break; 183256893Sfenner 183356893Sfenner case BGPTYPE_MP_UNREACH_NLRI: 1834146773Ssam TCHECK2(tptr[0], BGP_MP_NLRI_MINSIZE); 1835127668Sbms af = EXTRACT_16BITS(tptr); 1836127668Sbms safi = tptr[2]; 183756893Sfenner 1838127668Sbms printf("\n\t AFI: %s (%u), %sSAFI: %s (%u)", 1839172683Smlaier tok2strbuf(af_values, "Unknown AFI", af, 1840146773Ssam tokbuf, sizeof(tokbuf)), 1841127668Sbms af, 1842127668Sbms (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */ 1843146773Ssam tok2strbuf(bgp_safi_values, "Unknown SAFI", safi, 1844146773Ssam tokbuf, sizeof(tokbuf)), 1845127668Sbms safi); 1846127668Sbms 1847146773Ssam if (len == BGP_MP_NLRI_MINSIZE) 1848146773Ssam printf("\n\t End-of-Rib Marker (empty NLRI)"); 1849146773Ssam 1850127668Sbms tptr += 3; 1851127668Sbms 1852127668Sbms while (len - (tptr - pptr) > 0) { 1853146773Ssam switch (af<<8 | safi) { 1854146773Ssam case (AFNUM_INET<<8 | SAFNUM_UNICAST): 1855146773Ssam case (AFNUM_INET<<8 | SAFNUM_MULTICAST): 1856146773Ssam case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST): 1857241235Sdelphij advance = decode_prefix4(tptr, len, buf, sizeof(buf)); 1858146773Ssam if (advance == -1) 1859146773Ssam printf("\n\t (illegal prefix length)"); 1860146773Ssam else if (advance == -2) 1861146773Ssam goto trunc; 1862241235Sdelphij else if (advance == -3) 1863241235Sdelphij break; /* bytes left, but not enough */ 1864146773Ssam else 1865146773Ssam printf("\n\t %s", buf); 1866146773Ssam break; 1867146773Ssam case (AFNUM_INET<<8 | SAFNUM_LABUNICAST): 1868241235Sdelphij advance = decode_labeled_prefix4(tptr, len, buf, sizeof(buf)); 1869146773Ssam if (advance == -1) 1870146773Ssam printf("\n\t (illegal prefix length)"); 1871146773Ssam else if (advance == -2) 1872146773Ssam goto trunc; 1873241235Sdelphij else if (advance == -3) 1874241235Sdelphij break; /* bytes left, but not enough */ 1875146773Ssam else 1876146773Ssam printf("\n\t %s", buf); 1877146773Ssam break; 1878146773Ssam case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST): 1879146773Ssam case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST): 1880146773Ssam case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST): 1881146773Ssam advance = decode_labeled_vpn_prefix4(tptr, buf, sizeof(buf)); 1882146773Ssam if (advance == -1) 1883146773Ssam printf("\n\t (illegal prefix length)"); 1884146773Ssam else if (advance == -2) 1885146773Ssam goto trunc; 1886146773Ssam else 1887146773Ssam printf("\n\t %s", buf); 1888146773Ssam break; 188956893Sfenner#ifdef INET6 1890146773Ssam case (AFNUM_INET6<<8 | SAFNUM_UNICAST): 1891146773Ssam case (AFNUM_INET6<<8 | SAFNUM_MULTICAST): 1892146773Ssam case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST): 1893241235Sdelphij advance = decode_prefix6(tptr, len, buf, sizeof(buf)); 1894146773Ssam if (advance == -1) 1895146773Ssam printf("\n\t (illegal prefix length)"); 1896146773Ssam else if (advance == -2) 1897146773Ssam goto trunc; 1898241235Sdelphij else if (advance == -3) 1899241235Sdelphij break; /* bytes left, but not enough */ 1900146773Ssam else 1901146773Ssam printf("\n\t %s", buf); 1902146773Ssam break; 1903146773Ssam case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST): 1904241235Sdelphij advance = decode_labeled_prefix6(tptr, len, buf, sizeof(buf)); 1905146773Ssam if (advance == -1) 1906146773Ssam printf("\n\t (illegal prefix length)"); 1907146773Ssam else if (advance == -2) 1908146773Ssam goto trunc; 1909241235Sdelphij else if (advance == -3) 1910241235Sdelphij break; /* bytes left, but not enough */ 1911146773Ssam else 1912146773Ssam printf("\n\t %s", buf); 1913146773Ssam break; 1914146773Ssam case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST): 1915146773Ssam case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST): 1916146773Ssam case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST): 1917146773Ssam advance = decode_labeled_vpn_prefix6(tptr, buf, sizeof(buf)); 1918146773Ssam if (advance == -1) 1919146773Ssam printf("\n\t (illegal prefix length)"); 1920146773Ssam else if (advance == -2) 1921146773Ssam goto trunc; 1922146773Ssam else 1923146773Ssam printf("\n\t %s", buf); 1924146773Ssam break; 192556893Sfenner#endif 1926172683Smlaier case (AFNUM_VPLS<<8 | SAFNUM_VPLS): 1927146773Ssam case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST): 1928146773Ssam case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST): 1929146773Ssam case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST): 1930146773Ssam advance = decode_labeled_vpn_l2(tptr, buf, sizeof(buf)); 1931146773Ssam if (advance == -1) 1932146773Ssam printf("\n\t (illegal length)"); 1933146773Ssam else if (advance == -2) 1934146773Ssam goto trunc; 1935146773Ssam else 1936146773Ssam printf("\n\t %s", buf); 1937146773Ssam break; 1938146773Ssam case (AFNUM_NSAP<<8 | SAFNUM_UNICAST): 1939146773Ssam case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST): 1940146773Ssam case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST): 1941147899Ssam advance = decode_clnp_prefix(tptr, buf, sizeof(buf)); 1942146773Ssam if (advance == -1) 1943146773Ssam printf("\n\t (illegal prefix length)"); 1944146773Ssam else if (advance == -2) 1945146773Ssam goto trunc; 1946146773Ssam else 1947146773Ssam printf("\n\t %s", buf); 1948146773Ssam break; 1949146773Ssam case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST): 1950146773Ssam case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST): 1951146773Ssam case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST): 1952146773Ssam advance = decode_labeled_vpn_clnp_prefix(tptr, buf, sizeof(buf)); 1953146773Ssam if (advance == -1) 1954146773Ssam printf("\n\t (illegal prefix length)"); 1955146773Ssam else if (advance == -2) 1956146773Ssam goto trunc; 1957146773Ssam else 1958146773Ssam printf("\n\t %s", buf); 1959146773Ssam break; 1960214478Srpaulo case (AFNUM_INET<<8 | SAFNUM_MDT): 1961214478Srpaulo advance = decode_mdt_vpn_nlri(tptr, buf, sizeof(buf)); 1962214478Srpaulo if (advance == -1) 1963214478Srpaulo printf("\n\t (illegal prefix length)"); 1964214478Srpaulo else if (advance == -2) 1965214478Srpaulo goto trunc; 1966214478Srpaulo else 1967214478Srpaulo printf("\n\t %s", buf); 1968214478Srpaulo break; 1969190207Srpaulo case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN): /* fall through */ 1970190207Srpaulo case (AFNUM_INET6<<8 | SAFNUM_MULTICAST_VPN): 1971190207Srpaulo advance = decode_multicast_vpn(tptr, buf, sizeof(buf)); 1972190207Srpaulo if (advance == -1) 1973190207Srpaulo printf("\n\t (illegal prefix length)"); 1974190207Srpaulo else if (advance == -2) 1975190207Srpaulo goto trunc; 1976190207Srpaulo else 1977190207Srpaulo printf("\n\t %s", buf); 1978190207Srpaulo break; 1979146773Ssam default: 1980146773Ssam TCHECK2(*(tptr-3),tlen); 1981146773Ssam printf("no AFI %u / SAFI %u decoder",af,safi); 1982146773Ssam if (vflag <= 1) 1983146773Ssam print_unknown_data(tptr-3,"\n\t ",tlen); 1984146773Ssam advance = 0; 1985146773Ssam tptr = pptr + len; 1986146773Ssam break; 1987146773Ssam } 1988147899Ssam if (advance < 0) 1989147899Ssam break; 1990146773Ssam tptr += advance; 199156893Sfenner } 199256893Sfenner break; 1993127668Sbms case BGPTYPE_EXTD_COMMUNITIES: 1994127668Sbms if (len % 8) { 1995127668Sbms printf("invalid len"); 1996127668Sbms break; 1997127668Sbms } 1998127668Sbms while (tlen>0) { 1999127668Sbms u_int16_t extd_comm; 2000127668Sbms 2001127668Sbms TCHECK2(tptr[0], 2); 2002127668Sbms extd_comm=EXTRACT_16BITS(tptr); 2003127668Sbms 2004127668Sbms printf("\n\t %s (0x%04x), Flags [%s]", 2005146773Ssam tok2strbuf(bgp_extd_comm_subtype_values, 2006146773Ssam "unknown extd community typecode", 2007146773Ssam extd_comm, tokbuf, sizeof(tokbuf)), 2008127668Sbms extd_comm, 2009127668Sbms bittok2str(bgp_extd_comm_flag_values, "none", extd_comm)); 2010127668Sbms 2011127668Sbms TCHECK2(*(tptr+2), 6); 2012127668Sbms switch(extd_comm) { 2013127668Sbms case BGP_EXT_COM_RT_0: 2014127668Sbms case BGP_EXT_COM_RO_0: 2015235530Sdelphij case BGP_EXT_COM_L2VPN_RT_0: 2016190207Srpaulo printf(": %u:%u (= %s)", 2017127668Sbms EXTRACT_16BITS(tptr+2), 2018190207Srpaulo EXTRACT_32BITS(tptr+4), 2019127668Sbms getname(tptr+4)); 2020127668Sbms break; 2021127668Sbms case BGP_EXT_COM_RT_1: 2022127668Sbms case BGP_EXT_COM_RO_1: 2023235530Sdelphij case BGP_EXT_COM_L2VPN_RT_1: 2024190207Srpaulo case BGP_EXT_COM_VRF_RT_IMP: 2025127668Sbms printf(": %s:%u", 2026127668Sbms getname(tptr+2), 2027127668Sbms EXTRACT_16BITS(tptr+6)); 2028127668Sbms break; 2029127668Sbms case BGP_EXT_COM_RT_2: 2030127668Sbms case BGP_EXT_COM_RO_2: 2031214478Srpaulo printf(": %s:%u", 2032214478Srpaulo as_printf(astostr, sizeof(astostr), 2033214478Srpaulo EXTRACT_32BITS(tptr+2)), EXTRACT_16BITS(tptr+6)); 2034214478Srpaulo break; 2035127668Sbms case BGP_EXT_COM_LINKBAND: 2036127668Sbms bw.i = EXTRACT_32BITS(tptr+2); 2037127668Sbms printf(": bandwidth: %.3f Mbps", 2038127668Sbms bw.f*8/1000000); 2039127668Sbms break; 2040127668Sbms case BGP_EXT_COM_VPN_ORIGIN: 2041127668Sbms case BGP_EXT_COM_VPN_ORIGIN2: 2042127668Sbms case BGP_EXT_COM_VPN_ORIGIN3: 2043127668Sbms case BGP_EXT_COM_VPN_ORIGIN4: 2044127668Sbms case BGP_EXT_COM_OSPF_RID: 2045127668Sbms case BGP_EXT_COM_OSPF_RID2: 2046127668Sbms printf("%s", getname(tptr+2)); 2047127668Sbms break; 2048127668Sbms case BGP_EXT_COM_OSPF_RTYPE: 2049127668Sbms case BGP_EXT_COM_OSPF_RTYPE2: 2050127668Sbms printf(": area:%s, router-type:%s, metric-type:%s%s", 2051127668Sbms getname(tptr+2), 2052146773Ssam tok2strbuf(bgp_extd_comm_ospf_rtype_values, 2053146773Ssam "unknown (0x%02x)", 2054146773Ssam *(tptr+6), 2055146773Ssam tokbuf, sizeof(tokbuf)), 2056127668Sbms (*(tptr+7) & BGP_OSPF_RTYPE_METRIC_TYPE) ? "E2" : "", 2057172683Smlaier ((*(tptr+6) == BGP_OSPF_RTYPE_EXT) || (*(tptr+6) == BGP_OSPF_RTYPE_NSSA)) ? "E1" : ""); 2058127668Sbms break; 2059127668Sbms case BGP_EXT_COM_L2INFO: 2060127668Sbms printf(": %s Control Flags [0x%02x]:MTU %u", 2061146773Ssam tok2strbuf(l2vpn_encaps_values, 2062146773Ssam "unknown encaps", 2063146773Ssam *(tptr+2), 2064146773Ssam tokbuf, sizeof(tokbuf)), 2065127668Sbms *(tptr+3), 2066127668Sbms EXTRACT_16BITS(tptr+4)); 2067127668Sbms break; 2068190207Srpaulo case BGP_EXT_COM_SOURCE_AS: 2069190207Srpaulo printf(": AS %u", EXTRACT_16BITS(tptr+2)); 2070190207Srpaulo break; 2071127668Sbms default: 2072147899Ssam TCHECK2(*tptr,8); 2073127668Sbms print_unknown_data(tptr,"\n\t ",8); 2074127668Sbms break; 2075127668Sbms } 2076127668Sbms tlen -=8; 2077127668Sbms tptr +=8; 2078127668Sbms } 2079127668Sbms break; 2080127668Sbms 2081190207Srpaulo case BGPTYPE_PMSI_TUNNEL: 2082190207Srpaulo { 2083190207Srpaulo u_int8_t tunnel_type, flags; 2084190207Srpaulo 2085190207Srpaulo tunnel_type = *(tptr+1); 2086190207Srpaulo flags = *tptr; 2087190207Srpaulo tlen = len; 2088190207Srpaulo 2089190207Srpaulo TCHECK2(tptr[0], 5); 2090190207Srpaulo printf("\n\t Tunnel-type %s (%u), Flags [%s], MPLS Label %u", 2091190207Srpaulo tok2str(bgp_pmsi_tunnel_values, "Unknown", tunnel_type), 2092190207Srpaulo tunnel_type, 2093190207Srpaulo bittok2str(bgp_pmsi_flag_values, "none", flags), 2094190207Srpaulo EXTRACT_24BITS(tptr+2)>>4); 2095190207Srpaulo 2096190207Srpaulo tptr +=5; 2097190207Srpaulo tlen -= 5; 2098190207Srpaulo 2099190207Srpaulo switch (tunnel_type) { 2100190207Srpaulo case BGP_PMSI_TUNNEL_PIM_SM: /* fall through */ 2101190207Srpaulo case BGP_PMSI_TUNNEL_PIM_BIDIR: 2102190207Srpaulo TCHECK2(tptr[0], 8); 2103190207Srpaulo printf("\n\t Sender %s, P-Group %s", 2104190207Srpaulo ipaddr_string(tptr), 2105190207Srpaulo ipaddr_string(tptr+4)); 2106190207Srpaulo break; 2107190207Srpaulo 2108190207Srpaulo case BGP_PMSI_TUNNEL_PIM_SSM: 2109190207Srpaulo TCHECK2(tptr[0], 8); 2110190207Srpaulo printf("\n\t Root-Node %s, P-Group %s", 2111190207Srpaulo ipaddr_string(tptr), 2112190207Srpaulo ipaddr_string(tptr+4)); 2113190207Srpaulo break; 2114190207Srpaulo case BGP_PMSI_TUNNEL_INGRESS: 2115190207Srpaulo TCHECK2(tptr[0], 4); 2116190207Srpaulo printf("\n\t Tunnel-Endpoint %s", 2117190207Srpaulo ipaddr_string(tptr)); 2118190207Srpaulo break; 2119190207Srpaulo case BGP_PMSI_TUNNEL_LDP_P2MP: /* fall through */ 2120190207Srpaulo case BGP_PMSI_TUNNEL_LDP_MP2MP: 2121190207Srpaulo TCHECK2(tptr[0], 8); 2122190207Srpaulo printf("\n\t Root-Node %s, LSP-ID 0x%08x", 2123190207Srpaulo ipaddr_string(tptr), 2124190207Srpaulo EXTRACT_32BITS(tptr+4)); 2125190207Srpaulo break; 2126190207Srpaulo case BGP_PMSI_TUNNEL_RSVP_P2MP: 2127190207Srpaulo TCHECK2(tptr[0], 8); 2128190207Srpaulo printf("\n\t Extended-Tunnel-ID %s, P2MP-ID 0x%08x", 2129190207Srpaulo ipaddr_string(tptr), 2130190207Srpaulo EXTRACT_32BITS(tptr+4)); 2131190207Srpaulo break; 2132190207Srpaulo default: 2133190207Srpaulo if (vflag <= 1) { 2134190207Srpaulo print_unknown_data(tptr,"\n\t ",tlen); 2135190207Srpaulo } 2136190207Srpaulo } 2137190207Srpaulo break; 2138190207Srpaulo } 2139146773Ssam case BGPTYPE_ATTR_SET: 2140146773Ssam TCHECK2(tptr[0], 4); 2141241235Sdelphij if (len < 4) 2142241235Sdelphij goto trunc; 2143214478Srpaulo printf("\n\t Origin AS: %s", 2144214478Srpaulo as_printf(astostr, sizeof(astostr), EXTRACT_32BITS(tptr))); 2145214478Srpaulo tptr+=4; 2146146773Ssam len -=4; 2147146773Ssam 2148241235Sdelphij while (len) { 2149241235Sdelphij u_int aflags, atype, alenlen, alen; 2150146773Ssam 2151241235Sdelphij TCHECK2(tptr[0], 2); 2152241235Sdelphij if (len < 2) 2153241235Sdelphij goto trunc; 2154241235Sdelphij aflags = *tptr; 2155241235Sdelphij atype = *(tptr + 1); 2156241235Sdelphij tptr += 2; 2157241235Sdelphij len -= 2; 2158241235Sdelphij alenlen = bgp_attr_lenlen(aflags, tptr); 2159241235Sdelphij TCHECK2(tptr[0], alenlen); 2160241235Sdelphij if (len < alenlen) 2161241235Sdelphij goto trunc; 2162241235Sdelphij alen = bgp_attr_len(aflags, tptr); 2163241235Sdelphij tptr += alenlen; 2164241235Sdelphij len -= alenlen; 2165146773Ssam 2166146773Ssam printf("\n\t %s (%u), length: %u", 2167146773Ssam tok2strbuf(bgp_attr_values, 2168241235Sdelphij "Unknown Attribute", atype, 2169241235Sdelphij tokbuf, sizeof(tokbuf)), 2170241235Sdelphij atype, 2171146773Ssam alen); 2172146773Ssam 2173241235Sdelphij if (aflags) { 2174146773Ssam printf(", Flags [%s%s%s%s", 2175241235Sdelphij aflags & 0x80 ? "O" : "", 2176241235Sdelphij aflags & 0x40 ? "T" : "", 2177241235Sdelphij aflags & 0x20 ? "P" : "", 2178241235Sdelphij aflags & 0x10 ? "E" : ""); 2179241235Sdelphij if (aflags & 0xf) 2180241235Sdelphij printf("+%x", aflags & 0xf); 2181146773Ssam printf("]: "); 2182146773Ssam } 2183146773Ssam /* FIXME check for recursion */ 2184241235Sdelphij if (!bgp_attr_print(atype, tptr, alen)) 2185146773Ssam return 0; 2186146773Ssam tptr += alen; 2187146773Ssam len -= alen; 2188146773Ssam } 2189146773Ssam break; 2190146773Ssam 2191146773Ssam 219256893Sfenner default: 2193127668Sbms TCHECK2(*pptr,len); 2194241235Sdelphij printf("\n\t no Attribute %u decoder",atype); /* we have no decoder for the attribute */ 2195127668Sbms if (vflag <= 1) 2196127668Sbms print_unknown_data(pptr,"\n\t ",len); 2197127668Sbms break; 219856893Sfenner } 2199147899Ssam if (vflag > 1 && len) { /* omit zero length attributes*/ 2200147899Ssam TCHECK2(*pptr,len); 2201127668Sbms print_unknown_data(pptr,"\n\t ",len); 2202147899Ssam } 2203127668Sbms return 1; 2204127668Sbms 2205127668Sbmstrunc: 2206127668Sbms return 0; 220756893Sfenner} 220856893Sfenner 220956893Sfennerstatic void 2210241235Sdelphijbgp_capabilities_print(const u_char *opt, int caps_len) 2211241235Sdelphij{ 2212241235Sdelphij char tokbuf[TOKBUFSIZE]; 2213241235Sdelphij char tokbuf2[TOKBUFSIZE]; 2214241235Sdelphij int cap_type, cap_len, tcap_len, cap_offset; 2215241235Sdelphij int i = 0; 2216241235Sdelphij 2217241235Sdelphij while (i < caps_len) { 2218241235Sdelphij TCHECK2(opt[i], BGP_CAP_HEADER_SIZE); 2219241235Sdelphij cap_type=opt[i]; 2220241235Sdelphij cap_len=opt[i+1]; 2221241235Sdelphij tcap_len=cap_len; 2222241235Sdelphij printf("\n\t %s (%u), length: %u", 2223241235Sdelphij tok2strbuf(bgp_capcode_values, "Unknown", 2224241235Sdelphij cap_type, tokbuf, sizeof(tokbuf)), 2225241235Sdelphij cap_type, 2226241235Sdelphij cap_len); 2227241235Sdelphij TCHECK2(opt[i+2], cap_len); 2228241235Sdelphij switch (cap_type) { 2229241235Sdelphij case BGP_CAPCODE_MP: 2230241235Sdelphij printf("\n\t\tAFI %s (%u), SAFI %s (%u)", 2231241235Sdelphij tok2strbuf(af_values, "Unknown", 2232241235Sdelphij EXTRACT_16BITS(opt+i+2), 2233241235Sdelphij tokbuf, sizeof(tokbuf)), 2234241235Sdelphij EXTRACT_16BITS(opt+i+2), 2235241235Sdelphij tok2strbuf(bgp_safi_values, "Unknown", 2236241235Sdelphij opt[i+5], 2237241235Sdelphij tokbuf, sizeof(tokbuf)), 2238241235Sdelphij opt[i+5]); 2239241235Sdelphij break; 2240241235Sdelphij case BGP_CAPCODE_RESTART: 2241241235Sdelphij printf("\n\t\tRestart Flags: [%s], Restart Time %us", 2242241235Sdelphij ((opt[i+2])&0x80) ? "R" : "none", 2243241235Sdelphij EXTRACT_16BITS(opt+i+2)&0xfff); 2244241235Sdelphij tcap_len-=2; 2245241235Sdelphij cap_offset=4; 2246241235Sdelphij while(tcap_len>=4) { 2247241235Sdelphij printf("\n\t\t AFI %s (%u), SAFI %s (%u), Forwarding state preserved: %s", 2248241235Sdelphij tok2strbuf(af_values,"Unknown", 2249241235Sdelphij EXTRACT_16BITS(opt+i+cap_offset), 2250241235Sdelphij tokbuf, sizeof(tokbuf)), 2251241235Sdelphij EXTRACT_16BITS(opt+i+cap_offset), 2252241235Sdelphij tok2strbuf(bgp_safi_values,"Unknown", 2253241235Sdelphij opt[i+cap_offset+2], 2254241235Sdelphij tokbuf2, sizeof(tokbuf2)), 2255241235Sdelphij opt[i+cap_offset+2], 2256241235Sdelphij ((opt[i+cap_offset+3])&0x80) ? "yes" : "no" ); 2257241235Sdelphij tcap_len-=4; 2258241235Sdelphij cap_offset+=4; 2259241235Sdelphij } 2260241235Sdelphij break; 2261241235Sdelphij case BGP_CAPCODE_RR: 2262241235Sdelphij case BGP_CAPCODE_RR_CISCO: 2263241235Sdelphij break; 2264241235Sdelphij case BGP_CAPCODE_AS_NEW: 2265241235Sdelphij 2266241235Sdelphij /* 2267241235Sdelphij * Extract the 4 byte AS number encoded. 2268241235Sdelphij */ 2269241235Sdelphij if (cap_len == 4) { 2270241235Sdelphij printf("\n\t\t 4 Byte AS %s", 2271241235Sdelphij as_printf(astostr, sizeof(astostr), 2272241235Sdelphij EXTRACT_32BITS(opt + i + 2))); 2273241235Sdelphij } 2274241235Sdelphij break; 2275241235Sdelphij default: 2276241235Sdelphij printf("\n\t\tno decoder for Capability %u", 2277241235Sdelphij cap_type); 2278241235Sdelphij if (vflag <= 1) 2279241235Sdelphij print_unknown_data(&opt[i+2],"\n\t\t",cap_len); 2280241235Sdelphij break; 2281241235Sdelphij } 2282241235Sdelphij if (vflag > 1 && cap_len > 0) { 2283241235Sdelphij print_unknown_data(&opt[i+2],"\n\t\t",cap_len); 2284241235Sdelphij } 2285241235Sdelphij i += BGP_CAP_HEADER_SIZE + cap_len; 2286241235Sdelphij } 2287241235Sdelphij return; 2288241235Sdelphij 2289241235Sdelphijtrunc: 2290241235Sdelphij printf("[|BGP]"); 2291241235Sdelphij} 2292241235Sdelphij 2293241235Sdelphijstatic void 229456893Sfennerbgp_open_print(const u_char *dat, int length) 229556893Sfenner{ 229656893Sfenner struct bgp_open bgpo; 229756893Sfenner struct bgp_opt bgpopt; 229856893Sfenner const u_char *opt; 2299241235Sdelphij int i; 2300146773Ssam char tokbuf[TOKBUFSIZE]; 230156893Sfenner 230298524Sfenner TCHECK2(dat[0], BGP_OPEN_SIZE); 230398524Sfenner memcpy(&bgpo, dat, BGP_OPEN_SIZE); 230456893Sfenner 2305127668Sbms printf("\n\t Version %d, ", bgpo.bgpo_version); 2306214478Srpaulo printf("my AS %s, ", 2307214478Srpaulo as_printf(astostr, sizeof(astostr), ntohs(bgpo.bgpo_myas))); 2308127668Sbms printf("Holdtime %us, ", ntohs(bgpo.bgpo_holdtime)); 2309127668Sbms printf("ID %s", getname((u_char *)&bgpo.bgpo_id)); 2310127668Sbms printf("\n\t Optional parameters, length: %u", bgpo.bgpo_optlen); 231156893Sfenner 2312127668Sbms /* some little sanity checking */ 2313127668Sbms if (length < bgpo.bgpo_optlen+BGP_OPEN_SIZE) 2314127668Sbms return; 2315127668Sbms 231656893Sfenner /* ugly! */ 231798524Sfenner opt = &((const struct bgp_open *)dat)->bgpo_optlen; 231856893Sfenner opt++; 231956893Sfenner 232098524Sfenner i = 0; 232198524Sfenner while (i < bgpo.bgpo_optlen) { 232298524Sfenner TCHECK2(opt[i], BGP_OPT_SIZE); 232398524Sfenner memcpy(&bgpopt, &opt[i], BGP_OPT_SIZE); 232456893Sfenner if (i + 2 + bgpopt.bgpopt_len > bgpo.bgpo_optlen) { 2325241235Sdelphij printf("\n\t Option %d, length: %u", bgpopt.bgpopt_type, bgpopt.bgpopt_len); 232656893Sfenner break; 232756893Sfenner } 232856893Sfenner 2329127668Sbms printf("\n\t Option %s (%u), length: %u", 2330241235Sdelphij tok2strbuf(bgp_opt_values,"Unknown", 2331146773Ssam bgpopt.bgpopt_type, 2332146773Ssam tokbuf, sizeof(tokbuf)), 2333241235Sdelphij bgpopt.bgpopt_type, 2334241235Sdelphij bgpopt.bgpopt_len); 2335127668Sbms 2336241235Sdelphij /* now let's decode the options we know*/ 2337241235Sdelphij switch(bgpopt.bgpopt_type) { 2338214478Srpaulo 2339241235Sdelphij case BGP_OPT_CAP: 2340241235Sdelphij bgp_capabilities_print(&opt[i+BGP_OPT_SIZE], 2341241235Sdelphij bgpopt.bgpopt_len); 2342241235Sdelphij break; 2343127668Sbms 2344241235Sdelphij case BGP_OPT_AUTH: 2345241235Sdelphij default: 2346241235Sdelphij printf("\n\t no decoder for option %u", 2347241235Sdelphij bgpopt.bgpopt_type); 2348241235Sdelphij break; 2349241235Sdelphij } 235098524Sfenner i += BGP_OPT_SIZE + bgpopt.bgpopt_len; 235156893Sfenner } 235275115Sfenner return; 235375115Sfennertrunc: 235475115Sfenner printf("[|BGP]"); 235556893Sfenner} 235656893Sfenner 235756893Sfennerstatic void 235856893Sfennerbgp_update_print(const u_char *dat, int length) 235956893Sfenner{ 236056893Sfenner struct bgp bgp; 236156893Sfenner const u_char *p; 2362241235Sdelphij int withdrawn_routes_len; 236356893Sfenner int len; 236456893Sfenner int i; 2365146773Ssam char tokbuf[TOKBUFSIZE]; 2366241235Sdelphij#ifndef INET6 2367241235Sdelphij char buf[MAXHOSTNAMELEN + 100]; 2368241235Sdelphij int wpfx; 2369241235Sdelphij#endif 237056893Sfenner 237198524Sfenner TCHECK2(dat[0], BGP_SIZE); 2372241235Sdelphij if (length < BGP_SIZE) 2373241235Sdelphij goto trunc; 237498524Sfenner memcpy(&bgp, dat, BGP_SIZE); 237556893Sfenner p = dat + BGP_SIZE; /*XXX*/ 2376241235Sdelphij length -= BGP_SIZE; 237756893Sfenner 237856893Sfenner /* Unfeasible routes */ 2379241235Sdelphij TCHECK2(p[0], 2); 2380241235Sdelphij if (length < 2) 2381241235Sdelphij goto trunc; 2382241235Sdelphij withdrawn_routes_len = EXTRACT_16BITS(p); 2383241235Sdelphij p += 2; 2384241235Sdelphij length -= 2; 2385241235Sdelphij if (withdrawn_routes_len) { 238698524Sfenner /* 238798524Sfenner * Without keeping state from the original NLRI message, 238898524Sfenner * it's not possible to tell if this a v4 or v6 route, 238998524Sfenner * so only try to decode it if we're not v6 enabled. 239075115Sfenner */ 2391241235Sdelphij TCHECK2(p[0], withdrawn_routes_len); 2392241235Sdelphij if (length < withdrawn_routes_len) 2393241235Sdelphij goto trunc; 239475115Sfenner#ifdef INET6 2395241235Sdelphij printf("\n\t Withdrawn routes: %d bytes", withdrawn_routes_len); 2396241235Sdelphij p += withdrawn_routes_len; 2397241235Sdelphij length -= withdrawn_routes_len; 2398127668Sbms#else 2399241235Sdelphij if (withdrawn_routes_len < 2) 2400241235Sdelphij goto trunc; 2401241235Sdelphij length -= 2; 2402241235Sdelphij withdrawn_routes_len -= 2; 240375115Sfenner 240475115Sfenner 2405127668Sbms printf("\n\t Withdrawn routes:"); 2406127668Sbms 2407241235Sdelphij while(withdrawn_routes_len > 0) { 2408241235Sdelphij wpfx = decode_prefix4(p, withdrawn_routes_len, buf, sizeof(buf)); 2409127668Sbms if (wpfx == -1) { 2410127668Sbms printf("\n\t (illegal prefix length)"); 2411111726Sfenner break; 2412127668Sbms } else if (wpfx == -2) 2413127668Sbms goto trunc; 2414241235Sdelphij else if (wpfx == -3) 2415241235Sdelphij goto trunc; /* bytes left, but not enough */ 2416127668Sbms else { 2417127668Sbms printf("\n\t %s", buf); 2418241235Sdelphij p += wpfx; 2419241235Sdelphij length -= wpfx; 2420241235Sdelphij withdrawn_routes_len -= wpfx; 2421127668Sbms } 242275115Sfenner } 242375115Sfenner#endif 242456893Sfenner } 242556893Sfenner 242675115Sfenner TCHECK2(p[0], 2); 2427241235Sdelphij if (length < 2) 2428241235Sdelphij goto trunc; 242975115Sfenner len = EXTRACT_16BITS(p); 2430241235Sdelphij p += 2; 2431241235Sdelphij length -= 2; 2432146773Ssam 2433241235Sdelphij if (withdrawn_routes_len == 0 && len == 0 && length == 0) { 2434241235Sdelphij /* No withdrawn routes, no path attributes, no NLRI */ 2435146773Ssam printf("\n\t End-of-Rib Marker (empty NLRI)"); 2436146773Ssam return; 2437146773Ssam } 2438146773Ssam 243956893Sfenner if (len) { 244056893Sfenner /* do something more useful!*/ 2441241235Sdelphij while (len) { 2442241235Sdelphij int aflags, atype, alenlen, alen; 244356893Sfenner 2444241235Sdelphij TCHECK2(p[0], 2); 2445241235Sdelphij if (len < 2) 2446241235Sdelphij goto trunc; 2447241235Sdelphij if (length < 2) 2448241235Sdelphij goto trunc; 2449241235Sdelphij aflags = *p; 2450241235Sdelphij atype = *(p + 1); 2451241235Sdelphij p += 2; 2452241235Sdelphij len -= 2; 2453241235Sdelphij length -= 2; 2454241235Sdelphij alenlen = bgp_attr_lenlen(aflags, p); 2455241235Sdelphij TCHECK2(p[0], alenlen); 2456241235Sdelphij if (len < alenlen) 2457241235Sdelphij goto trunc; 2458241235Sdelphij if (length < alenlen) 2459241235Sdelphij goto trunc; 2460241235Sdelphij alen = bgp_attr_len(aflags, p); 2461241235Sdelphij p += alenlen; 2462241235Sdelphij len -= alenlen; 2463241235Sdelphij length -= alenlen; 246456893Sfenner 2465241235Sdelphij printf("\n\t %s (%u), length: %u", 2466146773Ssam tok2strbuf(bgp_attr_values, "Unknown Attribute", 2467241235Sdelphij atype, 2468146773Ssam tokbuf, sizeof(tokbuf)), 2469241235Sdelphij atype, 2470127668Sbms alen); 2471127668Sbms 2472241235Sdelphij if (aflags) { 2473127668Sbms printf(", Flags [%s%s%s%s", 2474241235Sdelphij aflags & 0x80 ? "O" : "", 2475241235Sdelphij aflags & 0x40 ? "T" : "", 2476241235Sdelphij aflags & 0x20 ? "P" : "", 2477241235Sdelphij aflags & 0x10 ? "E" : ""); 2478241235Sdelphij if (aflags & 0xf) 2479241235Sdelphij printf("+%x", aflags & 0xf); 2480127668Sbms printf("]: "); 248156893Sfenner } 2482241235Sdelphij if (len < alen) 2483127668Sbms goto trunc; 2484241235Sdelphij if (length < alen) 2485241235Sdelphij goto trunc; 2486241235Sdelphij if (!bgp_attr_print(atype, p, alen)) 2487241235Sdelphij goto trunc; 2488241235Sdelphij p += alen; 2489241235Sdelphij len -= alen; 2490241235Sdelphij length -= alen; 249156893Sfenner } 2492146773Ssam } 249356893Sfenner 2494241235Sdelphij if (length) { 2495241235Sdelphij /* 2496241235Sdelphij * XXX - what if they're using the "Advertisement of 2497241235Sdelphij * Multiple Paths in BGP" feature: 2498241235Sdelphij * 2499241235Sdelphij * https://datatracker.ietf.org/doc/draft-ietf-idr-add-paths/ 2500241235Sdelphij * 2501241235Sdelphij * http://tools.ietf.org/html/draft-ietf-idr-add-paths-06 2502241235Sdelphij */ 2503147899Ssam printf("\n\t Updated routes:"); 2504241235Sdelphij while (length) { 250575115Sfenner char buf[MAXHOSTNAMELEN + 100]; 2506241235Sdelphij i = decode_prefix4(p, length, buf, sizeof(buf)); 2507147173Ssam if (i == -1) { 2508127668Sbms printf("\n\t (illegal prefix length)"); 2509147173Ssam break; 2510147173Ssam } else if (i == -2) 2511127668Sbms goto trunc; 2512241235Sdelphij else if (i == -3) 2513241235Sdelphij goto trunc; /* bytes left, but not enough */ 2514127668Sbms else { 2515127668Sbms printf("\n\t %s", buf); 2516127668Sbms p += i; 2517241235Sdelphij length -= i; 2518127668Sbms } 251956893Sfenner } 252056893Sfenner } 252175115Sfenner return; 252275115Sfennertrunc: 252375115Sfenner printf("[|BGP]"); 252456893Sfenner} 252556893Sfenner 252656893Sfennerstatic void 252756893Sfennerbgp_notification_print(const u_char *dat, int length) 252856893Sfenner{ 252956893Sfenner struct bgp_notification bgpn; 2530127668Sbms const u_char *tptr; 2531146773Ssam char tokbuf[TOKBUFSIZE]; 2532146773Ssam char tokbuf2[TOKBUFSIZE]; 253356893Sfenner 253498524Sfenner TCHECK2(dat[0], BGP_NOTIFICATION_SIZE); 253598524Sfenner memcpy(&bgpn, dat, BGP_NOTIFICATION_SIZE); 253656893Sfenner 2537127668Sbms /* some little sanity checking */ 2538127668Sbms if (length<BGP_NOTIFICATION_SIZE) 2539127668Sbms return; 2540127668Sbms 2541127668Sbms printf(", %s (%u)", 2542146773Ssam tok2strbuf(bgp_notify_major_values, "Unknown Error", 2543146773Ssam bgpn.bgpn_major, tokbuf, sizeof(tokbuf)), 2544127668Sbms bgpn.bgpn_major); 2545127668Sbms 2546127668Sbms switch (bgpn.bgpn_major) { 2547127668Sbms 2548127668Sbms case BGP_NOTIFY_MAJOR_MSG: 2549127668Sbms printf(", subcode %s (%u)", 2550146773Ssam tok2strbuf(bgp_notify_minor_msg_values, "Unknown", 2551146773Ssam bgpn.bgpn_minor, tokbuf, sizeof(tokbuf)), 2552127668Sbms bgpn.bgpn_minor); 2553127668Sbms break; 2554127668Sbms case BGP_NOTIFY_MAJOR_OPEN: 2555127668Sbms printf(", subcode %s (%u)", 2556146773Ssam tok2strbuf(bgp_notify_minor_open_values, "Unknown", 2557146773Ssam bgpn.bgpn_minor, tokbuf, sizeof(tokbuf)), 2558127668Sbms bgpn.bgpn_minor); 2559127668Sbms break; 2560127668Sbms case BGP_NOTIFY_MAJOR_UPDATE: 2561127668Sbms printf(", subcode %s (%u)", 2562146773Ssam tok2strbuf(bgp_notify_minor_update_values, "Unknown", 2563146773Ssam bgpn.bgpn_minor, tokbuf, sizeof(tokbuf)), 2564127668Sbms bgpn.bgpn_minor); 2565127668Sbms break; 2566127668Sbms case BGP_NOTIFY_MAJOR_CAP: 2567127668Sbms printf(" subcode %s (%u)", 2568146773Ssam tok2strbuf(bgp_notify_minor_cap_values, "Unknown", 2569146773Ssam bgpn.bgpn_minor, tokbuf, sizeof(tokbuf)), 2570127668Sbms bgpn.bgpn_minor); 2571127668Sbms case BGP_NOTIFY_MAJOR_CEASE: 2572127668Sbms printf(", subcode %s (%u)", 2573146773Ssam tok2strbuf(bgp_notify_minor_cease_values, "Unknown", 2574146773Ssam bgpn.bgpn_minor, tokbuf, sizeof(tokbuf)), 2575127668Sbms bgpn.bgpn_minor); 2576127668Sbms 2577127668Sbms /* draft-ietf-idr-cease-subcode-02 mentions optionally 7 bytes 2578127668Sbms * for the maxprefix subtype, which may contain AFI, SAFI and MAXPREFIXES 2579127668Sbms */ 2580127668Sbms if(bgpn.bgpn_minor == BGP_NOTIFY_MINOR_CEASE_MAXPRFX && length >= BGP_NOTIFICATION_SIZE + 7) { 2581127668Sbms tptr = dat + BGP_NOTIFICATION_SIZE; 2582127668Sbms TCHECK2(*tptr, 7); 2583127668Sbms printf(", AFI %s (%u), SAFI %s (%u), Max Prefixes: %u", 2584172683Smlaier tok2strbuf(af_values, "Unknown", 2585146773Ssam EXTRACT_16BITS(tptr), tokbuf, sizeof(tokbuf)), 2586127668Sbms EXTRACT_16BITS(tptr), 2587146773Ssam tok2strbuf(bgp_safi_values, "Unknown", *(tptr+2), 2588146773Ssam tokbuf2, sizeof(tokbuf)), 2589127668Sbms *(tptr+2), 2590127668Sbms EXTRACT_32BITS(tptr+3)); 2591127668Sbms } 2592127668Sbms break; 2593127668Sbms default: 2594127668Sbms break; 2595127668Sbms } 2596127668Sbms 259775115Sfenner return; 259875115Sfennertrunc: 259975115Sfenner printf("[|BGP]"); 260056893Sfenner} 260156893Sfenner 260256893Sfennerstatic void 2603127668Sbmsbgp_route_refresh_print(const u_char *pptr, int len) { 2604127668Sbms 2605127668Sbms const struct bgp_route_refresh *bgp_route_refresh_header; 2606146773Ssam char tokbuf[TOKBUFSIZE]; 2607146773Ssam char tokbuf2[TOKBUFSIZE]; 2608146773Ssam 2609147899Ssam TCHECK2(pptr[0], BGP_ROUTE_REFRESH_SIZE); 2610147899Ssam 2611147899Ssam /* some little sanity checking */ 2612147899Ssam if (len<BGP_ROUTE_REFRESH_SIZE) 2613147899Ssam return; 2614147899Ssam 2615127668Sbms bgp_route_refresh_header = (const struct bgp_route_refresh *)pptr; 2616127668Sbms 2617127668Sbms printf("\n\t AFI %s (%u), SAFI %s (%u)", 2618172683Smlaier tok2strbuf(af_values,"Unknown", 2619146773Ssam /* this stinks but the compiler pads the structure 2620146773Ssam * weird */ 2621146773Ssam EXTRACT_16BITS(&bgp_route_refresh_header->afi), 2622146773Ssam tokbuf, sizeof(tokbuf)), 2623127668Sbms EXTRACT_16BITS(&bgp_route_refresh_header->afi), 2624146773Ssam tok2strbuf(bgp_safi_values,"Unknown", 2625146773Ssam bgp_route_refresh_header->safi, 2626146773Ssam tokbuf2, sizeof(tokbuf2)), 2627127668Sbms bgp_route_refresh_header->safi); 2628127668Sbms 2629147899Ssam if (vflag > 1) { 2630147899Ssam TCHECK2(*pptr, len); 2631127668Sbms print_unknown_data(pptr,"\n\t ", len); 2632147899Ssam } 2633127668Sbms 2634127668Sbms return; 2635147899Ssamtrunc: 2636147899Ssam printf("[|BGP]"); 2637127668Sbms} 2638127668Sbms 2639127668Sbmsstatic int 264056893Sfennerbgp_header_print(const u_char *dat, int length) 264156893Sfenner{ 264256893Sfenner struct bgp bgp; 2643146773Ssam char tokbuf[TOKBUFSIZE]; 264456893Sfenner 264598524Sfenner TCHECK2(dat[0], BGP_SIZE); 264698524Sfenner memcpy(&bgp, dat, BGP_SIZE); 2647127668Sbms printf("\n\t%s Message (%u), length: %u", 2648146773Ssam tok2strbuf(bgp_msg_values, "Unknown", bgp.bgp_type, 2649146773Ssam tokbuf, sizeof(tokbuf)), 2650127668Sbms bgp.bgp_type, 2651127668Sbms length); 265256893Sfenner 265356893Sfenner switch (bgp.bgp_type) { 265456893Sfenner case BGP_OPEN: 265556893Sfenner bgp_open_print(dat, length); 265656893Sfenner break; 265756893Sfenner case BGP_UPDATE: 265856893Sfenner bgp_update_print(dat, length); 265956893Sfenner break; 266056893Sfenner case BGP_NOTIFICATION: 266156893Sfenner bgp_notification_print(dat, length); 266256893Sfenner break; 2663127668Sbms case BGP_KEEPALIVE: 2664127668Sbms break; 2665127668Sbms case BGP_ROUTE_REFRESH: 2666127668Sbms bgp_route_refresh_print(dat, length); 2667127668Sbms break; 2668127668Sbms default: 2669147899Ssam /* we have no decoder for the BGP message */ 2670147899Ssam TCHECK2(*dat, length); 2671147899Ssam printf("\n\t no Message %u decoder",bgp.bgp_type); 2672147899Ssam print_unknown_data(dat,"\n\t ",length); 2673127668Sbms break; 267456893Sfenner } 2675127668Sbms return 1; 267675115Sfennertrunc: 267775115Sfenner printf("[|BGP]"); 2678127668Sbms return 0; 267956893Sfenner} 268056893Sfenner 268156893Sfennervoid 268256893Sfennerbgp_print(const u_char *dat, int length) 268356893Sfenner{ 268456893Sfenner const u_char *p; 268556893Sfenner const u_char *ep; 268656893Sfenner const u_char *start; 268756893Sfenner const u_char marker[] = { 2688127668Sbms 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 2689127668Sbms 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 269056893Sfenner }; 269156893Sfenner struct bgp bgp; 269256893Sfenner u_int16_t hlen; 2693146773Ssam char tokbuf[TOKBUFSIZE]; 269456893Sfenner 269556893Sfenner ep = dat + length; 269656893Sfenner if (snapend < dat + length) 269756893Sfenner ep = snapend; 269856893Sfenner 2699127668Sbms printf(": BGP, length: %u",length); 270056893Sfenner 2701127668Sbms if (vflag < 1) /* lets be less chatty */ 2702127668Sbms return; 2703127668Sbms 270456893Sfenner p = dat; 270556893Sfenner start = p; 2706147899Ssam while (p < ep) { 270756893Sfenner if (!TTEST2(p[0], 1)) 270856893Sfenner break; 270956893Sfenner if (p[0] != 0xff) { 271056893Sfenner p++; 271156893Sfenner continue; 271256893Sfenner } 271356893Sfenner 271456893Sfenner if (!TTEST2(p[0], sizeof(marker))) 271556893Sfenner break; 271656893Sfenner if (memcmp(p, marker, sizeof(marker)) != 0) { 271756893Sfenner p++; 271856893Sfenner continue; 271956893Sfenner } 272056893Sfenner 272156893Sfenner /* found BGP header */ 272298524Sfenner TCHECK2(p[0], BGP_SIZE); /*XXX*/ 272398524Sfenner memcpy(&bgp, p, BGP_SIZE); 272456893Sfenner 272556893Sfenner if (start != p) 272656893Sfenner printf(" [|BGP]"); 272756893Sfenner 272856893Sfenner hlen = ntohs(bgp.bgp_len); 2729127668Sbms if (hlen < BGP_SIZE) { 2730127668Sbms printf("\n[|BGP Bogus header length %u < %u]", hlen, 2731127668Sbms BGP_SIZE); 2732127668Sbms break; 2733127668Sbms } 2734127668Sbms 273556893Sfenner if (TTEST2(p[0], hlen)) { 2736127668Sbms if (!bgp_header_print(p, hlen)) 2737127668Sbms return; 273856893Sfenner p += hlen; 273956893Sfenner start = p; 274056893Sfenner } else { 2741146773Ssam printf("\n[|BGP %s]", 2742146773Ssam tok2strbuf(bgp_msg_values, 2743146773Ssam "Unknown Message Type", 2744146773Ssam bgp.bgp_type, 2745146773Ssam tokbuf, sizeof(tokbuf))); 274656893Sfenner break; 274756893Sfenner } 274856893Sfenner } 274956893Sfenner 275056893Sfenner return; 275156893Sfenner 275256893Sfennertrunc: 275356893Sfenner printf(" [|BGP]"); 275456893Sfenner} 2755190207Srpaulo 2756190207Srpaulo/* 2757190207Srpaulo * Local Variables: 2758190207Srpaulo * c-style: whitesmith 2759190207Srpaulo * c-basic-offset: 4 2760190207Srpaulo * End: 2761190207Srpaulo */ 2762