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