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