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