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