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