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