back to topotato report
topotato coverage report
Current view: top level - bgpd - bgp_open.c (source / functions) Hit Total Coverage
Test: aggregated run ( view descriptions ) Lines: 401 928 43.2 %
Date: 2023-02-24 14:41:08 Functions: 15 22 68.2 %

          Line data    Source code
       1             : /* BGP open message handling
       2             :  * Copyright (C) 1998, 1999 Kunihiro Ishiguro
       3             :  *
       4             :  * This file is part of GNU Zebra.
       5             :  *
       6             :  * GNU Zebra is free software; you can redistribute it and/or modify it
       7             :  * under the terms of the GNU General Public License as published by the
       8             :  * Free Software Foundation; either version 2, or (at your option) any
       9             :  * later version.
      10             :  *
      11             :  * GNU Zebra is distributed in the hope that it will be useful, but
      12             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License along
      17             :  * with this program; see the file COPYING; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : #include <zebra.h>
      22             : 
      23             : #include "linklist.h"
      24             : #include "prefix.h"
      25             : #include "stream.h"
      26             : #include "thread.h"
      27             : #include "log.h"
      28             : #include "command.h"
      29             : #include "memory.h"
      30             : #include "queue.h"
      31             : #include "filter.h"
      32             : 
      33             : #include "lib/json.h"
      34             : #include "bgpd/bgpd.h"
      35             : #include "bgpd/bgp_attr.h"
      36             : #include "bgpd/bgp_debug.h"
      37             : #include "bgpd/bgp_errors.h"
      38             : #include "bgpd/bgp_fsm.h"
      39             : #include "bgpd/bgp_packet.h"
      40             : #include "bgpd/bgp_open.h"
      41             : #include "bgpd/bgp_aspath.h"
      42             : #include "bgpd/bgp_vty.h"
      43             : #include "bgpd/bgp_memory.h"
      44             : 
      45             : static const struct message capcode_str[] = {
      46             :         {CAPABILITY_CODE_MP, "MultiProtocol Extensions"},
      47             :         {CAPABILITY_CODE_REFRESH, "Route Refresh"},
      48             :         {CAPABILITY_CODE_ORF, "Cooperative Route Filtering"},
      49             :         {CAPABILITY_CODE_RESTART, "Graceful Restart"},
      50             :         {CAPABILITY_CODE_AS4, "4-octet AS number"},
      51             :         {CAPABILITY_CODE_ADDPATH, "AddPath"},
      52             :         {CAPABILITY_CODE_DYNAMIC, "Dynamic"},
      53             :         {CAPABILITY_CODE_ENHE, "Extended Next Hop Encoding"},
      54             :         {CAPABILITY_CODE_DYNAMIC_OLD, "Dynamic (Old)"},
      55             :         {CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)"},
      56             :         {CAPABILITY_CODE_ORF_OLD, "ORF (Old)"},
      57             :         {CAPABILITY_CODE_FQDN, "FQDN"},
      58             :         {CAPABILITY_CODE_ENHANCED_RR, "Enhanced Route Refresh"},
      59             :         {CAPABILITY_CODE_EXT_MESSAGE, "BGP Extended Message"},
      60             :         {CAPABILITY_CODE_LLGR, "Long-lived BGP Graceful Restart"},
      61             :         {CAPABILITY_CODE_ROLE, "Role"},
      62             :         {0}};
      63             : 
      64             : /* Minimum sizes for length field of each cap (so not inc. the header) */
      65             : static const size_t cap_minsizes[] = {
      66             :                 [CAPABILITY_CODE_MP] = CAPABILITY_CODE_MP_LEN,
      67             :                 [CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN,
      68             :                 [CAPABILITY_CODE_ORF] = CAPABILITY_CODE_ORF_LEN,
      69             :                 [CAPABILITY_CODE_RESTART] = CAPABILITY_CODE_RESTART_LEN,
      70             :                 [CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN,
      71             :                 [CAPABILITY_CODE_ADDPATH] = CAPABILITY_CODE_ADDPATH_LEN,
      72             :                 [CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN,
      73             :                 [CAPABILITY_CODE_DYNAMIC_OLD] = CAPABILITY_CODE_DYNAMIC_LEN,
      74             :                 [CAPABILITY_CODE_ENHE] = CAPABILITY_CODE_ENHE_LEN,
      75             :                 [CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN,
      76             :                 [CAPABILITY_CODE_ORF_OLD] = CAPABILITY_CODE_ORF_LEN,
      77             :                 [CAPABILITY_CODE_FQDN] = CAPABILITY_CODE_MIN_FQDN_LEN,
      78             :                 [CAPABILITY_CODE_ENHANCED_RR] = CAPABILITY_CODE_ENHANCED_LEN,
      79             :                 [CAPABILITY_CODE_EXT_MESSAGE] = CAPABILITY_CODE_EXT_MESSAGE_LEN,
      80             :                 [CAPABILITY_CODE_LLGR] = CAPABILITY_CODE_LLGR_LEN,
      81             :                 [CAPABILITY_CODE_ROLE] = CAPABILITY_CODE_ROLE_LEN,
      82             : };
      83             : 
      84             : /* value the capability must be a multiple of.
      85             :  * 0-data capabilities won't be checked against this.
      86             :  * Other capabilities whose data doesn't fall on convenient boundaries for this
      87             :  * table should be set to 1.
      88             :  */
      89             : static const size_t cap_modsizes[] = {
      90             :                 [CAPABILITY_CODE_MP] = 4,
      91             :                 [CAPABILITY_CODE_REFRESH] = 1,
      92             :                 [CAPABILITY_CODE_ORF] = 1,
      93             :                 [CAPABILITY_CODE_RESTART] = 1,
      94             :                 [CAPABILITY_CODE_AS4] = 4,
      95             :                 [CAPABILITY_CODE_ADDPATH] = 4,
      96             :                 [CAPABILITY_CODE_DYNAMIC] = 1,
      97             :                 [CAPABILITY_CODE_DYNAMIC_OLD] = 1,
      98             :                 [CAPABILITY_CODE_ENHE] = 6,
      99             :                 [CAPABILITY_CODE_REFRESH_OLD] = 1,
     100             :                 [CAPABILITY_CODE_ORF_OLD] = 1,
     101             :                 [CAPABILITY_CODE_FQDN] = 1,
     102             :                 [CAPABILITY_CODE_ENHANCED_RR] = 1,
     103             :                 [CAPABILITY_CODE_EXT_MESSAGE] = 1,
     104             :                 [CAPABILITY_CODE_LLGR] = 1,
     105             :                 [CAPABILITY_CODE_ROLE] = 1,
     106             : };
     107             : 
     108             : /* BGP-4 Multiprotocol Extentions lead us to the complex world. We can
     109             :    negotiate remote peer supports extentions or not. But if
     110             :    remote-peer doesn't supports negotiation process itself.  We would
     111             :    like to do manual configuration.
     112             : 
     113             :    So there is many configurable point.  First of all we want set each
     114             :    peer whether we send capability negotiation to the peer or not.
     115             :    Next, if we send capability to the peer we want to set my capability
     116             :    inforation at each peer. */
     117             : 
     118           0 : void bgp_capability_vty_out(struct vty *vty, struct peer *peer, bool use_json,
     119             :                             json_object *json_neigh)
     120             : {
     121           0 :         char *pnt;
     122           0 :         char *end;
     123           0 :         struct capability_mp_data mpc;
     124           0 :         struct capability_header *hdr;
     125           0 :         json_object *json_cap = NULL;
     126             : 
     127           0 :         if (use_json)
     128           0 :                 json_cap = json_object_new_object();
     129             : 
     130           0 :         pnt = peer->notify.data;
     131           0 :         end = pnt + peer->notify.length;
     132             : 
     133           0 :         while (pnt < end) {
     134           0 :                 if (pnt + sizeof(struct capability_mp_data) + 2 > end)
     135             :                         return;
     136             : 
     137           0 :                 hdr = (struct capability_header *)pnt;
     138           0 :                 if (pnt + hdr->length + 2 > end)
     139             :                         return;
     140             : 
     141           0 :                 memcpy(&mpc, pnt + 2, sizeof(struct capability_mp_data));
     142             : 
     143           0 :                 if (hdr->code == CAPABILITY_CODE_MP) {
     144           0 :                         afi_t afi;
     145           0 :                         safi_t safi;
     146             : 
     147           0 :                         (void)bgp_map_afi_safi_iana2int(ntohs(mpc.afi),
     148             :                                                         mpc.safi, &afi, &safi);
     149             : 
     150           0 :                         if (use_json) {
     151           0 :                                 switch (afi) {
     152           0 :                                 case AFI_IP:
     153           0 :                                         json_object_string_add(
     154             :                                                 json_cap,
     155             :                                                 "capabilityErrorMultiProtocolAfi",
     156             :                                                 "IPv4");
     157           0 :                                         break;
     158           0 :                                 case AFI_IP6:
     159           0 :                                         json_object_string_add(
     160             :                                                 json_cap,
     161             :                                                 "capabilityErrorMultiProtocolAfi",
     162             :                                                 "IPv6");
     163           0 :                                         break;
     164           0 :                                 case AFI_L2VPN:
     165           0 :                                         json_object_string_add(
     166             :                                                 json_cap,
     167             :                                                 "capabilityErrorMultiProtocolAfi",
     168             :                                                 "L2VPN");
     169           0 :                                         break;
     170           0 :                                 case AFI_UNSPEC:
     171             :                                 case AFI_MAX:
     172           0 :                                         json_object_int_add(
     173             :                                                 json_cap,
     174             :                                                 "capabilityErrorMultiProtocolAfiUnknown",
     175           0 :                                                 ntohs(mpc.afi));
     176           0 :                                         break;
     177             :                                 }
     178           0 :                                 switch (safi) {
     179           0 :                                 case SAFI_UNICAST:
     180           0 :                                         json_object_string_add(
     181             :                                                 json_cap,
     182             :                                                 "capabilityErrorMultiProtocolSafi",
     183             :                                                 "unicast");
     184           0 :                                         break;
     185           0 :                                 case SAFI_MULTICAST:
     186           0 :                                         json_object_string_add(
     187             :                                                 json_cap,
     188             :                                                 "capabilityErrorMultiProtocolSafi",
     189             :                                                 "multicast");
     190           0 :                                         break;
     191           0 :                                 case SAFI_LABELED_UNICAST:
     192           0 :                                         json_object_string_add(
     193             :                                                 json_cap,
     194             :                                                 "capabilityErrorMultiProtocolSafi",
     195             :                                                 "labeled-unicast");
     196           0 :                                         break;
     197           0 :                                 case SAFI_MPLS_VPN:
     198           0 :                                         json_object_string_add(
     199             :                                                 json_cap,
     200             :                                                 "capabilityErrorMultiProtocolSafi",
     201             :                                                 "MPLS-labeled VPN");
     202           0 :                                         break;
     203           0 :                                 case SAFI_ENCAP:
     204           0 :                                         json_object_string_add(
     205             :                                                 json_cap,
     206             :                                                 "capabilityErrorMultiProtocolSafi",
     207             :                                                 "encap");
     208           0 :                                         break;
     209           0 :                                 case SAFI_EVPN:
     210           0 :                                         json_object_string_add(
     211             :                                                 json_cap,
     212             :                                                 "capabilityErrorMultiProtocolSafi",
     213             :                                                 "EVPN");
     214           0 :                                         break;
     215           0 :                                 case SAFI_FLOWSPEC:
     216           0 :                                         json_object_string_add(
     217             :                                                 json_cap,
     218             :                                                 "capabilityErrorMultiProtocolSafi",
     219             :                                                 "flowspec");
     220           0 :                                         break;
     221           0 :                                 case SAFI_UNSPEC:
     222             :                                 case SAFI_MAX:
     223           0 :                                         json_object_int_add(
     224             :                                                 json_cap,
     225             :                                                 "capabilityErrorMultiProtocolSafiUnknown",
     226             :                                                 mpc.safi);
     227           0 :                                         break;
     228             :                                 }
     229             :                         } else {
     230           0 :                                 vty_out(vty,
     231             :                                         "  Capability error for: Multi protocol ");
     232           0 :                                 switch (afi) {
     233           0 :                                 case AFI_IP:
     234           0 :                                         vty_out(vty, "AFI IPv4, ");
     235           0 :                                         break;
     236           0 :                                 case AFI_IP6:
     237           0 :                                         vty_out(vty, "AFI IPv6, ");
     238           0 :                                         break;
     239           0 :                                 case AFI_L2VPN:
     240           0 :                                         vty_out(vty, "AFI L2VPN, ");
     241           0 :                                         break;
     242           0 :                                 case AFI_UNSPEC:
     243             :                                 case AFI_MAX:
     244           0 :                                         vty_out(vty, "AFI Unknown %d, ",
     245           0 :                                                 ntohs(mpc.afi));
     246           0 :                                         break;
     247             :                                 }
     248           0 :                                 switch (safi) {
     249           0 :                                 case SAFI_UNICAST:
     250           0 :                                         vty_out(vty, "SAFI Unicast");
     251           0 :                                         break;
     252           0 :                                 case SAFI_MULTICAST:
     253           0 :                                         vty_out(vty, "SAFI Multicast");
     254           0 :                                         break;
     255           0 :                                 case SAFI_LABELED_UNICAST:
     256           0 :                                         vty_out(vty, "SAFI Labeled-unicast");
     257           0 :                                         break;
     258           0 :                                 case SAFI_MPLS_VPN:
     259           0 :                                         vty_out(vty, "SAFI MPLS-labeled VPN");
     260           0 :                                         break;
     261           0 :                                 case SAFI_ENCAP:
     262           0 :                                         vty_out(vty, "SAFI ENCAP");
     263           0 :                                         break;
     264           0 :                                 case SAFI_FLOWSPEC:
     265           0 :                                         vty_out(vty, "SAFI FLOWSPEC");
     266           0 :                                         break;
     267           0 :                                 case SAFI_EVPN:
     268           0 :                                         vty_out(vty, "SAFI EVPN");
     269           0 :                                         break;
     270           0 :                                 case SAFI_UNSPEC:
     271             :                                 case SAFI_MAX:
     272           0 :                                         vty_out(vty, "SAFI Unknown %d ",
     273             :                                                 mpc.safi);
     274           0 :                                         break;
     275             :                                 }
     276           0 :                                 vty_out(vty, "\n");
     277             :                         }
     278           0 :                 } else if (hdr->code >= 128) {
     279           0 :                         if (use_json)
     280           0 :                                 json_object_int_add(
     281             :                                         json_cap,
     282             :                                         "capabilityErrorVendorSpecificCapabilityCode",
     283             :                                         hdr->code);
     284             :                         else
     285           0 :                                 vty_out(vty,
     286             :                                         "  Capability error: vendor specific capability code %d",
     287             :                                         hdr->code);
     288             :                 } else {
     289           0 :                         if (use_json)
     290           0 :                                 json_object_int_add(
     291             :                                         json_cap,
     292             :                                         "capabilityErrorUnknownCapabilityCode",
     293             :                                         hdr->code);
     294             :                         else
     295           0 :                                 vty_out(vty,
     296             :                                         "  Capability error: unknown capability code %d",
     297             :                                         hdr->code);
     298             :                 }
     299           0 :                 pnt += hdr->length + 2;
     300             :         }
     301           0 :         if (use_json)
     302           0 :                 json_object_object_add(json_neigh, "capabilityErrors",
     303             :                                        json_cap);
     304             : }
     305             : 
     306          66 : static void bgp_capability_mp_data(struct stream *s,
     307             :                                    struct capability_mp_data *mpc)
     308             : {
     309          66 :         mpc->afi = stream_getw(s);
     310          66 :         mpc->reserved = stream_getc(s);
     311          66 :         mpc->safi = stream_getc(s);
     312          66 : }
     313             : 
     314             : /* Set negotiated capability value. */
     315          66 : static int bgp_capability_mp(struct peer *peer, struct capability_header *hdr)
     316             : {
     317          66 :         struct capability_mp_data mpc;
     318          66 :         struct stream *s = BGP_INPUT(peer);
     319          66 :         afi_t afi;
     320          66 :         safi_t safi;
     321             : 
     322             :         /* Verify length is 4 */
     323          66 :         if (hdr->length != 4) {
     324           0 :                 flog_warn(
     325             :                         EC_BGP_CAPABILITY_INVALID_LENGTH,
     326             :                         "MP Cap: Received invalid length %d, non-multiple of 4",
     327             :                         hdr->length);
     328           0 :                 return -1;
     329             :         }
     330             : 
     331          66 :         bgp_capability_mp_data(s, &mpc);
     332             : 
     333          66 :         if (bgp_debug_neighbor_events(peer))
     334           0 :                 zlog_debug("%s OPEN has %s capability for afi/safi: %s/%s",
     335             :                            peer->host, lookup_msg(capcode_str, hdr->code, NULL),
     336             :                            iana_afi2str(mpc.afi), iana_safi2str(mpc.safi));
     337             : 
     338             :         /* Convert AFI, SAFI to internal values, check. */
     339          66 :         if (bgp_map_afi_safi_iana2int(mpc.afi, mpc.safi, &afi, &safi))
     340             :                 return -1;
     341             : 
     342             :         /* Now safi remapped, and afi/safi are valid array indices */
     343          54 :         peer->afc_recv[afi][safi] = 1;
     344             : 
     345          54 :         if (peer->afc[afi][safi])
     346          34 :                 peer->afc_nego[afi][safi] = 1;
     347             :         else
     348             :                 return -1;
     349             : 
     350          34 :         return 0;
     351             : }
     352             : 
     353           0 : static void bgp_capability_orf_not_support(struct peer *peer, iana_afi_t afi,
     354             :                                            iana_safi_t safi, uint8_t type,
     355             :                                            uint8_t mode)
     356             : {
     357           0 :         if (bgp_debug_neighbor_events(peer))
     358           0 :                 zlog_debug(
     359             :                         "%s Addr-family %d/%d has ORF type/mode %d/%d not supported",
     360             :                         peer->host, afi, safi, type, mode);
     361           0 : }
     362             : 
     363             : static const struct message orf_type_str[] = {
     364             :         {ORF_TYPE_RESERVED, "Reserved"},
     365             :         {ORF_TYPE_PREFIX, "Prefixlist"},
     366             :         {ORF_TYPE_PREFIX_OLD, "Prefixlist (old)"},
     367             :         {0}};
     368             : 
     369             : static const struct message orf_mode_str[] = {{ORF_MODE_RECEIVE, "Receive"},
     370             :                                               {ORF_MODE_SEND, "Send"},
     371             :                                               {ORF_MODE_BOTH, "Both"},
     372             :                                               {0}};
     373             : 
     374           0 : static int bgp_capability_orf_entry(struct peer *peer,
     375             :                                     struct capability_header *hdr)
     376             : {
     377           0 :         struct stream *s = BGP_INPUT(peer);
     378           0 :         struct capability_mp_data mpc;
     379           0 :         uint8_t num;
     380           0 :         iana_afi_t pkt_afi;
     381           0 :         afi_t afi;
     382           0 :         iana_safi_t pkt_safi;
     383           0 :         safi_t safi;
     384           0 :         uint8_t type;
     385           0 :         uint8_t mode;
     386           0 :         uint16_t sm_cap = 0; /* capability send-mode receive */
     387           0 :         uint16_t rm_cap = 0; /* capability receive-mode receive */
     388           0 :         int i;
     389             : 
     390             :         /* ORF Entry header */
     391           0 :         bgp_capability_mp_data(s, &mpc);
     392           0 :         num = stream_getc(s);
     393           0 :         pkt_afi = mpc.afi;
     394           0 :         pkt_safi = mpc.safi;
     395             : 
     396           0 :         if (bgp_debug_neighbor_events(peer))
     397           0 :                 zlog_debug("%s ORF Cap entry for afi/safi: %s/%s", peer->host,
     398             :                            iana_afi2str(mpc.afi), iana_safi2str(mpc.safi));
     399             : 
     400             :         /* Convert AFI, SAFI to internal values, check. */
     401           0 :         if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
     402           0 :                 zlog_info(
     403             :                         "%s Addr-family %d/%d not supported. Ignoring the ORF capability",
     404             :                         peer->host, pkt_afi, pkt_safi);
     405           0 :                 return 0;
     406             :         }
     407             : 
     408           0 :         mpc.afi = pkt_afi;
     409           0 :         mpc.safi = safi;
     410             : 
     411             :         /* validate number field */
     412           0 :         if (CAPABILITY_CODE_ORF_LEN + (num * 2) > hdr->length) {
     413           0 :                 zlog_info(
     414             :                         "%s ORF Capability entry length error, Cap length %u, num %u",
     415             :                         peer->host, hdr->length, num);
     416           0 :                 bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
     417             :                                 BGP_NOTIFY_OPEN_MALFORMED_ATTR);
     418           0 :                 return -1;
     419             :         }
     420             : 
     421           0 :         for (i = 0; i < num; i++) {
     422           0 :                 type = stream_getc(s);
     423           0 :                 mode = stream_getc(s);
     424             : 
     425             :                 /* ORF Mode error check */
     426           0 :                 switch (mode) {
     427             :                 case ORF_MODE_BOTH:
     428             :                 case ORF_MODE_SEND:
     429             :                 case ORF_MODE_RECEIVE:
     430           0 :                         break;
     431           0 :                 default:
     432           0 :                         bgp_capability_orf_not_support(peer, pkt_afi, pkt_safi,
     433             :                                                        type, mode);
     434           0 :                         continue;
     435             :                 }
     436             :                 /* ORF Type and afi/safi error checks */
     437             :                 /* capcode versus type */
     438           0 :                 switch (hdr->code) {
     439           0 :                 case CAPABILITY_CODE_ORF:
     440           0 :                         switch (type) {
     441           0 :                         case ORF_TYPE_RESERVED:
     442           0 :                                 if (bgp_debug_neighbor_events(peer))
     443           0 :                                         zlog_debug(
     444             :                                                 "%s Addr-family %d/%d has reserved ORF type, ignoring",
     445             :                                                 peer->host, afi, safi);
     446             :                                 break;
     447             :                         case ORF_TYPE_PREFIX:
     448             :                                 break;
     449           0 :                         default:
     450           0 :                                 bgp_capability_orf_not_support(
     451             :                                         peer, pkt_afi, pkt_safi, type, mode);
     452           0 :                                 continue;
     453             :                         }
     454             :                         break;
     455           0 :                 case CAPABILITY_CODE_ORF_OLD:
     456           0 :                         switch (type) {
     457           0 :                         case ORF_TYPE_RESERVED:
     458           0 :                                 if (bgp_debug_neighbor_events(peer))
     459           0 :                                         zlog_debug(
     460             :                                                 "%s Addr-family %d/%d has reserved ORF type, ignoring",
     461             :                                                 peer->host, afi, safi);
     462             :                                 break;
     463             :                         case ORF_TYPE_PREFIX_OLD:
     464             :                                 break;
     465           0 :                         default:
     466           0 :                                 bgp_capability_orf_not_support(
     467             :                                         peer, pkt_afi, pkt_safi, type, mode);
     468           0 :                                 continue;
     469             :                         }
     470             :                         break;
     471           0 :                 default:
     472           0 :                         bgp_capability_orf_not_support(peer, pkt_afi, pkt_safi,
     473             :                                                        type, mode);
     474           0 :                         continue;
     475             :                 }
     476             : 
     477             :                 /* AFI vs SAFI */
     478           0 :                 if (!((afi == AFI_IP && safi == SAFI_UNICAST)
     479           0 :                       || (afi == AFI_IP && safi == SAFI_MULTICAST)
     480           0 :                       || (afi == AFI_IP6 && safi == SAFI_UNICAST))) {
     481           0 :                         bgp_capability_orf_not_support(peer, pkt_afi, pkt_safi,
     482             :                                                        type, mode);
     483           0 :                         continue;
     484             :                 }
     485             : 
     486           0 :                 if (bgp_debug_neighbor_events(peer))
     487           0 :                         zlog_debug(
     488             :                                 "%s OPEN has %s ORF capability as %s for afi/safi: %s/%s",
     489             :                                 peer->host,
     490             :                                 lookup_msg(orf_type_str, type, NULL),
     491             :                                 lookup_msg(orf_mode_str, mode, NULL),
     492             :                                 iana_afi2str(pkt_afi), iana_safi2str(pkt_safi));
     493             : 
     494           0 :                 if (hdr->code == CAPABILITY_CODE_ORF) {
     495             :                         sm_cap = PEER_CAP_ORF_PREFIX_SM_RCV;
     496             :                         rm_cap = PEER_CAP_ORF_PREFIX_RM_RCV;
     497           0 :                 } else if (hdr->code == CAPABILITY_CODE_ORF_OLD) {
     498             :                         sm_cap = PEER_CAP_ORF_PREFIX_SM_OLD_RCV;
     499             :                         rm_cap = PEER_CAP_ORF_PREFIX_RM_OLD_RCV;
     500             :                 } else {
     501           0 :                         bgp_capability_orf_not_support(peer, pkt_afi, pkt_safi,
     502             :                                                        type, mode);
     503           0 :                         continue;
     504             :                 }
     505             : 
     506           0 :                 switch (mode) {
     507           0 :                 case ORF_MODE_BOTH:
     508           0 :                         SET_FLAG(peer->af_cap[afi][safi], sm_cap);
     509           0 :                         SET_FLAG(peer->af_cap[afi][safi], rm_cap);
     510           0 :                         break;
     511           0 :                 case ORF_MODE_SEND:
     512           0 :                         SET_FLAG(peer->af_cap[afi][safi], sm_cap);
     513           0 :                         break;
     514           0 :                 case ORF_MODE_RECEIVE:
     515           0 :                         SET_FLAG(peer->af_cap[afi][safi], rm_cap);
     516           0 :                         break;
     517             :                 }
     518             :         }
     519             :         return 0;
     520             : }
     521             : 
     522          30 : static int bgp_capability_restart(struct peer *peer,
     523             :                                   struct capability_header *caphdr)
     524             : {
     525          30 :         struct stream *s = BGP_INPUT(peer);
     526          30 :         uint16_t restart_flag_time;
     527          30 :         size_t end = stream_get_getp(s) + caphdr->length;
     528             : 
     529             :         /* Verify length is a multiple of 4 */
     530          30 :         if ((caphdr->length - 2) % 4) {
     531           0 :                 flog_warn(
     532             :                         EC_BGP_CAPABILITY_INVALID_LENGTH,
     533             :                         "Restart Cap: Received invalid length %d, non-multiple of 4",
     534             :                         caphdr->length);
     535           0 :                 return -1;
     536             :         }
     537             : 
     538          30 :         SET_FLAG(peer->cap, PEER_CAP_RESTART_RCV);
     539          30 :         restart_flag_time = stream_getw(s);
     540             : 
     541             :         /* The most significant bit is defined in [RFC4724] as
     542             :          * the Restart State ("R") bit.
     543             :          */
     544          30 :         if (CHECK_FLAG(restart_flag_time, GRACEFUL_RESTART_R_BIT))
     545          30 :                 SET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV);
     546             :         else
     547           0 :                 UNSET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV);
     548             : 
     549             :         /* The second most significant bit is defined in this
     550             :          * document as the Graceful Notification ("N") bit.
     551             :          */
     552          30 :         if (CHECK_FLAG(restart_flag_time, GRACEFUL_RESTART_N_BIT))
     553          30 :                 SET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_N_BIT_RCV);
     554             :         else
     555           0 :                 UNSET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_N_BIT_RCV);
     556             : 
     557          30 :         UNSET_FLAG(restart_flag_time, 0xF000);
     558          30 :         peer->v_gr_restart = restart_flag_time;
     559             : 
     560          30 :         if (bgp_debug_neighbor_events(peer)) {
     561           0 :                 zlog_debug(
     562             :                         "%s Peer has%srestarted. Restart Time: %d, N-bit set: %s",
     563             :                         peer->host,
     564             :                         CHECK_FLAG(peer->cap,
     565             :                                    PEER_CAP_GRACEFUL_RESTART_R_BIT_RCV)
     566             :                                 ? " "
     567             :                                 : " not ",
     568             :                         peer->v_gr_restart,
     569             :                         CHECK_FLAG(peer->cap,
     570             :                                    PEER_CAP_GRACEFUL_RESTART_N_BIT_RCV)
     571             :                                 ? "yes"
     572             :                                 : "no");
     573             :         }
     574             : 
     575          30 :         while (stream_get_getp(s) + 4 <= end) {
     576           0 :                 afi_t afi;
     577           0 :                 safi_t safi;
     578           0 :                 iana_afi_t pkt_afi = stream_getw(s);
     579           0 :                 iana_safi_t pkt_safi = stream_getc(s);
     580           0 :                 uint8_t flag = stream_getc(s);
     581             : 
     582             :                 /* Convert AFI, SAFI to internal values, check. */
     583           0 :                 if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
     584           0 :                         if (bgp_debug_neighbor_events(peer))
     585           0 :                                 zlog_debug(
     586             :                                         "%s Addr-family %s/%s(afi/safi) not supported. Ignore the Graceful Restart capability for this AFI/SAFI",
     587             :                                         peer->host, iana_afi2str(pkt_afi),
     588             :                                         iana_safi2str(pkt_safi));
     589           0 :                 } else if (!peer->afc[afi][safi]) {
     590           0 :                         if (bgp_debug_neighbor_events(peer))
     591           0 :                                 zlog_debug(
     592             :                                         "%s Addr-family %s/%s(afi/safi) not enabled. Ignore the Graceful Restart capability",
     593             :                                         peer->host, iana_afi2str(pkt_afi),
     594             :                                         iana_safi2str(pkt_safi));
     595             :                 } else {
     596           0 :                         if (bgp_debug_neighbor_events(peer))
     597           0 :                                 zlog_debug(
     598             :                                         "%s Address family %s is%spreserved",
     599             :                                         peer->host, get_afi_safi_str(afi, safi, false),
     600             :                                         CHECK_FLAG(
     601             :                                                 peer->af_cap[afi][safi],
     602             :                                                 PEER_CAP_RESTART_AF_PRESERVE_RCV)
     603             :                                                 ? " "
     604             :                                                 : " not ");
     605             : 
     606           0 :                         SET_FLAG(peer->af_cap[afi][safi],
     607             :                                  PEER_CAP_RESTART_AF_RCV);
     608           0 :                         if (CHECK_FLAG(flag, GRACEFUL_RESTART_F_BIT))
     609           0 :                                 SET_FLAG(peer->af_cap[afi][safi],
     610             :                                          PEER_CAP_RESTART_AF_PRESERVE_RCV);
     611             :                 }
     612             :         }
     613             :         return 0;
     614             : }
     615             : 
     616          30 : static int bgp_capability_llgr(struct peer *peer,
     617             :                                struct capability_header *caphdr)
     618             : {
     619          30 :         struct stream *s = BGP_INPUT(peer);
     620          30 :         size_t end = stream_get_getp(s) + caphdr->length;
     621             : 
     622          30 :         SET_FLAG(peer->cap, PEER_CAP_LLGR_RCV);
     623             : 
     624          62 :         while (stream_get_getp(s) + 4 <= end) {
     625          32 :                 afi_t afi;
     626          32 :                 safi_t safi;
     627          32 :                 iana_afi_t pkt_afi = stream_getw(s);
     628          32 :                 iana_safi_t pkt_safi = stream_getc(s);
     629          32 :                 uint8_t flags = stream_getc(s);
     630          32 :                 uint32_t stale_time = stream_get3(s);
     631             : 
     632          32 :                 if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
     633           0 :                         if (bgp_debug_neighbor_events(peer))
     634           0 :                                 zlog_debug(
     635             :                                         "%s Addr-family %s/%s(afi/safi) not supported. Ignore the Long-lived Graceful Restart capability for this AFI/SAFI",
     636             :                                         peer->host, iana_afi2str(pkt_afi),
     637             :                                         iana_safi2str(pkt_safi));
     638          32 :                 } else if (!peer->afc[afi][safi]
     639          32 :                            || !CHECK_FLAG(peer->af_cap[afi][safi],
     640             :                                           PEER_CAP_RESTART_AF_RCV)) {
     641          32 :                         if (bgp_debug_neighbor_events(peer))
     642           0 :                                 zlog_debug(
     643             :                                         "%s Addr-family %s/%s(afi/safi) not enabled. Ignore the Long-lived Graceful Restart capability",
     644             :                                         peer->host, iana_afi2str(pkt_afi),
     645             :                                         iana_safi2str(pkt_safi));
     646             :                 } else {
     647           0 :                         if (bgp_debug_neighbor_events(peer))
     648           0 :                                 zlog_debug(
     649             :                                         "%s Addr-family %s/%s(afi/safi) Long-lived Graceful Restart capability stale time %u sec",
     650             :                                         peer->host, iana_afi2str(pkt_afi),
     651             :                                         iana_safi2str(pkt_safi), stale_time);
     652             : 
     653           0 :                         peer->llgr[afi][safi].flags = flags;
     654           0 :                         peer->llgr[afi][safi].stale_time =
     655           0 :                                 MIN(stale_time, peer->bgp->llgr_stale_time);
     656           0 :                         SET_FLAG(peer->af_cap[afi][safi], PEER_CAP_LLGR_AF_RCV);
     657             :                 }
     658             :         }
     659             : 
     660          30 :         return 0;
     661             : }
     662             : 
     663             : /* Unlike other capability parsing routines, this one returns 0 on error */
     664          72 : static as_t bgp_capability_as4(struct peer *peer, struct capability_header *hdr)
     665             : {
     666          72 :         SET_FLAG(peer->cap, PEER_CAP_AS4_RCV);
     667             : 
     668          72 :         if (hdr->length != CAPABILITY_CODE_AS4_LEN) {
     669           0 :                 flog_err(EC_BGP_PKT_OPEN,
     670             :                          "%s AS4 capability has incorrect data length %d",
     671             :                          peer->host, hdr->length);
     672           0 :                 return 0;
     673             :         }
     674             : 
     675          72 :         as_t as4 = stream_getl(BGP_INPUT(peer));
     676             : 
     677          72 :         if (BGP_DEBUG(as4, AS4))
     678           0 :                 zlog_debug(
     679             :                         "%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u",
     680             :                         peer->host, as4);
     681             :         return as4;
     682             : }
     683             : 
     684          32 : static int bgp_capability_ext_message(struct peer *peer,
     685             :                                       struct capability_header *hdr)
     686             : {
     687          32 :         if (hdr->length != CAPABILITY_CODE_EXT_MESSAGE_LEN) {
     688           0 :                 flog_err(
     689             :                         EC_BGP_PKT_OPEN,
     690             :                         "%s: BGP Extended Message capability has incorrect data length %d",
     691             :                         peer->host, hdr->length);
     692           0 :                 return -1;
     693             :         }
     694             : 
     695          32 :         SET_FLAG(peer->cap, PEER_CAP_EXTENDED_MESSAGE_RCV);
     696             : 
     697          32 :         return 0;
     698             : }
     699             : 
     700          30 : static int bgp_capability_addpath(struct peer *peer,
     701             :                                   struct capability_header *hdr)
     702             : {
     703          30 :         struct stream *s = BGP_INPUT(peer);
     704          30 :         size_t end = stream_get_getp(s) + hdr->length;
     705             : 
     706          30 :         SET_FLAG(peer->cap, PEER_CAP_ADDPATH_RCV);
     707             : 
     708             :         /* Verify length is a multiple of 4 */
     709          30 :         if (hdr->length % 4) {
     710           0 :                 flog_warn(
     711             :                         EC_BGP_CAPABILITY_INVALID_LENGTH,
     712             :                         "Add Path: Received invalid length %d, non-multiple of 4",
     713             :                         hdr->length);
     714           0 :                 return -1;
     715             :         }
     716             : 
     717          62 :         while (stream_get_getp(s) + 4 <= end) {
     718          32 :                 afi_t afi;
     719          32 :                 safi_t safi;
     720          32 :                 iana_afi_t pkt_afi = stream_getw(s);
     721          32 :                 iana_safi_t pkt_safi = stream_getc(s);
     722          32 :                 uint8_t send_receive = stream_getc(s);
     723             : 
     724          32 :                 if (bgp_debug_neighbor_events(peer))
     725           0 :                         zlog_debug(
     726             :                                 "%s OPEN has %s capability for afi/safi: %s/%s%s%s",
     727             :                                 peer->host,
     728             :                                 lookup_msg(capcode_str, hdr->code, NULL),
     729             :                                 iana_afi2str(pkt_afi), iana_safi2str(pkt_safi),
     730             :                                 (send_receive & BGP_ADDPATH_RX) ? ", receive"
     731             :                                                                 : "",
     732             :                                 (send_receive & BGP_ADDPATH_TX) ? ", transmit"
     733             :                                                                 : "");
     734             : 
     735             :                 /* Convert AFI, SAFI to internal values, check. */
     736          32 :                 if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
     737           0 :                         if (bgp_debug_neighbor_events(peer))
     738           0 :                                 zlog_debug(
     739             :                                         "%s Addr-family %s/%s(afi/safi) not supported. Ignore the Addpath Attribute for this AFI/SAFI",
     740             :                                         peer->host, iana_afi2str(pkt_afi),
     741             :                                         iana_safi2str(pkt_safi));
     742           0 :                         continue;
     743          32 :                 } else if (!peer->afc[afi][safi]) {
     744           0 :                         if (bgp_debug_neighbor_events(peer))
     745           0 :                                 zlog_debug(
     746             :                                         "%s Addr-family %s/%s(afi/safi) not enabled. Ignore the AddPath capability for this AFI/SAFI",
     747             :                                         peer->host, iana_afi2str(pkt_afi),
     748             :                                         iana_safi2str(pkt_safi));
     749           0 :                         continue;
     750             :                 }
     751             : 
     752          32 :                 if (send_receive & BGP_ADDPATH_RX)
     753          32 :                         SET_FLAG(peer->af_cap[afi][safi],
     754             :                                  PEER_CAP_ADDPATH_AF_RX_RCV);
     755             : 
     756          32 :                 if (send_receive & BGP_ADDPATH_TX)
     757           0 :                         SET_FLAG(peer->af_cap[afi][safi],
     758             :                                  PEER_CAP_ADDPATH_AF_TX_RCV);
     759             :         }
     760             : 
     761             :         return 0;
     762             : }
     763             : 
     764           0 : static int bgp_capability_enhe(struct peer *peer, struct capability_header *hdr)
     765             : {
     766           0 :         struct stream *s = BGP_INPUT(peer);
     767           0 :         size_t end = stream_get_getp(s) + hdr->length;
     768             : 
     769             :         /* Verify length is a multiple of 4 */
     770           0 :         if (hdr->length % 6) {
     771           0 :                 flog_warn(
     772             :                         EC_BGP_CAPABILITY_INVALID_LENGTH,
     773             :                         "Extended NH: Received invalid length %d, non-multiple of 6",
     774             :                         hdr->length);
     775           0 :                 return -1;
     776             :         }
     777             : 
     778           0 :         while (stream_get_getp(s) + 6 <= end) {
     779           0 :                 iana_afi_t pkt_afi = stream_getw(s);
     780           0 :                 afi_t afi;
     781           0 :                 iana_safi_t pkt_safi = stream_getw(s);
     782           0 :                 safi_t safi;
     783           0 :                 iana_afi_t pkt_nh_afi = stream_getw(s);
     784           0 :                 afi_t nh_afi;
     785             : 
     786           0 :                 if (bgp_debug_neighbor_events(peer))
     787           0 :                         zlog_debug(
     788             :                                 "%s Received with afi/safi/next-hop afi: %s/%s/%u",
     789             :                                 peer->host, iana_afi2str(pkt_afi),
     790             :                                 iana_safi2str(pkt_safi), pkt_nh_afi);
     791             : 
     792             :                 /* Convert AFI, SAFI to internal values, check. */
     793           0 :                 if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
     794           0 :                         if (bgp_debug_neighbor_events(peer))
     795           0 :                                 zlog_debug(
     796             :                                         "%s Addr-family %s/%s(afi/safi) not supported. Ignore the ENHE Attribute for this AFI/SAFI",
     797             :                                         peer->host, iana_afi2str(pkt_afi),
     798             :                                         iana_safi2str(pkt_safi));
     799           0 :                         continue;
     800             :                 }
     801             : 
     802             :                 /* RFC 5549 specifies use of this capability only for IPv4 AFI,
     803             :                  * with
     804             :                  * the Nexthop AFI being IPv6. A future spec may introduce other
     805             :                  * possibilities, so we ignore other values with a log. Also,
     806             :                  * only
     807             :                  * SAFI_UNICAST and SAFI_LABELED_UNICAST are currently supported
     808             :                  * (and expected).
     809             :                  */
     810           0 :                 nh_afi = afi_iana2int(pkt_nh_afi);
     811             : 
     812           0 :                 if (afi != AFI_IP || nh_afi != AFI_IP6
     813           0 :                     || !(safi == SAFI_UNICAST || safi == SAFI_MPLS_VPN
     814             :                          || safi == SAFI_LABELED_UNICAST)) {
     815           0 :                         flog_warn(
     816             :                                 EC_BGP_CAPABILITY_INVALID_DATA,
     817             :                                 "%s Unexpected afi/safi/next-hop afi: %s/%s/%u in Extended Next-hop capability, ignoring",
     818             :                                 peer->host, iana_afi2str(pkt_afi),
     819             :                                 iana_safi2str(pkt_safi), pkt_nh_afi);
     820           0 :                         continue;
     821             :                 }
     822             : 
     823           0 :                 SET_FLAG(peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_RCV);
     824             : 
     825           0 :                 if (CHECK_FLAG(peer->af_cap[afi][safi], PEER_CAP_ENHE_AF_ADV))
     826           0 :                         SET_FLAG(peer->af_cap[afi][safi],
     827             :                                  PEER_CAP_ENHE_AF_NEGO);
     828             :         }
     829             : 
     830           0 :         SET_FLAG(peer->cap, PEER_CAP_ENHE_RCV);
     831             : 
     832           0 :         return 0;
     833             : }
     834             : 
     835          30 : static int bgp_capability_hostname(struct peer *peer,
     836             :                                    struct capability_header *hdr)
     837             : {
     838          30 :         struct stream *s = BGP_INPUT(peer);
     839          30 :         char str[BGP_MAX_HOSTNAME + 1];
     840          30 :         size_t end = stream_get_getp(s) + hdr->length;
     841          30 :         uint8_t len;
     842             : 
     843          30 :         SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_RCV);
     844             : 
     845          30 :         len = stream_getc(s);
     846          30 :         if (stream_get_getp(s) + len > end) {
     847           0 :                 flog_warn(
     848             :                         EC_BGP_CAPABILITY_INVALID_DATA,
     849             :                         "%s: Received malformed hostname capability from peer %s",
     850             :                         __func__, peer->host);
     851           0 :                 return -1;
     852             :         }
     853             : 
     854          30 :         if (len > BGP_MAX_HOSTNAME) {
     855           0 :                 stream_get(str, s, BGP_MAX_HOSTNAME);
     856           0 :                 stream_forward_getp(s, len - BGP_MAX_HOSTNAME);
     857           0 :                 len = BGP_MAX_HOSTNAME; /* to set the '\0' below */
     858          30 :         } else if (len)
     859          30 :                 stream_get(str, s, len);
     860             : 
     861          30 :         if (len) {
     862          30 :                 str[len] = '\0';
     863             : 
     864          30 :                 XFREE(MTYPE_BGP_PEER_HOST, peer->hostname);
     865          30 :                 XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
     866             : 
     867          30 :                 peer->hostname = XSTRDUP(MTYPE_BGP_PEER_HOST, str);
     868             :         }
     869             : 
     870          30 :         if (stream_get_getp(s) + 1 > end) {
     871           0 :                 flog_warn(
     872             :                         EC_BGP_CAPABILITY_INVALID_DATA,
     873             :                         "%s: Received invalid domain name len (hostname capability) from peer %s",
     874             :                         __func__, peer->host);
     875           0 :                 return -1;
     876             :         }
     877             : 
     878          30 :         len = stream_getc(s);
     879          30 :         if (stream_get_getp(s) + len > end) {
     880           0 :                 flog_warn(
     881             :                         EC_BGP_CAPABILITY_INVALID_DATA,
     882             :                         "%s: Received runt domain name (hostname capability) from peer %s",
     883             :                         __func__, peer->host);
     884           0 :                 return -1;
     885             :         }
     886             : 
     887          30 :         if (len > BGP_MAX_HOSTNAME) {
     888           0 :                 stream_get(str, s, BGP_MAX_HOSTNAME);
     889           0 :                 stream_forward_getp(s, len - BGP_MAX_HOSTNAME);
     890           0 :                 len = BGP_MAX_HOSTNAME; /* to set the '\0' below */
     891          30 :         } else if (len)
     892           0 :                 stream_get(str, s, len);
     893             : 
     894           0 :         if (len) {
     895           0 :                 str[len] = '\0';
     896             : 
     897           0 :                 XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
     898             : 
     899           0 :                 peer->domainname = XSTRDUP(MTYPE_BGP_PEER_HOST, str);
     900             :         }
     901             : 
     902          30 :         if (bgp_debug_neighbor_events(peer)) {
     903           0 :                 zlog_debug("%s received hostname %s, domainname %s", peer->host,
     904             :                            peer->hostname, peer->domainname);
     905             :         }
     906             : 
     907             :         return 0;
     908             : }
     909             : 
     910           0 : static int bgp_capability_role(struct peer *peer, struct capability_header *hdr)
     911             : {
     912           0 :         SET_FLAG(peer->cap, PEER_CAP_ROLE_RCV);
     913           0 :         if (hdr->length != CAPABILITY_CODE_ROLE_LEN) {
     914           0 :                 flog_warn(EC_BGP_CAPABILITY_INVALID_LENGTH,
     915             :                           "Role: Received invalid length %d", hdr->length);
     916           0 :                 return -1;
     917             :         }
     918           0 :         uint8_t role = stream_getc(BGP_INPUT(peer));
     919             : 
     920           0 :         peer->remote_role = role;
     921           0 :         return 0;
     922             : }
     923             : 
     924             : /**
     925             :  * Parse given capability.
     926             :  * XXX: This is reading into a stream, but not using stream API
     927             :  *
     928             :  * @param[out] mp_capability Set to 1 on return iff one or more Multiprotocol
     929             :  *                           capabilities were encountered.
     930             :  */
     931         340 : static int bgp_capability_parse(struct peer *peer, size_t length,
     932             :                                 int *mp_capability, uint8_t **error)
     933             : {
     934         340 :         int ret;
     935         340 :         struct stream *s = BGP_INPUT(peer);
     936         340 :         size_t end = stream_get_getp(s) + length;
     937         340 :         uint16_t restart_flag_time = 0;
     938             : 
     939         340 :         assert(STREAM_READABLE(s) >= length);
     940             : 
     941         680 :         while (stream_get_getp(s) < end) {
     942         340 :                 size_t start;
     943         340 :                 uint8_t *sp = stream_pnt(s);
     944         340 :                 struct capability_header caphdr;
     945             : 
     946         340 :                 ret = 0;
     947             :                 /* We need at least capability code and capability length. */
     948         340 :                 if (stream_get_getp(s) + 2 > end) {
     949           0 :                         zlog_info("%s Capability length error (< header)",
     950             :                                   peer->host);
     951           0 :                         bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
     952             :                                         BGP_NOTIFY_OPEN_MALFORMED_ATTR);
     953           0 :                         return -1;
     954             :                 }
     955             : 
     956         340 :                 caphdr.code = stream_getc(s);
     957         340 :                 caphdr.length = stream_getc(s);
     958         340 :                 start = stream_get_getp(s);
     959             : 
     960             :                 /* Capability length check sanity check. */
     961         340 :                 if (start + caphdr.length > end) {
     962           0 :                         zlog_info("%s Capability length error (< length)",
     963             :                                   peer->host);
     964           0 :                         bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
     965             :                                         BGP_NOTIFY_OPEN_MALFORMED_ATTR);
     966           0 :                         return -1;
     967             :                 }
     968             : 
     969         340 :                 if (bgp_debug_neighbor_events(peer))
     970           0 :                         zlog_debug("%s OPEN has %s capability (%u), length %u",
     971             :                                    peer->host,
     972             :                                    lookup_msg(capcode_str, caphdr.code, NULL),
     973             :                                    caphdr.code, caphdr.length);
     974             : 
     975             :                 /* Length sanity check, type-specific, for known capabilities */
     976         340 :                 switch (caphdr.code) {
     977         310 :                 case CAPABILITY_CODE_MP:
     978             :                 case CAPABILITY_CODE_REFRESH:
     979             :                 case CAPABILITY_CODE_REFRESH_OLD:
     980             :                 case CAPABILITY_CODE_ORF:
     981             :                 case CAPABILITY_CODE_ORF_OLD:
     982             :                 case CAPABILITY_CODE_RESTART:
     983             :                 case CAPABILITY_CODE_AS4:
     984             :                 case CAPABILITY_CODE_ADDPATH:
     985             :                 case CAPABILITY_CODE_DYNAMIC:
     986             :                 case CAPABILITY_CODE_DYNAMIC_OLD:
     987             :                 case CAPABILITY_CODE_ENHE:
     988             :                 case CAPABILITY_CODE_FQDN:
     989             :                 case CAPABILITY_CODE_ENHANCED_RR:
     990             :                 case CAPABILITY_CODE_EXT_MESSAGE:
     991             :                 case CAPABILITY_CODE_ROLE:
     992             :                         /* Check length. */
     993         310 :                         if (caphdr.length < cap_minsizes[caphdr.code]) {
     994           0 :                                 zlog_info(
     995             :                                         "%s %s Capability length error: got %u, expected at least %u",
     996             :                                         peer->host,
     997             :                                         lookup_msg(capcode_str, caphdr.code,
     998             :                                                    NULL),
     999             :                                         caphdr.length,
    1000             :                                         (unsigned)cap_minsizes[caphdr.code]);
    1001           0 :                                 bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
    1002             :                                                 BGP_NOTIFY_OPEN_MALFORMED_ATTR);
    1003           0 :                                 return -1;
    1004             :                         }
    1005         310 :                         if (caphdr.length
    1006         188 :                             && caphdr.length % cap_modsizes[caphdr.code] != 0) {
    1007           0 :                                 zlog_info(
    1008             :                                         "%s %s Capability length error: got %u, expected a multiple of %u",
    1009             :                                         peer->host,
    1010             :                                         lookup_msg(capcode_str, caphdr.code,
    1011             :                                                    NULL),
    1012             :                                         caphdr.length,
    1013             :                                         (unsigned)cap_modsizes[caphdr.code]);
    1014           0 :                                 bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
    1015             :                                                 BGP_NOTIFY_OPEN_MALFORMED_ATTR);
    1016           0 :                                 return -1;
    1017             :                         }
    1018             :                 /* we deliberately ignore unknown codes, see below */
    1019             :                 default:
    1020         340 :                         break;
    1021             :                 }
    1022             : 
    1023         340 :                 switch (caphdr.code) {
    1024          66 :                 case CAPABILITY_CODE_MP: {
    1025          66 :                         *mp_capability = 1;
    1026             : 
    1027             :                         /* Ignore capability when override-capability is set. */
    1028          66 :                         if (!CHECK_FLAG(peer->flags,
    1029             :                                         PEER_FLAG_OVERRIDE_CAPABILITY)) {
    1030             :                                 /* Set negotiated value. */
    1031          66 :                                 ret = bgp_capability_mp(peer, &caphdr);
    1032             : 
    1033             :                                 /* Unsupported Capability. */
    1034          66 :                                 if (ret < 0) {
    1035             :                                         /* Store return data. */
    1036          32 :                                         memcpy(*error, sp, caphdr.length + 2);
    1037          32 :                                         *error += caphdr.length + 2;
    1038             :                                 }
    1039             :                                 ret = 0; /* Don't return error for this */
    1040             :                         }
    1041             :                 } break;
    1042          90 :                 case CAPABILITY_CODE_ENHANCED_RR:
    1043             :                 case CAPABILITY_CODE_REFRESH:
    1044             :                 case CAPABILITY_CODE_REFRESH_OLD: {
    1045             :                         /* BGP refresh capability */
    1046          90 :                         if (caphdr.code == CAPABILITY_CODE_ENHANCED_RR)
    1047          30 :                                 SET_FLAG(peer->cap, PEER_CAP_ENHANCED_RR_RCV);
    1048          60 :                         else if (caphdr.code == CAPABILITY_CODE_REFRESH_OLD)
    1049          30 :                                 SET_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV);
    1050             :                         else
    1051          30 :                                 SET_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV);
    1052             :                 } break;
    1053           0 :                 case CAPABILITY_CODE_ORF:
    1054             :                 case CAPABILITY_CODE_ORF_OLD:
    1055           0 :                         ret = bgp_capability_orf_entry(peer, &caphdr);
    1056           0 :                         break;
    1057          30 :                 case CAPABILITY_CODE_RESTART:
    1058          30 :                         ret = bgp_capability_restart(peer, &caphdr);
    1059          30 :                         break;
    1060          30 :                 case CAPABILITY_CODE_LLGR:
    1061          30 :                         ret = bgp_capability_llgr(peer, &caphdr);
    1062          30 :                         break;
    1063           0 :                 case CAPABILITY_CODE_DYNAMIC:
    1064             :                 case CAPABILITY_CODE_DYNAMIC_OLD:
    1065           0 :                         SET_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV);
    1066           0 :                         break;
    1067          32 :                 case CAPABILITY_CODE_AS4:
    1068             :                         /* Already handled as a special-case parsing of the
    1069             :                          * capabilities
    1070             :                          * at the beginning of OPEN processing. So we care not a
    1071             :                          * jot
    1072             :                          * for the value really, only error case.
    1073             :                          */
    1074          32 :                         if (!bgp_capability_as4(peer, &caphdr))
    1075             :                                 ret = -1;
    1076             :                         break;
    1077          30 :                 case CAPABILITY_CODE_ADDPATH:
    1078          30 :                         ret = bgp_capability_addpath(peer, &caphdr);
    1079          30 :                         break;
    1080           0 :                 case CAPABILITY_CODE_ENHE:
    1081           0 :                         ret = bgp_capability_enhe(peer, &caphdr);
    1082           0 :                         break;
    1083          32 :                 case CAPABILITY_CODE_EXT_MESSAGE:
    1084          32 :                         ret = bgp_capability_ext_message(peer, &caphdr);
    1085          32 :                         break;
    1086          30 :                 case CAPABILITY_CODE_FQDN:
    1087          30 :                         ret = bgp_capability_hostname(peer, &caphdr);
    1088          30 :                         break;
    1089           0 :                 case CAPABILITY_CODE_ROLE:
    1090           0 :                         ret = bgp_capability_role(peer, &caphdr);
    1091           0 :                         break;
    1092           0 :                 default:
    1093           0 :                         if (caphdr.code > 128) {
    1094             :                                 /* We don't send Notification for unknown vendor
    1095             :                                    specific
    1096             :                                    capabilities.  It seems reasonable for now...
    1097             :                                    */
    1098           0 :                                 flog_warn(EC_BGP_CAPABILITY_VENDOR,
    1099             :                                           "%s Vendor specific capability %d",
    1100             :                                           peer->host, caphdr.code);
    1101             :                         } else {
    1102           0 :                                 flog_warn(
    1103             :                                         EC_BGP_CAPABILITY_UNKNOWN,
    1104             :                                         "%s unrecognized capability code: %d - ignored",
    1105             :                                         peer->host, caphdr.code);
    1106           0 :                                 memcpy(*error, sp, caphdr.length + 2);
    1107           0 :                                 *error += caphdr.length + 2;
    1108             :                         }
    1109             :                 }
    1110             : 
    1111         242 :                 if (ret < 0) {
    1112           0 :                         bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
    1113             :                                         BGP_NOTIFY_OPEN_MALFORMED_ATTR);
    1114           0 :                         return -1;
    1115             :                 }
    1116         340 :                 if (stream_get_getp(s) != (start + caphdr.length)) {
    1117           0 :                         if (stream_get_getp(s) > (start + caphdr.length))
    1118           0 :                                 flog_warn(
    1119             :                                         EC_BGP_CAPABILITY_INVALID_LENGTH,
    1120             :                                         "%s Cap-parser for %s read past cap-length, %u!",
    1121             :                                         peer->host,
    1122             :                                         lookup_msg(capcode_str, caphdr.code,
    1123             :                                                    NULL),
    1124             :                                         caphdr.length);
    1125           0 :                         stream_set_getp(s, start + caphdr.length);
    1126             :                 }
    1127             : 
    1128         340 :                 if (!CHECK_FLAG(peer->cap, PEER_CAP_RESTART_RCV)) {
    1129         280 :                         UNSET_FLAG(restart_flag_time, 0xF000);
    1130         280 :                         peer->v_gr_restart = restart_flag_time;
    1131             :                 }
    1132             :         }
    1133             :         return 0;
    1134             : }
    1135             : 
    1136           0 : static bool strict_capability_same(struct peer *peer)
    1137             : {
    1138           0 :         int i, j;
    1139             : 
    1140           0 :         for (i = AFI_IP; i < AFI_MAX; i++)
    1141           0 :                 for (j = SAFI_UNICAST; j < SAFI_MAX; j++)
    1142           0 :                         if (peer->afc[i][j] != peer->afc_nego[i][j])
    1143             :                                 return false;
    1144             :         return true;
    1145             : }
    1146             : 
    1147             : 
    1148          32 : static bool bgp_role_violation(struct peer *peer)
    1149             : {
    1150          32 :         uint8_t local_role = peer->local_role;
    1151          32 :         uint8_t remote_role = peer->remote_role;
    1152             : 
    1153          32 :         if (local_role != ROLE_UNDEFINED && remote_role != ROLE_UNDEFINED &&
    1154           0 :             !((local_role == ROLE_PEER && remote_role == ROLE_PEER) ||
    1155           0 :               (local_role == ROLE_PROVIDER && remote_role == ROLE_CUSTOMER) ||
    1156           0 :               (local_role == ROLE_CUSTOMER && remote_role == ROLE_PROVIDER) ||
    1157           0 :               (local_role == ROLE_RS_SERVER && remote_role == ROLE_RS_CLIENT) ||
    1158           0 :               (local_role == ROLE_RS_CLIENT &&
    1159           0 :                remote_role == ROLE_RS_SERVER))) {
    1160           0 :                 bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
    1161             :                                 BGP_NOTIFY_OPEN_ROLE_MISMATCH);
    1162           0 :                 return true;
    1163             :         }
    1164          32 :         if (remote_role == ROLE_UNDEFINED &&
    1165          32 :             CHECK_FLAG(peer->flags, PEER_FLAG_ROLE_STRICT_MODE)) {
    1166           0 :                 const char *err_msg =
    1167             :                         "Strict mode. Please set the role on your side.";
    1168           0 :                 bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR,
    1169             :                                           BGP_NOTIFY_OPEN_ROLE_MISMATCH,
    1170             :                                           (uint8_t *)err_msg, strlen(err_msg));
    1171           0 :                 return true;
    1172             :         }
    1173             :         return false;
    1174             : }
    1175             : 
    1176             : 
    1177             : /* peek into option, stores ASN to *as4 if the AS4 capability was found.
    1178             :  * Returns  0 if no as4 found, as4cap value otherwise.
    1179             :  */
    1180          40 : as_t peek_for_as4_capability(struct peer *peer, uint16_t length)
    1181             : {
    1182          40 :         struct stream *s = BGP_INPUT(peer);
    1183          40 :         size_t orig_getp = stream_get_getp(s);
    1184          40 :         size_t end = orig_getp + length;
    1185          40 :         as_t as4 = 0;
    1186             : 
    1187          40 :         if (BGP_DEBUG(as4, AS4))
    1188           0 :                 zlog_debug(
    1189             :                         "%s [AS4] rcv OPEN w/ OPTION parameter len: %u, peeking for as4",
    1190             :                         peer->host, length);
    1191             :         /* the error cases we DONT handle, we ONLY try to read as4 out of
    1192             :          * correctly formatted options.
    1193             :          */
    1194         228 :         while (stream_get_getp(s) < end) {
    1195         228 :                 uint8_t opt_type;
    1196         228 :                 uint16_t opt_length;
    1197             : 
    1198             :                 /* Ensure we can read the option type */
    1199         228 :                 if (stream_get_getp(s) + 1 > end)
    1200           0 :                         goto end;
    1201             : 
    1202             :                 /* Fetch the option type */
    1203         228 :                 opt_type = stream_getc(s);
    1204             : 
    1205             :                 /*
    1206             :                  * Check the length and fetch the opt_length
    1207             :                  * If the peer is BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)
    1208             :                  * then we do a getw which is 2 bytes.  So we need to
    1209             :                  * ensure that we can read that as well
    1210             :                  */
    1211         228 :                 if (BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)) {
    1212           0 :                         if (stream_get_getp(s) + 2 > end)
    1213           0 :                                 goto end;
    1214             : 
    1215           0 :                         opt_length = stream_getw(s);
    1216             :                 } else {
    1217         228 :                         if (stream_get_getp(s) + 1 > end)
    1218           0 :                                 goto end;
    1219             : 
    1220         228 :                         opt_length = stream_getc(s);
    1221             :                 }
    1222             : 
    1223             :                 /* Option length check. */
    1224         228 :                 if (stream_get_getp(s) + opt_length > end)
    1225           0 :                         goto end;
    1226             : 
    1227         228 :                 if (opt_type == BGP_OPEN_OPT_CAP) {
    1228         228 :                         unsigned long capd_start = stream_get_getp(s);
    1229         228 :                         unsigned long capd_end = capd_start + opt_length;
    1230             : 
    1231         228 :                         assert(capd_end <= end);
    1232             : 
    1233         416 :                         while (stream_get_getp(s) < capd_end) {
    1234         228 :                                 struct capability_header hdr;
    1235             : 
    1236         228 :                                 if (stream_get_getp(s) + 2 > capd_end)
    1237          40 :                                         goto end;
    1238             : 
    1239         228 :                                 hdr.code = stream_getc(s);
    1240         228 :                                 hdr.length = stream_getc(s);
    1241             : 
    1242         228 :                                 if ((stream_get_getp(s) + hdr.length)
    1243             :                                     > capd_end)
    1244           0 :                                         goto end;
    1245             : 
    1246         228 :                                 if (hdr.code == CAPABILITY_CODE_AS4) {
    1247          40 :                                         if (BGP_DEBUG(as4, AS4))
    1248           0 :                                                 zlog_debug(
    1249             :                                                         "[AS4] found AS4 capability, about to parse");
    1250          40 :                                         as4 = bgp_capability_as4(peer, &hdr);
    1251             : 
    1252          40 :                                         goto end;
    1253             :                                 }
    1254         188 :                                 stream_forward_getp(s, hdr.length);
    1255             :                         }
    1256             :                 }
    1257             :         }
    1258             : 
    1259           0 : end:
    1260          40 :         stream_set_getp(s, orig_getp);
    1261          40 :         return as4;
    1262             : }
    1263             : 
    1264             : /**
    1265             :  * Parse open option.
    1266             :  *
    1267             :  * @param[out] mp_capability @see bgp_capability_parse() for semantics.
    1268             :  */
    1269          32 : int bgp_open_option_parse(struct peer *peer, uint16_t length,
    1270             :                           int *mp_capability)
    1271             : {
    1272          32 :         int ret = 0;
    1273          32 :         uint8_t *error;
    1274          32 :         uint8_t error_data[BGP_STANDARD_MESSAGE_MAX_PACKET_SIZE];
    1275          32 :         struct stream *s = BGP_INPUT(peer);
    1276          32 :         size_t end = stream_get_getp(s) + length;
    1277             : 
    1278          32 :         error = error_data;
    1279             : 
    1280          32 :         if (bgp_debug_neighbor_events(peer))
    1281           0 :                 zlog_debug("%s rcv OPEN w/ OPTION parameter len: %u",
    1282             :                            peer->host, length);
    1283             : 
    1284             :         /* Unset any previously received GR capability. */
    1285          32 :         UNSET_FLAG(peer->cap, PEER_CAP_RESTART_RCV);
    1286             : 
    1287         372 :         while (stream_get_getp(s) < end) {
    1288         340 :                 uint8_t opt_type;
    1289         340 :                 uint16_t opt_length;
    1290             : 
    1291             :                 /*
    1292             :                  * Check that we can read the opt_type and fetch it
    1293             :                  */
    1294         340 :                 if (STREAM_READABLE(s) < 1) {
    1295           0 :                         zlog_info("%s Option length error", peer->host);
    1296           0 :                         bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
    1297             :                                         BGP_NOTIFY_OPEN_MALFORMED_ATTR);
    1298           0 :                         return -1;
    1299             :                 }
    1300         340 :                 opt_type = stream_getc(s);
    1301             : 
    1302             :                 /*
    1303             :                  * Check the length of the stream to ensure that
    1304             :                  * FRR can properly read the opt_length. Then read it
    1305             :                  */
    1306         340 :                 if (BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)) {
    1307           0 :                         if (STREAM_READABLE(s) < 2) {
    1308           0 :                                 zlog_info("%s Option length error", peer->host);
    1309           0 :                                 bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
    1310             :                                                 BGP_NOTIFY_OPEN_MALFORMED_ATTR);
    1311           0 :                                 return -1;
    1312             :                         }
    1313             : 
    1314           0 :                         opt_length = stream_getw(s);
    1315             :                 } else {
    1316         340 :                         if (STREAM_READABLE(s) < 1) {
    1317           0 :                                 zlog_info("%s Option length error", peer->host);
    1318           0 :                                 bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
    1319             :                                                 BGP_NOTIFY_OPEN_MALFORMED_ATTR);
    1320           0 :                                 return -1;
    1321             :                         }
    1322             : 
    1323         340 :                         opt_length = stream_getc(s);
    1324             :                 }
    1325             : 
    1326             :                 /* Option length check. */
    1327         340 :                 if (STREAM_READABLE(s) < opt_length) {
    1328           0 :                         zlog_info("%s Option length error (%d)", peer->host,
    1329             :                                   opt_length);
    1330           0 :                         bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
    1331             :                                         BGP_NOTIFY_OPEN_MALFORMED_ATTR);
    1332           0 :                         return -1;
    1333             :                 }
    1334             : 
    1335         340 :                 if (bgp_debug_neighbor_events(peer))
    1336           0 :                         zlog_debug(
    1337             :                                 "%s rcvd OPEN w/ optional parameter type %u (%s) len %u",
    1338             :                                 peer->host, opt_type,
    1339             :                                 opt_type == BGP_OPEN_OPT_CAP ? "Capability"
    1340             :                                                              : "Unknown",
    1341             :                                 opt_length);
    1342             : 
    1343         340 :                 switch (opt_type) {
    1344         340 :                 case BGP_OPEN_OPT_CAP:
    1345         340 :                         ret = bgp_capability_parse(peer, opt_length,
    1346             :                                                    mp_capability, &error);
    1347         340 :                         break;
    1348           0 :                 default:
    1349           0 :                         bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
    1350             :                                         BGP_NOTIFY_OPEN_UNSUP_PARAM);
    1351           0 :                         ret = -1;
    1352           0 :                         break;
    1353             :                 }
    1354             : 
    1355             :                 /* Parse error.  To accumulate all unsupported capability codes,
    1356             :                    bgp_capability_parse does not return -1 when encounter
    1357             :                    unsupported capability code.  To detect that, please check
    1358             :                    error and erro_data pointer, like below.  */
    1359         340 :                 if (ret < 0)
    1360             :                         return -1;
    1361             :         }
    1362             : 
    1363             :         /* All OPEN option is parsed.  Check capability when strict compare
    1364             :            flag is enabled.*/
    1365          32 :         if (CHECK_FLAG(peer->flags, PEER_FLAG_STRICT_CAP_MATCH)) {
    1366             :                 /* If Unsupported Capability exists. */
    1367           0 :                 if (error != error_data) {
    1368           0 :                         bgp_notify_send_with_data(peer, BGP_NOTIFY_OPEN_ERR,
    1369             :                                                   BGP_NOTIFY_OPEN_UNSUP_CAPBL,
    1370             :                                                   error_data,
    1371           0 :                                                   error - error_data);
    1372           0 :                         return -1;
    1373             :                 }
    1374             : 
    1375             :                 /* Check local capability does not negotiated with remote
    1376             :                    peer. */
    1377           0 :                 if (!strict_capability_same(peer)) {
    1378           0 :                         bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
    1379             :                                         BGP_NOTIFY_OPEN_UNSUP_CAPBL);
    1380           0 :                         return -1;
    1381             :                 }
    1382             :         }
    1383             : 
    1384             :         /* Extended Message Support */
    1385          64 :         peer->max_packet_size =
    1386             :                 (CHECK_FLAG(peer->cap, PEER_CAP_EXTENDED_MESSAGE_RCV)
    1387          32 :                  && CHECK_FLAG(peer->cap, PEER_CAP_EXTENDED_MESSAGE_ADV))
    1388             :                         ? BGP_EXTENDED_MESSAGE_MAX_PACKET_SIZE
    1389             :                         : BGP_STANDARD_MESSAGE_MAX_PACKET_SIZE;
    1390             : 
    1391             :         /* Check that roles are corresponding to each other */
    1392          32 :         if (bgp_role_violation(peer))
    1393             :                 return -1;
    1394             : 
    1395             :         /* Check there are no common AFI/SAFIs and send Unsupported Capability
    1396             :            error. */
    1397          32 :         if (*mp_capability
    1398          32 :             && !CHECK_FLAG(peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) {
    1399          32 :                 if (!peer->afc_nego[AFI_IP][SAFI_UNICAST]
    1400          32 :                     && !peer->afc_nego[AFI_IP][SAFI_MULTICAST]
    1401           0 :                     && !peer->afc_nego[AFI_IP][SAFI_LABELED_UNICAST]
    1402             :                     && !peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
    1403           0 :                     && !peer->afc_nego[AFI_IP][SAFI_ENCAP]
    1404             :                     && !peer->afc_nego[AFI_IP][SAFI_FLOWSPEC]
    1405           0 :                     && !peer->afc_nego[AFI_IP6][SAFI_UNICAST]
    1406           0 :                     && !peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
    1407           0 :                     && !peer->afc_nego[AFI_IP6][SAFI_LABELED_UNICAST]
    1408             :                     && !peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
    1409           0 :                     && !peer->afc_nego[AFI_IP6][SAFI_ENCAP]
    1410             :                     && !peer->afc_nego[AFI_IP6][SAFI_FLOWSPEC]
    1411           0 :                     && !peer->afc_nego[AFI_L2VPN][SAFI_EVPN]) {
    1412           0 :                         flog_err(EC_BGP_PKT_OPEN,
    1413             :                                  "%s [Error] Configured AFI/SAFIs do not overlap with received MP capabilities",
    1414             :                                  peer->host);
    1415             : 
    1416           0 :                         if (error != error_data)
    1417           0 :                                 bgp_notify_send_with_data(
    1418             :                                         peer, BGP_NOTIFY_OPEN_ERR,
    1419             :                                         BGP_NOTIFY_OPEN_UNSUP_CAPBL, error_data,
    1420           0 :                                         error - error_data);
    1421             :                         else
    1422           0 :                                 bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
    1423             :                                                 BGP_NOTIFY_OPEN_UNSUP_CAPBL);
    1424           0 :                         return -1;
    1425             :                 }
    1426             :         }
    1427             :         return 0;
    1428             : }
    1429             : 
    1430           0 : static void bgp_open_capability_orf(struct stream *s, struct peer *peer,
    1431             :                                     afi_t afi, safi_t safi, uint8_t code,
    1432             :                                     bool ext_opt_params)
    1433             : {
    1434           0 :         uint16_t cap_len;
    1435           0 :         uint8_t orf_len;
    1436           0 :         unsigned long capp;
    1437           0 :         unsigned long orfp;
    1438           0 :         unsigned long numberp;
    1439           0 :         int number_of_orfs = 0;
    1440           0 :         iana_afi_t pkt_afi = IANA_AFI_IPV4;
    1441           0 :         iana_safi_t pkt_safi = IANA_SAFI_UNICAST;
    1442             : 
    1443             :         /* Convert AFI, SAFI to values for packet. */
    1444           0 :         bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
    1445             : 
    1446           0 :         stream_putc(s, BGP_OPEN_OPT_CAP);
    1447           0 :         capp = stream_get_endp(s); /* Set Capability Len Pointer */
    1448           0 :         ext_opt_params ? stream_putw(s, 0)
    1449           0 :                        : stream_putc(s, 0); /* Capability Length */
    1450           0 :         stream_putc(s, code);      /* Capability Code */
    1451           0 :         orfp = stream_get_endp(s); /* Set ORF Len Pointer */
    1452           0 :         stream_putc(s, 0);       /* ORF Length */
    1453           0 :         stream_putw(s, pkt_afi);
    1454           0 :         stream_putc(s, 0);
    1455           0 :         stream_putc(s, pkt_safi);
    1456           0 :         numberp = stream_get_endp(s); /* Set Number Pointer */
    1457           0 :         stream_putc(s, 0);          /* Number of ORFs */
    1458             : 
    1459             :         /* Address Prefix ORF */
    1460           0 :         if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
    1461           0 :             || CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM)) {
    1462           0 :                 stream_putc(s, (code == CAPABILITY_CODE_ORF
    1463             :                                         ? ORF_TYPE_PREFIX
    1464             :                                         : ORF_TYPE_PREFIX_OLD));
    1465             : 
    1466           0 :                 if (CHECK_FLAG(peer->af_flags[afi][safi],
    1467             :                                PEER_FLAG_ORF_PREFIX_SM)
    1468           0 :                     && CHECK_FLAG(peer->af_flags[afi][safi],
    1469             :                                   PEER_FLAG_ORF_PREFIX_RM)) {
    1470           0 :                         SET_FLAG(peer->af_cap[afi][safi],
    1471             :                                  PEER_CAP_ORF_PREFIX_SM_ADV);
    1472           0 :                         SET_FLAG(peer->af_cap[afi][safi],
    1473             :                                  PEER_CAP_ORF_PREFIX_RM_ADV);
    1474           0 :                         stream_putc(s, ORF_MODE_BOTH);
    1475           0 :                 } else if (CHECK_FLAG(peer->af_flags[afi][safi],
    1476             :                                       PEER_FLAG_ORF_PREFIX_SM)) {
    1477           0 :                         SET_FLAG(peer->af_cap[afi][safi],
    1478             :                                  PEER_CAP_ORF_PREFIX_SM_ADV);
    1479           0 :                         stream_putc(s, ORF_MODE_SEND);
    1480             :                 } else {
    1481           0 :                         SET_FLAG(peer->af_cap[afi][safi],
    1482             :                                  PEER_CAP_ORF_PREFIX_RM_ADV);
    1483           0 :                         stream_putc(s, ORF_MODE_RECEIVE);
    1484             :                 }
    1485             :                 number_of_orfs++;
    1486             :         }
    1487             : 
    1488             :         /* Total Number of ORFs. */
    1489           0 :         stream_putc_at(s, numberp, number_of_orfs);
    1490             : 
    1491             :         /* Total ORF Len. */
    1492           0 :         orf_len = stream_get_endp(s) - orfp - 1;
    1493           0 :         stream_putc_at(s, orfp, orf_len);
    1494             : 
    1495             :         /* Total Capability Len. */
    1496           0 :         cap_len = stream_get_endp(s) - capp - 1;
    1497           0 :         ext_opt_params ? stream_putw_at(s, capp, cap_len)
    1498           0 :                        : stream_putc_at(s, capp, cap_len);
    1499           0 : }
    1500             : 
    1501          41 : static void bgp_peer_send_gr_capability(struct stream *s, struct peer *peer,
    1502             :                                         bool ext_opt_params)
    1503             : {
    1504          41 :         int len;
    1505          41 :         iana_afi_t pkt_afi = IANA_AFI_IPV4;
    1506          41 :         afi_t afi;
    1507          41 :         safi_t safi;
    1508          41 :         iana_safi_t pkt_safi = IANA_SAFI_UNICAST;
    1509          41 :         uint32_t restart_time;
    1510          41 :         unsigned long capp = 0;
    1511          41 :         unsigned long rcapp = 0;
    1512             : 
    1513          41 :         if (!CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART)
    1514          41 :             && !CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART_HELPER))
    1515           0 :                 return;
    1516             : 
    1517          41 :         if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
    1518           0 :                 zlog_debug("[BGP_GR] Sending helper Capability for Peer :%s :",
    1519             :                            peer->host);
    1520             : 
    1521          41 :         SET_FLAG(peer->cap, PEER_CAP_RESTART_ADV);
    1522          41 :         stream_putc(s, BGP_OPEN_OPT_CAP);
    1523          41 :         capp = stream_get_endp(s); /* Set Capability Len Pointer */
    1524           0 :         ext_opt_params ? stream_putw(s, 0)
    1525          41 :                        : stream_putc(s, 0); /* Capability Length */
    1526          41 :         stream_putc(s, CAPABILITY_CODE_RESTART);
    1527             :         /* Set Restart Capability Len Pointer */
    1528          41 :         rcapp = stream_get_endp(s);
    1529          41 :         stream_putc(s, 0);
    1530          41 :         restart_time = peer->bgp->restart_time;
    1531          41 :         if (peer->bgp->t_startup) {
    1532          41 :                 SET_FLAG(restart_time, GRACEFUL_RESTART_R_BIT);
    1533          41 :                 SET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_R_BIT_ADV);
    1534          41 :                 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
    1535           0 :                         zlog_debug("[BGP_GR] Sending R-Bit for peer: %s",
    1536             :                                    peer->host);
    1537             :         }
    1538             : 
    1539          41 :         if (CHECK_FLAG(peer->bgp->flags, BGP_FLAG_GRACEFUL_NOTIFICATION)) {
    1540          41 :                 SET_FLAG(restart_time, GRACEFUL_RESTART_N_BIT);
    1541          41 :                 SET_FLAG(peer->cap, PEER_CAP_GRACEFUL_RESTART_N_BIT_ADV);
    1542          41 :                 if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
    1543           0 :                         zlog_debug("[BGP_GR] Sending N-Bit for peer: %s",
    1544             :                                    peer->host);
    1545             :         }
    1546             : 
    1547          41 :         stream_putw(s, restart_time);
    1548             : 
    1549             :         /* Send address-family specific graceful-restart capability
    1550             :          * only when GR config is present
    1551             :          */
    1552          41 :         if (CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART)) {
    1553           0 :                 if (CHECK_FLAG(peer->bgp->flags, BGP_FLAG_GR_PRESERVE_FWD)
    1554           0 :                     && BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
    1555           0 :                         zlog_debug("[BGP_GR] F bit Set");
    1556             : 
    1557           0 :                 FOREACH_AFI_SAFI (afi, safi) {
    1558           0 :                         if (!peer->afc[afi][safi])
    1559           0 :                                 continue;
    1560             : 
    1561           0 :                         if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
    1562           0 :                                 zlog_debug(
    1563             :                                         "[BGP_GR] Sending GR Capability for AFI :%d :, SAFI :%d:",
    1564             :                                         afi, safi);
    1565             : 
    1566             :                         /* Convert AFI, SAFI to values for
    1567             :                          * packet.
    1568             :                          */
    1569           0 :                         bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi,
    1570             :                                                   &pkt_safi);
    1571           0 :                         stream_putw(s, pkt_afi);
    1572           0 :                         stream_putc(s, pkt_safi);
    1573           0 :                         if (CHECK_FLAG(peer->bgp->flags,
    1574             :                                        BGP_FLAG_GR_PRESERVE_FWD))
    1575           0 :                                 stream_putc(s, GRACEFUL_RESTART_F_BIT);
    1576             :                         else
    1577           0 :                                 stream_putc(s, 0);
    1578             :                 }
    1579             :         }
    1580             : 
    1581             :         /* Total Graceful restart capability Len. */
    1582          41 :         len = stream_get_endp(s) - rcapp - 1;
    1583          41 :         stream_putc_at(s, rcapp, len);
    1584             : 
    1585             :         /* Total Capability Len. */
    1586          41 :         len = stream_get_endp(s) - capp - 1;
    1587           0 :         ext_opt_params ? stream_putw_at(s, capp, len - 1)
    1588          41 :                        : stream_putc_at(s, capp, len);
    1589             : }
    1590             : 
    1591          41 : static void bgp_peer_send_llgr_capability(struct stream *s, struct peer *peer,
    1592             :                                           bool ext_opt_params)
    1593             : {
    1594          41 :         int len;
    1595          41 :         iana_afi_t pkt_afi = IANA_AFI_IPV4;
    1596          41 :         afi_t afi;
    1597          41 :         safi_t safi;
    1598          41 :         iana_safi_t pkt_safi = IANA_SAFI_UNICAST;
    1599          41 :         unsigned long capp = 0;
    1600          41 :         unsigned long rcapp = 0;
    1601             : 
    1602          41 :         if (!CHECK_FLAG(peer->cap, PEER_CAP_RESTART_ADV))
    1603           0 :                 return;
    1604             : 
    1605          41 :         SET_FLAG(peer->cap, PEER_CAP_LLGR_ADV);
    1606             : 
    1607          41 :         stream_putc(s, BGP_OPEN_OPT_CAP);
    1608          41 :         capp = stream_get_endp(s); /* Set Capability Len Pointer */
    1609           0 :         ext_opt_params ? stream_putw(s, 0)
    1610          41 :                        : stream_putc(s, 0); /* Capability Length */
    1611          41 :         stream_putc(s, CAPABILITY_CODE_LLGR);
    1612             : 
    1613          41 :         rcapp = stream_get_endp(s);
    1614          41 :         stream_putc(s, 0);
    1615             : 
    1616        1066 :         FOREACH_AFI_SAFI (afi, safi) {
    1617         861 :                 if (!peer->afc[afi][safi])
    1618         818 :                         continue;
    1619             : 
    1620          43 :                 bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
    1621             : 
    1622          43 :                 stream_putw(s, pkt_afi);
    1623          43 :                 stream_putc(s, pkt_safi);
    1624          43 :                 stream_putc(s, LLGR_F_BIT);
    1625          43 :                 stream_put3(s, peer->bgp->llgr_stale_time);
    1626             : 
    1627          43 :                 SET_FLAG(peer->af_cap[afi][safi], PEER_CAP_LLGR_AF_ADV);
    1628             :         }
    1629             : 
    1630             :         /* Total Long-lived Graceful Restart capability Len. */
    1631          41 :         len = stream_get_endp(s) - rcapp - 1;
    1632          41 :         stream_putc_at(s, rcapp, len);
    1633             : 
    1634             :         /* Total Capability Len. */
    1635          41 :         len = stream_get_endp(s) - capp - 1;
    1636           0 :         ext_opt_params ? stream_putw_at(s, capp, len - 1)
    1637          41 :                        : stream_putc_at(s, capp, len);
    1638             : }
    1639             : 
    1640             : /* Fill in capability open option to the packet. */
    1641          42 : uint16_t bgp_open_capability(struct stream *s, struct peer *peer,
    1642             :                              bool ext_opt_params)
    1643             : {
    1644          42 :         uint16_t len;
    1645          42 :         unsigned long cp, capp, rcapp, eopl = 0;
    1646          42 :         iana_afi_t pkt_afi = IANA_AFI_IPV4;
    1647          42 :         afi_t afi;
    1648          42 :         safi_t safi;
    1649          42 :         iana_safi_t pkt_safi = IANA_SAFI_UNICAST;
    1650          42 :         as_t local_as;
    1651          42 :         uint8_t afi_safi_count = 0;
    1652          42 :         bool adv_addpath_tx = false;
    1653             : 
    1654             :         /* Non-Ext OP Len. */
    1655          42 :         cp = stream_get_endp(s);
    1656          42 :         stream_putc(s, 0);
    1657             : 
    1658          42 :         if (ext_opt_params) {
    1659             :                 /* Non-Ext OP Len. */
    1660           0 :                 stream_putc_at(s, cp, BGP_OPEN_NON_EXT_OPT_LEN);
    1661             : 
    1662             :                 /* Non-Ext OP Type */
    1663           0 :                 stream_putc(s, BGP_OPEN_NON_EXT_OPT_TYPE_EXTENDED_LENGTH);
    1664             : 
    1665             :                 /* Extended Opt. Parm. Length */
    1666           0 :                 eopl = stream_get_endp(s);
    1667           0 :                 stream_putw(s, 0);
    1668             :         }
    1669             : 
    1670             :         /* Do not send capability. */
    1671          42 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN)
    1672          42 :             || CHECK_FLAG(peer->flags, PEER_FLAG_DONT_CAPABILITY))
    1673             :                 return 0;
    1674             : 
    1675             :         /* MP capability for configured AFI, SAFI */
    1676        1025 :         FOREACH_AFI_SAFI (afi, safi) {
    1677         861 :                 if (peer->afc[afi][safi]) {
    1678             :                         /* Convert AFI, SAFI to values for packet. */
    1679          43 :                         bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi,
    1680             :                                                   &pkt_safi);
    1681             : 
    1682          43 :                         peer->afc_adv[afi][safi] = 1;
    1683          43 :                         stream_putc(s, BGP_OPEN_OPT_CAP);
    1684          43 :                         ext_opt_params
    1685           0 :                                 ? stream_putw(s, CAPABILITY_CODE_MP_LEN + 2)
    1686          43 :                                 : stream_putc(s, CAPABILITY_CODE_MP_LEN + 2);
    1687          43 :                         stream_putc(s, CAPABILITY_CODE_MP);
    1688          43 :                         stream_putc(s, CAPABILITY_CODE_MP_LEN);
    1689          43 :                         stream_putw(s, pkt_afi);
    1690          43 :                         stream_putc(s, 0);
    1691          43 :                         stream_putc(s, pkt_safi);
    1692             : 
    1693             :                         /* Extended nexthop capability - currently
    1694             :                          * supporting RFC-5549 for
    1695             :                          * Link-Local peering only
    1696             :                          */
    1697          43 :                         if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE)
    1698           0 :                             && peer->su.sa.sa_family == AF_INET6
    1699           0 :                             && afi == AFI_IP
    1700           0 :                             && (safi == SAFI_UNICAST || safi == SAFI_MPLS_VPN
    1701             :                                 || safi == SAFI_LABELED_UNICAST)) {
    1702             :                                 /* RFC 5549 Extended Next Hop Encoding
    1703             :                                  */
    1704           0 :                                 SET_FLAG(peer->cap, PEER_CAP_ENHE_ADV);
    1705           0 :                                 stream_putc(s, BGP_OPEN_OPT_CAP);
    1706           0 :                                 ext_opt_params
    1707           0 :                                         ? stream_putw(s,
    1708             :                                                       CAPABILITY_CODE_ENHE_LEN
    1709             :                                                               + 2)
    1710           0 :                                         : stream_putc(s,
    1711             :                                                       CAPABILITY_CODE_ENHE_LEN
    1712             :                                                               + 2);
    1713           0 :                                 stream_putc(s, CAPABILITY_CODE_ENHE);
    1714           0 :                                 stream_putc(s, CAPABILITY_CODE_ENHE_LEN);
    1715             : 
    1716           0 :                                 SET_FLAG(peer->af_cap[AFI_IP][safi],
    1717             :                                          PEER_CAP_ENHE_AF_ADV);
    1718           0 :                                 stream_putw(s, pkt_afi);
    1719           0 :                                 stream_putw(s, pkt_safi);
    1720           0 :                                 stream_putw(s, afi_int2iana(AFI_IP6));
    1721             : 
    1722           0 :                                 if (CHECK_FLAG(peer->af_cap[afi][safi],
    1723             :                                                PEER_CAP_ENHE_AF_RCV))
    1724           0 :                                         SET_FLAG(peer->af_cap[afi][safi],
    1725             :                                                  PEER_CAP_ENHE_AF_NEGO);
    1726             :                         }
    1727             :                 }
    1728             :         }
    1729             : 
    1730             :         /* Route refresh. */
    1731          41 :         SET_FLAG(peer->cap, PEER_CAP_REFRESH_ADV);
    1732          41 :         stream_putc(s, BGP_OPEN_OPT_CAP);
    1733           0 :         ext_opt_params ? stream_putw(s, CAPABILITY_CODE_REFRESH_LEN + 2)
    1734          41 :                        : stream_putc(s, CAPABILITY_CODE_REFRESH_LEN + 2);
    1735          41 :         stream_putc(s, CAPABILITY_CODE_REFRESH_OLD);
    1736          41 :         stream_putc(s, CAPABILITY_CODE_REFRESH_LEN);
    1737          41 :         stream_putc(s, BGP_OPEN_OPT_CAP);
    1738           0 :         ext_opt_params ? stream_putw(s, CAPABILITY_CODE_REFRESH_LEN + 2)
    1739          41 :                        : stream_putc(s, CAPABILITY_CODE_REFRESH_LEN + 2);
    1740          41 :         stream_putc(s, CAPABILITY_CODE_REFRESH);
    1741          41 :         stream_putc(s, CAPABILITY_CODE_REFRESH_LEN);
    1742             : 
    1743             :         /* Enhanced Route Refresh. */
    1744          41 :         SET_FLAG(peer->cap, PEER_CAP_ENHANCED_RR_ADV);
    1745          41 :         stream_putc(s, BGP_OPEN_OPT_CAP);
    1746           0 :         ext_opt_params ? stream_putw(s, CAPABILITY_CODE_ENHANCED_LEN + 2)
    1747          41 :                        : stream_putc(s, CAPABILITY_CODE_ENHANCED_LEN + 2);
    1748          41 :         stream_putc(s, CAPABILITY_CODE_ENHANCED_RR);
    1749          41 :         stream_putc(s, CAPABILITY_CODE_ENHANCED_LEN);
    1750             : 
    1751             :         /* AS4 */
    1752          41 :         SET_FLAG(peer->cap, PEER_CAP_AS4_ADV);
    1753          41 :         stream_putc(s, BGP_OPEN_OPT_CAP);
    1754           0 :         ext_opt_params ? stream_putw(s, CAPABILITY_CODE_AS4_LEN + 2)
    1755          41 :                        : stream_putc(s, CAPABILITY_CODE_AS4_LEN + 2);
    1756          41 :         stream_putc(s, CAPABILITY_CODE_AS4);
    1757          41 :         stream_putc(s, CAPABILITY_CODE_AS4_LEN);
    1758          41 :         if (peer->change_local_as)
    1759             :                 local_as = peer->change_local_as;
    1760             :         else
    1761          41 :                 local_as = peer->local_as;
    1762          41 :         stream_putl(s, local_as);
    1763             : 
    1764             :         /* Extended Message Support */
    1765          41 :         SET_FLAG(peer->cap, PEER_CAP_EXTENDED_MESSAGE_ADV);
    1766          41 :         stream_putc(s, BGP_OPEN_OPT_CAP);
    1767           0 :         ext_opt_params ? stream_putw(s, CAPABILITY_CODE_EXT_MESSAGE_LEN + 2)
    1768          41 :                        : stream_putc(s, CAPABILITY_CODE_EXT_MESSAGE_LEN + 2);
    1769          41 :         stream_putc(s, CAPABILITY_CODE_EXT_MESSAGE);
    1770          41 :         stream_putc(s, CAPABILITY_CODE_EXT_MESSAGE_LEN);
    1771             : 
    1772             :         /* Role*/
    1773          41 :         if (peer->local_role != ROLE_UNDEFINED) {
    1774           0 :                 SET_FLAG(peer->cap, PEER_CAP_ROLE_ADV);
    1775           0 :                 stream_putc(s, BGP_OPEN_OPT_CAP);
    1776           0 :                 stream_putc(s, CAPABILITY_CODE_ROLE_LEN + 2);
    1777           0 :                 stream_putc(s, CAPABILITY_CODE_ROLE);
    1778           0 :                 stream_putc(s, CAPABILITY_CODE_ROLE_LEN);
    1779           0 :                 stream_putc(s, peer->local_role);
    1780             :         }
    1781             : 
    1782             :         /* AddPath */
    1783        1025 :         FOREACH_AFI_SAFI (afi, safi) {
    1784         861 :                 if (peer->afc[afi][safi]) {
    1785          43 :                         afi_safi_count++;
    1786             : 
    1787             :                         /* Only advertise addpath TX if a feature that
    1788             :                          * will use it is
    1789             :                          * configured */
    1790          43 :                         if (peer->addpath_type[afi][safi] != BGP_ADDPATH_NONE)
    1791           0 :                                 adv_addpath_tx = true;
    1792             : 
    1793             :                         /* If we have enabled labeled unicast, we MUST check
    1794             :                          * against unicast SAFI because addpath IDs are
    1795             :                          * allocated under unicast SAFI, the same as the RIB
    1796             :                          * is managed in unicast SAFI.
    1797             :                          */
    1798          43 :                         if (safi == SAFI_LABELED_UNICAST)
    1799           0 :                                 if (peer->addpath_type[afi][SAFI_UNICAST] !=
    1800             :                                     BGP_ADDPATH_NONE)
    1801         861 :                                         adv_addpath_tx = true;
    1802             :                 }
    1803             :         }
    1804             : 
    1805          41 :         SET_FLAG(peer->cap, PEER_CAP_ADDPATH_ADV);
    1806          41 :         stream_putc(s, BGP_OPEN_OPT_CAP);
    1807          41 :         ext_opt_params
    1808           0 :                 ? stream_putw(s, (CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count)
    1809           0 :                                          + 2)
    1810          41 :                 : stream_putc(s, (CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count)
    1811          41 :                                          + 2);
    1812          41 :         stream_putc(s, CAPABILITY_CODE_ADDPATH);
    1813          41 :         stream_putc(s, CAPABILITY_CODE_ADDPATH_LEN * afi_safi_count);
    1814             : 
    1815        1066 :         FOREACH_AFI_SAFI (afi, safi) {
    1816         861 :                 if (peer->afc[afi][safi]) {
    1817          43 :                         bool adv_addpath_rx =
    1818          43 :                                 !CHECK_FLAG(peer->af_flags[afi][safi],
    1819             :                                             PEER_FLAG_DISABLE_ADDPATH_RX);
    1820          43 :                         uint8_t flags = 0;
    1821             : 
    1822             :                         /* Convert AFI, SAFI to values for packet. */
    1823          43 :                         bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi,
    1824             :                                                   &pkt_safi);
    1825             : 
    1826          43 :                         stream_putw(s, pkt_afi);
    1827          43 :                         stream_putc(s, pkt_safi);
    1828             : 
    1829          43 :                         if (adv_addpath_rx) {
    1830          43 :                                 SET_FLAG(flags, BGP_ADDPATH_RX);
    1831          43 :                                 SET_FLAG(peer->af_cap[afi][safi],
    1832             :                                          PEER_CAP_ADDPATH_AF_RX_ADV);
    1833             :                         } else {
    1834           0 :                                 UNSET_FLAG(peer->af_cap[afi][safi],
    1835             :                                            PEER_CAP_ADDPATH_AF_RX_ADV);
    1836             :                         }
    1837             : 
    1838          43 :                         if (adv_addpath_tx) {
    1839           0 :                                 SET_FLAG(flags, BGP_ADDPATH_TX);
    1840           0 :                                 SET_FLAG(peer->af_cap[afi][safi],
    1841             :                                          PEER_CAP_ADDPATH_AF_TX_ADV);
    1842           0 :                                 if (safi == SAFI_LABELED_UNICAST)
    1843           0 :                                         SET_FLAG(
    1844             :                                                 peer->af_cap[afi][SAFI_UNICAST],
    1845             :                                                 PEER_CAP_ADDPATH_AF_TX_ADV);
    1846             :                         } else {
    1847          43 :                                 UNSET_FLAG(peer->af_cap[afi][safi],
    1848             :                                            PEER_CAP_ADDPATH_AF_TX_ADV);
    1849             :                         }
    1850             : 
    1851          43 :                         stream_putc(s, flags);
    1852             :                 }
    1853             :         }
    1854             : 
    1855             :         /* ORF capability. */
    1856        1025 :         FOREACH_AFI_SAFI (afi, safi) {
    1857         861 :                 if (CHECK_FLAG(peer->af_flags[afi][safi],
    1858             :                                PEER_FLAG_ORF_PREFIX_SM)
    1859         861 :                     || CHECK_FLAG(peer->af_flags[afi][safi],
    1860             :                                   PEER_FLAG_ORF_PREFIX_RM)) {
    1861           0 :                         bgp_open_capability_orf(s, peer, afi, safi,
    1862             :                                                 CAPABILITY_CODE_ORF_OLD,
    1863             :                                                 ext_opt_params);
    1864           0 :                         bgp_open_capability_orf(s, peer, afi, safi,
    1865             :                                                 CAPABILITY_CODE_ORF,
    1866             :                                                 ext_opt_params);
    1867             :                 }
    1868             :         }
    1869             : 
    1870             :         /* Dynamic capability. */
    1871          41 :         if (CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY)) {
    1872           0 :                 SET_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV);
    1873           0 :                 stream_putc(s, BGP_OPEN_OPT_CAP);
    1874           0 :                 ext_opt_params
    1875           0 :                         ? stream_putw(s, CAPABILITY_CODE_DYNAMIC_LEN + 2)
    1876           0 :                         : stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
    1877           0 :                 stream_putc(s, CAPABILITY_CODE_DYNAMIC_OLD);
    1878           0 :                 stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN);
    1879           0 :                 stream_putc(s, BGP_OPEN_OPT_CAP);
    1880           0 :                 ext_opt_params
    1881           0 :                         ? stream_putw(s, CAPABILITY_CODE_DYNAMIC_LEN + 2)
    1882           0 :                         : stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
    1883           0 :                 stream_putc(s, CAPABILITY_CODE_DYNAMIC);
    1884           0 :                 stream_putc(s, CAPABILITY_CODE_DYNAMIC_LEN);
    1885             :         }
    1886             : 
    1887             :         /* Hostname capability */
    1888          41 :         if (cmd_hostname_get()) {
    1889          41 :                 SET_FLAG(peer->cap, PEER_CAP_HOSTNAME_ADV);
    1890          41 :                 stream_putc(s, BGP_OPEN_OPT_CAP);
    1891          41 :                 rcapp = stream_get_endp(s); /* Ptr to length placeholder */
    1892           0 :                 ext_opt_params ? stream_putw(s, 0)
    1893          41 :                                : stream_putc(s, 0); /* Capability Length */
    1894          41 :                 stream_putc(s, CAPABILITY_CODE_FQDN);
    1895          41 :                 capp = stream_get_endp(s);
    1896          41 :                 stream_putc(s, 0); /* dummy len for now */
    1897          41 :                 len = strlen(cmd_hostname_get());
    1898          41 :                 if (len > BGP_MAX_HOSTNAME)
    1899             :                         len = BGP_MAX_HOSTNAME;
    1900             : 
    1901          41 :                 stream_putc(s, len);
    1902          41 :                 stream_put(s, cmd_hostname_get(), len);
    1903          41 :                 if (cmd_domainname_get()) {
    1904           0 :                         len = strlen(cmd_domainname_get());
    1905           0 :                         if (len > BGP_MAX_HOSTNAME)
    1906             :                                 len = BGP_MAX_HOSTNAME;
    1907             : 
    1908           0 :                         stream_putc(s, len);
    1909           0 :                         stream_put(s, cmd_domainname_get(), len);
    1910             :                 } else
    1911          41 :                         stream_putc(s, 0); /* 0 length */
    1912             : 
    1913             :                 /* Set the lengths straight */
    1914          41 :                 len = stream_get_endp(s) - rcapp - 1;
    1915           0 :                 ext_opt_params ? stream_putw_at(s, rcapp, len - 1)
    1916          41 :                                : stream_putc_at(s, rcapp, len);
    1917             : 
    1918          41 :                 len = stream_get_endp(s) - capp - 1;
    1919          41 :                 stream_putc_at(s, capp, len);
    1920             : 
    1921          41 :                 if (bgp_debug_neighbor_events(peer))
    1922           0 :                         zlog_debug(
    1923             :                                 "%s Sending hostname cap with hn = %s, dn = %s",
    1924             :                                 peer->host, cmd_hostname_get(),
    1925             :                                 cmd_domainname_get());
    1926             :         }
    1927             : 
    1928          41 :         bgp_peer_send_gr_capability(s, peer, ext_opt_params);
    1929          41 :         bgp_peer_send_llgr_capability(s, peer, ext_opt_params);
    1930             : 
    1931             :         /* Total Opt Parm Len. */
    1932          41 :         len = stream_get_endp(s) - cp - 1;
    1933             : 
    1934          41 :         if (ext_opt_params) {
    1935           0 :                 len = stream_get_endp(s) - eopl - 2;
    1936           0 :                 stream_putw_at(s, eopl, len);
    1937             :         } else {
    1938          41 :                 stream_putc_at(s, cp, len);
    1939             :         }
    1940             : 
    1941             :         return len;
    1942             : }

Generated by: LCOV version v1.16-topotato