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