"Fossies" - the Fresh Open Source Software Archive

Member "tcpdump-4.99.1/./print-bgp.c" (7 Jun 2021, 109155 Bytes) of package /linux/misc/tcpdump-4.99.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "print-bgp.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 4.99.0_vs_4.99.1.

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