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

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

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