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