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