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