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