LCOV - code coverage report
Current view: top level - bgpd - bgpd.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 149 2646 5.6 %
Date: 2015-11-19 Functions: 18 131 13.7 %

          Line data    Source code
       1             : /* BGP-4, BGP-4+ daemon program
       2             :    Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
       3             : 
       4             : This file is part of GNU Zebra.
       5             : 
       6             : GNU Zebra is free software; you can redistribute it and/or modify it
       7             : under the terms of the GNU General Public License as published by the
       8             : Free Software Foundation; either version 2, or (at your option) any
       9             : later version.
      10             : 
      11             : GNU Zebra is distributed in the hope that it will be useful, but
      12             : WITHOUT ANY WARRANTY; without even the implied warranty of
      13             : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             : General Public License for more details.
      15             : 
      16             : You should have received a copy of the GNU General Public License
      17             : along with GNU Zebra; see the file COPYING.  If not, write to the Free
      18             : Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
      19             : 02111-1307, USA.  */
      20             : 
      21             : #include <zebra.h>
      22             : 
      23             : #include "prefix.h"
      24             : #include "thread.h"
      25             : #include "buffer.h"
      26             : #include "stream.h"
      27             : #include "command.h"
      28             : #include "sockunion.h"
      29             : #include "network.h"
      30             : #include "memory.h"
      31             : #include "filter.h"
      32             : #include "routemap.h"
      33             : #include "str.h"
      34             : #include "log.h"
      35             : #include "plist.h"
      36             : #include "linklist.h"
      37             : #include "workqueue.h"
      38             : 
      39             : #include "bgpd/bgpd.h"
      40             : #include "bgpd/bgp_table.h"
      41             : #include "bgpd/bgp_aspath.h"
      42             : #include "bgpd/bgp_route.h"
      43             : #include "bgpd/bgp_dump.h"
      44             : #include "bgpd/bgp_debug.h"
      45             : #include "bgpd/bgp_community.h"
      46             : #include "bgpd/bgp_attr.h"
      47             : #include "bgpd/bgp_regex.h"
      48             : #include "bgpd/bgp_clist.h"
      49             : #include "bgpd/bgp_fsm.h"
      50             : #include "bgpd/bgp_packet.h"
      51             : #include "bgpd/bgp_zebra.h"
      52             : #include "bgpd/bgp_open.h"
      53             : #include "bgpd/bgp_filter.h"
      54             : #include "bgpd/bgp_nexthop.h"
      55             : #include "bgpd/bgp_damp.h"
      56             : #include "bgpd/bgp_mplsvpn.h"
      57             : #include "bgpd/bgp_advertise.h"
      58             : #include "bgpd/bgp_network.h"
      59             : #include "bgpd/bgp_vty.h"
      60             : #include "bgpd/bgp_mpath.h"
      61             : #ifdef HAVE_SNMP
      62             : #include "bgpd/bgp_snmp.h"
      63             : #endif /* HAVE_SNMP */
      64             : 
      65             : /* BGP process wide configuration.  */
      66             : static struct bgp_master bgp_master;
      67             : 
      68             : extern struct in_addr router_id_zebra;
      69             : 
      70             : /* BGP process wide configuration pointer to export.  */
      71             : struct bgp_master *bm;
      72             : 
      73             : /* BGP community-list.  */
      74             : struct community_list_handler *bgp_clist;
      75             : 
      76             : /* BGP global flag manipulation.  */
      77             : int
      78           4 : bgp_option_set (int flag)
      79             : {
      80           4 :   switch (flag)
      81             :     {
      82             :     case BGP_OPT_NO_FIB:
      83             :     case BGP_OPT_MULTIPLE_INSTANCE:
      84             :     case BGP_OPT_CONFIG_CISCO:
      85             :     case BGP_OPT_NO_LISTEN:
      86           4 :       SET_FLAG (bm->options, flag);
      87           4 :       break;
      88             :     default:
      89           0 :       return BGP_ERR_INVALID_FLAG;
      90             :     }
      91           4 :   return 0;
      92             : }
      93             : 
      94             : int
      95           0 : bgp_option_unset (int flag)
      96             : {
      97           0 :   switch (flag)
      98             :     {
      99             :     case BGP_OPT_MULTIPLE_INSTANCE:
     100           0 :       if (listcount (bm->bgp) > 1)
     101           0 :         return BGP_ERR_MULTIPLE_INSTANCE_USED;
     102             :       /* Fall through.  */
     103             :     case BGP_OPT_NO_FIB:
     104             :     case BGP_OPT_CONFIG_CISCO:
     105           0 :       UNSET_FLAG (bm->options, flag);
     106           0 :       break;
     107             :     default:
     108           0 :       return BGP_ERR_INVALID_FLAG;
     109             :     }
     110           0 :   return 0;
     111             : }
     112             : 
     113             : int
     114          36 : bgp_option_check (int flag)
     115             : {
     116          36 :   return CHECK_FLAG (bm->options, flag);
     117             : }
     118             : 
     119             : /* BGP flag manipulation.  */
     120             : int
     121           0 : bgp_flag_set (struct bgp *bgp, int flag)
     122             : {
     123           0 :   SET_FLAG (bgp->flags, flag);
     124           0 :   return 0;
     125             : }
     126             : 
     127             : int
     128           0 : bgp_flag_unset (struct bgp *bgp, int flag)
     129             : {
     130           0 :   UNSET_FLAG (bgp->flags, flag);
     131           0 :   return 0;
     132             : }
     133             : 
     134             : int
     135          37 : bgp_flag_check (struct bgp *bgp, int flag)
     136             : {
     137          37 :   return CHECK_FLAG (bgp->flags, flag);
     138             : }
     139             : 
     140             : /* Internal function to set BGP structure configureation flag.  */
     141             : static void
     142           2 : bgp_config_set (struct bgp *bgp, int config)
     143             : {
     144           2 :   SET_FLAG (bgp->config, config);
     145           2 : }
     146             : 
     147             : static void
     148           0 : bgp_config_unset (struct bgp *bgp, int config)
     149             : {
     150           0 :   UNSET_FLAG (bgp->config, config);
     151           0 : }
     152             : 
     153             : static int
     154           2 : bgp_config_check (struct bgp *bgp, int config)
     155             : {
     156           2 :   return CHECK_FLAG (bgp->config, config);
     157             : }
     158             : 
     159             : /* Set BGP router identifier. */
     160             : int
     161           2 : bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
     162             : {
     163             :   struct peer *peer;
     164             :   struct listnode *node, *nnode;
     165             : 
     166           2 :   if (bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID)
     167           0 :       && IPV4_ADDR_SAME (&bgp->router_id, id))
     168           0 :     return 0;
     169             : 
     170           2 :   IPV4_ADDR_COPY (&bgp->router_id, id);
     171           2 :   bgp_config_set (bgp, BGP_CONFIG_ROUTER_ID);
     172             : 
     173             :   /* Set all peer's local identifier with this value. */
     174           2 :   for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
     175             :     {
     176           0 :       IPV4_ADDR_COPY (&peer->local_id, id);
     177             : 
     178           0 :       if (peer->status == Established)
     179             :        {
     180           0 :          peer->last_reset = PEER_DOWN_RID_CHANGE;
     181           0 :          bgp_notify_send (peer, BGP_NOTIFY_CEASE,
     182             :                           BGP_NOTIFY_CEASE_CONFIG_CHANGE);
     183             :        }
     184             :     }
     185           2 :   return 0;
     186             : }
     187             : 
     188             : /* BGP's cluster-id control. */
     189             : int
     190           0 : bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
     191             : {
     192             :   struct peer *peer;
     193             :   struct listnode *node, *nnode;
     194             : 
     195           0 :   if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)
     196           0 :       && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id))
     197           0 :     return 0;
     198             : 
     199           0 :   IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id);
     200           0 :   bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID);
     201             : 
     202             :   /* Clear all IBGP peer. */
     203           0 :   for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
     204             :     {
     205           0 :       if (peer->sort != BGP_PEER_IBGP)
     206           0 :         continue;
     207             : 
     208           0 :       if (peer->status == Established)
     209             :        {
     210           0 :          peer->last_reset = PEER_DOWN_CLID_CHANGE;
     211           0 :          bgp_notify_send (peer, BGP_NOTIFY_CEASE,
     212             :                           BGP_NOTIFY_CEASE_CONFIG_CHANGE);
     213             :        }
     214             :     }
     215           0 :   return 0;
     216             : }
     217             : 
     218             : int
     219           0 : bgp_cluster_id_unset (struct bgp *bgp)
     220             : {
     221             :   struct peer *peer;
     222             :   struct listnode *node, *nnode;
     223             : 
     224           0 :   if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID))
     225           0 :     return 0;
     226             : 
     227           0 :   bgp->cluster_id.s_addr = 0;
     228           0 :   bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID);
     229             : 
     230             :   /* Clear all IBGP peer. */
     231           0 :   for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
     232             :     {
     233           0 :       if (peer->sort != BGP_PEER_IBGP)
     234           0 :         continue;
     235             : 
     236           0 :       if (peer->status == Established)
     237             :        {
     238           0 :          peer->last_reset = PEER_DOWN_CLID_CHANGE;
     239           0 :          bgp_notify_send (peer, BGP_NOTIFY_CEASE,
     240             :                           BGP_NOTIFY_CEASE_CONFIG_CHANGE);
     241             :        }
     242             :     }
     243           0 :   return 0;
     244             : }
     245             : 
     246             : /* time_t value that is monotonicly increasing
     247             :  * and uneffected by adjustments to system clock
     248             :  */
     249           4 : time_t bgp_clock (void)
     250             : {
     251             :   struct timeval tv;
     252             : 
     253           4 :   quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv);
     254           4 :   return tv.tv_sec;
     255             : }
     256             : 
     257             : /* BGP timer configuration.  */
     258             : int
     259           0 : bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
     260             : {
     261           0 :   bgp->default_keepalive = (keepalive < holdtime / 3 
     262           0 :                             ? keepalive : holdtime / 3);
     263           0 :   bgp->default_holdtime = holdtime;
     264             : 
     265           0 :   return 0;
     266             : }
     267             : 
     268             : int
     269           0 : bgp_timers_unset (struct bgp *bgp)
     270             : {
     271           0 :   bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
     272           0 :   bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
     273             : 
     274           0 :   return 0;
     275             : }
     276             : 
     277             : /* BGP confederation configuration.  */
     278             : int
     279           0 : bgp_confederation_id_set (struct bgp *bgp, as_t as)
     280             : {
     281             :   struct peer *peer;
     282             :   struct listnode *node, *nnode;
     283             :   int already_confed;
     284             : 
     285           0 :   if (as == 0)
     286           0 :     return BGP_ERR_INVALID_AS;
     287             : 
     288             :   /* Remember - were we doing confederation before? */
     289           0 :   already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);
     290           0 :   bgp->confed_id = as;
     291           0 :   bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);
     292             : 
     293             :   /* If we were doing confederation already, this is just an external
     294             :      AS change.  Just Reset EBGP sessions, not CONFED sessions.  If we
     295             :      were not doing confederation before, reset all EBGP sessions.  */
     296           0 :   for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
     297             :     {
     298             :       /* We're looking for peers who's AS is not local or part of our
     299             :          confederation.  */
     300           0 :       if (already_confed)
     301             :         {
     302           0 :           if (peer_sort (peer) == BGP_PEER_EBGP)
     303             :             {
     304           0 :               peer->local_as = as;
     305           0 :               if (peer->status == Established)
     306             :                {
     307           0 :                  peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
     308           0 :                  bgp_notify_send (peer, BGP_NOTIFY_CEASE,
     309             :                               BGP_NOTIFY_CEASE_CONFIG_CHANGE);
     310             :                }
     311             : 
     312             :               else
     313           0 :                 BGP_EVENT_ADD (peer, BGP_Stop);
     314             :             }
     315             :         }
     316             :       else
     317             :         {
     318             :           /* Not doign confederation before, so reset every non-local
     319             :              session */
     320           0 :           if (peer_sort (peer) != BGP_PEER_IBGP)
     321             :             {
     322             :               /* Reset the local_as to be our EBGP one */
     323           0 :               if (peer_sort (peer) == BGP_PEER_EBGP)
     324           0 :                 peer->local_as = as;
     325           0 :               if (peer->status == Established)
     326             :                {
     327           0 :                  peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
     328           0 :                  bgp_notify_send (peer, BGP_NOTIFY_CEASE,
     329             :                               BGP_NOTIFY_CEASE_CONFIG_CHANGE);
     330             :                }
     331             :               else
     332           0 :                 BGP_EVENT_ADD (peer, BGP_Stop);
     333             :             }
     334             :         }
     335             :     }
     336           0 :   return 0;
     337             : }
     338             : 
     339             : int
     340           0 : bgp_confederation_id_unset (struct bgp *bgp)
     341             : {
     342             :   struct peer *peer;
     343             :   struct listnode *node, *nnode;
     344             : 
     345           0 :   bgp->confed_id = 0;
     346           0 :   bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
     347             :       
     348           0 :   for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
     349             :     {
     350             :       /* We're looking for peers who's AS is not local */
     351           0 :       if (peer_sort (peer) != BGP_PEER_IBGP)
     352             :         {
     353           0 :           peer->local_as = bgp->as;
     354           0 :           if (peer->status == Established)
     355             :            {
     356           0 :              peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
     357           0 :              bgp_notify_send (peer, BGP_NOTIFY_CEASE,
     358             :                               BGP_NOTIFY_CEASE_CONFIG_CHANGE);
     359             :            }
     360             : 
     361             :           else
     362           0 :             BGP_EVENT_ADD (peer, BGP_Stop);
     363             :         }
     364             :     }
     365           0 :   return 0;
     366             : }
     367             : 
     368             : /* Is an AS part of the confed or not? */
     369             : int
     370           0 : bgp_confederation_peers_check (struct bgp *bgp, as_t as)
     371             : {
     372             :   int i;
     373             : 
     374           0 :   if (! bgp)
     375           0 :     return 0;
     376             : 
     377           0 :   for (i = 0; i < bgp->confed_peers_cnt; i++)
     378           0 :     if (bgp->confed_peers[i] == as)
     379           0 :       return 1;
     380             :   
     381           0 :   return 0;
     382             : }
     383             : 
     384             : /* Add an AS to the confederation set.  */
     385             : int
     386           0 : bgp_confederation_peers_add (struct bgp *bgp, as_t as)
     387             : {
     388             :   struct peer *peer;
     389             :   struct listnode *node, *nnode;
     390             : 
     391           0 :   if (! bgp)
     392           0 :     return BGP_ERR_INVALID_BGP;
     393             : 
     394           0 :   if (bgp->as == as)
     395           0 :     return BGP_ERR_INVALID_AS;
     396             : 
     397           0 :   if (bgp_confederation_peers_check (bgp, as))
     398           0 :     return -1;
     399             : 
     400           0 :   if (bgp->confed_peers)
     401           0 :     bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST, 
     402             :                                   bgp->confed_peers,
     403             :                                   (bgp->confed_peers_cnt + 1) * sizeof (as_t));
     404             :   else
     405           0 :     bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST, 
     406             :                                  (bgp->confed_peers_cnt + 1) * sizeof (as_t));
     407             : 
     408           0 :   bgp->confed_peers[bgp->confed_peers_cnt] = as;
     409           0 :   bgp->confed_peers_cnt++;
     410             : 
     411           0 :   if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
     412             :     {
     413           0 :       for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
     414             :         {
     415           0 :           if (peer->as == as)
     416             :             {
     417           0 :               peer->local_as = bgp->as;
     418           0 :               if (peer->status == Established)
     419             :                {
     420           0 :                  peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
     421           0 :                  bgp_notify_send (peer, BGP_NOTIFY_CEASE,
     422             :                                   BGP_NOTIFY_CEASE_CONFIG_CHANGE);
     423             :                }
     424             :               else
     425           0 :                 BGP_EVENT_ADD (peer, BGP_Stop);
     426             :             }
     427             :         }
     428             :     }
     429           0 :   return 0;
     430             : }
     431             : 
     432             : /* Delete an AS from the confederation set.  */
     433             : int
     434           0 : bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
     435             : {
     436             :   int i;
     437             :   int j;
     438             :   struct peer *peer;
     439             :   struct listnode *node, *nnode;
     440             : 
     441           0 :   if (! bgp)
     442           0 :     return -1;
     443             : 
     444           0 :   if (! bgp_confederation_peers_check (bgp, as))
     445           0 :     return -1;
     446             : 
     447           0 :   for (i = 0; i < bgp->confed_peers_cnt; i++)
     448           0 :     if (bgp->confed_peers[i] == as)
     449           0 :       for(j = i + 1; j < bgp->confed_peers_cnt; j++)
     450           0 :         bgp->confed_peers[j - 1] = bgp->confed_peers[j];
     451             : 
     452           0 :   bgp->confed_peers_cnt--;
     453             : 
     454           0 :   if (bgp->confed_peers_cnt == 0)
     455             :     {
     456           0 :       if (bgp->confed_peers)
     457           0 :         XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
     458           0 :       bgp->confed_peers = NULL;
     459             :     }
     460             :   else
     461           0 :     bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
     462             :                                   bgp->confed_peers,
     463             :                                   bgp->confed_peers_cnt * sizeof (as_t));
     464             : 
     465             :   /* Now reset any peer who's remote AS has just been removed from the
     466             :      CONFED */
     467           0 :   if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
     468             :     {
     469           0 :       for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
     470             :         {
     471           0 :           if (peer->as == as)
     472             :             {
     473           0 :               peer->local_as = bgp->confed_id;
     474           0 :               if (peer->status == Established)
     475             :                {
     476           0 :                  peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
     477           0 :                  bgp_notify_send (peer, BGP_NOTIFY_CEASE,
     478             :                                   BGP_NOTIFY_CEASE_CONFIG_CHANGE);
     479             :                }
     480             :               else
     481           0 :                 BGP_EVENT_ADD (peer, BGP_Stop);
     482             :             }
     483             :         }
     484             :     }
     485             : 
     486           0 :   return 0;
     487             : }
     488             : 
     489             : /* Local preference configuration.  */
     490             : int
     491           0 : bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
     492             : {
     493           0 :   if (! bgp)
     494           0 :     return -1;
     495             : 
     496           0 :   bgp->default_local_pref = local_pref;
     497             : 
     498           0 :   return 0;
     499             : }
     500             : 
     501             : int
     502           0 : bgp_default_local_preference_unset (struct bgp *bgp)
     503             : {
     504           0 :   if (! bgp)
     505           0 :     return -1;
     506             : 
     507           0 :   bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
     508             : 
     509           0 :   return 0;
     510             : }
     511             : 
     512             : /* If peer is RSERVER_CLIENT in at least one address family and is not member
     513             :     of a peer_group for that family, return 1.
     514             :     Used to check wether the peer is included in list bgp->rsclient. */
     515             : int
     516           0 : peer_rsclient_active (struct peer *peer)
     517             : {
     518             :   int i;
     519             :   int j;
     520             : 
     521           0 :   for (i=AFI_IP; i < AFI_MAX; i++)
     522           0 :     for (j=SAFI_UNICAST; j < SAFI_MAX; j++)
     523           0 :       if (CHECK_FLAG(peer->af_flags[i][j], PEER_FLAG_RSERVER_CLIENT)
     524           0 :             && ! peer->af_group[i][j])
     525           0 :         return 1;
     526           0 :   return 0;
     527             : }
     528             : 
     529             : /* Peer comparison function for sorting.  */
     530             : static int
     531           0 : peer_cmp (struct peer *p1, struct peer *p2)
     532             : {
     533           0 :   return sockunion_cmp (&p1->su, &p2->su);
     534             : }
     535             : 
     536             : int
     537           0 : peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
     538             : {
     539           0 :   return CHECK_FLAG (peer->af_flags[afi][safi], flag);
     540             : }
     541             : 
     542             : /* Reset all address family specific configuration.  */
     543             : static void
     544           0 : peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
     545             : {
     546             :   int i;
     547             :   struct bgp_filter *filter;
     548             :   char orf_name[BUFSIZ];
     549             : 
     550           0 :   filter = &peer->filter[afi][safi];
     551             : 
     552             :   /* Clear neighbor filter and route-map */
     553           0 :   for (i = FILTER_IN; i < FILTER_MAX; i++)
     554             :     {
     555           0 :       if (filter->dlist[i].name)
     556             :         {
     557           0 :           free (filter->dlist[i].name);
     558           0 :           filter->dlist[i].name = NULL;
     559             :         }
     560           0 :       if (filter->plist[i].name)
     561             :         {
     562           0 :           free (filter->plist[i].name);
     563           0 :           filter->plist[i].name = NULL; 
     564             :         }
     565           0 :       if (filter->aslist[i].name)
     566             :         {
     567           0 :           free (filter->aslist[i].name);
     568           0 :           filter->aslist[i].name = NULL;
     569             :         }
     570             :    }
     571           0 :  for (i = RMAP_IN; i < RMAP_MAX; i++)
     572             :        {
     573           0 :       if (filter->map[i].name)
     574             :         {
     575           0 :           free (filter->map[i].name);
     576           0 :           filter->map[i].name = NULL;
     577             :         }
     578             :     }
     579             : 
     580             :   /* Clear unsuppress map.  */
     581           0 :   if (filter->usmap.name)
     582           0 :     free (filter->usmap.name);
     583           0 :   filter->usmap.name = NULL;
     584           0 :   filter->usmap.map = NULL;
     585             : 
     586             :   /* Clear neighbor's all address family flags.  */
     587           0 :   peer->af_flags[afi][safi] = 0;
     588             : 
     589             :   /* Clear neighbor's all address family sflags. */
     590           0 :   peer->af_sflags[afi][safi] = 0;
     591             : 
     592             :   /* Clear neighbor's all address family capabilities. */
     593           0 :   peer->af_cap[afi][safi] = 0;
     594             : 
     595             :   /* Clear ORF info */
     596           0 :   peer->orf_plist[afi][safi] = NULL;
     597           0 :   sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
     598           0 :   prefix_bgp_orf_remove_all (orf_name);
     599             : 
     600             :   /* Set default neighbor send-community.  */
     601           0 :   if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
     602             :     {
     603           0 :       SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
     604           0 :       SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
     605             :     }
     606             : 
     607             :   /* Clear neighbor default_originate_rmap */
     608           0 :   if (peer->default_rmap[afi][safi].name)
     609           0 :     free (peer->default_rmap[afi][safi].name);
     610           0 :   peer->default_rmap[afi][safi].name = NULL;
     611           0 :   peer->default_rmap[afi][safi].map = NULL;
     612             : 
     613             :   /* Clear neighbor maximum-prefix */
     614           0 :   peer->pmax[afi][safi] = 0;
     615           0 :   peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
     616           0 : }
     617             : 
     618             : /* peer global config reset */
     619             : static void
     620           0 : peer_global_config_reset (struct peer *peer)
     621             : {
     622           0 :   peer->weight = 0;
     623           0 :   peer->change_local_as = 0;
     624           0 :   peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
     625           0 :   if (peer->update_source)
     626             :     {
     627           0 :       sockunion_free (peer->update_source);
     628           0 :       peer->update_source = NULL;
     629             :     }
     630           0 :   if (peer->update_if)
     631             :     {
     632           0 :       XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
     633           0 :       peer->update_if = NULL;
     634             :     }
     635             : 
     636           0 :   if (peer_sort (peer) == BGP_PEER_IBGP)
     637           0 :     peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
     638             :   else
     639           0 :     peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
     640             : 
     641           0 :   peer->flags = 0;
     642           0 :   peer->config = 0;
     643           0 :   peer->holdtime = 0;
     644           0 :   peer->keepalive = 0;
     645           0 :   peer->connect = 0;
     646           0 :   peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
     647           0 : }
     648             : 
     649             : /* Check peer's AS number and determines if this peer is IBGP or EBGP */
     650             : static bgp_peer_sort_t
     651           0 : peer_calc_sort (struct peer *peer)
     652             : {
     653             :   struct bgp *bgp;
     654             : 
     655           0 :   bgp = peer->bgp;
     656             : 
     657             :   /* Peer-group */
     658           0 :   if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
     659             :     {
     660           0 :       if (peer->as)
     661           0 :         return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
     662             :       else
     663             :         {
     664             :           struct peer *peer1;
     665           0 :           peer1 = listnode_head (peer->group->peer);
     666           0 :           if (peer1)
     667           0 :             return (peer1->local_as == peer1->as 
     668             :                     ? BGP_PEER_IBGP : BGP_PEER_EBGP);
     669             :         } 
     670           0 :       return BGP_PEER_INTERNAL;
     671             :     }
     672             : 
     673             :   /* Normal peer */
     674           0 :   if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
     675             :     {
     676           0 :       if (peer->local_as == 0)
     677           0 :         return BGP_PEER_INTERNAL;
     678             : 
     679           0 :       if (peer->local_as == peer->as)
     680             :         {
     681           0 :           if (peer->local_as == bgp->confed_id)
     682           0 :             return BGP_PEER_EBGP;
     683             :           else
     684           0 :             return BGP_PEER_IBGP;
     685             :         }
     686             : 
     687           0 :       if (bgp_confederation_peers_check (bgp, peer->as))
     688           0 :         return BGP_PEER_CONFED;
     689             : 
     690           0 :       return BGP_PEER_EBGP;
     691             :     }
     692             :   else
     693             :     {
     694           0 :       return (peer->local_as == 0
     695           0 :               ? BGP_PEER_INTERNAL : peer->local_as == peer->as
     696             :               ? BGP_PEER_IBGP : BGP_PEER_EBGP);
     697             :     }
     698             : }
     699             : 
     700             : /* Calculate and cache the peer "sort" */
     701             : bgp_peer_sort_t
     702           0 : peer_sort (struct peer *peer)
     703             : {
     704           0 :   peer->sort = peer_calc_sort (peer);
     705           0 :   return peer->sort;
     706             : }
     707             : 
     708             : static void
     709           0 : peer_free (struct peer *peer)
     710             : {
     711           0 :   assert (peer->status == Deleted);
     712             : 
     713           0 :   bgp_unlock(peer->bgp);
     714             : 
     715             :   /* this /ought/ to have been done already through bgp_stop earlier,
     716             :    * but just to be sure.. 
     717             :    */
     718           0 :   bgp_timer_set (peer);
     719           0 :   BGP_READ_OFF (peer->t_read);
     720           0 :   BGP_WRITE_OFF (peer->t_write);
     721           0 :   BGP_EVENT_FLUSH (peer);
     722             :   
     723           0 :   if (peer->desc)
     724           0 :     XFREE (MTYPE_PEER_DESC, peer->desc);
     725             :   
     726             :   /* Free allocated host character. */
     727           0 :   if (peer->host)
     728           0 :     XFREE (MTYPE_BGP_PEER_HOST, peer->host);
     729             :   
     730             :   /* Update source configuration.  */
     731           0 :   if (peer->update_source)
     732           0 :     sockunion_free (peer->update_source);
     733             :   
     734           0 :   if (peer->update_if)
     735           0 :     XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
     736             :     
     737           0 :   if (peer->clear_node_queue)
     738           0 :     work_queue_free (peer->clear_node_queue);
     739             :   
     740           0 :   bgp_sync_delete (peer);
     741           0 :   memset (peer, 0, sizeof (struct peer));
     742             :   
     743           0 :   XFREE (MTYPE_BGP_PEER, peer);
     744           0 : }
     745             :                                                 
     746             : /* increase reference count on a struct peer */
     747             : struct peer *
     748          11 : peer_lock (struct peer *peer)
     749             : {
     750          11 :   assert (peer && (peer->lock >= 0));
     751             :     
     752          11 :   peer->lock++;
     753             :   
     754          11 :   return peer;
     755             : }
     756             : 
     757             : /* decrease reference count on a struct peer
     758             :  * struct peer is freed and NULL returned if last reference
     759             :  */
     760             : struct peer *
     761           0 : peer_unlock (struct peer *peer)
     762             : {
     763           0 :   assert (peer && (peer->lock > 0));
     764             :   
     765           0 :   peer->lock--;
     766             :   
     767           0 :   if (peer->lock == 0)
     768             :     {
     769             : #if 0
     770             :       zlog_debug ("unlocked and freeing");
     771             :       zlog_backtrace (LOG_DEBUG);
     772             : #endif
     773           0 :       peer_free (peer);
     774           0 :       return NULL;
     775             :     }
     776             : 
     777             : #if 0
     778             :   if (peer->lock == 1)
     779             :     {
     780             :       zlog_debug ("unlocked to 1");
     781             :       zlog_backtrace (LOG_DEBUG);
     782             :     }
     783             : #endif
     784             : 
     785           0 :   return peer;
     786             : }
     787             :   
     788             : /* Allocate new peer object, implicitely locked.  */
     789             : static struct peer *
     790           4 : peer_new (struct bgp *bgp)
     791             : {
     792             :   afi_t afi;
     793             :   safi_t safi;
     794             :   struct peer *peer;
     795             :   struct servent *sp;
     796             :   
     797             :   /* bgp argument is absolutely required */
     798           4 :   assert (bgp);
     799           4 :   if (!bgp)
     800           0 :     return NULL;
     801             :   
     802             :   /* Allocate new peer. */
     803           4 :   peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
     804             : 
     805             :   /* Set default value. */
     806           4 :   peer->fd = -1;
     807           4 :   peer->v_start = BGP_INIT_START_TIMER;
     808           4 :   peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
     809           4 :   peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
     810           4 :   peer->status = Idle;
     811           4 :   peer->ostatus = Idle;
     812           4 :   peer->weight = 0;
     813           4 :   peer->password = NULL;
     814           4 :   peer->bgp = bgp;
     815           4 :   peer = peer_lock (peer); /* initial reference */
     816           4 :   bgp_lock (bgp);
     817             : 
     818             :   /* Set default flags.  */
     819          12 :   for (afi = AFI_IP; afi < AFI_MAX; afi++)
     820          40 :     for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
     821             :       {
     822          32 :         if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
     823             :           {
     824          32 :             SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
     825          32 :             SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
     826             :           }
     827          32 :         peer->orf_plist[afi][safi] = NULL;
     828             :       }
     829           4 :   SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
     830             : 
     831             :   /* Create buffers.  */
     832           4 :   peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
     833           4 :   peer->obuf = stream_fifo_new ();
     834           4 :   peer->work = stream_new (BGP_MAX_PACKET_SIZE);
     835             : 
     836           4 :   bgp_sync_init (peer);
     837             : 
     838             :   /* Get service port number.  */
     839           4 :   sp = getservbyname ("bgp", "tcp");
     840           4 :   peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
     841             : 
     842           4 :   return peer;
     843             : }
     844             : 
     845             : /* Create new BGP peer.  */
     846             : static struct peer *
     847           0 : peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
     848             :              as_t remote_as, afi_t afi, safi_t safi)
     849             : {
     850             :   int active;
     851             :   struct peer *peer;
     852             :   char buf[SU_ADDRSTRLEN];
     853             : 
     854           0 :   peer = peer_new (bgp);
     855           0 :   peer->su = *su;
     856           0 :   peer->local_as = local_as;
     857           0 :   peer->as = remote_as;
     858           0 :   peer->local_id = bgp->router_id;
     859           0 :   peer->v_holdtime = bgp->default_holdtime;
     860           0 :   peer->v_keepalive = bgp->default_keepalive;
     861           0 :   if (peer_sort (peer) == BGP_PEER_IBGP)
     862           0 :     peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
     863             :   else
     864           0 :     peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
     865             :     
     866           0 :   peer = peer_lock (peer); /* bgp peer list reference */
     867           0 :   listnode_add_sort (bgp->peer, peer);
     868             : 
     869           0 :   active = peer_active (peer);
     870             : 
     871           0 :   if (afi && safi)
     872           0 :     peer->afc[afi][safi] = 1;
     873             : 
     874             :   /* Last read and reset time set */
     875           0 :   peer->readtime = peer->resettime = bgp_clock ();
     876             : 
     877             :   /* Default TTL set. */
     878           0 :   peer->ttl = (peer->sort == BGP_PEER_IBGP) ? 255 : 1;
     879             : 
     880             :   /* Make peer's address string. */
     881           0 :   sockunion2str (su, buf, SU_ADDRSTRLEN);
     882           0 :   peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
     883             : 
     884             :   /* Set up peer's events and timers. */
     885           0 :   if (! active && peer_active (peer))
     886           0 :     bgp_timer_set (peer);
     887             : 
     888           0 :   return peer;
     889             : }
     890             : 
     891             : /* Make accept BGP peer.  Called from bgp_accept (). */
     892             : struct peer *
     893           2 : peer_create_accept (struct bgp *bgp)
     894             : {
     895             :   struct peer *peer;
     896             : 
     897           2 :   peer = peer_new (bgp);
     898             :   
     899           2 :   peer = peer_lock (peer); /* bgp peer list reference */
     900           2 :   listnode_add_sort (bgp->peer, peer);
     901             : 
     902           2 :   return peer;
     903             : }
     904             : 
     905             : /* Change peer's AS number.  */
     906             : static void
     907           0 : peer_as_change (struct peer *peer, as_t as)
     908             : {
     909             :   bgp_peer_sort_t type;
     910             : 
     911             :   /* Stop peer. */
     912           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
     913             :     {
     914           0 :       if (peer->status == Established)
     915             :        {
     916           0 :          peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
     917           0 :          bgp_notify_send (peer, BGP_NOTIFY_CEASE,
     918             :                           BGP_NOTIFY_CEASE_CONFIG_CHANGE);
     919             :        }
     920             :       else
     921           0 :         BGP_EVENT_ADD (peer, BGP_Stop);
     922             :     }
     923           0 :   type = peer_sort (peer);
     924           0 :   peer->as = as;
     925             : 
     926           0 :   if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
     927           0 :       && ! bgp_confederation_peers_check (peer->bgp, as)
     928           0 :       && peer->bgp->as != as)
     929           0 :     peer->local_as = peer->bgp->confed_id;
     930             :   else
     931           0 :     peer->local_as = peer->bgp->as;
     932             : 
     933             :   /* Advertisement-interval reset */
     934           0 :   if (peer_sort (peer) == BGP_PEER_IBGP)
     935           0 :     peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
     936             :   else
     937           0 :     peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
     938             : 
     939             :   /* TTL reset */
     940           0 :   if (peer_sort (peer) == BGP_PEER_IBGP)
     941           0 :     peer->ttl = 255;
     942           0 :   else if (type == BGP_PEER_IBGP)
     943           0 :     peer->ttl = 1;
     944             : 
     945             :   /* reflector-client reset */
     946           0 :   if (peer_sort (peer) != BGP_PEER_IBGP)
     947             :     {
     948           0 :       UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
     949             :                   PEER_FLAG_REFLECTOR_CLIENT);
     950           0 :       UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
     951             :                   PEER_FLAG_REFLECTOR_CLIENT);
     952           0 :       UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
     953             :                   PEER_FLAG_REFLECTOR_CLIENT);
     954           0 :       UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
     955             :                   PEER_FLAG_REFLECTOR_CLIENT);
     956           0 :       UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
     957             :                   PEER_FLAG_REFLECTOR_CLIENT);
     958             :     }
     959             : 
     960             :   /* local-as reset */
     961           0 :   if (peer_sort (peer) != BGP_PEER_EBGP)
     962             :     {
     963           0 :       peer->change_local_as = 0;
     964           0 :       UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
     965           0 :       UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
     966             :     }
     967           0 : }
     968             : 
     969             : /* If peer does not exist, create new one.  If peer already exists,
     970             :    set AS number to the peer.  */
     971             : int
     972           0 : peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
     973             :                 afi_t afi, safi_t safi)
     974             : {
     975             :   struct peer *peer;
     976             :   as_t local_as;
     977             : 
     978           0 :   peer = peer_lookup (bgp, su);
     979             : 
     980           0 :   if (peer)
     981             :     {
     982             :       /* When this peer is a member of peer-group.  */
     983           0 :       if (peer->group)
     984             :         {
     985           0 :           if (peer->group->conf->as)
     986             :             {
     987             :               /* Return peer group's AS number.  */
     988           0 :               *as = peer->group->conf->as;
     989           0 :               return BGP_ERR_PEER_GROUP_MEMBER;
     990             :             }
     991           0 :           if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
     992             :             {
     993           0 :               if (bgp->as != *as)
     994             :                 {
     995           0 :                   *as = peer->as;
     996           0 :                   return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
     997             :                 }
     998             :             }
     999             :           else
    1000             :             {
    1001           0 :               if (bgp->as == *as)
    1002             :                 {
    1003           0 :                   *as = peer->as;
    1004           0 :                   return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
    1005             :                 }
    1006             :             }
    1007             :         }
    1008             : 
    1009             :       /* Existing peer's AS number change. */
    1010           0 :       if (peer->as != *as)
    1011           0 :         peer_as_change (peer, *as);
    1012             :     }
    1013             :   else
    1014             :     {
    1015             : 
    1016             :       /* If the peer is not part of our confederation, and its not an
    1017             :          iBGP peer then spoof the source AS */
    1018           0 :       if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
    1019           0 :           && ! bgp_confederation_peers_check (bgp, *as) 
    1020           0 :           && bgp->as != *as)
    1021           0 :         local_as = bgp->confed_id;
    1022             :       else
    1023           0 :         local_as = bgp->as;
    1024             :       
    1025             :       /* If this is IPv4 unicast configuration and "no bgp default
    1026             :          ipv4-unicast" is specified. */
    1027             : 
    1028           0 :       if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
    1029           0 :           && afi == AFI_IP && safi == SAFI_UNICAST)
    1030           0 :         peer = peer_create (su, bgp, local_as, *as, 0, 0); 
    1031             :       else
    1032           0 :         peer = peer_create (su, bgp, local_as, *as, afi, safi); 
    1033             :     }
    1034             : 
    1035           0 :   return 0;
    1036             : }
    1037             : 
    1038             : /* Activate the peer or peer group for specified AFI and SAFI.  */
    1039             : int
    1040           0 : peer_activate (struct peer *peer, afi_t afi, safi_t safi)
    1041             : {
    1042             :   int active;
    1043             : 
    1044           0 :   if (peer->afc[afi][safi])
    1045           0 :     return 0;
    1046             : 
    1047             :   /* Activate the address family configuration. */
    1048           0 :   if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    1049           0 :     peer->afc[afi][safi] = 1;
    1050             :   else
    1051             :     {
    1052           0 :       active = peer_active (peer);
    1053             : 
    1054           0 :       peer->afc[afi][safi] = 1;
    1055             : 
    1056           0 :       if (! active && peer_active (peer))
    1057           0 :         bgp_timer_set (peer);
    1058             :       else
    1059             :         {
    1060           0 :           if (peer->status == Established)
    1061             :             {
    1062           0 :               if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
    1063             :                 {
    1064           0 :                   peer->afc_adv[afi][safi] = 1;
    1065           0 :                   bgp_capability_send (peer, afi, safi,
    1066             :                                        CAPABILITY_CODE_MP,
    1067             :                                        CAPABILITY_ACTION_SET);
    1068           0 :                   if (peer->afc_recv[afi][safi])
    1069             :                     {
    1070           0 :                       peer->afc_nego[afi][safi] = 1;
    1071           0 :                       bgp_announce_route (peer, afi, safi);
    1072             :                     }
    1073             :                 }
    1074             :               else
    1075             :                {
    1076           0 :                  peer->last_reset = PEER_DOWN_AF_ACTIVATE;
    1077           0 :                  bgp_notify_send (peer, BGP_NOTIFY_CEASE,
    1078             :                                   BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    1079             :                }
    1080             :             }
    1081             :         }
    1082             :     }
    1083           0 :   return 0;
    1084             : }
    1085             : 
    1086             : int
    1087           0 : peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
    1088             : {
    1089             :   struct peer_group *group;
    1090             :   struct peer *peer1;
    1091             :   struct listnode *node, *nnode;
    1092             : 
    1093           0 :   if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    1094             :     {
    1095           0 :       group = peer->group;
    1096             : 
    1097           0 :       for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
    1098             :         {
    1099           0 :           if (peer1->af_group[afi][safi])
    1100           0 :             return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
    1101             :         }
    1102             :     }
    1103             :   else
    1104             :     {
    1105           0 :       if (peer->af_group[afi][safi])
    1106           0 :         return BGP_ERR_PEER_BELONGS_TO_GROUP;
    1107             :     }
    1108             : 
    1109           0 :   if (! peer->afc[afi][safi])
    1110           0 :     return 0;
    1111             : 
    1112             :   /* De-activate the address family configuration. */
    1113           0 :   peer->afc[afi][safi] = 0;
    1114           0 :   peer_af_flag_reset (peer, afi, safi);
    1115             : 
    1116           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    1117             :     {  
    1118           0 :       if (peer->status == Established)
    1119             :         {
    1120           0 :           if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
    1121             :             {
    1122           0 :               peer->afc_adv[afi][safi] = 0;
    1123           0 :               peer->afc_nego[afi][safi] = 0;
    1124             : 
    1125           0 :               if (peer_active_nego (peer))
    1126             :                 {
    1127           0 :                   bgp_capability_send (peer, afi, safi,
    1128             :                                        CAPABILITY_CODE_MP,
    1129             :                                        CAPABILITY_ACTION_UNSET);
    1130           0 :                   bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
    1131           0 :                   peer->pcount[afi][safi] = 0;
    1132             :                 }
    1133             :               else
    1134             :                {
    1135           0 :                  peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
    1136           0 :                  bgp_notify_send (peer, BGP_NOTIFY_CEASE,
    1137             :                                   BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    1138             :                }
    1139             :             }
    1140             :           else
    1141             :            {
    1142           0 :              peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
    1143           0 :              bgp_notify_send (peer, BGP_NOTIFY_CEASE,
    1144             :                               BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    1145             :            }
    1146             :         }
    1147             :     }
    1148           0 :   return 0;
    1149             : }
    1150             : 
    1151             : static void
    1152           0 : peer_nsf_stop (struct peer *peer)
    1153             : {
    1154             :   afi_t afi;
    1155             :   safi_t safi;
    1156             : 
    1157           0 :   UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
    1158           0 :   UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
    1159             : 
    1160           0 :   for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
    1161           0 :     for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
    1162           0 :       peer->nsf[afi][safi] = 0;
    1163             : 
    1164           0 :   if (peer->t_gr_restart)
    1165             :     {
    1166           0 :       BGP_TIMER_OFF (peer->t_gr_restart);
    1167           0 :       if (BGP_DEBUG (events, EVENTS))
    1168           0 :         zlog_debug ("%s graceful restart timer stopped", peer->host);
    1169             :     }
    1170           0 :   if (peer->t_gr_stale)
    1171             :     {
    1172           0 :       BGP_TIMER_OFF (peer->t_gr_stale);
    1173           0 :       if (BGP_DEBUG (events, EVENTS))
    1174           0 :         zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
    1175             :     }
    1176           0 :   bgp_clear_route_all (peer);
    1177           0 : }
    1178             : 
    1179             : /* Delete peer from confguration.
    1180             :  *
    1181             :  * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
    1182             :  * it to "cool off" and refcounts to hit 0, at which state it is freed.
    1183             :  *
    1184             :  * This function /should/ take care to be idempotent, to guard against
    1185             :  * it being called multiple times through stray events that come in
    1186             :  * that happen to result in this function being called again.  That
    1187             :  * said, getting here for a "Deleted" peer is a bug in the neighbour
    1188             :  * FSM.
    1189             :  */
    1190             : int
    1191           0 : peer_delete (struct peer *peer)
    1192             : {
    1193             :   int i;
    1194             :   afi_t afi;
    1195             :   safi_t safi;
    1196             :   struct bgp *bgp;
    1197             :   struct bgp_filter *filter;
    1198             :   struct listnode *pn;
    1199             : 
    1200           0 :   assert (peer->status != Deleted);
    1201             :   
    1202           0 :   bgp = peer->bgp;
    1203             : 
    1204           0 :   if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
    1205           0 :     peer_nsf_stop (peer);
    1206             : 
    1207             :   /* If this peer belongs to peer group, clear up the
    1208             :      relationship.  */
    1209           0 :   if (peer->group)
    1210             :     {
    1211           0 :       if ((pn = listnode_lookup (peer->group->peer, peer)))
    1212             :         {
    1213           0 :           peer = peer_unlock (peer); /* group->peer list reference */
    1214           0 :           list_delete_node (peer->group->peer, pn);
    1215             :         }
    1216           0 :       peer->group = NULL;
    1217             :     }
    1218             :   
    1219             :   /* Withdraw all information from routing table.  We can not use
    1220             :    * BGP_EVENT_ADD (peer, BGP_Stop) at here.  Because the event is
    1221             :    * executed after peer structure is deleted.
    1222             :    */
    1223           0 :   peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
    1224           0 :   bgp_stop (peer);
    1225           0 :   bgp_fsm_change_status (peer, Deleted);
    1226             : 
    1227             :   /* Password configuration */
    1228           0 :   if (peer->password)
    1229             :     {
    1230           0 :       XFREE (MTYPE_PEER_PASSWORD, peer->password);
    1231           0 :       peer->password = NULL;
    1232             : 
    1233           0 :       if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    1234           0 :         bgp_md5_set (peer);
    1235             :     }
    1236             :   
    1237           0 :   bgp_timer_set (peer); /* stops all timers for Deleted */
    1238             :   
    1239             :   /* Delete from all peer list. */
    1240           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
    1241           0 :       && (pn = listnode_lookup (bgp->peer, peer)))
    1242             :     {
    1243           0 :       peer_unlock (peer); /* bgp peer list reference */
    1244           0 :       list_delete_node (bgp->peer, pn);
    1245             :     }
    1246             :       
    1247           0 :   if (peer_rsclient_active (peer)
    1248           0 :       && (pn = listnode_lookup (bgp->rsclient, peer)))
    1249             :     {
    1250           0 :       peer_unlock (peer); /* rsclient list reference */
    1251           0 :       list_delete_node (bgp->rsclient, pn);
    1252             : 
    1253             :       /* Clear our own rsclient ribs. */
    1254           0 :       for (afi = AFI_IP; afi < AFI_MAX; afi++)
    1255           0 :         for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
    1256           0 :           if (CHECK_FLAG(peer->af_flags[afi][safi],
    1257             :                          PEER_FLAG_RSERVER_CLIENT))
    1258           0 :             bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
    1259             :     }
    1260             : 
    1261             :   /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
    1262             :       member of a peer_group. */
    1263           0 :   for (afi = AFI_IP; afi < AFI_MAX; afi++)
    1264           0 :     for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
    1265           0 :       if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
    1266           0 :         bgp_table_finish (&peer->rib[afi][safi]);
    1267             : 
    1268             :   /* Buffers.  */
    1269           0 :   if (peer->ibuf)
    1270           0 :     stream_free (peer->ibuf);
    1271           0 :   if (peer->obuf)
    1272           0 :     stream_fifo_free (peer->obuf);
    1273           0 :   if (peer->work)
    1274           0 :     stream_free (peer->work);
    1275           0 :   peer->obuf = NULL;
    1276           0 :   peer->work = peer->ibuf = NULL;
    1277             : 
    1278             :   /* Local and remote addresses. */
    1279           0 :   if (peer->su_local)
    1280           0 :     sockunion_free (peer->su_local);
    1281           0 :   if (peer->su_remote)
    1282           0 :     sockunion_free (peer->su_remote);
    1283           0 :   peer->su_local = peer->su_remote = NULL;
    1284             :   
    1285             :   /* Free filter related memory.  */
    1286           0 :   for (afi = AFI_IP; afi < AFI_MAX; afi++)
    1287           0 :     for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
    1288             :       {
    1289           0 :         filter = &peer->filter[afi][safi];
    1290             : 
    1291           0 :         for (i = FILTER_IN; i < FILTER_MAX; i++)
    1292             :           {
    1293           0 :             if (filter->dlist[i].name)
    1294           0 :               free (filter->dlist[i].name);
    1295           0 :             if (filter->plist[i].name)
    1296           0 :               free (filter->plist[i].name);
    1297           0 :             if (filter->aslist[i].name)
    1298           0 :               free (filter->aslist[i].name);
    1299             :             
    1300           0 :             filter->dlist[i].name = NULL;
    1301           0 :             filter->plist[i].name = NULL;
    1302           0 :             filter->aslist[i].name = NULL;
    1303             :           }
    1304           0 :         for (i = RMAP_IN; i < RMAP_MAX; i++)
    1305             :           {
    1306           0 :             if (filter->map[i].name)
    1307           0 :               free (filter->map[i].name);
    1308           0 :             filter->map[i].name = NULL;
    1309             :           }
    1310             : 
    1311           0 :         if (filter->usmap.name)
    1312           0 :           free (filter->usmap.name);
    1313             : 
    1314           0 :         if (peer->default_rmap[afi][safi].name)
    1315           0 :           free (peer->default_rmap[afi][safi].name);
    1316             :         
    1317           0 :         filter->usmap.name = NULL;
    1318           0 :         peer->default_rmap[afi][safi].name = NULL;
    1319             :       }
    1320             :   
    1321           0 :   peer_unlock (peer); /* initial reference */
    1322             : 
    1323           0 :   return 0;
    1324             : }
    1325             : 
    1326             : static int
    1327           0 : peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
    1328             : {
    1329           0 :   return strcmp (g1->name, g2->name);
    1330             : }
    1331             : 
    1332             : /* If peer is configured at least one address family return 1. */
    1333             : static int
    1334           0 : peer_group_active (struct peer *peer)
    1335             : {
    1336           0 :   if (peer->af_group[AFI_IP][SAFI_UNICAST]
    1337           0 :       || peer->af_group[AFI_IP][SAFI_MULTICAST]
    1338           0 :       || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
    1339           0 :       || peer->af_group[AFI_IP6][SAFI_UNICAST]
    1340           0 :       || peer->af_group[AFI_IP6][SAFI_MULTICAST])
    1341           0 :     return 1;
    1342           0 :   return 0;
    1343             : }
    1344             : 
    1345             : /* Peer group cofiguration. */
    1346             : static struct peer_group *
    1347           0 : peer_group_new (void)
    1348             : {
    1349           0 :   return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
    1350             :                                         sizeof (struct peer_group));
    1351             : }
    1352             : 
    1353             : static void
    1354           0 : peer_group_free (struct peer_group *group)
    1355             : {
    1356           0 :   XFREE (MTYPE_PEER_GROUP, group);
    1357           0 : }
    1358             : 
    1359             : struct peer_group *
    1360           0 : peer_group_lookup (struct bgp *bgp, const char *name)
    1361             : {
    1362             :   struct peer_group *group;
    1363             :   struct listnode *node, *nnode;
    1364             : 
    1365           0 :   for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
    1366             :     {
    1367           0 :       if (strcmp (group->name, name) == 0)
    1368           0 :         return group;
    1369             :     }
    1370           0 :   return NULL;
    1371             : }
    1372             : 
    1373             : struct peer_group *
    1374           0 : peer_group_get (struct bgp *bgp, const char *name)
    1375             : {
    1376             :   struct peer_group *group;
    1377             : 
    1378           0 :   group = peer_group_lookup (bgp, name);
    1379           0 :   if (group)
    1380           0 :     return group;
    1381             : 
    1382           0 :   group = peer_group_new ();
    1383           0 :   group->bgp = bgp;
    1384           0 :   group->name = strdup (name);
    1385           0 :   group->peer = list_new ();
    1386           0 :   group->conf = peer_new (bgp);
    1387           0 :   if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
    1388           0 :     group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
    1389           0 :   group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
    1390           0 :   group->conf->group = group;
    1391           0 :   group->conf->as = 0; 
    1392           0 :   group->conf->ttl = 1;
    1393           0 :   group->conf->gtsm_hops = 0;
    1394           0 :   group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
    1395           0 :   UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
    1396           0 :   UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
    1397           0 :   group->conf->keepalive = 0;
    1398           0 :   group->conf->holdtime = 0;
    1399           0 :   group->conf->connect = 0;
    1400           0 :   SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
    1401           0 :   listnode_add_sort (bgp->group, group);
    1402             : 
    1403           0 :   return 0;
    1404             : }
    1405             : 
    1406             : static void 
    1407           0 : peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
    1408             :                              afi_t afi, safi_t safi)
    1409             : {
    1410           0 :   int in = FILTER_IN;
    1411           0 :   int out = FILTER_OUT;
    1412             :   struct peer *conf;
    1413             :   struct bgp_filter *pfilter;
    1414             :   struct bgp_filter *gfilter;
    1415             : 
    1416           0 :   conf = group->conf;
    1417           0 :   pfilter = &peer->filter[afi][safi];
    1418           0 :   gfilter = &conf->filter[afi][safi];
    1419             : 
    1420             :   /* remote-as */
    1421           0 :   if (conf->as)
    1422           0 :     peer->as = conf->as;
    1423             : 
    1424             :   /* remote-as */
    1425           0 :   if (conf->change_local_as)
    1426           0 :     peer->change_local_as = conf->change_local_as;
    1427             : 
    1428             :   /* TTL */
    1429           0 :   peer->ttl = conf->ttl;
    1430             : 
    1431             :   /* GTSM hops */
    1432           0 :   peer->gtsm_hops = conf->gtsm_hops;
    1433             : 
    1434             :   /* Weight */
    1435           0 :   peer->weight = conf->weight;
    1436             : 
    1437             :   /* peer flags apply */
    1438           0 :   peer->flags = conf->flags;
    1439             :   /* peer af_flags apply */
    1440           0 :   peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
    1441             :   /* peer config apply */
    1442           0 :   peer->config = conf->config;
    1443             : 
    1444             :   /* peer timers apply */
    1445           0 :   peer->holdtime = conf->holdtime;
    1446           0 :   peer->keepalive = conf->keepalive;
    1447           0 :   peer->connect = conf->connect;
    1448           0 :   if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
    1449           0 :     peer->v_connect = conf->connect;
    1450             :   else
    1451           0 :     peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
    1452             : 
    1453             :   /* advertisement-interval reset */
    1454           0 :   if (peer_sort (peer) == BGP_PEER_IBGP)
    1455           0 :     peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
    1456             :   else
    1457           0 :     peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
    1458             : 
    1459             :   /* password apply */
    1460           0 :   if (conf->password && !peer->password)
    1461           0 :     peer->password =  XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
    1462             : 
    1463           0 :   bgp_md5_set (peer);
    1464             : 
    1465             :   /* maximum-prefix */
    1466           0 :   peer->pmax[afi][safi] = conf->pmax[afi][safi];
    1467           0 :   peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
    1468           0 :   peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
    1469             : 
    1470             :   /* allowas-in */
    1471           0 :   peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
    1472             : 
    1473             :   /* route-server-client */
    1474           0 :   if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
    1475             :     {
    1476             :       /* Make peer's RIB point to group's RIB. */
    1477           0 :       peer->rib[afi][safi] = group->conf->rib[afi][safi];
    1478             : 
    1479             :       /* Import policy. */
    1480           0 :       if (pfilter->map[RMAP_IMPORT].name)
    1481           0 :         free (pfilter->map[RMAP_IMPORT].name);
    1482           0 :       if (gfilter->map[RMAP_IMPORT].name)
    1483             :         {
    1484           0 :           pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
    1485           0 :           pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
    1486             :         }
    1487             :       else
    1488             :         {
    1489           0 :           pfilter->map[RMAP_IMPORT].name = NULL;
    1490           0 :           pfilter->map[RMAP_IMPORT].map = NULL;
    1491             :         }
    1492             : 
    1493             :       /* Export policy. */
    1494           0 :       if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
    1495             :         {
    1496           0 :           pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
    1497           0 :           pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
    1498             :         }
    1499             :     }
    1500             : 
    1501             :   /* default-originate route-map */
    1502           0 :   if (conf->default_rmap[afi][safi].name)
    1503             :     {
    1504           0 :       if (peer->default_rmap[afi][safi].name)
    1505           0 :         free (peer->default_rmap[afi][safi].name);
    1506           0 :       peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
    1507           0 :       peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
    1508             :     }
    1509             : 
    1510             :   /* update-source apply */
    1511           0 :   if (conf->update_source)
    1512             :     {
    1513           0 :       if (peer->update_source)
    1514           0 :         sockunion_free (peer->update_source);
    1515           0 :       if (peer->update_if)
    1516             :         {
    1517           0 :           XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
    1518           0 :           peer->update_if = NULL;
    1519             :         }
    1520           0 :       peer->update_source = sockunion_dup (conf->update_source);
    1521             :     }
    1522           0 :   else if (conf->update_if)
    1523             :     {
    1524           0 :       if (peer->update_if)
    1525           0 :         XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
    1526           0 :       if (peer->update_source)
    1527             :         {
    1528           0 :           sockunion_free (peer->update_source);
    1529           0 :           peer->update_source = NULL;
    1530             :         }
    1531           0 :       peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
    1532             :     }
    1533             : 
    1534             :   /* inbound filter apply */
    1535           0 :   if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
    1536             :     {
    1537           0 :       if (pfilter->dlist[in].name)
    1538           0 :         free (pfilter->dlist[in].name);
    1539           0 :       pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
    1540           0 :       pfilter->dlist[in].alist = gfilter->dlist[in].alist;
    1541             :     }
    1542           0 :   if (gfilter->plist[in].name && ! pfilter->plist[in].name)
    1543             :     {
    1544           0 :       if (pfilter->plist[in].name)
    1545           0 :         free (pfilter->plist[in].name);
    1546           0 :       pfilter->plist[in].name = strdup (gfilter->plist[in].name);
    1547           0 :       pfilter->plist[in].plist = gfilter->plist[in].plist;
    1548             :     }
    1549           0 :   if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
    1550             :     {
    1551           0 :       if (pfilter->aslist[in].name)
    1552           0 :         free (pfilter->aslist[in].name);
    1553           0 :       pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
    1554           0 :       pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
    1555             :     }
    1556           0 :   if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
    1557             :     {
    1558           0 :       if (pfilter->map[RMAP_IN].name)
    1559           0 :         free (pfilter->map[RMAP_IN].name);
    1560           0 :       pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
    1561           0 :       pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
    1562             :     }
    1563             : 
    1564             :   /* outbound filter apply */
    1565           0 :   if (gfilter->dlist[out].name)
    1566             :     {
    1567           0 :       if (pfilter->dlist[out].name)
    1568           0 :         free (pfilter->dlist[out].name);
    1569           0 :       pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
    1570           0 :       pfilter->dlist[out].alist = gfilter->dlist[out].alist;
    1571             :     }
    1572             :   else
    1573             :     {
    1574           0 :       if (pfilter->dlist[out].name)
    1575           0 :         free (pfilter->dlist[out].name);
    1576           0 :       pfilter->dlist[out].name = NULL;
    1577           0 :       pfilter->dlist[out].alist = NULL;
    1578             :     }
    1579           0 :   if (gfilter->plist[out].name)
    1580             :     {
    1581           0 :       if (pfilter->plist[out].name)
    1582           0 :         free (pfilter->plist[out].name);
    1583           0 :       pfilter->plist[out].name = strdup (gfilter->plist[out].name);
    1584           0 :       pfilter->plist[out].plist = gfilter->plist[out].plist;
    1585             :     }
    1586             :   else
    1587             :     {
    1588           0 :       if (pfilter->plist[out].name)
    1589           0 :         free (pfilter->plist[out].name);
    1590           0 :       pfilter->plist[out].name = NULL;
    1591           0 :       pfilter->plist[out].plist = NULL;
    1592             :     }
    1593           0 :   if (gfilter->aslist[out].name)
    1594             :     {
    1595           0 :       if (pfilter->aslist[out].name)
    1596           0 :         free (pfilter->aslist[out].name);
    1597           0 :       pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
    1598           0 :       pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
    1599             :     }
    1600             :   else
    1601             :     {
    1602           0 :       if (pfilter->aslist[out].name)
    1603           0 :         free (pfilter->aslist[out].name);
    1604           0 :       pfilter->aslist[out].name = NULL;
    1605           0 :       pfilter->aslist[out].aslist = NULL;
    1606             :     }
    1607           0 :   if (gfilter->map[RMAP_OUT].name)
    1608             :     {
    1609           0 :       if (pfilter->map[RMAP_OUT].name)
    1610           0 :         free (pfilter->map[RMAP_OUT].name);
    1611           0 :       pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
    1612           0 :       pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
    1613             :     }
    1614             :   else
    1615             :     {
    1616           0 :       if (pfilter->map[RMAP_OUT].name)
    1617           0 :         free (pfilter->map[RMAP_OUT].name);
    1618           0 :       pfilter->map[RMAP_OUT].name = NULL;
    1619           0 :       pfilter->map[RMAP_OUT].map = NULL;
    1620             :     }
    1621             : 
    1622             :  /* RS-client's import/export route-maps. */
    1623           0 :   if (gfilter->map[RMAP_IMPORT].name)
    1624             :     {
    1625           0 :       if (pfilter->map[RMAP_IMPORT].name)
    1626           0 :         free (pfilter->map[RMAP_IMPORT].name);
    1627           0 :       pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
    1628           0 :       pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
    1629             :     }
    1630             :   else
    1631             :     {
    1632           0 :       if (pfilter->map[RMAP_IMPORT].name)
    1633           0 :         free (pfilter->map[RMAP_IMPORT].name);
    1634           0 :       pfilter->map[RMAP_IMPORT].name = NULL;
    1635           0 :       pfilter->map[RMAP_IMPORT].map = NULL;
    1636             :     }
    1637           0 :   if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
    1638             :     {
    1639           0 :       if (pfilter->map[RMAP_EXPORT].name)
    1640           0 :         free (pfilter->map[RMAP_EXPORT].name);
    1641           0 :       pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
    1642           0 :       pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
    1643             :     }
    1644             : 
    1645           0 :   if (gfilter->usmap.name)
    1646             :     {
    1647           0 :       if (pfilter->usmap.name)
    1648           0 :         free (pfilter->usmap.name);
    1649           0 :       pfilter->usmap.name = strdup (gfilter->usmap.name);
    1650           0 :       pfilter->usmap.map = gfilter->usmap.map;
    1651             :     }
    1652             :   else
    1653             :     {
    1654           0 :       if (pfilter->usmap.name)
    1655           0 :         free (pfilter->usmap.name);
    1656           0 :       pfilter->usmap.name = NULL;
    1657           0 :       pfilter->usmap.map = NULL;
    1658             :     }
    1659           0 : } 
    1660             : 
    1661             : /* Peer group's remote AS configuration.  */
    1662             : int
    1663           0 : peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
    1664             : {
    1665             :   struct peer_group *group;
    1666             :   struct peer *peer;
    1667             :   struct listnode *node, *nnode;
    1668             : 
    1669           0 :   group = peer_group_lookup (bgp, group_name);
    1670           0 :   if (! group)
    1671           0 :     return -1;
    1672             : 
    1673           0 :   if (group->conf->as == *as)
    1674           0 :     return 0;
    1675             : 
    1676             :   /* When we setup peer-group AS number all peer group member's AS
    1677             :      number must be updated to same number.  */
    1678           0 :   peer_as_change (group->conf, *as);
    1679             : 
    1680           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    1681             :     {
    1682           0 :       if (peer->as != *as)
    1683           0 :         peer_as_change (peer, *as);
    1684             :     }
    1685             : 
    1686           0 :   return 0;
    1687             : }
    1688             : 
    1689             : int
    1690           0 : peer_group_delete (struct peer_group *group)
    1691             : {
    1692             :   struct bgp *bgp;
    1693             :   struct peer *peer;
    1694             :   struct listnode *node, *nnode;
    1695             : 
    1696           0 :   bgp = group->bgp;
    1697             : 
    1698           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    1699             :     {
    1700           0 :       peer->group = NULL;
    1701           0 :       peer_delete (peer);
    1702             :     }
    1703           0 :   list_delete (group->peer);
    1704             : 
    1705           0 :   free (group->name);
    1706           0 :   group->name = NULL;
    1707             : 
    1708           0 :   group->conf->group = NULL;
    1709           0 :   peer_delete (group->conf);
    1710             : 
    1711             :   /* Delete from all peer_group list. */
    1712           0 :   listnode_delete (bgp->group, group);
    1713             : 
    1714           0 :   peer_group_free (group);
    1715             : 
    1716           0 :   return 0;
    1717             : }
    1718             : 
    1719             : int
    1720           0 : peer_group_remote_as_delete (struct peer_group *group)
    1721             : {
    1722             :   struct peer *peer;
    1723             :   struct listnode *node, *nnode;
    1724             : 
    1725           0 :   if (! group->conf->as)
    1726           0 :     return 0;
    1727             : 
    1728           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    1729             :     {
    1730           0 :       peer->group = NULL;
    1731           0 :       peer_delete (peer);
    1732             :     }
    1733           0 :   list_delete_all_node (group->peer);
    1734             : 
    1735           0 :   group->conf->as = 0;
    1736             : 
    1737           0 :   return 0;
    1738             : }
    1739             : 
    1740             : /* Bind specified peer to peer group.  */
    1741             : int
    1742           0 : peer_group_bind (struct bgp *bgp, union sockunion *su,
    1743             :                  struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
    1744             : {
    1745             :   struct peer *peer;
    1746           0 :   int first_member = 0;
    1747             : 
    1748             :   /* Check peer group's address family.  */
    1749           0 :   if (! group->conf->afc[afi][safi])
    1750           0 :     return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
    1751             : 
    1752             :   /* Lookup the peer.  */
    1753           0 :   peer = peer_lookup (bgp, su);
    1754             : 
    1755             :   /* Create a new peer. */
    1756           0 :   if (! peer)
    1757             :     {
    1758           0 :       if (! group->conf->as)
    1759           0 :         return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
    1760             : 
    1761           0 :       peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
    1762           0 :       peer->group = group;
    1763           0 :       peer->af_group[afi][safi] = 1;
    1764             : 
    1765           0 :       peer = peer_lock (peer); /* group->peer list reference */
    1766           0 :       listnode_add (group->peer, peer);
    1767           0 :       peer_group2peer_config_copy (group, peer, afi, safi);
    1768             : 
    1769           0 :       return 0;
    1770             :     }
    1771             : 
    1772             :   /* When the peer already belongs to peer group, check the consistency.  */
    1773           0 :   if (peer->af_group[afi][safi])
    1774             :     {
    1775           0 :       if (strcmp (peer->group->name, group->name) != 0)
    1776           0 :         return BGP_ERR_PEER_GROUP_CANT_CHANGE;
    1777             : 
    1778           0 :       return 0;
    1779             :     }
    1780             : 
    1781             :   /* Check current peer group configuration.  */
    1782           0 :   if (peer_group_active (peer)
    1783           0 :       && strcmp (peer->group->name, group->name) != 0)
    1784           0 :     return BGP_ERR_PEER_GROUP_MISMATCH;
    1785             : 
    1786           0 :   if (! group->conf->as)
    1787             :     {
    1788           0 :       if (peer_sort (group->conf) != BGP_PEER_INTERNAL
    1789           0 :           && peer_sort (group->conf) != peer_sort (peer))
    1790             :         {
    1791           0 :           if (as)
    1792           0 :             *as = peer->as;
    1793           0 :           return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
    1794             :         }
    1795             : 
    1796           0 :       if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
    1797           0 :         first_member = 1;
    1798             :     }
    1799             : 
    1800           0 :   peer->af_group[afi][safi] = 1;
    1801           0 :   peer->afc[afi][safi] = 1;
    1802           0 :   if (! peer->group)
    1803             :     {
    1804           0 :       peer->group = group;
    1805             :       
    1806           0 :       peer = peer_lock (peer); /* group->peer list reference */
    1807           0 :       listnode_add (group->peer, peer);
    1808             :     }
    1809             :   else
    1810           0 :     assert (group && peer->group == group);
    1811             : 
    1812           0 :   if (first_member)
    1813             :     {
    1814             :       /* Advertisement-interval reset */
    1815           0 :       if (peer_sort (group->conf) == BGP_PEER_IBGP)
    1816           0 :         group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
    1817             :       else
    1818           0 :         group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
    1819             : 
    1820             :       /* ebgp-multihop reset */
    1821           0 :       if (peer_sort (group->conf) == BGP_PEER_IBGP)
    1822           0 :         group->conf->ttl = 255;
    1823             : 
    1824             :       /* local-as reset */
    1825           0 :       if (peer_sort (group->conf) != BGP_PEER_EBGP)
    1826             :         {
    1827           0 :           group->conf->change_local_as = 0;
    1828           0 :           UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
    1829           0 :           UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
    1830             :         }
    1831             :     }
    1832             : 
    1833           0 :   if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
    1834             :     {
    1835             :       struct listnode *pn;
    1836             :       
    1837             :       /* If it's not configured as RSERVER_CLIENT in any other address
    1838             :           family, without being member of a peer_group, remove it from
    1839             :           list bgp->rsclient.*/
    1840           0 :       if (! peer_rsclient_active (peer)
    1841           0 :           && (pn = listnode_lookup (bgp->rsclient, peer)))
    1842             :         {
    1843           0 :           peer_unlock (peer); /* peer rsclient reference */
    1844           0 :           list_delete_node (bgp->rsclient, pn);
    1845             : 
    1846             :           /* Clear our own rsclient rib for this afi/safi. */
    1847           0 :           bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
    1848             :         }
    1849             : 
    1850           0 :       bgp_table_finish (&peer->rib[afi][safi]);
    1851             : 
    1852             :       /* Import policy. */
    1853           0 :       if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
    1854             :         {
    1855           0 :           free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
    1856           0 :           peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
    1857           0 :           peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
    1858             :         }
    1859             : 
    1860             :       /* Export policy. */
    1861           0 :       if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
    1862           0 :               && peer->filter[afi][safi].map[RMAP_EXPORT].name)
    1863             :         {
    1864           0 :           free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
    1865           0 :           peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
    1866           0 :           peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
    1867             :         }
    1868             :     }
    1869             : 
    1870           0 :   peer_group2peer_config_copy (group, peer, afi, safi);
    1871             : 
    1872           0 :   if (peer->status == Established)
    1873             :     {
    1874           0 :       peer->last_reset = PEER_DOWN_RMAP_BIND;
    1875           0 :       bgp_notify_send (peer, BGP_NOTIFY_CEASE,
    1876             :                       BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    1877             :     }
    1878             :   else
    1879           0 :     BGP_EVENT_ADD (peer, BGP_Stop);
    1880             : 
    1881           0 :   return 0;
    1882             : }
    1883             : 
    1884             : int
    1885           0 : peer_group_unbind (struct bgp *bgp, struct peer *peer,
    1886             :                    struct peer_group *group, afi_t afi, safi_t safi)
    1887             : {
    1888           0 :   if (! peer->af_group[afi][safi])
    1889           0 :       return 0;
    1890             : 
    1891           0 :   if (group != peer->group)
    1892           0 :     return BGP_ERR_PEER_GROUP_MISMATCH;
    1893             : 
    1894           0 :   peer->af_group[afi][safi] = 0;
    1895           0 :   peer->afc[afi][safi] = 0;
    1896           0 :   peer_af_flag_reset (peer, afi, safi);
    1897             : 
    1898           0 :   if (peer->rib[afi][safi])
    1899           0 :     peer->rib[afi][safi] = NULL;
    1900             : 
    1901           0 :   if (! peer_group_active (peer))
    1902             :     {
    1903           0 :       assert (listnode_lookup (group->peer, peer));
    1904           0 :       peer_unlock (peer); /* peer group list reference */
    1905           0 :       listnode_delete (group->peer, peer);
    1906           0 :       peer->group = NULL;
    1907           0 :       if (group->conf->as)
    1908             :         {
    1909           0 :           peer_delete (peer);
    1910           0 :           return 0;
    1911             :         }
    1912           0 :       peer_global_config_reset (peer);
    1913             :     }
    1914             : 
    1915           0 :   if (peer->status == Established)
    1916             :     {
    1917           0 :       peer->last_reset = PEER_DOWN_RMAP_UNBIND;
    1918           0 :       bgp_notify_send (peer, BGP_NOTIFY_CEASE,
    1919             :                       BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    1920             :     }
    1921             :   else
    1922           0 :     BGP_EVENT_ADD (peer, BGP_Stop);
    1923             : 
    1924           0 :   return 0;
    1925             : }
    1926             : 
    1927             : /* BGP instance creation by `router bgp' commands. */
    1928             : static struct bgp *
    1929           2 : bgp_create (as_t *as, const char *name)
    1930             : {
    1931             :   struct bgp *bgp;
    1932             :   afi_t afi;
    1933             :   safi_t safi;
    1934             : 
    1935           2 :   if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
    1936           0 :     return NULL;
    1937             :   
    1938           2 :   bgp_lock (bgp);
    1939           2 :   bgp->peer_self = peer_new (bgp);
    1940           2 :   bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
    1941             : 
    1942           2 :   bgp->peer = list_new ();
    1943           2 :   bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
    1944             : 
    1945           2 :   bgp->group = list_new ();
    1946           2 :   bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
    1947             : 
    1948           2 :   bgp->rsclient = list_new ();
    1949           2 :   bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
    1950             : 
    1951           6 :   for (afi = AFI_IP; afi < AFI_MAX; afi++)
    1952          20 :     for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
    1953             :       {
    1954          16 :         bgp->route[afi][safi] = bgp_table_init (afi, safi);
    1955          16 :         bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
    1956          16 :         bgp->rib[afi][safi] = bgp_table_init (afi, safi);
    1957          16 :         bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
    1958          16 :         bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
    1959             :       }
    1960             : 
    1961           2 :   bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
    1962           2 :   bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
    1963           2 :   bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
    1964           2 :   bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
    1965           2 :   bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
    1966             : 
    1967           2 :   bgp->as = *as;
    1968             : 
    1969           2 :   if (name)
    1970           0 :     bgp->name = strdup (name);
    1971             : 
    1972           2 :   return bgp;
    1973             : }
    1974             : 
    1975             : /* Return first entry of BGP. */
    1976             : struct bgp *
    1977           2 : bgp_get_default (void)
    1978             : {
    1979           2 :   if (bm->bgp->head)
    1980           0 :     return (listgetdata (listhead (bm->bgp)));
    1981           2 :   return NULL;
    1982             : }
    1983             : 
    1984             : /* Lookup BGP entry. */
    1985             : struct bgp *
    1986           0 : bgp_lookup (as_t as, const char *name)
    1987             : {
    1988             :   struct bgp *bgp;
    1989             :   struct listnode *node, *nnode;
    1990             : 
    1991           0 :   for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
    1992           0 :     if (bgp->as == as
    1993           0 :         && ((bgp->name == NULL && name == NULL) 
    1994           0 :             || (bgp->name && name && strcmp (bgp->name, name) == 0)))
    1995           0 :       return bgp;
    1996           0 :   return NULL;
    1997             : }
    1998             : 
    1999             : /* Lookup BGP structure by view name. */
    2000             : struct bgp *
    2001           0 : bgp_lookup_by_name (const char *name)
    2002             : {
    2003             :   struct bgp *bgp;
    2004             :   struct listnode *node, *nnode;
    2005             : 
    2006           0 :   for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
    2007           0 :     if ((bgp->name == NULL && name == NULL)
    2008           0 :         || (bgp->name && name && strcmp (bgp->name, name) == 0))
    2009           0 :       return bgp;
    2010           0 :   return NULL;
    2011             : }
    2012             : 
    2013             : /* Called from VTY commands. */
    2014             : int
    2015           2 : bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
    2016             : {
    2017             :   struct bgp *bgp;
    2018             : 
    2019             :   /* Multiple instance check. */
    2020           2 :   if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
    2021             :     {
    2022           0 :       if (name)
    2023           0 :         bgp = bgp_lookup_by_name (name);
    2024             :       else
    2025           0 :         bgp = bgp_get_default ();
    2026             : 
    2027             :       /* Already exists. */
    2028           0 :       if (bgp)
    2029             :         {
    2030           0 :           if (bgp->as != *as)
    2031             :             {
    2032           0 :               *as = bgp->as;
    2033           0 :               return BGP_ERR_INSTANCE_MISMATCH;
    2034             :             }
    2035           0 :           *bgp_val = bgp;
    2036           0 :           return 0;
    2037             :         }
    2038             :     }
    2039             :   else
    2040             :     {
    2041             :       /* BGP instance name can not be specified for single instance.  */
    2042           2 :       if (name)
    2043           0 :         return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
    2044             : 
    2045             :       /* Get default BGP structure if exists. */
    2046           2 :       bgp = bgp_get_default ();
    2047             : 
    2048           2 :       if (bgp)
    2049             :         {
    2050           0 :           if (bgp->as != *as)
    2051             :             {
    2052           0 :               *as = bgp->as;
    2053           0 :               return BGP_ERR_AS_MISMATCH;
    2054             :             }
    2055           0 :           *bgp_val = bgp;
    2056           0 :           return 0;
    2057             :         }
    2058             :     }
    2059             : 
    2060           2 :   bgp = bgp_create (as, name);
    2061           2 :   bgp_router_id_set(bgp, &router_id_zebra);
    2062           2 :   *bgp_val = bgp;
    2063             : 
    2064             :   /* Create BGP server socket, if first instance.  */
    2065           2 :   if (list_isempty(bm->bgp)
    2066           2 :       && !bgp_option_check (BGP_OPT_NO_LISTEN))
    2067             :     {
    2068           0 :       if (bgp_socket (bm->port, bm->address) < 0)
    2069           0 :         return BGP_ERR_INVALID_VALUE;
    2070             :     }
    2071             : 
    2072           2 :   listnode_add (bm->bgp, bgp);
    2073             : 
    2074           2 :   return 0;
    2075             : }
    2076             : 
    2077             : /* Delete BGP instance. */
    2078             : int
    2079           1 : bgp_delete (struct bgp *bgp)
    2080             : {
    2081             :   struct peer *peer;
    2082             :   struct peer_group *group;
    2083             :   struct listnode *node;
    2084             :   struct listnode *next;
    2085             :   afi_t afi;
    2086             :   int i;
    2087             : 
    2088             :   /* Delete static route. */
    2089           1 :   bgp_static_delete (bgp);
    2090             : 
    2091             :   /* Unset redistribution. */
    2092           3 :   for (afi = AFI_IP; afi < AFI_MAX; afi++)
    2093          28 :     for (i = 0; i < ZEBRA_ROUTE_MAX; i++) 
    2094          26 :       if (i != ZEBRA_ROUTE_BGP)
    2095          24 :         bgp_redistribute_unset (bgp, afi, i);
    2096             : 
    2097           1 :   for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
    2098           0 :     peer_delete (peer);
    2099             : 
    2100           1 :   for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
    2101           0 :     peer_group_delete (group);
    2102             : 
    2103           1 :   assert (listcount (bgp->rsclient) == 0);
    2104             : 
    2105           1 :   if (bgp->peer_self) {
    2106           0 :     peer_delete(bgp->peer_self);
    2107           0 :     bgp->peer_self = NULL;
    2108             :   }
    2109             :   
    2110             :   /* Remove visibility via the master list - there may however still be
    2111             :    * routes to be processed still referencing the struct bgp.
    2112             :    */
    2113           1 :   listnode_delete (bm->bgp, bgp);
    2114           1 :   if (list_isempty(bm->bgp))
    2115           1 :     bgp_close ();
    2116             : 
    2117           1 :   bgp_unlock(bgp);  /* initial reference */
    2118             :   
    2119           1 :   return 0;
    2120             : }
    2121             : 
    2122             : static void bgp_free (struct bgp *);
    2123             : 
    2124             : void
    2125           7 : bgp_lock (struct bgp *bgp)
    2126             : {
    2127           7 :   ++bgp->lock;
    2128           7 : }
    2129             : 
    2130             : void
    2131           1 : bgp_unlock(struct bgp *bgp)
    2132             : {
    2133           1 :   assert(bgp->lock > 0);
    2134           1 :   if (--bgp->lock == 0)
    2135           1 :     bgp_free (bgp);
    2136           1 : }
    2137             : 
    2138             : static void
    2139           1 : bgp_free (struct bgp *bgp)
    2140             : {
    2141             :   afi_t afi;
    2142             :   safi_t safi;
    2143             : 
    2144           1 :   list_delete (bgp->group);
    2145           1 :   list_delete (bgp->peer);
    2146           1 :   list_delete (bgp->rsclient);
    2147             : 
    2148           1 :   if (bgp->name)
    2149           0 :     free (bgp->name);
    2150             :   
    2151           3 :   for (afi = AFI_IP; afi < AFI_MAX; afi++)
    2152          10 :     for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
    2153             :       {
    2154           8 :         if (bgp->route[afi][safi])
    2155           8 :           bgp_table_finish (&bgp->route[afi][safi]);
    2156           8 :         if (bgp->aggregate[afi][safi])
    2157           8 :           bgp_table_finish (&bgp->aggregate[afi][safi]) ;
    2158           8 :         if (bgp->rib[afi][safi])
    2159           8 :           bgp_table_finish (&bgp->rib[afi][safi]);
    2160             :       }
    2161           1 :   XFREE (MTYPE_BGP, bgp);
    2162           1 : }
    2163             : 
    2164             : struct peer *
    2165           0 : peer_lookup (struct bgp *bgp, union sockunion *su)
    2166             : {
    2167             :   struct peer *peer;
    2168             :   struct listnode *node, *nnode;
    2169             : 
    2170           0 :   if (bgp != NULL)
    2171             :     {
    2172           0 :       for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
    2173           0 :         if (sockunion_same (&peer->su, su)
    2174           0 :             && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
    2175           0 :           return peer;
    2176             :     }
    2177           0 :   else if (bm->bgp != NULL)
    2178             :     {
    2179             :       struct listnode *bgpnode, *nbgpnode;
    2180             :   
    2181           0 :       for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
    2182           0 :         for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
    2183           0 :           if (sockunion_same (&peer->su, su)
    2184           0 :               && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
    2185           0 :             return peer;
    2186             :     }
    2187           0 :   return NULL;
    2188             : }
    2189             : 
    2190             : struct peer *
    2191           0 : peer_lookup_with_open (union sockunion *su, as_t remote_as,
    2192             :                        struct in_addr *remote_id, int *as)
    2193             : {
    2194             :   struct peer *peer;
    2195             :   struct listnode *node;
    2196             :   struct listnode *bgpnode;
    2197             :   struct bgp *bgp;
    2198             : 
    2199           0 :   if (! bm->bgp)
    2200           0 :     return NULL;
    2201             : 
    2202           0 :   for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
    2203             :     {
    2204           0 :       for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
    2205             :         {
    2206           0 :           if (sockunion_same (&peer->su, su)
    2207           0 :               && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
    2208             :             {
    2209           0 :               if (peer->as == remote_as
    2210           0 :                   && peer->remote_id.s_addr == remote_id->s_addr)
    2211           0 :                 return peer;
    2212           0 :               if (peer->as == remote_as)
    2213           0 :                 *as = 1;
    2214             :             }
    2215             :         }
    2216             : 
    2217           0 :       for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
    2218             :         {
    2219           0 :           if (sockunion_same (&peer->su, su)
    2220           0 :               &&  ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
    2221             :             {
    2222           0 :               if (peer->as == remote_as
    2223           0 :                   && peer->remote_id.s_addr == 0)
    2224           0 :                 return peer;
    2225           0 :               if (peer->as == remote_as)
    2226           0 :                 *as = 1;
    2227             :             }
    2228             :         }
    2229             :     }
    2230           0 :   return NULL;
    2231             : }
    2232             : 
    2233             : /* If peer is configured at least one address family return 1. */
    2234             : int
    2235           0 : peer_active (struct peer *peer)
    2236             : {
    2237           0 :   if (peer->afc[AFI_IP][SAFI_UNICAST]
    2238           0 :       || peer->afc[AFI_IP][SAFI_MULTICAST]
    2239           0 :       || peer->afc[AFI_IP][SAFI_MPLS_VPN]
    2240           0 :       || peer->afc[AFI_IP6][SAFI_UNICAST]
    2241           0 :       || peer->afc[AFI_IP6][SAFI_MULTICAST])
    2242           0 :     return 1;
    2243           0 :   return 0;
    2244             : }
    2245             : 
    2246             : /* If peer is negotiated at least one address family return 1. */
    2247             : int
    2248           0 : peer_active_nego (struct peer *peer)
    2249             : {
    2250           0 :   if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
    2251           0 :       || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
    2252           0 :       || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
    2253           0 :       || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
    2254           0 :       || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
    2255           0 :     return 1;
    2256           0 :   return 0;
    2257             : }
    2258             : 
    2259             : /* peer_flag_change_type. */
    2260             : enum peer_change_type
    2261             : {
    2262             :   peer_change_none,
    2263             :   peer_change_reset,
    2264             :   peer_change_reset_in,
    2265             :   peer_change_reset_out,
    2266             : };
    2267             : 
    2268             : static void
    2269           0 : peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
    2270             :                     enum peer_change_type type)
    2271             : {
    2272           0 :   if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    2273           0 :     return;
    2274             : 
    2275           0 :   if (type == peer_change_reset)
    2276           0 :     bgp_notify_send (peer, BGP_NOTIFY_CEASE,
    2277             :                      BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    2278           0 :   else if (type == peer_change_reset_in)
    2279             :     {
    2280           0 :       if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
    2281           0 :           || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
    2282           0 :         bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
    2283             :       else
    2284           0 :         bgp_notify_send (peer, BGP_NOTIFY_CEASE,
    2285             :                          BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    2286             :     }
    2287           0 :   else if (type == peer_change_reset_out)
    2288           0 :     bgp_announce_route (peer, afi, safi);
    2289             : }
    2290             : 
    2291             : struct peer_flag_action
    2292             : {
    2293             :   /* Peer's flag.  */
    2294             :   u_int32_t flag;
    2295             : 
    2296             :   /* This flag can be set for peer-group member.  */
    2297             :   u_char not_for_member;
    2298             : 
    2299             :   /* Action when the flag is changed.  */
    2300             :   enum peer_change_type type;
    2301             : 
    2302             :   /* Peer down cause */
    2303             :   u_char peer_down;
    2304             : };
    2305             : 
    2306             : static const struct peer_flag_action peer_flag_action_list[] =
    2307             :   {
    2308             :     { PEER_FLAG_PASSIVE,                  0, peer_change_reset },
    2309             :     { PEER_FLAG_SHUTDOWN,                 0, peer_change_reset },
    2310             :     { PEER_FLAG_DONT_CAPABILITY,          0, peer_change_none },
    2311             :     { PEER_FLAG_OVERRIDE_CAPABILITY,      0, peer_change_none },
    2312             :     { PEER_FLAG_STRICT_CAP_MATCH,         0, peer_change_none },
    2313             :     { PEER_FLAG_DYNAMIC_CAPABILITY,       0, peer_change_reset },
    2314             :     { PEER_FLAG_DISABLE_CONNECTED_CHECK,  0, peer_change_reset },
    2315             :     { 0, 0, 0 }
    2316             :   };
    2317             : 
    2318             : static const struct peer_flag_action peer_af_flag_action_list[] =
    2319             :   {
    2320             :     { PEER_FLAG_NEXTHOP_SELF,             1, peer_change_reset_out },
    2321             :     { PEER_FLAG_SEND_COMMUNITY,           1, peer_change_reset_out },
    2322             :     { PEER_FLAG_SEND_EXT_COMMUNITY,       1, peer_change_reset_out },
    2323             :     { PEER_FLAG_SOFT_RECONFIG,            0, peer_change_reset_in },
    2324             :     { PEER_FLAG_REFLECTOR_CLIENT,         1, peer_change_reset },
    2325             :     { PEER_FLAG_RSERVER_CLIENT,           1, peer_change_reset },
    2326             :     { PEER_FLAG_AS_PATH_UNCHANGED,        1, peer_change_reset_out },
    2327             :     { PEER_FLAG_NEXTHOP_UNCHANGED,        1, peer_change_reset_out },
    2328             :     { PEER_FLAG_MED_UNCHANGED,            1, peer_change_reset_out },
    2329             :     { PEER_FLAG_REMOVE_PRIVATE_AS,        1, peer_change_reset_out },
    2330             :     { PEER_FLAG_ALLOWAS_IN,               0, peer_change_reset_in },
    2331             :     { PEER_FLAG_ORF_PREFIX_SM,            1, peer_change_reset },
    2332             :     { PEER_FLAG_ORF_PREFIX_RM,            1, peer_change_reset },
    2333             :     { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED,  0, peer_change_reset_out },
    2334             :     { 0, 0, 0 }
    2335             :   };
    2336             : 
    2337             : /* Proper action set. */
    2338             : static int
    2339           0 : peer_flag_action_set (const struct peer_flag_action *action_list, int size,
    2340             :                       struct peer_flag_action *action, u_int32_t flag)
    2341             : {
    2342             :   int i;
    2343           0 :   int found = 0;
    2344           0 :   int reset_in = 0;
    2345           0 :   int reset_out = 0;
    2346           0 :   const struct peer_flag_action *match = NULL;
    2347             : 
    2348             :   /* Check peer's frag action.  */
    2349           0 :   for (i = 0; i < size; i++)
    2350             :     {
    2351           0 :       match = &action_list[i];
    2352             : 
    2353           0 :       if (match->flag == 0)
    2354           0 :         break;
    2355             : 
    2356           0 :       if (match->flag & flag)
    2357             :         {
    2358           0 :           found = 1;
    2359             : 
    2360           0 :           if (match->type == peer_change_reset_in)
    2361           0 :             reset_in = 1;
    2362           0 :           if (match->type == peer_change_reset_out)
    2363           0 :             reset_out = 1;
    2364           0 :           if (match->type == peer_change_reset)
    2365             :             {
    2366           0 :               reset_in = 1;
    2367           0 :               reset_out = 1;
    2368             :             }
    2369           0 :           if (match->not_for_member)
    2370           0 :             action->not_for_member = 1;
    2371             :         }
    2372             :     }
    2373             : 
    2374             :   /* Set peer clear type.  */
    2375           0 :   if (reset_in && reset_out)
    2376           0 :     action->type = peer_change_reset;
    2377           0 :   else if (reset_in)
    2378           0 :     action->type = peer_change_reset_in;
    2379           0 :   else if (reset_out)
    2380           0 :     action->type = peer_change_reset_out;
    2381             :   else
    2382           0 :     action->type = peer_change_none;
    2383             : 
    2384           0 :   return found;
    2385             : }
    2386             : 
    2387             : static void
    2388           0 : peer_flag_modify_action (struct peer *peer, u_int32_t flag)
    2389             : {
    2390           0 :   if (flag == PEER_FLAG_SHUTDOWN)
    2391             :     {
    2392           0 :       if (CHECK_FLAG (peer->flags, flag))
    2393             :         {
    2394           0 :           if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
    2395           0 :             peer_nsf_stop (peer);
    2396             : 
    2397           0 :           UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
    2398           0 :           if (peer->t_pmax_restart)
    2399             :             {
    2400           0 :               BGP_TIMER_OFF (peer->t_pmax_restart);
    2401           0 :               if (BGP_DEBUG (events, EVENTS))
    2402           0 :                 zlog_debug ("%s Maximum-prefix restart timer canceled",
    2403             :                             peer->host);
    2404             :             }
    2405             : 
    2406           0 :       if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
    2407           0 :         peer_nsf_stop (peer);
    2408             : 
    2409           0 :           if (peer->status == Established)
    2410           0 :             bgp_notify_send (peer, BGP_NOTIFY_CEASE,
    2411             :                              BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
    2412             :           else
    2413           0 :             BGP_EVENT_ADD (peer, BGP_Stop);
    2414             :         }
    2415             :       else
    2416             :         {
    2417           0 :           peer->v_start = BGP_INIT_START_TIMER;
    2418           0 :           BGP_EVENT_ADD (peer, BGP_Stop);
    2419             :         }
    2420             :     }
    2421           0 :   else if (peer->status == Established)
    2422             :     {
    2423           0 :       if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
    2424           0 :         peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
    2425           0 :       else if (flag == PEER_FLAG_PASSIVE)
    2426           0 :         peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
    2427           0 :       else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
    2428           0 :         peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
    2429             : 
    2430           0 :       bgp_notify_send (peer, BGP_NOTIFY_CEASE,
    2431             :                        BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    2432             :     }
    2433             :   else
    2434           0 :     BGP_EVENT_ADD (peer, BGP_Stop);
    2435           0 : }
    2436             : 
    2437             : /* Change specified peer flag. */
    2438             : static int
    2439           0 : peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
    2440             : {
    2441             :   int found;
    2442             :   int size;
    2443             :   struct peer_group *group;
    2444             :   struct listnode *node, *nnode;
    2445             :   struct peer_flag_action action;
    2446             : 
    2447           0 :   memset (&action, 0, sizeof (struct peer_flag_action));
    2448           0 :   size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
    2449             : 
    2450           0 :   found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
    2451             : 
    2452             :   /* No flag action is found.  */
    2453           0 :   if (! found)
    2454           0 :     return BGP_ERR_INVALID_FLAG;    
    2455             : 
    2456             :   /* Not for peer-group member.  */
    2457           0 :   if (action.not_for_member && peer_group_active (peer))
    2458           0 :     return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
    2459             : 
    2460             :   /* When unset the peer-group member's flag we have to check
    2461             :      peer-group configuration.  */
    2462           0 :   if (! set && peer_group_active (peer))
    2463           0 :     if (CHECK_FLAG (peer->group->conf->flags, flag))
    2464             :       {
    2465           0 :         if (flag == PEER_FLAG_SHUTDOWN)
    2466           0 :           return BGP_ERR_PEER_GROUP_SHUTDOWN;
    2467             :         else
    2468           0 :           return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
    2469             :       }
    2470             : 
    2471             :   /* Flag conflict check.  */
    2472           0 :   if (set
    2473           0 :       && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
    2474           0 :       && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
    2475           0 :     return BGP_ERR_PEER_FLAG_CONFLICT;
    2476             : 
    2477           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    2478             :     {
    2479           0 :       if (set && CHECK_FLAG (peer->flags, flag) == flag)
    2480           0 :         return 0;
    2481           0 :       if (! set && ! CHECK_FLAG (peer->flags, flag))
    2482           0 :         return 0;
    2483             :     }
    2484             : 
    2485           0 :   if (set)
    2486           0 :     SET_FLAG (peer->flags, flag);
    2487             :   else
    2488           0 :     UNSET_FLAG (peer->flags, flag);
    2489             :  
    2490           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    2491             :     {
    2492           0 :       if (action.type == peer_change_reset)
    2493           0 :         peer_flag_modify_action (peer, flag);
    2494             : 
    2495           0 :       return 0;
    2496             :     }
    2497             : 
    2498             :   /* peer-group member updates. */
    2499           0 :   group = peer->group;
    2500             : 
    2501           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    2502             :     {
    2503           0 :       if (set && CHECK_FLAG (peer->flags, flag) == flag)
    2504           0 :         continue;
    2505             : 
    2506           0 :       if (! set && ! CHECK_FLAG (peer->flags, flag))
    2507           0 :         continue;
    2508             : 
    2509           0 :       if (set)
    2510           0 :         SET_FLAG (peer->flags, flag);
    2511             :       else
    2512           0 :         UNSET_FLAG (peer->flags, flag);
    2513             : 
    2514           0 :       if (action.type == peer_change_reset)
    2515           0 :         peer_flag_modify_action (peer, flag);
    2516             :     }
    2517           0 :   return 0;
    2518             : }
    2519             : 
    2520             : int
    2521           0 : peer_flag_set (struct peer *peer, u_int32_t flag)
    2522             : {
    2523           0 :   return peer_flag_modify (peer, flag, 1);
    2524             : }
    2525             : 
    2526             : int
    2527           0 : peer_flag_unset (struct peer *peer, u_int32_t flag)
    2528             : {
    2529           0 :   return peer_flag_modify (peer, flag, 0);
    2530             : }
    2531             : 
    2532             : static int
    2533           0 : peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
    2534             : {
    2535           0 :   if (peer->af_group[afi][safi])
    2536           0 :     return 1;
    2537           0 :   return 0;
    2538             : }
    2539             : 
    2540             : static int
    2541           0 : peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
    2542             :                      int set)
    2543             : {
    2544             :   int found;
    2545             :   int size;
    2546             :   struct listnode *node, *nnode;
    2547             :   struct peer_group *group;
    2548             :   struct peer_flag_action action;
    2549             : 
    2550           0 :   memset (&action, 0, sizeof (struct peer_flag_action));
    2551           0 :   size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
    2552             :   
    2553           0 :   found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
    2554             :   
    2555             :   /* No flag action is found.  */
    2556           0 :   if (! found)
    2557           0 :     return BGP_ERR_INVALID_FLAG;    
    2558             : 
    2559             :   /* Adress family must be activated.  */
    2560           0 :   if (! peer->afc[afi][safi])
    2561           0 :     return BGP_ERR_PEER_INACTIVE;
    2562             : 
    2563             :   /* Not for peer-group member.  */
    2564           0 :   if (action.not_for_member && peer_is_group_member (peer, afi, safi))
    2565           0 :     return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
    2566             : 
    2567             :  /* Spcecial check for reflector client.  */
    2568           0 :   if (flag & PEER_FLAG_REFLECTOR_CLIENT
    2569           0 :       && peer_sort (peer) != BGP_PEER_IBGP)
    2570           0 :     return BGP_ERR_NOT_INTERNAL_PEER;
    2571             : 
    2572             :   /* Spcecial check for remove-private-AS.  */
    2573           0 :   if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
    2574           0 :       && peer_sort (peer) == BGP_PEER_IBGP)
    2575           0 :     return BGP_ERR_REMOVE_PRIVATE_AS;
    2576             : 
    2577             :   /* When unset the peer-group member's flag we have to check
    2578             :      peer-group configuration.  */
    2579           0 :   if (! set && peer->af_group[afi][safi])
    2580           0 :     if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
    2581           0 :       return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
    2582             : 
    2583             :   /* When current flag configuration is same as requested one.  */
    2584           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    2585             :     {
    2586           0 :       if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
    2587           0 :         return 0;
    2588           0 :       if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
    2589           0 :         return 0;
    2590             :     }
    2591             : 
    2592           0 :   if (set)
    2593           0 :     SET_FLAG (peer->af_flags[afi][safi], flag);
    2594             :   else
    2595           0 :     UNSET_FLAG (peer->af_flags[afi][safi], flag);
    2596             : 
    2597             :   /* Execute action when peer is established.  */
    2598           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
    2599           0 :       && peer->status == Established)
    2600             :     {
    2601           0 :       if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
    2602           0 :         bgp_clear_adj_in (peer, afi, safi);
    2603             :       else
    2604             :        {
    2605           0 :          if (flag == PEER_FLAG_REFLECTOR_CLIENT)
    2606           0 :            peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
    2607           0 :          else if (flag == PEER_FLAG_RSERVER_CLIENT)
    2608           0 :            peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
    2609           0 :          else if (flag == PEER_FLAG_ORF_PREFIX_SM)
    2610           0 :            peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
    2611           0 :          else if (flag == PEER_FLAG_ORF_PREFIX_RM)
    2612           0 :            peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
    2613             : 
    2614           0 :          peer_change_action (peer, afi, safi, action.type);
    2615             :        }
    2616             : 
    2617             :     }
    2618             : 
    2619             :   /* Peer group member updates.  */
    2620           0 :   if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    2621             :     {
    2622           0 :       group = peer->group;
    2623             :       
    2624           0 :       for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    2625             :         {
    2626           0 :           if (! peer->af_group[afi][safi])
    2627           0 :             continue;
    2628             : 
    2629           0 :           if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
    2630           0 :             continue;
    2631             : 
    2632           0 :           if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
    2633           0 :             continue;
    2634             : 
    2635           0 :           if (set)
    2636           0 :             SET_FLAG (peer->af_flags[afi][safi], flag);
    2637             :           else
    2638           0 :             UNSET_FLAG (peer->af_flags[afi][safi], flag);
    2639             : 
    2640           0 :           if (peer->status == Established)
    2641             :             {
    2642           0 :               if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
    2643           0 :                 bgp_clear_adj_in (peer, afi, safi);
    2644             :               else
    2645             :                {
    2646           0 :                  if (flag == PEER_FLAG_REFLECTOR_CLIENT)
    2647           0 :                    peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
    2648           0 :                  else if (flag == PEER_FLAG_RSERVER_CLIENT)
    2649           0 :                    peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
    2650           0 :                  else if (flag == PEER_FLAG_ORF_PREFIX_SM)
    2651           0 :                    peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
    2652           0 :                  else if (flag == PEER_FLAG_ORF_PREFIX_RM)
    2653           0 :                    peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
    2654             : 
    2655           0 :                  peer_change_action (peer, afi, safi, action.type);
    2656             :                }
    2657             :             }
    2658             :         }
    2659             :     }
    2660           0 :   return 0;
    2661             : }
    2662             : 
    2663             : int
    2664           0 : peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
    2665             : {
    2666           0 :   return peer_af_flag_modify (peer, afi, safi, flag, 1);
    2667             : }
    2668             : 
    2669             : int
    2670           0 : peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
    2671             : {
    2672           0 :   return peer_af_flag_modify (peer, afi, safi, flag, 0);
    2673             : }
    2674             : 
    2675             : /* EBGP multihop configuration. */
    2676             : int
    2677           0 : peer_ebgp_multihop_set (struct peer *peer, int ttl)
    2678             : {
    2679             :   struct peer_group *group;
    2680             :   struct listnode *node, *nnode;
    2681             :   struct peer *peer1;
    2682             : 
    2683           0 :   if (peer->sort == BGP_PEER_IBGP)
    2684           0 :     return 0;
    2685             : 
    2686             :   /* see comment in peer_ttl_security_hops_set() */
    2687           0 :   if (ttl != MAXTTL)
    2688             :     {
    2689           0 :       if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    2690             :         {
    2691           0 :           group = peer->group;
    2692           0 :           if (group->conf->gtsm_hops != 0)
    2693           0 :             return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
    2694             : 
    2695           0 :           for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
    2696             :             {
    2697           0 :               if (peer1->sort == BGP_PEER_IBGP)
    2698           0 :                 continue;
    2699             : 
    2700           0 :               if (peer1->gtsm_hops != 0)
    2701           0 :                 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
    2702             :             }
    2703             :         }
    2704             :       else
    2705             :         {
    2706           0 :           if (peer->gtsm_hops != 0)
    2707           0 :             return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
    2708             :         }
    2709             :     }
    2710             : 
    2711           0 :   peer->ttl = ttl;
    2712             : 
    2713           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    2714             :     {
    2715           0 :       if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
    2716           0 :         sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
    2717             :     }
    2718             :   else
    2719             :     {
    2720           0 :       group = peer->group;
    2721           0 :       for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    2722             :         {
    2723           0 :           if (peer->sort == BGP_PEER_IBGP)
    2724           0 :             continue;
    2725             : 
    2726           0 :           peer->ttl = group->conf->ttl;
    2727             : 
    2728           0 :           if (peer->fd >= 0)
    2729           0 :             sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
    2730             :         }
    2731             :     }
    2732           0 :   return 0;
    2733             : }
    2734             : 
    2735             : int
    2736           0 : peer_ebgp_multihop_unset (struct peer *peer)
    2737             : {
    2738             :   struct peer_group *group;
    2739             :   struct listnode *node, *nnode;
    2740             : 
    2741           0 :   if (peer->sort == BGP_PEER_IBGP)
    2742           0 :     return 0;
    2743             : 
    2744           0 :   if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
    2745           0 :       return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
    2746             : 
    2747           0 :   if (peer_group_active (peer))
    2748           0 :     peer->ttl = peer->group->conf->ttl;
    2749             :   else
    2750           0 :     peer->ttl = 1;
    2751             : 
    2752           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    2753             :     {
    2754           0 :       if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
    2755           0 :         sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
    2756             :     }
    2757             :   else
    2758             :     {
    2759           0 :       group = peer->group;
    2760           0 :       for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    2761             :         {
    2762           0 :           if (peer->sort == BGP_PEER_IBGP)
    2763           0 :             continue;
    2764             : 
    2765           0 :           peer->ttl = 1;
    2766             :           
    2767           0 :           if (peer->fd >= 0)
    2768           0 :             sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
    2769             :         }
    2770             :     }
    2771           0 :   return 0;
    2772             : }
    2773             : 
    2774             : /* Neighbor description. */
    2775             : int
    2776           0 : peer_description_set (struct peer *peer, char *desc)
    2777             : {
    2778           0 :   if (peer->desc)
    2779           0 :     XFREE (MTYPE_PEER_DESC, peer->desc);
    2780             : 
    2781           0 :   peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
    2782             : 
    2783           0 :   return 0;
    2784             : }
    2785             : 
    2786             : int
    2787           0 : peer_description_unset (struct peer *peer)
    2788             : {
    2789           0 :   if (peer->desc)
    2790           0 :     XFREE (MTYPE_PEER_DESC, peer->desc);
    2791             : 
    2792           0 :   peer->desc = NULL;
    2793             : 
    2794           0 :   return 0;
    2795             : }
    2796             : 
    2797             : /* Neighbor update-source. */
    2798             : int
    2799           0 : peer_update_source_if_set (struct peer *peer, const char *ifname)
    2800             : {
    2801             :   struct peer_group *group;
    2802             :   struct listnode *node, *nnode;
    2803             : 
    2804           0 :   if (peer->update_if)
    2805             :     {
    2806           0 :       if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
    2807           0 :           && strcmp (peer->update_if, ifname) == 0)
    2808           0 :         return 0;
    2809             : 
    2810           0 :       XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
    2811           0 :       peer->update_if = NULL;
    2812             :     }
    2813             : 
    2814           0 :   if (peer->update_source)
    2815             :     {
    2816           0 :       sockunion_free (peer->update_source);
    2817           0 :       peer->update_source = NULL;
    2818             :     }
    2819             : 
    2820           0 :   peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
    2821             : 
    2822           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    2823             :     {
    2824           0 :       if (peer->status == Established)
    2825             :        {
    2826           0 :          peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
    2827           0 :          bgp_notify_send (peer, BGP_NOTIFY_CEASE,
    2828             :                           BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    2829             :        }
    2830             :       else
    2831           0 :         BGP_EVENT_ADD (peer, BGP_Stop);
    2832           0 :       return 0;
    2833             :     }
    2834             : 
    2835             :   /* peer-group member updates. */
    2836           0 :   group = peer->group;
    2837           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    2838             :     {
    2839           0 :       if (peer->update_if)
    2840             :         {
    2841           0 :           if (strcmp (peer->update_if, ifname) == 0)
    2842           0 :             continue;
    2843             : 
    2844           0 :           XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
    2845           0 :           peer->update_if = NULL;
    2846             :         }
    2847             : 
    2848           0 :       if (peer->update_source)
    2849             :         {
    2850           0 :           sockunion_free (peer->update_source);
    2851           0 :           peer->update_source = NULL;
    2852             :         }
    2853             : 
    2854           0 :       peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
    2855             : 
    2856           0 :       if (peer->status == Established)
    2857             :        {
    2858           0 :          peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
    2859           0 :          bgp_notify_send (peer, BGP_NOTIFY_CEASE,
    2860             :                           BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    2861             :        }
    2862             :       else
    2863           0 :         BGP_EVENT_ADD (peer, BGP_Stop);
    2864             :     }
    2865           0 :   return 0;
    2866             : }
    2867             : 
    2868             : int
    2869           0 : peer_update_source_addr_set (struct peer *peer, union sockunion *su)
    2870             : {
    2871             :   struct peer_group *group;
    2872             :   struct listnode *node, *nnode;
    2873             : 
    2874           0 :   if (peer->update_source)
    2875             :     {
    2876           0 :       if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
    2877           0 :           && sockunion_cmp (peer->update_source, su) == 0)
    2878           0 :         return 0;
    2879           0 :       sockunion_free (peer->update_source);
    2880           0 :       peer->update_source = NULL;
    2881             :     }
    2882             : 
    2883           0 :   if (peer->update_if)
    2884             :     {
    2885           0 :       XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
    2886           0 :       peer->update_if = NULL;
    2887             :     }
    2888             : 
    2889           0 :   peer->update_source = sockunion_dup (su);
    2890             : 
    2891           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    2892             :     {
    2893           0 :       if (peer->status == Established)
    2894             :        {
    2895           0 :          peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
    2896           0 :          bgp_notify_send (peer, BGP_NOTIFY_CEASE,
    2897             :                           BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    2898             :        }
    2899             :       else
    2900           0 :         BGP_EVENT_ADD (peer, BGP_Stop);
    2901           0 :       return 0;
    2902             :     }
    2903             : 
    2904             :   /* peer-group member updates. */
    2905           0 :   group = peer->group;
    2906           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    2907             :     {
    2908           0 :       if (peer->update_source)
    2909             :         {
    2910           0 :           if (sockunion_cmp (peer->update_source, su) == 0)
    2911           0 :             continue;
    2912           0 :           sockunion_free (peer->update_source);
    2913           0 :           peer->update_source = NULL;
    2914             :         }
    2915             : 
    2916           0 :       if (peer->update_if)
    2917             :         {
    2918           0 :           XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
    2919           0 :           peer->update_if = NULL;
    2920             :         }
    2921             : 
    2922           0 :       peer->update_source = sockunion_dup (su);
    2923             : 
    2924           0 :       if (peer->status == Established)
    2925             :        {
    2926           0 :          peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
    2927           0 :          bgp_notify_send (peer, BGP_NOTIFY_CEASE,
    2928             :                           BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    2929             :        }
    2930             :       else
    2931           0 :         BGP_EVENT_ADD (peer, BGP_Stop);
    2932             :     }
    2933           0 :   return 0;
    2934             : }
    2935             : 
    2936             : int
    2937           0 : peer_update_source_unset (struct peer *peer)
    2938             : {
    2939             :   union sockunion *su;
    2940             :   struct peer_group *group;
    2941             :   struct listnode *node, *nnode;
    2942             : 
    2943           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
    2944           0 :       && ! peer->update_source
    2945           0 :       && ! peer->update_if)
    2946           0 :     return 0;
    2947             : 
    2948           0 :   if (peer->update_source)
    2949             :     {
    2950           0 :       sockunion_free (peer->update_source);
    2951           0 :       peer->update_source = NULL;
    2952             :     }
    2953           0 :   if (peer->update_if)
    2954             :     {
    2955           0 :       XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
    2956           0 :       peer->update_if = NULL;
    2957             :     }
    2958             : 
    2959           0 :   if (peer_group_active (peer))
    2960             :     {
    2961           0 :       group = peer->group;
    2962             : 
    2963           0 :       if (group->conf->update_source)
    2964             :         {
    2965           0 :           su = sockunion_dup (group->conf->update_source);
    2966           0 :           peer->update_source = su;
    2967             :         }
    2968           0 :       else if (group->conf->update_if)
    2969           0 :         peer->update_if = 
    2970           0 :           XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
    2971             :     }
    2972             : 
    2973           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    2974             :     {
    2975           0 :       if (peer->status == Established)
    2976             :        {
    2977           0 :          peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
    2978           0 :          bgp_notify_send (peer, BGP_NOTIFY_CEASE,
    2979             :                           BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    2980             :        }
    2981             :       else
    2982           0 :         BGP_EVENT_ADD (peer, BGP_Stop);
    2983           0 :       return 0;
    2984             :     }
    2985             : 
    2986             :   /* peer-group member updates. */
    2987           0 :   group = peer->group;
    2988           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    2989             :     {
    2990           0 :       if (! peer->update_source && ! peer->update_if)
    2991           0 :         continue;
    2992             : 
    2993           0 :       if (peer->update_source)
    2994             :         {
    2995           0 :           sockunion_free (peer->update_source);
    2996           0 :           peer->update_source = NULL;
    2997             :         }
    2998             : 
    2999           0 :       if (peer->update_if)
    3000             :         {
    3001           0 :           XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
    3002           0 :           peer->update_if = NULL;
    3003             :         }
    3004             : 
    3005           0 :       if (peer->status == Established)
    3006             :        {
    3007           0 :          peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
    3008           0 :          bgp_notify_send (peer, BGP_NOTIFY_CEASE,
    3009             :                           BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    3010             :        }
    3011             :       else
    3012           0 :         BGP_EVENT_ADD (peer, BGP_Stop);
    3013             :     }
    3014           0 :   return 0;
    3015             : }
    3016             : 
    3017             : int
    3018           0 : peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
    3019             :                             const char *rmap)
    3020             : {
    3021             :   struct peer_group *group;
    3022             :   struct listnode *node, *nnode;
    3023             : 
    3024             :   /* Adress family must be activated.  */
    3025           0 :   if (! peer->afc[afi][safi])
    3026           0 :     return BGP_ERR_PEER_INACTIVE;
    3027             : 
    3028             :   /* Default originate can't be used for peer group memeber.  */
    3029           0 :   if (peer_is_group_member (peer, afi, safi))
    3030           0 :     return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
    3031             : 
    3032           0 :   if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
    3033           0 :       || (rmap && ! peer->default_rmap[afi][safi].name)
    3034           0 :       || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
    3035             :     { 
    3036           0 :       SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
    3037             : 
    3038           0 :       if (rmap)
    3039             :         {
    3040           0 :           if (peer->default_rmap[afi][safi].name)
    3041           0 :             free (peer->default_rmap[afi][safi].name);
    3042           0 :           peer->default_rmap[afi][safi].name = strdup (rmap);
    3043           0 :           peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
    3044             :         }
    3045             :     }
    3046             : 
    3047           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    3048             :     {
    3049           0 :       if (peer->status == Established && peer->afc_nego[afi][safi])
    3050           0 :         bgp_default_originate (peer, afi, safi, 0);
    3051           0 :       return 0;
    3052             :     }
    3053             : 
    3054             :   /* peer-group member updates. */
    3055           0 :   group = peer->group;
    3056           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    3057             :     {
    3058           0 :       SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
    3059             : 
    3060           0 :       if (rmap)
    3061             :         {
    3062           0 :           if (peer->default_rmap[afi][safi].name)
    3063           0 :             free (peer->default_rmap[afi][safi].name);
    3064           0 :           peer->default_rmap[afi][safi].name = strdup (rmap);
    3065           0 :           peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
    3066             :         }
    3067             : 
    3068           0 :       if (peer->status == Established && peer->afc_nego[afi][safi])
    3069           0 :         bgp_default_originate (peer, afi, safi, 0);
    3070             :     }
    3071           0 :   return 0;
    3072             : }
    3073             : 
    3074             : int
    3075           0 : peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
    3076             : {
    3077             :   struct peer_group *group;
    3078             :   struct listnode *node, *nnode;
    3079             : 
    3080             :   /* Adress family must be activated.  */
    3081           0 :   if (! peer->afc[afi][safi])
    3082           0 :     return BGP_ERR_PEER_INACTIVE;
    3083             : 
    3084             :   /* Default originate can't be used for peer group memeber.  */
    3085           0 :   if (peer_is_group_member (peer, afi, safi))
    3086           0 :     return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
    3087             : 
    3088           0 :   if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
    3089             :     { 
    3090           0 :       UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
    3091             : 
    3092           0 :       if (peer->default_rmap[afi][safi].name)
    3093           0 :         free (peer->default_rmap[afi][safi].name);
    3094           0 :       peer->default_rmap[afi][safi].name = NULL;
    3095           0 :       peer->default_rmap[afi][safi].map = NULL;
    3096             :     }
    3097             : 
    3098           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    3099             :     {
    3100           0 :       if (peer->status == Established && peer->afc_nego[afi][safi])
    3101           0 :         bgp_default_originate (peer, afi, safi, 1);
    3102           0 :       return 0;
    3103             :     }
    3104             : 
    3105             :   /* peer-group member updates. */
    3106           0 :   group = peer->group;
    3107           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    3108             :     {
    3109           0 :       UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
    3110             : 
    3111           0 :       if (peer->default_rmap[afi][safi].name)
    3112           0 :         free (peer->default_rmap[afi][safi].name);
    3113           0 :       peer->default_rmap[afi][safi].name = NULL;
    3114           0 :       peer->default_rmap[afi][safi].map = NULL;
    3115             : 
    3116           0 :       if (peer->status == Established && peer->afc_nego[afi][safi])
    3117           0 :         bgp_default_originate (peer, afi, safi, 1);
    3118             :     }
    3119           0 :   return 0;
    3120             : }
    3121             : 
    3122             : int
    3123           0 : peer_port_set (struct peer *peer, u_int16_t port)
    3124             : {
    3125           0 :   peer->port = port;
    3126           0 :   return 0;
    3127             : }
    3128             : 
    3129             : int
    3130           0 : peer_port_unset (struct peer *peer)
    3131             : {
    3132           0 :   peer->port = BGP_PORT_DEFAULT;
    3133           0 :   return 0;
    3134             : }
    3135             : 
    3136             : /* neighbor weight. */
    3137             : int
    3138           0 : peer_weight_set (struct peer *peer, u_int16_t weight)
    3139             : {
    3140             :   struct peer_group *group;
    3141             :   struct listnode *node, *nnode;
    3142             : 
    3143           0 :   SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
    3144           0 :   peer->weight = weight;
    3145             : 
    3146           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    3147           0 :     return 0;
    3148             : 
    3149             :   /* peer-group member updates. */
    3150           0 :   group = peer->group;
    3151           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    3152             :     {
    3153           0 :       peer->weight = group->conf->weight;
    3154             :     }
    3155           0 :   return 0;
    3156             : }
    3157             : 
    3158             : int
    3159           0 : peer_weight_unset (struct peer *peer)
    3160             : {
    3161             :   struct peer_group *group;
    3162             :   struct listnode *node, *nnode;
    3163             : 
    3164             :   /* Set default weight. */
    3165           0 :   if (peer_group_active (peer))
    3166           0 :     peer->weight = peer->group->conf->weight;
    3167             :   else
    3168           0 :     peer->weight = 0;
    3169             : 
    3170           0 :   UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
    3171             : 
    3172           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    3173           0 :     return 0;
    3174             : 
    3175             :   /* peer-group member updates. */
    3176           0 :   group = peer->group;
    3177           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    3178             :     {
    3179           0 :       peer->weight = 0;
    3180             :     }
    3181           0 :   return 0;
    3182             : }
    3183             : 
    3184             : int
    3185           0 : peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
    3186             : {
    3187             :   struct peer_group *group;
    3188             :   struct listnode *node, *nnode;
    3189             : 
    3190             :   /* Not for peer group memeber.  */
    3191           0 :   if (peer_group_active (peer))
    3192           0 :     return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
    3193             : 
    3194             :   /* keepalive value check.  */
    3195           0 :   if (keepalive > 65535)
    3196           0 :     return BGP_ERR_INVALID_VALUE;
    3197             : 
    3198             :   /* Holdtime value check.  */
    3199           0 :   if (holdtime > 65535)
    3200           0 :     return BGP_ERR_INVALID_VALUE;
    3201             : 
    3202             :   /* Holdtime value must be either 0 or greater than 3.  */
    3203           0 :   if (holdtime < 3 && holdtime != 0)
    3204           0 :     return BGP_ERR_INVALID_VALUE;
    3205             : 
    3206             :   /* Set value to the configuration. */
    3207           0 :   SET_FLAG (peer->config, PEER_CONFIG_TIMER);
    3208           0 :   peer->holdtime = holdtime;
    3209           0 :   peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
    3210             : 
    3211           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    3212           0 :     return 0;
    3213             : 
    3214             :   /* peer-group member updates. */
    3215           0 :   group = peer->group;
    3216           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    3217             :     {
    3218           0 :       SET_FLAG (peer->config, PEER_CONFIG_TIMER);
    3219           0 :       peer->holdtime = group->conf->holdtime;
    3220           0 :       peer->keepalive = group->conf->keepalive;
    3221             :     }
    3222           0 :   return 0;
    3223             : }
    3224             : 
    3225             : int
    3226           0 : peer_timers_unset (struct peer *peer)
    3227             : {
    3228             :   struct peer_group *group;
    3229             :   struct listnode *node, *nnode;
    3230             : 
    3231           0 :   if (peer_group_active (peer))
    3232           0 :     return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
    3233             : 
    3234             :   /* Clear configuration. */
    3235           0 :   UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
    3236           0 :   peer->keepalive = 0;
    3237           0 :   peer->holdtime = 0;
    3238             : 
    3239           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    3240           0 :     return 0;
    3241             : 
    3242             :   /* peer-group member updates. */
    3243           0 :   group = peer->group;
    3244           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    3245             :     {
    3246           0 :       UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
    3247           0 :       peer->holdtime = 0;
    3248           0 :       peer->keepalive = 0;
    3249             :     }
    3250             : 
    3251           0 :   return 0;
    3252             : }
    3253             : 
    3254             : int
    3255           0 : peer_timers_connect_set (struct peer *peer, u_int32_t connect)
    3256             : {
    3257           0 :   if (peer_group_active (peer))
    3258           0 :     return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
    3259             : 
    3260           0 :   if (connect > 65535)
    3261           0 :     return BGP_ERR_INVALID_VALUE;
    3262             : 
    3263             :   /* Set value to the configuration. */
    3264           0 :   SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
    3265           0 :   peer->connect = connect;
    3266             : 
    3267             :   /* Set value to timer setting. */
    3268           0 :   peer->v_connect = connect;
    3269             : 
    3270           0 :   return 0;
    3271             : }
    3272             : 
    3273             : int
    3274           0 : peer_timers_connect_unset (struct peer *peer)
    3275             : {
    3276           0 :   if (peer_group_active (peer))
    3277           0 :     return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
    3278             : 
    3279             :   /* Clear configuration. */
    3280           0 :   UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
    3281           0 :   peer->connect = 0;
    3282             : 
    3283             :   /* Set timer setting to default value. */
    3284           0 :   peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
    3285             : 
    3286           0 :   return 0;
    3287             : }
    3288             : 
    3289             : int
    3290           0 : peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
    3291             : {
    3292           0 :   if (peer_group_active (peer))
    3293           0 :     return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
    3294             : 
    3295           0 :   if (routeadv > 600)
    3296           0 :     return BGP_ERR_INVALID_VALUE;
    3297             : 
    3298           0 :   SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
    3299           0 :   peer->routeadv = routeadv;
    3300           0 :   peer->v_routeadv = routeadv;
    3301             : 
    3302           0 :   return 0;
    3303             : }
    3304             : 
    3305             : int
    3306           0 : peer_advertise_interval_unset (struct peer *peer)
    3307             : {
    3308           0 :   if (peer_group_active (peer))
    3309           0 :     return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
    3310             : 
    3311           0 :   UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
    3312           0 :   peer->routeadv = 0;
    3313             : 
    3314           0 :   if (peer->sort == BGP_PEER_IBGP)
    3315           0 :     peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
    3316             :   else
    3317           0 :     peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
    3318             :   
    3319           0 :   return 0;
    3320             : }
    3321             : 
    3322             : /* neighbor interface */
    3323             : int
    3324           0 : peer_interface_set (struct peer *peer, const char *str)
    3325             : {
    3326           0 :   if (peer->ifname)
    3327           0 :     free (peer->ifname);
    3328           0 :   peer->ifname = strdup (str);
    3329             : 
    3330           0 :   return 0;
    3331             : }
    3332             : 
    3333             : int
    3334           0 : peer_interface_unset (struct peer *peer)
    3335             : {
    3336           0 :   if (peer->ifname)
    3337           0 :     free (peer->ifname);
    3338           0 :   peer->ifname = NULL;
    3339             : 
    3340           0 :   return 0;
    3341             : }
    3342             : 
    3343             : /* Allow-as in.  */
    3344             : int
    3345           0 : peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
    3346             : {
    3347             :   struct peer_group *group;
    3348             :   struct listnode *node, *nnode;
    3349             : 
    3350           0 :   if (allow_num < 1 || allow_num > 10)
    3351           0 :     return BGP_ERR_INVALID_VALUE;
    3352             : 
    3353           0 :   if (peer->allowas_in[afi][safi] != allow_num)
    3354             :     {
    3355           0 :       peer->allowas_in[afi][safi] = allow_num;
    3356           0 :       SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
    3357           0 :       peer_change_action (peer, afi, safi, peer_change_reset_in);
    3358             :     }
    3359             : 
    3360           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    3361           0 :     return 0;
    3362             : 
    3363           0 :   group = peer->group;
    3364           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    3365             :     {
    3366           0 :       if (peer->allowas_in[afi][safi] != allow_num)
    3367             :         {
    3368           0 :           peer->allowas_in[afi][safi] = allow_num;
    3369           0 :           SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
    3370           0 :           peer_change_action (peer, afi, safi, peer_change_reset_in);
    3371             :         }
    3372             :           
    3373             :     }
    3374           0 :   return 0;
    3375             : }
    3376             : 
    3377             : int
    3378           0 : peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
    3379             : {
    3380             :   struct peer_group *group;
    3381             :   struct listnode *node, *nnode;
    3382             : 
    3383           0 :   if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
    3384             :     {
    3385           0 :       peer->allowas_in[afi][safi] = 0;
    3386           0 :       peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
    3387             :     }
    3388             : 
    3389           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    3390           0 :     return 0;
    3391             : 
    3392           0 :   group = peer->group;
    3393           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    3394             :     {
    3395           0 :       if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
    3396             :         {
    3397           0 :           peer->allowas_in[afi][safi] = 0;
    3398           0 :           peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
    3399             :         }
    3400             :     }
    3401           0 :   return 0;
    3402             : }
    3403             : 
    3404             : int
    3405           0 : peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
    3406             : {
    3407           0 :   struct bgp *bgp = peer->bgp;
    3408             :   struct peer_group *group;
    3409             :   struct listnode *node, *nnode;
    3410             : 
    3411           0 :   if (peer_sort (peer) != BGP_PEER_EBGP
    3412           0 :       && peer_sort (peer) != BGP_PEER_INTERNAL)
    3413           0 :     return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
    3414             : 
    3415           0 :   if (bgp->as == as)
    3416           0 :     return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
    3417             : 
    3418           0 :   if (peer_group_active (peer))
    3419           0 :     return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
    3420             : 
    3421           0 :   if (peer->as == as)
    3422           0 :     return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
    3423             : 
    3424           0 :   if (peer->change_local_as == as &&
    3425           0 :       ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
    3426           0 :        || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
    3427           0 :       ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
    3428           0 :        || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
    3429           0 :     return 0;
    3430             : 
    3431           0 :   peer->change_local_as = as;
    3432           0 :   if (no_prepend)
    3433           0 :     SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
    3434             :   else
    3435           0 :     UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
    3436             : 
    3437           0 :   if (replace_as)
    3438           0 :     SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
    3439             :   else
    3440           0 :     UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
    3441             : 
    3442           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    3443             :     {
    3444           0 :       if (peer->status == Established)
    3445             :        {
    3446           0 :          peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
    3447           0 :          bgp_notify_send (peer, BGP_NOTIFY_CEASE,
    3448             :                           BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    3449             :        }
    3450             :       else
    3451           0 :         BGP_EVENT_ADD (peer, BGP_Stop);
    3452             : 
    3453           0 :       return 0;
    3454             :     }
    3455             : 
    3456           0 :   group = peer->group;
    3457           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    3458             :     {
    3459           0 :       peer->change_local_as = as;
    3460           0 :       if (no_prepend)
    3461           0 :         SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
    3462             :       else
    3463           0 :         UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
    3464             : 
    3465           0 :       if (replace_as)
    3466           0 :         SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
    3467             :       else
    3468           0 :         UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
    3469             : 
    3470           0 :       if (peer->status == Established)
    3471             :        {
    3472           0 :          peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
    3473           0 :          bgp_notify_send (peer, BGP_NOTIFY_CEASE,
    3474             :                           BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    3475             :        }
    3476             :       else
    3477           0 :         BGP_EVENT_ADD (peer, BGP_Stop);
    3478             :     }
    3479             : 
    3480           0 :   return 0;
    3481             : }
    3482             : 
    3483             : int
    3484           0 : peer_local_as_unset (struct peer *peer)
    3485             : {
    3486             :   struct peer_group *group;
    3487             :   struct listnode *node, *nnode;
    3488             : 
    3489           0 :   if (peer_group_active (peer))
    3490           0 :     return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
    3491             : 
    3492           0 :   if (! peer->change_local_as)
    3493           0 :     return 0;
    3494             : 
    3495           0 :   peer->change_local_as = 0;
    3496           0 :   UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
    3497           0 :   UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
    3498             : 
    3499           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    3500             :     {
    3501           0 :       if (peer->status == Established)
    3502             :        {
    3503           0 :          peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
    3504           0 :          bgp_notify_send (peer, BGP_NOTIFY_CEASE,
    3505             :                           BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    3506             :        }
    3507             :       else
    3508           0 :         BGP_EVENT_ADD (peer, BGP_Stop);
    3509             : 
    3510           0 :       return 0;
    3511             :     }
    3512             : 
    3513           0 :   group = peer->group;
    3514           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    3515             :     {
    3516           0 :       peer->change_local_as = 0;
    3517           0 :       UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
    3518           0 :       UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
    3519             : 
    3520           0 :       if (peer->status == Established)
    3521             :        {
    3522           0 :          peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
    3523           0 :          bgp_notify_send (peer, BGP_NOTIFY_CEASE,
    3524             :                           BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    3525             :        }
    3526             :       else
    3527           0 :         BGP_EVENT_ADD (peer, BGP_Stop);
    3528             :     }
    3529           0 :   return 0;
    3530             : }
    3531             : 
    3532             : /* Set password for authenticating with the peer. */
    3533             : int
    3534           0 : peer_password_set (struct peer *peer, const char *password)
    3535             : {
    3536             :   struct listnode *nn, *nnode;
    3537           0 :   int len = password ? strlen(password) : 0;
    3538           0 :   int ret = BGP_SUCCESS;
    3539             : 
    3540           0 :   if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
    3541           0 :     return BGP_ERR_INVALID_VALUE;
    3542             : 
    3543           0 :   if (peer->password && strcmp (peer->password, password) == 0
    3544           0 :       && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    3545           0 :     return 0;
    3546             : 
    3547           0 :   if (peer->password)
    3548           0 :     XFREE (MTYPE_PEER_PASSWORD, peer->password);
    3549             :   
    3550           0 :   peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
    3551             : 
    3552           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    3553             :     {
    3554           0 :       if (peer->status == Established)
    3555           0 :           bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    3556             :       else
    3557           0 :         BGP_EVENT_ADD (peer, BGP_Stop);
    3558             :         
    3559           0 :       return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
    3560             :     }
    3561             : 
    3562           0 :   for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
    3563             :     {
    3564           0 :       if (peer->password && strcmp (peer->password, password) == 0)
    3565           0 :         continue;
    3566             :       
    3567           0 :       if (peer->password)
    3568           0 :         XFREE (MTYPE_PEER_PASSWORD, peer->password);
    3569             :       
    3570           0 :       peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
    3571             : 
    3572           0 :       if (peer->status == Established)
    3573           0 :         bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    3574             :       else
    3575           0 :         BGP_EVENT_ADD (peer, BGP_Stop);
    3576             :       
    3577           0 :       if (bgp_md5_set (peer) < 0)
    3578           0 :         ret = BGP_ERR_TCPSIG_FAILED;
    3579             :     }
    3580             : 
    3581           0 :   return ret;
    3582             : }
    3583             : 
    3584             : int
    3585           0 : peer_password_unset (struct peer *peer)
    3586             : {
    3587             :   struct listnode *nn, *nnode;
    3588             : 
    3589           0 :   if (!peer->password
    3590           0 :       && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    3591           0 :     return 0;
    3592             : 
    3593           0 :   if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    3594             :     {
    3595           0 :       if (peer_group_active (peer)
    3596           0 :           && peer->group->conf->password
    3597           0 :           && strcmp (peer->group->conf->password, peer->password) == 0)
    3598           0 :         return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
    3599             : 
    3600           0 :       if (peer->status == Established)
    3601           0 :         bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    3602             :       else
    3603           0 :         BGP_EVENT_ADD (peer, BGP_Stop);
    3604             : 
    3605           0 :       if (peer->password)
    3606           0 :         XFREE (MTYPE_PEER_PASSWORD, peer->password);
    3607             :       
    3608           0 :       peer->password = NULL;
    3609             :       
    3610           0 :       bgp_md5_set (peer);
    3611             : 
    3612           0 :       return 0;
    3613             :     }
    3614             : 
    3615           0 :   XFREE (MTYPE_PEER_PASSWORD, peer->password);
    3616           0 :   peer->password = NULL;
    3617             : 
    3618           0 :   for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
    3619             :     {
    3620           0 :       if (!peer->password)
    3621           0 :         continue;
    3622             : 
    3623           0 :       if (peer->status == Established)
    3624           0 :         bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
    3625             :       else
    3626           0 :         BGP_EVENT_ADD (peer, BGP_Stop);
    3627             :       
    3628           0 :       XFREE (MTYPE_PEER_PASSWORD, peer->password);
    3629           0 :       peer->password = NULL;
    3630             : 
    3631           0 :       bgp_md5_set (peer);
    3632             :     }
    3633             : 
    3634           0 :   return 0;
    3635             : }
    3636             : 
    3637             : /* Set distribute list to the peer. */
    3638             : int
    3639           0 : peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct, 
    3640             :                      const char *name)
    3641             : {
    3642             :   struct bgp_filter *filter;
    3643             :   struct peer_group *group;
    3644             :   struct listnode *node, *nnode;
    3645             : 
    3646           0 :   if (! peer->afc[afi][safi])
    3647           0 :     return BGP_ERR_PEER_INACTIVE;
    3648             : 
    3649           0 :   if (direct != FILTER_IN && direct != FILTER_OUT)
    3650           0 :     return BGP_ERR_INVALID_VALUE;
    3651             : 
    3652           0 :   if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
    3653           0 :     return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
    3654             : 
    3655           0 :   filter = &peer->filter[afi][safi];
    3656             : 
    3657           0 :   if (filter->plist[direct].name)
    3658           0 :     return BGP_ERR_PEER_FILTER_CONFLICT;
    3659             : 
    3660           0 :   if (filter->dlist[direct].name)
    3661           0 :     free (filter->dlist[direct].name);
    3662           0 :   filter->dlist[direct].name = strdup (name);
    3663           0 :   filter->dlist[direct].alist = access_list_lookup (afi, name);
    3664             : 
    3665           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    3666           0 :     return 0;
    3667             : 
    3668           0 :   group = peer->group;
    3669           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    3670             :     {
    3671           0 :       filter = &peer->filter[afi][safi];
    3672             : 
    3673           0 :       if (! peer->af_group[afi][safi])
    3674           0 :         continue;
    3675             : 
    3676           0 :       if (filter->dlist[direct].name)
    3677           0 :         free (filter->dlist[direct].name);
    3678           0 :       filter->dlist[direct].name = strdup (name);
    3679           0 :       filter->dlist[direct].alist = access_list_lookup (afi, name);
    3680             :     }
    3681             : 
    3682           0 :   return 0;
    3683             : }
    3684             : 
    3685             : int
    3686           0 : peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
    3687             : {
    3688             :   struct bgp_filter *filter;
    3689             :   struct bgp_filter *gfilter;
    3690             :   struct peer_group *group;
    3691             :   struct listnode *node, *nnode;
    3692             : 
    3693           0 :   if (! peer->afc[afi][safi])
    3694           0 :     return BGP_ERR_PEER_INACTIVE;
    3695             : 
    3696           0 :   if (direct != FILTER_IN && direct != FILTER_OUT)
    3697           0 :     return BGP_ERR_INVALID_VALUE;
    3698             : 
    3699           0 :   if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
    3700           0 :     return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
    3701             : 
    3702           0 :   filter = &peer->filter[afi][safi];
    3703             : 
    3704             :   /* apply peer-group filter */
    3705           0 :   if (peer->af_group[afi][safi])
    3706             :     {
    3707           0 :       gfilter = &peer->group->conf->filter[afi][safi];
    3708             : 
    3709           0 :       if (gfilter->dlist[direct].name)
    3710             :         {
    3711           0 :           if (filter->dlist[direct].name)
    3712           0 :             free (filter->dlist[direct].name);
    3713           0 :           filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
    3714           0 :           filter->dlist[direct].alist = gfilter->dlist[direct].alist;
    3715           0 :           return 0;
    3716             :         }
    3717             :     }
    3718             : 
    3719           0 :   if (filter->dlist[direct].name)
    3720           0 :     free (filter->dlist[direct].name);
    3721           0 :   filter->dlist[direct].name = NULL;
    3722           0 :   filter->dlist[direct].alist = NULL;
    3723             : 
    3724           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    3725           0 :     return 0;
    3726             : 
    3727           0 :     group = peer->group;
    3728           0 :     for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    3729             :       {
    3730           0 :         filter = &peer->filter[afi][safi];
    3731             : 
    3732           0 :         if (! peer->af_group[afi][safi])
    3733           0 :           continue;
    3734             : 
    3735           0 :         if (filter->dlist[direct].name)
    3736           0 :           free (filter->dlist[direct].name);
    3737           0 :         filter->dlist[direct].name = NULL;
    3738           0 :         filter->dlist[direct].alist = NULL;
    3739             :       }
    3740             : 
    3741           0 :   return 0;
    3742             : }
    3743             : 
    3744             : /* Update distribute list. */
    3745             : static void
    3746           0 : peer_distribute_update (struct access_list *access)
    3747             : {
    3748             :   afi_t afi;
    3749             :   safi_t safi;
    3750             :   int direct;
    3751             :   struct listnode *mnode, *mnnode;
    3752             :   struct listnode *node, *nnode;
    3753             :   struct bgp *bgp;
    3754             :   struct peer *peer;
    3755             :   struct peer_group *group;
    3756             :   struct bgp_filter *filter;
    3757             : 
    3758           0 :   for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
    3759             :     {
    3760           0 :       for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
    3761             :         {
    3762           0 :           for (afi = AFI_IP; afi < AFI_MAX; afi++)
    3763           0 :             for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
    3764             :               {
    3765           0 :                 filter = &peer->filter[afi][safi];
    3766             : 
    3767           0 :                 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
    3768             :                   {
    3769           0 :                     if (filter->dlist[direct].name)
    3770           0 :                       filter->dlist[direct].alist = 
    3771           0 :                         access_list_lookup (afi, filter->dlist[direct].name);
    3772             :                     else
    3773           0 :                       filter->dlist[direct].alist = NULL;
    3774             :                   }
    3775             :               }
    3776             :         }
    3777           0 :       for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
    3778             :         {
    3779           0 :           for (afi = AFI_IP; afi < AFI_MAX; afi++)
    3780           0 :             for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
    3781             :               {
    3782           0 :                 filter = &group->conf->filter[afi][safi];
    3783             : 
    3784           0 :                 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
    3785             :                   {
    3786           0 :                     if (filter->dlist[direct].name)
    3787           0 :                       filter->dlist[direct].alist = 
    3788           0 :                         access_list_lookup (afi, filter->dlist[direct].name);
    3789             :                     else
    3790           0 :                       filter->dlist[direct].alist = NULL;
    3791             :                   }
    3792             :               }
    3793             :         }
    3794             :     }
    3795           0 : }
    3796             : 
    3797             : /* Set prefix list to the peer. */
    3798             : int
    3799           0 : peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct, 
    3800             :                       const char *name)
    3801             : {
    3802             :   struct bgp_filter *filter;
    3803             :   struct peer_group *group;
    3804             :   struct listnode *node, *nnode;
    3805             : 
    3806           0 :   if (! peer->afc[afi][safi])
    3807           0 :     return BGP_ERR_PEER_INACTIVE;
    3808             : 
    3809           0 :   if (direct != FILTER_IN && direct != FILTER_OUT)
    3810           0 :     return BGP_ERR_INVALID_VALUE;
    3811             : 
    3812           0 :   if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
    3813           0 :     return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
    3814             : 
    3815           0 :   filter = &peer->filter[afi][safi];
    3816             : 
    3817           0 :   if (filter->dlist[direct].name)
    3818           0 :     return BGP_ERR_PEER_FILTER_CONFLICT;
    3819             : 
    3820           0 :   if (filter->plist[direct].name)
    3821           0 :     free (filter->plist[direct].name);
    3822           0 :   filter->plist[direct].name = strdup (name);
    3823           0 :   filter->plist[direct].plist = prefix_list_lookup (afi, name);
    3824             : 
    3825           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    3826           0 :     return 0;
    3827             : 
    3828           0 :   group = peer->group;
    3829           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    3830             :     {
    3831           0 :       filter = &peer->filter[afi][safi];
    3832             : 
    3833           0 :       if (! peer->af_group[afi][safi])
    3834           0 :         continue;
    3835             : 
    3836           0 :       if (filter->plist[direct].name)
    3837           0 :         free (filter->plist[direct].name);
    3838           0 :       filter->plist[direct].name = strdup (name);
    3839           0 :       filter->plist[direct].plist = prefix_list_lookup (afi, name);
    3840             :     }
    3841           0 :   return 0;
    3842             : }
    3843             : 
    3844             : int
    3845           0 : peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
    3846             : {
    3847             :   struct bgp_filter *filter;
    3848             :   struct bgp_filter *gfilter;
    3849             :   struct peer_group *group;
    3850             :   struct listnode *node, *nnode;
    3851             : 
    3852           0 :   if (! peer->afc[afi][safi])
    3853           0 :     return BGP_ERR_PEER_INACTIVE;
    3854             : 
    3855           0 :   if (direct != FILTER_IN && direct != FILTER_OUT)
    3856           0 :     return BGP_ERR_INVALID_VALUE;
    3857             : 
    3858           0 :   if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
    3859           0 :     return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
    3860             : 
    3861           0 :   filter = &peer->filter[afi][safi];
    3862             : 
    3863             :   /* apply peer-group filter */
    3864           0 :   if (peer->af_group[afi][safi])
    3865             :     {
    3866           0 :       gfilter = &peer->group->conf->filter[afi][safi];
    3867             : 
    3868           0 :       if (gfilter->plist[direct].name)
    3869             :         {
    3870           0 :           if (filter->plist[direct].name)
    3871           0 :             free (filter->plist[direct].name);
    3872           0 :           filter->plist[direct].name = strdup (gfilter->plist[direct].name);
    3873           0 :           filter->plist[direct].plist = gfilter->plist[direct].plist;
    3874           0 :           return 0;
    3875             :         }
    3876             :     }
    3877             : 
    3878           0 :   if (filter->plist[direct].name)
    3879           0 :     free (filter->plist[direct].name);
    3880           0 :   filter->plist[direct].name = NULL;
    3881           0 :   filter->plist[direct].plist = NULL;
    3882             : 
    3883           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    3884           0 :     return 0;
    3885             : 
    3886           0 :   group = peer->group;
    3887           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    3888             :     {
    3889           0 :       filter = &peer->filter[afi][safi];
    3890             : 
    3891           0 :       if (! peer->af_group[afi][safi])
    3892           0 :         continue;
    3893             : 
    3894           0 :       if (filter->plist[direct].name)
    3895           0 :         free (filter->plist[direct].name);
    3896           0 :       filter->plist[direct].name = NULL;
    3897           0 :       filter->plist[direct].plist = NULL;
    3898             :     }
    3899             : 
    3900           0 :   return 0;
    3901             : }
    3902             : 
    3903             : /* Update prefix-list list. */
    3904             : static void
    3905           0 : peer_prefix_list_update (struct prefix_list *plist)
    3906             : {
    3907             :   struct listnode *mnode, *mnnode;
    3908             :   struct listnode *node, *nnode;
    3909             :   struct bgp *bgp;
    3910             :   struct peer *peer;
    3911             :   struct peer_group *group;
    3912             :   struct bgp_filter *filter;
    3913             :   afi_t afi;
    3914             :   safi_t safi;
    3915             :   int direct;
    3916             : 
    3917           0 :   for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
    3918             :     {
    3919           0 :       for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
    3920             :         {
    3921           0 :           for (afi = AFI_IP; afi < AFI_MAX; afi++)
    3922           0 :             for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
    3923             :               {
    3924           0 :                 filter = &peer->filter[afi][safi];
    3925             : 
    3926           0 :                 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
    3927             :                   {
    3928           0 :                     if (filter->plist[direct].name)
    3929           0 :                       filter->plist[direct].plist = 
    3930           0 :                         prefix_list_lookup (afi, filter->plist[direct].name);
    3931             :                     else
    3932           0 :                       filter->plist[direct].plist = NULL;
    3933             :                   }
    3934             :               }
    3935             :         }
    3936           0 :       for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
    3937             :         {
    3938           0 :           for (afi = AFI_IP; afi < AFI_MAX; afi++)
    3939           0 :             for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
    3940             :               {
    3941           0 :                 filter = &group->conf->filter[afi][safi];
    3942             : 
    3943           0 :                 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
    3944             :                   {
    3945           0 :                     if (filter->plist[direct].name)
    3946           0 :                       filter->plist[direct].plist = 
    3947           0 :                         prefix_list_lookup (afi, filter->plist[direct].name);
    3948             :                     else
    3949           0 :                       filter->plist[direct].plist = NULL;
    3950             :                   }
    3951             :               }
    3952             :         }
    3953             :     }
    3954           0 : }
    3955             : 
    3956             : int
    3957           0 : peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
    3958             :                  const char *name)
    3959             : {
    3960             :   struct bgp_filter *filter;
    3961             :   struct peer_group *group;
    3962             :   struct listnode *node, *nnode;
    3963             : 
    3964           0 :   if (! peer->afc[afi][safi])
    3965           0 :     return BGP_ERR_PEER_INACTIVE;
    3966             : 
    3967           0 :   if (direct != FILTER_IN && direct != FILTER_OUT)
    3968           0 :     return BGP_ERR_INVALID_VALUE;
    3969             : 
    3970           0 :   if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
    3971           0 :     return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
    3972             : 
    3973           0 :   filter = &peer->filter[afi][safi];
    3974             : 
    3975           0 :   if (filter->aslist[direct].name)
    3976           0 :     free (filter->aslist[direct].name);
    3977           0 :   filter->aslist[direct].name = strdup (name);
    3978           0 :   filter->aslist[direct].aslist = as_list_lookup (name);
    3979             : 
    3980           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    3981           0 :     return 0;
    3982             : 
    3983           0 :   group = peer->group;
    3984           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    3985             :     {
    3986           0 :       filter = &peer->filter[afi][safi];
    3987             : 
    3988           0 :       if (! peer->af_group[afi][safi])
    3989           0 :         continue;
    3990             : 
    3991           0 :       if (filter->aslist[direct].name)
    3992           0 :         free (filter->aslist[direct].name);
    3993           0 :       filter->aslist[direct].name = strdup (name);
    3994           0 :       filter->aslist[direct].aslist = as_list_lookup (name);
    3995             :     }
    3996           0 :   return 0;
    3997             : }
    3998             : 
    3999             : int
    4000           0 : peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
    4001             : {
    4002             :   struct bgp_filter *filter;
    4003             :   struct bgp_filter *gfilter;
    4004             :   struct peer_group *group;
    4005             :   struct listnode *node, *nnode;
    4006             : 
    4007           0 :   if (! peer->afc[afi][safi])
    4008           0 :     return BGP_ERR_PEER_INACTIVE;
    4009             : 
    4010           0 :   if (direct != FILTER_IN && direct != FILTER_OUT)
    4011           0 :     return BGP_ERR_INVALID_VALUE;
    4012             : 
    4013           0 :   if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
    4014           0 :     return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
    4015             : 
    4016           0 :   filter = &peer->filter[afi][safi];
    4017             : 
    4018             :   /* apply peer-group filter */
    4019           0 :   if (peer->af_group[afi][safi])
    4020             :     {
    4021           0 :       gfilter = &peer->group->conf->filter[afi][safi];
    4022             : 
    4023           0 :       if (gfilter->aslist[direct].name)
    4024             :         {
    4025           0 :           if (filter->aslist[direct].name)
    4026           0 :             free (filter->aslist[direct].name);
    4027           0 :           filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
    4028           0 :           filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
    4029           0 :           return 0;
    4030             :         }
    4031             :     }
    4032             : 
    4033           0 :   if (filter->aslist[direct].name)
    4034           0 :     free (filter->aslist[direct].name);
    4035           0 :   filter->aslist[direct].name = NULL;
    4036           0 :   filter->aslist[direct].aslist = NULL;
    4037             : 
    4038           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    4039           0 :     return 0;
    4040             : 
    4041           0 :   group = peer->group;
    4042           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    4043             :     {
    4044           0 :       filter = &peer->filter[afi][safi];
    4045             : 
    4046           0 :       if (! peer->af_group[afi][safi])
    4047           0 :         continue;
    4048             : 
    4049           0 :       if (filter->aslist[direct].name)
    4050           0 :         free (filter->aslist[direct].name);
    4051           0 :       filter->aslist[direct].name = NULL;
    4052           0 :       filter->aslist[direct].aslist = NULL;
    4053             :     }
    4054             : 
    4055           0 :   return 0;
    4056             : }
    4057             : 
    4058             : static void
    4059           0 : peer_aslist_update (void)
    4060             : {
    4061             :   afi_t afi;
    4062             :   safi_t safi;
    4063             :   int direct;
    4064             :   struct listnode *mnode, *mnnode;
    4065             :   struct listnode *node, *nnode;
    4066             :   struct bgp *bgp;
    4067             :   struct peer *peer;
    4068             :   struct peer_group *group;
    4069             :   struct bgp_filter *filter;
    4070             : 
    4071           0 :   for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
    4072             :     {
    4073           0 :       for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
    4074             :         {
    4075           0 :           for (afi = AFI_IP; afi < AFI_MAX; afi++)
    4076           0 :             for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
    4077             :               {
    4078           0 :                 filter = &peer->filter[afi][safi];
    4079             : 
    4080           0 :                 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
    4081             :                   {
    4082           0 :                     if (filter->aslist[direct].name)
    4083           0 :                       filter->aslist[direct].aslist = 
    4084           0 :                         as_list_lookup (filter->aslist[direct].name);
    4085             :                     else
    4086           0 :                       filter->aslist[direct].aslist = NULL;
    4087             :                   }
    4088             :               }
    4089             :         }
    4090           0 :       for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
    4091             :         {
    4092           0 :           for (afi = AFI_IP; afi < AFI_MAX; afi++)
    4093           0 :             for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
    4094             :               {
    4095           0 :                 filter = &group->conf->filter[afi][safi];
    4096             : 
    4097           0 :                 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
    4098             :                   {
    4099           0 :                     if (filter->aslist[direct].name)
    4100           0 :                       filter->aslist[direct].aslist = 
    4101           0 :                         as_list_lookup (filter->aslist[direct].name);
    4102             :                     else
    4103           0 :                       filter->aslist[direct].aslist = NULL;
    4104             :                   }
    4105             :               }
    4106             :         }
    4107             :     }
    4108           0 : }
    4109             : 
    4110             : /* Set route-map to the peer. */
    4111             : int
    4112           0 : peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct, 
    4113             :                     const char *name)
    4114             : {
    4115             :   struct bgp_filter *filter;
    4116             :   struct peer_group *group;
    4117             :   struct listnode *node, *nnode;
    4118             : 
    4119           0 :   if (! peer->afc[afi][safi])
    4120           0 :     return BGP_ERR_PEER_INACTIVE;
    4121             : 
    4122           0 :   if (direct != RMAP_IN && direct != RMAP_OUT &&
    4123           0 :       direct != RMAP_IMPORT && direct != RMAP_EXPORT)
    4124           0 :     return BGP_ERR_INVALID_VALUE;
    4125             : 
    4126           0 :   if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
    4127           0 :       && peer_is_group_member (peer, afi, safi))
    4128           0 :     return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
    4129             : 
    4130           0 :   filter = &peer->filter[afi][safi];
    4131             : 
    4132           0 :   if (filter->map[direct].name)
    4133           0 :     free (filter->map[direct].name);
    4134             :   
    4135           0 :   filter->map[direct].name = strdup (name);
    4136           0 :   filter->map[direct].map = route_map_lookup_by_name (name);
    4137             : 
    4138           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    4139           0 :     return 0;
    4140             : 
    4141           0 :   group = peer->group;
    4142           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    4143             :     {
    4144           0 :       filter = &peer->filter[afi][safi];
    4145             : 
    4146           0 :       if (! peer->af_group[afi][safi])
    4147           0 :         continue;
    4148             : 
    4149           0 :       if (filter->map[direct].name)
    4150           0 :         free (filter->map[direct].name);
    4151           0 :       filter->map[direct].name = strdup (name);
    4152           0 :       filter->map[direct].map = route_map_lookup_by_name (name);
    4153             :     }
    4154           0 :   return 0;
    4155             : }
    4156             : 
    4157             : /* Unset route-map from the peer. */
    4158             : int
    4159           0 : peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
    4160             : {
    4161             :   struct bgp_filter *filter;
    4162             :   struct bgp_filter *gfilter;
    4163             :   struct peer_group *group;
    4164             :   struct listnode *node, *nnode;
    4165             : 
    4166           0 :   if (! peer->afc[afi][safi])
    4167           0 :     return BGP_ERR_PEER_INACTIVE;
    4168             : 
    4169           0 :   if (direct != RMAP_IN && direct != RMAP_OUT &&
    4170           0 :       direct != RMAP_IMPORT && direct != RMAP_EXPORT)
    4171           0 :     return BGP_ERR_INVALID_VALUE;
    4172             : 
    4173           0 :   if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
    4174           0 :       && peer_is_group_member (peer, afi, safi))
    4175           0 :     return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
    4176             : 
    4177           0 :   filter = &peer->filter[afi][safi];
    4178             : 
    4179             :   /* apply peer-group filter */
    4180           0 :   if (peer->af_group[afi][safi])
    4181             :     {
    4182           0 :       gfilter = &peer->group->conf->filter[afi][safi];
    4183             : 
    4184           0 :       if (gfilter->map[direct].name)
    4185             :         {
    4186           0 :           if (filter->map[direct].name)
    4187           0 :             free (filter->map[direct].name);
    4188           0 :           filter->map[direct].name = strdup (gfilter->map[direct].name);
    4189           0 :           filter->map[direct].map = gfilter->map[direct].map;
    4190           0 :           return 0;
    4191             :         }
    4192             :     }
    4193             : 
    4194           0 :   if (filter->map[direct].name)
    4195           0 :     free (filter->map[direct].name);
    4196           0 :   filter->map[direct].name = NULL;
    4197           0 :   filter->map[direct].map = NULL;
    4198             : 
    4199           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    4200           0 :     return 0;
    4201             : 
    4202           0 :   group = peer->group;
    4203           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    4204             :     {
    4205           0 :       filter = &peer->filter[afi][safi];
    4206             : 
    4207           0 :       if (! peer->af_group[afi][safi])
    4208           0 :         continue;
    4209             : 
    4210           0 :       if (filter->map[direct].name)
    4211           0 :         free (filter->map[direct].name);
    4212           0 :       filter->map[direct].name = NULL;
    4213           0 :       filter->map[direct].map = NULL;
    4214             :     }
    4215           0 :   return 0;
    4216             : }
    4217             : 
    4218             : /* Set unsuppress-map to the peer. */
    4219             : int
    4220           0 : peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi, 
    4221             :                          const char *name)
    4222             : {
    4223             :   struct bgp_filter *filter;
    4224             :   struct peer_group *group;
    4225             :   struct listnode *node, *nnode;
    4226             : 
    4227           0 :   if (! peer->afc[afi][safi])
    4228           0 :     return BGP_ERR_PEER_INACTIVE;
    4229             : 
    4230           0 :   if (peer_is_group_member (peer, afi, safi))
    4231           0 :     return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
    4232             :       
    4233           0 :   filter = &peer->filter[afi][safi];
    4234             : 
    4235           0 :   if (filter->usmap.name)
    4236           0 :     free (filter->usmap.name);
    4237             :   
    4238           0 :   filter->usmap.name = strdup (name);
    4239           0 :   filter->usmap.map = route_map_lookup_by_name (name);
    4240             : 
    4241           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    4242           0 :     return 0;
    4243             : 
    4244           0 :   group = peer->group;
    4245           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    4246             :     {
    4247           0 :       filter = &peer->filter[afi][safi];
    4248             : 
    4249           0 :       if (! peer->af_group[afi][safi])
    4250           0 :         continue;
    4251             : 
    4252           0 :       if (filter->usmap.name)
    4253           0 :         free (filter->usmap.name);
    4254           0 :       filter->usmap.name = strdup (name);
    4255           0 :       filter->usmap.map = route_map_lookup_by_name (name);
    4256             :     }
    4257           0 :   return 0;
    4258             : }
    4259             : 
    4260             : /* Unset route-map from the peer. */
    4261             : int
    4262           0 : peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
    4263             : {
    4264             :   struct bgp_filter *filter;
    4265             :   struct peer_group *group;
    4266             :   struct listnode *node, *nnode;
    4267             : 
    4268           0 :   if (! peer->afc[afi][safi])
    4269           0 :     return BGP_ERR_PEER_INACTIVE;
    4270             :   
    4271           0 :   if (peer_is_group_member (peer, afi, safi))
    4272           0 :     return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
    4273             : 
    4274           0 :   filter = &peer->filter[afi][safi];
    4275             : 
    4276           0 :   if (filter->usmap.name)
    4277           0 :     free (filter->usmap.name);
    4278           0 :   filter->usmap.name = NULL;
    4279           0 :   filter->usmap.map = NULL;
    4280             : 
    4281           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    4282           0 :     return 0;
    4283             : 
    4284           0 :   group = peer->group;
    4285           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    4286             :     {
    4287           0 :       filter = &peer->filter[afi][safi];
    4288             : 
    4289           0 :       if (! peer->af_group[afi][safi])
    4290           0 :         continue;
    4291             : 
    4292           0 :       if (filter->usmap.name)
    4293           0 :         free (filter->usmap.name);
    4294           0 :       filter->usmap.name = NULL;
    4295           0 :       filter->usmap.map = NULL;
    4296             :     }
    4297           0 :   return 0;
    4298             : }
    4299             : 
    4300             : int
    4301           0 : peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
    4302             :                          u_int32_t max, u_char threshold,
    4303             :                          int warning, u_int16_t restart)
    4304             : {
    4305             :   struct peer_group *group;
    4306             :   struct listnode *node, *nnode;
    4307             : 
    4308           0 :   if (! peer->afc[afi][safi])
    4309           0 :     return BGP_ERR_PEER_INACTIVE;
    4310             : 
    4311           0 :   SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
    4312           0 :   peer->pmax[afi][safi] = max;
    4313           0 :   peer->pmax_threshold[afi][safi] = threshold;
    4314           0 :   peer->pmax_restart[afi][safi] = restart;
    4315           0 :   if (warning)
    4316           0 :     SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
    4317             :   else
    4318           0 :     UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
    4319             : 
    4320           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    4321           0 :     return 0;
    4322             : 
    4323           0 :   group = peer->group;
    4324           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    4325             :     {
    4326           0 :       if (! peer->af_group[afi][safi])
    4327           0 :         continue;
    4328             : 
    4329           0 :       SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
    4330           0 :       peer->pmax[afi][safi] = max;
    4331           0 :       peer->pmax_threshold[afi][safi] = threshold;
    4332           0 :       peer->pmax_restart[afi][safi] = restart;
    4333           0 :       if (warning)
    4334           0 :         SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
    4335             :       else
    4336           0 :         UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
    4337             :     }
    4338           0 :   return 0;
    4339             : }
    4340             : 
    4341             : int
    4342           0 : peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
    4343             : {
    4344             :   struct peer_group *group;
    4345             :   struct listnode *node, *nnode;
    4346             : 
    4347           0 :   if (! peer->afc[afi][safi])
    4348           0 :     return BGP_ERR_PEER_INACTIVE;
    4349             : 
    4350             :   /* apply peer-group config */
    4351           0 :   if (peer->af_group[afi][safi])
    4352             :     {
    4353           0 :       if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
    4354             :           PEER_FLAG_MAX_PREFIX))
    4355           0 :         SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
    4356             :       else
    4357           0 :         UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
    4358             : 
    4359           0 :       if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
    4360             :           PEER_FLAG_MAX_PREFIX_WARNING))
    4361           0 :         SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
    4362             :       else
    4363           0 :         UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
    4364             : 
    4365           0 :       peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
    4366           0 :       peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
    4367           0 :       peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
    4368           0 :       return 0;
    4369             :     }
    4370             : 
    4371           0 :   UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
    4372           0 :   UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
    4373           0 :   peer->pmax[afi][safi] = 0;
    4374           0 :   peer->pmax_threshold[afi][safi] = 0;
    4375           0 :   peer->pmax_restart[afi][safi] = 0;
    4376             : 
    4377           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    4378           0 :     return 0;
    4379             : 
    4380           0 :   group = peer->group;
    4381           0 :   for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    4382             :     {
    4383           0 :       if (! peer->af_group[afi][safi])
    4384           0 :         continue;
    4385             : 
    4386           0 :       UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
    4387           0 :       UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
    4388           0 :       peer->pmax[afi][safi] = 0;
    4389           0 :       peer->pmax_threshold[afi][safi] = 0;
    4390           0 :       peer->pmax_restart[afi][safi] = 0;
    4391             :     }
    4392           0 :   return 0;
    4393             : }
    4394             : 
    4395             : /* Set # of hops between us and BGP peer. */
    4396             : int
    4397           0 : peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
    4398             : {
    4399             :   struct peer_group *group;
    4400             :   struct listnode *node, *nnode;
    4401             :   struct peer *peer1;
    4402             :   int ret;
    4403             : 
    4404           0 :   zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
    4405             : 
    4406           0 :   if (peer->sort == BGP_PEER_IBGP)
    4407           0 :     return BGP_ERR_NO_IBGP_WITH_TTLHACK;
    4408             : 
    4409             :   /* We cannot configure ttl-security hops when ebgp-multihop is already
    4410             :      set.  For non peer-groups, the check is simple.  For peer-groups, it's
    4411             :      slightly messy, because we need to check both the peer-group structure
    4412             :      and all peer-group members for any trace of ebgp-multihop configuration
    4413             :      before actually applying the ttl-security rules.  Cisco really made a
    4414             :      mess of this configuration parameter, and OpenBGPD got it right.
    4415             :   */
    4416             :   
    4417           0 :   if (peer->gtsm_hops == 0) {
    4418           0 :     if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    4419             :       {
    4420           0 :         group = peer->group;
    4421           0 :         if (group->conf->ttl != 1)
    4422           0 :           return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
    4423             : 
    4424           0 :         for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
    4425             :           {
    4426           0 :             if (peer1->sort == BGP_PEER_IBGP)
    4427           0 :               continue;
    4428             : 
    4429           0 :             if (peer1->ttl != 1)
    4430           0 :               return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
    4431             :           }
    4432             :       }
    4433             :     else
    4434             :       {
    4435           0 :         if (peer->ttl != 1)
    4436           0 :           return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
    4437             :       }
    4438             :     /* specify MAXTTL on outgoing packets */
    4439           0 :     ret = peer_ebgp_multihop_set (peer, MAXTTL);
    4440           0 :     if (ret != 0)
    4441           0 :       return ret;
    4442             :   }
    4443             :   
    4444           0 :   peer->gtsm_hops = gtsm_hops;
    4445             : 
    4446           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    4447             :     {
    4448           0 :       if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
    4449           0 :         sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
    4450             :     }
    4451             :   else
    4452             :     {
    4453           0 :       group = peer->group;
    4454           0 :       for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    4455             :         {
    4456           0 :           if (peer->sort == BGP_PEER_IBGP)
    4457           0 :             continue;
    4458             : 
    4459           0 :           peer->gtsm_hops = group->conf->gtsm_hops;
    4460             : 
    4461             :           /* Change setting of existing peer
    4462             :            *   established then change value (may break connectivity)
    4463             :            *   not established yet (teardown session and restart)
    4464             :            *   no session then do nothing (will get handled by next connection)
    4465             :            */
    4466           0 :           if (peer->status == Established)
    4467             :             {
    4468           0 :               if (peer->fd >= 0 && peer->gtsm_hops != 0)
    4469           0 :                 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
    4470           0 :                                 MAXTTL + 1 - peer->gtsm_hops);
    4471             :             }
    4472           0 :           else if (peer->status < Established)
    4473             :             {
    4474           0 :               if (BGP_DEBUG (events, EVENTS))
    4475           0 :                 zlog_debug ("%s Min-ttl changed", peer->host);
    4476           0 :               BGP_EVENT_ADD (peer, BGP_Stop);
    4477             :             }
    4478             :         }
    4479             :     }
    4480             : 
    4481           0 :   return 0;
    4482             : }
    4483             : 
    4484             : int
    4485           0 : peer_ttl_security_hops_unset (struct peer *peer)
    4486             : {
    4487             :   struct peer_group *group;
    4488             :   struct listnode *node, *nnode;
    4489             :   struct peer *opeer;
    4490             : 
    4491           0 :   zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
    4492             : 
    4493           0 :   if (peer->sort == BGP_PEER_IBGP)
    4494           0 :       return 0;
    4495             : 
    4496             :   /* if a peer-group member, then reset to peer-group default rather than 0 */
    4497           0 :   if (peer_group_active (peer))
    4498           0 :     peer->gtsm_hops = peer->group->conf->gtsm_hops;
    4499             :   else
    4500           0 :     peer->gtsm_hops = 0;
    4501             : 
    4502           0 :   opeer = peer;
    4503           0 :   if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    4504             :     {
    4505           0 :       if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
    4506           0 :         sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
    4507             :     }
    4508             :   else
    4509             :     {
    4510           0 :       group = peer->group;
    4511           0 :       for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
    4512             :         {
    4513           0 :           if (peer->sort == BGP_PEER_IBGP)
    4514           0 :             continue;
    4515             : 
    4516           0 :           peer->gtsm_hops = 0;
    4517             :           
    4518           0 :           if (peer->fd >= 0)
    4519           0 :             sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
    4520             :         }
    4521             :     }
    4522             : 
    4523           0 :   return peer_ebgp_multihop_unset (opeer);
    4524             : }
    4525             : 
    4526             : int
    4527           0 : peer_clear (struct peer *peer)
    4528             : {
    4529           0 :   if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
    4530             :     {
    4531           0 :       if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
    4532             :         {
    4533           0 :           UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
    4534           0 :           if (peer->t_pmax_restart)
    4535             :             {
    4536           0 :               BGP_TIMER_OFF (peer->t_pmax_restart);
    4537           0 :               if (BGP_DEBUG (events, EVENTS))
    4538           0 :                 zlog_debug ("%s Maximum-prefix restart timer canceled",
    4539             :                             peer->host);
    4540             :             }
    4541           0 :           BGP_EVENT_ADD (peer, BGP_Start);
    4542           0 :           return 0;
    4543             :         }
    4544             : 
    4545           0 :       peer->v_start = BGP_INIT_START_TIMER;
    4546           0 :       if (peer->status == Established)
    4547           0 :         bgp_notify_send (peer, BGP_NOTIFY_CEASE,
    4548             :                          BGP_NOTIFY_CEASE_ADMIN_RESET);
    4549             :       else
    4550           0 :         BGP_EVENT_ADD (peer, BGP_Stop);
    4551             :     }
    4552           0 :   return 0;
    4553             : }
    4554             : 
    4555             : int
    4556           0 : peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
    4557             :                  enum bgp_clear_type stype)
    4558             : {
    4559           0 :   if (peer->status != Established)
    4560           0 :     return 0;
    4561             : 
    4562           0 :   if (! peer->afc[afi][safi])
    4563           0 :     return BGP_ERR_AF_UNCONFIGURED;
    4564             : 
    4565           0 :   if (stype == BGP_CLEAR_SOFT_RSCLIENT)
    4566             :     {
    4567           0 :       if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
    4568           0 :         return 0;
    4569           0 :       bgp_check_local_routes_rsclient (peer, afi, safi);
    4570           0 :       bgp_soft_reconfig_rsclient (peer, afi, safi);
    4571             :     }
    4572             : 
    4573           0 :   if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
    4574           0 :     bgp_announce_route (peer, afi, safi);
    4575             : 
    4576           0 :   if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
    4577             :     {
    4578           0 :       if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
    4579           0 :           && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
    4580           0 :               || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
    4581             :         {
    4582           0 :           struct bgp_filter *filter = &peer->filter[afi][safi];
    4583             :           u_char prefix_type;
    4584             : 
    4585           0 :           if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
    4586           0 :             prefix_type = ORF_TYPE_PREFIX;
    4587             :           else
    4588           0 :             prefix_type = ORF_TYPE_PREFIX_OLD;
    4589             : 
    4590           0 :           if (filter->plist[FILTER_IN].plist)
    4591             :             {
    4592           0 :               if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
    4593           0 :                 bgp_route_refresh_send (peer, afi, safi,
    4594             :                                         prefix_type, REFRESH_DEFER, 1);
    4595           0 :               bgp_route_refresh_send (peer, afi, safi, prefix_type,
    4596             :                                       REFRESH_IMMEDIATE, 0);
    4597             :             }
    4598             :           else
    4599             :             {
    4600           0 :               if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
    4601           0 :                 bgp_route_refresh_send (peer, afi, safi,
    4602             :                                         prefix_type, REFRESH_IMMEDIATE, 1);
    4603             :               else
    4604           0 :                 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
    4605             :             }
    4606           0 :           return 0;
    4607             :         }
    4608             :     }
    4609             : 
    4610           0 :   if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
    4611           0 :       || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
    4612             :     {
    4613             :       /* If neighbor has soft reconfiguration inbound flag.
    4614             :          Use Adj-RIB-In database. */
    4615           0 :       if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
    4616           0 :         bgp_soft_reconfig_in (peer, afi, safi);
    4617             :       else
    4618             :         {
    4619             :           /* If neighbor has route refresh capability, send route refresh
    4620             :              message to the peer. */
    4621           0 :           if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
    4622           0 :               || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
    4623           0 :             bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
    4624             :           else
    4625           0 :             return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
    4626             :         }
    4627             :     }
    4628           0 :   return 0;
    4629             : }
    4630             : 
    4631             : /* Display peer uptime.*/
    4632             : /* XXX: why does this function return char * when it takes buffer? */
    4633             : char *
    4634           0 : peer_uptime (time_t uptime2, char *buf, size_t len)
    4635             : {
    4636             :   time_t uptime1;
    4637             :   struct tm *tm;
    4638             : 
    4639             :   /* Check buffer length. */
    4640           0 :   if (len < BGP_UPTIME_LEN)
    4641             :     {
    4642           0 :       zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
    4643             :       /* XXX: should return status instead of buf... */
    4644           0 :       snprintf (buf, len, "<error> "); 
    4645           0 :       return buf;
    4646             :     }
    4647             : 
    4648             :   /* If there is no connection has been done before print `never'. */
    4649           0 :   if (uptime2 == 0)
    4650             :     {
    4651           0 :       snprintf (buf, len, "never   ");
    4652           0 :       return buf;
    4653             :     }
    4654             : 
    4655             :   /* Get current time. */
    4656           0 :   uptime1 = bgp_clock ();
    4657           0 :   uptime1 -= uptime2;
    4658           0 :   tm = gmtime (&uptime1);
    4659             : 
    4660             :   /* Making formatted timer strings. */
    4661             : #define ONE_DAY_SECOND 60*60*24
    4662             : #define ONE_WEEK_SECOND 60*60*24*7
    4663             : 
    4664           0 :   if (uptime1 < ONE_DAY_SECOND)
    4665           0 :     snprintf (buf, len, "%02d:%02d:%02d", 
    4666             :               tm->tm_hour, tm->tm_min, tm->tm_sec);
    4667           0 :   else if (uptime1 < ONE_WEEK_SECOND)
    4668           0 :     snprintf (buf, len, "%dd%02dh%02dm", 
    4669             :               tm->tm_yday, tm->tm_hour, tm->tm_min);
    4670             :   else
    4671           0 :     snprintf (buf, len, "%02dw%dd%02dh", 
    4672           0 :               tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
    4673           0 :   return buf;
    4674             : }
    4675             : 
    4676             : static void
    4677           0 : bgp_config_write_filter (struct vty *vty, struct peer *peer,
    4678             :                          afi_t afi, safi_t safi)
    4679             : {
    4680             :   struct bgp_filter *filter;
    4681           0 :   struct bgp_filter *gfilter = NULL;
    4682             :   char *addr;
    4683           0 :   int in = FILTER_IN;
    4684           0 :   int out = FILTER_OUT;
    4685             : 
    4686           0 :   addr = peer->host;
    4687           0 :   filter = &peer->filter[afi][safi];
    4688           0 :   if (peer->af_group[afi][safi])
    4689           0 :     gfilter = &peer->group->conf->filter[afi][safi];
    4690             : 
    4691             :   /* distribute-list. */
    4692           0 :   if (filter->dlist[in].name)
    4693           0 :     if (! gfilter || ! gfilter->dlist[in].name
    4694           0 :         || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
    4695           0 :     vty_out (vty, " neighbor %s distribute-list %s in%s", addr, 
    4696           0 :              filter->dlist[in].name, VTY_NEWLINE);
    4697           0 :   if (filter->dlist[out].name && ! gfilter)
    4698           0 :     vty_out (vty, " neighbor %s distribute-list %s out%s", addr, 
    4699           0 :              filter->dlist[out].name, VTY_NEWLINE);
    4700             : 
    4701             :   /* prefix-list. */
    4702           0 :   if (filter->plist[in].name)
    4703           0 :     if (! gfilter || ! gfilter->plist[in].name
    4704           0 :         || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
    4705           0 :     vty_out (vty, " neighbor %s prefix-list %s in%s", addr, 
    4706           0 :              filter->plist[in].name, VTY_NEWLINE);
    4707           0 :   if (filter->plist[out].name && ! gfilter)
    4708           0 :     vty_out (vty, " neighbor %s prefix-list %s out%s", addr, 
    4709           0 :              filter->plist[out].name, VTY_NEWLINE);
    4710             : 
    4711             :   /* route-map. */
    4712           0 :   if (filter->map[RMAP_IN].name)
    4713           0 :     if (! gfilter || ! gfilter->map[RMAP_IN].name
    4714           0 :        || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
    4715           0 :       vty_out (vty, " neighbor %s route-map %s in%s", addr, 
    4716           0 :               filter->map[RMAP_IN].name, VTY_NEWLINE);
    4717           0 :   if (filter->map[RMAP_OUT].name && ! gfilter)
    4718           0 :     vty_out (vty, " neighbor %s route-map %s out%s", addr, 
    4719           0 :             filter->map[RMAP_OUT].name, VTY_NEWLINE);
    4720           0 :   if (filter->map[RMAP_IMPORT].name && ! gfilter)
    4721           0 :     vty_out (vty, " neighbor %s route-map %s import%s", addr,
    4722           0 :         filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
    4723           0 :   if (filter->map[RMAP_EXPORT].name)
    4724           0 :     if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
    4725           0 :     || strcmp (filter->map[RMAP_EXPORT].name,
    4726           0 :                     gfilter->map[RMAP_EXPORT].name) != 0)
    4727           0 :     vty_out (vty, " neighbor %s route-map %s export%s", addr,
    4728           0 :         filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
    4729             : 
    4730             :   /* unsuppress-map */
    4731           0 :   if (filter->usmap.name && ! gfilter)
    4732           0 :     vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
    4733           0 :              filter->usmap.name, VTY_NEWLINE);
    4734             : 
    4735             :   /* filter-list. */
    4736           0 :   if (filter->aslist[in].name)
    4737           0 :     if (! gfilter || ! gfilter->aslist[in].name
    4738           0 :         || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
    4739           0 :       vty_out (vty, " neighbor %s filter-list %s in%s", addr, 
    4740           0 :                filter->aslist[in].name, VTY_NEWLINE);
    4741           0 :   if (filter->aslist[out].name && ! gfilter)
    4742           0 :     vty_out (vty, " neighbor %s filter-list %s out%s", addr, 
    4743           0 :              filter->aslist[out].name, VTY_NEWLINE);
    4744           0 : }
    4745             : 
    4746             : /* BGP peer configuration display function. */
    4747             : static void
    4748           0 : bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
    4749             :                        struct peer *peer, afi_t afi, safi_t safi)
    4750             : {
    4751           0 :   struct peer *g_peer = NULL;
    4752             :   char buf[SU_ADDRSTRLEN];
    4753             :   char *addr;
    4754             : 
    4755           0 :   addr = peer->host;
    4756           0 :   if (peer_group_active (peer))
    4757           0 :     g_peer = peer->group->conf;
    4758             : 
    4759             :   /************************************
    4760             :    ****** Global to the neighbor ******
    4761             :    ************************************/
    4762           0 :   if (afi == AFI_IP && safi == SAFI_UNICAST)
    4763             :     {
    4764             :       /* remote-as. */
    4765           0 :       if (! peer_group_active (peer))
    4766             :         {
    4767           0 :           if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
    4768           0 :             vty_out (vty, " neighbor %s peer-group%s", addr,
    4769           0 :                      VTY_NEWLINE);
    4770           0 :           if (peer->as)
    4771           0 :             vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
    4772           0 :                      VTY_NEWLINE);
    4773             :         }
    4774             :       else
    4775             :         {
    4776           0 :           if (! g_peer->as)
    4777           0 :             vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
    4778           0 :                      VTY_NEWLINE);
    4779           0 :           if (peer->af_group[AFI_IP][SAFI_UNICAST])
    4780           0 :             vty_out (vty, " neighbor %s peer-group %s%s", addr,
    4781           0 :                      peer->group->name, VTY_NEWLINE);
    4782             :         }
    4783             : 
    4784             :       /* local-as. */
    4785           0 :       if (peer->change_local_as)
    4786           0 :         if (! peer_group_active (peer))
    4787           0 :           vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
    4788             :                    peer->change_local_as,
    4789           0 :                    CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
    4790             :                    " no-prepend" : "",
    4791           0 :                    CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
    4792           0 :                    " replace-as" : "", VTY_NEWLINE);
    4793             : 
    4794             :       /* Description. */
    4795           0 :       if (peer->desc)
    4796           0 :         vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
    4797           0 :                  VTY_NEWLINE);
    4798             : 
    4799             :       /* Shutdown. */
    4800           0 :       if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
    4801           0 :         if (! peer_group_active (peer) ||
    4802           0 :             ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
    4803           0 :           vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
    4804             : 
    4805             :       /* Password. */
    4806           0 :       if (peer->password)
    4807           0 :         if (!peer_group_active (peer)
    4808           0 :             || ! g_peer->password
    4809           0 :             || strcmp (peer->password, g_peer->password) != 0)
    4810           0 :           vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
    4811           0 :                    VTY_NEWLINE);
    4812             : 
    4813             :       /* BGP port. */
    4814           0 :       if (peer->port != BGP_PORT_DEFAULT)
    4815           0 :         vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
    4816           0 :                  VTY_NEWLINE);
    4817             : 
    4818             :       /* Local interface name. */
    4819           0 :       if (peer->ifname)
    4820           0 :         vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
    4821           0 :                  VTY_NEWLINE);
    4822             :   
    4823             :       /* Passive. */
    4824           0 :       if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
    4825           0 :         if (! peer_group_active (peer) ||
    4826           0 :             ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
    4827           0 :           vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
    4828             : 
    4829             :       /* EBGP multihop.  */
    4830           0 :       if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
    4831           0 :                    !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
    4832           0 :         if (! peer_group_active (peer) ||
    4833           0 :             g_peer->ttl != peer->ttl)
    4834           0 :           vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
    4835           0 :                    VTY_NEWLINE);
    4836             : 
    4837             :      /* ttl-security hops */
    4838           0 :       if (peer->sort != BGP_PEER_IBGP && peer->gtsm_hops != 0)
    4839           0 :         if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
    4840           0 :           vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
    4841           0 :                    peer->gtsm_hops, VTY_NEWLINE);
    4842             : 
    4843             :       /* disable-connected-check.  */
    4844           0 :       if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
    4845           0 :         if (! peer_group_active (peer) ||
    4846           0 :             ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
    4847           0 :           vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
    4848             : 
    4849             :       /* Update-source. */
    4850           0 :       if (peer->update_if)
    4851           0 :         if (! peer_group_active (peer) || ! g_peer->update_if
    4852           0 :             || strcmp (g_peer->update_if, peer->update_if) != 0)
    4853           0 :           vty_out (vty, " neighbor %s update-source %s%s", addr,
    4854           0 :                    peer->update_if, VTY_NEWLINE);
    4855           0 :       if (peer->update_source)
    4856           0 :         if (! peer_group_active (peer) || ! g_peer->update_source
    4857           0 :             || sockunion_cmp (g_peer->update_source,
    4858             :                               peer->update_source) != 0)
    4859           0 :           vty_out (vty, " neighbor %s update-source %s%s", addr,
    4860             :                    sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
    4861           0 :                    VTY_NEWLINE);
    4862             : 
    4863             :       /* advertisement-interval */
    4864           0 :       if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
    4865           0 :         vty_out (vty, " neighbor %s advertisement-interval %d%s",
    4866           0 :                  addr, peer->v_routeadv, VTY_NEWLINE); 
    4867             : 
    4868             :       /* timers. */
    4869           0 :       if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
    4870           0 :           && ! peer_group_active (peer))
    4871           0 :           vty_out (vty, " neighbor %s timers %d %d%s", addr, 
    4872           0 :           peer->keepalive, peer->holdtime, VTY_NEWLINE);
    4873             : 
    4874           0 :       if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
    4875           0 :           vty_out (vty, " neighbor %s timers connect %d%s", addr, 
    4876           0 :           peer->connect, VTY_NEWLINE);
    4877             : 
    4878             :       /* Default weight. */
    4879           0 :       if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
    4880           0 :         if (! peer_group_active (peer) ||
    4881           0 :             g_peer->weight != peer->weight)
    4882           0 :           vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
    4883           0 :                    VTY_NEWLINE);
    4884             : 
    4885             :       /* Dynamic capability.  */
    4886           0 :       if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
    4887           0 :         if (! peer_group_active (peer) ||
    4888           0 :             ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
    4889           0 :         vty_out (vty, " neighbor %s capability dynamic%s", addr,
    4890           0 :              VTY_NEWLINE);
    4891             : 
    4892             :       /* dont capability negotiation. */
    4893           0 :       if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
    4894           0 :         if (! peer_group_active (peer) ||
    4895           0 :             ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
    4896           0 :         vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
    4897           0 :                  VTY_NEWLINE);
    4898             : 
    4899             :       /* override capability negotiation. */
    4900           0 :       if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
    4901           0 :         if (! peer_group_active (peer) ||
    4902           0 :             ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
    4903           0 :         vty_out (vty, " neighbor %s override-capability%s", addr,
    4904           0 :                  VTY_NEWLINE);
    4905             : 
    4906             :       /* strict capability negotiation. */
    4907           0 :       if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
    4908           0 :         if (! peer_group_active (peer) ||
    4909           0 :             ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
    4910           0 :         vty_out (vty, " neighbor %s strict-capability-match%s", addr,
    4911           0 :              VTY_NEWLINE);
    4912             : 
    4913           0 :       if (! peer->af_group[AFI_IP][SAFI_UNICAST])
    4914             :         {
    4915           0 :           if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
    4916             :             {
    4917           0 :               if (peer->afc[AFI_IP][SAFI_UNICAST])
    4918           0 :                 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
    4919             :             }
    4920             :           else
    4921             :             {
    4922           0 :               if (! peer->afc[AFI_IP][SAFI_UNICAST])
    4923           0 :                 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
    4924             :             }
    4925             :         }
    4926             :     }
    4927             : 
    4928             : 
    4929             :   /************************************
    4930             :    ****** Per AF to the neighbor ******
    4931             :    ************************************/
    4932             : 
    4933           0 :   if (! (afi == AFI_IP && safi == SAFI_UNICAST))
    4934             :     {
    4935           0 :       if (peer->af_group[afi][safi])
    4936           0 :         vty_out (vty, " neighbor %s peer-group %s%s", addr,
    4937           0 :                  peer->group->name, VTY_NEWLINE);
    4938             :       else
    4939           0 :         vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
    4940             :     }
    4941             : 
    4942             :   /* ORF capability.  */
    4943           0 :   if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
    4944           0 :       || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
    4945           0 :     if (! peer->af_group[afi][safi])
    4946             :     {
    4947           0 :       vty_out (vty, " neighbor %s capability orf prefix-list", addr);
    4948             : 
    4949           0 :       if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
    4950           0 :           && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
    4951           0 :         vty_out (vty, " both");
    4952           0 :       else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
    4953           0 :         vty_out (vty, " send");
    4954             :       else
    4955           0 :         vty_out (vty, " receive");
    4956           0 :       vty_out (vty, "%s", VTY_NEWLINE);
    4957             :     }
    4958             : 
    4959             :   /* Route reflector client. */
    4960           0 :   if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
    4961           0 :       && ! peer->af_group[afi][safi])
    4962           0 :     vty_out (vty, " neighbor %s route-reflector-client%s", addr, 
    4963           0 :              VTY_NEWLINE);
    4964             : 
    4965             :   /* Nexthop self. */
    4966           0 :   if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
    4967           0 :       && ! peer->af_group[afi][safi])
    4968           0 :     vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
    4969             : 
    4970             :   /* Remove private AS. */
    4971           0 :   if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
    4972           0 :       && ! peer->af_group[afi][safi])
    4973           0 :     vty_out (vty, " neighbor %s remove-private-AS%s",
    4974           0 :              addr, VTY_NEWLINE);
    4975             : 
    4976             :   /* send-community print. */
    4977           0 :   if (! peer->af_group[afi][safi])
    4978             :     {
    4979           0 :       if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
    4980             :         {
    4981           0 :           if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
    4982           0 :               && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
    4983           0 :             vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
    4984           0 :           else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))  
    4985           0 :             vty_out (vty, " neighbor %s send-community extended%s",
    4986           0 :                      addr, VTY_NEWLINE);
    4987           0 :           else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
    4988           0 :             vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
    4989             :         }
    4990             :       else
    4991             :         {
    4992           0 :           if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
    4993           0 :               && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
    4994           0 :             vty_out (vty, " no neighbor %s send-community both%s",
    4995           0 :                      addr, VTY_NEWLINE);
    4996           0 :           else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
    4997           0 :             vty_out (vty, " no neighbor %s send-community extended%s",
    4998           0 :                      addr, VTY_NEWLINE);
    4999           0 :           else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
    5000           0 :             vty_out (vty, " no neighbor %s send-community%s",
    5001           0 :                      addr, VTY_NEWLINE);
    5002             :         }
    5003             :     }
    5004             : 
    5005             :   /* Default information */
    5006           0 :   if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
    5007           0 :       && ! peer->af_group[afi][safi])
    5008             :     {
    5009           0 :       vty_out (vty, " neighbor %s default-originate", addr);
    5010           0 :       if (peer->default_rmap[afi][safi].name)
    5011           0 :         vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
    5012           0 :       vty_out (vty, "%s", VTY_NEWLINE);
    5013             :     }
    5014             : 
    5015             :   /* Soft reconfiguration inbound. */
    5016           0 :   if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
    5017           0 :     if (! peer->af_group[afi][safi] ||
    5018           0 :         ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
    5019           0 :     vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
    5020           0 :              VTY_NEWLINE);
    5021             : 
    5022             :   /* maximum-prefix. */
    5023           0 :   if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
    5024           0 :     if (! peer->af_group[afi][safi]
    5025           0 :         || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
    5026           0 :         || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
    5027           0 :         || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
    5028           0 :            != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
    5029             :       {
    5030           0 :         vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
    5031           0 :         if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
    5032           0 :           vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
    5033           0 :         if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
    5034           0 :           vty_out (vty, " warning-only");
    5035           0 :         if (peer->pmax_restart[afi][safi])
    5036           0 :           vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
    5037           0 :         vty_out (vty, "%s", VTY_NEWLINE);
    5038             :       }
    5039             : 
    5040             :   /* Route server client. */
    5041           0 :   if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
    5042           0 :       && ! peer->af_group[afi][safi])
    5043           0 :     vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
    5044             : 
    5045             :   /* Nexthop-local unchanged. */
    5046           0 :   if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
    5047           0 :       && ! peer->af_group[afi][safi])
    5048           0 :     vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
    5049             : 
    5050             :   /* Allow AS in.  */
    5051           0 :   if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
    5052           0 :     if (! peer_group_active (peer)
    5053           0 :         || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
    5054           0 :         || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
    5055             :       {
    5056           0 :         if (peer->allowas_in[afi][safi] == 3)
    5057           0 :           vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
    5058             :         else
    5059           0 :           vty_out (vty, " neighbor %s allowas-in %d%s", addr,
    5060           0 :                    peer->allowas_in[afi][safi], VTY_NEWLINE);
    5061             :       }
    5062             : 
    5063             :   /* Filter. */
    5064           0 :   bgp_config_write_filter (vty, peer, afi, safi);
    5065             : 
    5066             :   /* atribute-unchanged. */
    5067           0 :   if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
    5068           0 :       || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
    5069           0 :       || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
    5070           0 :       && ! peer->af_group[afi][safi])
    5071             :     {
    5072           0 :       if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
    5073           0 :           && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
    5074           0 :           && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
    5075           0 :         vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
    5076             :       else
    5077           0 :         vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr, 
    5078           0 :              (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
    5079             :              " as-path" : "",
    5080           0 :              (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
    5081             :              " next-hop" : "",
    5082           0 :              (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
    5083           0 :              " med" : "", VTY_NEWLINE);
    5084             :     }
    5085           0 : }
    5086             : 
    5087             : /* Display "address-family" configuration header. */
    5088             : void
    5089           0 : bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
    5090             :                                 int *write)
    5091             : {
    5092           0 :   if (*write)
    5093           0 :     return;
    5094             : 
    5095           0 :   if (afi == AFI_IP && safi == SAFI_UNICAST)
    5096           0 :     return;
    5097             : 
    5098           0 :   vty_out (vty, "!%s address-family ", VTY_NEWLINE);
    5099             : 
    5100           0 :   if (afi == AFI_IP)
    5101             :     {
    5102           0 :       if (safi == SAFI_MULTICAST)
    5103           0 :         vty_out (vty, "ipv4 multicast");
    5104           0 :       else if (safi == SAFI_MPLS_VPN)
    5105           0 :         vty_out (vty, "vpnv4 unicast");
    5106             :     }
    5107           0 :   else if (afi == AFI_IP6)
    5108             :     {
    5109           0 :       vty_out (vty, "ipv6");
    5110             :       
    5111           0 :       if (safi == SAFI_MULTICAST)
    5112           0 :         vty_out (vty, " multicast");
    5113             :     }
    5114             : 
    5115           0 :   vty_out (vty, "%s", VTY_NEWLINE);
    5116             : 
    5117           0 :   *write = 1;
    5118             : }
    5119             : 
    5120             : /* Address family based peer configuration display.  */
    5121             : static int
    5122           0 : bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
    5123             :                          safi_t safi)
    5124             : {
    5125           0 :   int write = 0;
    5126             :   struct peer *peer;
    5127             :   struct peer_group *group;
    5128             :   struct listnode *node, *nnode;
    5129             : 
    5130           0 :   bgp_config_write_network (vty, bgp, afi, safi, &write);
    5131             : 
    5132           0 :   bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
    5133             : 
    5134           0 :   for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
    5135             :     {
    5136           0 :       if (group->conf->afc[afi][safi])
    5137             :         {
    5138           0 :           bgp_config_write_family_header (vty, afi, safi, &write);
    5139           0 :           bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
    5140             :         }
    5141             :     }
    5142           0 :   for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
    5143             :     {
    5144           0 :       if (peer->afc[afi][safi])
    5145             :         {
    5146           0 :           if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
    5147             :             {
    5148           0 :               bgp_config_write_family_header (vty, afi, safi, &write);
    5149           0 :               bgp_config_write_peer (vty, bgp, peer, afi, safi);
    5150             :             }
    5151             :         }
    5152             :     }
    5153             : 
    5154           0 :   bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
    5155             : 
    5156           0 :   if (write)
    5157           0 :     vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
    5158             : 
    5159           0 :   return write;
    5160             : }
    5161             : 
    5162             : int
    5163           0 : bgp_config_write (struct vty *vty)
    5164             : {
    5165           0 :   int write = 0;
    5166             :   struct bgp *bgp;
    5167             :   struct peer_group *group;
    5168             :   struct peer *peer;
    5169             :   struct listnode *node, *nnode;
    5170             :   struct listnode *mnode, *mnnode;
    5171             : 
    5172             :   /* BGP Multiple instance. */
    5173           0 :   if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
    5174             :     {    
    5175           0 :       vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
    5176           0 :       write++;
    5177             :     }
    5178             : 
    5179             :   /* BGP Config type. */
    5180           0 :   if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
    5181             :     {    
    5182           0 :       vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
    5183           0 :       write++;
    5184             :     }
    5185             : 
    5186             :   /* BGP configuration. */
    5187           0 :   for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
    5188             :     {
    5189           0 :       if (write)
    5190           0 :         vty_out (vty, "!%s", VTY_NEWLINE);
    5191             : 
    5192             :       /* Router bgp ASN */
    5193           0 :       vty_out (vty, "router bgp %u", bgp->as);
    5194             : 
    5195           0 :       if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
    5196             :         {
    5197           0 :           if (bgp->name)
    5198           0 :             vty_out (vty, " view %s", bgp->name);
    5199             :         }
    5200           0 :       vty_out (vty, "%s", VTY_NEWLINE);
    5201             : 
    5202             :       /* No Synchronization */
    5203           0 :       if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
    5204           0 :         vty_out (vty, " no synchronization%s", VTY_NEWLINE);
    5205             : 
    5206             :       /* BGP fast-external-failover. */
    5207           0 :       if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
    5208           0 :         vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE); 
    5209             : 
    5210             :       /* BGP router ID. */
    5211           0 :       if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
    5212           0 :         vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id), 
    5213           0 :                  VTY_NEWLINE);
    5214             : 
    5215             :       /* BGP log-neighbor-changes. */
    5216           0 :       if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
    5217           0 :         vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
    5218             : 
    5219             :       /* BGP configuration. */
    5220           0 :       if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
    5221           0 :         vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
    5222             : 
    5223             :       /* BGP default ipv4-unicast. */
    5224           0 :       if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
    5225           0 :         vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
    5226             : 
    5227             :       /* BGP default local-preference. */
    5228           0 :       if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
    5229           0 :         vty_out (vty, " bgp default local-preference %d%s",
    5230           0 :                  bgp->default_local_pref, VTY_NEWLINE);
    5231             : 
    5232             :       /* BGP client-to-client reflection. */
    5233           0 :       if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
    5234           0 :         vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
    5235             :       
    5236             :       /* BGP cluster ID. */
    5237           0 :       if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
    5238           0 :         vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
    5239           0 :                  VTY_NEWLINE);
    5240             : 
    5241             :       /* Confederation identifier*/
    5242           0 :       if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
    5243           0 :        vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
    5244           0 :                 VTY_NEWLINE);
    5245             : 
    5246             :       /* Confederation peer */
    5247           0 :       if (bgp->confed_peers_cnt > 0)
    5248             :         {
    5249             :           int i;
    5250             : 
    5251           0 :           vty_out (vty, " bgp confederation peers");
    5252             : 
    5253           0 :          for (i = 0; i < bgp->confed_peers_cnt; i++)
    5254           0 :            vty_out(vty, " %u", bgp->confed_peers[i]);
    5255             : 
    5256           0 :           vty_out (vty, "%s", VTY_NEWLINE);
    5257             :         }
    5258             : 
    5259             :       /* BGP enforce-first-as. */
    5260           0 :       if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
    5261           0 :         vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
    5262             : 
    5263             :       /* BGP deterministic-med. */
    5264           0 :       if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
    5265           0 :         vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
    5266             : 
    5267             :       /* BGP graceful-restart. */
    5268           0 :       if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
    5269           0 :         vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
    5270           0 :                  bgp->stalepath_time, VTY_NEWLINE);
    5271           0 :       if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
    5272           0 :        vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
    5273             : 
    5274             :       /* BGP bestpath method. */
    5275           0 :       if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
    5276           0 :         vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
    5277           0 :       if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
    5278           0 :         vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
    5279           0 :       if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
    5280           0 :         vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
    5281           0 :       if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
    5282           0 :           || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
    5283             :         {
    5284           0 :           vty_out (vty, " bgp bestpath med");
    5285           0 :           if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
    5286           0 :             vty_out (vty, " confed");
    5287           0 :           if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
    5288           0 :             vty_out (vty, " missing-as-worst");
    5289           0 :           vty_out (vty, "%s", VTY_NEWLINE);
    5290             :         }
    5291             : 
    5292             :       /* BGP network import check. */
    5293           0 :       if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
    5294           0 :         vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
    5295             : 
    5296             :       /* BGP scan interval. */
    5297           0 :       bgp_config_write_scan_time (vty);
    5298             : 
    5299             :       /* BGP flag dampening. */
    5300           0 :       if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
    5301             :           BGP_CONFIG_DAMPENING))
    5302           0 :         bgp_config_write_damp (vty);
    5303             : 
    5304             :       /* BGP static route configuration. */
    5305           0 :       bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
    5306             : 
    5307             :       /* BGP redistribute configuration. */
    5308           0 :       bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
    5309             : 
    5310             :       /* BGP timers configuration. */
    5311           0 :       if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
    5312           0 :           && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
    5313           0 :         vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive, 
    5314           0 :                  bgp->default_holdtime, VTY_NEWLINE);
    5315             : 
    5316             :       /* peer-group */
    5317           0 :       for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
    5318             :         {
    5319           0 :           bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
    5320             :         }
    5321             : 
    5322             :       /* Normal neighbor configuration. */
    5323           0 :       for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
    5324             :         {
    5325           0 :           if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
    5326           0 :             bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
    5327             :         }
    5328             : 
    5329             :       /* maximum-paths */
    5330           0 :       bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
    5331             : 
    5332             :       /* Distance configuration. */
    5333           0 :       bgp_config_write_distance (vty, bgp);
    5334             :       
    5335             :       /* No auto-summary */
    5336           0 :       if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
    5337           0 :         vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
    5338             : 
    5339             :       /* IPv4 multicast configuration.  */
    5340           0 :       write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
    5341             : 
    5342             :       /* IPv4 VPN configuration.  */
    5343           0 :       write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
    5344             : 
    5345             :       /* IPv6 unicast configuration.  */
    5346           0 :       write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
    5347             : 
    5348             :       /* IPv6 multicast configuration.  */
    5349           0 :       write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
    5350             : 
    5351           0 :       write++;
    5352             :     }
    5353           0 :   return write;
    5354             : }
    5355             : 
    5356             : void
    5357           4 : bgp_master_init (void)
    5358             : {
    5359           4 :   memset (&bgp_master, 0, sizeof (struct bgp_master));
    5360             : 
    5361           4 :   bm = &bgp_master;
    5362           4 :   bm->bgp = list_new ();
    5363           4 :   bm->listen_sockets = list_new ();
    5364           4 :   bm->port = BGP_PORT_DEFAULT;
    5365           4 :   bm->master = thread_master_create ();
    5366           4 :   bm->start_time = bgp_clock ();
    5367           4 : }
    5368             : 
    5369             : 
    5370             : void
    5371           0 : bgp_init (void)
    5372             : {
    5373             :   /* BGP VTY commands installation.  */
    5374           0 :   bgp_vty_init ();
    5375             : 
    5376             :   /* Init zebra. */
    5377           0 :   bgp_zebra_init ();
    5378             : 
    5379             :   /* BGP inits. */
    5380           0 :   bgp_attr_init ();
    5381           0 :   bgp_debug_init ();
    5382           0 :   bgp_dump_init ();
    5383           0 :   bgp_route_init ();
    5384           0 :   bgp_route_map_init ();
    5385           0 :   bgp_address_init ();
    5386           0 :   bgp_scan_init ();
    5387           0 :   bgp_mplsvpn_init ();
    5388             : 
    5389             :   /* Access list initialize. */
    5390           0 :   access_list_init ();
    5391           0 :   access_list_add_hook (peer_distribute_update);
    5392           0 :   access_list_delete_hook (peer_distribute_update);
    5393             : 
    5394             :   /* Filter list initialize. */
    5395           0 :   bgp_filter_init ();
    5396           0 :   as_list_add_hook (peer_aslist_update);
    5397           0 :   as_list_delete_hook (peer_aslist_update);
    5398             : 
    5399             :   /* Prefix list initialize.*/
    5400           0 :   prefix_list_init ();
    5401           0 :   prefix_list_add_hook (peer_prefix_list_update);
    5402           0 :   prefix_list_delete_hook (peer_prefix_list_update);
    5403             : 
    5404             :   /* Community list initialize. */
    5405           0 :   bgp_clist = community_list_init ();
    5406             : 
    5407             : #ifdef HAVE_SNMP
    5408             :   bgp_snmp_init ();
    5409             : #endif /* HAVE_SNMP */
    5410           0 : }
    5411             : 
    5412             : void
    5413           0 : bgp_terminate (void)
    5414             : {
    5415             :   struct bgp *bgp;
    5416             :   struct peer *peer;
    5417             :   struct listnode *node, *nnode;
    5418             :   struct listnode *mnode, *mnnode;
    5419             : 
    5420           0 :   for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
    5421           0 :     for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
    5422           0 :       if (peer->status == Established)
    5423           0 :           bgp_notify_send (peer, BGP_NOTIFY_CEASE,
    5424             :                            BGP_NOTIFY_CEASE_PEER_UNCONFIG);
    5425             :   
    5426           0 :   bgp_cleanup_routes ();
    5427             :   
    5428           0 :   if (bm->process_main_queue)
    5429             :     {
    5430           0 :       work_queue_free (bm->process_main_queue);
    5431           0 :       bm->process_main_queue = NULL;
    5432             :     }
    5433           0 :   if (bm->process_rsclient_queue)
    5434             :     {
    5435           0 :       work_queue_free (bm->process_rsclient_queue);
    5436           0 :       bm->process_rsclient_queue = NULL;
    5437             :     }
    5438           0 : }

Generated by: LCOV version 1.10