back to topotato report
topotato coverage report
Current view: top level - bgpd - bgpd.c (source / functions) Hit Total Coverage
Test: test_bgp_ecmp_enhe.py::BGP_Unnumbered_ECMP Lines: 977 4035 24.2 %
Date: 2023-11-16 17:19:14 Functions: 68 425 16.0 %

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

Generated by: LCOV version v1.16-topotato