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