Annotation of embedaddon/quagga/bgpd/bgpd.c, revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>