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