back to topotato report
topotato coverage report
Current view: top level - bgpd - bgpd.c (source / functions) Hit Total Coverage
Test: test_bgp_as_wide_bgp_identifier.py::TestBGPAsWideBGPIdentifier Lines: 964 3860 25.0 %
Date: 2023-02-24 18:36:46 Functions: 62 209 29.7 %

          Line data    Source code
       1             : /* BGP-4, BGP-4+ daemon program
       2             :  * Copyright (C) 1996, 97, 98, 99, 2000 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 "prefix.h"
      24             : #include "thread.h"
      25             : #include "buffer.h"
      26             : #include "stream.h"
      27             : #include "ringbuf.h"
      28             : #include "command.h"
      29             : #include "sockunion.h"
      30             : #include "sockopt.h"
      31             : #include "network.h"
      32             : #include "memory.h"
      33             : #include "filter.h"
      34             : #include "routemap.h"
      35             : #include "log.h"
      36             : #include "plist.h"
      37             : #include "linklist.h"
      38             : #include "workqueue.h"
      39             : #include "queue.h"
      40             : #include "zclient.h"
      41             : #include "bfd.h"
      42             : #include "hash.h"
      43             : #include "jhash.h"
      44             : #include "table.h"
      45             : #include "lib/json.h"
      46             : #include "lib/sockopt.h"
      47             : #include "frr_pthread.h"
      48             : #include "bitfield.h"
      49             : 
      50             : #include "bgpd/bgpd.h"
      51             : #include "bgpd/bgp_table.h"
      52             : #include "bgpd/bgp_aspath.h"
      53             : #include "bgpd/bgp_route.h"
      54             : #include "bgpd/bgp_dump.h"
      55             : #include "bgpd/bgp_debug.h"
      56             : #include "bgpd/bgp_errors.h"
      57             : #include "bgpd/bgp_community.h"
      58             : #include "bgpd/bgp_community_alias.h"
      59             : #include "bgpd/bgp_conditional_adv.h"
      60             : #include "bgpd/bgp_attr.h"
      61             : #include "bgpd/bgp_regex.h"
      62             : #include "bgpd/bgp_clist.h"
      63             : #include "bgpd/bgp_fsm.h"
      64             : #include "bgpd/bgp_packet.h"
      65             : #include "bgpd/bgp_zebra.h"
      66             : #include "bgpd/bgp_open.h"
      67             : #include "bgpd/bgp_filter.h"
      68             : #include "bgpd/bgp_nexthop.h"
      69             : #include "bgpd/bgp_damp.h"
      70             : #include "bgpd/bgp_mplsvpn.h"
      71             : #ifdef ENABLE_BGP_VNC
      72             : #include "bgpd/rfapi/bgp_rfapi_cfg.h"
      73             : #include "bgpd/rfapi/rfapi_backend.h"
      74             : #endif
      75             : #include "bgpd/bgp_evpn.h"
      76             : #include "bgpd/bgp_advertise.h"
      77             : #include "bgpd/bgp_network.h"
      78             : #include "bgpd/bgp_vty.h"
      79             : #include "bgpd/bgp_mpath.h"
      80             : #include "bgpd/bgp_nht.h"
      81             : #include "bgpd/bgp_updgrp.h"
      82             : #include "bgpd/bgp_bfd.h"
      83             : #include "bgpd/bgp_memory.h"
      84             : #include "bgpd/bgp_evpn_vty.h"
      85             : #include "bgpd/bgp_keepalives.h"
      86             : #include "bgpd/bgp_io.h"
      87             : #include "bgpd/bgp_ecommunity.h"
      88             : #include "bgpd/bgp_flowspec.h"
      89             : #include "bgpd/bgp_labelpool.h"
      90             : #include "bgpd/bgp_pbr.h"
      91             : #include "bgpd/bgp_addpath.h"
      92             : #include "bgpd/bgp_evpn_private.h"
      93             : #include "bgpd/bgp_evpn_mh.h"
      94             : #include "bgpd/bgp_mac.h"
      95             : #include "bgp_trace.h"
      96             : 
      97           9 : DEFINE_MTYPE_STATIC(BGPD, PEER_TX_SHUTDOWN_MSG, "Peer shutdown message (TX)");
      98           9 : DEFINE_MTYPE_STATIC(BGPD, BGP_EVPN_INFO, "BGP EVPN instance information");
      99             : DEFINE_QOBJ_TYPE(bgp_master);
     100             : DEFINE_QOBJ_TYPE(bgp);
     101             : DEFINE_QOBJ_TYPE(peer);
     102           3 : DEFINE_HOOK(bgp_inst_delete, (struct bgp *bgp), (bgp));
     103             : 
     104             : /* BGP process wide configuration.  */
     105             : static struct bgp_master bgp_master;
     106             : 
     107             : /* BGP process wide configuration pointer to export.  */
     108             : struct bgp_master *bm;
     109             : 
     110             : /* BGP community-list.  */
     111             : struct community_list_handler *bgp_clist;
     112             : 
     113             : unsigned int multipath_num = MULTIPATH_NUM;
     114             : 
     115             : /* Number of bgp instances configured for suppress fib config */
     116             : unsigned int bgp_suppress_fib_count;
     117             : 
     118             : static void bgp_if_finish(struct bgp *bgp);
     119             : static void peer_drop_dynamic_neighbor(struct peer *peer);
     120             : 
     121             : extern struct zclient *zclient;
     122             : 
     123             : /* handle main socket creation or deletion */
     124           6 : static int bgp_check_main_socket(bool create, struct bgp *bgp)
     125             : {
     126           6 :         static int bgp_server_main_created;
     127           6 :         struct listnode *node;
     128           6 :         char *address;
     129             : 
     130           6 :         if (create) {
     131           3 :                 if (bgp_server_main_created)
     132             :                         return 0;
     133           3 :                 if (list_isempty(bm->addresses)) {
     134           3 :                         if (bgp_socket(bgp, bm->port, NULL) < 0)
     135             :                                 return BGP_ERR_INVALID_VALUE;
     136             :                 } else {
     137           0 :                         for (ALL_LIST_ELEMENTS_RO(bm->addresses, node, address))
     138           0 :                                 if (bgp_socket(bgp, bm->port, address) < 0)
     139             :                                         return BGP_ERR_INVALID_VALUE;
     140             :                 }
     141           3 :                 bgp_server_main_created = 1;
     142           3 :                 return 0;
     143             :         }
     144           3 :         if (!bgp_server_main_created)
     145             :                 return 0;
     146           3 :         bgp_close();
     147           3 :         bgp_server_main_created = 0;
     148           3 :         return 0;
     149             : }
     150             : 
     151           0 : void bgp_session_reset(struct peer *peer)
     152             : {
     153           0 :         if (peer->doppelganger && (peer->doppelganger->status != Deleted)
     154           0 :             && !(CHECK_FLAG(peer->doppelganger->flags, PEER_FLAG_CONFIG_NODE)))
     155           0 :                 peer_delete(peer->doppelganger);
     156             : 
     157           0 :         BGP_EVENT_ADD(peer, BGP_Stop);
     158           0 : }
     159             : 
     160             : /*
     161             :  * During session reset, we may delete the doppelganger peer, which would
     162             :  * be the next node to the current node. If the session reset was invoked
     163             :  * during walk of peer list, we would end up accessing the freed next
     164             :  * node. This function moves the next node along.
     165             :  */
     166           0 : static void bgp_session_reset_safe(struct peer *peer, struct listnode **nnode)
     167             : {
     168           0 :         struct listnode *n;
     169           0 :         struct peer *npeer;
     170             : 
     171           0 :         n = (nnode) ? *nnode : NULL;
     172           0 :         npeer = (n) ? listgetdata(n) : NULL;
     173             : 
     174           0 :         if (peer->doppelganger && (peer->doppelganger->status != Deleted)
     175           0 :             && !(CHECK_FLAG(peer->doppelganger->flags,
     176             :                             PEER_FLAG_CONFIG_NODE))) {
     177           0 :                 if (peer->doppelganger == npeer)
     178             :                         /* nnode and *nnode are confirmed to be non-NULL here */
     179           0 :                         *nnode = (*nnode)->next;
     180           0 :                 peer_delete(peer->doppelganger);
     181             :         }
     182             : 
     183           0 :         BGP_EVENT_ADD(peer, BGP_Stop);
     184           0 : }
     185             : 
     186             : /* BGP global flag manipulation.  */
     187           0 : int bgp_option_set(int flag)
     188             : {
     189           0 :         switch (flag) {
     190           0 :         case BGP_OPT_NO_FIB:
     191             :         case BGP_OPT_NO_LISTEN:
     192             :         case BGP_OPT_NO_ZEBRA:
     193           0 :                 SET_FLAG(bm->options, flag);
     194           0 :                 break;
     195             :         default:
     196             :                 return BGP_ERR_INVALID_FLAG;
     197             :         }
     198           0 :         return 0;
     199             : }
     200             : 
     201           0 : int bgp_option_unset(int flag)
     202             : {
     203           0 :         switch (flag) {
     204             :         /* Fall through.  */
     205           0 :         case BGP_OPT_NO_ZEBRA:
     206             :         case BGP_OPT_NO_FIB:
     207           0 :                 UNSET_FLAG(bm->options, flag);
     208           0 :                 break;
     209             :         default:
     210             :                 return BGP_ERR_INVALID_FLAG;
     211             :         }
     212           0 :         return 0;
     213             : }
     214             : 
     215           9 : int bgp_option_check(int flag)
     216             : {
     217           9 :         return CHECK_FLAG(bm->options, flag);
     218             : }
     219             : 
     220             : /* set the bgp no-rib option during runtime and remove installed routes */
     221           0 : void bgp_option_norib_set_runtime(void)
     222             : {
     223           0 :         struct bgp *bgp;
     224           0 :         struct listnode *node;
     225           0 :         afi_t afi;
     226           0 :         safi_t safi;
     227             : 
     228           0 :         if (bgp_option_check(BGP_OPT_NO_FIB))
     229             :                 return;
     230             : 
     231           0 :         bgp_option_set(BGP_OPT_NO_FIB);
     232             : 
     233           0 :         zlog_info("Disabled BGP route installation to RIB (Zebra)");
     234             : 
     235           0 :         for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
     236           0 :                 FOREACH_AFI_SAFI (afi, safi) {
     237             :                         /*
     238             :                          * Stop a crash, more work is needed
     239             :                          * here to properly add/remove these types of
     240             :                          * routes from zebra.
     241             :                          */
     242           0 :                         if (!bgp_fibupd_safi(safi))
     243           0 :                                 continue;
     244             : 
     245           0 :                         bgp_zebra_withdraw_table_all_subtypes(bgp, afi, safi);
     246             :                 }
     247             :         }
     248             : 
     249           0 :         zlog_info("All routes have been withdrawn from RIB (Zebra)");
     250             : }
     251             : 
     252             : /* unset the bgp no-rib option during runtime and announce routes to Zebra */
     253           0 : void bgp_option_norib_unset_runtime(void)
     254             : {
     255           0 :         struct bgp *bgp;
     256           0 :         struct listnode *node;
     257           0 :         afi_t afi;
     258           0 :         safi_t safi;
     259             : 
     260           0 :         if (!bgp_option_check(BGP_OPT_NO_FIB))
     261             :                 return;
     262             : 
     263           0 :         bgp_option_unset(BGP_OPT_NO_FIB);
     264             : 
     265           0 :         zlog_info("Enabled BGP route installation to RIB (Zebra)");
     266             : 
     267           0 :         for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
     268           0 :                 FOREACH_AFI_SAFI (afi, safi) {
     269             :                         /*
     270             :                          * Stop a crash, more work is needed
     271             :                          * here to properly add/remove these types
     272             :                          * of routes from zebra
     273             :                          */
     274           0 :                         if (!bgp_fibupd_safi(safi))
     275           0 :                                 continue;
     276             : 
     277           0 :                         bgp_zebra_announce_table_all_subtypes(bgp, afi, safi);
     278             :                 }
     279             :         }
     280             : 
     281           0 :         zlog_info("All routes have been installed in RIB (Zebra)");
     282             : }
     283             : 
     284             : /* Internal function to set BGP structure configureation flag.  */
     285           0 : static void bgp_config_set(struct bgp *bgp, int config)
     286             : {
     287           0 :         SET_FLAG(bgp->config, config);
     288             : }
     289             : 
     290           0 : static void bgp_config_unset(struct bgp *bgp, int config)
     291             : {
     292           0 :         UNSET_FLAG(bgp->config, config);
     293             : }
     294             : 
     295           4 : static int bgp_config_check(struct bgp *bgp, int config)
     296             : {
     297           4 :         return CHECK_FLAG(bgp->config, config);
     298             : }
     299             : 
     300             : /* Set BGP router identifier; distinguish between explicit config and other
     301             :  * cases.
     302             :  */
     303           6 : static int bgp_router_id_set(struct bgp *bgp, const struct in_addr *id,
     304             :                              bool is_config)
     305             : {
     306           6 :         struct peer *peer;
     307           6 :         struct listnode *node, *nnode;
     308             : 
     309           6 :         if (IPV4_ADDR_SAME(&bgp->router_id, id))
     310             :                 return 0;
     311             : 
     312             :         /* EVPN uses router id in RD, withdraw them */
     313           3 :         if (is_evpn_enabled())
     314           0 :                 bgp_evpn_handle_router_id_update(bgp, true);
     315             : 
     316           3 :         vpn_handle_router_id_update(bgp, true, is_config);
     317             : 
     318           3 :         IPV4_ADDR_COPY(&bgp->router_id, id);
     319             : 
     320             :         /* Set all peer's local identifier with this value. */
     321           6 :         for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
     322           0 :                 IPV4_ADDR_COPY(&peer->local_id, id);
     323             : 
     324           0 :                 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
     325           0 :                         peer->last_reset = PEER_DOWN_RID_CHANGE;
     326           0 :                         bgp_notify_send(peer, BGP_NOTIFY_CEASE,
     327             :                                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
     328             :                 }
     329             :         }
     330             : 
     331             :         /* EVPN uses router id in RD, update them */
     332           3 :         if (is_evpn_enabled())
     333           0 :                 bgp_evpn_handle_router_id_update(bgp, false);
     334             : 
     335           3 :         vpn_handle_router_id_update(bgp, false, is_config);
     336             : 
     337           3 :         return 0;
     338             : }
     339             : 
     340           5 : void bgp_router_id_zebra_bump(vrf_id_t vrf_id, const struct prefix *router_id)
     341             : {
     342           5 :         struct listnode *node, *nnode;
     343           5 :         struct bgp *bgp;
     344           5 :         struct in_addr *addr = NULL;
     345             : 
     346           5 :         if (router_id != NULL)
     347           3 :                 addr = (struct in_addr *)&(router_id->u.prefix4);
     348             : 
     349           5 :         if (vrf_id == VRF_DEFAULT) {
     350             :                 /* Router-id change for default VRF has to also update all
     351             :                  * views. */
     352          15 :                 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
     353           5 :                         if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
     354           0 :                                 continue;
     355             : 
     356           5 :                         if (addr)
     357           3 :                                 bgp->router_id_zebra = *addr;
     358             :                         else
     359           2 :                                 addr = &bgp->router_id_zebra;
     360             : 
     361           5 :                         if (!bgp->router_id_static.s_addr) {
     362             :                                 /* Router ID is updated if there are no active
     363             :                                  * peer sessions
     364             :                                  */
     365           0 :                                 if (bgp->established_peers == 0) {
     366           0 :                                         if (BGP_DEBUG(zebra, ZEBRA))
     367           0 :                                                 zlog_debug(
     368             :                                                         "RID change : vrf %s(%u), RTR ID %pI4",
     369             :                                                         bgp->name_pretty,
     370             :                                                         bgp->vrf_id, addr);
     371             :                                         /*
     372             :                                          * if old router-id was 0x0, set flag
     373             :                                          * to use this new value
     374             :                                          */
     375           0 :                                         bgp_router_id_set(bgp, addr,
     376           0 :                                                           (bgp->router_id.s_addr
     377             :                                                            == INADDR_ANY)
     378             :                                                                   ? true
     379             :                                                                   : false);
     380             :                                 }
     381             :                         }
     382             :                 }
     383             :         } else {
     384           5 :                 bgp = bgp_lookup_by_vrf_id(vrf_id);
     385           0 :                 if (bgp) {
     386           0 :                         if (addr)
     387           0 :                                 bgp->router_id_zebra = *addr;
     388             :                         else
     389           0 :                                 addr = &bgp->router_id_zebra;
     390             : 
     391           0 :                         if (!bgp->router_id_static.s_addr) {
     392             :                                 /* Router ID is updated if there are no active
     393             :                                  * peer sessions
     394             :                                  */
     395           0 :                                 if (bgp->established_peers == 0) {
     396           0 :                                         if (BGP_DEBUG(zebra, ZEBRA))
     397           0 :                                                 zlog_debug(
     398             :                                                         "RID change : vrf %s(%u), RTR ID %pI4",
     399             :                                                         bgp->name_pretty,
     400             :                                                         bgp->vrf_id, addr);
     401             :                                         /*
     402             :                                          * if old router-id was 0x0, set flag
     403             :                                          * to use this new value
     404             :                                          */
     405           0 :                                         bgp_router_id_set(bgp, addr,
     406           0 :                                                           (bgp->router_id.s_addr
     407             :                                                            == INADDR_ANY)
     408             :                                                                   ? true
     409             :                                                                   : false);
     410             :                                 }
     411             :                         }
     412             : 
     413             :                 }
     414             :         }
     415           5 : }
     416             : 
     417           3 : void bgp_router_id_static_set(struct bgp *bgp, struct in_addr id)
     418             : {
     419           3 :         bgp->router_id_static = id;
     420           3 :         bgp_router_id_set(bgp,
     421           3 :                           id.s_addr != INADDR_ANY ? &id : &bgp->router_id_zebra,
     422             :                           true /* is config */);
     423           3 : }
     424             : 
     425           0 : void bm_wait_for_fib_set(bool set)
     426             : {
     427           0 :         bool send_msg = false;
     428             : 
     429           0 :         if (bm->wait_for_fib == set)
     430             :                 return;
     431             : 
     432           0 :         bm->wait_for_fib = set;
     433           0 :         if (set) {
     434           0 :                 if (bgp_suppress_fib_count == 0)
     435           0 :                         send_msg = true;
     436           0 :                 bgp_suppress_fib_count++;
     437             :         } else {
     438           0 :                 bgp_suppress_fib_count--;
     439           0 :                 if (bgp_suppress_fib_count == 0)
     440             :                         send_msg = true;
     441             :         }
     442             : 
     443           0 :         if (send_msg && zclient)
     444           0 :                 zebra_route_notify_send(ZEBRA_ROUTE_NOTIFY_REQUEST,
     445             :                                         zclient, set);
     446             : }
     447             : 
     448             : /* Set the suppress fib pending for the bgp configuration */
     449           0 : void bgp_suppress_fib_pending_set(struct bgp *bgp, bool set)
     450             : {
     451           0 :         bool send_msg = false;
     452             : 
     453           0 :         if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
     454             :                 return;
     455             : 
     456           0 :         if (set) {
     457           0 :                 SET_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_FIB_PENDING);
     458             :                 /* Send msg to zebra for the first instance of bgp enabled
     459             :                  * with suppress fib
     460             :                  */
     461           0 :                 if (bgp_suppress_fib_count == 0)
     462           0 :                         send_msg = true;
     463           0 :                 bgp_suppress_fib_count++;
     464             :         } else {
     465           0 :                 UNSET_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_FIB_PENDING);
     466           0 :                 bgp_suppress_fib_count--;
     467             : 
     468             :                 /* Send msg to zebra if there are no instances enabled
     469             :                  * with suppress fib
     470             :                  */
     471           0 :                 if (bgp_suppress_fib_count == 0)
     472             :                         send_msg = true;
     473             :         }
     474             :         /* Send route notify request to RIB */
     475           0 :         if (send_msg) {
     476           0 :                 if (BGP_DEBUG(zebra, ZEBRA))
     477           0 :                         zlog_debug("Sending ZEBRA_ROUTE_NOTIFY_REQUEST");
     478             : 
     479           0 :                 if (zclient)
     480           0 :                         zebra_route_notify_send(ZEBRA_ROUTE_NOTIFY_REQUEST,
     481             :                                         zclient, set);
     482             :         }
     483             : }
     484             : 
     485             : /* BGP's cluster-id control. */
     486           0 : void bgp_cluster_id_set(struct bgp *bgp, struct in_addr *cluster_id)
     487             : {
     488           0 :         struct peer *peer;
     489           0 :         struct listnode *node, *nnode;
     490             : 
     491           0 :         if (bgp_config_check(bgp, BGP_CONFIG_CLUSTER_ID)
     492           0 :             && IPV4_ADDR_SAME(&bgp->cluster_id, cluster_id))
     493             :                 return;
     494             : 
     495           0 :         IPV4_ADDR_COPY(&bgp->cluster_id, cluster_id);
     496           0 :         bgp_config_set(bgp, BGP_CONFIG_CLUSTER_ID);
     497             : 
     498             :         /* Clear all IBGP peer. */
     499           0 :         for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
     500           0 :                 if (peer->sort != BGP_PEER_IBGP)
     501           0 :                         continue;
     502             : 
     503           0 :                 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
     504           0 :                         peer->last_reset = PEER_DOWN_CLID_CHANGE;
     505           0 :                         bgp_notify_send(peer, BGP_NOTIFY_CEASE,
     506             :                                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
     507             :                 }
     508             :         }
     509             : }
     510             : 
     511           0 : void bgp_cluster_id_unset(struct bgp *bgp)
     512             : {
     513           0 :         struct peer *peer;
     514           0 :         struct listnode *node, *nnode;
     515             : 
     516           0 :         if (!bgp_config_check(bgp, BGP_CONFIG_CLUSTER_ID))
     517             :                 return;
     518             : 
     519           0 :         bgp->cluster_id.s_addr = 0;
     520           0 :         bgp_config_unset(bgp, BGP_CONFIG_CLUSTER_ID);
     521             : 
     522             :         /* Clear all IBGP peer. */
     523           0 :         for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
     524           0 :                 if (peer->sort != BGP_PEER_IBGP)
     525           0 :                         continue;
     526             : 
     527           0 :                 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
     528           0 :                         peer->last_reset = PEER_DOWN_CLID_CHANGE;
     529           0 :                         bgp_notify_send(peer, BGP_NOTIFY_CEASE,
     530             :                                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
     531             :                 }
     532             :         }
     533             : }
     534             : 
     535             : /* BGP timer configuration.  */
     536           3 : void bgp_timers_set(struct bgp *bgp, uint32_t keepalive, uint32_t holdtime,
     537             :                     uint32_t connect_retry, uint32_t delayopen)
     538             : {
     539           3 :         bgp->default_keepalive =
     540           3 :                 (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
     541           3 :         bgp->default_holdtime = holdtime;
     542           3 :         bgp->default_connect_retry = connect_retry;
     543           3 :         bgp->default_delayopen = delayopen;
     544           3 : }
     545             : 
     546             : /* mostly for completeness - CLI uses its own defaults */
     547           3 : void bgp_timers_unset(struct bgp *bgp)
     548             : {
     549           3 :         bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
     550           3 :         bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
     551           3 :         bgp->default_connect_retry = BGP_DEFAULT_CONNECT_RETRY;
     552           3 :         bgp->default_delayopen = BGP_DEFAULT_DELAYOPEN;
     553           0 : }
     554             : 
     555           0 : void bgp_tcp_keepalive_set(struct bgp *bgp, uint16_t keepalive_idle,
     556             :                            uint16_t keepalive_intvl, uint16_t keepalive_probes)
     557             : {
     558           0 :         bgp->tcp_keepalive_idle = keepalive_idle;
     559           0 :         bgp->tcp_keepalive_intvl = keepalive_intvl;
     560           0 :         bgp->tcp_keepalive_probes = keepalive_probes;
     561           0 : }
     562             : 
     563           3 : void bgp_tcp_keepalive_unset(struct bgp *bgp)
     564             : {
     565           3 :         bgp->tcp_keepalive_idle = 0;
     566           3 :         bgp->tcp_keepalive_intvl = 0;
     567           3 :         bgp->tcp_keepalive_probes = 0;
     568           0 : }
     569             : 
     570             : /* BGP confederation configuration.  */
     571           0 : void bgp_confederation_id_set(struct bgp *bgp, as_t as)
     572             : {
     573           0 :         struct peer *peer;
     574           0 :         struct listnode *node, *nnode;
     575           0 :         int already_confed;
     576             : 
     577           0 :         if (as == 0)
     578             :                 return;
     579             : 
     580             :         /* Remember - were we doing confederation before? */
     581           0 :         already_confed = bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION);
     582           0 :         bgp->confed_id = as;
     583           0 :         bgp_config_set(bgp, BGP_CONFIG_CONFEDERATION);
     584             : 
     585             :         /* If we were doing confederation already, this is just an external
     586             :            AS change.  Just Reset EBGP sessions, not CONFED sessions.  If we
     587             :            were not doing confederation before, reset all EBGP sessions.  */
     588           0 :         for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
     589           0 :                 enum bgp_peer_sort ptype = peer_sort(peer);
     590             : 
     591             :                 /* We're looking for peers who's AS is not local or part of our
     592             :                    confederation.  */
     593           0 :                 if (already_confed) {
     594           0 :                         if (ptype == BGP_PEER_EBGP) {
     595           0 :                                 peer->local_as = as;
     596           0 :                                 if (BGP_IS_VALID_STATE_FOR_NOTIF(
     597             :                                             peer->status)) {
     598           0 :                                         peer->last_reset =
     599             :                                                 PEER_DOWN_CONFED_ID_CHANGE;
     600           0 :                                         bgp_notify_send(
     601             :                                                 peer, BGP_NOTIFY_CEASE,
     602             :                                                 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
     603             :                                 } else
     604           0 :                                         bgp_session_reset_safe(peer, &nnode);
     605             :                         }
     606             :                 } else {
     607             :                         /* Not doign confederation before, so reset every
     608             :                            non-local
     609             :                            session */
     610           0 :                         if (ptype != BGP_PEER_IBGP) {
     611             :                                 /* Reset the local_as to be our EBGP one */
     612           0 :                                 if (ptype == BGP_PEER_EBGP)
     613           0 :                                         peer->local_as = as;
     614           0 :                                 if (BGP_IS_VALID_STATE_FOR_NOTIF(
     615             :                                             peer->status)) {
     616           0 :                                         peer->last_reset =
     617             :                                                 PEER_DOWN_CONFED_ID_CHANGE;
     618           0 :                                         bgp_notify_send(
     619             :                                                 peer, BGP_NOTIFY_CEASE,
     620             :                                                 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
     621             :                                 } else
     622           0 :                                         bgp_session_reset_safe(peer, &nnode);
     623             :                         }
     624             :                 }
     625             :         }
     626             :         return;
     627             : }
     628             : 
     629           0 : void bgp_confederation_id_unset(struct bgp *bgp)
     630             : {
     631           0 :         struct peer *peer;
     632           0 :         struct listnode *node, *nnode;
     633             : 
     634           0 :         bgp->confed_id = 0;
     635           0 :         bgp_config_unset(bgp, BGP_CONFIG_CONFEDERATION);
     636             : 
     637           0 :         for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
     638             :                 /* We're looking for peers who's AS is not local */
     639           0 :                 if (peer_sort(peer) != BGP_PEER_IBGP) {
     640           0 :                         peer->local_as = bgp->as;
     641           0 :                         if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
     642           0 :                                 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
     643           0 :                                 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
     644             :                                                 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
     645             :                         }
     646             : 
     647             :                         else
     648           0 :                                 bgp_session_reset_safe(peer, &nnode);
     649             :                 }
     650             :         }
     651           0 : }
     652             : 
     653             : /* Is an AS part of the confed or not? */
     654           0 : bool bgp_confederation_peers_check(struct bgp *bgp, as_t as)
     655             : {
     656           0 :         int i;
     657             : 
     658           0 :         if (!bgp)
     659             :                 return false;
     660             : 
     661           0 :         for (i = 0; i < bgp->confed_peers_cnt; i++)
     662           0 :                 if (bgp->confed_peers[i] == as)
     663             :                         return true;
     664             : 
     665             :         return false;
     666             : }
     667             : 
     668             : /* Add an AS to the confederation set.  */
     669           0 : void bgp_confederation_peers_add(struct bgp *bgp, as_t as)
     670             : {
     671           0 :         struct peer *peer;
     672           0 :         struct listnode *node, *nnode;
     673             : 
     674           0 :         if (!bgp)
     675           0 :                 return;
     676             : 
     677           0 :         if (bgp_confederation_peers_check(bgp, as))
     678             :                 return;
     679             : 
     680           0 :         bgp->confed_peers =
     681           0 :                 XREALLOC(MTYPE_BGP_CONFED_LIST, bgp->confed_peers,
     682             :                          (bgp->confed_peers_cnt + 1) * sizeof(as_t));
     683             : 
     684           0 :         bgp->confed_peers[bgp->confed_peers_cnt] = as;
     685           0 :         bgp->confed_peers_cnt++;
     686             : 
     687           0 :         if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION)) {
     688           0 :                 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
     689           0 :                         if (peer->as == as) {
     690           0 :                                 peer->local_as = bgp->as;
     691           0 :                                 (void)peer_sort(peer);
     692           0 :                                 if (BGP_IS_VALID_STATE_FOR_NOTIF(
     693             :                                             peer->status)) {
     694           0 :                                         peer->last_reset =
     695             :                                                 PEER_DOWN_CONFED_PEER_CHANGE;
     696           0 :                                         bgp_notify_send(
     697             :                                                 peer, BGP_NOTIFY_CEASE,
     698             :                                                 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
     699             :                                 } else
     700           0 :                                         bgp_session_reset_safe(peer, &nnode);
     701             :                         }
     702             :                 }
     703             :         }
     704             : }
     705             : 
     706             : /* Delete an AS from the confederation set.  */
     707           0 : void bgp_confederation_peers_remove(struct bgp *bgp, as_t as)
     708             : {
     709           0 :         int i;
     710           0 :         int j;
     711           0 :         struct peer *peer;
     712           0 :         struct listnode *node, *nnode;
     713             : 
     714           0 :         if (!bgp)
     715           0 :                 return;
     716             : 
     717           0 :         if (!bgp_confederation_peers_check(bgp, as))
     718             :                 return;
     719             : 
     720           0 :         for (i = 0; i < bgp->confed_peers_cnt; i++)
     721           0 :                 if (bgp->confed_peers[i] == as)
     722           0 :                         for (j = i + 1; j < bgp->confed_peers_cnt; j++)
     723           0 :                                 bgp->confed_peers[j - 1] = bgp->confed_peers[j];
     724             : 
     725           0 :         bgp->confed_peers_cnt--;
     726             : 
     727           0 :         if (bgp->confed_peers_cnt == 0) {
     728           0 :                 if (bgp->confed_peers)
     729           0 :                         XFREE(MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
     730           0 :                 bgp->confed_peers = NULL;
     731             :         } else
     732           0 :                 bgp->confed_peers =
     733           0 :                         XREALLOC(MTYPE_BGP_CONFED_LIST, bgp->confed_peers,
     734             :                                  bgp->confed_peers_cnt * sizeof(as_t));
     735             : 
     736             :         /* Now reset any peer who's remote AS has just been removed from the
     737             :            CONFED */
     738           0 :         if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION)) {
     739           0 :                 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
     740           0 :                         if (peer->as == as) {
     741           0 :                                 peer->local_as = bgp->confed_id;
     742           0 :                                 (void)peer_sort(peer);
     743           0 :                                 if (BGP_IS_VALID_STATE_FOR_NOTIF(
     744             :                                             peer->status)) {
     745           0 :                                         peer->last_reset =
     746             :                                                 PEER_DOWN_CONFED_PEER_CHANGE;
     747           0 :                                         bgp_notify_send(
     748             :                                                 peer, BGP_NOTIFY_CEASE,
     749             :                                                 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
     750             :                                 } else
     751           0 :                                         bgp_session_reset_safe(peer, &nnode);
     752             :                         }
     753             :                 }
     754             :         }
     755             : }
     756             : 
     757             : /* Local preference configuration.  */
     758           0 : void bgp_default_local_preference_set(struct bgp *bgp, uint32_t local_pref)
     759             : {
     760           0 :         if (!bgp)
     761             :                 return;
     762             : 
     763           0 :         bgp->default_local_pref = local_pref;
     764             : }
     765             : 
     766           0 : void bgp_default_local_preference_unset(struct bgp *bgp)
     767             : {
     768           0 :         if (!bgp)
     769             :                 return;
     770             : 
     771           0 :         bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
     772             : }
     773             : 
     774             : /* Local preference configuration.  */
     775           0 : void bgp_default_subgroup_pkt_queue_max_set(struct bgp *bgp,
     776             :                                             uint32_t queue_size)
     777             : {
     778           0 :         if (!bgp)
     779             :                 return;
     780             : 
     781           0 :         bgp->default_subgroup_pkt_queue_max = queue_size;
     782             : }
     783             : 
     784           0 : void bgp_default_subgroup_pkt_queue_max_unset(struct bgp *bgp)
     785             : {
     786           0 :         if (!bgp)
     787             :                 return;
     788           0 :         bgp->default_subgroup_pkt_queue_max =
     789             :                 BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX;
     790             : }
     791             : 
     792             : /* Listen limit configuration.  */
     793           0 : void bgp_listen_limit_set(struct bgp *bgp, int listen_limit)
     794             : {
     795           0 :         if (!bgp)
     796             :                 return;
     797             : 
     798           0 :         bgp->dynamic_neighbors_limit = listen_limit;
     799             : }
     800             : 
     801           0 : void bgp_listen_limit_unset(struct bgp *bgp)
     802             : {
     803           0 :         if (!bgp)
     804             :                 return;
     805             : 
     806           0 :         bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT;
     807             : }
     808             : 
     809           6 : int bgp_map_afi_safi_iana2int(iana_afi_t pkt_afi, iana_safi_t pkt_safi,
     810             :                               afi_t *afi, safi_t *safi)
     811             : {
     812             :         /* Map from IANA values to internal values, return error if
     813             :          * values are unrecognized.
     814             :          */
     815           6 :         *afi = afi_iana2int(pkt_afi);
     816           6 :         *safi = safi_iana2int(pkt_safi);
     817           6 :         if (*afi == AFI_MAX || *safi == SAFI_MAX)
     818           0 :                 return -1;
     819             : 
     820             :         return 0;
     821             : }
     822             : 
     823          12 : int bgp_map_afi_safi_int2iana(afi_t afi, safi_t safi, iana_afi_t *pkt_afi,
     824             :                               iana_safi_t *pkt_safi)
     825             : {
     826             :         /* Map from internal values to IANA values, return error if
     827             :          * internal values are bad (unexpected).
     828             :          */
     829          12 :         if (afi == AFI_MAX || safi == SAFI_MAX)
     830             :                 return -1;
     831          12 :         *pkt_afi = afi_int2iana(afi);
     832          12 :         *pkt_safi = safi_int2iana(safi);
     833          12 :         return 0;
     834             : }
     835             : 
     836           6 : struct peer_af *peer_af_create(struct peer *peer, afi_t afi, safi_t safi)
     837             : {
     838           6 :         struct peer_af *af;
     839           6 :         int afid;
     840           6 :         struct bgp *bgp;
     841             : 
     842           6 :         if (!peer)
     843             :                 return NULL;
     844             : 
     845           6 :         afid = afindex(afi, safi);
     846           6 :         if (afid >= BGP_AF_MAX)
     847             :                 return NULL;
     848             : 
     849           6 :         bgp = peer->bgp;
     850           6 :         assert(peer->peer_af_array[afid] == NULL);
     851             : 
     852             :         /* Allocate new peer af */
     853           6 :         af = XCALLOC(MTYPE_BGP_PEER_AF, sizeof(struct peer_af));
     854             : 
     855           6 :         peer->peer_af_array[afid] = af;
     856           6 :         af->afi = afi;
     857           6 :         af->safi = safi;
     858           6 :         af->afid = afid;
     859           6 :         af->peer = peer;
     860           6 :         bgp->af_peer_count[afi][safi]++;
     861             : 
     862           6 :         return af;
     863             : }
     864             : 
     865           9 : struct peer_af *peer_af_find(struct peer *peer, afi_t afi, safi_t safi)
     866             : {
     867           9 :         int afid;
     868             : 
     869           9 :         if (!peer)
     870             :                 return NULL;
     871             : 
     872           9 :         afid = afindex(afi, safi);
     873           9 :         if (afid >= BGP_AF_MAX)
     874             :                 return NULL;
     875             : 
     876           9 :         return peer->peer_af_array[afid];
     877             : }
     878             : 
     879         189 : int peer_af_delete(struct peer *peer, afi_t afi, safi_t safi)
     880             : {
     881         189 :         struct peer_af *af;
     882         189 :         int afid;
     883         189 :         struct bgp *bgp;
     884             : 
     885         189 :         if (!peer)
     886             :                 return -1;
     887             : 
     888         189 :         afid = afindex(afi, safi);
     889         189 :         if (afid >= BGP_AF_MAX)
     890             :                 return -1;
     891             : 
     892         117 :         af = peer->peer_af_array[afid];
     893         117 :         if (!af)
     894             :                 return -1;
     895             : 
     896           6 :         bgp = peer->bgp;
     897           6 :         bgp_soft_reconfig_table_task_cancel(bgp, bgp->rib[afi][safi], peer);
     898             : 
     899           6 :         bgp_stop_announce_route_timer(af);
     900             : 
     901           6 :         if (PAF_SUBGRP(af)) {
     902           0 :                 if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
     903           0 :                         zlog_debug("u%" PRIu64 ":s%" PRIu64 " remove peer %s",
     904             :                                    af->subgroup->update_group->id,
     905             :                                    af->subgroup->id, peer->host);
     906             :         }
     907             : 
     908             : 
     909           6 :         update_subgroup_remove_peer(af->subgroup, af);
     910             : 
     911           6 :         if (bgp->af_peer_count[afi][safi])
     912           6 :                 bgp->af_peer_count[afi][safi]--;
     913             : 
     914           6 :         peer->peer_af_array[afid] = NULL;
     915           6 :         XFREE(MTYPE_BGP_PEER_AF, af);
     916           6 :         return 0;
     917             : }
     918             : 
     919             : /* Peer comparison function for sorting.  */
     920           5 : int peer_cmp(struct peer *p1, struct peer *p2)
     921             : {
     922           5 :         if (p1->group && !p2->group)
     923             :                 return -1;
     924             : 
     925           5 :         if (!p1->group && p2->group)
     926             :                 return 1;
     927             : 
     928           5 :         if (p1->group == p2->group) {
     929           5 :                 if (p1->conf_if && !p2->conf_if)
     930             :                         return -1;
     931             : 
     932           5 :                 if (!p1->conf_if && p2->conf_if)
     933             :                         return 1;
     934             : 
     935           5 :                 if (p1->conf_if && p2->conf_if)
     936           0 :                         return if_cmp_name_func(p1->conf_if, p2->conf_if);
     937             :         } else
     938           0 :                 return strcmp(p1->group->name, p2->group->name);
     939             : 
     940           5 :         return sockunion_cmp(&p1->su, &p2->su);
     941             : }
     942             : 
     943          24 : static unsigned int peer_hash_key_make(const void *p)
     944             : {
     945          24 :         const struct peer *peer = p;
     946          24 :         return sockunion_hash(&peer->su);
     947             : }
     948             : 
     949          16 : static bool peer_hash_same(const void *p1, const void *p2)
     950             : {
     951          16 :         const struct peer *peer1 = p1;
     952          16 :         const struct peer *peer2 = p2;
     953             : 
     954          16 :         return (sockunion_same(&peer1->su, &peer2->su)
     955          16 :                 && CHECK_FLAG(peer1->flags, PEER_FLAG_CONFIG_NODE)
     956          16 :                            == CHECK_FLAG(peer2->flags, PEER_FLAG_CONFIG_NODE));
     957             : }
     958             : 
     959           0 : void peer_flag_inherit(struct peer *peer, uint64_t flag)
     960             : {
     961           0 :         bool group_val;
     962             : 
     963             :         /* Skip if peer is not a peer-group member. */
     964           0 :         if (!peer_group_active(peer))
     965             :                 return;
     966             : 
     967             :         /* Unset override flag to signal inheritance from peer-group. */
     968           0 :         UNSET_FLAG(peer->flags_override, flag);
     969             : 
     970             :         /*
     971             :          * Inherit flag state from peer-group. If the flag of the peer-group is
     972             :          * not being inverted, the peer must inherit the inverse of the current
     973             :          * peer-group flag state.
     974             :          */
     975           0 :         group_val = CHECK_FLAG(peer->group->conf->flags, flag);
     976           0 :         if (!CHECK_FLAG(peer->group->conf->flags_invert, flag)
     977           0 :             && CHECK_FLAG(peer->flags_invert, flag))
     978           0 :                 COND_FLAG(peer->flags, flag, !group_val);
     979             :         else
     980           0 :                 COND_FLAG(peer->flags, flag, group_val);
     981             : }
     982             : 
     983           0 : int peer_af_flag_check(struct peer *peer, afi_t afi, safi_t safi, uint32_t flag)
     984             : {
     985           0 :         return CHECK_FLAG(peer->af_flags[afi][safi], flag);
     986             : }
     987             : 
     988           0 : void peer_af_flag_inherit(struct peer *peer, afi_t afi, safi_t safi,
     989             :                           uint64_t flag)
     990             : {
     991           0 :         bool group_val;
     992             : 
     993             :         /* Skip if peer is not a peer-group member. */
     994           0 :         if (!peer_group_active(peer))
     995             :                 return;
     996             : 
     997             :         /* Unset override flag to signal inheritance from peer-group. */
     998           0 :         UNSET_FLAG(peer->af_flags_override[afi][safi], flag);
     999             : 
    1000             :         /*
    1001             :          * Inherit flag state from peer-group. If the flag of the peer-group is
    1002             :          * not being inverted, the peer must inherit the inverse of the current
    1003             :          * peer-group flag state.
    1004             :          */
    1005           0 :         group_val = CHECK_FLAG(peer->group->conf->af_flags[afi][safi], flag);
    1006           0 :         if (!CHECK_FLAG(peer->group->conf->af_flags_invert[afi][safi], flag)
    1007           0 :             && CHECK_FLAG(peer->af_flags_invert[afi][safi], flag))
    1008           0 :                 COND_FLAG(peer->af_flags[afi][safi], flag, !group_val);
    1009             :         else
    1010           0 :                 COND_FLAG(peer->af_flags[afi][safi], flag, group_val);
    1011             : }
    1012             : 
    1013             : /* Check peer's AS number and determines if this peer is IBGP or EBGP */
    1014           8 : static inline enum bgp_peer_sort peer_calc_sort(struct peer *peer)
    1015             : {
    1016           8 :         struct bgp *bgp;
    1017           8 :         as_t local_as;
    1018             : 
    1019           8 :         bgp = peer->bgp;
    1020             : 
    1021           8 :         if (peer->change_local_as)
    1022             :                 local_as = peer->change_local_as;
    1023             :         else
    1024           8 :                 local_as = peer->local_as;
    1025             : 
    1026             :         /* Peer-group */
    1027           8 :         if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    1028           0 :                 if (peer->as_type == AS_INTERNAL)
    1029             :                         return BGP_PEER_IBGP;
    1030             : 
    1031           0 :                 else if (peer->as_type == AS_EXTERNAL)
    1032             :                         return BGP_PEER_EBGP;
    1033             : 
    1034           0 :                 else if (peer->as_type == AS_SPECIFIED && peer->as) {
    1035           0 :                         assert(bgp);
    1036           0 :                         return (local_as == peer->as ? BGP_PEER_IBGP
    1037           0 :                                                      : BGP_PEER_EBGP);
    1038             :                 }
    1039             : 
    1040             :                 else {
    1041           0 :                         struct peer *peer1;
    1042             : 
    1043           0 :                         assert(peer->group);
    1044           0 :                         peer1 = listnode_head(peer->group->peer);
    1045             : 
    1046           0 :                         if (peer1)
    1047           0 :                                 return peer1->sort;
    1048             :                 }
    1049             :                 return BGP_PEER_INTERNAL;
    1050             :         }
    1051             : 
    1052             :         /* Normal peer */
    1053           8 :         if (bgp && CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
    1054           0 :                 if (local_as == 0)
    1055             :                         return BGP_PEER_INTERNAL;
    1056             : 
    1057           0 :                 if (local_as == peer->as) {
    1058           0 :                         if (bgp->as == bgp->confed_id) {
    1059           0 :                                 if (local_as == bgp->as)
    1060             :                                         return BGP_PEER_IBGP;
    1061             :                                 else
    1062           0 :                                         return BGP_PEER_EBGP;
    1063             :                         } else {
    1064           0 :                                 if (local_as == bgp->confed_id)
    1065             :                                         return BGP_PEER_EBGP;
    1066             :                                 else
    1067           0 :                                         return BGP_PEER_IBGP;
    1068             :                         }
    1069             :                 }
    1070             : 
    1071           0 :                 if (bgp_confederation_peers_check(bgp, peer->as))
    1072             :                         return BGP_PEER_CONFED;
    1073             : 
    1074           0 :                 return BGP_PEER_EBGP;
    1075             :         } else {
    1076           8 :                 if (peer->as_type == AS_UNSPECIFIED) {
    1077             :                         /* check if in peer-group with AS information */
    1078           0 :                         if (peer->group
    1079           0 :                             && (peer->group->conf->as_type != AS_UNSPECIFIED)) {
    1080           0 :                                 if (peer->group->conf->as_type
    1081             :                                     == AS_SPECIFIED) {
    1082           0 :                                         if (local_as == peer->group->conf->as)
    1083             :                                                 return BGP_PEER_IBGP;
    1084             :                                         else
    1085           0 :                                                 return BGP_PEER_EBGP;
    1086           0 :                                 } else if (peer->group->conf->as_type
    1087             :                                            == AS_INTERNAL)
    1088             :                                         return BGP_PEER_IBGP;
    1089             :                                 else
    1090           0 :                                         return BGP_PEER_EBGP;
    1091             :                         }
    1092             :                         /* no AS information anywhere, let caller know */
    1093             :                         return BGP_PEER_UNSPECIFIED;
    1094           8 :                 } else if (peer->as_type != AS_SPECIFIED)
    1095           0 :                         return (peer->as_type == AS_INTERNAL ? BGP_PEER_IBGP
    1096           0 :                                                              : BGP_PEER_EBGP);
    1097             : 
    1098           8 :                 return (local_as == 0 ? BGP_PEER_INTERNAL
    1099           8 :                                       : local_as == peer->as ? BGP_PEER_IBGP
    1100             :                                                              : BGP_PEER_EBGP);
    1101             :         }
    1102             : }
    1103             : 
    1104             : /* Calculate and cache the peer "sort" */
    1105           8 : enum bgp_peer_sort peer_sort(struct peer *peer)
    1106             : {
    1107           0 :         peer->sort = peer_calc_sort(peer);
    1108           0 :         return peer->sort;
    1109             : }
    1110             : 
    1111           0 : enum bgp_peer_sort peer_sort_lookup(struct peer *peer)
    1112             : {
    1113           0 :         return peer->sort;
    1114             : }
    1115             : 
    1116           9 : static void peer_free(struct peer *peer)
    1117             : {
    1118           9 :         afi_t afi;
    1119           9 :         safi_t safi;
    1120             : 
    1121           9 :         assert(peer->status == Deleted);
    1122             : 
    1123           9 :         QOBJ_UNREG(peer);
    1124             : 
    1125             :         /* this /ought/ to have been done already through bgp_stop earlier,
    1126             :          * but just to be sure..
    1127             :          */
    1128           9 :         bgp_timer_set(peer);
    1129           9 :         bgp_reads_off(peer);
    1130           9 :         bgp_writes_off(peer);
    1131           9 :         thread_cancel_event_ready(bm->master, peer);
    1132         234 :         FOREACH_AFI_SAFI (afi, safi)
    1133         189 :                 THREAD_OFF(peer->t_revalidate_all[afi][safi]);
    1134           9 :         assert(!peer->t_write);
    1135           9 :         assert(!peer->t_read);
    1136           9 :         BGP_EVENT_FLUSH(peer);
    1137             : 
    1138           9 :         pthread_mutex_destroy(&peer->io_mtx);
    1139             : 
    1140             :         /* Free connected nexthop, if present */
    1141           9 :         if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE)
    1142           4 :             && !peer_dynamic_neighbor(peer))
    1143           4 :                 bgp_delete_connected_nexthop(family2afi(peer->su.sa.sa_family),
    1144             :                                              peer);
    1145             : 
    1146         225 :         FOREACH_AFI_SAFI (afi, safi) {
    1147         189 :                 if (peer->filter[afi][safi].advmap.aname)
    1148           0 :                         XFREE(MTYPE_BGP_FILTER_NAME,
    1149             :                               peer->filter[afi][safi].advmap.aname);
    1150         189 :                 if (peer->filter[afi][safi].advmap.cname)
    1151         189 :                         XFREE(MTYPE_BGP_FILTER_NAME,
    1152             :                               peer->filter[afi][safi].advmap.cname);
    1153             :         }
    1154             : 
    1155           9 :         XFREE(MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message);
    1156             : 
    1157           9 :         XFREE(MTYPE_PEER_DESC, peer->desc);
    1158           9 :         XFREE(MTYPE_BGP_PEER_HOST, peer->host);
    1159           9 :         XFREE(MTYPE_BGP_PEER_HOST, peer->hostname);
    1160           9 :         XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
    1161           9 :         XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
    1162             : 
    1163             :         /* Update source configuration.  */
    1164           9 :         if (peer->update_source) {
    1165           0 :                 sockunion_free(peer->update_source);
    1166           0 :                 peer->update_source = NULL;
    1167             :         }
    1168             : 
    1169           9 :         XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
    1170             : 
    1171           9 :         XFREE(MTYPE_BGP_NOTIFICATION, peer->notify.data);
    1172           9 :         memset(&peer->notify, 0, sizeof(struct bgp_notify));
    1173             : 
    1174           9 :         if (peer->clear_node_queue)
    1175           9 :                 work_queue_free_and_null(&peer->clear_node_queue);
    1176             : 
    1177           9 :         bgp_sync_delete(peer);
    1178             : 
    1179           9 :         XFREE(MTYPE_PEER_CONF_IF, peer->conf_if);
    1180             : 
    1181             :         /* Remove BFD configuration. */
    1182           9 :         if (peer->bfd_config)
    1183           0 :                 bgp_peer_remove_bfd_config(peer);
    1184             : 
    1185         225 :         FOREACH_AFI_SAFI (afi, safi)
    1186         189 :                 bgp_addpath_set_peer_type(peer, afi, safi, BGP_ADDPATH_NONE);
    1187             : 
    1188           9 :         bgp_unlock(peer->bgp);
    1189             : 
    1190           9 :         memset(peer, 0, sizeof(struct peer));
    1191             : 
    1192           9 :         XFREE(MTYPE_BGP_PEER, peer);
    1193           9 : }
    1194             : 
    1195             : /* increase reference count on a struct peer */
    1196         239 : struct peer *peer_lock_with_caller(const char *name, struct peer *peer)
    1197             : {
    1198         239 :         frrtrace(2, frr_bgp, bgp_peer_lock, peer, name);
    1199         239 :         assert(peer && (peer->lock >= 0));
    1200             : 
    1201         239 :         peer->lock++;
    1202             : 
    1203         239 :         return peer;
    1204             : }
    1205             : 
    1206             : /* decrease reference count on a struct peer
    1207             :  * struct peer is freed and NULL returned if last reference
    1208             :  */
    1209         239 : struct peer *peer_unlock_with_caller(const char *name, struct peer *peer)
    1210             : {
    1211         239 :         frrtrace(2, frr_bgp, bgp_peer_unlock, peer, name);
    1212         239 :         assert(peer && (peer->lock > 0));
    1213             : 
    1214         239 :         peer->lock--;
    1215             : 
    1216         239 :         if (peer->lock == 0) {
    1217           9 :                 peer_free(peer);
    1218           9 :                 return NULL;
    1219             :         }
    1220             : 
    1221             :         return peer;
    1222             : }
    1223             : /* BGP GR changes */
    1224             : 
    1225           3 : int bgp_global_gr_init(struct bgp *bgp)
    1226             : {
    1227           3 :         if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
    1228           0 :                 zlog_debug("%s called ..", __func__);
    1229             : 
    1230           3 :         int local_GLOBAL_GR_FSM[BGP_GLOBAL_GR_MODE][BGP_GLOBAL_GR_EVENT_CMD] = {
    1231             :                 /* GLOBAL_HELPER Mode  */
    1232             :                 {
    1233             :                 /*Event -> */
    1234             :                 /*GLOBAL_GR_cmd*/  /*no_Global_GR_cmd*/
    1235             :                         GLOBAL_GR,      GLOBAL_INVALID,
    1236             :                 /*GLOBAL_DISABLE_cmd*/ /*no_Global_Disable_cmd*/
    1237             :                         GLOBAL_DISABLE, GLOBAL_INVALID
    1238             :                 },
    1239             :                 /* GLOBAL_GR Mode */
    1240             :                 {
    1241             :                 /*Event -> */
    1242             :                 /*GLOBAL_GR_cmd*/ /*no_Global_GR_cmd*/
    1243             :                         GLOBAL_GR,  GLOBAL_HELPER,
    1244             :                 /*GLOBAL_DISABLE_cmd*/ /*no_Global_Disable_cmd*/
    1245             :                         GLOBAL_DISABLE,  GLOBAL_INVALID
    1246             :                 },
    1247             :                 /* GLOBAL_DISABLE Mode  */
    1248             :                 {
    1249             :                 /*Event -> */
    1250             :                 /*GLOBAL_GR_cmd */      /*no_Global_GR_cmd*/
    1251             :                         GLOBAL_GR,      GLOBAL_INVALID,
    1252             :                 /*GLOBAL_DISABLE_cmd*//*no_Global_Disable_cmd*/
    1253             :                         GLOBAL_INVALID, GLOBAL_HELPER
    1254             :                 },
    1255             :                 /* GLOBAL_INVALID Mode  */
    1256             :                 {
    1257             :                 /*Event -> */
    1258             :                 /*GLOBAL_GR_cmd*/       /*no_Global_GR_cmd*/
    1259             :                         GLOBAL_INVALID, GLOBAL_INVALID,
    1260             :                 /*GLOBAL_DISABLE_cmd*/ /*no_Global_Disable_cmd*/
    1261             :                         GLOBAL_INVALID, GLOBAL_INVALID
    1262             :                 }
    1263             :         };
    1264           3 :         memcpy(bgp->GLOBAL_GR_FSM, local_GLOBAL_GR_FSM,
    1265             :                                         sizeof(local_GLOBAL_GR_FSM));
    1266             : 
    1267           3 :         bgp->global_gr_present_state = GLOBAL_HELPER;
    1268           3 :         bgp->present_zebra_gr_state = ZEBRA_GR_DISABLE;
    1269             : 
    1270           3 :         return BGP_GR_SUCCESS;
    1271             : }
    1272             : 
    1273           9 : int bgp_peer_gr_init(struct peer *peer)
    1274             : {
    1275           9 :         if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
    1276           0 :                 zlog_debug("%s called ..", __func__);
    1277             : 
    1278           9 :         struct bgp_peer_gr local_Peer_GR_FSM[BGP_PEER_GR_MODE]
    1279             :                                         [BGP_PEER_GR_EVENT_CMD] = {
    1280             :         {
    1281             :         /*      PEER_HELPER Mode        */
    1282             :         /* Event-> */ /* PEER_GR_CMD */ /* NO_PEER_GR_CMD */
    1283             :                 { PEER_GR, bgp_peer_gr_action }, {PEER_INVALID, NULL },
    1284             :         /* Event-> */ /* PEER_DISABLE_CMD */ /* NO_PEER_DISABLE_CMD */
    1285             :                 {PEER_DISABLE, bgp_peer_gr_action }, {PEER_INVALID, NULL },
    1286             :         /* Event-> */ /* PEER_HELPER_cmd */ /* NO_PEER_HELPER_CMD */
    1287             :                 { PEER_INVALID, NULL }, {PEER_GLOBAL_INHERIT,
    1288             :                                                 bgp_peer_gr_action }
    1289             :         },
    1290             :         {
    1291             :         /*      PEER_GR Mode    */
    1292             :         /* Event-> */ /* PEER_GR_CMD */ /* NO_PEER_GR_CMD */
    1293             :                 { PEER_INVALID, NULL }, { PEER_GLOBAL_INHERIT,
    1294             :                                                 bgp_peer_gr_action },
    1295             :         /* Event-> */ /* PEER_DISABLE_CMD */ /* NO_PEER_DISABLE_CMD */
    1296             :                 {PEER_DISABLE, bgp_peer_gr_action }, { PEER_INVALID, NULL },
    1297             :         /* Event-> */ /* PEER_HELPER_cmd */ /* NO_PEER_HELPER_CMD */
    1298             :                 { PEER_HELPER, bgp_peer_gr_action }, { PEER_INVALID, NULL }
    1299             :         },
    1300             :         {
    1301             :         /*      PEER_DISABLE Mode       */
    1302             :         /* Event-> */ /* PEER_GR_CMD */ /* NO_PEER_GR_CMD */
    1303             :                 { PEER_GR, bgp_peer_gr_action }, { PEER_INVALID, NULL },
    1304             :         /* Event-> */ /* PEER_DISABLE_CMD */ /* NO_PEER_DISABLE_CMD */
    1305             :                 { PEER_INVALID, NULL }, { PEER_GLOBAL_INHERIT,
    1306             :                                                 bgp_peer_gr_action },
    1307             :         /* Event-> */ /* PEER_HELPER_cmd */  /* NO_PEER_HELPER_CMD */
    1308             :                 { PEER_HELPER, bgp_peer_gr_action }, { PEER_INVALID, NULL }
    1309             :         },
    1310             :         {
    1311             :         /*      PEER_INVALID Mode       */
    1312             :         /* Event-> */ /* PEER_GR_CMD */  /* NO_PEER_GR_CMD */
    1313             :                 { PEER_INVALID, NULL }, { PEER_INVALID, NULL },
    1314             :         /* Event-> */ /* PEER_DISABLE_CMD */  /* NO_PEER_DISABLE_CMD */
    1315             :                 { PEER_INVALID, NULL }, { PEER_INVALID, NULL },
    1316             :         /* Event-> */ /* PEER_HELPER_cmd */  /* NO_PEER_HELPER_CMD */
    1317             :                 { PEER_INVALID, NULL }, { PEER_INVALID, NULL },
    1318             :         },
    1319             :         {
    1320             :         /*      PEER_GLOBAL_INHERIT Mode        */
    1321             :         /* Event-> */ /* PEER_GR_CMD */              /* NO_PEER_GR_CMD */
    1322             :                 { PEER_GR, bgp_peer_gr_action }, { PEER_INVALID, NULL },
    1323             :         /* Event-> */ /* PEER_DISABLE_CMD */     /* NO_PEER_DISABLE_CMD */
    1324             :                 { PEER_DISABLE, bgp_peer_gr_action}, { PEER_INVALID, NULL },
    1325             :         /* Event-> */ /* PEER_HELPER_cmd */     /* NO_PEER_HELPER_CMD */
    1326             :                 { PEER_HELPER, bgp_peer_gr_action }, { PEER_INVALID, NULL }
    1327             :         }
    1328             :         };
    1329           9 :         memcpy(&peer->PEER_GR_FSM, local_Peer_GR_FSM,
    1330             :                                         sizeof(local_Peer_GR_FSM));
    1331           9 :         peer->peer_gr_present_state = PEER_GLOBAL_INHERIT;
    1332           9 :         bgp_peer_move_to_gr_mode(peer, PEER_GLOBAL_INHERIT);
    1333             : 
    1334           9 :         return BGP_GR_SUCCESS;
    1335             : }
    1336             : 
    1337           3 : static void bgp_srv6_init(struct bgp *bgp)
    1338             : {
    1339           3 :         bgp->srv6_enabled = false;
    1340           3 :         memset(bgp->srv6_locator_name, 0, sizeof(bgp->srv6_locator_name));
    1341           3 :         bgp->srv6_locator_chunks = list_new();
    1342           3 :         bgp->srv6_functions = list_new();
    1343           3 : }
    1344             : 
    1345           3 : static void bgp_srv6_cleanup(struct bgp *bgp)
    1346             : {
    1347           3 :         if (bgp->srv6_locator_chunks)
    1348           3 :                 list_delete(&bgp->srv6_locator_chunks);
    1349           3 :         if (bgp->srv6_functions)
    1350           3 :                 list_delete(&bgp->srv6_functions);
    1351           3 : }
    1352             : 
    1353             : /* Allocate new peer object, implicitely locked.  */
    1354           9 : struct peer *peer_new(struct bgp *bgp)
    1355             : {
    1356           9 :         afi_t afi;
    1357           9 :         safi_t safi;
    1358           9 :         struct peer *peer;
    1359           9 :         struct servent *sp;
    1360             : 
    1361             :         /* bgp argument is absolutely required */
    1362           9 :         assert(bgp);
    1363             : 
    1364             :         /* Allocate new peer. */
    1365           9 :         peer = XCALLOC(MTYPE_BGP_PEER, sizeof(struct peer));
    1366             : 
    1367             :         /* Set default value. */
    1368           9 :         peer->fd = -1;
    1369           9 :         peer->v_start = BGP_INIT_START_TIMER;
    1370           9 :         peer->v_connect = bgp->default_connect_retry;
    1371           9 :         peer->status = Idle;
    1372           9 :         peer->ostatus = Idle;
    1373           9 :         peer->cur_event = peer->last_event = peer->last_major_event = 0;
    1374           9 :         peer->bgp = bgp_lock(bgp);
    1375           9 :         peer = peer_lock(peer); /* initial reference */
    1376           9 :         peer->local_role = ROLE_UNDEFINED;
    1377           9 :         peer->remote_role = ROLE_UNDEFINED;
    1378           9 :         peer->password = NULL;
    1379           9 :         peer->max_packet_size = BGP_STANDARD_MESSAGE_MAX_PACKET_SIZE;
    1380             : 
    1381             :         /* Set default flags. */
    1382         225 :         FOREACH_AFI_SAFI (afi, safi) {
    1383         189 :                 SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
    1384         189 :                 SET_FLAG(peer->af_flags[afi][safi],
    1385             :                          PEER_FLAG_SEND_EXT_COMMUNITY);
    1386         189 :                 SET_FLAG(peer->af_flags[afi][safi],
    1387             :                          PEER_FLAG_SEND_LARGE_COMMUNITY);
    1388             : 
    1389         189 :                 SET_FLAG(peer->af_flags_invert[afi][safi],
    1390             :                          PEER_FLAG_SEND_COMMUNITY);
    1391         189 :                 SET_FLAG(peer->af_flags_invert[afi][safi],
    1392             :                          PEER_FLAG_SEND_EXT_COMMUNITY);
    1393         189 :                 SET_FLAG(peer->af_flags_invert[afi][safi],
    1394             :                          PEER_FLAG_SEND_LARGE_COMMUNITY);
    1395         189 :                 peer->addpath_type[afi][safi] = BGP_ADDPATH_NONE;
    1396         189 :                 peer->soo[afi][safi] = NULL;
    1397             :         }
    1398             : 
    1399             :         /* set nexthop-unchanged for l2vpn evpn by default */
    1400           9 :         SET_FLAG(peer->af_flags[AFI_L2VPN][SAFI_EVPN],
    1401             :                  PEER_FLAG_NEXTHOP_UNCHANGED);
    1402             : 
    1403           9 :         SET_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
    1404             : 
    1405             :         /* Initialize per peer bgp GR FSM */
    1406           9 :         bgp_peer_gr_init(peer);
    1407             : 
    1408             :         /* Create buffers.  */
    1409           9 :         peer->ibuf = stream_fifo_new();
    1410           9 :         peer->obuf = stream_fifo_new();
    1411           9 :         pthread_mutex_init(&peer->io_mtx, NULL);
    1412             : 
    1413             :         /* We use a larger buffer for peer->obuf_work in the event that:
    1414             :          * - We RX a BGP_UPDATE where the attributes alone are just
    1415             :          *   under BGP_EXTENDED_MESSAGE_MAX_PACKET_SIZE.
    1416             :          * - The user configures an outbound route-map that does many as-path
    1417             :          *   prepends or adds many communities. At most they can have
    1418             :          *   CMD_ARGC_MAX args in a route-map so there is a finite limit on how
    1419             :          *   large they can make the attributes.
    1420             :          *
    1421             :          * Having a buffer with BGP_MAX_PACKET_SIZE_OVERFLOW allows us to avoid
    1422             :          * bounds checking for every single attribute as we construct an
    1423             :          * UPDATE.
    1424             :          */
    1425          18 :         peer->obuf_work =
    1426           9 :                 stream_new(BGP_MAX_PACKET_SIZE + BGP_MAX_PACKET_SIZE_OVERFLOW);
    1427          18 :         peer->ibuf_work =
    1428           9 :                 ringbuf_new(BGP_MAX_PACKET_SIZE * BGP_READ_PACKET_MAX);
    1429             : 
    1430           9 :         peer->scratch = stream_new(BGP_MAX_PACKET_SIZE);
    1431             : 
    1432           9 :         bgp_sync_init(peer);
    1433             : 
    1434             :         /* Get service port number.  */
    1435           9 :         sp = getservbyname("bgp", "tcp");
    1436           9 :         peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs(sp->s_port);
    1437             : 
    1438           9 :         QOBJ_REG(peer, peer);
    1439           9 :         return peer;
    1440             : }
    1441             : 
    1442             : /*
    1443             :  * This function is invoked when a duplicate peer structure associated with
    1444             :  * a neighbor is being deleted. If this about-to-be-deleted structure is
    1445             :  * the one with all the config, then we have to copy over the info.
    1446             :  */
    1447           2 : void peer_xfer_config(struct peer *peer_dst, struct peer *peer_src)
    1448             : {
    1449           2 :         struct peer_af *paf;
    1450           2 :         afi_t afi;
    1451           2 :         safi_t safi;
    1452           2 :         int afidx;
    1453             : 
    1454           2 :         assert(peer_src);
    1455           2 :         assert(peer_dst);
    1456             : 
    1457             :         /* The following function is used by both peer group config copy to
    1458             :          * individual peer and when we transfer config
    1459             :          */
    1460           2 :         if (peer_src->change_local_as)
    1461           0 :                 peer_dst->change_local_as = peer_src->change_local_as;
    1462             : 
    1463             :         /* peer flags apply */
    1464           2 :         peer_dst->flags = peer_src->flags;
    1465             :         /*
    1466             :          * The doppelganger *must* not have a config node stored
    1467             :          */
    1468           2 :         UNSET_FLAG(peer_dst->flags, PEER_FLAG_CONFIG_NODE);
    1469           2 :         peer_dst->peer_gr_present_state = peer_src->peer_gr_present_state;
    1470           2 :         peer_dst->peer_gr_new_status_flag = peer_src->peer_gr_new_status_flag;
    1471             : 
    1472           2 :         peer_dst->local_as = peer_src->local_as;
    1473           2 :         peer_dst->port = peer_src->port;
    1474             :         /* copy tcp_mss value */
    1475           2 :         peer_dst->tcp_mss = peer_src->tcp_mss;
    1476           2 :         (void)peer_sort(peer_dst);
    1477           2 :         peer_dst->rmap_type = peer_src->rmap_type;
    1478           2 :         peer_dst->local_role = peer_src->local_role;
    1479             : 
    1480           2 :         peer_dst->max_packet_size = peer_src->max_packet_size;
    1481             : 
    1482             :         /* Timers */
    1483           2 :         peer_dst->holdtime = peer_src->holdtime;
    1484           2 :         peer_dst->keepalive = peer_src->keepalive;
    1485           2 :         peer_dst->connect = peer_src->connect;
    1486           2 :         peer_dst->delayopen = peer_src->delayopen;
    1487           2 :         peer_dst->v_holdtime = peer_src->v_holdtime;
    1488           2 :         peer_dst->v_keepalive = peer_src->v_keepalive;
    1489           2 :         peer_dst->routeadv = peer_src->routeadv;
    1490           2 :         peer_dst->v_routeadv = peer_src->v_routeadv;
    1491           2 :         peer_dst->v_delayopen = peer_src->v_delayopen;
    1492             : 
    1493             :         /* password apply */
    1494           2 :         if (peer_src->password && !peer_dst->password)
    1495           0 :                 peer_dst->password =
    1496           0 :                         XSTRDUP(MTYPE_PEER_PASSWORD, peer_src->password);
    1497             : 
    1498          50 :         FOREACH_AFI_SAFI (afi, safi) {
    1499          42 :                 peer_dst->afc[afi][safi] = peer_src->afc[afi][safi];
    1500          42 :                 peer_dst->af_flags[afi][safi] = peer_src->af_flags[afi][safi];
    1501          42 :                 peer_dst->allowas_in[afi][safi] =
    1502          42 :                         peer_src->allowas_in[afi][safi];
    1503          42 :                 peer_dst->weight[afi][safi] = peer_src->weight[afi][safi];
    1504          42 :                 peer_dst->addpath_type[afi][safi] =
    1505          42 :                         peer_src->addpath_type[afi][safi];
    1506             :         }
    1507             : 
    1508          28 :         for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) {
    1509          26 :                 paf = peer_src->peer_af_array[afidx];
    1510          26 :                 if (paf != NULL) {
    1511           2 :                         if (!peer_af_find(peer_dst, paf->afi, paf->safi))
    1512           0 :                                 peer_af_create(peer_dst, paf->afi, paf->safi);
    1513             :                 }
    1514             :         }
    1515             : 
    1516             :         /* update-source apply */
    1517           2 :         if (peer_src->update_source) {
    1518           0 :                 if (peer_dst->update_source)
    1519           0 :                         sockunion_free(peer_dst->update_source);
    1520           0 :                 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer_dst->update_if);
    1521           0 :                 peer_dst->update_source =
    1522           0 :                         sockunion_dup(peer_src->update_source);
    1523           2 :         } else if (peer_src->update_if) {
    1524           0 :                 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer_dst->update_if);
    1525           0 :                 if (peer_dst->update_source) {
    1526           0 :                         sockunion_free(peer_dst->update_source);
    1527           0 :                         peer_dst->update_source = NULL;
    1528             :                 }
    1529           0 :                 peer_dst->update_if =
    1530           0 :                         XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, peer_src->update_if);
    1531             :         }
    1532             : 
    1533           2 :         if (peer_src->ifname) {
    1534           0 :                 XFREE(MTYPE_BGP_PEER_IFNAME, peer_dst->ifname);
    1535             : 
    1536           0 :                 peer_dst->ifname =
    1537           0 :                         XSTRDUP(MTYPE_BGP_PEER_IFNAME, peer_src->ifname);
    1538             :         }
    1539           2 : }
    1540             : 
    1541           0 : static int bgp_peer_conf_if_to_su_update_v4(struct peer *peer,
    1542             :                                             struct interface *ifp)
    1543             : {
    1544           0 :         struct connected *ifc;
    1545           0 :         struct prefix p;
    1546           0 :         uint32_t addr;
    1547           0 :         struct listnode *node;
    1548             : 
    1549             :         /* If our IPv4 address on the interface is /30 or /31, we can derive the
    1550             :          * IPv4 address of the other end.
    1551             :          */
    1552           0 :         for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
    1553           0 :                 if (ifc->address && (ifc->address->family == AF_INET)) {
    1554           0 :                         prefix_copy(&p, CONNECTED_PREFIX(ifc));
    1555           0 :                         if (p.prefixlen == 30) {
    1556           0 :                                 peer->su.sa.sa_family = AF_INET;
    1557           0 :                                 addr = ntohl(p.u.prefix4.s_addr);
    1558           0 :                                 if (addr % 4 == 1)
    1559           0 :                                         peer->su.sin.sin_addr.s_addr =
    1560           0 :                                                 htonl(addr + 1);
    1561           0 :                                 else if (addr % 4 == 2)
    1562           0 :                                         peer->su.sin.sin_addr.s_addr =
    1563           0 :                                                 htonl(addr - 1);
    1564             : #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
    1565             :                                 peer->su.sin.sin_len =
    1566             :                                         sizeof(struct sockaddr_in);
    1567             : #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
    1568           0 :                                 return 1;
    1569           0 :                         } else if (p.prefixlen == 31) {
    1570           0 :                                 peer->su.sa.sa_family = AF_INET;
    1571           0 :                                 addr = ntohl(p.u.prefix4.s_addr);
    1572           0 :                                 if (addr % 2 == 0)
    1573           0 :                                         peer->su.sin.sin_addr.s_addr =
    1574           0 :                                                 htonl(addr + 1);
    1575             :                                 else
    1576           0 :                                         peer->su.sin.sin_addr.s_addr =
    1577           0 :                                                 htonl(addr - 1);
    1578             : #ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
    1579             :                                 peer->su.sin.sin_len =
    1580             :                                         sizeof(struct sockaddr_in);
    1581             : #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
    1582           0 :                                 return 1;
    1583           0 :                         } else if (bgp_debug_neighbor_events(peer))
    1584           0 :                                 zlog_debug(
    1585             :                                         "%s: IPv4 interface address is not /30 or /31, v4 session not started",
    1586             :                                         peer->conf_if);
    1587             :                 }
    1588             :         }
    1589             : 
    1590             :         return 0;
    1591             : }
    1592             : 
    1593           0 : static bool bgp_peer_conf_if_to_su_update_v6(struct peer *peer,
    1594             :                                              struct interface *ifp)
    1595             : {
    1596           0 :         struct nbr_connected *ifc_nbr;
    1597             : 
    1598             :         /* Have we learnt the peer's IPv6 link-local address? */
    1599           0 :         if (ifp->nbr_connected
    1600           0 :             && (ifc_nbr = listnode_head(ifp->nbr_connected))) {
    1601           0 :                 peer->su.sa.sa_family = AF_INET6;
    1602           0 :                 memcpy(&peer->su.sin6.sin6_addr, &ifc_nbr->address->u.prefix,
    1603             :                        sizeof(struct in6_addr));
    1604             : #ifdef SIN6_LEN
    1605             :                 peer->su.sin6.sin6_len = sizeof(struct sockaddr_in6);
    1606             : #endif
    1607           0 :                 peer->su.sin6.sin6_scope_id = ifp->ifindex;
    1608           0 :                 return true;
    1609             :         }
    1610             : 
    1611             :         return false;
    1612             : }
    1613             : 
    1614             : /*
    1615             :  * Set or reset the peer address socketunion structure based on the
    1616             :  * learnt/derived peer address. If the address has changed, update the
    1617             :  * password on the listen socket, if needed.
    1618             :  */
    1619          18 : void bgp_peer_conf_if_to_su_update(struct peer *peer)
    1620             : {
    1621          18 :         struct interface *ifp;
    1622          18 :         int prev_family;
    1623          18 :         int peer_addr_updated = 0;
    1624          18 :         struct listnode *node;
    1625          18 :         union sockunion old_su;
    1626             : 
    1627             :         /*
    1628             :          * This function is only ever needed when FRR an interface
    1629             :          * based peering, so this simple test will tell us if
    1630             :          * we are in an interface based configuration or not
    1631             :          */
    1632          18 :         if (!peer->conf_if)
    1633          18 :                 return;
    1634             : 
    1635           0 :         old_su = peer->su;
    1636             : 
    1637           0 :         prev_family = peer->su.sa.sa_family;
    1638           0 :         if ((ifp = if_lookup_by_name(peer->conf_if, peer->bgp->vrf_id))) {
    1639           0 :                 peer->ifp = ifp;
    1640             :                 /* If BGP unnumbered is not "v6only", we first see if we can
    1641             :                  * derive the
    1642             :                  * peer's IPv4 address.
    1643             :                  */
    1644           0 :                 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))
    1645           0 :                         peer_addr_updated =
    1646           0 :                                 bgp_peer_conf_if_to_su_update_v4(peer, ifp);
    1647             : 
    1648             :                 /* If "v6only" or we can't derive peer's IPv4 address, see if
    1649             :                  * we've
    1650             :                  * learnt the peer's IPv6 link-local address. This is from the
    1651             :                  * source
    1652             :                  * IPv6 address in router advertisement.
    1653             :                  */
    1654           0 :                 if (!peer_addr_updated)
    1655           0 :                         peer_addr_updated =
    1656           0 :                                 bgp_peer_conf_if_to_su_update_v6(peer, ifp);
    1657             :         }
    1658             :         /* If we could derive the peer address, we may need to install the
    1659             :          * password
    1660             :          * configured for the peer, if any, on the listen socket. Otherwise,
    1661             :          * mark
    1662             :          * that peer's address is not available and uninstall the password, if
    1663             :          * needed.
    1664             :          */
    1665           0 :         if (peer_addr_updated) {
    1666           0 :                 if (CHECK_FLAG(peer->flags, PEER_FLAG_PASSWORD)
    1667           0 :                     && prev_family == AF_UNSPEC)
    1668           0 :                         bgp_md5_set(peer);
    1669             :         } else {
    1670           0 :                 if (CHECK_FLAG(peer->flags, PEER_FLAG_PASSWORD)
    1671           0 :                     && prev_family != AF_UNSPEC)
    1672           0 :                         bgp_md5_unset(peer);
    1673           0 :                 peer->su.sa.sa_family = AF_UNSPEC;
    1674           0 :                 memset(&peer->su.sin6.sin6_addr, 0, sizeof(struct in6_addr));
    1675             :         }
    1676             : 
    1677             :         /*
    1678             :          * If they are the same, nothing to do here, move along
    1679             :          */
    1680           0 :         if (!sockunion_same(&old_su, &peer->su)) {
    1681           0 :                 union sockunion new_su = peer->su;
    1682           0 :                 struct bgp *bgp = peer->bgp;
    1683             : 
    1684             :                 /*
    1685             :                  * Our peer structure is stored in the bgp->peerhash
    1686             :                  * release it before we modify anything in both the
    1687             :                  * hash and the list.  But *only* if the peer
    1688             :                  * is in the bgp->peerhash as that on deletion
    1689             :                  * we call bgp_stop which calls this function :(
    1690             :                  * so on deletion let's remove from the list first
    1691             :                  * and then do the deletion preventing this from
    1692             :                  * being added back on the list below when we
    1693             :                  * fail to remove it up here.
    1694             :                  */
    1695             : 
    1696             :                 /*
    1697             :                  * listnode_lookup just scans the list
    1698             :                  * for the peer structure so it's safe
    1699             :                  * to use without modifying the su
    1700             :                  */
    1701           0 :                 node = listnode_lookup(bgp->peer, peer);
    1702           0 :                 if (node) {
    1703             :                         /*
    1704             :                          * Let's reset the peer->su release and
    1705             :                          * reset it and put it back.  We have to
    1706             :                          * do this because hash_release will
    1707             :                          * scan through looking for a matching
    1708             :                          * su if needed.
    1709             :                          */
    1710           0 :                         peer->su = old_su;
    1711           0 :                         hash_release(peer->bgp->peerhash, peer);
    1712           0 :                         listnode_delete(peer->bgp->peer, peer);
    1713             : 
    1714           0 :                         peer->su = new_su;
    1715           0 :                         (void)hash_get(peer->bgp->peerhash, peer,
    1716             :                                        hash_alloc_intern);
    1717           0 :                         listnode_add_sort(peer->bgp->peer, peer);
    1718             :                 }
    1719             :         }
    1720             : }
    1721             : 
    1722           0 : void bgp_recalculate_afi_safi_bestpaths(struct bgp *bgp, afi_t afi, safi_t safi)
    1723             : {
    1724           0 :         struct bgp_dest *dest, *ndest;
    1725           0 :         struct bgp_table *table;
    1726             : 
    1727           0 :         for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
    1728           0 :              dest = bgp_route_next(dest)) {
    1729           0 :                 table = bgp_dest_get_bgp_table_info(dest);
    1730           0 :                 if (table != NULL) {
    1731             :                         /* Special handling for 2-level routing
    1732             :                          * tables. */
    1733           0 :                         if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
    1734           0 :                             || safi == SAFI_EVPN) {
    1735           0 :                                 for (ndest = bgp_table_top(table); ndest;
    1736           0 :                                      ndest = bgp_route_next(ndest))
    1737           0 :                                         bgp_process(bgp, ndest, afi, safi);
    1738             :                         } else
    1739           0 :                                 bgp_process(bgp, dest, afi, safi);
    1740             :                 }
    1741             :         }
    1742           0 : }
    1743             : 
    1744             : /* Force a bestpath recalculation for all prefixes.  This is used
    1745             :  * when 'bgp bestpath' commands are entered.
    1746             :  */
    1747           0 : void bgp_recalculate_all_bestpaths(struct bgp *bgp)
    1748             : {
    1749           0 :         afi_t afi;
    1750           0 :         safi_t safi;
    1751             : 
    1752           0 :         FOREACH_AFI_SAFI (afi, safi) {
    1753           0 :                 bgp_recalculate_afi_safi_bestpaths(bgp, afi, safi);
    1754             :         }
    1755           0 : }
    1756             : 
    1757             : /*
    1758             :  * Create new BGP peer.
    1759             :  *
    1760             :  * conf_if and su are mutually exclusive if configuring from the cli.
    1761             :  * If we are handing a doppelganger, then we *must* pass in both
    1762             :  * the original peer's su and conf_if, so that we can appropriately
    1763             :  * track the bgp->peerhash( ie we don't want to remove the current
    1764             :  * one from the config ).
    1765             :  */
    1766           6 : struct peer *peer_create(union sockunion *su, const char *conf_if,
    1767             :                          struct bgp *bgp, as_t local_as, as_t remote_as,
    1768             :                          int as_type, struct peer_group *group,
    1769             :                          bool config_node)
    1770             : {
    1771           6 :         int active;
    1772           6 :         struct peer *peer;
    1773           6 :         char buf[SU_ADDRSTRLEN];
    1774           6 :         afi_t afi;
    1775           6 :         safi_t safi;
    1776             : 
    1777           6 :         peer = peer_new(bgp);
    1778           6 :         if (conf_if) {
    1779           0 :                 peer->conf_if = XSTRDUP(MTYPE_PEER_CONF_IF, conf_if);
    1780           0 :                 if (su)
    1781           0 :                         peer->su = *su;
    1782             :                 else
    1783           0 :                         bgp_peer_conf_if_to_su_update(peer);
    1784           0 :                 XFREE(MTYPE_BGP_PEER_HOST, peer->host);
    1785           0 :                 peer->host = XSTRDUP(MTYPE_BGP_PEER_HOST, conf_if);
    1786           6 :         } else if (su) {
    1787           6 :                 peer->su = *su;
    1788           6 :                 sockunion2str(su, buf, SU_ADDRSTRLEN);
    1789           6 :                 XFREE(MTYPE_BGP_PEER_HOST, peer->host);
    1790           6 :                 peer->host = XSTRDUP(MTYPE_BGP_PEER_HOST, buf);
    1791             :         }
    1792           6 :         peer->local_as = local_as;
    1793           6 :         peer->as = remote_as;
    1794           6 :         peer->as_type = as_type;
    1795           6 :         peer->local_id = bgp->router_id;
    1796           6 :         peer->v_holdtime = bgp->default_holdtime;
    1797           6 :         peer->v_keepalive = bgp->default_keepalive;
    1798           6 :         peer->v_routeadv = (peer_sort(peer) == BGP_PEER_IBGP)
    1799             :                                    ? BGP_DEFAULT_IBGP_ROUTEADV
    1800             :                                    : BGP_DEFAULT_EBGP_ROUTEADV;
    1801           6 :         if (bgp_config_inprocess())
    1802           0 :                 peer->shut_during_cfg = true;
    1803             : 
    1804           6 :         peer = peer_lock(peer); /* bgp peer list reference */
    1805           6 :         peer->group = group;
    1806           6 :         listnode_add_sort(bgp->peer, peer);
    1807             : 
    1808           6 :         if (config_node)
    1809           4 :                 SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
    1810             : 
    1811           6 :         (void)hash_get(bgp->peerhash, peer, hash_alloc_intern);
    1812             : 
    1813             :         /* Adjust update-group coalesce timer heuristics for # peers. */
    1814           6 :         if (bgp->heuristic_coalesce) {
    1815           6 :                 long ct = BGP_DEFAULT_SUBGROUP_COALESCE_TIME
    1816           6 :                           + (bgp->peer->count
    1817           6 :                              * BGP_PEER_ADJUST_SUBGROUP_COALESCE_TIME);
    1818           6 :                 bgp->coalesce_time = MIN(BGP_MAX_SUBGROUP_COALESCE_TIME, ct);
    1819             :         }
    1820             : 
    1821           6 :         active = peer_active(peer);
    1822           6 :         if (!active) {
    1823           6 :                 if (peer->su.sa.sa_family == AF_UNSPEC)
    1824           0 :                         peer->last_reset = PEER_DOWN_NBR_ADDR;
    1825             :                 else
    1826           6 :                         peer->last_reset = PEER_DOWN_NOAFI_ACTIVATED;
    1827             :         }
    1828             : 
    1829             :         /* Last read and reset time set */
    1830           6 :         peer->readtime = peer->resettime = monotime(NULL);
    1831             : 
    1832             :         /* Default TTL set. */
    1833           6 :         peer->ttl = (peer->sort == BGP_PEER_IBGP) ? MAXTTL : BGP_DEFAULT_TTL;
    1834             : 
    1835             :         /* Default configured keepalives count for shutdown rtt command */
    1836           6 :         peer->rtt_keepalive_conf = 1;
    1837             : 
    1838             :         /* If 'bgp default <afi>-<safi>' is configured, then activate the
    1839             :          * neighbor for the corresponding address family. IPv4 Unicast is
    1840             :          * the only address family enabled by default without expliict
    1841             :          * configuration.
    1842             :          */
    1843         150 :         FOREACH_AFI_SAFI (afi, safi) {
    1844         126 :                 if (bgp->default_af[afi][safi]) {
    1845           6 :                         peer->afc[afi][safi] = 1;
    1846           6 :                         peer_af_create(peer, afi, safi);
    1847             :                 }
    1848             :         }
    1849             : 
    1850             :         /* auto shutdown if configured */
    1851           6 :         if (bgp->autoshutdown)
    1852           6 :                 peer_flag_set(peer, PEER_FLAG_SHUTDOWN);
    1853             :         /* Set up peer's events and timers. */
    1854           6 :         else if (!active && peer_active(peer))
    1855           6 :                 bgp_timer_set(peer);
    1856             : 
    1857           6 :         bgp_peer_gr_flags_update(peer);
    1858          23 :         BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, bgp->peer);
    1859             : 
    1860           6 :         return peer;
    1861             : }
    1862             : 
    1863             : /* Make accept BGP peer. This function is only called from the test code */
    1864           0 : struct peer *peer_create_accept(struct bgp *bgp)
    1865             : {
    1866           0 :         struct peer *peer;
    1867             : 
    1868           0 :         peer = peer_new(bgp);
    1869             : 
    1870           0 :         peer = peer_lock(peer); /* bgp peer list reference */
    1871           0 :         listnode_add_sort(bgp->peer, peer);
    1872           0 :         (void)hash_get(bgp->peerhash, peer, hash_alloc_intern);
    1873             : 
    1874           0 :         return peer;
    1875             : }
    1876             : 
    1877             : /*
    1878             :  * Return true if we have a peer configured to use this afi/safi
    1879             :  */
    1880           0 : bool bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi)
    1881             : {
    1882           0 :         struct listnode *node;
    1883           0 :         struct peer *peer;
    1884             : 
    1885           0 :         for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
    1886           0 :                 if (!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
    1887           0 :                         continue;
    1888             : 
    1889           0 :                 if (peer->afc[afi][safi])
    1890             :                         return true;
    1891             :         }
    1892             : 
    1893             :         return false;
    1894             : }
    1895             : 
    1896             : /* Change peer's AS number.  */
    1897           0 : void peer_as_change(struct peer *peer, as_t as, int as_specified)
    1898             : {
    1899           0 :         enum bgp_peer_sort origtype, newtype;
    1900             : 
    1901             :         /* Stop peer. */
    1902           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    1903           0 :                 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
    1904           0 :                         peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
    1905           0 :                         bgp_notify_send(peer, BGP_NOTIFY_CEASE,
    1906             :                                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    1907             :                 } else
    1908           0 :                         bgp_session_reset(peer);
    1909             :         }
    1910           0 :         origtype = peer_sort_lookup(peer);
    1911           0 :         peer->as = as;
    1912           0 :         peer->as_type = as_specified;
    1913             : 
    1914           0 :         if (bgp_config_check(peer->bgp, BGP_CONFIG_CONFEDERATION)
    1915           0 :             && !bgp_confederation_peers_check(peer->bgp, as)
    1916           0 :             && peer->bgp->as != as)
    1917           0 :                 peer->local_as = peer->bgp->confed_id;
    1918             :         else
    1919           0 :                 peer->local_as = peer->bgp->as;
    1920             : 
    1921           0 :         newtype = peer_sort(peer);
    1922             :         /* Advertisement-interval reset */
    1923           0 :         if (!CHECK_FLAG(peer->flags, PEER_FLAG_ROUTEADV)) {
    1924           0 :                 peer->v_routeadv = (newtype == BGP_PEER_IBGP)
    1925             :                                            ? BGP_DEFAULT_IBGP_ROUTEADV
    1926             :                                            : BGP_DEFAULT_EBGP_ROUTEADV;
    1927             :         }
    1928             : 
    1929             :         /* TTL reset */
    1930           0 :         if (newtype == BGP_PEER_IBGP)
    1931           0 :                 peer->ttl = MAXTTL;
    1932           0 :         else if (origtype == BGP_PEER_IBGP)
    1933           0 :                 peer->ttl = BGP_DEFAULT_TTL;
    1934             : 
    1935             :         /* reflector-client reset */
    1936           0 :         if (newtype != BGP_PEER_IBGP) {
    1937           0 :                 UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_UNICAST],
    1938             :                            PEER_FLAG_REFLECTOR_CLIENT);
    1939           0 :                 UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_MULTICAST],
    1940             :                            PEER_FLAG_REFLECTOR_CLIENT);
    1941           0 :                 UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_LABELED_UNICAST],
    1942             :                            PEER_FLAG_REFLECTOR_CLIENT);
    1943           0 :                 UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
    1944             :                            PEER_FLAG_REFLECTOR_CLIENT);
    1945           0 :                 UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_ENCAP],
    1946             :                            PEER_FLAG_REFLECTOR_CLIENT);
    1947           0 :                 UNSET_FLAG(peer->af_flags[AFI_IP][SAFI_FLOWSPEC],
    1948             :                            PEER_FLAG_REFLECTOR_CLIENT);
    1949           0 :                 UNSET_FLAG(peer->af_flags[AFI_IP6][SAFI_UNICAST],
    1950             :                            PEER_FLAG_REFLECTOR_CLIENT);
    1951           0 :                 UNSET_FLAG(peer->af_flags[AFI_IP6][SAFI_MULTICAST],
    1952             :                            PEER_FLAG_REFLECTOR_CLIENT);
    1953           0 :                 UNSET_FLAG(peer->af_flags[AFI_IP6][SAFI_LABELED_UNICAST],
    1954             :                            PEER_FLAG_REFLECTOR_CLIENT);
    1955           0 :                 UNSET_FLAG(peer->af_flags[AFI_IP6][SAFI_MPLS_VPN],
    1956             :                            PEER_FLAG_REFLECTOR_CLIENT);
    1957           0 :                 UNSET_FLAG(peer->af_flags[AFI_IP6][SAFI_ENCAP],
    1958             :                            PEER_FLAG_REFLECTOR_CLIENT);
    1959           0 :                 UNSET_FLAG(peer->af_flags[AFI_IP6][SAFI_FLOWSPEC],
    1960             :                            PEER_FLAG_REFLECTOR_CLIENT);
    1961           0 :                 UNSET_FLAG(peer->af_flags[AFI_L2VPN][SAFI_EVPN],
    1962             :                            PEER_FLAG_REFLECTOR_CLIENT);
    1963             :         }
    1964           0 : }
    1965             : 
    1966             : /* If peer does not exist, create new one.  If peer already exists,
    1967             :    set AS number to the peer.  */
    1968           4 : int peer_remote_as(struct bgp *bgp, union sockunion *su, const char *conf_if,
    1969             :                    as_t *as, int as_type)
    1970             : {
    1971           4 :         struct peer *peer;
    1972           4 :         as_t local_as;
    1973             : 
    1974           4 :         if (conf_if)
    1975           0 :                 peer = peer_lookup_by_conf_if(bgp, conf_if);
    1976             :         else
    1977           4 :                 peer = peer_lookup(bgp, su);
    1978             : 
    1979           4 :         if (peer) {
    1980             :                 /* Not allowed for a dynamic peer. */
    1981           0 :                 if (peer_dynamic_neighbor(peer)) {
    1982           0 :                         *as = peer->as;
    1983           0 :                         return BGP_ERR_INVALID_FOR_DYNAMIC_PEER;
    1984             :                 }
    1985             : 
    1986             :                 /* When this peer is a member of peer-group.  */
    1987           0 :                 if (peer->group) {
    1988             :                         /* peer-group already has AS number/internal/external */
    1989           0 :                         if (peer->group->conf->as
    1990           0 :                             || peer->group->conf->as_type) {
    1991             :                                 /* Return peer group's AS number.  */
    1992           0 :                                 *as = peer->group->conf->as;
    1993           0 :                                 return BGP_ERR_PEER_GROUP_MEMBER;
    1994             :                         }
    1995             : 
    1996           0 :                         enum bgp_peer_sort peer_sort_type =
    1997           0 :                                 peer_sort(peer->group->conf);
    1998             : 
    1999             :                         /* Explicit AS numbers used, compare AS numbers */
    2000           0 :                         if (as_type == AS_SPECIFIED) {
    2001           0 :                                 if (((peer_sort_type == BGP_PEER_IBGP)
    2002           0 :                                     && (bgp->as != *as))
    2003           0 :                                     || ((peer_sort_type == BGP_PEER_EBGP)
    2004           0 :                                     && (bgp->as == *as))) {
    2005           0 :                                         *as = peer->as;
    2006           0 :                                         return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
    2007             :                                 }
    2008             :                         } else {
    2009             :                                 /* internal/external used, compare as-types */
    2010           0 :                                 if (((peer_sort_type == BGP_PEER_IBGP)
    2011           0 :                                     && (as_type != AS_INTERNAL))
    2012           0 :                                     || ((peer_sort_type == BGP_PEER_EBGP)
    2013           0 :                                     && (as_type != AS_EXTERNAL)))  {
    2014           0 :                                         *as = peer->as;
    2015           0 :                                         return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
    2016             :                                 }
    2017             :                         }
    2018             :                 }
    2019             : 
    2020             :                 /* Existing peer's AS number change. */
    2021           0 :                 if (((peer->as_type == AS_SPECIFIED) && peer->as != *as)
    2022           0 :                     || (peer->as_type != as_type))
    2023           0 :                         peer_as_change(peer, *as, as_type);
    2024             :         } else {
    2025           4 :                 if (conf_if)
    2026             :                         return BGP_ERR_NO_INTERFACE_CONFIG;
    2027             : 
    2028             :                 /* If the peer is not part of our confederation, and its not an
    2029             :                    iBGP peer then spoof the source AS */
    2030           4 :                 if (bgp_config_check(bgp, BGP_CONFIG_CONFEDERATION)
    2031           0 :                     && !bgp_confederation_peers_check(bgp, *as)
    2032           0 :                     && bgp->as != *as)
    2033           0 :                         local_as = bgp->confed_id;
    2034             :                 else
    2035           4 :                         local_as = bgp->as;
    2036             : 
    2037           4 :                 peer_create(su, conf_if, bgp, local_as, *as, as_type, NULL,
    2038             :                             true);
    2039             :         }
    2040             : 
    2041             :         return 0;
    2042             : }
    2043             : 
    2044          14 : const char *bgp_get_name_by_role(uint8_t role)
    2045             : {
    2046          14 :         switch (role) {
    2047             :         case ROLE_PROVIDER:
    2048             :                 return "provider";
    2049           0 :         case ROLE_RS_SERVER:
    2050           0 :                 return "rs-server";
    2051           0 :         case ROLE_RS_CLIENT:
    2052           0 :                 return "rs-client";
    2053           0 :         case ROLE_CUSTOMER:
    2054           0 :                 return "customer";
    2055           0 :         case ROLE_PEER:
    2056           0 :                 return "peer";
    2057          14 :         case ROLE_UNDEFINED:
    2058          14 :                 return "undefined";
    2059             :         }
    2060           0 :         return "unknown";
    2061             : }
    2062             : 
    2063           0 : static void peer_group2peer_config_copy_af(struct peer_group *group,
    2064             :                                            struct peer *peer, afi_t afi,
    2065             :                                            safi_t safi)
    2066             : {
    2067           0 :         int in = FILTER_IN;
    2068           0 :         int out = FILTER_OUT;
    2069           0 :         uint64_t flags_tmp;
    2070           0 :         uint64_t pflags_ovrd;
    2071           0 :         uint8_t *pfilter_ovrd;
    2072           0 :         struct peer *conf;
    2073             : 
    2074           0 :         conf = group->conf;
    2075           0 :         pflags_ovrd = peer->af_flags_override[afi][safi];
    2076           0 :         pfilter_ovrd = &peer->filter_override[afi][safi][in];
    2077             : 
    2078             :         /* peer af_flags apply */
    2079           0 :         flags_tmp = conf->af_flags[afi][safi] & ~pflags_ovrd;
    2080           0 :         flags_tmp ^= conf->af_flags_invert[afi][safi]
    2081           0 :                      ^ peer->af_flags_invert[afi][safi];
    2082           0 :         flags_tmp &= ~pflags_ovrd;
    2083             : 
    2084           0 :         UNSET_FLAG(peer->af_flags[afi][safi], ~pflags_ovrd);
    2085           0 :         SET_FLAG(peer->af_flags[afi][safi], flags_tmp);
    2086           0 :         SET_FLAG(peer->af_flags_invert[afi][safi],
    2087             :                  conf->af_flags_invert[afi][safi]);
    2088             : 
    2089             :         /* maximum-prefix */
    2090           0 :         if (!CHECK_FLAG(pflags_ovrd, PEER_FLAG_MAX_PREFIX)) {
    2091           0 :                 PEER_ATTR_INHERIT(peer, group, pmax[afi][safi]);
    2092           0 :                 PEER_ATTR_INHERIT(peer, group, pmax_threshold[afi][safi]);
    2093           0 :                 PEER_ATTR_INHERIT(peer, group, pmax_restart[afi][safi]);
    2094             :         }
    2095             : 
    2096             :         /* maximum-prefix-out */
    2097           0 :         if (!CHECK_FLAG(pflags_ovrd, PEER_FLAG_MAX_PREFIX_OUT))
    2098           0 :                 PEER_ATTR_INHERIT(peer, group, pmax_out[afi][safi]);
    2099             : 
    2100             :         /* allowas-in */
    2101           0 :         if (!CHECK_FLAG(pflags_ovrd, PEER_FLAG_ALLOWAS_IN))
    2102           0 :                 PEER_ATTR_INHERIT(peer, group, allowas_in[afi][safi]);
    2103             : 
    2104             :         /* soo */
    2105           0 :         if (!CHECK_FLAG(pflags_ovrd, PEER_FLAG_SOO))
    2106           0 :                 PEER_ATTR_INHERIT(peer, group, soo[afi][safi]);
    2107             : 
    2108             :         /* weight */
    2109           0 :         if (!CHECK_FLAG(pflags_ovrd, PEER_FLAG_WEIGHT))
    2110           0 :                 PEER_ATTR_INHERIT(peer, group, weight[afi][safi]);
    2111             : 
    2112             :         /* default-originate route-map */
    2113           0 :         if (!CHECK_FLAG(pflags_ovrd, PEER_FLAG_DEFAULT_ORIGINATE)) {
    2114           0 :                 PEER_STR_ATTR_INHERIT(peer, group, default_rmap[afi][safi].name,
    2115             :                                       MTYPE_ROUTE_MAP_NAME);
    2116           0 :                 PEER_ATTR_INHERIT(peer, group, default_rmap[afi][safi].map);
    2117             :         }
    2118             : 
    2119             :         /* inbound filter apply */
    2120           0 :         if (!CHECK_FLAG(pfilter_ovrd[in], PEER_FT_DISTRIBUTE_LIST)) {
    2121           0 :                 PEER_STR_ATTR_INHERIT(peer, group,
    2122             :                                       filter[afi][safi].dlist[in].name,
    2123             :                                       MTYPE_BGP_FILTER_NAME);
    2124           0 :                 PEER_ATTR_INHERIT(peer, group,
    2125             :                                   filter[afi][safi].dlist[in].alist);
    2126             :         }
    2127             : 
    2128           0 :         if (!CHECK_FLAG(pfilter_ovrd[in], PEER_FT_PREFIX_LIST)) {
    2129           0 :                 PEER_STR_ATTR_INHERIT(peer, group,
    2130             :                                       filter[afi][safi].plist[in].name,
    2131             :                                       MTYPE_BGP_FILTER_NAME);
    2132           0 :                 PEER_ATTR_INHERIT(peer, group,
    2133             :                                   filter[afi][safi].plist[in].plist);
    2134             :         }
    2135             : 
    2136           0 :         if (!CHECK_FLAG(pfilter_ovrd[in], PEER_FT_FILTER_LIST)) {
    2137           0 :                 PEER_STR_ATTR_INHERIT(peer, group,
    2138             :                                       filter[afi][safi].aslist[in].name,
    2139             :                                       MTYPE_BGP_FILTER_NAME);
    2140           0 :                 PEER_ATTR_INHERIT(peer, group,
    2141             :                                   filter[afi][safi].aslist[in].aslist);
    2142             :         }
    2143             : 
    2144           0 :         if (!CHECK_FLAG(pfilter_ovrd[RMAP_IN], PEER_FT_ROUTE_MAP)) {
    2145           0 :                 PEER_STR_ATTR_INHERIT(peer, group,
    2146             :                                       filter[afi][safi].map[in].name,
    2147             :                                       MTYPE_BGP_FILTER_NAME);
    2148           0 :                 PEER_ATTR_INHERIT(peer, group,
    2149             :                                   filter[afi][safi].map[RMAP_IN].map);
    2150             :         }
    2151             : 
    2152             :         /* outbound filter apply */
    2153           0 :         if (!CHECK_FLAG(pfilter_ovrd[out], PEER_FT_DISTRIBUTE_LIST)) {
    2154           0 :                 PEER_STR_ATTR_INHERIT(peer, group,
    2155             :                                       filter[afi][safi].dlist[out].name,
    2156             :                                       MTYPE_BGP_FILTER_NAME);
    2157           0 :                 PEER_ATTR_INHERIT(peer, group,
    2158             :                                   filter[afi][safi].dlist[out].alist);
    2159             :         }
    2160             : 
    2161           0 :         if (!CHECK_FLAG(pfilter_ovrd[out], PEER_FT_PREFIX_LIST)) {
    2162           0 :                 PEER_STR_ATTR_INHERIT(peer, group,
    2163             :                                       filter[afi][safi].plist[out].name,
    2164             :                                       MTYPE_BGP_FILTER_NAME);
    2165           0 :                 PEER_ATTR_INHERIT(peer, group,
    2166             :                                   filter[afi][safi].plist[out].plist);
    2167             :         }
    2168             : 
    2169           0 :         if (!CHECK_FLAG(pfilter_ovrd[out], PEER_FT_FILTER_LIST)) {
    2170           0 :                 PEER_STR_ATTR_INHERIT(peer, group,
    2171             :                                       filter[afi][safi].aslist[out].name,
    2172             :                                       MTYPE_BGP_FILTER_NAME);
    2173           0 :                 PEER_ATTR_INHERIT(peer, group,
    2174             :                                   filter[afi][safi].aslist[out].aslist);
    2175             :         }
    2176             : 
    2177           0 :         if (!CHECK_FLAG(pfilter_ovrd[RMAP_OUT], PEER_FT_ROUTE_MAP)) {
    2178           0 :                 PEER_STR_ATTR_INHERIT(peer, group,
    2179             :                                       filter[afi][safi].map[RMAP_OUT].name,
    2180             :                                       MTYPE_BGP_FILTER_NAME);
    2181           0 :                 PEER_ATTR_INHERIT(peer, group,
    2182             :                                   filter[afi][safi].map[RMAP_OUT].map);
    2183             :         }
    2184             : 
    2185             :         /* nondirectional filter apply */
    2186           0 :         if (!CHECK_FLAG(pfilter_ovrd[0], PEER_FT_UNSUPPRESS_MAP)) {
    2187           0 :                 PEER_STR_ATTR_INHERIT(peer, group, filter[afi][safi].usmap.name,
    2188             :                                       MTYPE_BGP_FILTER_NAME);
    2189           0 :                 PEER_ATTR_INHERIT(peer, group, filter[afi][safi].usmap.map);
    2190             :         }
    2191             : 
    2192             :         /* Conditional Advertisements */
    2193           0 :         if (!CHECK_FLAG(pfilter_ovrd[RMAP_OUT], PEER_FT_ADVERTISE_MAP)) {
    2194           0 :                 PEER_STR_ATTR_INHERIT(peer, group,
    2195             :                                       filter[afi][safi].advmap.aname,
    2196             :                                       MTYPE_BGP_FILTER_NAME);
    2197           0 :                 PEER_ATTR_INHERIT(peer, group, filter[afi][safi].advmap.amap);
    2198           0 :                 PEER_STR_ATTR_INHERIT(peer, group,
    2199             :                                       filter[afi][safi].advmap.cname,
    2200             :                                       MTYPE_BGP_FILTER_NAME);
    2201           0 :                 PEER_ATTR_INHERIT(peer, group, filter[afi][safi].advmap.cmap);
    2202           0 :                 PEER_ATTR_INHERIT(peer, group,
    2203             :                                   filter[afi][safi].advmap.condition);
    2204             :         }
    2205             : 
    2206           0 :         if (peer->addpath_type[afi][safi] == BGP_ADDPATH_NONE) {
    2207           0 :                 peer->addpath_type[afi][safi] = conf->addpath_type[afi][safi];
    2208           0 :                 bgp_addpath_type_changed(conf->bgp);
    2209             :         }
    2210           0 : }
    2211             : 
    2212           0 : static int peer_activate_af(struct peer *peer, afi_t afi, safi_t safi)
    2213             : {
    2214           0 :         int active;
    2215           0 :         struct peer *other;
    2216             : 
    2217           0 :         if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    2218           0 :                 flog_err(EC_BGP_PEER_GROUP, "%s was called for peer-group %s",
    2219             :                          __func__, peer->host);
    2220           0 :                 return 1;
    2221             :         }
    2222             : 
    2223             :         /* Do not activate a peer for both SAFI_UNICAST and SAFI_LABELED_UNICAST
    2224             :          */
    2225           0 :         if ((safi == SAFI_UNICAST && peer->afc[afi][SAFI_LABELED_UNICAST])
    2226           0 :             || (safi == SAFI_LABELED_UNICAST && peer->afc[afi][SAFI_UNICAST]))
    2227             :                 return BGP_ERR_PEER_SAFI_CONFLICT;
    2228             : 
    2229             :         /* Nothing to do if we've already activated this peer */
    2230           0 :         if (peer->afc[afi][safi])
    2231             :                 return 0;
    2232             : 
    2233           0 :         if (peer_af_create(peer, afi, safi) == NULL)
    2234             :                 return 1;
    2235             : 
    2236           0 :         active = peer_active(peer);
    2237           0 :         peer->afc[afi][safi] = 1;
    2238             : 
    2239           0 :         if (peer->group)
    2240           0 :                 peer_group2peer_config_copy_af(peer->group, peer, afi, safi);
    2241             : 
    2242           0 :         if (!active && peer_active(peer)) {
    2243           0 :                 bgp_timer_set(peer);
    2244             :         } else {
    2245           0 :                 if (peer_established(peer)) {
    2246           0 :                         if (CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV)) {
    2247           0 :                                 peer->afc_adv[afi][safi] = 1;
    2248           0 :                                 bgp_capability_send(peer, afi, safi,
    2249             :                                                     CAPABILITY_CODE_MP,
    2250             :                                                     CAPABILITY_ACTION_SET);
    2251           0 :                                 if (peer->afc_recv[afi][safi]) {
    2252           0 :                                         peer->afc_nego[afi][safi] = 1;
    2253           0 :                                         bgp_announce_route(peer, afi, safi,
    2254             :                                                            false);
    2255             :                                 }
    2256             :                         } else {
    2257           0 :                                 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
    2258           0 :                                 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
    2259             :                                                 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    2260             :                         }
    2261             :                 }
    2262           0 :                 if (peer->status == OpenSent || peer->status == OpenConfirm) {
    2263           0 :                         peer->last_reset = PEER_DOWN_AF_ACTIVATE;
    2264           0 :                         bgp_notify_send(peer, BGP_NOTIFY_CEASE,
    2265             :                                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    2266             :                 }
    2267             :                 /*
    2268             :                  * If we are turning on a AFI/SAFI locally and we've
    2269             :                  * started bringing a peer up, we need to tell
    2270             :                  * the other peer to restart because we might loose
    2271             :                  * configuration here because when the doppelganger
    2272             :                  * gets to a established state due to how
    2273             :                  * we resolve we could just overwrite the afi/safi
    2274             :                  * activation.
    2275             :                  */
    2276           0 :                 other = peer->doppelganger;
    2277           0 :                 if (other
    2278           0 :                     && (other->status == OpenSent
    2279           0 :                         || other->status == OpenConfirm)) {
    2280           0 :                         other->last_reset = PEER_DOWN_AF_ACTIVATE;
    2281           0 :                         bgp_notify_send(other, BGP_NOTIFY_CEASE,
    2282             :                                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    2283             :                 }
    2284             :         }
    2285             : 
    2286             :         return 0;
    2287             : }
    2288             : 
    2289             : /* Activate the peer or peer group for specified AFI and SAFI.  */
    2290           0 : int peer_activate(struct peer *peer, afi_t afi, safi_t safi)
    2291             : {
    2292           0 :         int ret = 0;
    2293           0 :         struct peer_group *group;
    2294           0 :         struct listnode *node, *nnode;
    2295           0 :         struct peer *tmp_peer;
    2296           0 :         struct bgp *bgp;
    2297             : 
    2298             :         /* Nothing to do if we've already activated this peer */
    2299           0 :         if (peer->afc[afi][safi])
    2300             :                 return ret;
    2301             : 
    2302           0 :         bgp = peer->bgp;
    2303             : 
    2304             :         /* This is a peer-group so activate all of the members of the
    2305             :          * peer-group as well */
    2306           0 :         if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    2307             : 
    2308             :                 /* Do not activate a peer for both SAFI_UNICAST and
    2309             :                  * SAFI_LABELED_UNICAST */
    2310           0 :                 if ((safi == SAFI_UNICAST
    2311           0 :                      && peer->afc[afi][SAFI_LABELED_UNICAST])
    2312           0 :                     || (safi == SAFI_LABELED_UNICAST
    2313           0 :                         && peer->afc[afi][SAFI_UNICAST]))
    2314             :                         return BGP_ERR_PEER_SAFI_CONFLICT;
    2315             : 
    2316           0 :                 peer->afc[afi][safi] = 1;
    2317           0 :                 group = peer->group;
    2318             : 
    2319           0 :                 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, tmp_peer)) {
    2320           0 :                         ret |= peer_activate_af(tmp_peer, afi, safi);
    2321             :                 }
    2322             :         } else {
    2323           0 :                 ret |= peer_activate_af(peer, afi, safi);
    2324             :         }
    2325             : 
    2326             :         /* If this is the first peer to be activated for this
    2327             :          * afi/labeled-unicast recalc bestpaths to trigger label allocation */
    2328           0 :         if (ret != BGP_ERR_PEER_SAFI_CONFLICT && safi == SAFI_LABELED_UNICAST
    2329           0 :             && !bgp->allocate_mpls_labels[afi][SAFI_UNICAST]) {
    2330             : 
    2331           0 :                 if (BGP_DEBUG(zebra, ZEBRA))
    2332           0 :                         zlog_debug(
    2333             :                                 "peer(s) are now active for labeled-unicast, allocate MPLS labels");
    2334             : 
    2335           0 :                 bgp->allocate_mpls_labels[afi][SAFI_UNICAST] = 1;
    2336           0 :                 bgp_recalculate_afi_safi_bestpaths(bgp, afi, SAFI_UNICAST);
    2337             :         }
    2338             : 
    2339           0 :         if (safi == SAFI_FLOWSPEC) {
    2340             :                 /* connect to table manager */
    2341           0 :                 bgp_zebra_init_tm_connect(bgp);
    2342             :         }
    2343             :         return ret;
    2344             : }
    2345             : 
    2346           0 : static bool non_peergroup_deactivate_af(struct peer *peer, afi_t afi,
    2347             :                                         safi_t safi)
    2348             : {
    2349           0 :         if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    2350           0 :                 flog_err(EC_BGP_PEER_GROUP, "%s was called for peer-group %s",
    2351             :                          __func__, peer->host);
    2352           0 :                 return true;
    2353             :         }
    2354             : 
    2355             :         /* Nothing to do if we've already deactivated this peer */
    2356           0 :         if (!peer->afc[afi][safi])
    2357             :                 return false;
    2358             : 
    2359             :         /* De-activate the address family configuration. */
    2360           0 :         peer->afc[afi][safi] = 0;
    2361             : 
    2362           0 :         if (peer_af_delete(peer, afi, safi) != 0) {
    2363           0 :                 flog_err(EC_BGP_PEER_DELETE,
    2364             :                          "couldn't delete af structure for peer %s(%s, %s)",
    2365             :                          peer->host, afi2str(afi), safi2str(safi));
    2366           0 :                 return true;
    2367             :         }
    2368             : 
    2369           0 :         if (peer_established(peer)) {
    2370           0 :                 if (CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV)) {
    2371           0 :                         peer->afc_adv[afi][safi] = 0;
    2372           0 :                         peer->afc_nego[afi][safi] = 0;
    2373             : 
    2374           0 :                         if (peer_active_nego(peer)) {
    2375           0 :                                 bgp_capability_send(peer, afi, safi,
    2376             :                                                     CAPABILITY_CODE_MP,
    2377             :                                                     CAPABILITY_ACTION_UNSET);
    2378           0 :                                 bgp_clear_route(peer, afi, safi);
    2379           0 :                                 peer->pcount[afi][safi] = 0;
    2380             :                         } else {
    2381           0 :                                 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
    2382           0 :                                 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
    2383             :                                                 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    2384             :                         }
    2385             :                 } else {
    2386           0 :                         peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
    2387           0 :                         bgp_notify_send(peer, BGP_NOTIFY_CEASE,
    2388             :                                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    2389             :                 }
    2390             :         }
    2391             : 
    2392             :         return false;
    2393             : }
    2394             : 
    2395           0 : int peer_deactivate(struct peer *peer, afi_t afi, safi_t safi)
    2396             : {
    2397           0 :         int ret = 0;
    2398           0 :         struct peer_group *group;
    2399           0 :         struct peer *tmp_peer;
    2400           0 :         struct listnode *node, *nnode;
    2401           0 :         struct bgp *bgp;
    2402             : 
    2403             :         /* Nothing to do if we've already de-activated this peer */
    2404           0 :         if (!peer->afc[afi][safi])
    2405             :                 return ret;
    2406             : 
    2407             :         /* This is a peer-group so de-activate all of the members of the
    2408             :          * peer-group as well */
    2409           0 :         if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    2410           0 :                 peer->afc[afi][safi] = 0;
    2411           0 :                 group = peer->group;
    2412             : 
    2413           0 :                 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, tmp_peer)) {
    2414           0 :                         ret |= non_peergroup_deactivate_af(tmp_peer, afi, safi);
    2415             :                 }
    2416             :         } else {
    2417           0 :                 ret |= non_peergroup_deactivate_af(peer, afi, safi);
    2418             :         }
    2419             : 
    2420           0 :         bgp = peer->bgp;
    2421             : 
    2422             :         /* If this is the last peer to be deactivated for this
    2423             :          * afi/labeled-unicast recalc bestpaths to trigger label deallocation */
    2424           0 :         if (safi == SAFI_LABELED_UNICAST
    2425           0 :             && bgp->allocate_mpls_labels[afi][SAFI_UNICAST]
    2426           0 :             && !bgp_afi_safi_peer_exists(bgp, afi, safi)) {
    2427             : 
    2428           0 :                 if (BGP_DEBUG(zebra, ZEBRA))
    2429           0 :                         zlog_debug(
    2430             :                                 "peer(s) are no longer active for labeled-unicast, deallocate MPLS labels");
    2431             : 
    2432           0 :                 bgp->allocate_mpls_labels[afi][SAFI_UNICAST] = 0;
    2433           0 :                 bgp_recalculate_afi_safi_bestpaths(bgp, afi, SAFI_UNICAST);
    2434             :         }
    2435             :         return ret;
    2436             : }
    2437             : 
    2438           0 : void peer_nsf_stop(struct peer *peer)
    2439             : {
    2440           0 :         afi_t afi;
    2441           0 :         safi_t safi;
    2442             : 
    2443           0 :         UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
    2444           0 :         UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
    2445             : 
    2446           0 :         FOREACH_AFI_SAFI_NSF (afi, safi) {
    2447           0 :                 peer->nsf[afi][safi] = 0;
    2448           0 :                 THREAD_OFF(peer->t_llgr_stale[afi][safi]);
    2449             :         }
    2450             : 
    2451           0 :         if (peer->t_gr_restart) {
    2452           0 :                 THREAD_OFF(peer->t_gr_restart);
    2453           0 :                 if (bgp_debug_neighbor_events(peer))
    2454           0 :                         zlog_debug("%pBP graceful restart timer stopped", peer);
    2455             :         }
    2456           0 :         if (peer->t_gr_stale) {
    2457           0 :                 THREAD_OFF(peer->t_gr_stale);
    2458           0 :                 if (bgp_debug_neighbor_events(peer))
    2459           0 :                         zlog_debug(
    2460             :                                 "%pBP graceful restart stalepath timer stopped",
    2461             :                                 peer);
    2462             :         }
    2463           0 :         bgp_clear_route_all(peer);
    2464           0 : }
    2465             : 
    2466             : /* Delete peer from confguration.
    2467             :  *
    2468             :  * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
    2469             :  * it to "cool off" and refcounts to hit 0, at which state it is freed.
    2470             :  *
    2471             :  * This function /should/ take care to be idempotent, to guard against
    2472             :  * it being called multiple times through stray events that come in
    2473             :  * that happen to result in this function being called again.  That
    2474             :  * said, getting here for a "Deleted" peer is a bug in the neighbour
    2475             :  * FSM.
    2476             :  */
    2477           9 : int peer_delete(struct peer *peer)
    2478             : {
    2479           9 :         int i;
    2480           9 :         afi_t afi;
    2481           9 :         safi_t safi;
    2482           9 :         struct bgp *bgp;
    2483           9 :         struct bgp_filter *filter;
    2484           9 :         struct listnode *pn;
    2485           9 :         int accept_peer;
    2486             : 
    2487           9 :         assert(peer->status != Deleted);
    2488             : 
    2489           9 :         bgp = peer->bgp;
    2490           9 :         accept_peer = CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER);
    2491             : 
    2492           9 :         bgp_soft_reconfig_table_task_cancel(bgp, NULL, peer);
    2493             : 
    2494           9 :         bgp_keepalives_off(peer);
    2495           9 :         bgp_reads_off(peer);
    2496           9 :         bgp_writes_off(peer);
    2497           9 :         thread_cancel_event_ready(bm->master, peer);
    2498         234 :         FOREACH_AFI_SAFI (afi, safi)
    2499         189 :                 THREAD_OFF(peer->t_revalidate_all[afi][safi]);
    2500           9 :         assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_WRITES_ON));
    2501           9 :         assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_READS_ON));
    2502           9 :         assert(!CHECK_FLAG(peer->thread_flags, PEER_THREAD_KEEPALIVES_ON));
    2503             : 
    2504           9 :         if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT))
    2505           0 :                 peer_nsf_stop(peer);
    2506             : 
    2507           9 :         SET_FLAG(peer->flags, PEER_FLAG_DELETE);
    2508             : 
    2509             :         /* Remove BFD settings. */
    2510           9 :         if (peer->bfd_config)
    2511           0 :                 bgp_peer_remove_bfd_config(peer);
    2512             : 
    2513             :         /* If this peer belongs to peer group, clear up the
    2514             :            relationship.  */
    2515           9 :         if (peer->group) {
    2516           0 :                 if (peer_dynamic_neighbor(peer))
    2517           0 :                         peer_drop_dynamic_neighbor(peer);
    2518             : 
    2519           0 :                 if ((pn = listnode_lookup(peer->group->peer, peer))) {
    2520           0 :                         peer = peer_unlock(
    2521             :                                 peer); /* group->peer list reference */
    2522           0 :                         list_delete_node(peer->group->peer, pn);
    2523             :                 }
    2524           0 :                 peer->group = NULL;
    2525             :         }
    2526             : 
    2527             :         /* Withdraw all information from routing table.  We can not use
    2528             :          * BGP_EVENT_ADD (peer, BGP_Stop) at here.  Because the event is
    2529             :          * executed after peer structure is deleted.
    2530             :          */
    2531           9 :         peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
    2532           9 :         bgp_stop(peer);
    2533           9 :         UNSET_FLAG(peer->flags, PEER_FLAG_DELETE);
    2534             : 
    2535           9 :         if (peer->doppelganger) {
    2536           2 :                 peer->doppelganger->doppelganger = NULL;
    2537           2 :                 peer->doppelganger = NULL;
    2538             :         }
    2539             : 
    2540           9 :         UNSET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER);
    2541           9 :         bgp_fsm_change_status(peer, Deleted);
    2542             : 
    2543             :         /* Remove from NHT */
    2544           9 :         if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
    2545           4 :                 bgp_unlink_nexthop_by_peer(peer);
    2546             : 
    2547             :         /* Password configuration */
    2548           9 :         if (CHECK_FLAG(peer->flags, PEER_FLAG_PASSWORD)) {
    2549           0 :                 XFREE(MTYPE_PEER_PASSWORD, peer->password);
    2550           0 :                 if (!accept_peer && !BGP_PEER_SU_UNSPEC(peer)
    2551           0 :                     && !CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)
    2552           0 :                     && !CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR))
    2553           0 :                         bgp_md5_unset(peer);
    2554             :         }
    2555             : 
    2556           9 :         bgp_timer_set(peer); /* stops all timers for Deleted */
    2557             : 
    2558             :         /* Delete from all peer list. */
    2559           9 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)
    2560           9 :             && (pn = listnode_lookup(bgp->peer, peer))) {
    2561             :                 /*
    2562             :                  * Removing from the list node first because
    2563             :                  * peer_unlock *can* call peer_delete( I know,
    2564             :                  * I know ).  So let's remove it and in
    2565             :                  * the su recalculate function we'll ensure
    2566             :                  * it's in there or not.
    2567             :                  */
    2568           6 :                 list_delete_node(bgp->peer, pn);
    2569           6 :                 hash_release(bgp->peerhash, peer);
    2570           6 :                 peer_unlock(peer); /* bgp peer list reference */
    2571             :         }
    2572             : 
    2573             :         /* Buffers.  */
    2574           9 :         if (peer->ibuf) {
    2575           9 :                 stream_fifo_free(peer->ibuf);
    2576           9 :                 peer->ibuf = NULL;
    2577             :         }
    2578             : 
    2579           9 :         if (peer->obuf) {
    2580           9 :                 stream_fifo_free(peer->obuf);
    2581           9 :                 peer->obuf = NULL;
    2582             :         }
    2583             : 
    2584           9 :         if (peer->ibuf_work) {
    2585           9 :                 ringbuf_del(peer->ibuf_work);
    2586           9 :                 peer->ibuf_work = NULL;
    2587             :         }
    2588             : 
    2589           9 :         if (peer->obuf_work) {
    2590           9 :                 stream_free(peer->obuf_work);
    2591           9 :                 peer->obuf_work = NULL;
    2592             :         }
    2593             : 
    2594           9 :         if (peer->scratch) {
    2595           9 :                 stream_free(peer->scratch);
    2596           9 :                 peer->scratch = NULL;
    2597             :         }
    2598             : 
    2599             :         /* Local and remote addresses. */
    2600           9 :         if (peer->su_local) {
    2601           5 :                 sockunion_free(peer->su_local);
    2602           5 :                 peer->su_local = NULL;
    2603             :         }
    2604             : 
    2605           9 :         if (peer->su_remote) {
    2606           5 :                 sockunion_free(peer->su_remote);
    2607           5 :                 peer->su_remote = NULL;
    2608             :         }
    2609             : 
    2610             :         /* Free filter related memory.  */
    2611         225 :         FOREACH_AFI_SAFI (afi, safi) {
    2612         567 :                 filter = &peer->filter[afi][safi];
    2613             : 
    2614         567 :                 for (i = FILTER_IN; i < FILTER_MAX; i++) {
    2615         378 :                         XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[i].name);
    2616         378 :                         XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[i].name);
    2617         378 :                         XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[i].name);
    2618             :                 }
    2619             : 
    2620         567 :                 for (i = RMAP_IN; i < RMAP_MAX; i++) {
    2621         378 :                         XFREE(MTYPE_BGP_FILTER_NAME, filter->map[i].name);
    2622             :                 }
    2623             : 
    2624         189 :                 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
    2625         189 :                 XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name);
    2626         189 :                 ecommunity_free(&peer->soo[afi][safi]);
    2627             :         }
    2628             : 
    2629         225 :         FOREACH_AFI_SAFI (afi, safi)
    2630         189 :                 peer_af_delete(peer, afi, safi);
    2631             : 
    2632           9 :         XFREE(MTYPE_BGP_PEER_HOST, peer->hostname);
    2633           9 :         XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
    2634             : 
    2635           9 :         peer_unlock(peer); /* initial reference */
    2636             : 
    2637           9 :         return 0;
    2638             : }
    2639             : 
    2640           0 : static int peer_group_cmp(struct peer_group *g1, struct peer_group *g2)
    2641             : {
    2642           0 :         return strcmp(g1->name, g2->name);
    2643             : }
    2644             : 
    2645             : /* Peer group cofiguration. */
    2646           0 : static struct peer_group *peer_group_new(void)
    2647             : {
    2648           0 :         return XCALLOC(MTYPE_PEER_GROUP, sizeof(struct peer_group));
    2649             : }
    2650             : 
    2651           0 : static void peer_group_free(struct peer_group *group)
    2652             : {
    2653           0 :         XFREE(MTYPE_PEER_GROUP, group);
    2654             : }
    2655             : 
    2656           0 : struct peer_group *peer_group_lookup(struct bgp *bgp, const char *name)
    2657             : {
    2658           0 :         struct peer_group *group;
    2659           0 :         struct listnode *node, *nnode;
    2660             : 
    2661           0 :         for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
    2662           0 :                 if (strcmp(group->name, name) == 0)
    2663           0 :                         return group;
    2664             :         }
    2665             :         return NULL;
    2666             : }
    2667             : 
    2668           0 : struct peer_group *peer_group_get(struct bgp *bgp, const char *name)
    2669             : {
    2670           0 :         struct peer_group *group;
    2671           0 :         afi_t afi;
    2672           0 :         safi_t safi;
    2673             : 
    2674           0 :         group = peer_group_lookup(bgp, name);
    2675           0 :         if (group)
    2676             :                 return group;
    2677             : 
    2678           0 :         group = peer_group_new();
    2679           0 :         group->bgp = bgp;
    2680           0 :         XFREE(MTYPE_PEER_GROUP_HOST, group->name);
    2681           0 :         group->name = XSTRDUP(MTYPE_PEER_GROUP_HOST, name);
    2682           0 :         group->peer = list_new();
    2683           0 :         for (afi = AFI_IP; afi < AFI_MAX; afi++)
    2684           0 :                 group->listen_range[afi] = list_new();
    2685           0 :         group->conf = peer_new(bgp);
    2686           0 :         FOREACH_AFI_SAFI (afi, safi) {
    2687           0 :                 if (bgp->default_af[afi][safi])
    2688           0 :                         group->conf->afc[afi][safi] = 1;
    2689             :         }
    2690           0 :         XFREE(MTYPE_BGP_PEER_HOST, group->conf->host);
    2691           0 :         group->conf->host = XSTRDUP(MTYPE_BGP_PEER_HOST, name);
    2692           0 :         group->conf->group = group;
    2693           0 :         group->conf->as = 0;
    2694           0 :         group->conf->ttl = BGP_DEFAULT_TTL;
    2695           0 :         group->conf->gtsm_hops = BGP_GTSM_HOPS_DISABLED;
    2696           0 :         group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
    2697           0 :         SET_FLAG(group->conf->sflags, PEER_STATUS_GROUP);
    2698           0 :         listnode_add_sort(bgp->group, group);
    2699             : 
    2700           0 :         return group;
    2701             : }
    2702             : 
    2703           0 : static void peer_group2peer_config_copy(struct peer_group *group,
    2704             :                                         struct peer *peer)
    2705             : {
    2706           0 :         uint32_t flags_tmp;
    2707           0 :         struct peer *conf;
    2708           0 :         bool config_node = !!CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
    2709             : 
    2710           0 :         conf = group->conf;
    2711             : 
    2712             :         /* remote-as */
    2713           0 :         if (conf->as)
    2714           0 :                 peer->as = conf->as;
    2715             : 
    2716             :         /* local-as */
    2717           0 :         if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_LOCAL_AS))
    2718           0 :                 peer->change_local_as = conf->change_local_as;
    2719             : 
    2720             :         /* If peer-group has configured TTL then override it */
    2721           0 :         if (conf->ttl != BGP_DEFAULT_TTL)
    2722           0 :                 peer->ttl = conf->ttl;
    2723             : 
    2724             :         /* GTSM hops */
    2725           0 :         peer->gtsm_hops = conf->gtsm_hops;
    2726             : 
    2727             :         /* peer flags apply */
    2728           0 :         flags_tmp = conf->flags & ~peer->flags_override;
    2729           0 :         flags_tmp ^= conf->flags_invert ^ peer->flags_invert;
    2730           0 :         flags_tmp &= ~peer->flags_override;
    2731             : 
    2732           0 :         UNSET_FLAG(peer->flags, ~peer->flags_override);
    2733           0 :         SET_FLAG(peer->flags, flags_tmp);
    2734           0 :         SET_FLAG(peer->flags_invert, conf->flags_invert);
    2735             : 
    2736           0 :         if (config_node)
    2737           0 :                 SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
    2738             : 
    2739             :         /* peer timers apply */
    2740           0 :         if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_TIMER)) {
    2741           0 :                 PEER_ATTR_INHERIT(peer, group, holdtime);
    2742           0 :                 PEER_ATTR_INHERIT(peer, group, keepalive);
    2743             :         }
    2744             : 
    2745           0 :         if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_TIMER_CONNECT)) {
    2746           0 :                 PEER_ATTR_INHERIT(peer, group, connect);
    2747           0 :                 if (CHECK_FLAG(conf->flags, PEER_FLAG_TIMER_CONNECT))
    2748           0 :                         peer->v_connect = conf->connect;
    2749             :                 else
    2750           0 :                         peer->v_connect = peer->bgp->default_connect_retry;
    2751             :         }
    2752             : 
    2753           0 :         if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_TIMER_DELAYOPEN)) {
    2754           0 :                 PEER_ATTR_INHERIT(peer, group, delayopen);
    2755           0 :                 if (CHECK_FLAG(conf->flags, PEER_FLAG_TIMER_DELAYOPEN))
    2756           0 :                         peer->v_delayopen = conf->delayopen;
    2757             :                 else
    2758           0 :                         peer->v_delayopen = peer->bgp->default_delayopen;
    2759             :         }
    2760             : 
    2761             :         /* advertisement-interval apply */
    2762           0 :         if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_ROUTEADV)) {
    2763           0 :                 PEER_ATTR_INHERIT(peer, group, routeadv);
    2764           0 :                 if (CHECK_FLAG(conf->flags, PEER_FLAG_ROUTEADV))
    2765           0 :                         peer->v_routeadv = conf->routeadv;
    2766             :                 else
    2767           0 :                         peer->v_routeadv = (peer_sort(peer) == BGP_PEER_IBGP)
    2768             :                                                    ? BGP_DEFAULT_IBGP_ROUTEADV
    2769             :                                                    : BGP_DEFAULT_EBGP_ROUTEADV;
    2770             :         }
    2771             : 
    2772             :         /* capability extended-nexthop apply */
    2773           0 :         if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_CAPABILITY_ENHE))
    2774           0 :                 if (CHECK_FLAG(conf->flags, PEER_FLAG_CAPABILITY_ENHE))
    2775           0 :                         SET_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE);
    2776             : 
    2777             :         /* password apply */
    2778           0 :         if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_PASSWORD))
    2779           0 :                 PEER_STR_ATTR_INHERIT(peer, group, password,
    2780             :                                       MTYPE_PEER_PASSWORD);
    2781             : 
    2782           0 :         if (!BGP_PEER_SU_UNSPEC(peer))
    2783           0 :                 bgp_md5_set(peer);
    2784             : 
    2785             :         /* update-source apply */
    2786           0 :         if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_UPDATE_SOURCE)) {
    2787           0 :                 if (conf->update_source) {
    2788           0 :                         XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
    2789           0 :                         PEER_SU_ATTR_INHERIT(peer, group, update_source);
    2790           0 :                 } else if (conf->update_if) {
    2791           0 :                         sockunion_free(peer->update_source);
    2792           0 :                         PEER_STR_ATTR_INHERIT(peer, group, update_if,
    2793             :                                               MTYPE_PEER_UPDATE_SOURCE);
    2794             :                 }
    2795             :         }
    2796             : 
    2797             :         /* role */
    2798           0 :         PEER_ATTR_INHERIT(peer, group, local_role);
    2799             : 
    2800             :         /* Update GR flags for the peer. */
    2801           0 :         bgp_peer_gr_flags_update(peer);
    2802             : 
    2803             :         /* Apply BFD settings from group to peer if it exists. */
    2804           0 :         if (conf->bfd_config) {
    2805           0 :                 bgp_peer_configure_bfd(peer, false);
    2806           0 :                 bgp_peer_config_apply(peer, group);
    2807             :         }
    2808           0 : }
    2809             : 
    2810             : /* Peer group's remote AS configuration.  */
    2811           0 : int peer_group_remote_as(struct bgp *bgp, const char *group_name, as_t *as,
    2812             :                          int as_type)
    2813             : {
    2814           0 :         struct peer_group *group;
    2815           0 :         struct peer *peer;
    2816           0 :         struct listnode *node, *nnode;
    2817             : 
    2818           0 :         group = peer_group_lookup(bgp, group_name);
    2819           0 :         if (!group)
    2820             :                 return -1;
    2821             : 
    2822           0 :         if ((as_type == group->conf->as_type) && (group->conf->as == *as))
    2823             :                 return 0;
    2824             : 
    2825             : 
    2826             :         /* When we setup peer-group AS number all peer group member's AS
    2827             :            number must be updated to same number.  */
    2828           0 :         peer_as_change(group->conf, *as, as_type);
    2829             : 
    2830           0 :         for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
    2831           0 :                 if (((peer->as_type == AS_SPECIFIED) && peer->as != *as)
    2832           0 :                     || (peer->as_type != as_type))
    2833           0 :                         peer_as_change(peer, *as, as_type);
    2834             :         }
    2835             : 
    2836             :         return 0;
    2837             : }
    2838             : 
    2839           0 : void peer_notify_unconfig(struct peer *peer)
    2840             : {
    2841           0 :         if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
    2842           0 :                 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
    2843             :                                 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
    2844           0 : }
    2845             : 
    2846           4 : static void peer_notify_shutdown(struct peer *peer)
    2847             : {
    2848           4 :         if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)) {
    2849           1 :                 if (bgp_debug_neighbor_events(peer))
    2850           0 :                         zlog_debug(
    2851             :                                 "%pBP configured Graceful-Restart, skipping shutdown notification",
    2852             :                                 peer);
    2853           1 :                 return;
    2854             :         }
    2855             : 
    2856           3 :         if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
    2857           0 :                 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
    2858             :                                 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
    2859             : }
    2860             : 
    2861           0 : void peer_group_notify_unconfig(struct peer_group *group)
    2862             : {
    2863           0 :         struct peer *peer, *other;
    2864           0 :         struct listnode *node, *nnode;
    2865             : 
    2866           0 :         for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
    2867           0 :                 other = peer->doppelganger;
    2868           0 :                 if (other && other->status != Deleted) {
    2869           0 :                         other->group = NULL;
    2870           0 :                         peer_notify_unconfig(other);
    2871             :                 } else
    2872           0 :                         peer_notify_unconfig(peer);
    2873             :         }
    2874           0 : }
    2875             : 
    2876           0 : int peer_group_delete(struct peer_group *group)
    2877             : {
    2878           0 :         struct bgp *bgp;
    2879           0 :         struct peer *peer;
    2880           0 :         struct prefix *prefix;
    2881           0 :         struct peer *other;
    2882           0 :         struct listnode *node, *nnode;
    2883           0 :         afi_t afi;
    2884             : 
    2885           0 :         bgp = group->bgp;
    2886             : 
    2887           0 :         for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
    2888           0 :                 other = peer->doppelganger;
    2889             : 
    2890           0 :                 if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE))
    2891           0 :                         bgp_zebra_terminate_radv(bgp, peer);
    2892             : 
    2893           0 :                 peer_delete(peer);
    2894           0 :                 if (other && other->status != Deleted) {
    2895           0 :                         other->group = NULL;
    2896           0 :                         peer_delete(other);
    2897             :                 }
    2898             :         }
    2899           0 :         list_delete(&group->peer);
    2900             : 
    2901           0 :         for (afi = AFI_IP; afi < AFI_MAX; afi++) {
    2902           0 :                 for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, nnode,
    2903             :                                        prefix)) {
    2904           0 :                         prefix_free(&prefix);
    2905             :                 }
    2906           0 :                 list_delete(&group->listen_range[afi]);
    2907             :         }
    2908             : 
    2909           0 :         XFREE(MTYPE_PEER_GROUP_HOST, group->name);
    2910           0 :         group->name = NULL;
    2911             : 
    2912           0 :         if (group->conf->bfd_config)
    2913           0 :                 bgp_peer_remove_bfd_config(group->conf);
    2914             : 
    2915           0 :         group->conf->group = NULL;
    2916           0 :         peer_delete(group->conf);
    2917             : 
    2918             :         /* Delete from all peer_group list. */
    2919           0 :         listnode_delete(bgp->group, group);
    2920             : 
    2921           0 :         peer_group_free(group);
    2922             : 
    2923           0 :         return 0;
    2924             : }
    2925             : 
    2926           0 : int peer_group_remote_as_delete(struct peer_group *group)
    2927             : {
    2928           0 :         struct peer *peer, *other;
    2929           0 :         struct listnode *node, *nnode;
    2930             : 
    2931           0 :         if ((group->conf->as_type == AS_UNSPECIFIED)
    2932           0 :             || ((!group->conf->as) && (group->conf->as_type == AS_SPECIFIED)))
    2933             :                 return 0;
    2934             : 
    2935           0 :         for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
    2936           0 :                 other = peer->doppelganger;
    2937             : 
    2938           0 :                 if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE))
    2939           0 :                         bgp_zebra_terminate_radv(peer->bgp, peer);
    2940             : 
    2941           0 :                 peer_delete(peer);
    2942             : 
    2943           0 :                 if (other && other->status != Deleted) {
    2944           0 :                         other->group = NULL;
    2945           0 :                         peer_delete(other);
    2946             :                 }
    2947             :         }
    2948           0 :         list_delete_all_node(group->peer);
    2949             : 
    2950           0 :         group->conf->as = 0;
    2951           0 :         group->conf->as_type = AS_UNSPECIFIED;
    2952             : 
    2953           0 :         return 0;
    2954             : }
    2955             : 
    2956           0 : int peer_group_listen_range_add(struct peer_group *group, struct prefix *range)
    2957             : {
    2958           0 :         struct prefix *prefix;
    2959           0 :         struct listnode *node, *nnode;
    2960           0 :         afi_t afi;
    2961             : 
    2962           0 :         afi = family2afi(range->family);
    2963             : 
    2964             :         /* Group needs remote AS configured. */
    2965           0 :         if (group->conf->as_type == AS_UNSPECIFIED)
    2966             :                 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
    2967             : 
    2968             :         /* Ensure no duplicates. Currently we don't care about overlaps. */
    2969           0 :         for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, nnode, prefix)) {
    2970           0 :                 if (prefix_same(range, prefix))
    2971             :                         return 0;
    2972             :         }
    2973             : 
    2974           0 :         prefix = prefix_new();
    2975           0 :         prefix_copy(prefix, range);
    2976           0 :         listnode_add(group->listen_range[afi], prefix);
    2977             : 
    2978             :         /* Update passwords for new ranges */
    2979           0 :         if (group->conf->password)
    2980           0 :                 bgp_md5_set_prefix(group->bgp, prefix, group->conf->password);
    2981             : 
    2982             :         return 0;
    2983             : }
    2984             : 
    2985           0 : int peer_group_listen_range_del(struct peer_group *group, struct prefix *range)
    2986             : {
    2987           0 :         struct prefix *prefix, prefix2;
    2988           0 :         struct listnode *node, *nnode;
    2989           0 :         struct peer *peer;
    2990           0 :         afi_t afi;
    2991             : 
    2992           0 :         afi = family2afi(range->family);
    2993             : 
    2994             :         /* Identify the listen range. */
    2995           0 :         for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, nnode, prefix)) {
    2996           0 :                 if (prefix_same(range, prefix))
    2997             :                         break;
    2998             :         }
    2999             : 
    3000           0 :         if (!prefix)
    3001             :                 return BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_NOT_FOUND;
    3002             : 
    3003             :         /* Dispose off any dynamic neighbors that exist due to this listen range
    3004             :          */
    3005           0 :         for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
    3006           0 :                 if (!peer_dynamic_neighbor(peer))
    3007           0 :                         continue;
    3008             : 
    3009           0 :                 if (sockunion2hostprefix(&peer->su, &prefix2)
    3010           0 :                     && prefix_match(prefix, &prefix2)) {
    3011           0 :                         if (bgp_debug_neighbor_events(peer))
    3012           0 :                                 zlog_debug(
    3013             :                                         "Deleting dynamic neighbor %s group %s upon delete of listen range %pFX",
    3014             :                                         peer->host, group->name, prefix);
    3015           0 :                         peer_delete(peer);
    3016             :                 }
    3017             :         }
    3018             : 
    3019             :         /* Get rid of the listen range */
    3020           0 :         listnode_delete(group->listen_range[afi], prefix);
    3021             : 
    3022             :         /* Remove passwords for deleted ranges */
    3023           0 :         if (group->conf->password)
    3024           0 :                 bgp_md5_unset_prefix(group->bgp, prefix);
    3025             : 
    3026             :         return 0;
    3027             : }
    3028             : 
    3029             : /* Bind specified peer to peer group.  */
    3030           0 : int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer,
    3031             :                     struct peer_group *group, as_t *as)
    3032             : {
    3033           0 :         int first_member = 0;
    3034           0 :         afi_t afi;
    3035           0 :         safi_t safi;
    3036           0 :         enum bgp_peer_sort ptype, gtype;
    3037             : 
    3038             :         /* Lookup the peer.  */
    3039           0 :         if (!peer)
    3040           0 :                 peer = peer_lookup(bgp, su);
    3041             : 
    3042             :         /* The peer exist, bind it to the peer-group */
    3043           0 :         if (peer) {
    3044             :                 /* When the peer already belongs to a peer-group, check the
    3045             :                  * consistency.  */
    3046           0 :                 if (peer_group_active(peer)) {
    3047             : 
    3048             :                         /* The peer is already bound to the peer-group,
    3049             :                          * nothing to do
    3050             :                          */
    3051           0 :                         if (strcmp(peer->group->name, group->name) == 0)
    3052             :                                 return 0;
    3053             :                         else
    3054             :                                 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
    3055             :                 }
    3056             : 
    3057             :                 /* The peer has not specified a remote-as, inherit it from the
    3058             :                  * peer-group */
    3059           0 :                 if (peer->as_type == AS_UNSPECIFIED) {
    3060           0 :                         peer->as_type = group->conf->as_type;
    3061           0 :                         peer->as = group->conf->as;
    3062           0 :                         peer->sort = group->conf->sort;
    3063             :                 }
    3064             : 
    3065           0 :                 ptype = peer_sort(peer);
    3066           0 :                 if (!group->conf->as && ptype != BGP_PEER_UNSPECIFIED) {
    3067           0 :                         gtype = peer_sort(group->conf);
    3068           0 :                         if ((gtype != BGP_PEER_INTERNAL) && (gtype != ptype)) {
    3069           0 :                                 if (as)
    3070           0 :                                         *as = peer->as;
    3071           0 :                                 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
    3072             :                         }
    3073             : 
    3074           0 :                         if (gtype == BGP_PEER_INTERNAL)
    3075           0 :                                 first_member = 1;
    3076             :                 }
    3077             : 
    3078           0 :                 peer_group2peer_config_copy(group, peer);
    3079             : 
    3080           0 :                 FOREACH_AFI_SAFI (afi, safi) {
    3081           0 :                         if (group->conf->afc[afi][safi]) {
    3082           0 :                                 peer->afc[afi][safi] = 1;
    3083             : 
    3084           0 :                                 if (peer_af_find(peer, afi, safi)
    3085           0 :                                     || peer_af_create(peer, afi, safi)) {
    3086           0 :                                         peer_group2peer_config_copy_af(
    3087             :                                                 group, peer, afi, safi);
    3088             :                                 }
    3089           0 :                         } else if (peer->afc[afi][safi])
    3090           0 :                                 peer_deactivate(peer, afi, safi);
    3091             :                 }
    3092             : 
    3093           0 :                 if (peer->group) {
    3094           0 :                         assert(group && peer->group == group);
    3095             :                 } else {
    3096           0 :                         listnode_delete(bgp->peer, peer);
    3097             : 
    3098           0 :                         peer->group = group;
    3099           0 :                         listnode_add_sort(bgp->peer, peer);
    3100             : 
    3101           0 :                         peer = peer_lock(peer); /* group->peer list reference */
    3102           0 :                         listnode_add(group->peer, peer);
    3103             :                 }
    3104             : 
    3105           0 :                 if (first_member) {
    3106           0 :                         gtype = peer_sort(group->conf);
    3107             :                         /* Advertisement-interval reset */
    3108           0 :                         if (!CHECK_FLAG(group->conf->flags,
    3109             :                                         PEER_FLAG_ROUTEADV)) {
    3110           0 :                                 group->conf->v_routeadv =
    3111             :                                         (gtype == BGP_PEER_IBGP)
    3112             :                                                 ? BGP_DEFAULT_IBGP_ROUTEADV
    3113             :                                                 : BGP_DEFAULT_EBGP_ROUTEADV;
    3114             :                         }
    3115             : 
    3116             :                         /* ebgp-multihop reset */
    3117           0 :                         if (gtype == BGP_PEER_IBGP)
    3118           0 :                                 group->conf->ttl = MAXTTL;
    3119             :                 }
    3120             : 
    3121           0 :                 SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
    3122             : 
    3123           0 :                 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
    3124           0 :                         peer->last_reset = PEER_DOWN_RMAP_BIND;
    3125           0 :                         bgp_notify_send(peer, BGP_NOTIFY_CEASE,
    3126             :                                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    3127             :                 } else {
    3128           0 :                         bgp_session_reset(peer);
    3129             :                 }
    3130             :         }
    3131             : 
    3132             :         /* Create a new peer. */
    3133             :         else {
    3134           0 :                 if ((group->conf->as_type == AS_SPECIFIED)
    3135           0 :                     && (!group->conf->as)) {
    3136             :                         return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
    3137             :                 }
    3138             : 
    3139           0 :                 peer = peer_create(su, NULL, bgp, bgp->as, group->conf->as,
    3140             :                                    group->conf->as_type, group, true);
    3141             : 
    3142           0 :                 peer = peer_lock(peer); /* group->peer list reference */
    3143           0 :                 listnode_add(group->peer, peer);
    3144             : 
    3145           0 :                 peer_group2peer_config_copy(group, peer);
    3146             : 
    3147             :                 /* If the peer-group is active for this afi/safi then activate
    3148             :                  * for this peer */
    3149           0 :                 FOREACH_AFI_SAFI (afi, safi) {
    3150           0 :                         if (group->conf->afc[afi][safi]) {
    3151           0 :                                 peer->afc[afi][safi] = 1;
    3152             : 
    3153           0 :                                 if (!peer_af_find(peer, afi, safi))
    3154           0 :                                         peer_af_create(peer, afi, safi);
    3155             : 
    3156           0 :                                 peer_group2peer_config_copy_af(group, peer, afi,
    3157             :                                                                safi);
    3158           0 :                         } else if (peer->afc[afi][safi])
    3159           0 :                                 peer_deactivate(peer, afi, safi);
    3160             :                 }
    3161             : 
    3162             :                 /* Set up peer's events and timers. */
    3163           0 :                 if (peer_active(peer))
    3164           0 :                         bgp_timer_set(peer);
    3165             :         }
    3166             : 
    3167             :         return 0;
    3168             : }
    3169             : 
    3170           0 : static void bgp_startup_timer_expire(struct thread *thread)
    3171             : {
    3172           0 :         struct bgp *bgp;
    3173             : 
    3174           0 :         bgp = THREAD_ARG(thread);
    3175           0 :         bgp->t_startup = NULL;
    3176           0 : }
    3177             : 
    3178             : /*
    3179             :  * On shutdown we call the cleanup function which
    3180             :  * does a free of the link list nodes,  free up
    3181             :  * the data we are pointing at too.
    3182             :  */
    3183           0 : static void bgp_vrf_string_name_delete(void *data)
    3184             : {
    3185           0 :         char *vname = data;
    3186             : 
    3187           0 :         XFREE(MTYPE_TMP, vname);
    3188           0 : }
    3189             : 
    3190             : /* BGP instance creation by `router bgp' commands. */
    3191           3 : static struct bgp *bgp_create(as_t *as, const char *name,
    3192             :                               enum bgp_instance_type inst_type)
    3193             : {
    3194           3 :         struct bgp *bgp;
    3195           3 :         afi_t afi;
    3196           3 :         safi_t safi;
    3197             : 
    3198           3 :         bgp = XCALLOC(MTYPE_BGP, sizeof(struct bgp));
    3199             : 
    3200           3 :         if (BGP_DEBUG(zebra, ZEBRA)) {
    3201           0 :                 if (inst_type == BGP_INSTANCE_TYPE_DEFAULT)
    3202           0 :                         zlog_debug("Creating Default VRF, AS %u", *as);
    3203             :                 else
    3204           0 :                         zlog_debug("Creating %s %s, AS %u",
    3205             :                                    (inst_type == BGP_INSTANCE_TYPE_VRF)
    3206             :                                            ? "VRF"
    3207             :                                            : "VIEW",
    3208             :                                    name, *as);
    3209             :         }
    3210             : 
    3211             :         /* Default the EVPN VRF to the default one */
    3212           3 :         if (inst_type == BGP_INSTANCE_TYPE_DEFAULT && !bgp_master.bgp_evpn) {
    3213           3 :                 bgp_lock(bgp);
    3214           3 :                 bm->bgp_evpn = bgp;
    3215             :         }
    3216             : 
    3217           3 :         bgp_lock(bgp);
    3218             : 
    3219           3 :         bgp->allow_martian = false;
    3220           3 :         bgp_process_queue_init(bgp);
    3221           3 :         bgp->heuristic_coalesce = true;
    3222           3 :         bgp->inst_type = inst_type;
    3223           6 :         bgp->vrf_id = (inst_type == BGP_INSTANCE_TYPE_DEFAULT) ? VRF_DEFAULT
    3224           3 :                                                                : VRF_UNKNOWN;
    3225           3 :         bgp->peer_self = peer_new(bgp);
    3226           3 :         XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->host);
    3227           6 :         bgp->peer_self->host =
    3228           3 :                 XSTRDUP(MTYPE_BGP_PEER_HOST, "Static announcement");
    3229           3 :         XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->hostname);
    3230           3 :         if (cmd_hostname_get())
    3231           3 :                 bgp->peer_self->hostname =
    3232           3 :                         XSTRDUP(MTYPE_BGP_PEER_HOST, cmd_hostname_get());
    3233             : 
    3234           3 :         XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->domainname);
    3235           3 :         if (cmd_domainname_get())
    3236           0 :                 bgp->peer_self->domainname =
    3237           0 :                         XSTRDUP(MTYPE_BGP_PEER_HOST, cmd_domainname_get());
    3238           3 :         bgp->peer = list_new();
    3239           3 :         bgp->peer->cmp = (int (*)(void *, void *))peer_cmp;
    3240           3 :         bgp->peerhash = hash_create(peer_hash_key_make, peer_hash_same,
    3241             :                                     "BGP Peer Hash");
    3242           3 :         bgp->peerhash->max_size = BGP_PEER_MAX_HASH_SIZE;
    3243             : 
    3244           3 :         bgp->group = list_new();
    3245           3 :         bgp->group->cmp = (int (*)(void *, void *))peer_group_cmp;
    3246             : 
    3247          75 :         FOREACH_AFI_SAFI (afi, safi) {
    3248          63 :                 bgp->route[afi][safi] = bgp_table_init(bgp, afi, safi);
    3249          63 :                 bgp->aggregate[afi][safi] = bgp_table_init(bgp, afi, safi);
    3250          63 :                 bgp->rib[afi][safi] = bgp_table_init(bgp, afi, safi);
    3251             : 
    3252             :                 /* Enable maximum-paths */
    3253          63 :                 bgp_maximum_paths_set(bgp, afi, safi, BGP_PEER_EBGP,
    3254             :                                       multipath_num, 0);
    3255          63 :                 bgp_maximum_paths_set(bgp, afi, safi, BGP_PEER_IBGP,
    3256             :                                       multipath_num, 0);
    3257             :                 /* Initialize graceful restart info */
    3258          63 :                 bgp->gr_info[afi][safi].eor_required = 0;
    3259          63 :                 bgp->gr_info[afi][safi].eor_received = 0;
    3260          63 :                 bgp->gr_info[afi][safi].t_select_deferral = NULL;
    3261          63 :                 bgp->gr_info[afi][safi].t_route_select = NULL;
    3262          63 :                 bgp->gr_info[afi][safi].gr_deferred = 0;
    3263             :         }
    3264             : 
    3265           3 :         bgp->v_update_delay = bm->v_update_delay;
    3266           3 :         bgp->v_establish_wait = bm->v_establish_wait;
    3267           3 :         bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
    3268           3 :         bgp->default_subgroup_pkt_queue_max =
    3269             :                 BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX;
    3270           3 :         bgp_tcp_keepalive_unset(bgp);
    3271           3 :         bgp_timers_unset(bgp);
    3272           3 :         bgp->default_min_holdtime = 0;
    3273           3 :         bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
    3274           3 :         bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
    3275           3 :         bgp->select_defer_time = BGP_DEFAULT_SELECT_DEFERRAL_TIME;
    3276           3 :         bgp->rib_stale_time = BGP_DEFAULT_RIB_STALE_TIME;
    3277           3 :         bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT;
    3278           3 :         bgp->dynamic_neighbors_count = 0;
    3279           3 :         bgp->lb_ref_bw = BGP_LINK_BW_REF_BW;
    3280           3 :         bgp->lb_handling = BGP_LINK_BW_ECMP;
    3281           3 :         bgp->reject_as_sets = false;
    3282           3 :         bgp->condition_check_period = DEFAULT_CONDITIONAL_ROUTES_POLL_TIME;
    3283           3 :         bgp_addpath_init_bgp_data(&bgp->tx_addpath);
    3284           3 :         bgp->fast_convergence = false;
    3285           3 :         bgp->as = *as;
    3286           3 :         bgp->llgr_stale_time = BGP_DEFAULT_LLGR_STALE_TIME;
    3287             : 
    3288             : #ifdef ENABLE_BGP_VNC
    3289           3 :         if (inst_type != BGP_INSTANCE_TYPE_VRF) {
    3290           3 :                 bgp->rfapi = bgp_rfapi_new(bgp);
    3291           3 :                 assert(bgp->rfapi);
    3292           3 :                 assert(bgp->rfapi_cfg);
    3293             :         }
    3294             : #endif /* ENABLE_BGP_VNC */
    3295             : 
    3296          12 :         for (afi = AFI_IP; afi < AFI_MAX; afi++) {
    3297           9 :                 bgp->vpn_policy[afi].bgp = bgp;
    3298           9 :                 bgp->vpn_policy[afi].afi = afi;
    3299           9 :                 bgp->vpn_policy[afi].tovpn_label = MPLS_LABEL_NONE;
    3300           9 :                 bgp->vpn_policy[afi].tovpn_zebra_vrf_label_last_sent =
    3301             :                         MPLS_LABEL_NONE;
    3302             : 
    3303           9 :                 bgp->vpn_policy[afi].import_vrf = list_new();
    3304           9 :                 bgp->vpn_policy[afi].import_vrf->del =
    3305             :                         bgp_vrf_string_name_delete;
    3306           9 :                 bgp->vpn_policy[afi].export_vrf = list_new();
    3307           9 :                 bgp->vpn_policy[afi].export_vrf->del =
    3308             :                         bgp_vrf_string_name_delete;
    3309           9 :                 SET_FLAG(bgp->af_flags[afi][SAFI_MPLS_VPN],
    3310             :                          BGP_VPNVX_RETAIN_ROUTE_TARGET_ALL);
    3311             :         }
    3312           3 :         if (name)
    3313           0 :                 bgp->name = XSTRDUP(MTYPE_BGP, name);
    3314             : 
    3315           3 :         thread_add_timer(bm->master, bgp_startup_timer_expire, bgp,
    3316             :                          bgp->restart_time, &bgp->t_startup);
    3317             : 
    3318             :         /* printable name we can use in debug messages */
    3319           3 :         if (inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
    3320           3 :                 bgp->name_pretty = XSTRDUP(MTYPE_BGP, "VRF default");
    3321             :         } else {
    3322           0 :                 const char *n;
    3323           0 :                 int len;
    3324             : 
    3325           0 :                 if (bgp->name)
    3326           0 :                         n = bgp->name;
    3327             :                 else
    3328             :                         n = "?";
    3329             : 
    3330           0 :                 len = 4 + 1 + strlen(n) + 1;    /* "view foo\0" */
    3331             : 
    3332           0 :                 bgp->name_pretty = XCALLOC(MTYPE_BGP, len);
    3333           0 :                 snprintf(bgp->name_pretty, len, "%s %s",
    3334           0 :                         (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
    3335             :                                 ? "VRF"
    3336             :                                 : "VIEW",
    3337             :                         n);
    3338             :         }
    3339             : 
    3340           3 :         atomic_store_explicit(&bgp->wpkt_quanta, BGP_WRITE_PACKET_MAX,
    3341             :                               memory_order_relaxed);
    3342           3 :         atomic_store_explicit(&bgp->rpkt_quanta, BGP_READ_PACKET_MAX,
    3343             :                               memory_order_relaxed);
    3344           3 :         bgp->coalesce_time = BGP_DEFAULT_SUBGROUP_COALESCE_TIME;
    3345           3 :         bgp->default_af[AFI_IP][SAFI_UNICAST] = true;
    3346             : 
    3347           3 :         QOBJ_REG(bgp, bgp);
    3348             : 
    3349           3 :         update_bgp_group_init(bgp);
    3350             : 
    3351             :         /* assign a unique rd id for auto derivation of vrf's RD */
    3352          18 :         bf_assign_index(bm->rd_idspace, bgp->vrf_rd_id);
    3353             : 
    3354           3 :         bgp->evpn_info = XCALLOC(MTYPE_BGP_EVPN_INFO,
    3355             :                                  sizeof(struct bgp_evpn_info));
    3356           3 :         bgp_evpn_init(bgp);
    3357           3 :         bgp_evpn_vrf_es_init(bgp);
    3358           3 :         bgp_pbr_init(bgp);
    3359           3 :         bgp_srv6_init(bgp);
    3360             : 
    3361             :         /*initilize global GR FSM */
    3362           3 :         bgp_global_gr_init(bgp);
    3363             : 
    3364           3 :         memset(&bgp->ebgprequirespolicywarning, 0,
    3365             :                sizeof(bgp->ebgprequirespolicywarning));
    3366             : 
    3367           3 :         return bgp;
    3368             : }
    3369             : 
    3370             : /* Return the "default VRF" instance of BGP. */
    3371          37 : struct bgp *bgp_get_default(void)
    3372             : {
    3373          37 :         struct bgp *bgp;
    3374          37 :         struct listnode *node, *nnode;
    3375             : 
    3376          74 :         for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
    3377          31 :                 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
    3378          31 :                         return bgp;
    3379             :         return NULL;
    3380             : }
    3381             : 
    3382             : /* Lookup BGP entry. */
    3383           3 : struct bgp *bgp_lookup(as_t as, const char *name)
    3384             : {
    3385           3 :         struct bgp *bgp;
    3386           3 :         struct listnode *node, *nnode;
    3387             : 
    3388           6 :         for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
    3389           0 :                 if (bgp->as == as
    3390           0 :                     && ((bgp->name == NULL && name == NULL)
    3391           0 :                         || (bgp->name && name && strcmp(bgp->name, name) == 0)))
    3392           0 :                         return bgp;
    3393             :         return NULL;
    3394             : }
    3395             : 
    3396             : /* Lookup BGP structure by view name. */
    3397           5 : struct bgp *bgp_lookup_by_name(const char *name)
    3398             : {
    3399           5 :         struct bgp *bgp;
    3400           5 :         struct listnode *node, *nnode;
    3401             : 
    3402          10 :         for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
    3403           2 :                 if ((bgp->name == NULL && name == NULL)
    3404           0 :                     || (bgp->name && name && strcmp(bgp->name, name) == 0))
    3405           2 :                         return bgp;
    3406             :         return NULL;
    3407             : }
    3408             : 
    3409             : /* Lookup BGP instance based on VRF id. */
    3410             : /* Note: Only to be used for incoming messages from Zebra. */
    3411          35 : struct bgp *bgp_lookup_by_vrf_id(vrf_id_t vrf_id)
    3412             : {
    3413          35 :         struct vrf *vrf;
    3414             : 
    3415             :         /* Lookup VRF (in tree) and follow link. */
    3416          35 :         vrf = vrf_lookup_by_id(vrf_id);
    3417          35 :         if (!vrf)
    3418             :                 return NULL;
    3419          35 :         return (vrf->info) ? (struct bgp *)vrf->info : NULL;
    3420             : }
    3421             : 
    3422             : /* Sets the BGP instance where EVPN is enabled */
    3423           3 : void bgp_set_evpn(struct bgp *bgp)
    3424             : {
    3425           3 :         if (bm->bgp_evpn == bgp)
    3426             :                 return;
    3427             : 
    3428             :         /* First, release the reference count we hold on the instance */
    3429           3 :         if (bm->bgp_evpn)
    3430           3 :                 bgp_unlock(bm->bgp_evpn);
    3431             : 
    3432           3 :         bm->bgp_evpn = bgp;
    3433             : 
    3434             :         /* Increase the reference count on this new VRF */
    3435           3 :         if (bm->bgp_evpn)
    3436           0 :                 bgp_lock(bm->bgp_evpn);
    3437             : }
    3438             : 
    3439             : /* Returns the BGP instance where EVPN is enabled, if any */
    3440           9 : struct bgp *bgp_get_evpn(void)
    3441             : {
    3442           6 :         return bm->bgp_evpn;
    3443             : }
    3444             : 
    3445             : /* handle socket creation or deletion, if necessary
    3446             :  * this is called for all new BGP instances
    3447             :  */
    3448           6 : int bgp_handle_socket(struct bgp *bgp, struct vrf *vrf, vrf_id_t old_vrf_id,
    3449             :                       bool create)
    3450             : {
    3451           6 :         struct listnode *node;
    3452           6 :         char *address;
    3453             : 
    3454             :         /* Create BGP server socket, if listen mode not disabled */
    3455           6 :         if (!bgp || bgp_option_check(BGP_OPT_NO_LISTEN))
    3456             :                 return 0;
    3457           6 :         if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) {
    3458             :                 /*
    3459             :                  * suppress vrf socket
    3460             :                  */
    3461           0 :                 if (!create) {
    3462           0 :                         bgp_close_vrf_socket(bgp);
    3463           0 :                         return 0;
    3464             :                 }
    3465           0 :                 if (vrf == NULL)
    3466             :                         return BGP_ERR_INVALID_VALUE;
    3467             :                 /* do nothing
    3468             :                  * if vrf_id did not change
    3469             :                  */
    3470           0 :                 if (vrf->vrf_id == old_vrf_id)
    3471             :                         return 0;
    3472           0 :                 if (old_vrf_id != VRF_UNKNOWN) {
    3473             :                         /* look for old socket. close it. */
    3474           0 :                         bgp_close_vrf_socket(bgp);
    3475             :                 }
    3476             :                 /* if backend is not yet identified ( VRF_UNKNOWN) then
    3477             :                  *   creation will be done later
    3478             :                  */
    3479           0 :                 if (vrf->vrf_id == VRF_UNKNOWN)
    3480             :                         return 0;
    3481           0 :                 if (list_isempty(bm->addresses)) {
    3482           0 :                         if (bgp_socket(bgp, bm->port, NULL) < 0)
    3483             :                                 return BGP_ERR_INVALID_VALUE;
    3484             :                 } else {
    3485           0 :                         for (ALL_LIST_ELEMENTS_RO(bm->addresses, node, address))
    3486           0 :                                 if (bgp_socket(bgp, bm->port, address) < 0)
    3487             :                                         return BGP_ERR_INVALID_VALUE;
    3488             :                 }
    3489           0 :                 return 0;
    3490             :         } else
    3491           6 :                 return bgp_check_main_socket(create, bgp);
    3492             : }
    3493             : 
    3494           3 : int bgp_lookup_by_as_name_type(struct bgp **bgp_val, as_t *as, const char *name,
    3495             :                                enum bgp_instance_type inst_type)
    3496             : {
    3497           3 :         struct bgp *bgp;
    3498             : 
    3499             :         /* Multiple instance check. */
    3500           3 :         if (name)
    3501           0 :                 bgp = bgp_lookup_by_name(name);
    3502             :         else
    3503           3 :                 bgp = bgp_get_default();
    3504             : 
    3505           3 :         if (bgp) {
    3506           0 :                 *bgp_val = bgp;
    3507           0 :                 if (bgp->as != *as) {
    3508           0 :                         *as = bgp->as;
    3509           0 :                         return BGP_ERR_AS_MISMATCH;
    3510             :                 }
    3511           0 :                 if (bgp->inst_type != inst_type)
    3512             :                         return BGP_ERR_INSTANCE_MISMATCH;
    3513             :                 return BGP_SUCCESS;
    3514             :         }
    3515           3 :         *bgp_val = NULL;
    3516             : 
    3517           3 :         return BGP_SUCCESS;
    3518             : }
    3519             : 
    3520             : /* Called from VTY commands. */
    3521           3 : int bgp_get(struct bgp **bgp_val, as_t *as, const char *name,
    3522             :             enum bgp_instance_type inst_type)
    3523             : {
    3524           3 :         struct bgp *bgp;
    3525           3 :         struct vrf *vrf = NULL;
    3526           3 :         int ret = 0;
    3527             : 
    3528           3 :         ret = bgp_lookup_by_as_name_type(bgp_val, as, name, inst_type);
    3529           3 :         if (ret || *bgp_val)
    3530             :                 return ret;
    3531             : 
    3532           3 :         bgp = bgp_create(as, name, inst_type);
    3533             : 
    3534             :         /*
    3535             :          * view instances will never work inside of a vrf
    3536             :          * as such they must always be in the VRF_DEFAULT
    3537             :          * Also we must set this to something useful because
    3538             :          * of the vrf socket code needing an actual useful
    3539             :          * default value to send to the underlying OS.
    3540             :          *
    3541             :          * This code is currently ignoring vrf based
    3542             :          * code using the -Z option( and that is probably
    3543             :          * best addressed elsewhere in the code )
    3544             :          */
    3545           3 :         if (inst_type == BGP_INSTANCE_TYPE_VIEW)
    3546           0 :                 bgp->vrf_id = VRF_DEFAULT;
    3547             : 
    3548           3 :         bgp_router_id_set(bgp, &bgp->router_id_zebra, true);
    3549           3 :         bgp_address_init(bgp);
    3550           3 :         bgp_tip_hash_init(bgp);
    3551           3 :         bgp_scan_init(bgp);
    3552           3 :         *bgp_val = bgp;
    3553             : 
    3554           3 :         bgp->t_rmap_def_originate_eval = NULL;
    3555             : 
    3556             :         /* If Default instance or VRF, link to the VRF structure, if present. */
    3557           3 :         if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
    3558             :             || bgp->inst_type == BGP_INSTANCE_TYPE_VRF) {
    3559           3 :                 vrf = bgp_vrf_lookup_by_instance_type(bgp);
    3560           3 :                 if (vrf)
    3561           3 :                         bgp_vrf_link(bgp, vrf);
    3562             :         }
    3563             :         /* BGP server socket already processed if BGP instance
    3564             :          * already part of the list
    3565             :          */
    3566           3 :         bgp_handle_socket(bgp, vrf, VRF_UNKNOWN, true);
    3567           3 :         listnode_add(bm->bgp, bgp);
    3568             : 
    3569           3 :         if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
    3570           3 :                 if (BGP_DEBUG(zebra, ZEBRA))
    3571           0 :                         zlog_debug("%s: Registering BGP instance %s to zebra",
    3572             :                                    __func__, bgp->name_pretty);
    3573           3 :                 bgp_zebra_instance_register(bgp);
    3574             :         }
    3575             : 
    3576             :         return BGP_CREATED;
    3577             : }
    3578             : 
    3579           0 : static void bgp_zclient_set_redist(afi_t afi, int type, unsigned short instance,
    3580             :                                    vrf_id_t vrf_id, bool set)
    3581             : {
    3582           0 :         if (instance) {
    3583           0 :                 if (set)
    3584           0 :                         redist_add_instance(&zclient->mi_redist[afi][type],
    3585             :                                             instance);
    3586             :                 else
    3587           0 :                         redist_del_instance(&zclient->mi_redist[afi][type],
    3588             :                                             instance);
    3589             :         } else {
    3590           0 :                 if (set)
    3591           0 :                         vrf_bitmap_set(zclient->redist[afi][type], vrf_id);
    3592             :                 else
    3593           0 :                         vrf_bitmap_unset(zclient->redist[afi][type], vrf_id);
    3594             :         }
    3595           0 : }
    3596             : 
    3597           0 : static void bgp_set_redist_vrf_bitmaps(struct bgp *bgp, bool set)
    3598             : {
    3599           0 :         afi_t afi;
    3600           0 :         int i;
    3601           0 :         struct list *red_list;
    3602           0 :         struct listnode *node;
    3603           0 :         struct bgp_redist *red;
    3604             : 
    3605           0 :         for (afi = AFI_IP; afi < AFI_MAX; afi++) {
    3606           0 :                 for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
    3607             : 
    3608           0 :                         red_list = bgp->redist[afi][i];
    3609           0 :                         if (!red_list)
    3610           0 :                                 continue;
    3611             : 
    3612           0 :                         for (ALL_LIST_ELEMENTS_RO(red_list, node, red))
    3613           0 :                                 bgp_zclient_set_redist(afi, i, red->instance,
    3614             :                                                        bgp->vrf_id, set);
    3615             :                 }
    3616             :         }
    3617           0 : }
    3618             : 
    3619             : /*
    3620             :  * Make BGP instance "up". Applies only to VRFs (non-default) and
    3621             :  * implies the VRF has been learnt from Zebra.
    3622             :  */
    3623           0 : void bgp_instance_up(struct bgp *bgp)
    3624             : {
    3625           0 :         struct peer *peer;
    3626           0 :         struct listnode *node, *next;
    3627             : 
    3628           0 :         bgp_set_redist_vrf_bitmaps(bgp, true);
    3629             : 
    3630             :         /* Register with zebra. */
    3631           0 :         bgp_zebra_instance_register(bgp);
    3632             : 
    3633             :         /* Kick off any peers that may have been configured. */
    3634           0 :         for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) {
    3635           0 :                 if (!BGP_PEER_START_SUPPRESSED(peer))
    3636           0 :                         BGP_EVENT_ADD(peer, BGP_Start);
    3637             :         }
    3638             : 
    3639             :         /* Process any networks that have been configured. */
    3640           0 :         bgp_static_add(bgp);
    3641           0 : }
    3642             : 
    3643             : /*
    3644             :  * Make BGP instance "down". Applies only to VRFs (non-default) and
    3645             :  * implies the VRF has been deleted by Zebra.
    3646             :  */
    3647           0 : void bgp_instance_down(struct bgp *bgp)
    3648             : {
    3649           0 :         struct peer *peer;
    3650           0 :         struct listnode *node;
    3651           0 :         struct listnode *next;
    3652             : 
    3653             :         /* Stop timers. */
    3654           0 :         if (bgp->t_rmap_def_originate_eval) {
    3655           0 :                 THREAD_OFF(bgp->t_rmap_def_originate_eval);
    3656           0 :                 bgp_unlock(bgp); /* TODO - This timer is started with a lock -
    3657             :                                     why? */
    3658             :         }
    3659             : 
    3660             :         /* Bring down peers, so corresponding routes are purged. */
    3661           0 :         for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) {
    3662           0 :                 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
    3663           0 :                         bgp_notify_send(peer, BGP_NOTIFY_CEASE,
    3664             :                                         BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
    3665             :                 else
    3666           0 :                         bgp_session_reset(peer);
    3667             :         }
    3668             : 
    3669             :         /* Purge network and redistributed routes. */
    3670           0 :         bgp_purge_static_redist_routes(bgp);
    3671             : 
    3672             :         /* Cleanup registered nexthops (flags) */
    3673           0 :         bgp_cleanup_nexthops(bgp);
    3674             : 
    3675           0 :         bgp_zebra_instance_deregister(bgp);
    3676             : 
    3677           0 :         bgp_set_redist_vrf_bitmaps(bgp, false);
    3678           0 : }
    3679             : 
    3680             : /* Delete BGP instance. */
    3681           3 : int bgp_delete(struct bgp *bgp)
    3682             : {
    3683           3 :         struct peer *peer;
    3684           3 :         struct peer_group *group;
    3685           3 :         struct listnode *node, *next;
    3686           3 :         struct vrf *vrf;
    3687           3 :         afi_t afi;
    3688           3 :         safi_t safi;
    3689           3 :         int i;
    3690           3 :         struct graceful_restart_info *gr_info;
    3691             : 
    3692           3 :         assert(bgp);
    3693             : 
    3694           3 :         bgp_soft_reconfig_table_task_cancel(bgp, NULL, NULL);
    3695             : 
    3696             :         /* make sure we withdraw any exported routes */
    3697           3 :         vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP, bgp_get_default(),
    3698             :                            bgp);
    3699           3 :         vpn_leak_prechange(BGP_VPN_POLICY_DIR_TOVPN, AFI_IP6, bgp_get_default(),
    3700             :                            bgp);
    3701             : 
    3702           3 :         bgp_vpn_leak_unimport(bgp);
    3703             : 
    3704           3 :         hook_call(bgp_inst_delete, bgp);
    3705             : 
    3706          78 :         FOREACH_AFI_SAFI (afi, safi)
    3707          63 :                 THREAD_OFF(bgp->t_revalidate[afi][safi]);
    3708             : 
    3709           3 :         THREAD_OFF(bgp->t_condition_check);
    3710           3 :         THREAD_OFF(bgp->t_startup);
    3711           3 :         THREAD_OFF(bgp->t_maxmed_onstartup);
    3712           3 :         THREAD_OFF(bgp->t_update_delay);
    3713           3 :         THREAD_OFF(bgp->t_establish_wait);
    3714             : 
    3715             :         /* Set flag indicating bgp instance delete in progress */
    3716           3 :         SET_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS);
    3717             : 
    3718             :         /* Delete the graceful restart info */
    3719          75 :         FOREACH_AFI_SAFI (afi, safi) {
    3720          63 :                 struct thread *t;
    3721             : 
    3722          63 :                 gr_info = &bgp->gr_info[afi][safi];
    3723          63 :                 if (!gr_info)
    3724             :                         continue;
    3725          63 :                 t = gr_info->t_select_deferral;
    3726          63 :                 if (t) {
    3727           0 :                         void *info = THREAD_ARG(t);
    3728             : 
    3729           0 :                         XFREE(MTYPE_TMP, info);
    3730             :                 }
    3731          63 :                 THREAD_OFF(gr_info->t_select_deferral);
    3732             : 
    3733          63 :                 t = gr_info->t_route_select;
    3734          63 :                 if (t) {
    3735           0 :                         void *info = THREAD_ARG(t);
    3736             : 
    3737           0 :                         XFREE(MTYPE_TMP, info);
    3738             :                 }
    3739          63 :                 THREAD_OFF(gr_info->t_route_select);
    3740             :         }
    3741             : 
    3742           3 :         if (BGP_DEBUG(zebra, ZEBRA)) {
    3743           0 :                 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
    3744           0 :                         zlog_debug("Deleting Default VRF");
    3745             :                 else
    3746           0 :                         zlog_debug("Deleting %s %s",
    3747             :                                    (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
    3748             :                                            ? "VRF"
    3749             :                                            : "VIEW",
    3750             :                                    bgp->name);
    3751             :         }
    3752             : 
    3753             :         /* unmap from RT list */
    3754           3 :         bgp_evpn_vrf_delete(bgp);
    3755             : 
    3756             :         /* unmap bgp vrf label */
    3757           3 :         vpn_leak_zebra_vrf_label_withdraw(bgp, AFI_IP);
    3758           3 :         vpn_leak_zebra_vrf_label_withdraw(bgp, AFI_IP6);
    3759             : 
    3760             :         /* Stop timers. */
    3761           3 :         if (bgp->t_rmap_def_originate_eval) {
    3762           0 :                 THREAD_OFF(bgp->t_rmap_def_originate_eval);
    3763           0 :                 bgp_unlock(bgp); /* TODO - This timer is started with a lock -
    3764             :                                     why? */
    3765             :         }
    3766             : 
    3767             :         /* Inform peers we're going down. */
    3768          10 :         for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer))
    3769           4 :                 peer_notify_shutdown(peer);
    3770             : 
    3771             :         /* Delete static routes (networks). */
    3772           3 :         bgp_static_delete(bgp);
    3773             : 
    3774             :         /* Unset redistribution. */
    3775          15 :         for (afi = AFI_IP; afi < AFI_MAX; afi++)
    3776         288 :                 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
    3777         279 :                         if (i != ZEBRA_ROUTE_BGP)
    3778         270 :                                 bgp_redistribute_unset(bgp, afi, i, 0);
    3779             : 
    3780             :         /* Free peers and peer-groups. */
    3781           6 :         for (ALL_LIST_ELEMENTS(bgp->group, node, next, group))
    3782           0 :                 peer_group_delete(group);
    3783             : 
    3784           7 :         while (listcount(bgp->peer)) {
    3785           4 :                 peer = listnode_head(bgp->peer);
    3786           4 :                 peer_delete(peer);
    3787             :         }
    3788             : 
    3789           3 :         if (bgp->peer_self) {
    3790           3 :                 peer_delete(bgp->peer_self);
    3791           3 :                 bgp->peer_self = NULL;
    3792             :         }
    3793             : 
    3794           3 :         update_bgp_group_free(bgp);
    3795             : 
    3796             : /* TODO - Other memory may need to be freed - e.g., NHT */
    3797             : 
    3798             : #ifdef ENABLE_BGP_VNC
    3799           3 :         rfapi_delete(bgp);
    3800             : #endif
    3801           3 :         bgp_cleanup_routes(bgp);
    3802             : 
    3803          18 :         for (afi = 0; afi < AFI_MAX; ++afi) {
    3804          12 :                 if (!bgp->vpn_policy[afi].import_redirect_rtlist)
    3805          12 :                         continue;
    3806           0 :                 ecommunity_free(
    3807             :                                 &bgp->vpn_policy[afi]
    3808             :                                 .import_redirect_rtlist);
    3809           0 :                 bgp->vpn_policy[afi].import_redirect_rtlist = NULL;
    3810             :         }
    3811             : 
    3812             :         /* Free any memory allocated to holding routemap references */
    3813          15 :         for (afi = 0; afi < AFI_MAX; ++afi) {
    3814             :                 for (enum vpn_policy_direction dir = 0;
    3815          36 :                      dir < BGP_VPN_POLICY_DIR_MAX; ++dir) {
    3816          24 :                         if (bgp->vpn_policy[afi].rmap_name[dir])
    3817           0 :                                 XFREE(MTYPE_ROUTE_MAP_NAME,
    3818             :                                       bgp->vpn_policy[afi].rmap_name[dir]);
    3819          24 :                         bgp->vpn_policy[afi].rmap[dir] = NULL;
    3820             :                 }
    3821             :         }
    3822             : 
    3823             :         /* Deregister from Zebra, if needed */
    3824           3 :         if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
    3825           3 :                 if (BGP_DEBUG(zebra, ZEBRA))
    3826           0 :                         zlog_debug(
    3827             :                                 "%s: deregistering this bgp %s instance from zebra",
    3828             :                                 __func__, bgp->name);
    3829           3 :                 bgp_zebra_instance_deregister(bgp);
    3830             :         }
    3831             : 
    3832             :         /* Remove visibility via the master list - there may however still be
    3833             :          * routes to be processed still referencing the struct bgp.
    3834             :          */
    3835           3 :         listnode_delete(bm->bgp, bgp);
    3836             : 
    3837             :         /* Free interfaces in this instance. */
    3838           3 :         bgp_if_finish(bgp);
    3839             : 
    3840           3 :         vrf = bgp_vrf_lookup_by_instance_type(bgp);
    3841           3 :         bgp_handle_socket(bgp, vrf, VRF_UNKNOWN, false);
    3842           3 :         if (vrf)
    3843           3 :                 bgp_vrf_unlink(bgp, vrf);
    3844             : 
    3845             :         /* Update EVPN VRF pointer */
    3846           3 :         if (bm->bgp_evpn == bgp) {
    3847           3 :                 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
    3848           3 :                         bgp_set_evpn(NULL);
    3849             :                 else
    3850           0 :                         bgp_set_evpn(bgp_get_default());
    3851             :         }
    3852             : 
    3853           3 :         if (bgp->process_queue)
    3854           3 :                 work_queue_free_and_null(&bgp->process_queue);
    3855             : 
    3856           3 :         thread_master_free_unused(bm->master);
    3857           3 :         bgp_unlock(bgp); /* initial reference */
    3858             : 
    3859           3 :         return 0;
    3860             : }
    3861             : 
    3862           3 : void bgp_free(struct bgp *bgp)
    3863             : {
    3864           3 :         afi_t afi;
    3865           3 :         safi_t safi;
    3866           3 :         struct bgp_table *table;
    3867           3 :         struct bgp_dest *dest;
    3868           3 :         struct bgp_rmap *rmap;
    3869             : 
    3870           3 :         QOBJ_UNREG(bgp);
    3871             : 
    3872           3 :         list_delete(&bgp->group);
    3873           3 :         list_delete(&bgp->peer);
    3874             : 
    3875           3 :         if (bgp->peerhash) {
    3876           3 :                 hash_free(bgp->peerhash);
    3877           3 :                 bgp->peerhash = NULL;
    3878             :         }
    3879             : 
    3880          75 :         FOREACH_AFI_SAFI (afi, safi) {
    3881             :                 /* Special handling for 2-level routing tables. */
    3882          63 :                 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
    3883          63 :                     || safi == SAFI_EVPN) {
    3884          54 :                         for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
    3885           0 :                              dest = bgp_route_next(dest)) {
    3886           0 :                                 table = bgp_dest_get_bgp_table_info(dest);
    3887           0 :                                 bgp_table_finish(&table);
    3888             :                         }
    3889             :                 }
    3890          63 :                 if (bgp->route[afi][safi])
    3891          63 :                         bgp_table_finish(&bgp->route[afi][safi]);
    3892          63 :                 if (bgp->aggregate[afi][safi])
    3893          63 :                         bgp_table_finish(&bgp->aggregate[afi][safi]);
    3894          63 :                 if (bgp->rib[afi][safi])
    3895          63 :                         bgp_table_finish(&bgp->rib[afi][safi]);
    3896          63 :                 rmap = &bgp->table_map[afi][safi];
    3897          63 :                 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
    3898             :         }
    3899             : 
    3900           3 :         bgp_scan_finish(bgp);
    3901           3 :         bgp_address_destroy(bgp);
    3902           3 :         bgp_tip_hash_destroy(bgp);
    3903             : 
    3904             :         /* release the auto RD id */
    3905           3 :         bf_release_index(bm->rd_idspace, bgp->vrf_rd_id);
    3906             : 
    3907           3 :         bgp_evpn_cleanup(bgp);
    3908           3 :         bgp_pbr_cleanup(bgp);
    3909           3 :         bgp_srv6_cleanup(bgp);
    3910           3 :         XFREE(MTYPE_BGP_EVPN_INFO, bgp->evpn_info);
    3911             : 
    3912          12 :         for (afi = AFI_IP; afi < AFI_MAX; afi++) {
    3913           9 :                 enum vpn_policy_direction dir;
    3914             : 
    3915           9 :                 if (bgp->vpn_policy[afi].import_vrf)
    3916           9 :                         list_delete(&bgp->vpn_policy[afi].import_vrf);
    3917           9 :                 if (bgp->vpn_policy[afi].export_vrf)
    3918           9 :                         list_delete(&bgp->vpn_policy[afi].export_vrf);
    3919             : 
    3920           9 :                 dir = BGP_VPN_POLICY_DIR_FROMVPN;
    3921           9 :                 if (bgp->vpn_policy[afi].rtlist[dir])
    3922           0 :                         ecommunity_free(&bgp->vpn_policy[afi].rtlist[dir]);
    3923           9 :                 dir = BGP_VPN_POLICY_DIR_TOVPN;
    3924           9 :                 if (bgp->vpn_policy[afi].rtlist[dir])
    3925           0 :                         ecommunity_free(&bgp->vpn_policy[afi].rtlist[dir]);
    3926             :         }
    3927             : 
    3928           3 :         XFREE(MTYPE_BGP, bgp->name);
    3929           3 :         XFREE(MTYPE_BGP, bgp->name_pretty);
    3930           3 :         XFREE(MTYPE_BGP, bgp->snmp_stats);
    3931             : 
    3932           3 :         XFREE(MTYPE_BGP, bgp);
    3933           3 : }
    3934             : 
    3935           0 : struct peer *peer_lookup_by_conf_if(struct bgp *bgp, const char *conf_if)
    3936             : {
    3937           0 :         struct peer *peer;
    3938           0 :         struct listnode *node, *nnode;
    3939             : 
    3940           0 :         if (!conf_if)
    3941             :                 return NULL;
    3942             : 
    3943           0 :         if (bgp != NULL) {
    3944           0 :                 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
    3945           0 :                         if (peer->conf_if && !strcmp(peer->conf_if, conf_if)
    3946           0 :                             && !CHECK_FLAG(peer->sflags,
    3947             :                                            PEER_STATUS_ACCEPT_PEER))
    3948           0 :                                 return peer;
    3949           0 :         } else if (bm->bgp != NULL) {
    3950           0 :                 struct listnode *bgpnode, *nbgpnode;
    3951             : 
    3952           0 :                 for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp))
    3953           0 :                         for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
    3954           0 :                                 if (peer->conf_if
    3955           0 :                                     && !strcmp(peer->conf_if, conf_if)
    3956           0 :                                     && !CHECK_FLAG(peer->sflags,
    3957             :                                                    PEER_STATUS_ACCEPT_PEER))
    3958           0 :                                         return peer;
    3959             :         }
    3960             :         return NULL;
    3961             : }
    3962             : 
    3963           0 : struct peer *peer_lookup_by_hostname(struct bgp *bgp, const char *hostname)
    3964             : {
    3965           0 :         struct peer *peer;
    3966           0 :         struct listnode *node, *nnode;
    3967             : 
    3968           0 :         if (!hostname)
    3969             :                 return NULL;
    3970             : 
    3971           0 :         if (bgp != NULL) {
    3972           0 :                 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
    3973           0 :                         if (peer->hostname && !strcmp(peer->hostname, hostname)
    3974           0 :                             && !CHECK_FLAG(peer->sflags,
    3975             :                                            PEER_STATUS_ACCEPT_PEER))
    3976           0 :                                 return peer;
    3977           0 :         } else if (bm->bgp != NULL) {
    3978           0 :                 struct listnode *bgpnode, *nbgpnode;
    3979             : 
    3980           0 :                 for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp))
    3981           0 :                         for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
    3982           0 :                                 if (peer->hostname
    3983           0 :                                     && !strcmp(peer->hostname, hostname)
    3984           0 :                                     && !CHECK_FLAG(peer->sflags,
    3985             :                                                    PEER_STATUS_ACCEPT_PEER))
    3986           0 :                                         return peer;
    3987             :         }
    3988             :         return NULL;
    3989             : }
    3990             : 
    3991          10 : struct peer *peer_lookup(struct bgp *bgp, union sockunion *su)
    3992             : {
    3993          10 :         struct peer *peer = NULL;
    3994          10 :         struct peer tmp_peer;
    3995             : 
    3996          10 :         memset(&tmp_peer, 0, sizeof(struct peer));
    3997             : 
    3998             :         /*
    3999             :          * We do not want to find the doppelganger peer so search for the peer
    4000             :          * in
    4001             :          * the hash that has PEER_FLAG_CONFIG_NODE
    4002             :          */
    4003          10 :         SET_FLAG(tmp_peer.flags, PEER_FLAG_CONFIG_NODE);
    4004             : 
    4005          10 :         tmp_peer.su = *su;
    4006             : 
    4007          10 :         if (bgp != NULL) {
    4008          10 :                 peer = hash_lookup(bgp->peerhash, &tmp_peer);
    4009           0 :         } else if (bm->bgp != NULL) {
    4010           0 :                 struct listnode *bgpnode, *nbgpnode;
    4011             : 
    4012           0 :                 for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp)) {
    4013           0 :                         peer = hash_lookup(bgp->peerhash, &tmp_peer);
    4014           0 :                         if (peer)
    4015             :                                 break;
    4016             :                 }
    4017             :         }
    4018             : 
    4019          10 :         return peer;
    4020             : }
    4021             : 
    4022           0 : struct peer *peer_create_bind_dynamic_neighbor(struct bgp *bgp,
    4023             :                                                union sockunion *su,
    4024             :                                                struct peer_group *group)
    4025             : {
    4026           0 :         struct peer *peer;
    4027           0 :         afi_t afi;
    4028           0 :         safi_t safi;
    4029             : 
    4030             :         /* Create peer first; we've already checked group config is valid. */
    4031           0 :         peer = peer_create(su, NULL, bgp, bgp->as, group->conf->as,
    4032           0 :                            group->conf->as_type, group, true);
    4033           0 :         if (!peer)
    4034             :                 return NULL;
    4035             : 
    4036             :         /* Link to group */
    4037           0 :         peer = peer_lock(peer);
    4038           0 :         listnode_add(group->peer, peer);
    4039             : 
    4040           0 :         peer_group2peer_config_copy(group, peer);
    4041             : 
    4042             :         /*
    4043             :          * Bind peer for all AFs configured for the group. We don't call
    4044             :          * peer_group_bind as that is sub-optimal and does some stuff we don't
    4045             :          * want.
    4046             :          */
    4047           0 :         FOREACH_AFI_SAFI (afi, safi) {
    4048           0 :                 if (!group->conf->afc[afi][safi])
    4049           0 :                         continue;
    4050           0 :                 peer->afc[afi][safi] = 1;
    4051             : 
    4052           0 :                 if (!peer_af_find(peer, afi, safi))
    4053           0 :                         peer_af_create(peer, afi, safi);
    4054             : 
    4055           0 :                 peer_group2peer_config_copy_af(group, peer, afi, safi);
    4056             :         }
    4057             : 
    4058             :         /* Mark as dynamic, but also as a "config node" for other things to
    4059             :          * work. */
    4060           0 :         SET_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR);
    4061             : 
    4062           0 :         return peer;
    4063             : }
    4064             : 
    4065             : struct prefix *
    4066           0 : peer_group_lookup_dynamic_neighbor_range(struct peer_group *group,
    4067             :                                          struct prefix *prefix)
    4068             : {
    4069           0 :         struct listnode *node, *nnode;
    4070           0 :         struct prefix *range;
    4071           0 :         afi_t afi;
    4072             : 
    4073           0 :         afi = family2afi(prefix->family);
    4074             : 
    4075           0 :         if (group->listen_range[afi])
    4076           0 :                 for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, nnode,
    4077             :                                        range))
    4078           0 :                         if (prefix_match(range, prefix))
    4079           0 :                                 return range;
    4080             : 
    4081             :         return NULL;
    4082             : }
    4083             : 
    4084             : struct peer_group *
    4085           0 : peer_group_lookup_dynamic_neighbor(struct bgp *bgp, struct prefix *prefix,
    4086             :                                    struct prefix **listen_range)
    4087             : {
    4088           0 :         struct prefix *range = NULL;
    4089           0 :         struct peer_group *group = NULL;
    4090           0 :         struct listnode *node, *nnode;
    4091             : 
    4092           0 :         *listen_range = NULL;
    4093           0 :         if (bgp != NULL) {
    4094           0 :                 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group))
    4095           0 :                         if ((range = peer_group_lookup_dynamic_neighbor_range(
    4096             :                                      group, prefix)))
    4097             :                                 break;
    4098           0 :         } else if (bm->bgp != NULL) {
    4099           0 :                 struct listnode *bgpnode, *nbgpnode;
    4100             : 
    4101           0 :                 for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp))
    4102           0 :                         for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group))
    4103           0 :                                 if ((range = peer_group_lookup_dynamic_neighbor_range(
    4104             :                                              group, prefix)))
    4105           0 :                                         goto found_range;
    4106             :         }
    4107             : 
    4108           0 : found_range:
    4109           0 :         *listen_range = range;
    4110           0 :         return (group && range) ? group : NULL;
    4111             : }
    4112             : 
    4113           0 : struct peer *peer_lookup_dynamic_neighbor(struct bgp *bgp, union sockunion *su)
    4114             : {
    4115           0 :         struct peer_group *group;
    4116           0 :         struct bgp *gbgp;
    4117           0 :         struct peer *peer;
    4118           0 :         struct prefix prefix;
    4119           0 :         struct prefix *listen_range;
    4120           0 :         int dncount;
    4121             : 
    4122           0 :         if (!sockunion2hostprefix(su, &prefix))
    4123             :                 return NULL;
    4124             : 
    4125             :         /* See if incoming connection matches a configured listen range. */
    4126           0 :         group = peer_group_lookup_dynamic_neighbor(bgp, &prefix, &listen_range);
    4127             : 
    4128           0 :         if (!group)
    4129             :                 return NULL;
    4130             : 
    4131             : 
    4132           0 :         gbgp = group->bgp;
    4133             : 
    4134           0 :         if (!gbgp)
    4135             :                 return NULL;
    4136             : 
    4137           0 :         if (bgp_debug_neighbor_events(NULL))
    4138           0 :                 zlog_debug(
    4139             :                         "Dynamic Neighbor %pFX matches group %s listen range %pFX",
    4140             :                         &prefix, group->name, listen_range);
    4141             : 
    4142             :         /* Are we within the listen limit? */
    4143           0 :         dncount = gbgp->dynamic_neighbors_count;
    4144             : 
    4145           0 :         if (dncount >= gbgp->dynamic_neighbors_limit) {
    4146           0 :                 if (bgp_debug_neighbor_events(NULL))
    4147           0 :                         zlog_debug(
    4148             :                                 "Dynamic Neighbor %pFX rejected - at limit %d",
    4149             :                                 &prefix, gbgp->dynamic_neighbors_limit);
    4150           0 :                 return NULL;
    4151             :         }
    4152             : 
    4153             :         /* Ensure group is not disabled. */
    4154           0 :         if (CHECK_FLAG(group->conf->flags, PEER_FLAG_SHUTDOWN)) {
    4155           0 :                 if (bgp_debug_neighbor_events(NULL))
    4156           0 :                         zlog_debug(
    4157             :                                 "Dynamic Neighbor %pFX rejected - group %s disabled",
    4158             :                                 &prefix, group->name);
    4159           0 :                 return NULL;
    4160             :         }
    4161             : 
    4162             :         /* Check that at least one AF is activated for the group. */
    4163           0 :         if (!peer_group_af_configured(group)) {
    4164           0 :                 if (bgp_debug_neighbor_events(NULL))
    4165           0 :                         zlog_debug(
    4166             :                                 "Dynamic Neighbor %pFX rejected - no AF activated for group %s",
    4167             :                                 &prefix, group->name);
    4168           0 :                 return NULL;
    4169             :         }
    4170             : 
    4171             :         /* Create dynamic peer and bind to associated group. */
    4172           0 :         peer = peer_create_bind_dynamic_neighbor(gbgp, su, group);
    4173           0 :         assert(peer);
    4174             : 
    4175           0 :         gbgp->dynamic_neighbors_count = ++dncount;
    4176             : 
    4177           0 :         if (bgp_debug_neighbor_events(peer))
    4178           0 :                 zlog_debug("%s Dynamic Neighbor added, group %s count %d",
    4179             :                            peer->host, group->name, dncount);
    4180             : 
    4181             :         return peer;
    4182             : }
    4183             : 
    4184           0 : static void peer_drop_dynamic_neighbor(struct peer *peer)
    4185             : {
    4186           0 :         int dncount = -1;
    4187           0 :         if (peer->group->bgp) {
    4188           0 :                 dncount = peer->group->bgp->dynamic_neighbors_count;
    4189           0 :                 if (dncount)
    4190           0 :                         peer->group->bgp->dynamic_neighbors_count = --dncount;
    4191             :         }
    4192           0 :         if (bgp_debug_neighbor_events(peer))
    4193           0 :                 zlog_debug("%s dropped from group %s, count %d", peer->host,
    4194             :                            peer->group->name, dncount);
    4195           0 : }
    4196             : 
    4197           0 : bool bgp_path_attribute_discard(struct peer *peer, char *buf, size_t size)
    4198             : {
    4199           0 :         if (!buf)
    4200             :                 return false;
    4201             : 
    4202           0 :         buf[0] = '\0';
    4203             : 
    4204           0 :         for (unsigned int i = 0; i < BGP_ATTR_MAX; i++) {
    4205           0 :                 if (peer->discard_attrs[i])
    4206           0 :                         snprintf(buf + strlen(buf), size - strlen(buf), "%s%d",
    4207           0 :                                  (strlen(buf) > 0) ? " " : "", i);
    4208             :         }
    4209             : 
    4210           0 :         if (strlen(buf) > 0)
    4211             :                 return true;
    4212             : 
    4213             :         return false;
    4214             : }
    4215             : 
    4216             : /* If peer is configured at least one address family return 1. */
    4217          24 : bool peer_active(struct peer *peer)
    4218             : {
    4219          24 :         if (BGP_PEER_SU_UNSPEC(peer))
    4220             :                 return false;
    4221          24 :         if (peer->afc[AFI_IP][SAFI_UNICAST] || peer->afc[AFI_IP][SAFI_MULTICAST]
    4222           6 :             || peer->afc[AFI_IP][SAFI_LABELED_UNICAST]
    4223           6 :             || peer->afc[AFI_IP][SAFI_MPLS_VPN] || peer->afc[AFI_IP][SAFI_ENCAP]
    4224             :             || peer->afc[AFI_IP][SAFI_FLOWSPEC]
    4225           6 :             || peer->afc[AFI_IP6][SAFI_UNICAST]
    4226           6 :             || peer->afc[AFI_IP6][SAFI_MULTICAST]
    4227           6 :             || peer->afc[AFI_IP6][SAFI_LABELED_UNICAST]
    4228             :             || peer->afc[AFI_IP6][SAFI_MPLS_VPN]
    4229           6 :             || peer->afc[AFI_IP6][SAFI_ENCAP]
    4230             :             || peer->afc[AFI_IP6][SAFI_FLOWSPEC]
    4231           6 :             || peer->afc[AFI_L2VPN][SAFI_EVPN])
    4232          18 :                 return true;
    4233             :         return false;
    4234             : }
    4235             : 
    4236             : /* If peer is negotiated at least one address family return 1. */
    4237           0 : bool peer_active_nego(struct peer *peer)
    4238             : {
    4239           0 :         if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
    4240           0 :             || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
    4241           0 :             || peer->afc_nego[AFI_IP][SAFI_LABELED_UNICAST]
    4242             :             || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
    4243           0 :             || peer->afc_nego[AFI_IP][SAFI_ENCAP]
    4244             :             || peer->afc_nego[AFI_IP][SAFI_FLOWSPEC]
    4245           0 :             || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
    4246           0 :             || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
    4247           0 :             || peer->afc_nego[AFI_IP6][SAFI_LABELED_UNICAST]
    4248             :             || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
    4249           0 :             || peer->afc_nego[AFI_IP6][SAFI_ENCAP]
    4250             :             || peer->afc_nego[AFI_IP6][SAFI_FLOWSPEC]
    4251           0 :             || peer->afc_nego[AFI_L2VPN][SAFI_EVPN])
    4252           0 :                 return true;
    4253             :         return false;
    4254             : }
    4255             : 
    4256             : /* If peer received at least one address family MP, return true */
    4257           0 : bool peer_afc_received(struct peer *peer)
    4258             : {
    4259           0 :         afi_t afi;
    4260           0 :         safi_t safi;
    4261             : 
    4262           0 :         FOREACH_AFI_SAFI (afi, safi)
    4263           0 :                 if (peer->afc_recv[afi][safi])
    4264             :                         return true;
    4265             : 
    4266             :         return false;
    4267             : }
    4268             : 
    4269             : /* If peer advertised at least one address family MP, return true */
    4270           0 : bool peer_afc_advertised(struct peer *peer)
    4271             : {
    4272           0 :         afi_t afi;
    4273           0 :         safi_t safi;
    4274             : 
    4275           0 :         FOREACH_AFI_SAFI (afi, safi)
    4276           0 :                 if (peer->afc_adv[afi][safi])
    4277             :                         return true;
    4278             : 
    4279             :         return false;
    4280             : }
    4281             : 
    4282           0 : void peer_change_action(struct peer *peer, afi_t afi, safi_t safi,
    4283             :                                enum peer_change_type type)
    4284             : {
    4285           0 :         struct peer_af *paf;
    4286             : 
    4287           0 :         if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
    4288             :                 return;
    4289             : 
    4290           0 :         if (!peer_established(peer))
    4291             :                 return;
    4292             : 
    4293           0 :         if (type == peer_change_reset) {
    4294             :                 /* If we're resetting session, we've to delete both peer struct
    4295             :                  */
    4296           0 :                 if ((peer->doppelganger)
    4297           0 :                     && (peer->doppelganger->status != Deleted)
    4298           0 :                     && (!CHECK_FLAG(peer->doppelganger->flags,
    4299             :                                     PEER_FLAG_CONFIG_NODE)))
    4300           0 :                         peer_delete(peer->doppelganger);
    4301             : 
    4302           0 :                 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
    4303             :                                 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    4304           0 :         } else if (type == peer_change_reset_in) {
    4305           0 :                 if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV)
    4306           0 :                     || CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV))
    4307           0 :                         bgp_route_refresh_send(peer, afi, safi, 0, 0, 0,
    4308             :                                                BGP_ROUTE_REFRESH_NORMAL);
    4309             :                 else {
    4310           0 :                         if ((peer->doppelganger)
    4311           0 :                             && (peer->doppelganger->status != Deleted)
    4312           0 :                             && (!CHECK_FLAG(peer->doppelganger->flags,
    4313             :                                             PEER_FLAG_CONFIG_NODE)))
    4314           0 :                                 peer_delete(peer->doppelganger);
    4315             : 
    4316           0 :                         bgp_notify_send(peer, BGP_NOTIFY_CEASE,
    4317             :                                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    4318             :                 }
    4319           0 :         } else if (type == peer_change_reset_out) {
    4320           0 :                 paf = peer_af_find(peer, afi, safi);
    4321           0 :                 if (paf && paf->subgroup)
    4322           0 :                         SET_FLAG(paf->subgroup->sflags,
    4323             :                                  SUBGRP_STATUS_FORCE_UPDATES);
    4324             : 
    4325           0 :                 update_group_adjust_peer(paf);
    4326           0 :                 bgp_announce_route(peer, afi, safi, false);
    4327             :         }
    4328             : }
    4329             : 
    4330             : struct peer_flag_action {
    4331             :         /* Peer's flag.  */
    4332             :         uint64_t flag;
    4333             : 
    4334             :         /* This flag can be set for peer-group member.  */
    4335             :         uint8_t not_for_member;
    4336             : 
    4337             :         /* Action when the flag is changed.  */
    4338             :         enum peer_change_type type;
    4339             : };
    4340             : 
    4341             : static const struct peer_flag_action peer_flag_action_list[] = {
    4342             :         {PEER_FLAG_PASSIVE, 0, peer_change_reset},
    4343             :         {PEER_FLAG_SHUTDOWN, 0, peer_change_reset},
    4344             :         {PEER_FLAG_RTT_SHUTDOWN, 0, peer_change_none},
    4345             :         {PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none},
    4346             :         {PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none},
    4347             :         {PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none},
    4348             :         {PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset},
    4349             :         {PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset},
    4350             :         {PEER_FLAG_CAPABILITY_ENHE, 0, peer_change_reset},
    4351             :         {PEER_FLAG_ENFORCE_FIRST_AS, 0, peer_change_reset_in},
    4352             :         {PEER_FLAG_IFPEER_V6ONLY, 0, peer_change_reset},
    4353             :         {PEER_FLAG_ROUTEADV, 0, peer_change_none},
    4354             :         {PEER_FLAG_TIMER, 0, peer_change_none},
    4355             :         {PEER_FLAG_TIMER_CONNECT, 0, peer_change_none},
    4356             :         {PEER_FLAG_TIMER_DELAYOPEN, 0, peer_change_none},
    4357             :         {PEER_FLAG_PASSWORD, 0, peer_change_none},
    4358             :         {PEER_FLAG_LOCAL_AS, 0, peer_change_reset},
    4359             :         {PEER_FLAG_LOCAL_AS_NO_PREPEND, 0, peer_change_reset},
    4360             :         {PEER_FLAG_LOCAL_AS_REPLACE_AS, 0, peer_change_reset},
    4361             :         {PEER_FLAG_UPDATE_SOURCE, 0, peer_change_none},
    4362             :         {PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE, 0, peer_change_none},
    4363             :         {PEER_FLAG_EXTENDED_OPT_PARAMS, 0, peer_change_reset},
    4364             :         {PEER_FLAG_ROLE_STRICT_MODE, 0, peer_change_reset},
    4365             :         {PEER_FLAG_ROLE, 0, peer_change_reset},
    4366             :         {PEER_FLAG_PORT, 0, peer_change_reset},
    4367             :         {PEER_FLAG_AIGP, 0, peer_change_none},
    4368             :         {PEER_FLAG_GRACEFUL_SHUTDOWN, 0, peer_change_none},
    4369             :         {0, 0, 0}};
    4370             : 
    4371             : static const struct peer_flag_action peer_af_flag_action_list[] = {
    4372             :         {PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out},
    4373             :         {PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out},
    4374             :         {PEER_FLAG_SEND_LARGE_COMMUNITY, 1, peer_change_reset_out},
    4375             :         {PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out},
    4376             :         {PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset},
    4377             :         {PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset},
    4378             :         {PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in},
    4379             :         {PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out},
    4380             :         {PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out},
    4381             :         {PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out},
    4382             :         {PEER_FLAG_DEFAULT_ORIGINATE, 0, peer_change_none},
    4383             :         {PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out},
    4384             :         {PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in},
    4385             :         {PEER_FLAG_ALLOWAS_IN_ORIGIN, 0, peer_change_reset_in},
    4386             :         {PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset},
    4387             :         {PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset},
    4388             :         {PEER_FLAG_MAX_PREFIX, 0, peer_change_none},
    4389             :         {PEER_FLAG_MAX_PREFIX_WARNING, 0, peer_change_none},
    4390             :         {PEER_FLAG_MAX_PREFIX_FORCE, 0, peer_change_none},
    4391             :         {PEER_FLAG_MAX_PREFIX_OUT, 0, peer_change_none},
    4392             :         {PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out},
    4393             :         {PEER_FLAG_FORCE_NEXTHOP_SELF, 1, peer_change_reset_out},
    4394             :         {PEER_FLAG_REMOVE_PRIVATE_AS_ALL, 1, peer_change_reset_out},
    4395             :         {PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE, 1, peer_change_reset_out},
    4396             :         {PEER_FLAG_AS_OVERRIDE, 1, peer_change_reset_out},
    4397             :         {PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE, 1, peer_change_reset_out},
    4398             :         {PEER_FLAG_WEIGHT, 0, peer_change_reset_in},
    4399             :         {PEER_FLAG_DISABLE_ADDPATH_RX, 0, peer_change_reset},
    4400             :         {PEER_FLAG_SOO, 0, peer_change_reset},
    4401             :         {PEER_FLAG_ACCEPT_OWN, 0, peer_change_reset},
    4402             :         {0, 0, 0}};
    4403             : 
    4404             : /* Proper action set. */
    4405           4 : static int peer_flag_action_set(const struct peer_flag_action *action_list,
    4406             :                                 int size, struct peer_flag_action *action,
    4407             :                                 uint64_t flag)
    4408             : {
    4409           4 :         int i;
    4410           4 :         int found = 0;
    4411           4 :         int reset_in = 0;
    4412           4 :         int reset_out = 0;
    4413           4 :         const struct peer_flag_action *match = NULL;
    4414             : 
    4415             :         /* Check peer's frag action.  */
    4416         112 :         for (i = 0; i < size; i++) {
    4417         112 :                 match = &action_list[i];
    4418             : 
    4419         112 :                 if (match->flag == 0)
    4420             :                         break;
    4421             : 
    4422         108 :                 if (match->flag & flag) {
    4423           4 :                         found = 1;
    4424             : 
    4425           4 :                         if (match->type == peer_change_reset_in)
    4426           0 :                                 reset_in = 1;
    4427           4 :                         if (match->type == peer_change_reset_out)
    4428           0 :                                 reset_out = 1;
    4429           4 :                         if (match->type == peer_change_reset) {
    4430           0 :                                 reset_in = 1;
    4431           0 :                                 reset_out = 1;
    4432             :                         }
    4433           4 :                         if (match->not_for_member)
    4434           0 :                                 action->not_for_member = 1;
    4435             :                 }
    4436             :         }
    4437             : 
    4438             :         /* Set peer clear type.  */
    4439           4 :         if (reset_in && reset_out)
    4440           0 :                 action->type = peer_change_reset;
    4441           4 :         else if (reset_in)
    4442           0 :                 action->type = peer_change_reset_in;
    4443           4 :         else if (reset_out)
    4444           0 :                 action->type = peer_change_reset_out;
    4445             :         else
    4446           4 :                 action->type = peer_change_none;
    4447             : 
    4448           4 :         return found;
    4449             : }
    4450             : 
    4451           0 : static void peer_flag_modify_action(struct peer *peer, uint32_t flag)
    4452             : {
    4453           0 :         if (flag == PEER_FLAG_SHUTDOWN) {
    4454           0 :                 if (CHECK_FLAG(peer->flags, flag)) {
    4455           0 :                         if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT))
    4456           0 :                                 peer_nsf_stop(peer);
    4457             : 
    4458           0 :                         UNSET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
    4459             : 
    4460           0 :                         if (peer->t_pmax_restart) {
    4461           0 :                                 THREAD_OFF(peer->t_pmax_restart);
    4462           0 :                                 if (bgp_debug_neighbor_events(peer))
    4463           0 :                                         zlog_debug(
    4464             :                                                 "%pBP Maximum-prefix restart timer canceled",
    4465             :                                                 peer);
    4466             :                         }
    4467             : 
    4468           0 :                         if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
    4469           0 :                                 char *msg = peer->tx_shutdown_message;
    4470           0 :                                 size_t msglen;
    4471           0 :                                 uint8_t msgbuf[BGP_ADMIN_SHUTDOWN_MSG_LEN + 1];
    4472             : 
    4473           0 :                                 if (!msg && peer_group_active(peer))
    4474           0 :                                         msg = peer->group->conf
    4475             :                                                       ->tx_shutdown_message;
    4476           0 :                                 msglen = msg ? strlen(msg) : 0;
    4477           0 :                                 if (msglen > BGP_ADMIN_SHUTDOWN_MSG_LEN)
    4478             :                                         msglen = BGP_ADMIN_SHUTDOWN_MSG_LEN;
    4479             : 
    4480           0 :                                 if (msglen) {
    4481           0 :                                         msgbuf[0] = msglen;
    4482           0 :                                         memcpy(msgbuf + 1, msg, msglen);
    4483             : 
    4484           0 :                                         bgp_notify_send_with_data(
    4485             :                                                 peer, BGP_NOTIFY_CEASE,
    4486             :                                                 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN,
    4487             :                                                 msgbuf, msglen + 1);
    4488             :                                 } else
    4489           0 :                                         bgp_notify_send(
    4490             :                                                 peer, BGP_NOTIFY_CEASE,
    4491             :                                                 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
    4492             :                         } else
    4493           0 :                                 bgp_session_reset(peer);
    4494             :                 } else {
    4495           0 :                         peer->v_start = BGP_INIT_START_TIMER;
    4496           0 :                         BGP_EVENT_ADD(peer, BGP_Stop);
    4497             :                 }
    4498           0 :         } else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
    4499           0 :                 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
    4500           0 :                         peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
    4501           0 :                 else if (flag == PEER_FLAG_PASSIVE)
    4502           0 :                         peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
    4503           0 :                 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
    4504           0 :                         peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
    4505             : 
    4506           0 :                 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
    4507             :                                 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    4508             :         } else
    4509           0 :                 bgp_session_reset(peer);
    4510           0 : }
    4511             : 
    4512             : /* Enable global administrative shutdown of all peers of BGP instance */
    4513           0 : void bgp_shutdown_enable(struct bgp *bgp, const char *msg)
    4514             : {
    4515           0 :         struct peer *peer;
    4516           0 :         struct listnode *node;
    4517             :         /* length(1) + message(N) */
    4518           0 :         uint8_t data[BGP_ADMIN_SHUTDOWN_MSG_LEN + 1];
    4519             : 
    4520             :         /* do nothing if already shut down */
    4521           0 :         if (CHECK_FLAG(bgp->flags, BGP_FLAG_SHUTDOWN))
    4522           0 :                 return;
    4523             : 
    4524             :         /* informational log message */
    4525           0 :         zlog_info("Enabled administrative shutdown on BGP instance AS %u",
    4526             :                   bgp->as);
    4527             : 
    4528             :         /* iterate through peers of BGP instance */
    4529           0 :         for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
    4530             :                 /* continue, if peer is already in administrative shutdown. */
    4531           0 :                 if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN))
    4532           0 :                         continue;
    4533             : 
    4534             :                 /* send a RFC 4486 notification message if necessary */
    4535           0 :                 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
    4536           0 :                         if (msg) {
    4537           0 :                                 size_t datalen = strlen(msg);
    4538             : 
    4539           0 :                                 if (datalen > BGP_ADMIN_SHUTDOWN_MSG_LEN)
    4540             :                                         datalen = BGP_ADMIN_SHUTDOWN_MSG_LEN;
    4541             : 
    4542           0 :                                 data[0] = datalen;
    4543           0 :                                 memcpy(data + 1, msg, datalen);
    4544             : 
    4545           0 :                                 bgp_notify_send_with_data(
    4546             :                                         peer, BGP_NOTIFY_CEASE,
    4547             :                                         BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN, data,
    4548             :                                         datalen + 1);
    4549             :                         } else {
    4550           0 :                                 bgp_notify_send(
    4551             :                                         peer, BGP_NOTIFY_CEASE,
    4552             :                                         BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
    4553             :                         }
    4554             :                 }
    4555             : 
    4556             :                 /* reset start timer to initial value */
    4557           0 :                 peer->v_start = BGP_INIT_START_TIMER;
    4558             : 
    4559             :                 /* trigger a RFC 4271 ManualStop event */
    4560           0 :                 BGP_EVENT_ADD(peer, BGP_Stop);
    4561             :         }
    4562             : 
    4563             :         /* set the BGP instances shutdown flag */
    4564           0 :         SET_FLAG(bgp->flags, BGP_FLAG_SHUTDOWN);
    4565             : }
    4566             : 
    4567             : /* Disable global administrative shutdown of all peers of BGP instance */
    4568           0 : void bgp_shutdown_disable(struct bgp *bgp)
    4569             : {
    4570             :         /* do nothing if not shut down. */
    4571           0 :         if (!CHECK_FLAG(bgp->flags, BGP_FLAG_SHUTDOWN))
    4572             :                 return;
    4573             : 
    4574             :         /* informational log message */
    4575           0 :         zlog_info("Disabled administrative shutdown on BGP instance AS %u",
    4576             :                   bgp->as);
    4577             : 
    4578             :         /* clear the BGP instances shutdown flag */
    4579           0 :         UNSET_FLAG(bgp->flags, BGP_FLAG_SHUTDOWN);
    4580             : }
    4581             : 
    4582             : /* Change specified peer flag. */
    4583           4 : static int peer_flag_modify(struct peer *peer, uint64_t flag, int set)
    4584             : {
    4585           4 :         int found;
    4586           4 :         int size;
    4587           4 :         bool invert, member_invert;
    4588           4 :         struct peer *member;
    4589           4 :         struct listnode *node, *nnode;
    4590           4 :         struct peer_flag_action action;
    4591             : 
    4592           4 :         memset(&action, 0, sizeof(struct peer_flag_action));
    4593           4 :         size = sizeof(peer_flag_action_list) / sizeof(struct peer_flag_action);
    4594             : 
    4595           4 :         invert = CHECK_FLAG(peer->flags_invert, flag);
    4596           4 :         found = peer_flag_action_set(peer_flag_action_list, size, &action,
    4597             :                                      flag);
    4598             : 
    4599             :         /* Abort if no flag action exists. */
    4600           4 :         if (!found)
    4601             :                 return BGP_ERR_INVALID_FLAG;
    4602             : 
    4603             :         /* Check for flag conflict: STRICT_CAP_MATCH && OVERRIDE_CAPABILITY */
    4604           4 :         if (set && CHECK_FLAG(peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
    4605           4 :             && CHECK_FLAG(peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
    4606             :                 return BGP_ERR_PEER_FLAG_CONFLICT;
    4607             : 
    4608             :         /* Handle flag updates where desired state matches current state. */
    4609           4 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    4610           4 :                 if (set && CHECK_FLAG(peer->flags, flag)) {
    4611           0 :                         COND_FLAG(peer->flags_override, flag, !invert);
    4612           0 :                         return 0;
    4613             :                 }
    4614             : 
    4615           0 :                 if (!set && !CHECK_FLAG(peer->flags, flag)) {
    4616           0 :                         COND_FLAG(peer->flags_override, flag, invert);
    4617           0 :                         return 0;
    4618             :                 }
    4619             :         }
    4620             : 
    4621             :         /* Inherit from peer-group or set/unset flags accordingly. */
    4622           4 :         if (peer_group_active(peer) && set == invert)
    4623           0 :                 peer_flag_inherit(peer, flag);
    4624             :         else
    4625           4 :                 COND_FLAG(peer->flags, flag, set);
    4626             : 
    4627             :         /* Check if handling a regular peer. */
    4628           4 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    4629             :                 /* Update flag override state accordingly. */
    4630           4 :                 COND_FLAG(peer->flags_override, flag, set != invert);
    4631             : 
    4632             :                 /*
    4633             :                  * For the extended next-hop encoding flag we need to turn RAs
    4634             :                  * on if flag is being set, but only turn RAs off if the flag
    4635             :                  * is being unset on this peer and if this peer is a member of a
    4636             :                  * peer-group, the peer-group also doesn't have the flag set.
    4637             :                  */
    4638           4 :                 if (flag == PEER_FLAG_CAPABILITY_ENHE) {
    4639           0 :                         if (set) {
    4640           0 :                                 bgp_zebra_initiate_radv(peer->bgp, peer);
    4641           0 :                         } else if (peer_group_active(peer)) {
    4642           0 :                                 if (!CHECK_FLAG(peer->group->conf->flags,
    4643           0 :                                                 flag) &&
    4644           0 :                                     !peer->conf_if)
    4645           0 :                                         bgp_zebra_terminate_radv(peer->bgp,
    4646             :                                                                  peer);
    4647             :                         } else
    4648           0 :                                 bgp_zebra_terminate_radv(peer->bgp, peer);
    4649             :                 }
    4650             : 
    4651             :                 /* Execute flag action on peer. */
    4652           4 :                 if (action.type == peer_change_reset)
    4653           0 :                         peer_flag_modify_action(peer, flag);
    4654             : 
    4655             :                 /* Skip peer-group mechanics for regular peers. */
    4656           4 :                 return 0;
    4657             :         }
    4658             : 
    4659             :         /*
    4660             :          * Update peer-group members, unless they are explicitly overriding
    4661             :          * peer-group configuration.
    4662             :          */
    4663           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    4664             :                 /* Skip peers with overridden configuration. */
    4665           0 :                 if (CHECK_FLAG(member->flags_override, flag))
    4666           0 :                         continue;
    4667             : 
    4668             :                 /* Check if only member without group is inverted. */
    4669           0 :                 member_invert =
    4670           0 :                         CHECK_FLAG(member->flags_invert, flag) && !invert;
    4671             : 
    4672             :                 /* Skip peers with equivalent configuration. */
    4673           0 :                 if (set != member_invert && CHECK_FLAG(member->flags, flag))
    4674           0 :                         continue;
    4675             : 
    4676           0 :                 if (set == member_invert && !CHECK_FLAG(member->flags, flag))
    4677           0 :                         continue;
    4678             : 
    4679             :                 /* Update flag on peer-group member. */
    4680           0 :                 COND_FLAG(member->flags, flag, set != member_invert);
    4681             : 
    4682           0 :                 if (flag == PEER_FLAG_CAPABILITY_ENHE && !member->conf_if)
    4683           0 :                         set ? bgp_zebra_initiate_radv(member->bgp, member)
    4684           0 :                             : bgp_zebra_terminate_radv(member->bgp, member);
    4685             : 
    4686             :                 /* Execute flag action on peer-group member. */
    4687           0 :                 if (action.type == peer_change_reset)
    4688           0 :                         peer_flag_modify_action(member, flag);
    4689             :         }
    4690             : 
    4691             :         return 0;
    4692             : }
    4693             : 
    4694           4 : int peer_flag_set(struct peer *peer, uint64_t flag)
    4695             : {
    4696           0 :         return peer_flag_modify(peer, flag, 1);
    4697             : }
    4698             : 
    4699           0 : int peer_flag_unset(struct peer *peer, uint64_t flag)
    4700             : {
    4701           0 :         return peer_flag_modify(peer, flag, 0);
    4702             : }
    4703             : 
    4704           0 : static int peer_af_flag_modify(struct peer *peer, afi_t afi, safi_t safi,
    4705             :                                uint64_t flag, bool set)
    4706             : {
    4707           0 :         int found;
    4708           0 :         int size;
    4709           0 :         bool invert, member_invert;
    4710           0 :         struct peer *member;
    4711           0 :         struct listnode *node, *nnode;
    4712           0 :         struct peer_flag_action action;
    4713           0 :         enum bgp_peer_sort ptype;
    4714             : 
    4715           0 :         memset(&action, 0, sizeof(struct peer_flag_action));
    4716           0 :         size = sizeof(peer_af_flag_action_list)
    4717             :                / sizeof(struct peer_flag_action);
    4718             : 
    4719           0 :         invert = CHECK_FLAG(peer->af_flags_invert[afi][safi], flag);
    4720           0 :         found = peer_flag_action_set(peer_af_flag_action_list, size, &action,
    4721             :                                      flag);
    4722             : 
    4723             :         /* Abort if flag action exists. */
    4724           0 :         if (!found)
    4725             :                 return BGP_ERR_INVALID_FLAG;
    4726             : 
    4727           0 :         ptype = peer_sort(peer);
    4728             :         /* Special check for reflector client.  */
    4729           0 :         if (flag & PEER_FLAG_REFLECTOR_CLIENT && ptype != BGP_PEER_IBGP)
    4730             :                 return BGP_ERR_NOT_INTERNAL_PEER;
    4731             : 
    4732             :         /* Special check for remove-private-AS.  */
    4733           0 :         if (flag & PEER_FLAG_REMOVE_PRIVATE_AS && ptype == BGP_PEER_IBGP)
    4734             :                 return BGP_ERR_REMOVE_PRIVATE_AS;
    4735             : 
    4736             :         /* as-override is not allowed for IBGP peers */
    4737           0 :         if (flag & PEER_FLAG_AS_OVERRIDE && ptype == BGP_PEER_IBGP)
    4738             :                 return BGP_ERR_AS_OVERRIDE;
    4739             : 
    4740             :         /* Handle flag updates where desired state matches current state. */
    4741           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    4742           0 :                 if (set && CHECK_FLAG(peer->af_flags[afi][safi], flag)) {
    4743           0 :                         COND_FLAG(peer->af_flags_override[afi][safi], flag,
    4744             :                                   !invert);
    4745           0 :                         return 0;
    4746             :                 }
    4747             : 
    4748           0 :                 if (!set && !CHECK_FLAG(peer->af_flags[afi][safi], flag)) {
    4749           0 :                         COND_FLAG(peer->af_flags_override[afi][safi], flag,
    4750             :                                   invert);
    4751           0 :                         return 0;
    4752             :                 }
    4753             :         }
    4754             : 
    4755             :         /*
    4756             :          * For EVPN we implicitly set the NEXTHOP_UNCHANGED flag,
    4757             :          * if we are setting/unsetting flags which conflict with this flag
    4758             :          * handle accordingly
    4759             :          */
    4760           0 :         if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
    4761           0 :                 if (set) {
    4762             : 
    4763             :                         /*
    4764             :                          * if we are setting NEXTHOP_SELF, we need to unset the
    4765             :                          * NEXTHOP_UNCHANGED flag
    4766             :                          */
    4767           0 :                         if (CHECK_FLAG(flag, PEER_FLAG_NEXTHOP_SELF) ||
    4768             :                             CHECK_FLAG(flag, PEER_FLAG_FORCE_NEXTHOP_SELF))
    4769           0 :                                 UNSET_FLAG(peer->af_flags[afi][safi],
    4770             :                                            PEER_FLAG_NEXTHOP_UNCHANGED);
    4771             :                 } else {
    4772             : 
    4773             :                         /*
    4774             :                          * if we are unsetting NEXTHOP_SELF, we need to set the
    4775             :                          * NEXTHOP_UNCHANGED flag to reset the defaults for EVPN
    4776             :                          */
    4777           0 :                         if (CHECK_FLAG(flag, PEER_FLAG_NEXTHOP_SELF) ||
    4778             :                             CHECK_FLAG(flag, PEER_FLAG_FORCE_NEXTHOP_SELF))
    4779           0 :                                 SET_FLAG(peer->af_flags[afi][safi],
    4780             :                                          PEER_FLAG_NEXTHOP_UNCHANGED);
    4781             :                 }
    4782             :         }
    4783             : 
    4784             :         /*
    4785             :          * If the peer is a route server client let's not
    4786             :          * muck with the nexthop on the way out the door
    4787             :          */
    4788           0 :         if (flag & PEER_FLAG_RSERVER_CLIENT) {
    4789           0 :                 if (set)
    4790           0 :                         SET_FLAG(peer->af_flags[afi][safi],
    4791             :                                  PEER_FLAG_NEXTHOP_UNCHANGED);
    4792             :                 else
    4793           0 :                         UNSET_FLAG(peer->af_flags[afi][safi],
    4794             :                                    PEER_FLAG_NEXTHOP_UNCHANGED);
    4795             :         }
    4796             : 
    4797             :         /* Inherit from peer-group or set/unset flags accordingly. */
    4798           0 :         if (peer_group_active(peer) && set == invert)
    4799           0 :                 peer_af_flag_inherit(peer, afi, safi, flag);
    4800             :         else
    4801           0 :                 COND_FLAG(peer->af_flags[afi][safi], flag, set);
    4802             : 
    4803             :         /* Execute action when peer is established.  */
    4804           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)
    4805           0 :             && peer_established(peer)) {
    4806           0 :                 if (!set && flag == PEER_FLAG_SOFT_RECONFIG)
    4807           0 :                         bgp_clear_adj_in(peer, afi, safi);
    4808             :                 else {
    4809           0 :                         if (flag == PEER_FLAG_REFLECTOR_CLIENT)
    4810           0 :                                 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
    4811           0 :                         else if (flag == PEER_FLAG_RSERVER_CLIENT)
    4812           0 :                                 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
    4813           0 :                         else if (flag == PEER_FLAG_ORF_PREFIX_SM)
    4814           0 :                                 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
    4815           0 :                         else if (flag == PEER_FLAG_ORF_PREFIX_RM)
    4816           0 :                                 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
    4817             : 
    4818           0 :                         peer_change_action(peer, afi, safi, action.type);
    4819             :                 }
    4820             :         }
    4821             : 
    4822             :         /* Check if handling a regular peer. */
    4823           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    4824           0 :                 COND_FLAG(peer->af_flags_override[afi][safi], flag,
    4825             :                           set != invert);
    4826             :         } else {
    4827             :                 /*
    4828             :                  * Update peer-group members, unless they are explicitly
    4829             :                  * overriding peer-group configuration.
    4830             :                  */
    4831           0 :                 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode,
    4832             :                                        member)) {
    4833             :                         /* Skip peers with overridden configuration. */
    4834           0 :                         if (CHECK_FLAG(member->af_flags_override[afi][safi],
    4835             :                                        flag))
    4836           0 :                                 continue;
    4837             : 
    4838             :                         /* Check if only member without group is inverted. */
    4839           0 :                         member_invert =
    4840           0 :                                 CHECK_FLAG(member->af_flags_invert[afi][safi],
    4841             :                                            flag)
    4842           0 :                                 && !invert;
    4843             : 
    4844             :                         /* Skip peers with equivalent configuration. */
    4845           0 :                         if (set != member_invert
    4846           0 :                             && CHECK_FLAG(member->af_flags[afi][safi], flag))
    4847           0 :                                 continue;
    4848             : 
    4849           0 :                         if (set == member_invert
    4850           0 :                             && !CHECK_FLAG(member->af_flags[afi][safi], flag))
    4851           0 :                                 continue;
    4852             : 
    4853             :                         /* Update flag on peer-group member. */
    4854           0 :                         COND_FLAG(member->af_flags[afi][safi], flag,
    4855             :                                   set != member_invert);
    4856             : 
    4857             :                         /* Execute flag action on peer-group member. */
    4858           0 :                         if (peer_established(member)) {
    4859           0 :                                 if (!set && flag == PEER_FLAG_SOFT_RECONFIG)
    4860           0 :                                         bgp_clear_adj_in(member, afi, safi);
    4861             :                                 else {
    4862           0 :                                         if (flag == PEER_FLAG_REFLECTOR_CLIENT)
    4863           0 :                                                 member->last_reset =
    4864             :                                                         PEER_DOWN_RR_CLIENT_CHANGE;
    4865           0 :                                         else if (flag
    4866             :                                                  == PEER_FLAG_RSERVER_CLIENT)
    4867           0 :                                                 member->last_reset =
    4868             :                                                         PEER_DOWN_RS_CLIENT_CHANGE;
    4869           0 :                                         else if (flag
    4870             :                                                  == PEER_FLAG_ORF_PREFIX_SM)
    4871           0 :                                                 member->last_reset =
    4872             :                                                         PEER_DOWN_CAPABILITY_CHANGE;
    4873           0 :                                         else if (flag
    4874             :                                                  == PEER_FLAG_ORF_PREFIX_RM)
    4875           0 :                                                 member->last_reset =
    4876             :                                                         PEER_DOWN_CAPABILITY_CHANGE;
    4877             : 
    4878           0 :                                         peer_change_action(member, afi, safi,
    4879             :                                                            action.type);
    4880             :                                 }
    4881             :                         }
    4882             :                 }
    4883             :         }
    4884             : 
    4885             :         return 0;
    4886             : }
    4887             : 
    4888           0 : int peer_af_flag_set(struct peer *peer, afi_t afi, safi_t safi, uint64_t flag)
    4889             : {
    4890           0 :         return peer_af_flag_modify(peer, afi, safi, flag, 1);
    4891             : }
    4892             : 
    4893           0 : int peer_af_flag_unset(struct peer *peer, afi_t afi, safi_t safi, uint64_t flag)
    4894             : {
    4895           0 :         return peer_af_flag_modify(peer, afi, safi, flag, 0);
    4896             : }
    4897             : 
    4898             : 
    4899           0 : void peer_tx_shutdown_message_set(struct peer *peer, const char *msg)
    4900             : {
    4901           0 :         XFREE(MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message);
    4902           0 :         peer->tx_shutdown_message =
    4903           0 :                 msg ? XSTRDUP(MTYPE_PEER_TX_SHUTDOWN_MSG, msg) : NULL;
    4904           0 : }
    4905             : 
    4906           0 : void peer_tx_shutdown_message_unset(struct peer *peer)
    4907             : {
    4908           0 :         XFREE(MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message);
    4909           0 : }
    4910             : 
    4911             : 
    4912             : /* EBGP multihop configuration. */
    4913           0 : int peer_ebgp_multihop_set(struct peer *peer, int ttl)
    4914             : {
    4915           0 :         struct peer_group *group;
    4916           0 :         struct listnode *node, *nnode;
    4917           0 :         struct peer *peer1;
    4918             : 
    4919           0 :         if (peer->sort == BGP_PEER_IBGP || peer->conf_if)
    4920             :                 return 0;
    4921             : 
    4922             :         /* is there anything to do? */
    4923           0 :         if (peer->ttl == ttl)
    4924             :                 return 0;
    4925             : 
    4926             :         /* see comment in peer_ttl_security_hops_set() */
    4927           0 :         if (ttl != MAXTTL) {
    4928           0 :                 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    4929           0 :                         group = peer->group;
    4930           0 :                         if (group->conf->gtsm_hops != BGP_GTSM_HOPS_DISABLED)
    4931             :                                 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
    4932             : 
    4933           0 :                         for (ALL_LIST_ELEMENTS(group->peer, node, nnode,
    4934             :                                                peer1)) {
    4935           0 :                                 if (peer1->sort == BGP_PEER_IBGP)
    4936           0 :                                         continue;
    4937             : 
    4938           0 :                                 if (peer1->gtsm_hops != BGP_GTSM_HOPS_DISABLED)
    4939             :                                         return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
    4940             :                         }
    4941             :                 } else {
    4942           0 :                         if (peer->gtsm_hops != BGP_GTSM_HOPS_DISABLED)
    4943             :                                 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
    4944             :                 }
    4945             :         }
    4946             : 
    4947           0 :         peer->ttl = ttl;
    4948             : 
    4949           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    4950           0 :                 if (peer->sort != BGP_PEER_IBGP) {
    4951           0 :                         if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
    4952           0 :                                 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
    4953             :                                                 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    4954             :                         else
    4955           0 :                                 bgp_session_reset(peer);
    4956             : 
    4957             :                         /* Reconfigure BFD peer with new TTL. */
    4958           0 :                         if (peer->bfd_config)
    4959           0 :                                 bgp_peer_bfd_update_source(peer);
    4960             :                 }
    4961             :         } else {
    4962           0 :                 group = peer->group;
    4963           0 :                 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
    4964           0 :                         if (peer->sort == BGP_PEER_IBGP)
    4965           0 :                                 continue;
    4966             : 
    4967           0 :                         peer->ttl = group->conf->ttl;
    4968             : 
    4969           0 :                         if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
    4970           0 :                                 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
    4971             :                                                 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    4972             :                         else
    4973           0 :                                 bgp_session_reset(peer);
    4974             : 
    4975             :                         /* Reconfigure BFD peer with new TTL. */
    4976           0 :                         if (peer->bfd_config)
    4977           0 :                                 bgp_peer_bfd_update_source(peer);
    4978             :                 }
    4979             :         }
    4980             :         return 0;
    4981             : }
    4982             : 
    4983           0 : int peer_ebgp_multihop_unset(struct peer *peer)
    4984             : {
    4985           0 :         struct peer_group *group;
    4986           0 :         struct listnode *node, *nnode;
    4987           0 :         int ttl;
    4988             : 
    4989           0 :         if (peer->sort == BGP_PEER_IBGP)
    4990             :                 return 0;
    4991             : 
    4992           0 :         if (peer->gtsm_hops != BGP_GTSM_HOPS_DISABLED && peer->ttl != MAXTTL)
    4993             :                 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
    4994             : 
    4995           0 :         if (peer_group_active(peer))
    4996           0 :                 ttl = peer->group->conf->ttl;
    4997             :         else
    4998             :                 ttl = BGP_DEFAULT_TTL;
    4999             : 
    5000           0 :         if (ttl == peer->ttl)
    5001             :                 return 0;
    5002             : 
    5003           0 :         peer->ttl = ttl;
    5004             : 
    5005           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    5006           0 :                 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
    5007           0 :                         bgp_notify_send(peer, BGP_NOTIFY_CEASE,
    5008             :                                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    5009             :                 else
    5010           0 :                         bgp_session_reset(peer);
    5011             : 
    5012             :                 /* Reconfigure BFD peer with new TTL. */
    5013           0 :                 if (peer->bfd_config)
    5014           0 :                         bgp_peer_bfd_update_source(peer);
    5015             :         } else {
    5016           0 :                 group = peer->group;
    5017           0 :                 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
    5018           0 :                         if (peer->sort == BGP_PEER_IBGP)
    5019           0 :                                 continue;
    5020             : 
    5021           0 :                         peer->ttl = BGP_DEFAULT_TTL;
    5022             : 
    5023           0 :                         if (peer->fd >= 0) {
    5024           0 :                                 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
    5025           0 :                                         bgp_notify_send(
    5026             :                                                 peer, BGP_NOTIFY_CEASE,
    5027             :                                                 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    5028             :                                 else
    5029           0 :                                         bgp_session_reset(peer);
    5030             :                         }
    5031             : 
    5032             :                         /* Reconfigure BFD peer with new TTL. */
    5033           0 :                         if (peer->bfd_config)
    5034           0 :                                 bgp_peer_bfd_update_source(peer);
    5035             :                 }
    5036             :         }
    5037             :         return 0;
    5038             : }
    5039             : 
    5040             : /* Set Open Policy Role and check its correctness */
    5041           0 : int peer_role_set(struct peer *peer, uint8_t role, bool strict_mode)
    5042             : {
    5043           0 :         struct peer *member;
    5044           0 :         struct listnode *node, *nnode;
    5045             : 
    5046           0 :         peer_flag_set(peer, PEER_FLAG_ROLE);
    5047             : 
    5048           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    5049           0 :                 if (peer->sort != BGP_PEER_EBGP)
    5050             :                         return BGP_ERR_INVALID_INTERNAL_ROLE;
    5051             : 
    5052           0 :                 if (peer->local_role == role) {
    5053           0 :                         if (CHECK_FLAG(peer->flags,
    5054           0 :                                        PEER_FLAG_ROLE_STRICT_MODE) &&
    5055             :                             !strict_mode)
    5056             :                                 /* TODO: Is session restart needed if it was
    5057             :                                  * down?
    5058             :                                  */
    5059           0 :                                 UNSET_FLAG(peer->flags,
    5060             :                                            PEER_FLAG_ROLE_STRICT_MODE);
    5061           0 :                         if (!CHECK_FLAG(peer->flags,
    5062           0 :                                         PEER_FLAG_ROLE_STRICT_MODE) &&
    5063             :                             strict_mode) {
    5064           0 :                                 SET_FLAG(peer->flags,
    5065             :                                          PEER_FLAG_ROLE_STRICT_MODE);
    5066             :                                 /* Restart session to throw Role Mismatch
    5067             :                                  * Notification
    5068             :                                  */
    5069           0 :                                 if (peer->remote_role == ROLE_UNDEFINED)
    5070           0 :                                         bgp_session_reset(peer);
    5071             :                         }
    5072             :                 } else {
    5073           0 :                         peer->local_role = role;
    5074           0 :                         if (strict_mode)
    5075           0 :                                 SET_FLAG(peer->flags,
    5076             :                                          PEER_FLAG_ROLE_STRICT_MODE);
    5077             :                         else
    5078           0 :                                 UNSET_FLAG(peer->flags,
    5079             :                                            PEER_FLAG_ROLE_STRICT_MODE);
    5080           0 :                         bgp_session_reset(peer);
    5081             :                 }
    5082             : 
    5083           0 :                 return CMD_SUCCESS;
    5084             :         }
    5085             : 
    5086           0 :         peer->local_role = role;
    5087           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    5088           0 :                 if (member->sort != BGP_PEER_EBGP)
    5089             :                         return BGP_ERR_INVALID_INTERNAL_ROLE;
    5090             : 
    5091           0 :                 if (member->local_role == role) {
    5092           0 :                         if (CHECK_FLAG(member->flags,
    5093           0 :                                        PEER_FLAG_ROLE_STRICT_MODE) &&
    5094             :                             !strict_mode)
    5095             :                                 /* TODO: Is session restart needed if it was
    5096             :                                  * down?
    5097             :                                  */
    5098           0 :                                 UNSET_FLAG(member->flags,
    5099             :                                            PEER_FLAG_ROLE_STRICT_MODE);
    5100           0 :                         if (!CHECK_FLAG(member->flags,
    5101           0 :                                         PEER_FLAG_ROLE_STRICT_MODE) &&
    5102             :                             strict_mode) {
    5103           0 :                                 SET_FLAG(peer->flags,
    5104             :                                          PEER_FLAG_ROLE_STRICT_MODE);
    5105           0 :                                 SET_FLAG(member->flags,
    5106             :                                          PEER_FLAG_ROLE_STRICT_MODE);
    5107             :                                 /* Restart session to throw Role Mismatch
    5108             :                                  * Notification
    5109             :                                  */
    5110           0 :                                 if (member->remote_role == ROLE_UNDEFINED)
    5111           0 :                                         bgp_session_reset(member);
    5112             :                         }
    5113             :                 } else {
    5114           0 :                         member->local_role = role;
    5115             : 
    5116           0 :                         if (strict_mode) {
    5117           0 :                                 SET_FLAG(peer->flags,
    5118             :                                          PEER_FLAG_ROLE_STRICT_MODE);
    5119           0 :                                 SET_FLAG(member->flags,
    5120             :                                          PEER_FLAG_ROLE_STRICT_MODE);
    5121             :                         } else {
    5122           0 :                                 UNSET_FLAG(member->flags,
    5123             :                                            PEER_FLAG_ROLE_STRICT_MODE);
    5124             :                         }
    5125           0 :                         bgp_session_reset(member);
    5126             :                 }
    5127             :         }
    5128             : 
    5129             :         return CMD_SUCCESS;
    5130             : }
    5131             : 
    5132           0 : int peer_role_unset(struct peer *peer)
    5133             : {
    5134           0 :         struct peer *member;
    5135           0 :         struct listnode *node, *nnode;
    5136             : 
    5137           0 :         peer_flag_unset(peer, PEER_FLAG_ROLE);
    5138             : 
    5139           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
    5140           0 :                 return peer_role_set(peer, ROLE_UNDEFINED, 0);
    5141             : 
    5142           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member))
    5143           0 :                 peer_role_set(member, ROLE_UNDEFINED, 0);
    5144             : 
    5145             :         return CMD_SUCCESS;
    5146             : }
    5147             : 
    5148             : /* Neighbor description. */
    5149           0 : void peer_description_set(struct peer *peer, const char *desc)
    5150             : {
    5151           0 :         XFREE(MTYPE_PEER_DESC, peer->desc);
    5152             : 
    5153           0 :         peer->desc = XSTRDUP(MTYPE_PEER_DESC, desc);
    5154           0 : }
    5155             : 
    5156           0 : void peer_description_unset(struct peer *peer)
    5157             : {
    5158           0 :         XFREE(MTYPE_PEER_DESC, peer->desc);
    5159           0 : }
    5160             : 
    5161             : /* Neighbor update-source. */
    5162           0 : int peer_update_source_if_set(struct peer *peer, const char *ifname)
    5163             : {
    5164           0 :         struct peer *member;
    5165           0 :         struct listnode *node, *nnode;
    5166             : 
    5167             :         /* Set flag and configuration on peer. */
    5168           0 :         peer_flag_set(peer, PEER_FLAG_UPDATE_SOURCE);
    5169           0 :         if (peer->update_if) {
    5170           0 :                 if (strcmp(peer->update_if, ifname) == 0)
    5171             :                         return 0;
    5172           0 :                 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
    5173             :         }
    5174           0 :         peer->update_if = XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, ifname);
    5175           0 :         sockunion_free(peer->update_source);
    5176           0 :         peer->update_source = NULL;
    5177             : 
    5178             :         /* Check if handling a regular peer. */
    5179           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    5180             :                 /* Send notification or reset peer depending on state. */
    5181           0 :                 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
    5182           0 :                         peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
    5183           0 :                         bgp_notify_send(peer, BGP_NOTIFY_CEASE,
    5184             :                                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    5185             :                 } else
    5186           0 :                         bgp_session_reset(peer);
    5187             : 
    5188             :                 /* Apply new source configuration to BFD session. */
    5189           0 :                 if (peer->bfd_config)
    5190           0 :                         bgp_peer_bfd_update_source(peer);
    5191             : 
    5192             :                 /* Skip peer-group mechanics for regular peers. */
    5193           0 :                 return 0;
    5194             :         }
    5195             : 
    5196             :         /*
    5197             :          * Set flag and configuration on all peer-group members, unless they are
    5198             :          * explicitly overriding peer-group configuration.
    5199             :          */
    5200           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    5201             :                 /* Skip peers with overridden configuration. */
    5202           0 :                 if (CHECK_FLAG(member->flags_override, PEER_FLAG_UPDATE_SOURCE))
    5203           0 :                         continue;
    5204             : 
    5205             :                 /* Skip peers with the same configuration. */
    5206           0 :                 if (member->update_if) {
    5207           0 :                         if (strcmp(member->update_if, ifname) == 0)
    5208           0 :                                 continue;
    5209           0 :                         XFREE(MTYPE_PEER_UPDATE_SOURCE, member->update_if);
    5210             :                 }
    5211             : 
    5212             :                 /* Set flag and configuration on peer-group member. */
    5213           0 :                 SET_FLAG(member->flags, PEER_FLAG_UPDATE_SOURCE);
    5214           0 :                 member->update_if = XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, ifname);
    5215           0 :                 sockunion_free(member->update_source);
    5216           0 :                 member->update_source = NULL;
    5217             : 
    5218             :                 /* Send notification or reset peer depending on state. */
    5219           0 :                 if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) {
    5220           0 :                         member->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
    5221           0 :                         bgp_notify_send(member, BGP_NOTIFY_CEASE,
    5222             :                                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    5223             :                 } else
    5224           0 :                         bgp_session_reset(member);
    5225             : 
    5226             :                 /* Apply new source configuration to BFD session. */
    5227           0 :                 if (member->bfd_config)
    5228           0 :                         bgp_peer_bfd_update_source(member);
    5229             :         }
    5230             : 
    5231             :         return 0;
    5232             : }
    5233             : 
    5234           0 : void peer_update_source_addr_set(struct peer *peer, const union sockunion *su)
    5235             : {
    5236           0 :         struct peer *member;
    5237           0 :         struct listnode *node, *nnode;
    5238             : 
    5239             :         /* Set flag and configuration on peer. */
    5240           0 :         peer_flag_set(peer, PEER_FLAG_UPDATE_SOURCE);
    5241           0 :         if (peer->update_source) {
    5242           0 :                 if (sockunion_cmp(peer->update_source, su) == 0)
    5243             :                         return;
    5244           0 :                 sockunion_free(peer->update_source);
    5245             :         }
    5246           0 :         peer->update_source = sockunion_dup(su);
    5247           0 :         XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
    5248             : 
    5249             :         /* Check if handling a regular peer. */
    5250           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    5251             :                 /* Send notification or reset peer depending on state. */
    5252           0 :                 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
    5253           0 :                         peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
    5254           0 :                         bgp_notify_send(peer, BGP_NOTIFY_CEASE,
    5255             :                                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    5256             :                 } else
    5257           0 :                         bgp_session_reset(peer);
    5258             : 
    5259             :                 /* Apply new source configuration to BFD session. */
    5260           0 :                 if (peer->bfd_config)
    5261           0 :                         bgp_peer_bfd_update_source(peer);
    5262             : 
    5263             :                 /* Skip peer-group mechanics for regular peers. */
    5264           0 :                 return;
    5265             :         }
    5266             : 
    5267             :         /*
    5268             :          * Set flag and configuration on all peer-group members, unless they are
    5269             :          * explicitly overriding peer-group configuration.
    5270             :          */
    5271           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    5272             :                 /* Skip peers with overridden configuration. */
    5273           0 :                 if (CHECK_FLAG(member->flags_override, PEER_FLAG_UPDATE_SOURCE))
    5274           0 :                         continue;
    5275             : 
    5276             :                 /* Skip peers with the same configuration. */
    5277           0 :                 if (member->update_source) {
    5278           0 :                         if (sockunion_cmp(member->update_source, su) == 0)
    5279           0 :                                 continue;
    5280           0 :                         sockunion_free(member->update_source);
    5281             :                 }
    5282             : 
    5283             :                 /* Set flag and configuration on peer-group member. */
    5284           0 :                 SET_FLAG(member->flags, PEER_FLAG_UPDATE_SOURCE);
    5285           0 :                 member->update_source = sockunion_dup(su);
    5286           0 :                 XFREE(MTYPE_PEER_UPDATE_SOURCE, member->update_if);
    5287             : 
    5288             :                 /* Send notification or reset peer depending on state. */
    5289           0 :                 if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) {
    5290           0 :                         member->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
    5291           0 :                         bgp_notify_send(member, BGP_NOTIFY_CEASE,
    5292             :                                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    5293             :                 } else
    5294           0 :                         bgp_session_reset(member);
    5295             : 
    5296             :                 /* Apply new source configuration to BFD session. */
    5297           0 :                 if (member->bfd_config)
    5298           0 :                         bgp_peer_bfd_update_source(member);
    5299             :         }
    5300             : }
    5301             : 
    5302           0 : void peer_update_source_unset(struct peer *peer)
    5303             : {
    5304           0 :         struct peer *member;
    5305           0 :         struct listnode *node, *nnode;
    5306             : 
    5307           0 :         if (!CHECK_FLAG(peer->flags, PEER_FLAG_UPDATE_SOURCE))
    5308             :                 return;
    5309             : 
    5310             :         /* Inherit configuration from peer-group if peer is member. */
    5311           0 :         if (peer_group_active(peer)) {
    5312           0 :                 peer_flag_inherit(peer, PEER_FLAG_UPDATE_SOURCE);
    5313           0 :                 PEER_SU_ATTR_INHERIT(peer, peer->group, update_source);
    5314           0 :                 PEER_STR_ATTR_INHERIT(peer, peer->group, update_if,
    5315             :                                       MTYPE_PEER_UPDATE_SOURCE);
    5316             :         } else {
    5317             :                 /* Otherwise remove flag and configuration from peer. */
    5318           0 :                 peer_flag_unset(peer, PEER_FLAG_UPDATE_SOURCE);
    5319           0 :                 sockunion_free(peer->update_source);
    5320           0 :                 peer->update_source = NULL;
    5321           0 :                 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
    5322             :         }
    5323             : 
    5324             :         /* Check if handling a regular peer. */
    5325           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    5326             :                 /* Send notification or reset peer depending on state. */
    5327           0 :                 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
    5328           0 :                         peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
    5329           0 :                         bgp_notify_send(peer, BGP_NOTIFY_CEASE,
    5330             :                                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    5331             :                 } else
    5332           0 :                         bgp_session_reset(peer);
    5333             : 
    5334             :                 /* Apply new source configuration to BFD session. */
    5335           0 :                 if (peer->bfd_config)
    5336           0 :                         bgp_peer_bfd_update_source(peer);
    5337             : 
    5338             :                 /* Skip peer-group mechanics for regular peers. */
    5339           0 :                 return;
    5340             :         }
    5341             : 
    5342             :         /*
    5343             :          * Set flag and configuration on all peer-group members, unless they are
    5344             :          * explicitly overriding peer-group configuration.
    5345             :          */
    5346           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    5347             :                 /* Skip peers with overridden configuration. */
    5348           0 :                 if (CHECK_FLAG(member->flags_override, PEER_FLAG_UPDATE_SOURCE))
    5349           0 :                         continue;
    5350             : 
    5351             :                 /* Skip peers with the same configuration. */
    5352           0 :                 if (!CHECK_FLAG(member->flags, PEER_FLAG_UPDATE_SOURCE)
    5353           0 :                     && !member->update_source && !member->update_if)
    5354           0 :                         continue;
    5355             : 
    5356             :                 /* Remove flag and configuration on peer-group member. */
    5357           0 :                 UNSET_FLAG(member->flags, PEER_FLAG_UPDATE_SOURCE);
    5358           0 :                 sockunion_free(member->update_source);
    5359           0 :                 member->update_source = NULL;
    5360           0 :                 XFREE(MTYPE_PEER_UPDATE_SOURCE, member->update_if);
    5361             : 
    5362             :                 /* Send notification or reset peer depending on state. */
    5363           0 :                 if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) {
    5364           0 :                         member->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
    5365           0 :                         bgp_notify_send(member, BGP_NOTIFY_CEASE,
    5366             :                                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    5367             :                 } else
    5368           0 :                         bgp_session_reset(member);
    5369             : 
    5370             :                 /* Apply new source configuration to BFD session. */
    5371           0 :                 if (member->bfd_config)
    5372           0 :                         bgp_peer_bfd_update_source(member);
    5373             :         }
    5374             : }
    5375             : 
    5376           0 : int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi,
    5377             :                                const char *rmap, struct route_map *route_map)
    5378             : {
    5379           0 :         struct peer *member;
    5380           0 :         struct listnode *node, *nnode;
    5381           0 :         struct update_subgroup *subgrp;
    5382             : 
    5383             :         /* Set flag and configuration on peer. */
    5384           0 :         peer_af_flag_set(peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE);
    5385             : 
    5386           0 :         subgrp = peer_subgroup(peer, afi, safi);
    5387             : 
    5388           0 :         if (rmap) {
    5389           0 :                 if (!peer->default_rmap[afi][safi].name
    5390           0 :                     || strcmp(rmap, peer->default_rmap[afi][safi].name) != 0) {
    5391           0 :                         if (peer->default_rmap[afi][safi].name)
    5392           0 :                                 XFREE(MTYPE_ROUTE_MAP_NAME,
    5393             :                                       peer->default_rmap[afi][safi].name);
    5394             : 
    5395             :                         /*
    5396             :                          * When there is a change in route-map policy,
    5397             :                          * this flow gets triggered. Since, the default
    5398             :                          * route is already originated, the flag is set.
    5399             :                          * The flag should be unset here,
    5400             :                          * to trigger the flow of sending update message.
    5401             :                          */
    5402           0 :                         if (subgrp)
    5403           0 :                                 UNSET_FLAG(subgrp->sflags,
    5404             :                                            SUBGRP_STATUS_DEFAULT_ORIGINATE);
    5405             : 
    5406           0 :                         route_map_counter_decrement(peer->default_rmap[afi][safi].map);
    5407           0 :                         peer->default_rmap[afi][safi].name =
    5408           0 :                                 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
    5409           0 :                         peer->default_rmap[afi][safi].map = route_map;
    5410           0 :                         route_map_counter_increment(route_map);
    5411             :                 }
    5412           0 :         } else if (!rmap) {
    5413           0 :                 if (peer->default_rmap[afi][safi].name)
    5414           0 :                         XFREE(MTYPE_ROUTE_MAP_NAME,
    5415             :                               peer->default_rmap[afi][safi].name);
    5416             : 
    5417             :                 /*
    5418             :                  * This is triggered in case of route-map deletion.
    5419             :                  * The flag needs to be unset, to trigger the flow
    5420             :                  * of sending an update message.
    5421             :                  */
    5422           0 :                 if (subgrp)
    5423           0 :                         UNSET_FLAG(subgrp->sflags,
    5424             :                                    SUBGRP_STATUS_DEFAULT_ORIGINATE);
    5425             : 
    5426           0 :                 route_map_counter_decrement(peer->default_rmap[afi][safi].map);
    5427           0 :                 peer->default_rmap[afi][safi].name = NULL;
    5428           0 :                 peer->default_rmap[afi][safi].map = NULL;
    5429             :         }
    5430             : 
    5431             :         /* Check if handling a regular peer. */
    5432           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    5433             :                 /* Update peer route announcements. */
    5434           0 :                 if (peer_established(peer) && peer->afc_nego[afi][safi]) {
    5435           0 :                         update_group_adjust_peer(peer_af_find(peer, afi, safi));
    5436           0 :                         bgp_default_originate(peer, afi, safi, 0);
    5437           0 :                         bgp_announce_route(peer, afi, safi, false);
    5438             :                 }
    5439             : 
    5440             :                 /* Skip peer-group mechanics for regular peers. */
    5441           0 :                 return 0;
    5442             :         }
    5443             : 
    5444             :         /*
    5445             :          * Set flag and configuration on all peer-group members, unless they are
    5446             :          * explicitly overriding peer-group configuration.
    5447             :          */
    5448           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    5449             :                 /* Skip peers with overridden configuration. */
    5450           0 :                 if (CHECK_FLAG(member->af_flags_override[afi][safi],
    5451             :                                PEER_FLAG_DEFAULT_ORIGINATE))
    5452           0 :                         continue;
    5453             : 
    5454             :                 /* Set flag and configuration on peer-group member. */
    5455           0 :                 SET_FLAG(member->af_flags[afi][safi],
    5456             :                          PEER_FLAG_DEFAULT_ORIGINATE);
    5457           0 :                 if (rmap) {
    5458           0 :                         if (member->default_rmap[afi][safi].name)
    5459           0 :                                 XFREE(MTYPE_ROUTE_MAP_NAME,
    5460             :                                       member->default_rmap[afi][safi].name);
    5461           0 :                         route_map_counter_decrement(
    5462             :                                         member->default_rmap[afi][safi].map);
    5463           0 :                         member->default_rmap[afi][safi].name =
    5464           0 :                                 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
    5465           0 :                         member->default_rmap[afi][safi].map = route_map;
    5466           0 :                         route_map_counter_increment(route_map);
    5467             :                 }
    5468             : 
    5469             :                 /* Update peer route announcements. */
    5470           0 :                 if (peer_established(member) && member->afc_nego[afi][safi]) {
    5471           0 :                         update_group_adjust_peer(
    5472             :                                 peer_af_find(member, afi, safi));
    5473           0 :                         bgp_default_originate(member, afi, safi, 0);
    5474           0 :                         bgp_announce_route(member, afi, safi, false);
    5475             :                 }
    5476             :         }
    5477             : 
    5478             :         return 0;
    5479             : }
    5480             : 
    5481           0 : int peer_default_originate_unset(struct peer *peer, afi_t afi, safi_t safi)
    5482             : {
    5483           0 :         struct peer *member;
    5484           0 :         struct listnode *node, *nnode;
    5485             : 
    5486             :         /* Inherit configuration from peer-group if peer is member. */
    5487           0 :         if (peer_group_active(peer)) {
    5488           0 :                 peer_af_flag_inherit(peer, afi, safi,
    5489             :                                      PEER_FLAG_DEFAULT_ORIGINATE);
    5490           0 :                 PEER_STR_ATTR_INHERIT(peer, peer->group,
    5491             :                                       default_rmap[afi][safi].name,
    5492             :                                       MTYPE_ROUTE_MAP_NAME);
    5493           0 :                 PEER_ATTR_INHERIT(peer, peer->group,
    5494             :                                   default_rmap[afi][safi].map);
    5495             :         } else {
    5496             :                 /* Otherwise remove flag and configuration from peer. */
    5497           0 :                 peer_af_flag_unset(peer, afi, safi,
    5498             :                                    PEER_FLAG_DEFAULT_ORIGINATE);
    5499           0 :                 if (peer->default_rmap[afi][safi].name)
    5500           0 :                         XFREE(MTYPE_ROUTE_MAP_NAME,
    5501             :                               peer->default_rmap[afi][safi].name);
    5502           0 :                 route_map_counter_decrement(peer->default_rmap[afi][safi].map);
    5503           0 :                 peer->default_rmap[afi][safi].name = NULL;
    5504           0 :                 peer->default_rmap[afi][safi].map = NULL;
    5505             :         }
    5506             : 
    5507             :         /* Check if handling a regular peer. */
    5508           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    5509             :                 /* Update peer route announcements. */
    5510           0 :                 if (peer_established(peer) && peer->afc_nego[afi][safi]) {
    5511           0 :                         update_group_adjust_peer(peer_af_find(peer, afi, safi));
    5512           0 :                         bgp_default_originate(peer, afi, safi, 1);
    5513           0 :                         bgp_announce_route(peer, afi, safi, false);
    5514             :                 }
    5515             : 
    5516             :                 /* Skip peer-group mechanics for regular peers. */
    5517           0 :                 return 0;
    5518             :         }
    5519             : 
    5520             :         /*
    5521             :          * Remove flag and configuration from all peer-group members, unless
    5522             :          * they are explicitly overriding peer-group configuration.
    5523             :          */
    5524           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    5525             :                 /* Skip peers with overridden configuration. */
    5526           0 :                 if (CHECK_FLAG(member->af_flags_override[afi][safi],
    5527             :                                PEER_FLAG_DEFAULT_ORIGINATE))
    5528           0 :                         continue;
    5529             : 
    5530             :                 /* Remove flag and configuration on peer-group member. */
    5531           0 :                 UNSET_FLAG(member->af_flags[afi][safi],
    5532             :                            PEER_FLAG_DEFAULT_ORIGINATE);
    5533           0 :                 if (member->default_rmap[afi][safi].name)
    5534           0 :                         XFREE(MTYPE_ROUTE_MAP_NAME,
    5535             :                               member->default_rmap[afi][safi].name);
    5536           0 :                 route_map_counter_decrement(member->default_rmap[afi][safi].map);
    5537           0 :                 member->default_rmap[afi][safi].name = NULL;
    5538           0 :                 member->default_rmap[afi][safi].map = NULL;
    5539             : 
    5540             :                 /* Update peer route announcements. */
    5541           0 :                 if (peer_established(member) && member->afc_nego[afi][safi]) {
    5542           0 :                         update_group_adjust_peer(peer_af_find(member, afi, safi));
    5543           0 :                         bgp_default_originate(member, afi, safi, 1);
    5544           0 :                         bgp_announce_route(member, afi, safi, false);
    5545             :                 }
    5546             :         }
    5547             : 
    5548             :         return 0;
    5549             : }
    5550             : 
    5551           0 : void peer_port_set(struct peer *peer, uint16_t port)
    5552             : {
    5553           0 :         peer->port = port;
    5554           0 :         peer_flag_set(peer, PEER_FLAG_PORT);
    5555           0 : }
    5556             : 
    5557           0 : void peer_port_unset(struct peer *peer)
    5558             : {
    5559           0 :         peer->port = BGP_PORT_DEFAULT;
    5560           0 :         peer_flag_unset(peer, PEER_FLAG_PORT);
    5561           0 : }
    5562             : 
    5563             : /* Set the TCP-MSS value in the peer structure,
    5564             :  * This gets applied only after connection reset
    5565             :  * So this value will be used in bgp_connect.
    5566             :  */
    5567           0 : void peer_tcp_mss_set(struct peer *peer, uint32_t tcp_mss)
    5568             : {
    5569           0 :         peer->tcp_mss = tcp_mss;
    5570           0 :         SET_FLAG(peer->flags, PEER_FLAG_TCP_MSS);
    5571           0 : }
    5572             : 
    5573             : /* Reset the TCP-MSS value in the peer structure,
    5574             :  * This gets applied only after connection reset
    5575             :  * So this value will be used in bgp_connect.
    5576             :  */
    5577           0 : void peer_tcp_mss_unset(struct peer *peer)
    5578             : {
    5579           0 :         UNSET_FLAG(peer->flags, PEER_FLAG_TCP_MSS);
    5580           0 :         peer->tcp_mss = 0;
    5581           0 : }
    5582             : 
    5583             : /*
    5584             :  * Helper function that is called after the name of the policy
    5585             :  * being used by a peer has changed (AF specific). Automatically
    5586             :  * initiates inbound or outbound processing as needed.
    5587             :  */
    5588           0 : void peer_on_policy_change(struct peer *peer, afi_t afi, safi_t safi,
    5589             :                            int outbound)
    5590             : {
    5591           0 :         if (outbound) {
    5592           0 :                 update_group_adjust_peer(peer_af_find(peer, afi, safi));
    5593           0 :                 if (peer_established(peer))
    5594           0 :                         bgp_announce_route(peer, afi, safi, false);
    5595             :         } else {
    5596           0 :                 if (!peer_established(peer))
    5597             :                         return;
    5598             : 
    5599           0 :                 if (bgp_soft_reconfig_in(peer, afi, safi))
    5600             :                         return;
    5601             : 
    5602           0 :                 if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV) ||
    5603             :                     CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV)) {
    5604           0 :                         if (CHECK_FLAG(peer->af_cap[afi][safi],
    5605           0 :                                        PEER_CAP_ORF_PREFIX_SM_ADV) &&
    5606           0 :                             (CHECK_FLAG(peer->af_cap[afi][safi],
    5607           0 :                                         PEER_CAP_ORF_PREFIX_RM_RCV) ||
    5608           0 :                              CHECK_FLAG(peer->af_cap[afi][safi],
    5609             :                                         PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
    5610           0 :                                 peer_clear_soft(peer, afi, safi,
    5611             :                                                 BGP_CLEAR_SOFT_IN_ORF_PREFIX);
    5612             :                         else
    5613           0 :                                 bgp_route_refresh_send(
    5614             :                                         peer, afi, safi, 0, 0, 0,
    5615             :                                         BGP_ROUTE_REFRESH_NORMAL);
    5616             :                 }
    5617             :         }
    5618             : }
    5619             : 
    5620             : 
    5621             : /* neighbor weight. */
    5622           0 : int peer_weight_set(struct peer *peer, afi_t afi, safi_t safi, uint16_t weight)
    5623             : {
    5624           0 :         struct peer *member;
    5625           0 :         struct listnode *node, *nnode;
    5626             : 
    5627             :         /* Set flag and configuration on peer. */
    5628           0 :         peer_af_flag_set(peer, afi, safi, PEER_FLAG_WEIGHT);
    5629           0 :         if (peer->weight[afi][safi] != weight) {
    5630           0 :                 peer->weight[afi][safi] = weight;
    5631           0 :                 peer_on_policy_change(peer, afi, safi, 0);
    5632             :         }
    5633             : 
    5634             :         /* Skip peer-group mechanics for regular peers. */
    5635           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
    5636             :                 return 0;
    5637             : 
    5638             :         /*
    5639             :          * Set flag and configuration on all peer-group members, unless they are
    5640             :          * explicitly overriding peer-group configuration.
    5641             :          */
    5642           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    5643             :                 /* Skip peers with overridden configuration. */
    5644           0 :                 if (CHECK_FLAG(member->af_flags_override[afi][safi],
    5645             :                                PEER_FLAG_WEIGHT))
    5646           0 :                         continue;
    5647             : 
    5648             :                 /* Set flag and configuration on peer-group member. */
    5649           0 :                 SET_FLAG(member->af_flags[afi][safi], PEER_FLAG_WEIGHT);
    5650           0 :                 if (member->weight[afi][safi] != weight) {
    5651           0 :                         member->weight[afi][safi] = weight;
    5652           0 :                         peer_on_policy_change(member, afi, safi, 0);
    5653             :                 }
    5654             :         }
    5655             : 
    5656             :         return 0;
    5657             : }
    5658             : 
    5659           0 : int peer_weight_unset(struct peer *peer, afi_t afi, safi_t safi)
    5660             : {
    5661           0 :         struct peer *member;
    5662           0 :         struct listnode *node, *nnode;
    5663             : 
    5664           0 :         if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_WEIGHT))
    5665             :                 return 0;
    5666             : 
    5667             :         /* Inherit configuration from peer-group if peer is member. */
    5668           0 :         if (peer_group_active(peer)) {
    5669           0 :                 peer_af_flag_inherit(peer, afi, safi, PEER_FLAG_WEIGHT);
    5670           0 :                 PEER_ATTR_INHERIT(peer, peer->group, weight[afi][safi]);
    5671             : 
    5672           0 :                 peer_on_policy_change(peer, afi, safi, 0);
    5673           0 :                 return 0;
    5674             :         }
    5675             : 
    5676             :         /* Remove flag and configuration from peer. */
    5677           0 :         peer_af_flag_unset(peer, afi, safi, PEER_FLAG_WEIGHT);
    5678           0 :         peer->weight[afi][safi] = 0;
    5679           0 :         peer_on_policy_change(peer, afi, safi, 0);
    5680             : 
    5681             :         /* Skip peer-group mechanics for regular peers. */
    5682           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
    5683             :                 return 0;
    5684             : 
    5685             :         /*
    5686             :          * Remove flag and configuration from all peer-group members, unless
    5687             :          * they are explicitly overriding peer-group configuration.
    5688             :          */
    5689           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    5690             :                 /* Skip peers with overridden configuration. */
    5691           0 :                 if (CHECK_FLAG(member->af_flags_override[afi][safi],
    5692             :                                PEER_FLAG_WEIGHT))
    5693           0 :                         continue;
    5694             : 
    5695             :                 /* Skip peers where flag is already disabled. */
    5696           0 :                 if (!CHECK_FLAG(member->af_flags[afi][safi], PEER_FLAG_WEIGHT))
    5697           0 :                         continue;
    5698             : 
    5699             :                 /* Remove flag and configuration on peer-group member. */
    5700           0 :                 UNSET_FLAG(member->af_flags[afi][safi], PEER_FLAG_WEIGHT);
    5701           0 :                 member->weight[afi][safi] = 0;
    5702           0 :                 peer_on_policy_change(member, afi, safi, 0);
    5703             :         }
    5704             : 
    5705             :         return 0;
    5706             : }
    5707             : 
    5708           4 : int peer_timers_set(struct peer *peer, uint32_t keepalive, uint32_t holdtime)
    5709             : {
    5710           4 :         struct peer *member;
    5711           4 :         struct listnode *node, *nnode;
    5712             : 
    5713           4 :         if (keepalive > UINT16_MAX)
    5714             :                 return BGP_ERR_INVALID_VALUE;
    5715             : 
    5716           4 :         if (holdtime > UINT16_MAX)
    5717             :                 return BGP_ERR_INVALID_VALUE;
    5718             : 
    5719           4 :         if (holdtime < 3 && holdtime != 0)
    5720             :                 return BGP_ERR_INVALID_VALUE;
    5721             : 
    5722             :         /* Set flag and configuration on peer. */
    5723           4 :         peer_flag_set(peer, PEER_FLAG_TIMER);
    5724           4 :         peer->holdtime = holdtime;
    5725           4 :         peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
    5726             : 
    5727             :         /* Skip peer-group mechanics for regular peers. */
    5728           4 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
    5729             :                 return 0;
    5730             : 
    5731             :         /*
    5732             :          * Set flag and configuration on all peer-group members, unless they are
    5733             :          * explicitly overriding peer-group configuration.
    5734             :          */
    5735           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    5736             :                 /* Skip peers with overridden configuration. */
    5737           0 :                 if (CHECK_FLAG(member->flags_override, PEER_FLAG_TIMER))
    5738           0 :                         continue;
    5739             : 
    5740             :                 /* Set flag and configuration on peer-group member. */
    5741           0 :                 SET_FLAG(member->flags, PEER_FLAG_TIMER);
    5742           0 :                 PEER_ATTR_INHERIT(member, peer->group, holdtime);
    5743           0 :                 PEER_ATTR_INHERIT(member, peer->group, keepalive);
    5744             :         }
    5745             : 
    5746             :         return 0;
    5747             : }
    5748             : 
    5749           0 : int peer_timers_unset(struct peer *peer)
    5750             : {
    5751           0 :         struct peer *member;
    5752           0 :         struct listnode *node, *nnode;
    5753             : 
    5754             :         /* Inherit configuration from peer-group if peer is member. */
    5755           0 :         if (peer_group_active(peer)) {
    5756           0 :                 peer_flag_inherit(peer, PEER_FLAG_TIMER);
    5757           0 :                 PEER_ATTR_INHERIT(peer, peer->group, holdtime);
    5758           0 :                 PEER_ATTR_INHERIT(peer, peer->group, keepalive);
    5759             :         } else {
    5760             :                 /* Otherwise remove flag and configuration from peer. */
    5761           0 :                 peer_flag_unset(peer, PEER_FLAG_TIMER);
    5762           0 :                 peer->holdtime = 0;
    5763           0 :                 peer->keepalive = 0;
    5764             :         }
    5765             : 
    5766             :         /* Skip peer-group mechanics for regular peers. */
    5767           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
    5768             :                 return 0;
    5769             : 
    5770             :         /*
    5771             :          * Remove flag and configuration from all peer-group members, unless
    5772             :          * they are explicitly overriding peer-group configuration.
    5773             :          */
    5774           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    5775             :                 /* Skip peers with overridden configuration. */
    5776           0 :                 if (CHECK_FLAG(member->flags_override, PEER_FLAG_TIMER))
    5777           0 :                         continue;
    5778             : 
    5779             :                 /* Remove flag and configuration on peer-group member. */
    5780           0 :                 UNSET_FLAG(member->flags, PEER_FLAG_TIMER);
    5781           0 :                 member->holdtime = 0;
    5782           0 :                 member->keepalive = 0;
    5783             :         }
    5784             : 
    5785             :         return 0;
    5786             : }
    5787             : 
    5788           0 : int peer_timers_connect_set(struct peer *peer, uint32_t connect)
    5789             : {
    5790           0 :         struct peer *member;
    5791           0 :         struct listnode *node, *nnode;
    5792             : 
    5793           0 :         if (connect > UINT16_MAX)
    5794             :                 return BGP_ERR_INVALID_VALUE;
    5795             : 
    5796             :         /* Set flag and configuration on peer. */
    5797           0 :         peer_flag_set(peer, PEER_FLAG_TIMER_CONNECT);
    5798           0 :         peer->connect = connect;
    5799           0 :         peer->v_connect = connect;
    5800             : 
    5801             :         /* Skip peer-group mechanics for regular peers. */
    5802           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    5803           0 :                 if (!peer_established(peer)) {
    5804           0 :                         if (peer_active(peer))
    5805           0 :                                 BGP_EVENT_ADD(peer, BGP_Stop);
    5806           0 :                         BGP_EVENT_ADD(peer, BGP_Start);
    5807             :                 }
    5808           0 :                 return 0;
    5809             :         }
    5810             :         /*
    5811             :          * Set flag and configuration on all peer-group members, unless they are
    5812             :          * explicitly overriding peer-group configuration.
    5813             :          */
    5814           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    5815             :                 /* Skip peers with overridden configuration. */
    5816           0 :                 if (CHECK_FLAG(member->flags_override, PEER_FLAG_TIMER_CONNECT))
    5817           0 :                         continue;
    5818             : 
    5819             :                 /* Set flag and configuration on peer-group member. */
    5820           0 :                 SET_FLAG(member->flags, PEER_FLAG_TIMER_CONNECT);
    5821           0 :                 member->connect = connect;
    5822           0 :                 member->v_connect = connect;
    5823             : 
    5824           0 :                 if (!peer_established(member)) {
    5825           0 :                         if (peer_active(member))
    5826           0 :                                 BGP_EVENT_ADD(member, BGP_Stop);
    5827           0 :                         BGP_EVENT_ADD(member, BGP_Start);
    5828             :                 }
    5829             :         }
    5830             : 
    5831             :         return 0;
    5832             : }
    5833             : 
    5834           0 : int peer_timers_connect_unset(struct peer *peer)
    5835             : {
    5836           0 :         struct peer *member;
    5837           0 :         struct listnode *node, *nnode;
    5838             : 
    5839             :         /* Inherit configuration from peer-group if peer is member. */
    5840           0 :         if (peer_group_active(peer)) {
    5841           0 :                 peer_flag_inherit(peer, PEER_FLAG_TIMER_CONNECT);
    5842           0 :                 PEER_ATTR_INHERIT(peer, peer->group, connect);
    5843             :         } else {
    5844             :                 /* Otherwise remove flag and configuration from peer. */
    5845           0 :                 peer_flag_unset(peer, PEER_FLAG_TIMER_CONNECT);
    5846           0 :                 peer->connect = 0;
    5847             :         }
    5848             : 
    5849             :         /* Set timer with fallback to default value. */
    5850           0 :         if (peer->connect)
    5851           0 :                 peer->v_connect = peer->connect;
    5852             :         else
    5853           0 :                 peer->v_connect = peer->bgp->default_connect_retry;
    5854             : 
    5855             :         /* Skip peer-group mechanics for regular peers. */
    5856           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    5857           0 :                 if (!peer_established(peer)) {
    5858           0 :                         if (peer_active(peer))
    5859           0 :                                 BGP_EVENT_ADD(peer, BGP_Stop);
    5860           0 :                         BGP_EVENT_ADD(peer, BGP_Start);
    5861             :                 }
    5862           0 :                 return 0;
    5863             :         }
    5864             :         /*
    5865             :          * Remove flag and configuration from all peer-group members, unless
    5866             :          * they are explicitly overriding peer-group configuration.
    5867             :          */
    5868           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    5869             :                 /* Skip peers with overridden configuration. */
    5870           0 :                 if (CHECK_FLAG(member->flags_override, PEER_FLAG_TIMER_CONNECT))
    5871           0 :                         continue;
    5872             : 
    5873             :                 /* Remove flag and configuration on peer-group member. */
    5874           0 :                 UNSET_FLAG(member->flags, PEER_FLAG_TIMER_CONNECT);
    5875           0 :                 member->connect = 0;
    5876           0 :                 member->v_connect = peer->bgp->default_connect_retry;
    5877             : 
    5878           0 :                 if (!peer_established(member)) {
    5879           0 :                         if (peer_active(member))
    5880           0 :                                 BGP_EVENT_ADD(member, BGP_Stop);
    5881           0 :                         BGP_EVENT_ADD(member, BGP_Start);
    5882             :                 }
    5883             :         }
    5884             : 
    5885             :         return 0;
    5886             : }
    5887             : 
    5888           0 : int peer_advertise_interval_set(struct peer *peer, uint32_t routeadv)
    5889             : {
    5890           0 :         struct peer *member;
    5891           0 :         struct listnode *node, *nnode;
    5892             : 
    5893           0 :         if (routeadv > 600)
    5894             :                 return BGP_ERR_INVALID_VALUE;
    5895             : 
    5896             :         /* Set flag and configuration on peer. */
    5897           0 :         peer_flag_set(peer, PEER_FLAG_ROUTEADV);
    5898           0 :         peer->routeadv = routeadv;
    5899           0 :         peer->v_routeadv = routeadv;
    5900             : 
    5901             :         /* Check if handling a regular peer. */
    5902           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    5903             :                 /* Update peer route announcements. */
    5904           0 :                 update_group_adjust_peer_afs(peer);
    5905           0 :                 if (peer_established(peer))
    5906           0 :                         bgp_announce_route_all(peer);
    5907             : 
    5908             :                 /* Skip peer-group mechanics for regular peers. */
    5909           0 :                 return 0;
    5910             :         }
    5911             : 
    5912             :         /*
    5913             :          * Set flag and configuration on all peer-group members, unless they are
    5914             :          * explicitly overriding peer-group configuration.
    5915             :          */
    5916           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    5917             :                 /* Skip peers with overridden configuration. */
    5918           0 :                 if (CHECK_FLAG(member->flags_override, PEER_FLAG_ROUTEADV))
    5919           0 :                         continue;
    5920             : 
    5921             :                 /* Set flag and configuration on peer-group member. */
    5922           0 :                 SET_FLAG(member->flags, PEER_FLAG_ROUTEADV);
    5923           0 :                 member->routeadv = routeadv;
    5924           0 :                 member->v_routeadv = routeadv;
    5925             : 
    5926             :                 /* Update peer route announcements. */
    5927           0 :                 update_group_adjust_peer_afs(member);
    5928           0 :                 if (peer_established(member))
    5929           0 :                         bgp_announce_route_all(member);
    5930             :         }
    5931             : 
    5932             :         return 0;
    5933             : }
    5934             : 
    5935           0 : int peer_advertise_interval_unset(struct peer *peer)
    5936             : {
    5937           0 :         struct peer *member;
    5938           0 :         struct listnode *node, *nnode;
    5939             : 
    5940             :         /* Inherit configuration from peer-group if peer is member. */
    5941           0 :         if (peer_group_active(peer)) {
    5942           0 :                 peer_flag_inherit(peer, PEER_FLAG_ROUTEADV);
    5943           0 :                 PEER_ATTR_INHERIT(peer, peer->group, routeadv);
    5944             :         } else {
    5945             :                 /* Otherwise remove flag and configuration from peer. */
    5946           0 :                 peer_flag_unset(peer, PEER_FLAG_ROUTEADV);
    5947           0 :                 peer->routeadv = 0;
    5948             :         }
    5949             : 
    5950             :         /* Set timer with fallback to default value. */
    5951           0 :         if (peer->routeadv)
    5952           0 :                 peer->v_routeadv = peer->routeadv;
    5953             :         else
    5954           0 :                 peer->v_routeadv = (peer->sort == BGP_PEER_IBGP)
    5955             :                                            ? BGP_DEFAULT_IBGP_ROUTEADV
    5956             :                                            : BGP_DEFAULT_EBGP_ROUTEADV;
    5957             : 
    5958             :         /* Check if handling a regular peer. */
    5959           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    5960             :                 /* Update peer route announcements. */
    5961           0 :                 update_group_adjust_peer_afs(peer);
    5962           0 :                 if (peer_established(peer))
    5963           0 :                         bgp_announce_route_all(peer);
    5964             : 
    5965             :                 /* Skip peer-group mechanics for regular peers. */
    5966           0 :                 return 0;
    5967             :         }
    5968             : 
    5969             :         /*
    5970             :          * Remove flag and configuration from all peer-group members, unless
    5971             :          * they are explicitly overriding peer-group configuration.
    5972             :          */
    5973           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    5974             :                 /* Skip peers with overridden configuration. */
    5975           0 :                 if (CHECK_FLAG(member->flags_override, PEER_FLAG_ROUTEADV))
    5976           0 :                         continue;
    5977             : 
    5978             :                 /* Remove flag and configuration on peer-group member. */
    5979           0 :                 UNSET_FLAG(member->flags, PEER_FLAG_ROUTEADV);
    5980           0 :                 member->routeadv = 0;
    5981           0 :                 member->v_routeadv = (member->sort == BGP_PEER_IBGP)
    5982             :                                              ? BGP_DEFAULT_IBGP_ROUTEADV
    5983             :                                              : BGP_DEFAULT_EBGP_ROUTEADV;
    5984             : 
    5985             :                 /* Update peer route announcements. */
    5986           0 :                 update_group_adjust_peer_afs(member);
    5987           0 :                 if (peer_established(member))
    5988           0 :                         bgp_announce_route_all(member);
    5989             :         }
    5990             : 
    5991             :         return 0;
    5992             : }
    5993             : 
    5994             : /* set the peers RFC 4271 DelayOpen session attribute flag and DelayOpenTimer
    5995             :  * interval
    5996             :  */
    5997           0 : int peer_timers_delayopen_set(struct peer *peer, uint32_t delayopen)
    5998             : {
    5999           0 :         struct peer *member;
    6000           0 :         struct listnode *node;
    6001             : 
    6002             :         /* Set peers session attribute flag and timer interval. */
    6003           0 :         peer_flag_set(peer, PEER_FLAG_TIMER_DELAYOPEN);
    6004           0 :         peer->delayopen = delayopen;
    6005           0 :         peer->v_delayopen = delayopen;
    6006             : 
    6007             :         /* Skip group mechanics for regular peers. */
    6008           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
    6009             :                 return 0;
    6010             : 
    6011             :         /* Set flag and configuration on all peer-group members, unless they are
    6012             :          * explicitly overriding peer-group configuration.
    6013             :          */
    6014           0 :         for (ALL_LIST_ELEMENTS_RO(peer->group->peer, node, member)) {
    6015             :                 /* Skip peers with overridden configuration. */
    6016           0 :                 if (CHECK_FLAG(member->flags_override,
    6017             :                                PEER_FLAG_TIMER_DELAYOPEN))
    6018           0 :                         continue;
    6019             : 
    6020             :                 /* Set session attribute flag and timer intervals on peer-group
    6021             :                  * member.
    6022             :                  */
    6023           0 :                 SET_FLAG(member->flags, PEER_FLAG_TIMER_DELAYOPEN);
    6024           0 :                 member->delayopen = delayopen;
    6025           0 :                 member->v_delayopen = delayopen;
    6026             :         }
    6027             : 
    6028             :         return 0;
    6029             : }
    6030             : 
    6031             : /* unset the peers RFC 4271 DelayOpen session attribute flag and reset the
    6032             :  * DelayOpenTimer interval to the default value.
    6033             :  */
    6034           0 : int peer_timers_delayopen_unset(struct peer *peer)
    6035             : {
    6036           0 :         struct peer *member;
    6037           0 :         struct listnode *node;
    6038             : 
    6039             :         /* Inherit configuration from peer-group if peer is member. */
    6040           0 :         if (peer_group_active(peer)) {
    6041           0 :                 peer_flag_inherit(peer, PEER_FLAG_TIMER_DELAYOPEN);
    6042           0 :                 PEER_ATTR_INHERIT(peer, peer->group, delayopen);
    6043             :         } else {
    6044             :                 /* Otherwise remove session attribute flag and set timer
    6045             :                  * interval to default value.
    6046             :                  */
    6047           0 :                 peer_flag_unset(peer, PEER_FLAG_TIMER_DELAYOPEN);
    6048           0 :                 peer->delayopen = peer->bgp->default_delayopen;
    6049             :         }
    6050             : 
    6051             :         /* Set timer value to zero */
    6052           0 :         peer->v_delayopen = 0;
    6053             : 
    6054             :         /* Skip peer-group mechanics for regular peers. */
    6055           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
    6056             :                 return 0;
    6057             : 
    6058             :         /* Remove flag and configuration from all peer-group members, unless
    6059             :          * they are explicitly overriding peer-group configuration.
    6060             :          */
    6061           0 :         for (ALL_LIST_ELEMENTS_RO(peer->group->peer, node, member)) {
    6062             :                 /* Skip peers with overridden configuration. */
    6063           0 :                 if (CHECK_FLAG(member->flags_override,
    6064             :                                PEER_FLAG_TIMER_DELAYOPEN))
    6065           0 :                         continue;
    6066             : 
    6067             :                 /* Remove session attribute flag, reset the timer interval to
    6068             :                  * the default value and set the timer value to zero.
    6069             :                  */
    6070           0 :                 UNSET_FLAG(member->flags, PEER_FLAG_TIMER_DELAYOPEN);
    6071           0 :                 member->delayopen = peer->bgp->default_delayopen;
    6072           0 :                 member->v_delayopen = 0;
    6073             :         }
    6074             : 
    6075             :         return 0;
    6076             : }
    6077             : 
    6078             : /* neighbor interface */
    6079           0 : void peer_interface_set(struct peer *peer, const char *str)
    6080             : {
    6081           0 :         XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
    6082           0 :         peer->ifname = XSTRDUP(MTYPE_BGP_PEER_IFNAME, str);
    6083           0 : }
    6084             : 
    6085           0 : void peer_interface_unset(struct peer *peer)
    6086             : {
    6087           0 :         XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
    6088           0 : }
    6089             : 
    6090             : /* Allow-as in.  */
    6091           0 : int peer_allowas_in_set(struct peer *peer, afi_t afi, safi_t safi,
    6092             :                         int allow_num, int origin)
    6093             : {
    6094           0 :         struct peer *member;
    6095           0 :         struct listnode *node, *nnode;
    6096             : 
    6097           0 :         if (!origin && (allow_num < 1 || allow_num > 10))
    6098             :                 return BGP_ERR_INVALID_VALUE;
    6099             : 
    6100             :         /* Set flag and configuration on peer. */
    6101           0 :         peer_af_flag_set(peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
    6102           0 :         if (origin) {
    6103           0 :                 if (peer->allowas_in[afi][safi] != 0
    6104           0 :                     || !CHECK_FLAG(peer->af_flags[afi][safi],
    6105             :                                    PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
    6106           0 :                         peer_af_flag_set(peer, afi, safi,
    6107             :                                          PEER_FLAG_ALLOWAS_IN_ORIGIN);
    6108           0 :                         peer->allowas_in[afi][safi] = 0;
    6109           0 :                         peer_on_policy_change(peer, afi, safi, 0);
    6110             :                 }
    6111             :         } else {
    6112           0 :                 if (peer->allowas_in[afi][safi] != allow_num
    6113           0 :                     || CHECK_FLAG(peer->af_flags[afi][safi],
    6114             :                                   PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
    6115             : 
    6116           0 :                         peer_af_flag_unset(peer, afi, safi,
    6117             :                                            PEER_FLAG_ALLOWAS_IN_ORIGIN);
    6118           0 :                         peer->allowas_in[afi][safi] = allow_num;
    6119           0 :                         peer_on_policy_change(peer, afi, safi, 0);
    6120             :                 }
    6121             :         }
    6122             : 
    6123             :         /* Skip peer-group mechanics for regular peers. */
    6124           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
    6125             :                 return 0;
    6126             : 
    6127             :         /*
    6128             :          * Set flag and configuration on all peer-group members, unless
    6129             :          * they are explicitly overriding peer-group configuration.
    6130             :          */
    6131           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    6132             :                 /* Skip peers with overridden configuration. */
    6133           0 :                 if (CHECK_FLAG(member->af_flags_override[afi][safi],
    6134             :                                PEER_FLAG_ALLOWAS_IN))
    6135           0 :                         continue;
    6136             : 
    6137             :                 /* Set flag and configuration on peer-group member. */
    6138           0 :                 SET_FLAG(member->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
    6139           0 :                 if (origin) {
    6140           0 :                         if (member->allowas_in[afi][safi] != 0
    6141           0 :                             || !CHECK_FLAG(member->af_flags[afi][safi],
    6142             :                                            PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
    6143           0 :                                 SET_FLAG(member->af_flags[afi][safi],
    6144             :                                          PEER_FLAG_ALLOWAS_IN_ORIGIN);
    6145           0 :                                 member->allowas_in[afi][safi] = 0;
    6146           0 :                                 peer_on_policy_change(peer, afi, safi, 0);
    6147             :                         }
    6148             :                 } else {
    6149           0 :                         if (member->allowas_in[afi][safi] != allow_num
    6150           0 :                             || CHECK_FLAG(member->af_flags[afi][safi],
    6151             :                                           PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
    6152           0 :                                 UNSET_FLAG(member->af_flags[afi][safi],
    6153             :                                            PEER_FLAG_ALLOWAS_IN_ORIGIN);
    6154           0 :                                 member->allowas_in[afi][safi] = allow_num;
    6155           0 :                                 peer_on_policy_change(peer, afi, safi, 0);
    6156             :                         }
    6157             :                 }
    6158             :         }
    6159             : 
    6160             :         return 0;
    6161             : }
    6162             : 
    6163           0 : int peer_allowas_in_unset(struct peer *peer, afi_t afi, safi_t safi)
    6164             : {
    6165           0 :         struct peer *member;
    6166           0 :         struct listnode *node, *nnode;
    6167             : 
    6168             :         /* Skip peer if flag is already disabled. */
    6169           0 :         if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
    6170             :                 return 0;
    6171             : 
    6172             :         /* Inherit configuration from peer-group if peer is member. */
    6173           0 :         if (peer_group_active(peer)) {
    6174           0 :                 peer_af_flag_inherit(peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
    6175           0 :                 peer_af_flag_inherit(peer, afi, safi,
    6176             :                                      PEER_FLAG_ALLOWAS_IN_ORIGIN);
    6177           0 :                 PEER_ATTR_INHERIT(peer, peer->group, allowas_in[afi][safi]);
    6178           0 :                 peer_on_policy_change(peer, afi, safi, 0);
    6179             : 
    6180           0 :                 return 0;
    6181             :         }
    6182             : 
    6183             :         /* Remove flag and configuration from peer. */
    6184           0 :         peer_af_flag_unset(peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
    6185           0 :         peer_af_flag_unset(peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN);
    6186           0 :         peer->allowas_in[afi][safi] = 0;
    6187           0 :         peer_on_policy_change(peer, afi, safi, 0);
    6188             : 
    6189             :         /* Skip peer-group mechanics if handling a regular peer. */
    6190           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
    6191             :                 return 0;
    6192             : 
    6193             :         /*
    6194             :          * Remove flags and configuration from all peer-group members, unless
    6195             :          * they are explicitly overriding peer-group configuration.
    6196             :          */
    6197           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    6198             :                 /* Skip peers with overridden configuration. */
    6199           0 :                 if (CHECK_FLAG(member->af_flags_override[afi][safi],
    6200             :                                PEER_FLAG_ALLOWAS_IN))
    6201           0 :                         continue;
    6202             : 
    6203             :                 /* Remove flags and configuration on peer-group member. */
    6204           0 :                 UNSET_FLAG(member->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
    6205           0 :                 UNSET_FLAG(member->af_flags[afi][safi],
    6206             :                            PEER_FLAG_ALLOWAS_IN_ORIGIN);
    6207           0 :                 member->allowas_in[afi][safi] = 0;
    6208           0 :                 peer_on_policy_change(member, afi, safi, 0);
    6209             :         }
    6210             : 
    6211             :         return 0;
    6212             : }
    6213             : 
    6214           0 : int peer_local_as_set(struct peer *peer, as_t as, bool no_prepend,
    6215             :                       bool replace_as)
    6216             : {
    6217           0 :         bool old_no_prepend, old_replace_as;
    6218           0 :         struct bgp *bgp = peer->bgp;
    6219           0 :         struct peer *member;
    6220           0 :         struct listnode *node, *nnode;
    6221             : 
    6222           0 :         if (bgp->as == as)
    6223             :                 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
    6224             : 
    6225             :         /* Save previous flag states. */
    6226           0 :         old_no_prepend =
    6227           0 :                 !!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
    6228           0 :         old_replace_as =
    6229           0 :                 !!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
    6230             : 
    6231             :         /* Set flag and configuration on peer. */
    6232           0 :         peer_flag_set(peer, PEER_FLAG_LOCAL_AS);
    6233           0 :         peer_flag_modify(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND, no_prepend);
    6234           0 :         peer_flag_modify(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS, replace_as);
    6235             : 
    6236           0 :         if (peer->change_local_as == as && old_no_prepend == no_prepend
    6237           0 :             && old_replace_as == replace_as)
    6238             :                 return 0;
    6239           0 :         peer->change_local_as = as;
    6240           0 :         (void)peer_sort(peer);
    6241             : 
    6242             :         /* Check if handling a regular peer. */
    6243           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
    6244             :                 return 0;
    6245             : 
    6246             :         /*
    6247             :          * Set flag and configuration on all peer-group members, unless they are
    6248             :          * explicitly overriding peer-group configuration.
    6249             :          */
    6250           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    6251             :                 /* Skip peers with overridden configuration. */
    6252           0 :                 if (CHECK_FLAG(member->flags_override, PEER_FLAG_LOCAL_AS))
    6253           0 :                         continue;
    6254             : 
    6255             :                 /* Skip peers with the same configuration. */
    6256           0 :                 old_no_prepend = CHECK_FLAG(member->flags,
    6257             :                                             PEER_FLAG_LOCAL_AS_NO_PREPEND);
    6258           0 :                 old_replace_as = CHECK_FLAG(member->flags,
    6259             :                                             PEER_FLAG_LOCAL_AS_REPLACE_AS);
    6260           0 :                 if (member->change_local_as == as
    6261           0 :                     && CHECK_FLAG(member->flags, PEER_FLAG_LOCAL_AS)
    6262           0 :                     && old_no_prepend == no_prepend
    6263           0 :                     && old_replace_as == replace_as)
    6264           0 :                         continue;
    6265             : 
    6266             :                 /* Set flag and configuration on peer-group member. */
    6267           0 :                 SET_FLAG(member->flags, PEER_FLAG_LOCAL_AS);
    6268           0 :                 COND_FLAG(member->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND,
    6269             :                           no_prepend);
    6270           0 :                 COND_FLAG(member->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS,
    6271             :                           replace_as);
    6272           0 :                 member->change_local_as = as;
    6273             :         }
    6274             : 
    6275             :         return 0;
    6276             : }
    6277             : 
    6278           0 : int peer_local_as_unset(struct peer *peer)
    6279             : {
    6280           0 :         struct peer *member;
    6281           0 :         struct listnode *node, *nnode;
    6282             : 
    6283           0 :         if (!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS))
    6284             :                 return 0;
    6285             : 
    6286             :         /* Inherit configuration from peer-group if peer is member. */
    6287           0 :         if (peer_group_active(peer)) {
    6288           0 :                 peer_flag_inherit(peer, PEER_FLAG_LOCAL_AS);
    6289           0 :                 peer_flag_inherit(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND);
    6290           0 :                 peer_flag_inherit(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS);
    6291           0 :                 PEER_ATTR_INHERIT(peer, peer->group, change_local_as);
    6292             :         } else {
    6293             :                 /* Otherwise remove flag and configuration from peer. */
    6294           0 :                 peer_flag_unset(peer, PEER_FLAG_LOCAL_AS);
    6295           0 :                 peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND);
    6296           0 :                 peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS);
    6297           0 :                 peer->change_local_as = 0;
    6298             :         }
    6299             : 
    6300             :         /* Check if handling a regular peer. */
    6301           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    6302             :                 /* Send notification or stop peer depending on state. */
    6303           0 :                 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
    6304           0 :                         peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
    6305           0 :                         bgp_notify_send(peer, BGP_NOTIFY_CEASE,
    6306             :                                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    6307             :                 } else
    6308           0 :                         BGP_EVENT_ADD(peer, BGP_Stop);
    6309             : 
    6310             :                 /* Skip peer-group mechanics for regular peers. */
    6311           0 :                 return 0;
    6312             :         }
    6313             : 
    6314             :         /*
    6315             :          * Remove flag and configuration from all peer-group members, unless
    6316             :          * they are explicitly overriding peer-group configuration.
    6317             :          */
    6318           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    6319             :                 /* Skip peers with overridden configuration. */
    6320           0 :                 if (CHECK_FLAG(member->flags_override, PEER_FLAG_LOCAL_AS))
    6321           0 :                         continue;
    6322             : 
    6323             :                 /* Remove flag and configuration on peer-group member. */
    6324           0 :                 UNSET_FLAG(member->flags, PEER_FLAG_LOCAL_AS);
    6325           0 :                 UNSET_FLAG(member->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
    6326           0 :                 UNSET_FLAG(member->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
    6327           0 :                 member->change_local_as = 0;
    6328             : 
    6329             :                 /* Send notification or stop peer depending on state. */
    6330           0 :                 if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) {
    6331           0 :                         member->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
    6332           0 :                         bgp_notify_send(member, BGP_NOTIFY_CEASE,
    6333             :                                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    6334             :                 } else
    6335           0 :                         bgp_session_reset(member);
    6336             :         }
    6337             : 
    6338             :         return 0;
    6339             : }
    6340             : 
    6341             : /* Set password for authenticating with the peer. */
    6342           0 : int peer_password_set(struct peer *peer, const char *password)
    6343             : {
    6344           0 :         struct peer *member;
    6345           0 :         struct listnode *node, *nnode;
    6346           0 :         int len = password ? strlen(password) : 0;
    6347           0 :         int ret = BGP_SUCCESS;
    6348             : 
    6349           0 :         if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
    6350             :                 return BGP_ERR_INVALID_VALUE;
    6351             : 
    6352             :         /* Set flag and configuration on peer. */
    6353           0 :         peer_flag_set(peer, PEER_FLAG_PASSWORD);
    6354           0 :         if (peer->password && strcmp(peer->password, password) == 0)
    6355             :                 return 0;
    6356           0 :         XFREE(MTYPE_PEER_PASSWORD, peer->password);
    6357           0 :         peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
    6358             : 
    6359             :         /* Check if handling a regular peer. */
    6360           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    6361             :                 /* Send notification or reset peer depending on state. */
    6362           0 :                 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
    6363           0 :                         bgp_notify_send(peer, BGP_NOTIFY_CEASE,
    6364             :                                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    6365             :                 else
    6366           0 :                         bgp_session_reset(peer);
    6367             : 
    6368             :                 /*
    6369             :                  * Attempt to install password on socket and skip peer-group
    6370             :                  * mechanics.
    6371             :                  */
    6372           0 :                 if (BGP_PEER_SU_UNSPEC(peer))
    6373             :                         return BGP_SUCCESS;
    6374           0 :                 return (bgp_md5_set(peer) >= 0) ? BGP_SUCCESS
    6375           0 :                                                 : BGP_ERR_TCPSIG_FAILED;
    6376             :         }
    6377             : 
    6378             :         /*
    6379             :          * Set flag and configuration on all peer-group members, unless they are
    6380             :          * explicitly overriding peer-group configuration.
    6381             :          */
    6382           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    6383             :                 /* Skip peers with overridden configuration. */
    6384           0 :                 if (CHECK_FLAG(member->flags_override, PEER_FLAG_PASSWORD))
    6385           0 :                         continue;
    6386             : 
    6387             :                 /* Skip peers with the same password. */
    6388           0 :                 if (member->password && strcmp(member->password, password) == 0)
    6389           0 :                         continue;
    6390             : 
    6391             :                 /* Set flag and configuration on peer-group member. */
    6392           0 :                 SET_FLAG(member->flags, PEER_FLAG_PASSWORD);
    6393           0 :                 if (member->password)
    6394           0 :                         XFREE(MTYPE_PEER_PASSWORD, member->password);
    6395           0 :                 member->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
    6396             : 
    6397             :                 /* Send notification or reset peer depending on state. */
    6398           0 :                 if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status))
    6399           0 :                         bgp_notify_send(member, BGP_NOTIFY_CEASE,
    6400             :                                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    6401             :                 else
    6402           0 :                         bgp_session_reset(member);
    6403             : 
    6404             :                 /* Attempt to install password on socket. */
    6405           0 :                 if (!BGP_PEER_SU_UNSPEC(member) && bgp_md5_set(member) < 0)
    6406           0 :                         ret = BGP_ERR_TCPSIG_FAILED;
    6407             :         }
    6408             : 
    6409             :         /* Set flag and configuration on all peer-group listen ranges */
    6410           0 :         struct listnode *ln;
    6411           0 :         struct prefix *lr;
    6412             : 
    6413           0 :         for (ALL_LIST_ELEMENTS_RO(peer->group->listen_range[AFI_IP], ln, lr))
    6414           0 :                 bgp_md5_set_prefix(peer->bgp, lr, password);
    6415           0 :         for (ALL_LIST_ELEMENTS_RO(peer->group->listen_range[AFI_IP6], ln, lr))
    6416           0 :                 bgp_md5_set_prefix(peer->bgp, lr, password);
    6417             : 
    6418             :         return ret;
    6419             : }
    6420             : 
    6421           0 : int peer_password_unset(struct peer *peer)
    6422             : {
    6423           0 :         struct peer *member;
    6424           0 :         struct listnode *node, *nnode;
    6425             : 
    6426           0 :         if (!CHECK_FLAG(peer->flags, PEER_FLAG_PASSWORD))
    6427             :                 return 0;
    6428             : 
    6429             :         /* Inherit configuration from peer-group if peer is member. */
    6430           0 :         if (peer_group_active(peer)) {
    6431           0 :                 peer_flag_inherit(peer, PEER_FLAG_PASSWORD);
    6432           0 :                 PEER_STR_ATTR_INHERIT(peer, peer->group, password,
    6433             :                                       MTYPE_PEER_PASSWORD);
    6434             :         } else {
    6435             :                 /* Otherwise remove flag and configuration from peer. */
    6436           0 :                 peer_flag_unset(peer, PEER_FLAG_PASSWORD);
    6437           0 :                 XFREE(MTYPE_PEER_PASSWORD, peer->password);
    6438             :         }
    6439             : 
    6440             :         /* Check if handling a regular peer. */
    6441           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    6442             :                 /* Send notification or reset peer depending on state. */
    6443           0 :                 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
    6444           0 :                         bgp_notify_send(peer, BGP_NOTIFY_CEASE,
    6445             :                                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    6446             :                 else
    6447           0 :                         bgp_session_reset(peer);
    6448             : 
    6449             :                 /* Attempt to uninstall password on socket. */
    6450           0 :                 if (!BGP_PEER_SU_UNSPEC(peer))
    6451           0 :                         bgp_md5_unset(peer);
    6452             :                 /* Skip peer-group mechanics for regular peers. */
    6453           0 :                 return 0;
    6454             :         }
    6455             : 
    6456             :         /*
    6457             :          * Remove flag and configuration from all peer-group members, unless
    6458             :          * they are explicitly overriding peer-group configuration.
    6459             :          */
    6460           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    6461             :                 /* Skip peers with overridden configuration. */
    6462           0 :                 if (CHECK_FLAG(member->flags_override, PEER_FLAG_PASSWORD))
    6463           0 :                         continue;
    6464             : 
    6465             :                 /* Remove flag and configuration on peer-group member. */
    6466           0 :                 UNSET_FLAG(member->flags, PEER_FLAG_PASSWORD);
    6467           0 :                 XFREE(MTYPE_PEER_PASSWORD, member->password);
    6468             : 
    6469             :                 /* Send notification or reset peer depending on state. */
    6470           0 :                 if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status))
    6471           0 :                         bgp_notify_send(member, BGP_NOTIFY_CEASE,
    6472             :                                         BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    6473             :                 else
    6474           0 :                         bgp_session_reset(member);
    6475             : 
    6476             :                 /* Attempt to uninstall password on socket. */
    6477           0 :                 if (!BGP_PEER_SU_UNSPEC(member))
    6478           0 :                         bgp_md5_unset(member);
    6479             :         }
    6480             : 
    6481             :         /* Set flag and configuration on all peer-group listen ranges */
    6482           0 :         struct listnode *ln;
    6483           0 :         struct prefix *lr;
    6484             : 
    6485           0 :         for (ALL_LIST_ELEMENTS_RO(peer->group->listen_range[AFI_IP], ln, lr))
    6486           0 :                 bgp_md5_unset_prefix(peer->bgp, lr);
    6487           0 :         for (ALL_LIST_ELEMENTS_RO(peer->group->listen_range[AFI_IP6], ln, lr))
    6488           0 :                 bgp_md5_unset_prefix(peer->bgp, lr);
    6489             : 
    6490             :         return 0;
    6491             : }
    6492             : 
    6493             : 
    6494             : /* Set distribute list to the peer. */
    6495           0 : int peer_distribute_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
    6496             :                         const char *name)
    6497             : {
    6498           0 :         struct peer *member;
    6499           0 :         struct bgp_filter *filter;
    6500           0 :         struct listnode *node, *nnode;
    6501             : 
    6502           0 :         if (direct != FILTER_IN && direct != FILTER_OUT)
    6503             :                 return BGP_ERR_INVALID_VALUE;
    6504             : 
    6505             :         /* Set configuration on peer. */
    6506           0 :         filter = &peer->filter[afi][safi];
    6507           0 :         if (filter->plist[direct].name)
    6508             :                 return BGP_ERR_PEER_FILTER_CONFLICT;
    6509           0 :         if (filter->dlist[direct].name)
    6510           0 :                 XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name);
    6511           0 :         filter->dlist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
    6512           0 :         filter->dlist[direct].alist = access_list_lookup(afi, name);
    6513             : 
    6514             :         /* Check if handling a regular peer. */
    6515           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    6516             :                 /* Set override-flag and process peer route updates. */
    6517           0 :                 SET_FLAG(peer->filter_override[afi][safi][direct],
    6518             :                          PEER_FT_DISTRIBUTE_LIST);
    6519           0 :                 peer_on_policy_change(peer, afi, safi,
    6520             :                                       (direct == FILTER_OUT) ? 1 : 0);
    6521             : 
    6522             :                 /* Skip peer-group mechanics for regular peers. */
    6523           0 :                 return 0;
    6524             :         }
    6525             : 
    6526             :         /*
    6527             :          * Set configuration on all peer-group members, un less they are
    6528             :          * explicitly overriding peer-group configuration.
    6529             :          */
    6530           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    6531             :                 /* Skip peers with overridden configuration. */
    6532           0 :                 if (CHECK_FLAG(member->filter_override[afi][safi][direct],
    6533             :                                PEER_FT_DISTRIBUTE_LIST))
    6534           0 :                         continue;
    6535             : 
    6536             :                 /* Set configuration on peer-group member. */
    6537           0 :                 filter = &member->filter[afi][safi];
    6538           0 :                 if (filter->dlist[direct].name)
    6539           0 :                         XFREE(MTYPE_BGP_FILTER_NAME,
    6540             :                               filter->dlist[direct].name);
    6541           0 :                 filter->dlist[direct].name =
    6542           0 :                         XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
    6543           0 :                 filter->dlist[direct].alist = access_list_lookup(afi, name);
    6544             : 
    6545             :                 /* Process peer route updates. */
    6546           0 :                 peer_on_policy_change(member, afi, safi,
    6547             :                                       (direct == FILTER_OUT) ? 1 : 0);
    6548             :         }
    6549             : 
    6550             :         return 0;
    6551             : }
    6552             : 
    6553           0 : int peer_distribute_unset(struct peer *peer, afi_t afi, safi_t safi, int direct)
    6554             : {
    6555           0 :         struct peer *member;
    6556           0 :         struct bgp_filter *filter;
    6557           0 :         struct listnode *node, *nnode;
    6558             : 
    6559           0 :         if (direct != FILTER_IN && direct != FILTER_OUT)
    6560             :                 return BGP_ERR_INVALID_VALUE;
    6561             : 
    6562             :         /* Unset override-flag unconditionally. */
    6563           0 :         UNSET_FLAG(peer->filter_override[afi][safi][direct],
    6564             :                    PEER_FT_DISTRIBUTE_LIST);
    6565             : 
    6566             :         /* Inherit configuration from peer-group if peer is member. */
    6567           0 :         if (peer_group_active(peer)) {
    6568           0 :                 PEER_STR_ATTR_INHERIT(peer, peer->group,
    6569             :                                       filter[afi][safi].dlist[direct].name,
    6570             :                                       MTYPE_BGP_FILTER_NAME);
    6571           0 :                 PEER_ATTR_INHERIT(peer, peer->group,
    6572             :                                   filter[afi][safi].dlist[direct].alist);
    6573             :         } else {
    6574             :                 /* Otherwise remove configuration from peer. */
    6575           0 :                 filter = &peer->filter[afi][safi];
    6576           0 :                 if (filter->dlist[direct].name)
    6577           0 :                         XFREE(MTYPE_BGP_FILTER_NAME,
    6578             :                               filter->dlist[direct].name);
    6579           0 :                 filter->dlist[direct].name = NULL;
    6580           0 :                 filter->dlist[direct].alist = NULL;
    6581             :         }
    6582             : 
    6583             :         /* Check if handling a regular peer. */
    6584           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    6585             :                 /* Process peer route updates. */
    6586           0 :                 peer_on_policy_change(peer, afi, safi,
    6587             :                                       (direct == FILTER_OUT) ? 1 : 0);
    6588             : 
    6589             :                 /* Skip peer-group mechanics for regular peers. */
    6590           0 :                 return 0;
    6591             :         }
    6592             : 
    6593             :         /*
    6594             :          * Remove configuration on all peer-group members, unless they are
    6595             :          * explicitly overriding peer-group configuration.
    6596             :          */
    6597           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    6598             :                 /* Skip peers with overridden configuration. */
    6599           0 :                 if (CHECK_FLAG(member->filter_override[afi][safi][direct],
    6600             :                                PEER_FT_DISTRIBUTE_LIST))
    6601           0 :                         continue;
    6602             : 
    6603             :                 /* Remove configuration on peer-group member. */
    6604           0 :                 filter = &member->filter[afi][safi];
    6605           0 :                 if (filter->dlist[direct].name)
    6606           0 :                         XFREE(MTYPE_BGP_FILTER_NAME,
    6607             :                               filter->dlist[direct].name);
    6608           0 :                 filter->dlist[direct].name = NULL;
    6609           0 :                 filter->dlist[direct].alist = NULL;
    6610             : 
    6611             :                 /* Process peer route updates. */
    6612           0 :                 peer_on_policy_change(member, afi, safi,
    6613             :                                       (direct == FILTER_OUT) ? 1 : 0);
    6614             :         }
    6615             : 
    6616             :         return 0;
    6617             : }
    6618             : 
    6619             : /* Update distribute list. */
    6620           0 : static void peer_distribute_update(struct access_list *access)
    6621             : {
    6622           0 :         afi_t afi;
    6623           0 :         safi_t safi;
    6624           0 :         int direct;
    6625           0 :         struct listnode *mnode, *mnnode;
    6626           0 :         struct listnode *node, *nnode;
    6627           0 :         struct bgp *bgp;
    6628           0 :         struct peer *peer;
    6629           0 :         struct peer_group *group;
    6630           0 :         struct bgp_filter *filter;
    6631             : 
    6632           0 :         for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
    6633           0 :                 if (access->name)
    6634           0 :                         update_group_policy_update(bgp,
    6635             :                                                    BGP_POLICY_DISTRIBUTE_LIST,
    6636             :                                                    access->name, true, 0);
    6637           0 :                 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
    6638           0 :                         FOREACH_AFI_SAFI (afi, safi) {
    6639           0 :                                 filter = &peer->filter[afi][safi];
    6640             : 
    6641           0 :                                 for (direct = FILTER_IN; direct < FILTER_MAX;
    6642           0 :                                      direct++) {
    6643           0 :                                         if (filter->dlist[direct].name)
    6644           0 :                                                 filter->dlist[direct]
    6645           0 :                                                         .alist = access_list_lookup(
    6646             :                                                         afi,
    6647             :                                                         filter->dlist[direct]
    6648             :                                                                 .name);
    6649             :                                         else
    6650           0 :                                                 filter->dlist[direct].alist =
    6651             :                                                         NULL;
    6652             :                                 }
    6653             :                         }
    6654             :                 }
    6655           0 :                 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
    6656           0 :                         FOREACH_AFI_SAFI (afi, safi) {
    6657           0 :                                 filter = &group->conf->filter[afi][safi];
    6658             : 
    6659           0 :                                 for (direct = FILTER_IN; direct < FILTER_MAX;
    6660           0 :                                      direct++) {
    6661           0 :                                         if (filter->dlist[direct].name)
    6662           0 :                                                 filter->dlist[direct]
    6663           0 :                                                         .alist = access_list_lookup(
    6664             :                                                         afi,
    6665             :                                                         filter->dlist[direct]
    6666             :                                                                 .name);
    6667             :                                         else
    6668           0 :                                                 filter->dlist[direct].alist =
    6669             :                                                         NULL;
    6670             :                                 }
    6671             :                         }
    6672             :                 }
    6673             : #ifdef ENABLE_BGP_VNC
    6674           0 :                 vnc_prefix_list_update(bgp);
    6675             : #endif
    6676             :         }
    6677           0 : }
    6678             : 
    6679             : /* Set prefix list to the peer. */
    6680           0 : int peer_prefix_list_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
    6681             :                          const char *name)
    6682             : {
    6683           0 :         struct peer *member;
    6684           0 :         struct bgp_filter *filter;
    6685           0 :         struct listnode *node, *nnode;
    6686             : 
    6687           0 :         if (direct != FILTER_IN && direct != FILTER_OUT)
    6688             :                 return BGP_ERR_INVALID_VALUE;
    6689             : 
    6690             :         /* Set configuration on peer. */
    6691           0 :         filter = &peer->filter[afi][safi];
    6692           0 :         if (filter->dlist[direct].name)
    6693             :                 return BGP_ERR_PEER_FILTER_CONFLICT;
    6694           0 :         if (filter->plist[direct].name)
    6695           0 :                 XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name);
    6696           0 :         filter->plist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
    6697           0 :         filter->plist[direct].plist = prefix_list_lookup(afi, name);
    6698             : 
    6699             :         /* Check if handling a regular peer. */
    6700           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    6701             :                 /* Set override-flag and process peer route updates. */
    6702           0 :                 SET_FLAG(peer->filter_override[afi][safi][direct],
    6703             :                          PEER_FT_PREFIX_LIST);
    6704           0 :                 peer_on_policy_change(peer, afi, safi,
    6705             :                                       (direct == FILTER_OUT) ? 1 : 0);
    6706             : 
    6707             :                 /* Skip peer-group mechanics for regular peers. */
    6708           0 :                 return 0;
    6709             :         }
    6710             : 
    6711             :         /*
    6712             :          * Set configuration on all peer-group members, unless they are
    6713             :          * explicitly overriding peer-group configuration.
    6714             :          */
    6715           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    6716             :                 /* Skip peers with overridden configuration. */
    6717           0 :                 if (CHECK_FLAG(member->filter_override[afi][safi][direct],
    6718             :                                PEER_FT_PREFIX_LIST))
    6719           0 :                         continue;
    6720             : 
    6721             :                 /* Set configuration on peer-group member. */
    6722           0 :                 filter = &member->filter[afi][safi];
    6723           0 :                 if (filter->plist[direct].name)
    6724           0 :                         XFREE(MTYPE_BGP_FILTER_NAME,
    6725             :                               filter->plist[direct].name);
    6726           0 :                 filter->plist[direct].name =
    6727           0 :                         XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
    6728           0 :                 filter->plist[direct].plist = prefix_list_lookup(afi, name);
    6729             : 
    6730             :                 /* Process peer route updates. */
    6731           0 :                 peer_on_policy_change(member, afi, safi,
    6732             :                                       (direct == FILTER_OUT) ? 1 : 0);
    6733             :         }
    6734             : 
    6735             :         return 0;
    6736             : }
    6737             : 
    6738           0 : int peer_prefix_list_unset(struct peer *peer, afi_t afi, safi_t safi,
    6739             :                            int direct)
    6740             : {
    6741           0 :         struct peer *member;
    6742           0 :         struct bgp_filter *filter;
    6743           0 :         struct listnode *node, *nnode;
    6744             : 
    6745           0 :         if (direct != FILTER_IN && direct != FILTER_OUT)
    6746             :                 return BGP_ERR_INVALID_VALUE;
    6747             : 
    6748             :         /* Unset override-flag unconditionally. */
    6749           0 :         UNSET_FLAG(peer->filter_override[afi][safi][direct],
    6750             :                    PEER_FT_PREFIX_LIST);
    6751             : 
    6752             :         /* Inherit configuration from peer-group if peer is member. */
    6753           0 :         if (peer_group_active(peer)) {
    6754           0 :                 PEER_STR_ATTR_INHERIT(peer, peer->group,
    6755             :                                       filter[afi][safi].plist[direct].name,
    6756             :                                       MTYPE_BGP_FILTER_NAME);
    6757           0 :                 PEER_ATTR_INHERIT(peer, peer->group,
    6758             :                                   filter[afi][safi].plist[direct].plist);
    6759             :         } else {
    6760             :                 /* Otherwise remove configuration from peer. */
    6761           0 :                 filter = &peer->filter[afi][safi];
    6762           0 :                 if (filter->plist[direct].name)
    6763           0 :                         XFREE(MTYPE_BGP_FILTER_NAME,
    6764             :                               filter->plist[direct].name);
    6765           0 :                 filter->plist[direct].name = NULL;
    6766           0 :                 filter->plist[direct].plist = NULL;
    6767             :         }
    6768             : 
    6769             :         /* Check if handling a regular peer. */
    6770           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    6771             :                 /* Process peer route updates. */
    6772           0 :                 peer_on_policy_change(peer, afi, safi,
    6773             :                                       (direct == FILTER_OUT) ? 1 : 0);
    6774             : 
    6775             :                 /* Skip peer-group mechanics for regular peers. */
    6776           0 :                 return 0;
    6777             :         }
    6778             : 
    6779             :         /*
    6780             :          * Remove configuration on all peer-group members, unless they are
    6781             :          * explicitly overriding peer-group configuration.
    6782             :          */
    6783           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    6784             :                 /* Skip peers with overridden configuration. */
    6785           0 :                 if (CHECK_FLAG(member->filter_override[afi][safi][direct],
    6786             :                                PEER_FT_PREFIX_LIST))
    6787           0 :                         continue;
    6788             : 
    6789             :                 /* Remove configuration on peer-group member. */
    6790           0 :                 filter = &member->filter[afi][safi];
    6791           0 :                 if (filter->plist[direct].name)
    6792           0 :                         XFREE(MTYPE_BGP_FILTER_NAME,
    6793             :                               filter->plist[direct].name);
    6794           0 :                 filter->plist[direct].name = NULL;
    6795           0 :                 filter->plist[direct].plist = NULL;
    6796             : 
    6797             :                 /* Process peer route updates. */
    6798           0 :                 peer_on_policy_change(member, afi, safi,
    6799             :                                       (direct == FILTER_OUT) ? 1 : 0);
    6800             :         }
    6801             : 
    6802             :         return 0;
    6803             : }
    6804             : 
    6805             : /* Update prefix-list list. */
    6806           0 : static void peer_prefix_list_update(struct prefix_list *plist)
    6807             : {
    6808           0 :         struct listnode *mnode, *mnnode;
    6809           0 :         struct listnode *node, *nnode;
    6810           0 :         struct bgp *bgp;
    6811           0 :         struct peer *peer;
    6812           0 :         struct peer_group *group;
    6813           0 :         struct bgp_filter *filter;
    6814           0 :         afi_t afi;
    6815           0 :         safi_t safi;
    6816           0 :         int direct;
    6817             : 
    6818           0 :         for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
    6819             : 
    6820             :                 /*
    6821             :                  * Update the prefix-list on update groups.
    6822             :                  */
    6823           0 :                 update_group_policy_update(
    6824             :                         bgp, BGP_POLICY_PREFIX_LIST,
    6825           0 :                         plist ? prefix_list_name(plist) : NULL, true, 0);
    6826             : 
    6827           0 :                 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
    6828           0 :                         FOREACH_AFI_SAFI (afi, safi) {
    6829           0 :                                 filter = &peer->filter[afi][safi];
    6830             : 
    6831           0 :                                 for (direct = FILTER_IN; direct < FILTER_MAX;
    6832           0 :                                      direct++) {
    6833           0 :                                         if (filter->plist[direct].name)
    6834           0 :                                                 filter->plist[direct]
    6835           0 :                                                         .plist = prefix_list_lookup(
    6836             :                                                         afi,
    6837             :                                                         filter->plist[direct]
    6838             :                                                                 .name);
    6839             :                                         else
    6840           0 :                                                 filter->plist[direct].plist =
    6841             :                                                         NULL;
    6842             :                                 }
    6843             : 
    6844             :                                 /* If we touch prefix-list, we need to process
    6845             :                                  * new updates. This is important for ORF to
    6846             :                                  * work correctly as well.
    6847             :                                  */
    6848           0 :                                 if (peer->afc_nego[afi][safi])
    6849           0 :                                         peer_on_policy_change(peer, afi, safi,
    6850             :                                                               0);
    6851             :                         }
    6852             :                 }
    6853           0 :                 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
    6854           0 :                         FOREACH_AFI_SAFI (afi, safi) {
    6855           0 :                                 filter = &group->conf->filter[afi][safi];
    6856             : 
    6857           0 :                                 for (direct = FILTER_IN; direct < FILTER_MAX;
    6858           0 :                                      direct++) {
    6859           0 :                                         if (filter->plist[direct].name)
    6860           0 :                                                 filter->plist[direct]
    6861           0 :                                                         .plist = prefix_list_lookup(
    6862             :                                                         afi,
    6863             :                                                         filter->plist[direct]
    6864             :                                                                 .name);
    6865             :                                         else
    6866           0 :                                                 filter->plist[direct].plist =
    6867             :                                                         NULL;
    6868             :                                 }
    6869             :                         }
    6870             :                 }
    6871             :         }
    6872           0 : }
    6873             : 
    6874           0 : int peer_aslist_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
    6875             :                     const char *name)
    6876             : {
    6877           0 :         struct peer *member;
    6878           0 :         struct bgp_filter *filter;
    6879           0 :         struct listnode *node, *nnode;
    6880             : 
    6881           0 :         if (direct != FILTER_IN && direct != FILTER_OUT)
    6882             :                 return BGP_ERR_INVALID_VALUE;
    6883             : 
    6884             :         /* Set configuration on peer. */
    6885           0 :         filter = &peer->filter[afi][safi];
    6886           0 :         if (filter->aslist[direct].name)
    6887           0 :                 XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name);
    6888           0 :         filter->aslist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
    6889           0 :         filter->aslist[direct].aslist = as_list_lookup(name);
    6890             : 
    6891             :         /* Check if handling a regular peer. */
    6892           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    6893             :                 /* Set override-flag and process peer route updates. */
    6894           0 :                 SET_FLAG(peer->filter_override[afi][safi][direct],
    6895             :                          PEER_FT_FILTER_LIST);
    6896           0 :                 peer_on_policy_change(peer, afi, safi,
    6897             :                                       (direct == FILTER_OUT) ? 1 : 0);
    6898             : 
    6899             :                 /* Skip peer-group mechanics for regular peers. */
    6900           0 :                 return 0;
    6901             :         }
    6902             : 
    6903             :         /*
    6904             :          * Set configuration on all peer-group members, unless they are
    6905             :          * explicitly overriding peer-group configuration.
    6906             :          */
    6907           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    6908             :                 /* Skip peers with overridden configuration. */
    6909           0 :                 if (CHECK_FLAG(member->filter_override[afi][safi][direct],
    6910             :                                PEER_FT_FILTER_LIST))
    6911           0 :                         continue;
    6912             : 
    6913             :                 /* Set configuration on peer-group member. */
    6914           0 :                 filter = &member->filter[afi][safi];
    6915           0 :                 if (filter->aslist[direct].name)
    6916           0 :                         XFREE(MTYPE_BGP_FILTER_NAME,
    6917             :                               filter->aslist[direct].name);
    6918           0 :                 filter->aslist[direct].name =
    6919           0 :                         XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
    6920           0 :                 filter->aslist[direct].aslist = as_list_lookup(name);
    6921             : 
    6922             :                 /* Process peer route updates. */
    6923           0 :                 peer_on_policy_change(member, afi, safi,
    6924             :                                       (direct == FILTER_OUT) ? 1 : 0);
    6925             :         }
    6926             : 
    6927             :         return 0;
    6928             : }
    6929             : 
    6930           0 : int peer_aslist_unset(struct peer *peer, afi_t afi, safi_t safi, int direct)
    6931             : {
    6932           0 :         struct peer *member;
    6933           0 :         struct bgp_filter *filter;
    6934           0 :         struct listnode *node, *nnode;
    6935             : 
    6936           0 :         if (direct != FILTER_IN && direct != FILTER_OUT)
    6937             :                 return BGP_ERR_INVALID_VALUE;
    6938             : 
    6939             :         /* Unset override-flag unconditionally. */
    6940           0 :         UNSET_FLAG(peer->filter_override[afi][safi][direct],
    6941             :                    PEER_FT_FILTER_LIST);
    6942             : 
    6943             :         /* Inherit configuration from peer-group if peer is member. */
    6944           0 :         if (peer_group_active(peer)) {
    6945           0 :                 PEER_STR_ATTR_INHERIT(peer, peer->group,
    6946             :                                       filter[afi][safi].aslist[direct].name,
    6947             :                                       MTYPE_BGP_FILTER_NAME);
    6948           0 :                 PEER_ATTR_INHERIT(peer, peer->group,
    6949             :                                   filter[afi][safi].aslist[direct].aslist);
    6950             :         } else {
    6951             :                 /* Otherwise remove configuration from peer. */
    6952           0 :                 filter = &peer->filter[afi][safi];
    6953           0 :                 if (filter->aslist[direct].name)
    6954           0 :                         XFREE(MTYPE_BGP_FILTER_NAME,
    6955             :                               filter->aslist[direct].name);
    6956           0 :                 filter->aslist[direct].name = NULL;
    6957           0 :                 filter->aslist[direct].aslist = NULL;
    6958             :         }
    6959             : 
    6960             :         /* Check if handling a regular peer. */
    6961           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    6962             :                 /* Process peer route updates. */
    6963           0 :                 peer_on_policy_change(peer, afi, safi,
    6964             :                                       (direct == FILTER_OUT) ? 1 : 0);
    6965             : 
    6966             :                 /* Skip peer-group mechanics for regular peers. */
    6967           0 :                 return 0;
    6968             :         }
    6969             : 
    6970             :         /*
    6971             :          * Remove configuration on all peer-group members, unless they are
    6972             :          * explicitly overriding peer-group configuration.
    6973             :          */
    6974           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    6975             :                 /* Skip peers with overridden configuration. */
    6976           0 :                 if (CHECK_FLAG(member->filter_override[afi][safi][direct],
    6977             :                                PEER_FT_FILTER_LIST))
    6978           0 :                         continue;
    6979             : 
    6980             :                 /* Remove configuration on peer-group member. */
    6981           0 :                 filter = &member->filter[afi][safi];
    6982           0 :                 if (filter->aslist[direct].name)
    6983           0 :                         XFREE(MTYPE_BGP_FILTER_NAME,
    6984             :                               filter->aslist[direct].name);
    6985           0 :                 filter->aslist[direct].name = NULL;
    6986           0 :                 filter->aslist[direct].aslist = NULL;
    6987             : 
    6988             :                 /* Process peer route updates. */
    6989           0 :                 peer_on_policy_change(member, afi, safi,
    6990             :                                       (direct == FILTER_OUT) ? 1 : 0);
    6991             :         }
    6992             : 
    6993             :         return 0;
    6994             : }
    6995             : 
    6996           0 : static void peer_aslist_update(const char *aslist_name)
    6997             : {
    6998           0 :         afi_t afi;
    6999           0 :         safi_t safi;
    7000           0 :         int direct;
    7001           0 :         struct listnode *mnode, *mnnode;
    7002           0 :         struct listnode *node, *nnode;
    7003           0 :         struct bgp *bgp;
    7004           0 :         struct peer *peer;
    7005           0 :         struct peer_group *group;
    7006           0 :         struct bgp_filter *filter;
    7007             : 
    7008           0 :         for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
    7009           0 :                 update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST,
    7010             :                                            aslist_name, true, 0);
    7011             : 
    7012           0 :                 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
    7013           0 :                         FOREACH_AFI_SAFI (afi, safi) {
    7014           0 :                                 filter = &peer->filter[afi][safi];
    7015             : 
    7016           0 :                                 for (direct = FILTER_IN; direct < FILTER_MAX;
    7017           0 :                                      direct++) {
    7018           0 :                                         if (filter->aslist[direct].name)
    7019           0 :                                                 filter->aslist[direct]
    7020           0 :                                                         .aslist = as_list_lookup(
    7021             :                                                         filter->aslist[direct]
    7022             :                                                                 .name);
    7023             :                                         else
    7024           0 :                                                 filter->aslist[direct].aslist =
    7025             :                                                         NULL;
    7026             :                                 }
    7027             :                         }
    7028             :                 }
    7029           0 :                 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
    7030           0 :                         FOREACH_AFI_SAFI (afi, safi) {
    7031           0 :                                 filter = &group->conf->filter[afi][safi];
    7032             : 
    7033           0 :                                 for (direct = FILTER_IN; direct < FILTER_MAX;
    7034           0 :                                      direct++) {
    7035           0 :                                         if (filter->aslist[direct].name)
    7036           0 :                                                 filter->aslist[direct]
    7037           0 :                                                         .aslist = as_list_lookup(
    7038             :                                                         filter->aslist[direct]
    7039             :                                                                 .name);
    7040             :                                         else
    7041           0 :                                                 filter->aslist[direct].aslist =
    7042             :                                                         NULL;
    7043             :                                 }
    7044             :                         }
    7045             :                 }
    7046             :         }
    7047           0 : }
    7048             : 
    7049           0 : static void peer_aslist_add(char *aslist_name)
    7050             : {
    7051           0 :         peer_aslist_update(aslist_name);
    7052           0 :         route_map_notify_dependencies(aslist_name, RMAP_EVENT_ASLIST_ADDED);
    7053           0 : }
    7054             : 
    7055           0 : static void peer_aslist_del(const char *aslist_name)
    7056             : {
    7057           0 :         peer_aslist_update(aslist_name);
    7058           0 :         route_map_notify_dependencies(aslist_name, RMAP_EVENT_ASLIST_DELETED);
    7059           0 : }
    7060             : 
    7061             : 
    7062           0 : int peer_route_map_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
    7063             :                        const char *name, struct route_map *route_map)
    7064             : {
    7065           0 :         struct peer *member;
    7066           0 :         struct bgp_filter *filter;
    7067           0 :         struct listnode *node, *nnode;
    7068             : 
    7069           0 :         if (direct != RMAP_IN && direct != RMAP_OUT)
    7070             :                 return BGP_ERR_INVALID_VALUE;
    7071             : 
    7072             :         /* Set configuration on peer. */
    7073           0 :         filter = &peer->filter[afi][safi];
    7074           0 :         if (filter->map[direct].name) {
    7075             :                 /* If the neighbor is configured with the same route-map
    7076             :                  * again then, ignore the duplicate configuration.
    7077             :                  */
    7078           0 :                 if (strcmp(filter->map[direct].name, name) == 0)
    7079             :                         return 0;
    7080             : 
    7081           0 :                 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
    7082             :         }
    7083           0 :         route_map_counter_decrement(filter->map[direct].map);
    7084           0 :         filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
    7085           0 :         filter->map[direct].map = route_map;
    7086           0 :         route_map_counter_increment(route_map);
    7087             : 
    7088             :         /* Check if handling a regular peer. */
    7089           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    7090             :                 /* Set override-flag and process peer route updates. */
    7091           0 :                 SET_FLAG(peer->filter_override[afi][safi][direct],
    7092             :                          PEER_FT_ROUTE_MAP);
    7093           0 :                 peer_on_policy_change(peer, afi, safi,
    7094             :                                       (direct == RMAP_OUT) ? 1 : 0);
    7095             : 
    7096             :                 /* Skip peer-group mechanics for regular peers. */
    7097           0 :                 return 0;
    7098             :         }
    7099             : 
    7100             :         /*
    7101             :          * Set configuration on all peer-group members, unless they are
    7102             :          * explicitly overriding peer-group configuration.
    7103             :          */
    7104           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    7105             :                 /* Skip peers with overridden configuration. */
    7106           0 :                 if (CHECK_FLAG(member->filter_override[afi][safi][direct],
    7107             :                                PEER_FT_ROUTE_MAP))
    7108           0 :                         continue;
    7109             : 
    7110             :                 /* Set configuration on peer-group member. */
    7111           0 :                 filter = &member->filter[afi][safi];
    7112           0 :                 if (filter->map[direct].name)
    7113           0 :                         XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
    7114           0 :                 route_map_counter_decrement(filter->map[direct].map);
    7115           0 :                 filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
    7116           0 :                 filter->map[direct].map = route_map;
    7117           0 :                 route_map_counter_increment(route_map);
    7118             : 
    7119             :                 /* Process peer route updates. */
    7120           0 :                 peer_on_policy_change(member, afi, safi,
    7121             :                                       (direct == RMAP_OUT) ? 1 : 0);
    7122             :         }
    7123             :         return 0;
    7124             : }
    7125             : 
    7126             : /* Unset route-map from the peer. */
    7127           0 : int peer_route_map_unset(struct peer *peer, afi_t afi, safi_t safi, int direct)
    7128             : {
    7129           0 :         struct peer *member;
    7130           0 :         struct bgp_filter *filter;
    7131           0 :         struct listnode *node, *nnode;
    7132             : 
    7133           0 :         if (direct != RMAP_IN && direct != RMAP_OUT)
    7134             :                 return BGP_ERR_INVALID_VALUE;
    7135             : 
    7136             :         /* Unset override-flag unconditionally. */
    7137           0 :         UNSET_FLAG(peer->filter_override[afi][safi][direct], PEER_FT_ROUTE_MAP);
    7138             : 
    7139             :         /* Inherit configuration from peer-group if peer is member. */
    7140           0 :         if (peer_group_active(peer)) {
    7141           0 :                 PEER_STR_ATTR_INHERIT(peer, peer->group,
    7142             :                                       filter[afi][safi].map[direct].name,
    7143             :                                       MTYPE_BGP_FILTER_NAME);
    7144           0 :                 PEER_ATTR_INHERIT(peer, peer->group,
    7145             :                                   filter[afi][safi].map[direct].map);
    7146             :         } else {
    7147             :                 /* Otherwise remove configuration from peer. */
    7148           0 :                 filter = &peer->filter[afi][safi];
    7149           0 :                 if (filter->map[direct].name)
    7150           0 :                         XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
    7151           0 :                 route_map_counter_decrement(filter->map[direct].map);
    7152           0 :                 filter->map[direct].name = NULL;
    7153           0 :                 filter->map[direct].map = NULL;
    7154             :         }
    7155             : 
    7156             :         /* Check if handling a regular peer. */
    7157           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    7158             :                 /* Process peer route updates. */
    7159           0 :                 peer_on_policy_change(peer, afi, safi,
    7160             :                                       (direct == RMAP_OUT) ? 1 : 0);
    7161             : 
    7162             :                 /* Skip peer-group mechanics for regular peers. */
    7163           0 :                 return 0;
    7164             :         }
    7165             : 
    7166             :         /*
    7167             :          * Remove configuration on all peer-group members, unless they are
    7168             :          * explicitly overriding peer-group configuration.
    7169             :          */
    7170           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    7171             :                 /* Skip peers with overridden configuration. */
    7172           0 :                 if (CHECK_FLAG(member->filter_override[afi][safi][direct],
    7173             :                                PEER_FT_ROUTE_MAP))
    7174           0 :                         continue;
    7175             : 
    7176             :                 /* Remove configuration on peer-group member. */
    7177           0 :                 filter = &member->filter[afi][safi];
    7178           0 :                 if (filter->map[direct].name)
    7179           0 :                         XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
    7180           0 :                 route_map_counter_decrement(filter->map[direct].map);
    7181           0 :                 filter->map[direct].name = NULL;
    7182           0 :                 filter->map[direct].map = NULL;
    7183             : 
    7184             :                 /* Process peer route updates. */
    7185           0 :                 peer_on_policy_change(member, afi, safi,
    7186             :                                       (direct == RMAP_OUT) ? 1 : 0);
    7187             :         }
    7188             : 
    7189             :         return 0;
    7190             : }
    7191             : 
    7192             : /* Set unsuppress-map to the peer. */
    7193           0 : int peer_unsuppress_map_set(struct peer *peer, afi_t afi, safi_t safi,
    7194             :                             const char *name, struct route_map *route_map)
    7195             : {
    7196           0 :         struct peer *member;
    7197           0 :         struct bgp_filter *filter;
    7198           0 :         struct listnode *node, *nnode;
    7199             : 
    7200             :         /* Set configuration on peer. */
    7201           0 :         filter = &peer->filter[afi][safi];
    7202           0 :         if (filter->usmap.name)
    7203           0 :                 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
    7204           0 :         route_map_counter_decrement(filter->usmap.map);
    7205           0 :         filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
    7206           0 :         filter->usmap.map = route_map;
    7207           0 :         route_map_counter_increment(route_map);
    7208             : 
    7209             :         /* Check if handling a regular peer. */
    7210           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    7211             :                 /* Set override-flag and process peer route updates. */
    7212           0 :                 SET_FLAG(peer->filter_override[afi][safi][0],
    7213             :                          PEER_FT_UNSUPPRESS_MAP);
    7214           0 :                 peer_on_policy_change(peer, afi, safi, 1);
    7215             : 
    7216             :                 /* Skip peer-group mechanics for regular peers. */
    7217           0 :                 return 0;
    7218             :         }
    7219             : 
    7220             :         /*
    7221             :          * Set configuration on all peer-group members, unless they are
    7222             :          * explicitly overriding peer-group configuration.
    7223             :          */
    7224           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    7225             :                 /* Skip peers with overridden configuration. */
    7226           0 :                 if (CHECK_FLAG(member->filter_override[afi][safi][0],
    7227             :                                PEER_FT_UNSUPPRESS_MAP))
    7228           0 :                         continue;
    7229             : 
    7230             :                 /* Set configuration on peer-group member. */
    7231           0 :                 filter = &member->filter[afi][safi];
    7232           0 :                 if (filter->usmap.name)
    7233           0 :                         XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
    7234           0 :                 route_map_counter_decrement(filter->usmap.map);
    7235           0 :                 filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
    7236           0 :                 filter->usmap.map = route_map;
    7237           0 :                 route_map_counter_increment(route_map);
    7238             : 
    7239             :                 /* Process peer route updates. */
    7240           0 :                 peer_on_policy_change(member, afi, safi, 1);
    7241             :         }
    7242             : 
    7243             :         return 0;
    7244             : }
    7245             : 
    7246             : /* Unset route-map from the peer. */
    7247           0 : int peer_unsuppress_map_unset(struct peer *peer, afi_t afi, safi_t safi)
    7248             : {
    7249           0 :         struct peer *member;
    7250           0 :         struct bgp_filter *filter;
    7251           0 :         struct listnode *node, *nnode;
    7252             : 
    7253             :         /* Unset override-flag unconditionally. */
    7254           0 :         UNSET_FLAG(peer->filter_override[afi][safi][0], PEER_FT_UNSUPPRESS_MAP);
    7255             : 
    7256             :         /* Inherit configuration from peer-group if peer is member. */
    7257           0 :         if (peer_group_active(peer)) {
    7258           0 :                 PEER_STR_ATTR_INHERIT(peer, peer->group,
    7259             :                                       filter[afi][safi].usmap.name,
    7260             :                                       MTYPE_BGP_FILTER_NAME);
    7261           0 :                 PEER_ATTR_INHERIT(peer, peer->group,
    7262             :                                   filter[afi][safi].usmap.map);
    7263             :         } else {
    7264             :                 /* Otherwise remove configuration from peer. */
    7265           0 :                 filter = &peer->filter[afi][safi];
    7266           0 :                 if (filter->usmap.name)
    7267           0 :                         XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
    7268           0 :                 route_map_counter_decrement(filter->usmap.map);
    7269           0 :                 filter->usmap.name = NULL;
    7270           0 :                 filter->usmap.map = NULL;
    7271             :         }
    7272             : 
    7273             :         /* Check if handling a regular peer. */
    7274           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    7275             :                 /* Process peer route updates. */
    7276           0 :                 peer_on_policy_change(peer, afi, safi, 1);
    7277             : 
    7278             :                 /* Skip peer-group mechanics for regular peers. */
    7279           0 :                 return 0;
    7280             :         }
    7281             : 
    7282             :         /*
    7283             :          * Remove configuration on all peer-group members, unless they are
    7284             :          * explicitly overriding peer-group configuration.
    7285             :          */
    7286           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    7287             :                 /* Skip peers with overridden configuration. */
    7288           0 :                 if (CHECK_FLAG(member->filter_override[afi][safi][0],
    7289             :                                PEER_FT_UNSUPPRESS_MAP))
    7290           0 :                         continue;
    7291             : 
    7292             :                 /* Remove configuration on peer-group member. */
    7293           0 :                 filter = &member->filter[afi][safi];
    7294           0 :                 if (filter->usmap.name)
    7295           0 :                         XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
    7296           0 :                 route_map_counter_decrement(filter->usmap.map);
    7297           0 :                 filter->usmap.name = NULL;
    7298           0 :                 filter->usmap.map = NULL;
    7299             : 
    7300             :                 /* Process peer route updates. */
    7301           0 :                 peer_on_policy_change(member, afi, safi, 1);
    7302             :         }
    7303             : 
    7304             :         return 0;
    7305             : }
    7306             : 
    7307           0 : static bool peer_maximum_prefix_clear_overflow(struct peer *peer)
    7308             : {
    7309           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
    7310             :                 return false;
    7311             : 
    7312           0 :         UNSET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
    7313           0 :         if (peer->t_pmax_restart) {
    7314           0 :                 THREAD_OFF(peer->t_pmax_restart);
    7315           0 :                 if (bgp_debug_neighbor_events(peer))
    7316           0 :                         zlog_debug(
    7317             :                                 "%pBP Maximum-prefix restart timer cancelled",
    7318             :                                 peer);
    7319             :         }
    7320           0 :         BGP_EVENT_ADD(peer, BGP_Start);
    7321             :         return true;
    7322             : }
    7323             : 
    7324           0 : int peer_maximum_prefix_set(struct peer *peer, afi_t afi, safi_t safi,
    7325             :                             uint32_t max, uint8_t threshold, int warning,
    7326             :                             uint16_t restart, bool force)
    7327             : {
    7328           0 :         struct peer *member;
    7329           0 :         struct listnode *node, *nnode;
    7330             : 
    7331             :         /* Set flags and configuration on peer. */
    7332           0 :         peer_af_flag_set(peer, afi, safi, PEER_FLAG_MAX_PREFIX);
    7333             : 
    7334           0 :         if (force)
    7335           0 :                 peer_af_flag_set(peer, afi, safi, PEER_FLAG_MAX_PREFIX_FORCE);
    7336             :         else
    7337           0 :                 peer_af_flag_unset(peer, afi, safi, PEER_FLAG_MAX_PREFIX_FORCE);
    7338             : 
    7339           0 :         if (warning)
    7340           0 :                 peer_af_flag_set(peer, afi, safi, PEER_FLAG_MAX_PREFIX_WARNING);
    7341             :         else
    7342           0 :                 peer_af_flag_unset(peer, afi, safi,
    7343             :                                    PEER_FLAG_MAX_PREFIX_WARNING);
    7344             : 
    7345           0 :         peer->pmax[afi][safi] = max;
    7346           0 :         peer->pmax_threshold[afi][safi] = threshold;
    7347           0 :         peer->pmax_restart[afi][safi] = restart;
    7348             : 
    7349             :         /* Check if handling a regular peer. */
    7350           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    7351             :                 /* Re-check if peer violates maximum-prefix. */
    7352           0 :                 if ((peer_established(peer)) && (peer->afc[afi][safi]))
    7353           0 :                         bgp_maximum_prefix_overflow(peer, afi, safi, 1);
    7354             : 
    7355             :                 /* Skip peer-group mechanics for regular peers. */
    7356           0 :                 return 0;
    7357             :         }
    7358             : 
    7359             :         /*
    7360             :          * Set flags and configuration on all peer-group members, unless they
    7361             :          * are explicitly overriding peer-group configuration.
    7362             :          */
    7363           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    7364             :                 /* Skip peers with overridden configuration. */
    7365           0 :                 if (CHECK_FLAG(member->af_flags_override[afi][safi],
    7366             :                                PEER_FLAG_MAX_PREFIX))
    7367           0 :                         continue;
    7368             : 
    7369             :                 /* Set flag and configuration on peer-group member. */
    7370           0 :                 member->pmax[afi][safi] = max;
    7371           0 :                 member->pmax_threshold[afi][safi] = threshold;
    7372           0 :                 member->pmax_restart[afi][safi] = restart;
    7373             : 
    7374           0 :                 if (force)
    7375           0 :                         SET_FLAG(member->af_flags[afi][safi],
    7376             :                                  PEER_FLAG_MAX_PREFIX_FORCE);
    7377             :                 else
    7378           0 :                         UNSET_FLAG(member->af_flags[afi][safi],
    7379             :                                    PEER_FLAG_MAX_PREFIX_FORCE);
    7380             : 
    7381           0 :                 if (warning)
    7382           0 :                         SET_FLAG(member->af_flags[afi][safi],
    7383             :                                  PEER_FLAG_MAX_PREFIX_WARNING);
    7384             :                 else
    7385           0 :                         UNSET_FLAG(member->af_flags[afi][safi],
    7386             :                                    PEER_FLAG_MAX_PREFIX_WARNING);
    7387             : 
    7388             :                 /* Re-check if peer violates maximum-prefix. */
    7389           0 :                 if ((peer_established(member)) && (member->afc[afi][safi]))
    7390           0 :                         bgp_maximum_prefix_overflow(member, afi, safi, 1);
    7391             :         }
    7392             : 
    7393             :         return 0;
    7394             : }
    7395             : 
    7396           0 : int peer_maximum_prefix_unset(struct peer *peer, afi_t afi, safi_t safi)
    7397             : {
    7398             :         /* Inherit configuration from peer-group if peer is member. */
    7399           0 :         if (peer_group_active(peer)) {
    7400           0 :                 peer_af_flag_inherit(peer, afi, safi, PEER_FLAG_MAX_PREFIX);
    7401           0 :                 peer_af_flag_inherit(peer, afi, safi,
    7402             :                                      PEER_FLAG_MAX_PREFIX_FORCE);
    7403           0 :                 peer_af_flag_inherit(peer, afi, safi,
    7404             :                                      PEER_FLAG_MAX_PREFIX_WARNING);
    7405           0 :                 PEER_ATTR_INHERIT(peer, peer->group, pmax[afi][safi]);
    7406           0 :                 PEER_ATTR_INHERIT(peer, peer->group, pmax_threshold[afi][safi]);
    7407           0 :                 PEER_ATTR_INHERIT(peer, peer->group, pmax_restart[afi][safi]);
    7408             : 
    7409           0 :                 return 0;
    7410             :         }
    7411             : 
    7412             :         /* Remove flags and configuration from peer. */
    7413           0 :         peer_af_flag_unset(peer, afi, safi, PEER_FLAG_MAX_PREFIX);
    7414           0 :         peer_af_flag_unset(peer, afi, safi, PEER_FLAG_MAX_PREFIX_FORCE);
    7415           0 :         peer_af_flag_unset(peer, afi, safi, PEER_FLAG_MAX_PREFIX_WARNING);
    7416           0 :         peer->pmax[afi][safi] = 0;
    7417           0 :         peer->pmax_threshold[afi][safi] = 0;
    7418           0 :         peer->pmax_restart[afi][safi] = 0;
    7419             : 
    7420             :         /*
    7421             :          * Remove flags and configuration from all peer-group members, unless
    7422             :          * they are explicitly overriding peer-group configuration.
    7423             :          */
    7424           0 :         if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    7425           0 :                 struct peer *member;
    7426           0 :                 struct listnode *node;
    7427             : 
    7428           0 :                 for (ALL_LIST_ELEMENTS_RO(peer->group->peer, node, member)) {
    7429             :                         /* Skip peers with overridden configuration. */
    7430           0 :                         if (CHECK_FLAG(member->af_flags_override[afi][safi],
    7431             :                                        PEER_FLAG_MAX_PREFIX))
    7432           0 :                                 continue;
    7433             : 
    7434             :                         /* Remove flag and configuration on peer-group member.
    7435             :                          */
    7436           0 :                         UNSET_FLAG(member->af_flags[afi][safi],
    7437             :                                    PEER_FLAG_MAX_PREFIX);
    7438           0 :                         UNSET_FLAG(member->af_flags[afi][safi],
    7439             :                                    PEER_FLAG_MAX_PREFIX_FORCE);
    7440           0 :                         UNSET_FLAG(member->af_flags[afi][safi],
    7441             :                                    PEER_FLAG_MAX_PREFIX_WARNING);
    7442           0 :                         member->pmax[afi][safi] = 0;
    7443           0 :                         member->pmax_threshold[afi][safi] = 0;
    7444           0 :                         member->pmax_restart[afi][safi] = 0;
    7445             : 
    7446           0 :                         peer_maximum_prefix_clear_overflow(member);
    7447             :                 }
    7448             :         } else {
    7449           0 :                 peer_maximum_prefix_clear_overflow(peer);
    7450             :         }
    7451             : 
    7452             :         return 0;
    7453             : }
    7454             : 
    7455           0 : void peer_maximum_prefix_out_refresh_routes(struct peer *peer, afi_t afi,
    7456             :                                             safi_t safi)
    7457             : {
    7458           0 :         update_group_adjust_peer(peer_af_find(peer, afi, safi));
    7459             : 
    7460           0 :         if (peer_established(peer))
    7461           0 :                 bgp_announce_route(peer, afi, safi, false);
    7462           0 : }
    7463             : 
    7464           0 : int peer_maximum_prefix_out_set(struct peer *peer, afi_t afi, safi_t safi,
    7465             :                                 uint32_t max)
    7466             : {
    7467           0 :         struct peer *member;
    7468           0 :         struct listnode *node, *nnode;
    7469             : 
    7470             :         /* Set flag on peer and peer-group member if any */
    7471           0 :         peer_af_flag_set(peer, afi, safi, PEER_FLAG_MAX_PREFIX_OUT);
    7472             :         /* Set configuration on peer. */
    7473           0 :         peer->pmax_out[afi][safi] = max;
    7474             : 
    7475             :         /* Check if handling a regular peer. */
    7476           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    7477             :                 /* Skip peer-group mechanics for regular peers. */
    7478           0 :                 peer_maximum_prefix_out_refresh_routes(peer, afi, safi);
    7479           0 :                 return 0;
    7480             :         }
    7481             : 
    7482             :         /*
    7483             :          * Set flag and configuration on all peer-group members, unless they
    7484             :          * are explicitly overriding peer-group configuration.
    7485             :          */
    7486           0 :         for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
    7487             :                 /* Skip peers with overridden configuration. */
    7488           0 :                 if (CHECK_FLAG(member->af_flags_override[afi][safi],
    7489             :                                PEER_FLAG_MAX_PREFIX_OUT))
    7490           0 :                         continue;
    7491             : 
    7492             :                 /* Set configuration on peer-group member. */
    7493           0 :                 member->pmax_out[afi][safi] = max;
    7494             : 
    7495           0 :                 peer_maximum_prefix_out_refresh_routes(member, afi, safi);
    7496             :         }
    7497             :         return 0;
    7498             : }
    7499             : 
    7500           0 : int peer_maximum_prefix_out_unset(struct peer *peer, afi_t afi, safi_t safi)
    7501             : {
    7502           0 :         struct peer *member;
    7503           0 :         struct listnode *node;
    7504             :         /* Inherit configuration from peer-group if peer is member. */
    7505           0 :         if (peer_group_active(peer)) {
    7506           0 :                 peer_af_flag_inherit(peer, afi, safi, PEER_FLAG_MAX_PREFIX_OUT);
    7507           0 :                 PEER_ATTR_INHERIT(peer, peer->group, pmax_out[afi][safi]);
    7508             : 
    7509           0 :                 peer_maximum_prefix_out_refresh_routes(peer, afi, safi);
    7510           0 :                 return 0;
    7511             :         }
    7512             : 
    7513             :         /* Remove flag and configuration from peer. */
    7514           0 :         peer_af_flag_unset(peer, afi, safi, PEER_FLAG_MAX_PREFIX_OUT);
    7515           0 :         peer->pmax_out[afi][safi] = 0;
    7516             : 
    7517             :         /* Check if handling a regular peer. */
    7518           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    7519             :                 /* Skip peer-group mechanics for regular peers. */
    7520           0 :                 peer_maximum_prefix_out_refresh_routes(peer, afi, safi);
    7521           0 :                 return 0;
    7522             :         }
    7523             : 
    7524             :         /*
    7525             :          * Remove flag and configuration from all peer-group members, unless
    7526             :          * they are explicitly overriding peer-group configuration.
    7527             :          */
    7528           0 :         for (ALL_LIST_ELEMENTS_RO(peer->group->peer, node, member)) {
    7529             :                 /* Skip peers with overridden configuration. */
    7530           0 :                 if (CHECK_FLAG(member->af_flags_override[afi][safi],
    7531             :                                PEER_FLAG_MAX_PREFIX_OUT))
    7532           0 :                         continue;
    7533             : 
    7534             :                 /* Remove flag and configuration on peer-group member.
    7535             :                  */
    7536           0 :                 UNSET_FLAG(member->af_flags[afi][safi],
    7537             :                            PEER_FLAG_MAX_PREFIX_OUT);
    7538           0 :                 member->pmax_out[afi][safi] = 0;
    7539             : 
    7540           0 :                 peer_maximum_prefix_out_refresh_routes(member, afi, safi);
    7541             :         }
    7542             :         return 0;
    7543             : }
    7544             : 
    7545           0 : int is_ebgp_multihop_configured(struct peer *peer)
    7546             : {
    7547           0 :         struct peer_group *group;
    7548           0 :         struct listnode *node, *nnode;
    7549           0 :         struct peer *peer1;
    7550             : 
    7551           0 :         if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    7552           0 :                 group = peer->group;
    7553           0 :                 if ((peer_sort(peer) != BGP_PEER_IBGP)
    7554           0 :                     && (group->conf->ttl != BGP_DEFAULT_TTL))
    7555             :                         return 1;
    7556             : 
    7557           0 :                 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer1)) {
    7558           0 :                         if ((peer_sort(peer1) != BGP_PEER_IBGP)
    7559           0 :                             && (peer1->ttl != BGP_DEFAULT_TTL))
    7560             :                                 return 1;
    7561             :                 }
    7562             :         } else {
    7563           0 :                 if ((peer_sort(peer) != BGP_PEER_IBGP)
    7564           0 :                     && (peer->ttl != BGP_DEFAULT_TTL))
    7565             :                         return 1;
    7566             :         }
    7567             :         return 0;
    7568             : }
    7569             : 
    7570             : /* Set # of hops between us and BGP peer. */
    7571           0 : int peer_ttl_security_hops_set(struct peer *peer, int gtsm_hops)
    7572             : {
    7573           0 :         struct peer_group *group;
    7574           0 :         struct peer *gpeer;
    7575           0 :         struct listnode *node, *nnode;
    7576           0 :         int ret;
    7577             : 
    7578           0 :         zlog_debug("%s: set gtsm_hops to %d for %s", __func__, gtsm_hops,
    7579             :                    peer->host);
    7580             : 
    7581             :         /* We cannot configure ttl-security hops when ebgp-multihop is already
    7582             :            set.  For non peer-groups, the check is simple.  For peer-groups,
    7583             :            it's
    7584             :            slightly messy, because we need to check both the peer-group
    7585             :            structure
    7586             :            and all peer-group members for any trace of ebgp-multihop
    7587             :            configuration
    7588             :            before actually applying the ttl-security rules.  Cisco really made a
    7589             :            mess of this configuration parameter, and OpenBGPD got it right.
    7590             :         */
    7591             : 
    7592           0 :         if ((peer->gtsm_hops == BGP_GTSM_HOPS_DISABLED)
    7593           0 :             && (peer->sort != BGP_PEER_IBGP)) {
    7594           0 :                 if (is_ebgp_multihop_configured(peer))
    7595             :                         return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
    7596             : 
    7597           0 :                 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    7598           0 :                         peer->gtsm_hops = gtsm_hops;
    7599             : 
    7600             :                         /* Calling ebgp multihop also resets the session.
    7601             :                          * On restart, NHT will get setup correctly as will the
    7602             :                          * min & max ttls on the socket. The return value is
    7603             :                          * irrelevant.
    7604             :                          */
    7605           0 :                         ret = peer_ebgp_multihop_set(peer, MAXTTL);
    7606             : 
    7607           0 :                         if (ret != 0)
    7608             :                                 return ret;
    7609             :                 } else {
    7610           0 :                         group = peer->group;
    7611           0 :                         group->conf->gtsm_hops = gtsm_hops;
    7612           0 :                         for (ALL_LIST_ELEMENTS(group->peer, node, nnode,
    7613             :                                                gpeer)) {
    7614           0 :                                 gpeer->gtsm_hops = group->conf->gtsm_hops;
    7615             : 
    7616             :                                 /* Calling ebgp multihop also resets the
    7617             :                                  * session.
    7618             :                                  * On restart, NHT will get setup correctly as
    7619             :                                  * will the
    7620             :                                  * min & max ttls on the socket. The return
    7621             :                                  * value is
    7622             :                                  * irrelevant.
    7623             :                                  */
    7624           0 :                                 peer_ebgp_multihop_set(gpeer, MAXTTL);
    7625             :                         }
    7626             :                 }
    7627             :         } else {
    7628             :                 /* Post the first gtsm setup or if its ibgp, maxttl setting
    7629             :                  * isn't
    7630             :                  * necessary, just set the minttl.
    7631             :                  */
    7632           0 :                 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    7633           0 :                         peer->gtsm_hops = gtsm_hops;
    7634             : 
    7635           0 :                         if (peer->fd >= 0)
    7636           0 :                                 sockopt_minttl(peer->su.sa.sa_family, peer->fd,
    7637             :                                                MAXTTL + 1 - gtsm_hops);
    7638           0 :                         if ((peer->status < Established) && peer->doppelganger
    7639           0 :                             && (peer->doppelganger->fd >= 0))
    7640           0 :                                 sockopt_minttl(peer->su.sa.sa_family,
    7641             :                                                peer->doppelganger->fd,
    7642             :                                                MAXTTL + 1 - gtsm_hops);
    7643             :                 } else {
    7644           0 :                         group = peer->group;
    7645           0 :                         group->conf->gtsm_hops = gtsm_hops;
    7646           0 :                         for (ALL_LIST_ELEMENTS(group->peer, node, nnode,
    7647             :                                                gpeer)) {
    7648           0 :                                 gpeer->gtsm_hops = group->conf->gtsm_hops;
    7649             : 
    7650             :                                 /* Change setting of existing peer
    7651             :                                  *   established then change value (may break
    7652             :                                  * connectivity)
    7653             :                                  *   not established yet (teardown session and
    7654             :                                  * restart)
    7655             :                                  *   no session then do nothing (will get
    7656             :                                  * handled by next connection)
    7657             :                                  */
    7658           0 :                                 if (gpeer->fd >= 0
    7659           0 :                                     && gpeer->gtsm_hops
    7660             :                                                != BGP_GTSM_HOPS_DISABLED)
    7661           0 :                                         sockopt_minttl(
    7662           0 :                                                 gpeer->su.sa.sa_family,
    7663             :                                                 gpeer->fd,
    7664             :                                                 MAXTTL + 1 - gpeer->gtsm_hops);
    7665           0 :                                 if ((gpeer->status < Established)
    7666           0 :                                     && gpeer->doppelganger
    7667           0 :                                     && (gpeer->doppelganger->fd >= 0))
    7668           0 :                                         sockopt_minttl(gpeer->su.sa.sa_family,
    7669             :                                                        gpeer->doppelganger->fd,
    7670             :                                                        MAXTTL + 1 - gtsm_hops);
    7671             :                         }
    7672             :                 }
    7673             :         }
    7674             : 
    7675             :         return 0;
    7676             : }
    7677             : 
    7678           0 : int peer_ttl_security_hops_unset(struct peer *peer)
    7679             : {
    7680           0 :         struct peer_group *group;
    7681           0 :         struct listnode *node, *nnode;
    7682           0 :         int ret = 0;
    7683             : 
    7684           0 :         zlog_debug("%s: set gtsm_hops to zero for %s", __func__, peer->host);
    7685             : 
    7686             :         /* if a peer-group member, then reset to peer-group default rather than
    7687             :          * 0 */
    7688           0 :         if (peer_group_active(peer))
    7689           0 :                 peer->gtsm_hops = peer->group->conf->gtsm_hops;
    7690             :         else
    7691           0 :                 peer->gtsm_hops = BGP_GTSM_HOPS_DISABLED;
    7692             : 
    7693           0 :         if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
    7694             :                 /* Invoking ebgp_multihop_set will set the TTL back to the
    7695             :                  * original
    7696             :                  * value as well as restting the NHT and such. The session is
    7697             :                  * reset.
    7698             :                  */
    7699           0 :                 if (peer->sort == BGP_PEER_EBGP)
    7700           0 :                         ret = peer_ebgp_multihop_unset(peer);
    7701             :                 else {
    7702           0 :                         if (peer->fd >= 0)
    7703           0 :                                 sockopt_minttl(peer->su.sa.sa_family, peer->fd,
    7704             :                                                0);
    7705             : 
    7706           0 :                         if ((peer->status < Established) && peer->doppelganger
    7707           0 :                             && (peer->doppelganger->fd >= 0))
    7708           0 :                                 sockopt_minttl(peer->su.sa.sa_family,
    7709             :                                                peer->doppelganger->fd, 0);
    7710             :                 }
    7711             :         } else {
    7712           0 :                 group = peer->group;
    7713           0 :                 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
    7714           0 :                         peer->gtsm_hops = BGP_GTSM_HOPS_DISABLED;
    7715           0 :                         if (peer->sort == BGP_PEER_EBGP)
    7716           0 :                                 ret = peer_ebgp_multihop_unset(peer);
    7717             :                         else {
    7718           0 :                                 if (peer->fd >= 0)
    7719           0 :                                         sockopt_minttl(peer->su.sa.sa_family,
    7720             :                                                        peer->fd, 0);
    7721             : 
    7722           0 :                                 if ((peer->status < Established)
    7723           0 :                                     && peer->doppelganger
    7724           0 :                                     && (peer->doppelganger->fd >= 0))
    7725           0 :                                         sockopt_minttl(peer->su.sa.sa_family,
    7726             :                                                        peer->doppelganger->fd,
    7727             :                                                        0);
    7728             :                         }
    7729             :                 }
    7730             :         }
    7731             : 
    7732           0 :         return ret;
    7733             : }
    7734             : 
    7735           0 : static void peer_reset_message_stats(struct peer *peer)
    7736             : {
    7737           0 :         if (peer) {
    7738           0 :                 atomic_store_explicit(&peer->open_in, 0, memory_order_relaxed);
    7739           0 :                 atomic_store_explicit(&peer->open_out, 0, memory_order_relaxed);
    7740           0 :                 atomic_store_explicit(&peer->update_in, 0,
    7741             :                                       memory_order_relaxed);
    7742           0 :                 atomic_store_explicit(&peer->update_out, 0,
    7743             :                                       memory_order_relaxed);
    7744           0 :                 atomic_store_explicit(&peer->keepalive_in, 0,
    7745             :                                       memory_order_relaxed);
    7746           0 :                 atomic_store_explicit(&peer->keepalive_out, 0,
    7747             :                                       memory_order_relaxed);
    7748           0 :                 atomic_store_explicit(&peer->notify_in, 0,
    7749             :                                       memory_order_relaxed);
    7750           0 :                 atomic_store_explicit(&peer->notify_out, 0,
    7751             :                                       memory_order_relaxed);
    7752           0 :                 atomic_store_explicit(&peer->refresh_in, 0,
    7753             :                                       memory_order_relaxed);
    7754           0 :                 atomic_store_explicit(&peer->refresh_out, 0,
    7755             :                                       memory_order_relaxed);
    7756           0 :                 atomic_store_explicit(&peer->dynamic_cap_in, 0,
    7757             :                                       memory_order_relaxed);
    7758           0 :                 atomic_store_explicit(&peer->dynamic_cap_out, 0,
    7759             :                                       memory_order_relaxed);
    7760             :         }
    7761           0 : }
    7762             : 
    7763             : /*
    7764             :  * If peer clear is invoked in a loop for all peers on the BGP instance,
    7765             :  * it may end up freeing the doppelganger, and if this was the next node
    7766             :  * to the current node, we would end up accessing the freed next node.
    7767             :  * Pass along additional parameter which can be updated if next node
    7768             :  * is freed; only required when walking the peer list on BGP instance.
    7769             :  */
    7770           0 : int peer_clear(struct peer *peer, struct listnode **nnode)
    7771             : {
    7772           0 :         if (!CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)
    7773           0 :             || !CHECK_FLAG(peer->bgp->flags, BGP_FLAG_SHUTDOWN)) {
    7774           0 :                 if (peer_maximum_prefix_clear_overflow(peer))
    7775             :                         return 0;
    7776             : 
    7777           0 :                 peer->v_start = BGP_INIT_START_TIMER;
    7778           0 :                 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
    7779           0 :                         bgp_notify_send(peer, BGP_NOTIFY_CEASE,
    7780             :                                         BGP_NOTIFY_CEASE_ADMIN_RESET);
    7781             :                 else
    7782           0 :                         bgp_session_reset_safe(peer, nnode);
    7783             :         }
    7784             :         return 0;
    7785             : }
    7786             : 
    7787           0 : int peer_clear_soft(struct peer *peer, afi_t afi, safi_t safi,
    7788             :                     enum bgp_clear_type stype)
    7789             : {
    7790           0 :         struct peer_af *paf;
    7791             : 
    7792           0 :         if (!peer_established(peer))
    7793             :                 return 0;
    7794             : 
    7795           0 :         if (!peer->afc[afi][safi])
    7796             :                 return BGP_ERR_AF_UNCONFIGURED;
    7797             : 
    7798           0 :         peer->rtt = sockopt_tcp_rtt(peer->fd);
    7799             : 
    7800           0 :         if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH) {
    7801             :                 /* Clear the "neighbor x.x.x.x default-originate" flag */
    7802           0 :                 paf = peer_af_find(peer, afi, safi);
    7803           0 :                 if (paf && paf->subgroup
    7804           0 :                     && CHECK_FLAG(paf->subgroup->sflags,
    7805             :                                   SUBGRP_STATUS_DEFAULT_ORIGINATE))
    7806           0 :                         UNSET_FLAG(paf->subgroup->sflags,
    7807             :                                    SUBGRP_STATUS_DEFAULT_ORIGINATE);
    7808             : 
    7809           0 :                 bgp_announce_route(peer, afi, safi, false);
    7810             :         }
    7811             : 
    7812           0 :         if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX) {
    7813           0 :                 if (CHECK_FLAG(peer->af_cap[afi][safi],
    7814             :                                PEER_CAP_ORF_PREFIX_SM_ADV)
    7815           0 :                     && (CHECK_FLAG(peer->af_cap[afi][safi],
    7816             :                                    PEER_CAP_ORF_PREFIX_RM_RCV)
    7817           0 :                         || CHECK_FLAG(peer->af_cap[afi][safi],
    7818             :                                       PEER_CAP_ORF_PREFIX_RM_OLD_RCV))) {
    7819           0 :                         struct bgp_filter *filter = &peer->filter[afi][safi];
    7820           0 :                         uint8_t prefix_type;
    7821             : 
    7822           0 :                         if (CHECK_FLAG(peer->af_cap[afi][safi],
    7823             :                                        PEER_CAP_ORF_PREFIX_RM_RCV))
    7824             :                                 prefix_type = ORF_TYPE_PREFIX;
    7825             :                         else
    7826           0 :                                 prefix_type = ORF_TYPE_PREFIX_OLD;
    7827             : 
    7828           0 :                         if (filter->plist[FILTER_IN].plist) {
    7829           0 :                                 if (CHECK_FLAG(peer->af_sflags[afi][safi],
    7830             :                                                PEER_STATUS_ORF_PREFIX_SEND))
    7831           0 :                                         bgp_route_refresh_send(
    7832             :                                                 peer, afi, safi, prefix_type,
    7833             :                                                 REFRESH_DEFER, 1,
    7834             :                                                 BGP_ROUTE_REFRESH_NORMAL);
    7835           0 :                                 bgp_route_refresh_send(
    7836             :                                         peer, afi, safi, prefix_type,
    7837             :                                         REFRESH_IMMEDIATE, 0,
    7838             :                                         BGP_ROUTE_REFRESH_NORMAL);
    7839             :                         } else {
    7840           0 :                                 if (CHECK_FLAG(peer->af_sflags[afi][safi],
    7841             :                                                PEER_STATUS_ORF_PREFIX_SEND))
    7842           0 :                                         bgp_route_refresh_send(
    7843             :                                                 peer, afi, safi, prefix_type,
    7844             :                                                 REFRESH_IMMEDIATE, 1,
    7845             :                                                 BGP_ROUTE_REFRESH_NORMAL);
    7846             :                                 else
    7847           0 :                                         bgp_route_refresh_send(
    7848             :                                                 peer, afi, safi, 0, 0, 0,
    7849             :                                                 BGP_ROUTE_REFRESH_NORMAL);
    7850             :                         }
    7851           0 :                         return 0;
    7852             :                 }
    7853             :         }
    7854             : 
    7855           0 :         if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
    7856           0 :             || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX) {
    7857             :                 /* If neighbor has soft reconfiguration inbound flag.
    7858             :                    Use Adj-RIB-In database. */
    7859           0 :                 if (!bgp_soft_reconfig_in(peer, afi, safi)) {
    7860             :                         /* If neighbor has route refresh capability, send route
    7861             :                            refresh
    7862             :                            message to the peer. */
    7863           0 :                         if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV)
    7864           0 :                             || CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV))
    7865           0 :                                 bgp_route_refresh_send(
    7866             :                                         peer, afi, safi, 0, 0, 0,
    7867             :                                         BGP_ROUTE_REFRESH_NORMAL);
    7868             :                         else
    7869             :                                 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
    7870             :                 }
    7871             :         }
    7872             : 
    7873           0 :         if (stype == BGP_CLEAR_MESSAGE_STATS)
    7874           0 :                 peer_reset_message_stats(peer);
    7875             : 
    7876             :         return 0;
    7877             : }
    7878             : 
    7879             : /* Display peer uptime.*/
    7880           1 : char *peer_uptime(time_t uptime2, char *buf, size_t len, bool use_json,
    7881             :                   json_object *json)
    7882             : {
    7883           1 :         time_t uptime1, epoch_tbuf;
    7884           1 :         struct tm tm;
    7885             : 
    7886             :         /* If there is no connection has been done before print `never'. */
    7887           1 :         if (uptime2 == 0) {
    7888           0 :                 if (use_json) {
    7889           0 :                         json_object_string_add(json, "peerUptime", "never");
    7890           0 :                         json_object_int_add(json, "peerUptimeMsec", 0);
    7891             :                 } else
    7892           0 :                         snprintf(buf, len, "never");
    7893           0 :                 return buf;
    7894             :         }
    7895             : 
    7896             :         /* Get current time. */
    7897           1 :         uptime1 = monotime(NULL);
    7898           1 :         uptime1 -= uptime2;
    7899           1 :         gmtime_r(&uptime1, &tm);
    7900             : 
    7901           1 :         if (uptime1 < ONE_DAY_SECOND)
    7902           1 :                 snprintf(buf, len, "%02d:%02d:%02d", tm.tm_hour, tm.tm_min,
    7903             :                          tm.tm_sec);
    7904           0 :         else if (uptime1 < ONE_WEEK_SECOND)
    7905           0 :                 snprintf(buf, len, "%dd%02dh%02dm", tm.tm_yday, tm.tm_hour,
    7906             :                          tm.tm_min);
    7907           0 :         else if (uptime1 < ONE_YEAR_SECOND)
    7908           0 :                 snprintf(buf, len, "%02dw%dd%02dh", tm.tm_yday / 7,
    7909           0 :                          tm.tm_yday - ((tm.tm_yday / 7) * 7), tm.tm_hour);
    7910             :         else
    7911           0 :                 snprintf(buf, len, "%02dy%02dw%dd", tm.tm_year - 70,
    7912             :                          tm.tm_yday / 7,
    7913           0 :                          tm.tm_yday - ((tm.tm_yday / 7) * 7));
    7914             : 
    7915           1 :         if (use_json) {
    7916           0 :                 epoch_tbuf = time(NULL) - uptime1;
    7917           0 :                 json_object_string_add(json, "peerUptime", buf);
    7918           0 :                 json_object_int_add(json, "peerUptimeMsec", uptime1 * 1000);
    7919           0 :                 json_object_int_add(json, "peerUptimeEstablishedEpoch",
    7920             :                                     epoch_tbuf);
    7921             :         }
    7922             : 
    7923             :         return buf;
    7924             : }
    7925             : 
    7926           3 : void bgp_master_init(struct thread_master *master, const int buffer_size,
    7927             :                      struct list *addresses)
    7928             : {
    7929           3 :         qobj_init();
    7930             : 
    7931           3 :         memset(&bgp_master, 0, sizeof(bgp_master));
    7932             : 
    7933           3 :         bm = &bgp_master;
    7934           3 :         bm->bgp = list_new();
    7935           3 :         bm->listen_sockets = list_new();
    7936           3 :         bm->port = BGP_PORT_DEFAULT;
    7937           3 :         bm->addresses = addresses;
    7938           3 :         bm->master = master;
    7939           3 :         bm->start_time = monotime(NULL);
    7940           3 :         bm->t_rmap_update = NULL;
    7941           3 :         bm->rmap_update_timer = RMAP_DEFAULT_UPDATE_TIMER;
    7942           3 :         bm->v_update_delay = BGP_UPDATE_DELAY_DEF;
    7943           3 :         bm->v_establish_wait = BGP_UPDATE_DELAY_DEF;
    7944           3 :         bm->terminating = false;
    7945           3 :         bm->socket_buffer = buffer_size;
    7946           3 :         bm->wait_for_fib = false;
    7947           3 :         bm->tcp_dscp = IPTOS_PREC_INTERNETCONTROL;
    7948           3 :         bm->inq_limit = BM_DEFAULT_Q_LIMIT;
    7949           3 :         bm->outq_limit = BM_DEFAULT_Q_LIMIT;
    7950             : 
    7951           3 :         bgp_mac_init();
    7952             :         /* init the rd id space.
    7953             :            assign 0th index in the bitfield,
    7954             :            so that we start with id 1
    7955             :          */
    7956           3 :         bf_init(bm->rd_idspace, UINT16_MAX);
    7957          15 :         bf_assign_zero_index(bm->rd_idspace);
    7958             : 
    7959             :         /* mpls label dynamic allocation pool */
    7960           3 :         bgp_lp_init(bm->master, &bm->labelpool);
    7961             : 
    7962           3 :         bgp_l3nhg_init();
    7963           3 :         bgp_evpn_mh_init();
    7964           3 :         QOBJ_REG(bm, bgp_master);
    7965           3 : }
    7966             : 
    7967             : /*
    7968             :  * Free up connected routes and interfaces for a BGP instance. Invoked upon
    7969             :  * instance delete (non-default only) or BGP exit.
    7970             :  */
    7971           3 : static void bgp_if_finish(struct bgp *bgp)
    7972             : {
    7973           3 :         struct vrf *vrf;
    7974           3 :         struct interface *ifp;
    7975             : 
    7976           3 :         vrf = bgp_vrf_lookup_by_instance_type(bgp);
    7977             : 
    7978           3 :         if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW || !vrf)
    7979             :                 return;
    7980             : 
    7981          12 :         FOR_ALL_INTERFACES (vrf, ifp) {
    7982           6 :                 struct listnode *c_node, *c_nnode;
    7983           6 :                 struct connected *c;
    7984             : 
    7985          27 :                 for (ALL_LIST_ELEMENTS(ifp->connected, c_node, c_nnode, c))
    7986          15 :                         bgp_connected_delete(bgp, c);
    7987             :         }
    7988             : }
    7989             : 
    7990           0 : static void bgp_viewvrf_autocomplete(vector comps, struct cmd_token *token)
    7991             : {
    7992           0 :         struct vrf *vrf = NULL;
    7993           0 :         struct listnode *next;
    7994           0 :         struct bgp *bgp;
    7995             : 
    7996           0 :         RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
    7997           0 :                 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, vrf->name));
    7998             : 
    7999           0 :         for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) {
    8000           0 :                 if (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
    8001           0 :                         continue;
    8002             : 
    8003           0 :                 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, bgp->name));
    8004             :         }
    8005           0 : }
    8006             : 
    8007           0 : static void bgp_instasn_autocomplete(vector comps, struct cmd_token *token)
    8008             : {
    8009           0 :         struct listnode *next, *next2;
    8010           0 :         struct bgp *bgp, *bgp2;
    8011           0 :         char buf[11];
    8012             : 
    8013           0 :         for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) {
    8014             :                 /* deduplicate */
    8015           0 :                 for (ALL_LIST_ELEMENTS_RO(bm->bgp, next2, bgp2)) {
    8016           0 :                         if (bgp2->as == bgp->as)
    8017             :                                 break;
    8018           0 :                         if (bgp2 == bgp)
    8019             :                                 break;
    8020             :                 }
    8021           0 :                 if (bgp2 != bgp)
    8022           0 :                         continue;
    8023             : 
    8024           0 :                 snprintf(buf, sizeof(buf), "%u", bgp->as);
    8025           0 :                 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, buf));
    8026             :         }
    8027           0 : }
    8028             : 
    8029             : static const struct cmd_variable_handler bgp_viewvrf_var_handlers[] = {
    8030             :         {.tokenname = "VIEWVRFNAME", .completions = bgp_viewvrf_autocomplete},
    8031             :         {.varname = "instasn", .completions = bgp_instasn_autocomplete},
    8032             :         {.completions = NULL},
    8033             : };
    8034             : 
    8035             : struct frr_pthread *bgp_pth_io;
    8036             : struct frr_pthread *bgp_pth_ka;
    8037             : 
    8038           3 : static void bgp_pthreads_init(void)
    8039             : {
    8040           3 :         assert(!bgp_pth_io);
    8041           3 :         assert(!bgp_pth_ka);
    8042             : 
    8043           3 :         struct frr_pthread_attr io = {
    8044           3 :                 .start = frr_pthread_attr_default.start,
    8045           3 :                 .stop = frr_pthread_attr_default.stop,
    8046             :         };
    8047           3 :         struct frr_pthread_attr ka = {
    8048             :                 .start = bgp_keepalives_start,
    8049             :                 .stop = bgp_keepalives_stop,
    8050             :         };
    8051           3 :         bgp_pth_io = frr_pthread_new(&io, "BGP I/O thread", "bgpd_io");
    8052           3 :         bgp_pth_ka = frr_pthread_new(&ka, "BGP Keepalives thread", "bgpd_ka");
    8053           3 : }
    8054             : 
    8055           3 : void bgp_pthreads_run(void)
    8056             : {
    8057           3 :         frr_pthread_run(bgp_pth_io, NULL);
    8058           3 :         frr_pthread_run(bgp_pth_ka, NULL);
    8059             : 
    8060             :         /* Wait until threads are ready. */
    8061           3 :         frr_pthread_wait_running(bgp_pth_io);
    8062           3 :         frr_pthread_wait_running(bgp_pth_ka);
    8063           3 : }
    8064             : 
    8065           3 : void bgp_pthreads_finish(void)
    8066             : {
    8067           3 :         frr_pthread_stop_all();
    8068           3 : }
    8069             : 
    8070           0 : static int peer_unshut_after_cfg(struct bgp *bgp)
    8071             : {
    8072           0 :         struct listnode *node;
    8073           0 :         struct peer *peer;
    8074             : 
    8075           0 :         for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
    8076           0 :                 if (!peer->shut_during_cfg)
    8077           0 :                         continue;
    8078             : 
    8079           0 :                 if (bgp_debug_neighbor_events(peer))
    8080           0 :                         zlog_debug("%s: released from config-pending hold",
    8081             :                                    peer->host);
    8082             : 
    8083           0 :                 peer->shut_during_cfg = false;
    8084           0 :                 if (peer_active(peer) && peer->status != Established) {
    8085           0 :                         if (peer->status != Idle)
    8086           0 :                                 BGP_EVENT_ADD(peer, BGP_Stop);
    8087           0 :                         BGP_EVENT_ADD(peer, BGP_Start);
    8088             :                 }
    8089             :         }
    8090             : 
    8091           0 :         return 0;
    8092             : }
    8093             : 
    8094           3 : void bgp_init(unsigned short instance)
    8095             : {
    8096           3 :         hook_register(bgp_config_end, peer_unshut_after_cfg);
    8097             : 
    8098             :         /* allocates some vital data structures used by peer commands in
    8099             :          * vty_init */
    8100             : 
    8101             :         /* pre-init pthreads */
    8102           3 :         bgp_pthreads_init();
    8103             : 
    8104             :         /* Init zebra. */
    8105           3 :         bgp_zebra_init(bm->master, instance);
    8106             : 
    8107             : #ifdef ENABLE_BGP_VNC
    8108           3 :         vnc_zebra_init(bm->master);
    8109             : #endif
    8110             : 
    8111             :         /* BGP VTY commands installation.  */
    8112           3 :         bgp_vty_init();
    8113             : 
    8114             :         /* BGP inits. */
    8115           3 :         bgp_attr_init();
    8116           3 :         bgp_debug_init();
    8117           3 :         bgp_community_alias_init();
    8118           3 :         bgp_dump_init();
    8119           3 :         bgp_route_init();
    8120           3 :         bgp_route_map_init();
    8121           3 :         bgp_scan_vty_init();
    8122           3 :         bgp_mplsvpn_init();
    8123             : #ifdef ENABLE_BGP_VNC
    8124           3 :         rfapi_init();
    8125             : #endif
    8126           3 :         bgp_ethernetvpn_init();
    8127           3 :         bgp_flowspec_vty_init();
    8128             : 
    8129             :         /* Access list initialize. */
    8130           3 :         access_list_init();
    8131           3 :         access_list_add_hook(peer_distribute_update);
    8132           3 :         access_list_delete_hook(peer_distribute_update);
    8133             : 
    8134             :         /* Filter list initialize. */
    8135           3 :         bgp_filter_init();
    8136           3 :         as_list_add_hook(peer_aslist_add);
    8137           3 :         as_list_delete_hook(peer_aslist_del);
    8138             : 
    8139             :         /* Prefix list initialize.*/
    8140           3 :         prefix_list_init();
    8141           3 :         prefix_list_add_hook(peer_prefix_list_update);
    8142           3 :         prefix_list_delete_hook(peer_prefix_list_update);
    8143             : 
    8144             :         /* Community list initialize. */
    8145           3 :         bgp_clist = community_list_init();
    8146             : 
    8147             :         /* BFD init */
    8148           3 :         bgp_bfd_init(bm->master);
    8149             : 
    8150           3 :         bgp_lp_vty_init();
    8151             : 
    8152           3 :         cmd_variable_handler_register(bgp_viewvrf_var_handlers);
    8153           3 : }
    8154             : 
    8155           3 : void bgp_terminate(void)
    8156             : {
    8157           3 :         struct bgp *bgp;
    8158           3 :         struct peer *peer;
    8159           3 :         struct listnode *node, *nnode;
    8160           3 :         struct listnode *mnode, *mnnode;
    8161             : 
    8162           3 :         QOBJ_UNREG(bm);
    8163             : 
    8164             :         /* Close the listener sockets first as this prevents peers from
    8165             :          * attempting
    8166             :          * to reconnect on receiving the peer unconfig message. In the presence
    8167             :          * of a large number of peers this will ensure that no peer is left with
    8168             :          * a dangling connection
    8169             :          */
    8170             : 
    8171           3 :         bgp_close();
    8172             :         /* reverse bgp_master_init */
    8173           9 :         for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
    8174           3 :                 bgp_close_vrf_socket(bgp);
    8175          10 :                 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
    8176           4 :                         if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)) {
    8177           1 :                                 if (bgp_debug_neighbor_events(peer))
    8178           0 :                                         zlog_debug(
    8179             :                                                 "%pBP configured Graceful-Restart, skipping unconfig notification",
    8180             :                                                 peer);
    8181           1 :                                 continue;
    8182             :                         }
    8183           3 :                         if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
    8184           0 :                                 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
    8185             :                                                 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
    8186             :                 }
    8187             :         }
    8188             : 
    8189           3 :         if (bm->listen_sockets)
    8190           3 :                 list_delete(&bm->listen_sockets);
    8191             : 
    8192           3 :         THREAD_OFF(bm->t_rmap_update);
    8193             : 
    8194           3 :         bgp_mac_finish();
    8195           3 : }
    8196             : 
    8197           0 : struct peer *peer_lookup_in_view(struct vty *vty, struct bgp *bgp,
    8198             :                                  const char *ip_str, bool use_json)
    8199             : {
    8200           0 :         int ret;
    8201           0 :         struct peer *peer;
    8202           0 :         union sockunion su;
    8203             : 
    8204             :         /* Get peer sockunion. */
    8205           0 :         ret = str2sockunion(ip_str, &su);
    8206           0 :         if (ret < 0) {
    8207           0 :                 peer = peer_lookup_by_conf_if(bgp, ip_str);
    8208           0 :                 if (!peer) {
    8209           0 :                         peer = peer_lookup_by_hostname(bgp, ip_str);
    8210             : 
    8211           0 :                         if (!peer) {
    8212           0 :                                 if (use_json) {
    8213           0 :                                         json_object *json_no = NULL;
    8214           0 :                                         json_no = json_object_new_object();
    8215           0 :                                         json_object_string_add(
    8216             :                                                 json_no,
    8217             :                                                 "malformedAddressOrName",
    8218             :                                                 ip_str);
    8219           0 :                                         vty_json(vty, json_no);
    8220             :                                 } else
    8221           0 :                                         vty_out(vty,
    8222             :                                                 "%% Malformed address or name: %s\n",
    8223             :                                                 ip_str);
    8224           0 :                                 return NULL;
    8225             :                         }
    8226             :                 }
    8227           0 :                 return peer;
    8228             :         }
    8229             : 
    8230             :         /* Peer structure lookup. */
    8231           0 :         peer = peer_lookup(bgp, &su);
    8232           0 :         if (!peer) {
    8233           0 :                 if (use_json) {
    8234           0 :                         json_object *json_no = NULL;
    8235           0 :                         json_no = json_object_new_object();
    8236           0 :                         json_object_string_add(json_no, "warning",
    8237             :                                                "No such neighbor in this view/vrf");
    8238           0 :                         vty_json(vty, json_no);
    8239             :                 } else
    8240           0 :                         vty_out(vty, "No such neighbor in this view/vrf\n");
    8241           0 :                 return NULL;
    8242             :         }
    8243             : 
    8244             :         return peer;
    8245             : }
    8246             : 
    8247           3 : void bgp_gr_apply_running_config(void)
    8248             : {
    8249           3 :         struct peer *peer = NULL;
    8250           3 :         struct bgp *bgp = NULL;
    8251           3 :         struct listnode *node, *nnode;
    8252           3 :         bool gr_router_detected = false;
    8253             : 
    8254           3 :         if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
    8255           0 :                 zlog_debug("[BGP_GR] %s called !", __func__);
    8256             : 
    8257           6 :         for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
    8258           0 :                 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
    8259           0 :                         bgp_peer_gr_flags_update(peer);
    8260           0 :                         if (CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART))
    8261           0 :                                 gr_router_detected = true;
    8262             :                 }
    8263             : 
    8264           0 :                 if (gr_router_detected
    8265           0 :                     && bgp->present_zebra_gr_state == ZEBRA_GR_DISABLE) {
    8266           0 :                         bgp_zebra_send_capabilities(bgp, true);
    8267           0 :                 } else if (!gr_router_detected
    8268           0 :                            && bgp->present_zebra_gr_state == ZEBRA_GR_ENABLE) {
    8269           0 :                         bgp_zebra_send_capabilities(bgp, false);
    8270             :                 }
    8271             : 
    8272             :                 gr_router_detected = false;
    8273             :         }
    8274           3 : }
    8275             : 
    8276           3 : printfrr_ext_autoreg_p("BP", printfrr_bp);
    8277           0 : static ssize_t printfrr_bp(struct fbuf *buf, struct printfrr_eargs *ea,
    8278             :                            const void *ptr)
    8279             : {
    8280           0 :         const struct peer *peer = ptr;
    8281             : 
    8282           0 :         if (!peer)
    8283           0 :                 return bputs(buf, "(null)");
    8284             : 
    8285           0 :         return bprintfrr(buf, "%s(%s)", peer->host,
    8286           0 :                          peer->hostname ? peer->hostname : "Unknown");
    8287             : }

Generated by: LCOV version v1.16-topotato