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