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