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