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