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