]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgpd.c
bgpd: Validate large-community-list against UINT_MAX
[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())
d62a17ae 254 bgp_evpn_handle_router_id_update(bgp, TRUE);
2d48ee25 255
636f7608
CS
256 vpn_handle_router_id_update(bgp, TRUE);
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())
d62a17ae 273 bgp_evpn_handle_router_id_update(bgp, FALSE);
2d48ee25 274
636f7608
CS
275 vpn_handle_router_id_update(bgp, FALSE);
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. */
1591 peer->ttl = (peer->sort == BGP_PEER_IBGP) ? MAXTTL : 1;
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)
1678 peer->ttl = 1;
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;
2438 group->conf->ttl = 1;
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
d62a17ae 2463 /* TTL */
2464 peer->ttl = conf->ttl;
518f0eb1 2465
d62a17ae 2466 /* GTSM hops */
2467 peer->gtsm_hops = conf->gtsm_hops;
ad12dde6 2468
4c391142
PM
2469 /* peer flags apply */
2470 flags_tmp = conf->flags & ~peer->flags_override;
2471 flags_tmp ^= conf->flags_invert ^ peer->flags_invert;
2472 flags_tmp &= ~peer->flags_override;
2473
2474 UNSET_FLAG(peer->flags, ~peer->flags_override);
2475 SET_FLAG(peer->flags, flags_tmp);
2476 SET_FLAG(peer->flags_invert, conf->flags_invert);
ad4cbda1 2477
d62a17ae 2478 /* peer timers apply */
b90a8e13
PM
2479 if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_TIMER)) {
2480 PEER_ATTR_INHERIT(peer, group, holdtime);
2481 PEER_ATTR_INHERIT(peer, group, keepalive);
2482 }
6aeb9e78 2483
b90a8e13
PM
2484 if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_TIMER_CONNECT)) {
2485 PEER_ATTR_INHERIT(peer, group, connect);
2486 if (CHECK_FLAG(conf->flags, PEER_FLAG_TIMER_CONNECT))
2487 peer->v_connect = conf->connect;
2488 else
2489 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
2490 }
2491
2492 /* advertisement-interval apply */
2493 if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_ROUTEADV)) {
2494 PEER_ATTR_INHERIT(peer, group, routeadv);
2495 if (CHECK_FLAG(conf->flags, PEER_FLAG_ROUTEADV))
2496 peer->v_routeadv = conf->routeadv;
2497 else
2498 peer->v_routeadv = (peer_sort(peer) == BGP_PEER_IBGP)
2499 ? BGP_DEFAULT_IBGP_ROUTEADV
2500 : BGP_DEFAULT_EBGP_ROUTEADV;
2501 }
718e3744 2502
d62a17ae 2503 /* password apply */
a14810f4
PM
2504 if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_PASSWORD))
2505 PEER_STR_ATTR_INHERIT(peer, group, password,
2506 MTYPE_PEER_PASSWORD);
718e3744 2507
d62a17ae 2508 if (!BGP_PEER_SU_UNSPEC(peer))
2509 bgp_md5_set(peer);
d4a7a753 2510
d62a17ae 2511 /* update-source apply */
a14810f4
PM
2512 if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_UPDATE_SOURCE)) {
2513 if (conf->update_source) {
d62a17ae 2514 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
a14810f4
PM
2515 PEER_SU_ATTR_INHERIT(peer, group, update_source);
2516 } else if (conf->update_if) {
d62a17ae 2517 sockunion_free(peer->update_source);
a14810f4
PM
2518 PEER_STR_ATTR_INHERIT(peer, group, update_if,
2519 MTYPE_PEER_UPDATE_SOURCE);
d62a17ae 2520 }
d62a17ae 2521 }
cd92e548 2522
d62a17ae 2523 bgp_bfd_peer_group2peer_copy(conf, peer);
ad4cbda1 2524}
718e3744 2525
d62a17ae 2526/* Peer group's remote AS configuration. */
2527int peer_group_remote_as(struct bgp *bgp, const char *group_name, as_t *as,
2528 int as_type)
f14e6fdb 2529{
d62a17ae 2530 struct peer_group *group;
2531 struct peer *peer;
2532 struct listnode *node, *nnode;
f14e6fdb 2533
d62a17ae 2534 group = peer_group_lookup(bgp, group_name);
2535 if (!group)
2536 return -1;
f14e6fdb 2537
d62a17ae 2538 if ((as_type == group->conf->as_type) && (group->conf->as == *as))
2539 return 0;
f14e6fdb 2540
f14e6fdb 2541
d62a17ae 2542 /* When we setup peer-group AS number all peer group member's AS
2543 number must be updated to same number. */
2544 peer_as_change(group->conf, *as, as_type);
f14e6fdb 2545
d62a17ae 2546 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
2547 if (((peer->as_type == AS_SPECIFIED) && peer->as != *as)
2548 || (peer->as_type != as_type))
2549 peer_as_change(peer, *as, as_type);
2550 }
f14e6fdb 2551
d62a17ae 2552 return 0;
f14e6fdb
DS
2553}
2554
d62a17ae 2555int peer_group_delete(struct peer_group *group)
f14e6fdb 2556{
d62a17ae 2557 struct bgp *bgp;
2558 struct peer *peer;
2559 struct prefix *prefix;
2560 struct peer *other;
2561 struct listnode *node, *nnode;
2562 afi_t afi;
f14e6fdb 2563
d62a17ae 2564 bgp = group->bgp;
f14e6fdb 2565
d62a17ae 2566 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
2567 other = peer->doppelganger;
2568 peer_delete(peer);
2569 if (other && other->status != Deleted) {
2570 other->group = NULL;
2571 peer_delete(other);
2572 }
2573 }
6a154c88 2574 list_delete(&group->peer);
f14e6fdb 2575
d62a17ae 2576 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
2577 for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, nnode,
2578 prefix)) {
2579 prefix_free(prefix);
2580 }
6a154c88 2581 list_delete(&group->listen_range[afi]);
d62a17ae 2582 }
f14e6fdb 2583
d62a17ae 2584 XFREE(MTYPE_PEER_GROUP_HOST, group->name);
2585 group->name = NULL;
0299c004 2586
d62a17ae 2587 bfd_info_free(&(group->conf->bfd_info));
f14e6fdb 2588
d62a17ae 2589 group->conf->group = NULL;
2590 peer_delete(group->conf);
f14e6fdb 2591
d62a17ae 2592 /* Delete from all peer_group list. */
2593 listnode_delete(bgp->group, group);
f14e6fdb 2594
d62a17ae 2595 peer_group_free(group);
f14e6fdb 2596
d62a17ae 2597 return 0;
2598}
f14e6fdb 2599
d62a17ae 2600int peer_group_remote_as_delete(struct peer_group *group)
2601{
2602 struct peer *peer, *other;
2603 struct listnode *node, *nnode;
f14e6fdb 2604
d62a17ae 2605 if ((group->conf->as_type == AS_UNSPECIFIED)
2606 || ((!group->conf->as) && (group->conf->as_type == AS_SPECIFIED)))
2607 return 0;
f14e6fdb 2608
d62a17ae 2609 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
2610 other = peer->doppelganger;
f14e6fdb 2611
d62a17ae 2612 peer_delete(peer);
f14e6fdb 2613
d62a17ae 2614 if (other && other->status != Deleted) {
2615 other->group = NULL;
2616 peer_delete(other);
2617 }
2618 }
2619 list_delete_all_node(group->peer);
f14e6fdb 2620
d62a17ae 2621 group->conf->as = 0;
2622 group->conf->as_type = AS_UNSPECIFIED;
f14e6fdb 2623
d62a17ae 2624 return 0;
f14e6fdb 2625}
d62a17ae 2626
2627int peer_group_listen_range_add(struct peer_group *group, struct prefix *range)
f14e6fdb 2628{
d62a17ae 2629 struct prefix *prefix;
2630 struct listnode *node, *nnode;
2631 afi_t afi;
f14e6fdb 2632
d62a17ae 2633 afi = family2afi(range->family);
f14e6fdb 2634
d62a17ae 2635 /* Group needs remote AS configured. */
2636 if (group->conf->as_type == AS_UNSPECIFIED)
2637 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
718e3744 2638
d62a17ae 2639 /* Ensure no duplicates. Currently we don't care about overlaps. */
2640 for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, nnode, prefix)) {
2641 if (prefix_same(range, prefix))
2642 return 0;
2643 }
2644
2645 prefix = prefix_new();
2646 prefix_copy(prefix, range);
2647 listnode_add(group->listen_range[afi], prefix);
9e7d9a61
QY
2648
2649 /* Update passwords for new ranges */
2650 if (group->conf->password)
2651 bgp_md5_set_prefix(prefix, group->conf->password);
2652
d62a17ae 2653 return 0;
718e3744 2654}
6b0655a2 2655
d62a17ae 2656int peer_group_listen_range_del(struct peer_group *group, struct prefix *range)
718e3744 2657{
d62a17ae 2658 struct prefix *prefix, prefix2;
2659 struct listnode *node, *nnode;
2660 struct peer *peer;
2661 afi_t afi;
2662 char buf[PREFIX2STR_BUFFER];
718e3744 2663
d62a17ae 2664 afi = family2afi(range->family);
1ff9a340 2665
d62a17ae 2666 /* Identify the listen range. */
2667 for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, nnode, prefix)) {
2668 if (prefix_same(range, prefix))
2669 break;
1ff9a340 2670 }
718e3744 2671
d62a17ae 2672 if (!prefix)
2673 return BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_NOT_FOUND;
2674
2675 prefix2str(prefix, buf, sizeof(buf));
2676
2677 /* Dispose off any dynamic neighbors that exist due to this listen range
2678 */
2679 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
2680 if (!peer_dynamic_neighbor(peer))
2681 continue;
2682
2683 sockunion2hostprefix(&peer->su, &prefix2);
2684 if (prefix_match(prefix, &prefix2)) {
2685 if (bgp_debug_neighbor_events(peer))
2686 zlog_debug(
2687 "Deleting dynamic neighbor %s group %s upon "
2688 "delete of listen range %s",
2689 peer->host, group->name, buf);
2690 peer_delete(peer);
2691 }
2692 }
718e3744 2693
d62a17ae 2694 /* Get rid of the listen range */
2695 listnode_delete(group->listen_range[afi], prefix);
718e3744 2696
9e7d9a61
QY
2697 /* Remove passwords for deleted ranges */
2698 if (group->conf->password)
2699 bgp_md5_unset_prefix(prefix);
2700
d62a17ae 2701 return 0;
2702}
e0701b79 2703
d62a17ae 2704/* Bind specified peer to peer group. */
2705int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer,
2706 struct peer_group *group, as_t *as)
2707{
2708 int first_member = 0;
2709 afi_t afi;
2710 safi_t safi;
d62a17ae 2711
2712 /* Lookup the peer. */
2713 if (!peer)
2714 peer = peer_lookup(bgp, su);
2715
2716 /* The peer exist, bind it to the peer-group */
2717 if (peer) {
ed9fb826 2718 /* When the peer already belongs to a peer-group, check the
d62a17ae 2719 * consistency. */
ed9fb826
DW
2720 if (peer_group_active(peer)) {
2721
2722 /* The peer is already bound to the peer-group,
d8a079e8
DW
2723 * nothing to do
2724 */
ed9fb826
DW
2725 if (strcmp(peer->group->name, group->name) == 0)
2726 return 0;
2727 else
2728 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
2729 }
d62a17ae 2730
2731 /* The peer has not specified a remote-as, inherit it from the
2732 * peer-group */
2733 if (peer->as_type == AS_UNSPECIFIED) {
2734 peer->as_type = group->conf->as_type;
2735 peer->as = group->conf->as;
faa16034 2736 peer->sort = group->conf->sort;
d62a17ae 2737 }
718e3744 2738
390485fd 2739 if (!group->conf->as && peer_sort(peer)) {
d62a17ae 2740 if (peer_sort(group->conf) != BGP_PEER_INTERNAL
2741 && peer_sort(group->conf) != peer_sort(peer)) {
2742 if (as)
2743 *as = peer->as;
2744 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
2745 }
718e3744 2746
d62a17ae 2747 if (peer_sort(group->conf) == BGP_PEER_INTERNAL)
2748 first_member = 1;
2749 }
718e3744 2750
d62a17ae 2751 peer_group2peer_config_copy(group, peer);
2752
05c7a1cc
QY
2753 FOREACH_AFI_SAFI (afi, safi) {
2754 if (group->conf->afc[afi][safi]) {
2755 peer->afc[afi][safi] = 1;
2756
2757 if (peer_af_find(peer, afi, safi)
2758 || peer_af_create(peer, afi, safi)) {
2759 peer_group2peer_config_copy_af(
2760 group, peer, afi, safi);
2761 }
2762 } else if (peer->afc[afi][safi])
2763 peer_deactivate(peer, afi, safi);
a4d82a8a 2764 }
d62a17ae 2765
2766 if (peer->group) {
2767 assert(group && peer->group == group);
2768 } else {
0866cdaf
A
2769 listnode_delete(bgp->peer, peer);
2770
d62a17ae 2771 peer->group = group;
2772 listnode_add_sort(bgp->peer, peer);
2773
2774 peer = peer_lock(peer); /* group->peer list reference */
2775 listnode_add(group->peer, peer);
2776 }
718e3744 2777
d62a17ae 2778 if (first_member) {
2779 /* Advertisement-interval reset */
b90a8e13
PM
2780 if (!CHECK_FLAG(group->conf->flags,
2781 PEER_FLAG_ROUTEADV)) {
2782 group->conf->v_routeadv =
2783 (peer_sort(group->conf)
2784 == BGP_PEER_IBGP)
2785 ? BGP_DEFAULT_IBGP_ROUTEADV
2786 : BGP_DEFAULT_EBGP_ROUTEADV;
d62a17ae 2787 }
2788
2789 /* ebgp-multihop reset */
2790 if (peer_sort(group->conf) == BGP_PEER_IBGP)
2791 group->conf->ttl = MAXTTL;
2792
2793 /* local-as reset */
2794 if (peer_sort(group->conf) != BGP_PEER_EBGP) {
2795 group->conf->change_local_as = 0;
a14810f4
PM
2796 peer_flag_unset(group->conf,
2797 PEER_FLAG_LOCAL_AS);
2798 peer_flag_unset(group->conf,
2799 PEER_FLAG_LOCAL_AS_NO_PREPEND);
2800 peer_flag_unset(group->conf,
2801 PEER_FLAG_LOCAL_AS_REPLACE_AS);
d62a17ae 2802 }
2803 }
718e3744 2804
d62a17ae 2805 SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
718e3744 2806
d62a17ae 2807 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
2808 peer->last_reset = PEER_DOWN_RMAP_BIND;
2809 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
2810 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2811 } else {
2812 bgp_session_reset(peer);
2813 }
2814 }
718e3744 2815
d62a17ae 2816 /* Create a new peer. */
2817 else {
2818 if ((group->conf->as_type == AS_SPECIFIED)
2819 && (!group->conf->as)) {
2820 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
2821 }
718e3744 2822
d62a17ae 2823 peer = peer_create(su, NULL, bgp, bgp->as, group->conf->as,
2824 group->conf->as_type, 0, 0, group);
718e3744 2825
d62a17ae 2826 peer = peer_lock(peer); /* group->peer list reference */
2827 listnode_add(group->peer, peer);
718e3744 2828
d62a17ae 2829 peer_group2peer_config_copy(group, peer);
a4ed4829 2830
d62a17ae 2831 /* If the peer-group is active for this afi/safi then activate
2832 * for this peer */
05c7a1cc
QY
2833 FOREACH_AFI_SAFI (afi, safi) {
2834 if (group->conf->afc[afi][safi]) {
2835 peer->afc[afi][safi] = 1;
2836 peer_af_create(peer, afi, safi);
2837 peer_group2peer_config_copy_af(group, peer, afi,
2838 safi);
2839 } else if (peer->afc[afi][safi])
2840 peer_deactivate(peer, afi, safi);
2841 }
718e3744 2842
d62a17ae 2843 SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
718e3744 2844
d62a17ae 2845 /* Set up peer's events and timers. */
2846 if (peer_active(peer))
2847 bgp_timer_set(peer);
2848 }
718e3744 2849
d62a17ae 2850 return 0;
718e3744 2851}
2852
d62a17ae 2853static int bgp_startup_timer_expire(struct thread *thread)
2854{
2855 struct bgp *bgp;
718e3744 2856
d62a17ae 2857 bgp = THREAD_ARG(thread);
2858 bgp->t_startup = NULL;
718e3744 2859
d62a17ae 2860 return 0;
2861}
e0701b79 2862
829e590b
DS
2863/*
2864 * On shutdown we call the cleanup function which
2865 * does a free of the link list nodes, free up
2866 * the data we are pointing at too.
2867 */
2868static void bgp_vrf_string_name_delete(void *data)
2869{
2870 char *vname = data;
2871
2872 XFREE(MTYPE_TMP, vname);
2873}
2874
d62a17ae 2875/* BGP instance creation by `router bgp' commands. */
2876static struct bgp *bgp_create(as_t *as, const char *name,
2877 enum bgp_instance_type inst_type)
2878{
0291c246
MK
2879 struct bgp *bgp;
2880 afi_t afi;
2881 safi_t safi;
d62a17ae 2882
2883 if ((bgp = XCALLOC(MTYPE_BGP, sizeof(struct bgp))) == NULL)
2884 return NULL;
2885
2886 if (BGP_DEBUG(zebra, ZEBRA)) {
2887 if (inst_type == BGP_INSTANCE_TYPE_DEFAULT)
2888 zlog_debug("Creating Default VRF, AS %u", *as);
2889 else
2890 zlog_debug("Creating %s %s, AS %u",
2891 (inst_type == BGP_INSTANCE_TYPE_VRF)
2892 ? "VRF"
2893 : "VIEW",
2894 name, *as);
718e3744 2895 }
adbac85e 2896
e2f3a930
T
2897 /* Default the EVPN VRF to the default one */
2898 if (inst_type == BGP_INSTANCE_TYPE_DEFAULT && !bgp_master.bgp_evpn) {
2899 bgp_lock(bgp);
2900 bm->bgp_evpn = bgp;
2901 }
2902
d62a17ae 2903 bgp_lock(bgp);
9df5ac49 2904 bgp->heuristic_coalesce = true;
d62a17ae 2905 bgp->inst_type = inst_type;
2906 bgp->vrf_id = (inst_type == BGP_INSTANCE_TYPE_DEFAULT) ? VRF_DEFAULT
2907 : VRF_UNKNOWN;
2908 bgp->peer_self = peer_new(bgp);
0a22ddfb 2909 XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->host);
d62a17ae 2910 bgp->peer_self->host =
2911 XSTRDUP(MTYPE_BGP_PEER_HOST, "Static announcement");
d77114b7
MK
2912 if (bgp->peer_self->hostname != NULL) {
2913 XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->hostname);
2914 bgp->peer_self->hostname = NULL;
2915 }
6b3ee3a0 2916 if (cmd_hostname_get())
60466a63
QY
2917 bgp->peer_self->hostname =
2918 XSTRDUP(MTYPE_BGP_PEER_HOST, cmd_hostname_get());
d77114b7
MK
2919
2920 if (bgp->peer_self->domainname != NULL) {
2921 XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->domainname);
2922 bgp->peer_self->domainname = NULL;
2923 }
6b3ee3a0 2924 if (cmd_domainname_get())
60466a63
QY
2925 bgp->peer_self->domainname =
2926 XSTRDUP(MTYPE_BGP_PEER_HOST, cmd_domainname_get());
d62a17ae 2927 bgp->peer = list_new();
2928 bgp->peer->cmp = (int (*)(void *, void *))peer_cmp;
a4d82a8a 2929 bgp->peerhash = hash_create(peer_hash_key_make, peer_hash_same,
3f65c5b1 2930 "BGP Peer Hash");
40520c36 2931 bgp->peerhash->max_size = BGP_PEER_MAX_HASH_SIZE;
d62a17ae 2932
2933 bgp->group = list_new();
2934 bgp->group->cmp = (int (*)(void *, void *))peer_group_cmp;
2935
05c7a1cc 2936 FOREACH_AFI_SAFI (afi, safi) {
960035b2
PZ
2937 bgp->route[afi][safi] = bgp_table_init(bgp, afi, safi);
2938 bgp->aggregate[afi][safi] = bgp_table_init(bgp, afi, safi);
2939 bgp->rib[afi][safi] = bgp_table_init(bgp, afi, safi);
05c7a1cc
QY
2940
2941 /* Enable maximum-paths */
2942 bgp_maximum_paths_set(bgp, afi, safi, BGP_PEER_EBGP,
2943 multipath_num, 0);
2944 bgp_maximum_paths_set(bgp, afi, safi, BGP_PEER_IBGP,
2945 multipath_num, 0);
2946 }
d62a17ae 2947
2948 bgp->v_update_delay = BGP_UPDATE_DELAY_DEF;
2949 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
2950 bgp->default_subgroup_pkt_queue_max =
2951 BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX;
2952 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
2953 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
2954 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
2955 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
2956 bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT;
2957 bgp->dynamic_neighbors_count = 0;
9dac9fc8 2958 bgp->ebgp_requires_policy = DEFAULT_EBGP_POLICY_DISABLED;
d62a17ae 2959#if DFLT_BGP_IMPORT_CHECK
2960 bgp_flag_set(bgp, BGP_FLAG_IMPORT_CHECK);
2961#endif
2962#if DFLT_BGP_SHOW_HOSTNAME
2963 bgp_flag_set(bgp, BGP_FLAG_SHOW_HOSTNAME);
2964#endif
2965#if DFLT_BGP_LOG_NEIGHBOR_CHANGES
2966 bgp_flag_set(bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES);
2967#endif
2968#if DFLT_BGP_DETERMINISTIC_MED
2969 bgp_flag_set(bgp, BGP_FLAG_DETERMINISTIC_MED);
2970#endif
dcc68b5e 2971 bgp_addpath_init_bgp_data(&bgp->tx_addpath);
d62a17ae 2972
2973 bgp->as = *as;
2974
2975#if ENABLE_BGP_VNC
2976 if (inst_type != BGP_INSTANCE_TYPE_VRF) {
2977 bgp->rfapi = bgp_rfapi_new(bgp);
2978 assert(bgp->rfapi);
2979 assert(bgp->rfapi_cfg);
2980 }
2981#endif /* ENABLE_BGP_VNC */
adbac85e 2982
ddb5b488 2983 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
e70e9f8e
PZ
2984 bgp->vpn_policy[afi].bgp = bgp;
2985 bgp->vpn_policy[afi].afi = afi;
ddb5b488
PZ
2986 bgp->vpn_policy[afi].tovpn_label = MPLS_LABEL_NONE;
2987 bgp->vpn_policy[afi].tovpn_zebra_vrf_label_last_sent =
2988 MPLS_LABEL_NONE;
12a844a5
DS
2989
2990 bgp->vpn_policy[afi].import_vrf = list_new();
829e590b
DS
2991 bgp->vpn_policy[afi].import_vrf->del =
2992 bgp_vrf_string_name_delete;
12a844a5 2993 bgp->vpn_policy[afi].export_vrf = list_new();
829e590b
DS
2994 bgp->vpn_policy[afi].export_vrf->del =
2995 bgp_vrf_string_name_delete;
ddb5b488 2996 }
d62a17ae 2997 if (name) {
2998 bgp->name = XSTRDUP(MTYPE_BGP, name);
2999 } else {
3000 /* TODO - The startup timer needs to be run for the whole of BGP
3001 */
3002 thread_add_timer(bm->master, bgp_startup_timer_expire, bgp,
3003 bgp->restart_time, &bgp->t_startup);
3004 }
06370dac 3005
3572fb26
PZ
3006 /* printable name we can use in debug messages */
3007 if (inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
3008 bgp->name_pretty = XSTRDUP(MTYPE_BGP, "VRF default");
3009 } else {
3010 const char *n;
3011 int len;
3012
3013 if (bgp->name)
3014 n = bgp->name;
3015 else
3016 n = "?";
3017
3018 len = 4 + 1 + strlen(n) + 1; /* "view foo\0" */
3019
3020 bgp->name_pretty = XCALLOC(MTYPE_BGP, len);
3021 snprintf(bgp->name_pretty, len, "%s %s",
3022 (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
3023 ? "VRF"
3024 : "VIEW",
3025 n);
3026 }
3027
555e09d4
QY
3028 atomic_store_explicit(&bgp->wpkt_quanta, BGP_WRITE_PACKET_MAX,
3029 memory_order_relaxed);
3030 atomic_store_explicit(&bgp->rpkt_quanta, BGP_READ_PACKET_MAX,
3031 memory_order_relaxed);
d62a17ae 3032 bgp->coalesce_time = BGP_DEFAULT_SUBGROUP_COALESCE_TIME;
adbac85e 3033
d62a17ae 3034 QOBJ_REG(bgp, bgp);
adbac85e 3035
d62a17ae 3036 update_bgp_group_init(bgp);
92708db6 3037
3038 /* assign a unique rd id for auto derivation of vrf's RD */
3039 bf_assign_index(bm->rd_idspace, bgp->vrf_rd_id);
3040
85c8d83b
CS
3041 bgp->evpn_info = XCALLOC(MTYPE_BGP_EVPN_INFO,
3042 sizeof(struct bgp_evpn_info));
3043
d62a17ae 3044 bgp_evpn_init(bgp);
f3d32faa 3045 bgp_pbr_init(bgp);
d62a17ae 3046 return bgp;
718e3744 3047}
3048
d62a17ae 3049/* Return the "default VRF" instance of BGP. */
3050struct bgp *bgp_get_default(void)
718e3744 3051{
d62a17ae 3052 struct bgp *bgp;
3053 struct listnode *node, *nnode;
3054
3055 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
3056 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
3057 return bgp;
3058 return NULL;
718e3744 3059}
3060
d62a17ae 3061/* Lookup BGP entry. */
3062struct bgp *bgp_lookup(as_t as, const char *name)
718e3744 3063{
d62a17ae 3064 struct bgp *bgp;
3065 struct listnode *node, *nnode;
6b0655a2 3066
d62a17ae 3067 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
3068 if (bgp->as == as
3069 && ((bgp->name == NULL && name == NULL)
3070 || (bgp->name && name && strcmp(bgp->name, name) == 0)))
3071 return bgp;
3072 return NULL;
3073}
73d70fa6 3074
d62a17ae 3075/* Lookup BGP structure by view name. */
3076struct bgp *bgp_lookup_by_name(const char *name)
73d70fa6 3077{
d62a17ae 3078 struct bgp *bgp;
3079 struct listnode *node, *nnode;
3080
3081 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
3082 if ((bgp->name == NULL && name == NULL)
3083 || (bgp->name && name && strcmp(bgp->name, name) == 0))
3084 return bgp;
3085 return NULL;
73d70fa6
DL
3086}
3087
d62a17ae 3088/* Lookup BGP instance based on VRF id. */
3089/* Note: Only to be used for incoming messages from Zebra. */
3090struct bgp *bgp_lookup_by_vrf_id(vrf_id_t vrf_id)
73d70fa6 3091{
d62a17ae 3092 struct vrf *vrf;
3093
3094 /* Lookup VRF (in tree) and follow link. */
3095 vrf = vrf_lookup_by_id(vrf_id);
3096 if (!vrf)
3097 return NULL;
3098 return (vrf->info) ? (struct bgp *)vrf->info : NULL;
73d70fa6
DL
3099}
3100
e2f3a930
T
3101/* Sets the BGP instance where EVPN is enabled */
3102void bgp_set_evpn(struct bgp *bgp)
3103{
3104 if (bm->bgp_evpn == bgp)
3105 return;
3106
3107 /* First, release the reference count we hold on the instance */
3108 if (bm->bgp_evpn)
3109 bgp_unlock(bm->bgp_evpn);
3110
3111 bm->bgp_evpn = bgp;
3112
3113 /* Increase the reference count on this new VRF */
3114 if (bm->bgp_evpn)
3115 bgp_lock(bm->bgp_evpn);
3116}
3117
3118/* Returns the BGP instance where EVPN is enabled, if any */
3119struct bgp *bgp_get_evpn(void)
3120{
3121 return bm->bgp_evpn;
3122}
3123
e5619c28
PG
3124/* handle socket creation or deletion, if necessary
3125 * this is called for all new BGP instances
3126 */
996c9314
LB
3127int bgp_handle_socket(struct bgp *bgp, struct vrf *vrf, vrf_id_t old_vrf_id,
3128 bool create)
e5619c28
PG
3129{
3130 int ret = 0;
3131
3132 /* Create BGP server socket, if listen mode not disabled */
3133 if (!bgp || bgp_option_check(BGP_OPT_NO_LISTEN))
3134 return 0;
3ad00234 3135 if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) {
e5619c28
PG
3136 /*
3137 * suppress vrf socket
3138 */
3139 if (create == FALSE) {
3ad00234
LB
3140 bgp_close_vrf_socket(bgp);
3141 return 0;
e5619c28 3142 }
3ad00234
LB
3143 if (vrf == NULL)
3144 return BGP_ERR_INVALID_VALUE;
e5619c28
PG
3145 /* do nothing
3146 * if vrf_id did not change
3147 */
3148 if (vrf->vrf_id == old_vrf_id)
3149 return 0;
3150 if (old_vrf_id != VRF_UNKNOWN) {
3151 /* look for old socket. close it. */
3152 bgp_close_vrf_socket(bgp);
3153 }
3154 /* if backend is not yet identified ( VRF_UNKNOWN) then
3155 * creation will be done later
3156 */
3157 if (vrf->vrf_id == VRF_UNKNOWN)
3158 return 0;
3ad00234
LB
3159 ret = bgp_socket(bgp, bm->port, bm->address);
3160 if (ret < 0)
3161 return BGP_ERR_INVALID_VALUE;
3162 return 0;
3163 } else
3164 return bgp_check_main_socket(create, bgp);
e5619c28
PG
3165}
3166
d62a17ae 3167/* Called from VTY commands. */
3168int bgp_get(struct bgp **bgp_val, as_t *as, const char *name,
3169 enum bgp_instance_type inst_type)
3170{
3171 struct bgp *bgp;
e5619c28 3172 struct vrf *vrf = NULL;
d62a17ae 3173
3174 /* Multiple instance check. */
3175 if (bgp_option_check(BGP_OPT_MULTIPLE_INSTANCE)) {
3176 if (name)
3177 bgp = bgp_lookup_by_name(name);
3178 else
3179 bgp = bgp_get_default();
3180
3181 /* Already exists. */
3182 if (bgp) {
3183 if (bgp->as != *as) {
3184 *as = bgp->as;
3185 return BGP_ERR_INSTANCE_MISMATCH;
3186 }
3187 if (bgp->inst_type != inst_type)
3188 return BGP_ERR_INSTANCE_MISMATCH;
3189 *bgp_val = bgp;
3190 return 0;
3191 }
3192 } else {
3193 /* BGP instance name can not be specified for single instance.
3194 */
3195 if (name)
3196 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
3197
3198 /* Get default BGP structure if exists. */
3199 bgp = bgp_get_default();
3200
3201 if (bgp) {
3202 if (bgp->as != *as) {
3203 *as = bgp->as;
3204 return BGP_ERR_AS_MISMATCH;
3205 }
3206 *bgp_val = bgp;
3207 return 0;
3208 }
3209 }
73d70fa6 3210
d62a17ae 3211 bgp = bgp_create(as, name, inst_type);
0b014ea6
PG
3212 if (bgp_option_check(BGP_OPT_NO_ZEBRA) && name)
3213 bgp->vrf_id = vrf_generate_id();
d62a17ae 3214 bgp_router_id_set(bgp, &bgp->router_id_zebra);
3215 bgp_address_init(bgp);
db0e1937 3216 bgp_tip_hash_init(bgp);
d62a17ae 3217 bgp_scan_init(bgp);
3218 *bgp_val = bgp;
eb821189 3219
d62a17ae 3220 bgp->t_rmap_def_originate_eval = NULL;
e5cc509c 3221
d62a17ae 3222 /* If Default instance or VRF, link to the VRF structure, if present. */
3223 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
3224 || bgp->inst_type == BGP_INSTANCE_TYPE_VRF) {
d62a17ae 3225 vrf = bgp_vrf_lookup_by_instance_type(bgp);
3226 if (vrf)
3227 bgp_vrf_link(bgp, vrf);
3228 }
e5619c28
PG
3229 /* BGP server socket already processed if BGP instance
3230 * already part of the list
3231 */
3232 bgp_handle_socket(bgp, vrf, VRF_UNKNOWN, true);
3233 listnode_add(bm->bgp, bgp);
718e3744 3234
bb4ef1ae
DS
3235 if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
3236 if (BGP_DEBUG(zebra, ZEBRA))
3237 zlog_debug("%s: Registering BGP instance %s to zebra",
3238 __PRETTY_FUNCTION__, name);
d62a17ae 3239 bgp_zebra_instance_register(bgp);
bb4ef1ae 3240 }
718e3744 3241
d62a17ae 3242 return 0;
718e3744 3243}
6b0655a2 3244
d62a17ae 3245/*
3246 * Make BGP instance "up". Applies only to VRFs (non-default) and
3247 * implies the VRF has been learnt from Zebra.
3248 */
3249void bgp_instance_up(struct bgp *bgp)
718e3744 3250{
d62a17ae 3251 struct peer *peer;
3252 struct listnode *node, *next;
718e3744 3253
d62a17ae 3254 /* Register with zebra. */
3255 bgp_zebra_instance_register(bgp);
718e3744 3256
d62a17ae 3257 /* Kick off any peers that may have been configured. */
3258 for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) {
3259 if (!BGP_PEER_START_SUPPRESSED(peer))
3260 BGP_EVENT_ADD(peer, BGP_Start);
718e3744 3261 }
3262
d62a17ae 3263 /* Process any networks that have been configured. */
3264 bgp_static_add(bgp);
3265}
3266
3267/*
3268 * Make BGP instance "down". Applies only to VRFs (non-default) and
3269 * implies the VRF has been deleted by Zebra.
3270 */
3271void bgp_instance_down(struct bgp *bgp)
3272{
3273 struct peer *peer;
3274 struct listnode *node;
3275 struct listnode *next;
3276
3277 /* Stop timers. */
3278 if (bgp->t_rmap_def_originate_eval) {
3279 BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval);
3280 bgp_unlock(bgp); /* TODO - This timer is started with a lock -
3281 why? */
718e3744 3282 }
3283
d62a17ae 3284 /* Bring down peers, so corresponding routes are purged. */
3285 for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) {
3286 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3287 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
3288 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
3289 else
3290 bgp_session_reset(peer);
3291 }
718e3744 3292
d62a17ae 3293 /* Purge network and redistributed routes. */
3294 bgp_purge_static_redist_routes(bgp);
ee7ca6c0 3295
3296 /* Cleanup registered nexthops (flags) */
3297 bgp_cleanup_nexthops(bgp);
718e3744 3298}
3299
d62a17ae 3300/* Delete BGP instance. */
3301int bgp_delete(struct bgp *bgp)
3302{
3303 struct peer *peer;
3304 struct peer_group *group;
3305 struct listnode *node, *next;
3306 struct vrf *vrf;
3307 afi_t afi;
3308 int i;
3309
bf383464 3310 assert(bgp);
d62a17ae 3311 THREAD_OFF(bgp->t_startup);
c969b2ed
DS
3312 THREAD_OFF(bgp->t_maxmed_onstartup);
3313 THREAD_OFF(bgp->t_update_delay);
3314 THREAD_OFF(bgp->t_establish_wait);
d62a17ae 3315
3316 if (BGP_DEBUG(zebra, ZEBRA)) {
3317 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
3318 zlog_debug("Deleting Default VRF");
3319 else
3320 zlog_debug("Deleting %s %s",
3321 (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
3322 ? "VRF"
3323 : "VIEW",
3324 bgp->name);
718e3744 3325 }
3326
10ebe1ab
MK
3327 /* unmap from RT list */
3328 bgp_evpn_vrf_delete(bgp);
3329
dfd17258
PG
3330 /* unmap bgp vrf label */
3331 vpn_leak_zebra_vrf_label_withdraw(bgp, AFI_IP);
3332 vpn_leak_zebra_vrf_label_withdraw(bgp, AFI_IP6);
3333
d62a17ae 3334 /* Stop timers. */
3335 if (bgp->t_rmap_def_originate_eval) {
3336 BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval);
3337 bgp_unlock(bgp); /* TODO - This timer is started with a lock -
3338 why? */
718e3744 3339 }
3340
d62a17ae 3341 /* Inform peers we're going down. */
3342 for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) {
3343 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3344 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
3345 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
718e3744 3346 }
3347
d62a17ae 3348 /* Delete static routes (networks). */
3349 bgp_static_delete(bgp);
6b0655a2 3350
d62a17ae 3351 /* Unset redistribution. */
3352 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3353 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3354 if (i != ZEBRA_ROUTE_BGP)
3355 bgp_redistribute_unset(bgp, afi, i, 0);
718e3744 3356
d62a17ae 3357 /* Free peers and peer-groups. */
3358 for (ALL_LIST_ELEMENTS(bgp->group, node, next, group))
3359 peer_group_delete(group);
718e3744 3360
d62a17ae 3361 for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer))
3362 peer_delete(peer);
3363
3364 if (bgp->peer_self) {
3365 peer_delete(bgp->peer_self);
3366 bgp->peer_self = NULL;
718e3744 3367 }
3368
d62a17ae 3369 update_bgp_group_free(bgp);
718e3744 3370
d62a17ae 3371/* TODO - Other memory may need to be freed - e.g., NHT */
3372
3373#if ENABLE_BGP_VNC
3374 rfapi_delete(bgp);
3375#endif
3376 bgp_cleanup_routes(bgp);
718e3744 3377
301ad80a
PG
3378 for (afi = 0; afi < AFI_MAX; ++afi) {
3379 if (!bgp->vpn_policy[afi].import_redirect_rtlist)
3380 continue;
3381 ecommunity_free(
3382 &bgp->vpn_policy[afi]
3383 .import_redirect_rtlist);
3384 bgp->vpn_policy[afi].import_redirect_rtlist = NULL;
3385 }
718e3744 3386
d62a17ae 3387 /* Deregister from Zebra, if needed */
bb4ef1ae
DS
3388 if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
3389 if (BGP_DEBUG(zebra, ZEBRA))
3390 zlog_debug("%s: deregistering this bgp %s instance from zebra",
3391 __PRETTY_FUNCTION__, bgp->name);
d62a17ae 3392 bgp_zebra_instance_deregister(bgp);
bb4ef1ae 3393 }
718e3744 3394
de6058ab
AK
3395 /* Remove visibility via the master list - there may however still be
3396 * routes to be processed still referencing the struct bgp.
3397 */
3398 listnode_delete(bm->bgp, bgp);
3399
d62a17ae 3400 /* Free interfaces in this instance. */
3401 bgp_if_finish(bgp);
718e3744 3402
d62a17ae 3403 vrf = bgp_vrf_lookup_by_instance_type(bgp);
e5619c28 3404 bgp_handle_socket(bgp, vrf, VRF_UNKNOWN, false);
d62a17ae 3405 if (vrf)
3406 bgp_vrf_unlink(bgp, vrf);
718e3744 3407
e2f3a930
T
3408 /* Update EVPN VRF pointer */
3409 if (bm->bgp_evpn == bgp) {
3410 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
3411 bgp_set_evpn(NULL);
3412 else
3413 bgp_set_evpn(bgp_get_default());
3414 }
3415
d62a17ae 3416 thread_master_free_unused(bm->master);
3417 bgp_unlock(bgp); /* initial reference */
718e3744 3418
d62a17ae 3419 return 0;
718e3744 3420}
6b0655a2 3421
92375c91 3422void bgp_free(struct bgp *bgp)
d93f7ffc 3423{
d62a17ae 3424 afi_t afi;
3425 safi_t safi;
3426 struct bgp_table *table;
3427 struct bgp_node *rn;
f8265580 3428 struct bgp_rmap *rmap;
d93f7ffc 3429
d62a17ae 3430 QOBJ_UNREG(bgp);
d93f7ffc 3431
6a154c88
DL
3432 list_delete(&bgp->group);
3433 list_delete(&bgp->peer);
966f821c 3434
d62a17ae 3435 if (bgp->peerhash) {
3436 hash_free(bgp->peerhash);
3437 bgp->peerhash = NULL;
3438 }
718e3744 3439
05c7a1cc
QY
3440 FOREACH_AFI_SAFI (afi, safi) {
3441 /* Special handling for 2-level routing tables. */
3442 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
3443 || safi == SAFI_EVPN) {
3444 for (rn = bgp_table_top(bgp->rib[afi][safi]); rn;
3445 rn = bgp_route_next(rn)) {
67009e22 3446 table = bgp_node_get_bgp_table_info(rn);
05c7a1cc 3447 bgp_table_finish(&table);
d62a17ae 3448 }
d62a17ae 3449 }
05c7a1cc
QY
3450 if (bgp->route[afi][safi])
3451 bgp_table_finish(&bgp->route[afi][safi]);
3452 if (bgp->aggregate[afi][safi])
3453 bgp_table_finish(&bgp->aggregate[afi][safi]);
3454 if (bgp->rib[afi][safi])
3455 bgp_table_finish(&bgp->rib[afi][safi]);
3456 rmap = &bgp->table_map[afi][safi];
0a22ddfb 3457 XFREE(MTYPE_ROUTE_MAP_NAME, rmap->name);
05c7a1cc 3458 }
718e3744 3459
d62a17ae 3460 bgp_scan_finish(bgp);
3461 bgp_address_destroy(bgp);
db0e1937 3462 bgp_tip_hash_destroy(bgp);
966f821c 3463
92708db6 3464 /* release the auto RD id */
3465 bf_release_index(bm->rd_idspace, bgp->vrf_rd_id);
3466
d62a17ae 3467 bgp_evpn_cleanup(bgp);
a6b07429 3468 bgp_pbr_cleanup(bgp);
85c8d83b 3469 XFREE(MTYPE_BGP_EVPN_INFO, bgp->evpn_info);
829e590b
DS
3470
3471 for (afi = AFI_IP; afi < AFI_MAX; afi++) {
3472 vpn_policy_direction_t dir;
3473
3474 if (bgp->vpn_policy[afi].import_vrf)
6a154c88 3475 list_delete(&bgp->vpn_policy[afi].import_vrf);
829e590b 3476 if (bgp->vpn_policy[afi].export_vrf)
6a154c88 3477 list_delete(&bgp->vpn_policy[afi].export_vrf);
829e590b
DS
3478
3479 dir = BGP_VPN_POLICY_DIR_FROMVPN;
3480 if (bgp->vpn_policy[afi].rtlist[dir])
3481 ecommunity_free(&bgp->vpn_policy[afi].rtlist[dir]);
3482 dir = BGP_VPN_POLICY_DIR_TOVPN;
3483 if (bgp->vpn_policy[afi].rtlist[dir])
3484 ecommunity_free(&bgp->vpn_policy[afi].rtlist[dir]);
3485 }
3486
0a22ddfb
QY
3487 XFREE(MTYPE_BGP, bgp->name);
3488 XFREE(MTYPE_BGP, bgp->name_pretty);
966f821c 3489
d62a17ae 3490 XFREE(MTYPE_BGP, bgp);
718e3744 3491}
3492
d62a17ae 3493struct peer *peer_lookup_by_conf_if(struct bgp *bgp, const char *conf_if)
718e3744 3494{
d62a17ae 3495 struct peer *peer;
3496 struct listnode *node, *nnode;
966f821c 3497
d62a17ae 3498 if (!conf_if)
3499 return NULL;
6b0655a2 3500
d62a17ae 3501 if (bgp != NULL) {
3502 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
3503 if (peer->conf_if && !strcmp(peer->conf_if, conf_if)
3504 && !CHECK_FLAG(peer->sflags,
3505 PEER_STATUS_ACCEPT_PEER))
3506 return peer;
3507 } else if (bm->bgp != NULL) {
3508 struct listnode *bgpnode, *nbgpnode;
3509
3510 for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp))
3511 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
3512 if (peer->conf_if
3513 && !strcmp(peer->conf_if, conf_if)
3514 && !CHECK_FLAG(peer->sflags,
3515 PEER_STATUS_ACCEPT_PEER))
3516 return peer;
3517 }
3518 return NULL;
718e3744 3519}
3520
d62a17ae 3521struct peer *peer_lookup_by_hostname(struct bgp *bgp, const char *hostname)
718e3744 3522{
d62a17ae 3523 struct peer *peer;
3524 struct listnode *node, *nnode;
6b0655a2 3525
d62a17ae 3526 if (!hostname)
3527 return NULL;
6b0655a2 3528
d62a17ae 3529 if (bgp != NULL) {
3530 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
3531 if (peer->hostname && !strcmp(peer->hostname, hostname)
3532 && !CHECK_FLAG(peer->sflags,
3533 PEER_STATUS_ACCEPT_PEER))
3534 return peer;
3535 } else if (bm->bgp != NULL) {
3536 struct listnode *bgpnode, *nbgpnode;
3537
3538 for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp))
3539 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
3540 if (peer->hostname
3541 && !strcmp(peer->hostname, hostname)
3542 && !CHECK_FLAG(peer->sflags,
3543 PEER_STATUS_ACCEPT_PEER))
3544 return peer;
3545 }
3546 return NULL;
3547}
3548
3549struct peer *peer_lookup(struct bgp *bgp, union sockunion *su)
3550{
3551 struct peer *peer = NULL;
3552 struct peer tmp_peer;
3553
3554 memset(&tmp_peer, 0, sizeof(struct peer));
3555
3556 /*
3557 * We do not want to find the doppelganger peer so search for the peer
3558 * in
3559 * the hash that has PEER_FLAG_CONFIG_NODE
3560 */
3561 SET_FLAG(tmp_peer.flags, PEER_FLAG_CONFIG_NODE);
3562
3563 tmp_peer.su = *su;
3564
3565 if (bgp != NULL) {
3566 peer = hash_lookup(bgp->peerhash, &tmp_peer);
3567 } else if (bm->bgp != NULL) {
3568 struct listnode *bgpnode, *nbgpnode;
3569
3570 for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp)) {
d62a17ae 3571 peer = hash_lookup(bgp->peerhash, &tmp_peer);
d62a17ae 3572 if (peer)
3573 break;
3574 }
3575 }
3576
3577 return peer;
3578}
3579
3580struct peer *peer_create_bind_dynamic_neighbor(struct bgp *bgp,
3581 union sockunion *su,
3582 struct peer_group *group)
3583{
3584 struct peer *peer;
3585 afi_t afi;
3586 safi_t safi;
3587
3588 /* Create peer first; we've already checked group config is valid. */
3589 peer = peer_create(su, NULL, bgp, bgp->as, group->conf->as,
3590 group->conf->as_type, 0, 0, group);
3591 if (!peer)
3592 return NULL;
3593
3594 /* Link to group */
3595 peer = peer_lock(peer);
3596 listnode_add(group->peer, peer);
3597
3598 peer_group2peer_config_copy(group, peer);
3599
3600 /*
3601 * Bind peer for all AFs configured for the group. We don't call
3602 * peer_group_bind as that is sub-optimal and does some stuff we don't
3603 * want.
3604 */
05c7a1cc
QY
3605 FOREACH_AFI_SAFI (afi, safi) {
3606 if (!group->conf->afc[afi][safi])
3607 continue;
3608 peer->afc[afi][safi] = 1;
d62a17ae 3609
05c7a1cc
QY
3610 if (!peer_af_find(peer, afi, safi))
3611 peer_af_create(peer, afi, safi);
d62a17ae 3612
05c7a1cc
QY
3613 peer_group2peer_config_copy_af(group, peer, afi, safi);
3614 }
d62a17ae 3615
3616 /* Mark as dynamic, but also as a "config node" for other things to
3617 * work. */
3618 SET_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR);
3619 SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
3620
3621 return peer;
3622}
3623
3624struct prefix *
3625peer_group_lookup_dynamic_neighbor_range(struct peer_group *group,
3626 struct prefix *prefix)
3627{
3628 struct listnode *node, *nnode;
3629 struct prefix *range;
3630 afi_t afi;
3631
3632 afi = family2afi(prefix->family);
3633
3634 if (group->listen_range[afi])
3635 for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, nnode,
3636 range))
3637 if (prefix_match(range, prefix))
3638 return range;
3639
3640 return NULL;
3641}
3642
3643struct peer_group *
3644peer_group_lookup_dynamic_neighbor(struct bgp *bgp, struct prefix *prefix,
3645 struct prefix **listen_range)
3646{
3647 struct prefix *range = NULL;
3648 struct peer_group *group = NULL;
3649 struct listnode *node, *nnode;
3650
3651 *listen_range = NULL;
3652 if (bgp != NULL) {
3653 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group))
3654 if ((range = peer_group_lookup_dynamic_neighbor_range(
3655 group, prefix)))
3656 break;
3657 } else if (bm->bgp != NULL) {
3658 struct listnode *bgpnode, *nbgpnode;
3659
3660 for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp))
3661 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group))
3662 if ((range = peer_group_lookup_dynamic_neighbor_range(
3663 group, prefix)))
3664 goto found_range;
3665 }
3666
3667found_range:
3668 *listen_range = range;
3669 return (group && range) ? group : NULL;
3670}
3671
3672struct peer *peer_lookup_dynamic_neighbor(struct bgp *bgp, union sockunion *su)
3673{
3674 struct peer_group *group;
3675 struct bgp *gbgp;
3676 struct peer *peer;
3677 struct prefix prefix;
3678 struct prefix *listen_range;
3679 int dncount;
3680 char buf[PREFIX2STR_BUFFER];
3681 char buf1[PREFIX2STR_BUFFER];
3682
3683 sockunion2hostprefix(su, &prefix);
3684
3685 /* See if incoming connection matches a configured listen range. */
3686 group = peer_group_lookup_dynamic_neighbor(bgp, &prefix, &listen_range);
3687
3688 if (!group)
3689 return NULL;
3690
3691
3692 gbgp = group->bgp;
3693
3694 if (!gbgp)
3695 return NULL;
3696
3697 prefix2str(&prefix, buf, sizeof(buf));
3698 prefix2str(listen_range, buf1, sizeof(buf1));
3699
3700 if (bgp_debug_neighbor_events(NULL))
3701 zlog_debug(
3702 "Dynamic Neighbor %s matches group %s listen range %s",
3703 buf, group->name, buf1);
3704
3705 /* Are we within the listen limit? */
3706 dncount = gbgp->dynamic_neighbors_count;
3707
3708 if (dncount >= gbgp->dynamic_neighbors_limit) {
3709 if (bgp_debug_neighbor_events(NULL))
3710 zlog_debug("Dynamic Neighbor %s rejected - at limit %d",
3711 inet_sutop(su, buf),
3712 gbgp->dynamic_neighbors_limit);
3713 return NULL;
3714 }
3715
3716 /* Ensure group is not disabled. */
3717 if (CHECK_FLAG(group->conf->flags, PEER_FLAG_SHUTDOWN)) {
3718 if (bgp_debug_neighbor_events(NULL))
3719 zlog_debug(
3720 "Dynamic Neighbor %s rejected - group %s disabled",
3721 buf, group->name);
3722 return NULL;
3723 }
3724
3725 /* Check that at least one AF is activated for the group. */
3726 if (!peer_group_af_configured(group)) {
3727 if (bgp_debug_neighbor_events(NULL))
3728 zlog_debug(
3729 "Dynamic Neighbor %s rejected - no AF activated for group %s",
3730 buf, group->name);
3731 return NULL;
3732 }
3733
3734 /* Create dynamic peer and bind to associated group. */
3735 peer = peer_create_bind_dynamic_neighbor(gbgp, su, group);
3736 assert(peer);
3737
3738 gbgp->dynamic_neighbors_count = ++dncount;
3739
3740 if (bgp_debug_neighbor_events(peer))
3741 zlog_debug("%s Dynamic Neighbor added, group %s count %d",
3742 peer->host, group->name, dncount);
3743
3744 return peer;
3745}
3746
cc32742c 3747static void peer_drop_dynamic_neighbor(struct peer *peer)
d62a17ae 3748{
3749 int dncount = -1;
cc32742c 3750 if (peer->group->bgp) {
d62a17ae 3751 dncount = peer->group->bgp->dynamic_neighbors_count;
3752 if (dncount)
3753 peer->group->bgp->dynamic_neighbors_count = --dncount;
3754 }
3755 if (bgp_debug_neighbor_events(peer))
3756 zlog_debug("%s dropped from group %s, count %d", peer->host,
3757 peer->group->name, dncount);
3758}
3759
d62a17ae 3760/* If peer is configured at least one address family return 1. */
3761int peer_active(struct peer *peer)
3762{
3763 if (BGP_PEER_SU_UNSPEC(peer))
3764 return 0;
3765 if (peer->afc[AFI_IP][SAFI_UNICAST] || peer->afc[AFI_IP][SAFI_MULTICAST]
3766 || peer->afc[AFI_IP][SAFI_LABELED_UNICAST]
3767 || peer->afc[AFI_IP][SAFI_MPLS_VPN] || peer->afc[AFI_IP][SAFI_ENCAP]
7c40bf39 3768 || peer->afc[AFI_IP][SAFI_FLOWSPEC]
d62a17ae 3769 || peer->afc[AFI_IP6][SAFI_UNICAST]
3770 || peer->afc[AFI_IP6][SAFI_MULTICAST]
3771 || peer->afc[AFI_IP6][SAFI_LABELED_UNICAST]
3772 || peer->afc[AFI_IP6][SAFI_MPLS_VPN]
3773 || peer->afc[AFI_IP6][SAFI_ENCAP]
7c40bf39 3774 || peer->afc[AFI_IP6][SAFI_FLOWSPEC]
d62a17ae 3775 || peer->afc[AFI_L2VPN][SAFI_EVPN])
3776 return 1;
3777 return 0;
3778}
3779
3780/* If peer is negotiated at least one address family return 1. */
3781int peer_active_nego(struct peer *peer)
3782{
3783 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
3784 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
3785 || peer->afc_nego[AFI_IP][SAFI_LABELED_UNICAST]
3786 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
3787 || peer->afc_nego[AFI_IP][SAFI_ENCAP]
7c40bf39 3788 || peer->afc_nego[AFI_IP][SAFI_FLOWSPEC]
d62a17ae 3789 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
3790 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
3791 || peer->afc_nego[AFI_IP6][SAFI_LABELED_UNICAST]
3792 || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
3793 || peer->afc_nego[AFI_IP6][SAFI_ENCAP]
7c40bf39 3794 || peer->afc_nego[AFI_IP6][SAFI_FLOWSPEC]
d62a17ae 3795 || peer->afc_nego[AFI_L2VPN][SAFI_EVPN])
3796 return 1;
3797 return 0;
3798}
3799
dcc68b5e 3800void peer_change_action(struct peer *peer, afi_t afi, safi_t safi,
d62a17ae 3801 enum peer_change_type type)
3802{
3803 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
3804 return;
3805
3806 if (peer->status != Established)
3807 return;
3808
3809 if (type == peer_change_reset) {
3810 /* If we're resetting session, we've to delete both peer struct
3811 */
3812 if ((peer->doppelganger)
3813 && (peer->doppelganger->status != Deleted)
3814 && (!CHECK_FLAG(peer->doppelganger->flags,
3815 PEER_FLAG_CONFIG_NODE)))
3816 peer_delete(peer->doppelganger);
3817
3818 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
3819 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3820 } else if (type == peer_change_reset_in) {
3821 if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV)
3822 || CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV))
3823 bgp_route_refresh_send(peer, afi, safi, 0, 0, 0);
3824 else {
3825 if ((peer->doppelganger)
3826 && (peer->doppelganger->status != Deleted)
3827 && (!CHECK_FLAG(peer->doppelganger->flags,
3828 PEER_FLAG_CONFIG_NODE)))
3829 peer_delete(peer->doppelganger);
3830
3831 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
3832 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3833 }
3834 } else if (type == peer_change_reset_out) {
3835 update_group_adjust_peer(peer_af_find(peer, afi, safi));
3836 bgp_announce_route(peer, afi, safi);
3837 }
3838}
3839
3840struct peer_flag_action {
3841 /* Peer's flag. */
d7c0a89a 3842 uint32_t flag;
d62a17ae 3843
3844 /* This flag can be set for peer-group member. */
d7c0a89a 3845 uint8_t not_for_member;
d62a17ae 3846
3847 /* Action when the flag is changed. */
3848 enum peer_change_type type;
d62a17ae 3849};
3850
3851static const struct peer_flag_action peer_flag_action_list[] = {
3852 {PEER_FLAG_PASSIVE, 0, peer_change_reset},
3853 {PEER_FLAG_SHUTDOWN, 0, peer_change_reset},
3854 {PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none},
3855 {PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none},
3856 {PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none},
3857 {PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset},
3858 {PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset},
3859 {PEER_FLAG_CAPABILITY_ENHE, 0, peer_change_reset},
47cbc09b 3860 {PEER_FLAG_ENFORCE_FIRST_AS, 0, peer_change_reset_in},
afad5ced 3861 {PEER_FLAG_IFPEER_V6ONLY, 0, peer_change_reset},
b90a8e13
PM
3862 {PEER_FLAG_ROUTEADV, 0, peer_change_none},
3863 {PEER_FLAG_TIMER, 0, peer_change_none},
3864 {PEER_FLAG_TIMER_CONNECT, 0, peer_change_none},
a14810f4
PM
3865 {PEER_FLAG_PASSWORD, 0, peer_change_none},
3866 {PEER_FLAG_LOCAL_AS, 0, peer_change_none},
3867 {PEER_FLAG_LOCAL_AS_NO_PREPEND, 0, peer_change_none},
3868 {PEER_FLAG_LOCAL_AS_REPLACE_AS, 0, peer_change_none},
3869 {PEER_FLAG_UPDATE_SOURCE, 0, peer_change_none},
d62a17ae 3870 {0, 0, 0}};
3871
3872static const struct peer_flag_action peer_af_flag_action_list[] = {
3873 {PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out},
3874 {PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out},
3875 {PEER_FLAG_SEND_LARGE_COMMUNITY, 1, peer_change_reset_out},
3876 {PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out},
3877 {PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset},
3878 {PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset},
3879 {PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in},
3880 {PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out},
3881 {PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out},
3882 {PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out},
598ce6bd 3883 {PEER_FLAG_DEFAULT_ORIGINATE, 0, peer_change_none},
d62a17ae 3884 {PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out},
3885 {PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in},
3886 {PEER_FLAG_ALLOWAS_IN_ORIGIN, 0, peer_change_reset_in},
3887 {PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset},
3888 {PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset},
598ce6bd
PM
3889 {PEER_FLAG_MAX_PREFIX, 0, peer_change_none},
3890 {PEER_FLAG_MAX_PREFIX_WARNING, 0, peer_change_none},
d62a17ae 3891 {PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out},
3892 {PEER_FLAG_FORCE_NEXTHOP_SELF, 1, peer_change_reset_out},
3893 {PEER_FLAG_REMOVE_PRIVATE_AS_ALL, 1, peer_change_reset_out},
3894 {PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE, 1, peer_change_reset_out},
3895 {PEER_FLAG_AS_OVERRIDE, 1, peer_change_reset_out},
3896 {PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE, 1, peer_change_reset_out},
d62a17ae 3897 {PEER_FLAG_WEIGHT, 0, peer_change_reset_in},
3898 {0, 0, 0}};
3899
3900/* Proper action set. */
3901static int peer_flag_action_set(const struct peer_flag_action *action_list,
3902 int size, struct peer_flag_action *action,
d7c0a89a 3903 uint32_t flag)
d62a17ae 3904{
3905 int i;
3906 int found = 0;
3907 int reset_in = 0;
3908 int reset_out = 0;
3909 const struct peer_flag_action *match = NULL;
3910
3911 /* Check peer's frag action. */
3912 for (i = 0; i < size; i++) {
3913 match = &action_list[i];
3914
3915 if (match->flag == 0)
3916 break;
3917
3918 if (match->flag & flag) {
3919 found = 1;
3920
3921 if (match->type == peer_change_reset_in)
3922 reset_in = 1;
3923 if (match->type == peer_change_reset_out)
3924 reset_out = 1;
3925 if (match->type == peer_change_reset) {
3926 reset_in = 1;
3927 reset_out = 1;
3928 }
3929 if (match->not_for_member)
3930 action->not_for_member = 1;
3931 }
3932 }
3933
3934 /* Set peer clear type. */
3935 if (reset_in && reset_out)
3936 action->type = peer_change_reset;
3937 else if (reset_in)
3938 action->type = peer_change_reset_in;
3939 else if (reset_out)
3940 action->type = peer_change_reset_out;
3941 else
3942 action->type = peer_change_none;
3943
3944 return found;
3945}
3946
d7c0a89a 3947static void peer_flag_modify_action(struct peer *peer, uint32_t flag)
d62a17ae 3948{
3949 if (flag == PEER_FLAG_SHUTDOWN) {
3950 if (CHECK_FLAG(peer->flags, flag)) {
3951 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT))
3952 peer_nsf_stop(peer);
3953
3954 UNSET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3955 if (peer->t_pmax_restart) {
3956 BGP_TIMER_OFF(peer->t_pmax_restart);
3957 if (bgp_debug_neighbor_events(peer))
3958 zlog_debug(
3959 "%s Maximum-prefix restart timer canceled",
3960 peer->host);
3961 }
3962
3963 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT))
3964 peer_nsf_stop(peer);
3965
3966 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
3967 char *msg = peer->tx_shutdown_message;
3968 size_t msglen;
3969
3970 if (!msg && peer_group_active(peer))
3971 msg = peer->group->conf
3972 ->tx_shutdown_message;
3973 msglen = msg ? strlen(msg) : 0;
3974 if (msglen > 128)
3975 msglen = 128;
3976
3977 if (msglen) {
d7c0a89a 3978 uint8_t msgbuf[129];
d62a17ae 3979
3980 msgbuf[0] = msglen;
3981 memcpy(msgbuf + 1, msg, msglen);
3982
3983 bgp_notify_send_with_data(
3984 peer, BGP_NOTIFY_CEASE,
3985 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN,
3986 msgbuf, msglen + 1);
3987 } else
3988 bgp_notify_send(
3989 peer, BGP_NOTIFY_CEASE,
3990 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
3991 } else
3992 bgp_session_reset(peer);
3993 } else {
3994 peer->v_start = BGP_INIT_START_TIMER;
3995 BGP_EVENT_ADD(peer, BGP_Stop);
3996 }
3997 } else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
3998 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
3999 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
4000 else if (flag == PEER_FLAG_PASSIVE)
4001 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
4002 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
4003 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
4004
4005 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4006 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4007 } else
4008 bgp_session_reset(peer);
4009}
4010
4011/* Change specified peer flag. */
d7c0a89a 4012static int peer_flag_modify(struct peer *peer, uint32_t flag, int set)
d62a17ae 4013{
4014 int found;
4015 int size;
9fb964de
PM
4016 bool invert, member_invert;
4017 struct peer *member;
d62a17ae 4018 struct listnode *node, *nnode;
4019 struct peer_flag_action action;
4020
4021 memset(&action, 0, sizeof(struct peer_flag_action));
4022 size = sizeof peer_flag_action_list / sizeof(struct peer_flag_action);
4023
9fb964de 4024 invert = CHECK_FLAG(peer->flags_invert, flag);
d62a17ae 4025 found = peer_flag_action_set(peer_flag_action_list, size, &action,
4026 flag);
4027
9fb964de 4028 /* Abort if no flag action exists. */
d62a17ae 4029 if (!found)
4030 return BGP_ERR_INVALID_FLAG;
4031
9fb964de 4032 /* Check for flag conflict: STRICT_CAP_MATCH && OVERRIDE_CAPABILITY */
d62a17ae 4033 if (set && CHECK_FLAG(peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
4034 && CHECK_FLAG(peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
4035 return BGP_ERR_PEER_FLAG_CONFLICT;
4036
9fb964de 4037 /* Handle flag updates where desired state matches current state. */
d62a17ae 4038 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
9fb964de
PM
4039 if (set && CHECK_FLAG(peer->flags, flag)) {
4040 COND_FLAG(peer->flags_override, flag, !invert);
d62a17ae 4041 return 0;
9fb964de
PM
4042 }
4043
4044 if (!set && !CHECK_FLAG(peer->flags, flag)) {
4045 COND_FLAG(peer->flags_override, flag, invert);
d62a17ae 4046 return 0;
9fb964de 4047 }
d62a17ae 4048 }
4049
9fb964de
PM
4050 /* Inherit from peer-group or set/unset flags accordingly. */
4051 if (peer_group_active(peer) && set == invert)
4052 peer_flag_inherit(peer, flag);
d62a17ae 4053 else
9fb964de 4054 COND_FLAG(peer->flags, flag, set);
d62a17ae 4055
9fb964de 4056 /* Check if handling a regular peer. */
d62a17ae 4057 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
9fb964de
PM
4058 /* Update flag override state accordingly. */
4059 COND_FLAG(peer->flags_override, flag, set != invert);
4060
4061 /* Execute flag action on peer. */
d62a17ae 4062 if (action.type == peer_change_reset)
4063 peer_flag_modify_action(peer, flag);
4064
9fb964de 4065 /* Skip peer-group mechanics for regular peers. */
d62a17ae 4066 return 0;
4067 }
4068
1ea03b90
DS
4069 if (set && flag == PEER_FLAG_CAPABILITY_ENHE)
4070 bgp_nht_register_enhe_capability_interfaces(peer);
4071
9fb964de
PM
4072 /*
4073 * Update peer-group members, unless they are explicitely overriding
4074 * peer-group configuration.
4075 */
4076 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
4077 /* Skip peers with overridden configuration. */
4078 if (CHECK_FLAG(member->flags_override, flag))
4079 continue;
d62a17ae 4080
527de3dc
PM
4081 /* Check if only member without group is inverted. */
4082 member_invert =
4083 CHECK_FLAG(member->flags_invert, flag) && !invert;
d62a17ae 4084
9fb964de
PM
4085 /* Skip peers with equivalent configuration. */
4086 if (set != member_invert && CHECK_FLAG(member->flags, flag))
d62a17ae 4087 continue;
4088
9fb964de 4089 if (set == member_invert && !CHECK_FLAG(member->flags, flag))
d62a17ae 4090 continue;
4091
9fb964de
PM
4092 /* Update flag on peer-group member. */
4093 COND_FLAG(member->flags, flag, set != member_invert);
d62a17ae 4094
1ea03b90
DS
4095 if (set && flag == PEER_FLAG_CAPABILITY_ENHE)
4096 bgp_nht_register_enhe_capability_interfaces(member);
4097
9fb964de 4098 /* Execute flag action on peer-group member. */
d62a17ae 4099 if (action.type == peer_change_reset)
9fb964de 4100 peer_flag_modify_action(member, flag);
d62a17ae 4101 }
9fb964de 4102
d62a17ae 4103 return 0;
4104}
4105
d7c0a89a 4106int peer_flag_set(struct peer *peer, uint32_t flag)
d62a17ae 4107{
4108 return peer_flag_modify(peer, flag, 1);
4109}
4110
d7c0a89a 4111int peer_flag_unset(struct peer *peer, uint32_t flag)
d62a17ae 4112{
4113 return peer_flag_modify(peer, flag, 0);
4114}
4115
4116static int peer_af_flag_modify(struct peer *peer, afi_t afi, safi_t safi,
27c05d4d 4117 uint32_t flag, bool set)
d62a17ae 4118{
4119 int found;
4120 int size;
527de3dc 4121 bool invert, member_invert;
527de3dc 4122 struct peer *member;
d62a17ae 4123 struct listnode *node, *nnode;
d62a17ae 4124 struct peer_flag_action action;
d62a17ae 4125
4126 memset(&action, 0, sizeof(struct peer_flag_action));
4127 size = sizeof peer_af_flag_action_list
4128 / sizeof(struct peer_flag_action);
4129
27c05d4d 4130 invert = CHECK_FLAG(peer->af_flags_invert[afi][safi], flag);
d62a17ae 4131 found = peer_flag_action_set(peer_af_flag_action_list, size, &action,
4132 flag);
4133
527de3dc 4134 /* Abort if flag action exists. */
d62a17ae 4135 if (!found)
4136 return BGP_ERR_INVALID_FLAG;
4137
4138 /* Special check for reflector client. */
4139 if (flag & PEER_FLAG_REFLECTOR_CLIENT
4140 && peer_sort(peer) != BGP_PEER_IBGP)
4141 return BGP_ERR_NOT_INTERNAL_PEER;
4142
4143 /* Special check for remove-private-AS. */
4144 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
4145 && peer_sort(peer) == BGP_PEER_IBGP)
4146 return BGP_ERR_REMOVE_PRIVATE_AS;
4147
4148 /* as-override is not allowed for IBGP peers */
4149 if (flag & PEER_FLAG_AS_OVERRIDE && peer_sort(peer) == BGP_PEER_IBGP)
4150 return BGP_ERR_AS_OVERRIDE;
4151
527de3dc 4152 /* Handle flag updates where desired state matches current state. */
d62a17ae 4153 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
598ce6bd 4154 if (set && CHECK_FLAG(peer->af_flags[afi][safi], flag)) {
527de3dc
PM
4155 COND_FLAG(peer->af_flags_override[afi][safi], flag,
4156 !invert);
d62a17ae 4157 return 0;
598ce6bd
PM
4158 }
4159
4160 if (!set && !CHECK_FLAG(peer->af_flags[afi][safi], flag)) {
527de3dc
PM
4161 COND_FLAG(peer->af_flags_override[afi][safi], flag,
4162 invert);
d62a17ae 4163 return 0;
598ce6bd 4164 }
d62a17ae 4165 }
4166
ace295a9
MK
4167 /*
4168 * For EVPN we implicitly set the NEXTHOP_UNCHANGED flag,
4169 * if we are setting/unsetting flags which conflict with this flag
4170 * handle accordingly
4171 */
4172 if (afi == AFI_L2VPN && safi == SAFI_EVPN) {
4173 if (set) {
4174
3518f352
DS
4175 /*
4176 * if we are setting NEXTHOP_SELF, we need to unset the
4177 * NEXTHOP_UNCHANGED flag
4178 */
ace295a9
MK
4179 if (CHECK_FLAG(flag, PEER_FLAG_NEXTHOP_SELF) ||
4180 CHECK_FLAG(flag, PEER_FLAG_FORCE_NEXTHOP_SELF))
4181 UNSET_FLAG(peer->af_flags[afi][safi],
4182 PEER_FLAG_NEXTHOP_UNCHANGED);
4183 } else {
4184
3518f352
DS
4185 /*
4186 * if we are unsetting NEXTHOP_SELF, we need to set the
ace295a9
MK
4187 * NEXTHOP_UNCHANGED flag to reset the defaults for EVPN
4188 */
4189 if (CHECK_FLAG(flag, PEER_FLAG_NEXTHOP_SELF) ||
4190 CHECK_FLAG(flag, PEER_FLAG_FORCE_NEXTHOP_SELF))
4191 SET_FLAG(peer->af_flags[afi][safi],
4192 PEER_FLAG_NEXTHOP_UNCHANGED);
4193 }
4194 }
4195
527de3dc
PM
4196 /* Inherit from peer-group or set/unset flags accordingly. */
4197 if (peer_group_active(peer) && set == invert)
4198 peer_af_flag_inherit(peer, afi, safi, flag);
4199 else
4200 COND_FLAG(peer->af_flags[afi][safi], flag, set);
d62a17ae 4201
4202 /* Execute action when peer is established. */
4203 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)
4204 && peer->status == Established) {
4205 if (!set && flag == PEER_FLAG_SOFT_RECONFIG)
4206 bgp_clear_adj_in(peer, afi, safi);
4207 else {
4208 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
4209 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
4210 else if (flag == PEER_FLAG_RSERVER_CLIENT)
4211 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
4212 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
4213 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
4214 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
4215 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
4216
4217 peer_change_action(peer, afi, safi, action.type);
4218 }
4219 }
4220
527de3dc
PM
4221 /* Check if handling a regular peer. */
4222 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4223 COND_FLAG(peer->af_flags_override[afi][safi], flag,
4224 set != invert);
4225 } else {
4226 /*
4227 * Update peer-group members, unless they are explicitely
4228 * overriding peer-group configuration.
4229 */
4230 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode,
4231 member)) {
4232 /* Skip peers with overridden configuration. */
4233 if (CHECK_FLAG(member->af_flags_override[afi][safi],
598ce6bd
PM
4234 flag))
4235 continue;
4236
527de3dc
PM
4237 /* Check if only member without group is inverted. */
4238 member_invert =
4239 CHECK_FLAG(member->af_flags_invert[afi][safi],
4240 flag)
4241 && !invert;
4242
4243 /* Skip peers with equivalent configuration. */
4244 if (set != member_invert
4245 && CHECK_FLAG(member->af_flags[afi][safi], flag))
d62a17ae 4246 continue;
4247
527de3dc
PM
4248 if (set == member_invert
4249 && !CHECK_FLAG(member->af_flags[afi][safi], flag))
d62a17ae 4250 continue;
4251
527de3dc
PM
4252 /* Update flag on peer-group member. */
4253 COND_FLAG(member->af_flags[afi][safi], flag,
4254 set != member_invert);
d62a17ae 4255
527de3dc
PM
4256 /* Execute flag action on peer-group member. */
4257 if (member->status == Established) {
d62a17ae 4258 if (!set && flag == PEER_FLAG_SOFT_RECONFIG)
527de3dc 4259 bgp_clear_adj_in(member, afi, safi);
d62a17ae 4260 else {
4261 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
527de3dc 4262 member->last_reset =
d62a17ae 4263 PEER_DOWN_RR_CLIENT_CHANGE;
4264 else if (flag
4265 == PEER_FLAG_RSERVER_CLIENT)
527de3dc 4266 member->last_reset =
d62a17ae 4267 PEER_DOWN_RS_CLIENT_CHANGE;
4268 else if (flag
4269 == PEER_FLAG_ORF_PREFIX_SM)
527de3dc 4270 member->last_reset =
d62a17ae 4271 PEER_DOWN_CAPABILITY_CHANGE;
4272 else if (flag
4273 == PEER_FLAG_ORF_PREFIX_RM)
527de3dc 4274 member->last_reset =
d62a17ae 4275 PEER_DOWN_CAPABILITY_CHANGE;
4276
527de3dc 4277 peer_change_action(member, afi, safi,
d62a17ae 4278 action.type);
4279 }
4280 }
4281 }
4282 }
4283
d62a17ae 4284 return 0;
4285}
4286
d7c0a89a 4287int peer_af_flag_set(struct peer *peer, afi_t afi, safi_t safi, uint32_t flag)
d62a17ae 4288{
4289 return peer_af_flag_modify(peer, afi, safi, flag, 1);
4290}
4291
d7c0a89a 4292int peer_af_flag_unset(struct peer *peer, afi_t afi, safi_t safi, uint32_t flag)
d62a17ae 4293{
4294 return peer_af_flag_modify(peer, afi, safi, flag, 0);
4295}
4296
4297
4298int peer_tx_shutdown_message_set(struct peer *peer, const char *msg)
4299{
4300 XFREE(MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message);
4301 peer->tx_shutdown_message =
4302 msg ? XSTRDUP(MTYPE_PEER_TX_SHUTDOWN_MSG, msg) : NULL;
4303 return 0;
4304}
4305
4306int peer_tx_shutdown_message_unset(struct peer *peer)
4307{
4308 XFREE(MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message);
4309 return 0;
4310}
4311
4312
4313/* EBGP multihop configuration. */
4314int peer_ebgp_multihop_set(struct peer *peer, int ttl)
4315{
4316 struct peer_group *group;
4317 struct listnode *node, *nnode;
4318 struct peer *peer1;
4319
4320 if (peer->sort == BGP_PEER_IBGP || peer->conf_if)
4321 return 0;
4322
4323 /* see comment in peer_ttl_security_hops_set() */
4324 if (ttl != MAXTTL) {
4325 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4326 group = peer->group;
4327 if (group->conf->gtsm_hops != 0)
4328 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4329
4330 for (ALL_LIST_ELEMENTS(group->peer, node, nnode,
4331 peer1)) {
4332 if (peer1->sort == BGP_PEER_IBGP)
4333 continue;
4334
4335 if (peer1->gtsm_hops != 0)
4336 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4337 }
4338 } else {
4339 if (peer->gtsm_hops != 0)
4340 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4341 }
4342 }
4343
4344 peer->ttl = ttl;
4345
4346 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4347 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP) {
4348 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4349 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4350 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4351 else
4352 bgp_session_reset(peer);
4353 }
4354 } else {
4355 group = peer->group;
4356 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4357 if (peer->sort == BGP_PEER_IBGP)
4358 continue;
4359
4360 peer->ttl = group->conf->ttl;
4361
4362 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4363 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4364 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4365 else
4366 bgp_session_reset(peer);
4367 }
4368 }
4369 return 0;
4370}
4371
4372int peer_ebgp_multihop_unset(struct peer *peer)
4373{
4374 struct peer_group *group;
4375 struct listnode *node, *nnode;
4376
4377 if (peer->sort == BGP_PEER_IBGP)
4378 return 0;
4379
4380 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
4381 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4382
4383 if (peer_group_active(peer))
4384 peer->ttl = peer->group->conf->ttl;
4385 else
4386 peer->ttl = 1;
4387
4388 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4389 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4390 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4391 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4392 else
4393 bgp_session_reset(peer);
4394 } else {
4395 group = peer->group;
4396 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4397 if (peer->sort == BGP_PEER_IBGP)
4398 continue;
4399
4400 peer->ttl = 1;
4401
4402 if (peer->fd >= 0) {
4403 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4404 bgp_notify_send(
4405 peer, BGP_NOTIFY_CEASE,
4406 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4407 else
4408 bgp_session_reset(peer);
4409 }
4410 }
4411 }
4412 return 0;
4413}
4414
4415/* Neighbor description. */
4416int peer_description_set(struct peer *peer, const char *desc)
4417{
0a22ddfb 4418 XFREE(MTYPE_PEER_DESC, peer->desc);
d62a17ae 4419
4420 peer->desc = XSTRDUP(MTYPE_PEER_DESC, desc);
4421
4422 return 0;
4423}
4424
4425int peer_description_unset(struct peer *peer)
4426{
0a22ddfb 4427 XFREE(MTYPE_PEER_DESC, peer->desc);
d62a17ae 4428
4429 peer->desc = NULL;
4430
4431 return 0;
4432}
4433
4434/* Neighbor update-source. */
4435int peer_update_source_if_set(struct peer *peer, const char *ifname)
4436{
a14810f4 4437 struct peer *member;
d62a17ae 4438 struct listnode *node, *nnode;
4439
a14810f4
PM
4440 /* Set flag and configuration on peer. */
4441 peer_flag_set(peer, PEER_FLAG_UPDATE_SOURCE);
d62a17ae 4442 if (peer->update_if) {
a14810f4 4443 if (strcmp(peer->update_if, ifname) == 0)
d62a17ae 4444 return 0;
d62a17ae 4445 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
d62a17ae 4446 }
d62a17ae 4447 peer->update_if = XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, ifname);
a14810f4
PM
4448 sockunion_free(peer->update_source);
4449 peer->update_source = NULL;
d62a17ae 4450
a14810f4 4451 /* Check if handling a regular peer. */
d62a17ae 4452 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
a14810f4 4453 /* Send notification or reset peer depending on state. */
d62a17ae 4454 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
4455 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4456 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4457 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4458 } else
4459 bgp_session_reset(peer);
a14810f4
PM
4460
4461 /* Skip peer-group mechanics for regular peers. */
d62a17ae 4462 return 0;
4463 }
4464
a14810f4
PM
4465 /*
4466 * Set flag and configuration on all peer-group members, unless they are
4467 * explicitely overriding peer-group configuration.
4468 */
4469 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
4470 /* Skip peers with overridden configuration. */
4471 if (CHECK_FLAG(member->flags_override, PEER_FLAG_UPDATE_SOURCE))
4472 continue;
d62a17ae 4473
a14810f4
PM
4474 /* Skip peers with the same configuration. */
4475 if (member->update_if) {
4476 if (strcmp(member->update_if, ifname) == 0)
4477 continue;
4478 XFREE(MTYPE_PEER_UPDATE_SOURCE, member->update_if);
d62a17ae 4479 }
4480
a14810f4
PM
4481 /* Set flag and configuration on peer-group member. */
4482 SET_FLAG(member->flags, PEER_FLAG_UPDATE_SOURCE);
4483 member->update_if = XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, ifname);
4484 sockunion_free(member->update_source);
4485 member->update_source = NULL;
4486
4487 /* Send notification or reset peer depending on state. */
4488 if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) {
4489 member->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4490 bgp_notify_send(member, BGP_NOTIFY_CEASE,
d62a17ae 4491 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4492 } else
a14810f4 4493 bgp_session_reset(member);
d62a17ae 4494 }
a14810f4 4495
d62a17ae 4496 return 0;
4497}
4498
4499int peer_update_source_addr_set(struct peer *peer, const union sockunion *su)
4500{
a14810f4 4501 struct peer *member;
d62a17ae 4502 struct listnode *node, *nnode;
4503
a14810f4
PM
4504 /* Set flag and configuration on peer. */
4505 peer_flag_set(peer, PEER_FLAG_UPDATE_SOURCE);
d62a17ae 4506 if (peer->update_source) {
a14810f4 4507 if (sockunion_cmp(peer->update_source, su) == 0)
d62a17ae 4508 return 0;
4509 sockunion_free(peer->update_source);
d62a17ae 4510 }
d62a17ae 4511 peer->update_source = sockunion_dup(su);
a14810f4 4512 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
d62a17ae 4513
a14810f4 4514 /* Check if handling a regular peer. */
d62a17ae 4515 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
a14810f4 4516 /* Send notification or reset peer depending on state. */
d62a17ae 4517 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
4518 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4519 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4520 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4521 } else
4522 bgp_session_reset(peer);
a14810f4
PM
4523
4524 /* Skip peer-group mechanics for regular peers. */
d62a17ae 4525 return 0;
4526 }
4527
a14810f4
PM
4528 /*
4529 * Set flag and configuration on all peer-group members, unless they are
4530 * explicitely overriding peer-group configuration.
4531 */
4532 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
4533 /* Skip peers with overridden configuration. */
4534 if (CHECK_FLAG(member->flags_override, PEER_FLAG_UPDATE_SOURCE))
4535 continue;
d62a17ae 4536
a14810f4
PM
4537 /* Skip peers with the same configuration. */
4538 if (member->update_source) {
4539 if (sockunion_cmp(member->update_source, su) == 0)
4540 continue;
4541 sockunion_free(member->update_source);
d62a17ae 4542 }
4543
a14810f4
PM
4544 /* Set flag and configuration on peer-group member. */
4545 SET_FLAG(member->flags, PEER_FLAG_UPDATE_SOURCE);
4546 member->update_source = sockunion_dup(su);
4547 XFREE(MTYPE_PEER_UPDATE_SOURCE, member->update_if);
4548
4549 /* Send notification or reset peer depending on state. */
4550 if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) {
4551 member->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4552 bgp_notify_send(member, BGP_NOTIFY_CEASE,
d62a17ae 4553 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4554 } else
a14810f4 4555 bgp_session_reset(member);
d62a17ae 4556 }
a14810f4 4557
d62a17ae 4558 return 0;
4559}
4560
4561int peer_update_source_unset(struct peer *peer)
4562{
a14810f4 4563 struct peer *member;
d62a17ae 4564 struct listnode *node, *nnode;
4565
a14810f4 4566 if (!CHECK_FLAG(peer->flags, PEER_FLAG_UPDATE_SOURCE))
d62a17ae 4567 return 0;
4568
a14810f4
PM
4569 /* Inherit configuration from peer-group if peer is member. */
4570 if (peer_group_active(peer)) {
4571 peer_flag_inherit(peer, PEER_FLAG_UPDATE_SOURCE);
4572 PEER_SU_ATTR_INHERIT(peer, peer->group, update_source);
4573 PEER_STR_ATTR_INHERIT(peer, peer->group, update_if,
4574 MTYPE_PEER_UPDATE_SOURCE);
4575 } else {
4576 /* Otherwise remove flag and configuration from peer. */
4577 peer_flag_unset(peer, PEER_FLAG_UPDATE_SOURCE);
d62a17ae 4578 sockunion_free(peer->update_source);
4579 peer->update_source = NULL;
d62a17ae 4580 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
d62a17ae 4581 }
4582
a14810f4 4583 /* Check if handling a regular peer. */
d62a17ae 4584 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
a14810f4 4585 /* Send notification or reset peer depending on state. */
d62a17ae 4586 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
4587 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4588 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4589 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4590 } else
4591 bgp_session_reset(peer);
a14810f4
PM
4592
4593 /* Skip peer-group mechanics for regular peers. */
d62a17ae 4594 return 0;
4595 }
4596
a14810f4
PM
4597 /*
4598 * Set flag and configuration on all peer-group members, unless they are
4599 * explicitely overriding peer-group configuration.
4600 */
4601 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
4602 /* Skip peers with overridden configuration. */
4603 if (CHECK_FLAG(member->flags_override, PEER_FLAG_UPDATE_SOURCE))
d62a17ae 4604 continue;
4605
a14810f4
PM
4606 /* Skip peers with the same configuration. */
4607 if (!CHECK_FLAG(member->flags, PEER_FLAG_UPDATE_SOURCE)
4608 && !member->update_source && !member->update_if)
4609 continue;
d62a17ae 4610
a14810f4
PM
4611 /* Remove flag and configuration on peer-group member. */
4612 UNSET_FLAG(member->flags, PEER_FLAG_UPDATE_SOURCE);
4613 sockunion_free(member->update_source);
4614 member->update_source = NULL;
4615 XFREE(MTYPE_PEER_UPDATE_SOURCE, member->update_if);
4616
4617 /* Send notification or reset peer depending on state. */
4618 if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) {
4619 member->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4620 bgp_notify_send(member, BGP_NOTIFY_CEASE,
d62a17ae 4621 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4622 } else
a14810f4 4623 bgp_session_reset(member);
d62a17ae 4624 }
a14810f4 4625
d62a17ae 4626 return 0;
4627}
4628
4629int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi,
1de27621 4630 const char *rmap, struct route_map *route_map)
d62a17ae 4631{
598ce6bd 4632 struct peer *member;
d62a17ae 4633 struct listnode *node, *nnode;
4634
598ce6bd
PM
4635 /* Set flag and configuration on peer. */
4636 peer_af_flag_set(peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE);
4637 if (rmap) {
4638 if (!peer->default_rmap[afi][safi].name
4639 || strcmp(rmap, peer->default_rmap[afi][safi].name) != 0) {
d62a17ae 4640 if (peer->default_rmap[afi][safi].name)
4641 XFREE(MTYPE_ROUTE_MAP_NAME,
4642 peer->default_rmap[afi][safi].name);
598ce6bd 4643
b4897fa5 4644 route_map_counter_decrement(peer->default_rmap[afi][safi].map);
d62a17ae 4645 peer->default_rmap[afi][safi].name =
4646 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
1de27621 4647 peer->default_rmap[afi][safi].map = route_map;
b4897fa5 4648 route_map_counter_increment(route_map);
d62a17ae 4649 }
598ce6bd
PM
4650 } else if (!rmap) {
4651 if (peer->default_rmap[afi][safi].name)
4652 XFREE(MTYPE_ROUTE_MAP_NAME,
4653 peer->default_rmap[afi][safi].name);
4654
b4897fa5 4655 route_map_counter_decrement(peer->default_rmap[afi][safi].map);
598ce6bd
PM
4656 peer->default_rmap[afi][safi].name = NULL;
4657 peer->default_rmap[afi][safi].map = NULL;
d62a17ae 4658 }
4659
598ce6bd 4660 /* Check if handling a regular peer. */
d62a17ae 4661 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
598ce6bd 4662 /* Update peer route announcements. */
d62a17ae 4663 if (peer->status == Established && peer->afc_nego[afi][safi]) {
4664 update_group_adjust_peer(peer_af_find(peer, afi, safi));
4665 bgp_default_originate(peer, afi, safi, 0);
4666 bgp_announce_route(peer, afi, safi);
4667 }
598ce6bd
PM
4668
4669 /* Skip peer-group mechanics for regular peers. */
d62a17ae 4670 return 0;
4671 }
4672
598ce6bd
PM
4673 /*
4674 * Set flag and configuration on all peer-group members, unless they are
4675 * explicitely overriding peer-group configuration.
4676 */
4677 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
4678 /* Skip peers with overridden configuration. */
4679 if (CHECK_FLAG(member->af_flags_override[afi][safi],
4680 PEER_FLAG_DEFAULT_ORIGINATE))
4681 continue;
d62a17ae 4682
598ce6bd
PM
4683 /* Set flag and configuration on peer-group member. */
4684 SET_FLAG(member->af_flags[afi][safi],
4685 PEER_FLAG_DEFAULT_ORIGINATE);
d62a17ae 4686 if (rmap) {
598ce6bd 4687 if (member->default_rmap[afi][safi].name)
d62a17ae 4688 XFREE(MTYPE_ROUTE_MAP_NAME,
598ce6bd 4689 member->default_rmap[afi][safi].name);
b4897fa5 4690 route_map_counter_decrement(
4691 member->default_rmap[afi][safi].map);
598ce6bd 4692 member->default_rmap[afi][safi].name =
d62a17ae 4693 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
1de27621 4694 member->default_rmap[afi][safi].map = route_map;
b4897fa5 4695 route_map_counter_increment(route_map);
d62a17ae 4696 }
4697
598ce6bd
PM
4698 /* Update peer route announcements. */
4699 if (member->status == Established
4700 && member->afc_nego[afi][safi]) {
4701 update_group_adjust_peer(
4702 peer_af_find(member, afi, safi));
4703 bgp_default_originate(member, afi, safi, 0);
4704 bgp_announce_route(member, afi, safi);
d62a17ae 4705 }
4706 }
598ce6bd 4707
d62a17ae 4708 return 0;
4709}
4710
4711int peer_default_originate_unset(struct peer *peer, afi_t afi, safi_t safi)
4712{
598ce6bd 4713 struct peer *member;
d62a17ae 4714 struct listnode *node, *nnode;
4715
598ce6bd
PM
4716 /* Inherit configuration from peer-group if peer is member. */
4717 if (peer_group_active(peer)) {
4718 peer_af_flag_inherit(peer, afi, safi,
4719 PEER_FLAG_DEFAULT_ORIGINATE);
e7103a96
PM
4720 PEER_STR_ATTR_INHERIT(peer, peer->group,
4721 default_rmap[afi][safi].name,
4722 MTYPE_ROUTE_MAP_NAME);
4723 PEER_ATTR_INHERIT(peer, peer->group,
4724 default_rmap[afi][safi].map);
598ce6bd
PM
4725 } else {
4726 /* Otherwise remove flag and configuration from peer. */
4727 peer_af_flag_unset(peer, afi, safi,
4728 PEER_FLAG_DEFAULT_ORIGINATE);
d62a17ae 4729 if (peer->default_rmap[afi][safi].name)
4730 XFREE(MTYPE_ROUTE_MAP_NAME,
4731 peer->default_rmap[afi][safi].name);
b4897fa5 4732 route_map_counter_decrement(peer->default_rmap[afi][safi].map);
d62a17ae 4733 peer->default_rmap[afi][safi].name = NULL;
4734 peer->default_rmap[afi][safi].map = NULL;
4735 }
4736
598ce6bd 4737 /* Check if handling a regular peer. */
d62a17ae 4738 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
598ce6bd 4739 /* Update peer route announcements. */
d62a17ae 4740 if (peer->status == Established && peer->afc_nego[afi][safi]) {
4741 update_group_adjust_peer(peer_af_find(peer, afi, safi));
4742 bgp_default_originate(peer, afi, safi, 1);
4743 bgp_announce_route(peer, afi, safi);
4744 }
598ce6bd
PM
4745
4746 /* Skip peer-group mechanics for regular peers. */
d62a17ae 4747 return 0;
4748 }
4749
598ce6bd
PM
4750 /*
4751 * Remove flag and configuration from all peer-group members, unless
4752 * they are explicitely overriding peer-group configuration.
4753 */
4754 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
4755 /* Skip peers with overridden configuration. */
4756 if (CHECK_FLAG(member->af_flags_override[afi][safi],
4757 PEER_FLAG_DEFAULT_ORIGINATE))
4758 continue;
4759
4760 /* Remove flag and configuration on peer-group member. */
d62a17ae 4761 UNSET_FLAG(peer->af_flags[afi][safi],
4762 PEER_FLAG_DEFAULT_ORIGINATE);
d62a17ae 4763 if (peer->default_rmap[afi][safi].name)
4764 XFREE(MTYPE_ROUTE_MAP_NAME,
4765 peer->default_rmap[afi][safi].name);
b4897fa5 4766 route_map_counter_decrement(peer->default_rmap[afi][safi].map);
d62a17ae 4767 peer->default_rmap[afi][safi].name = NULL;
4768 peer->default_rmap[afi][safi].map = NULL;
4769
598ce6bd 4770 /* Update peer route announcements. */
d62a17ae 4771 if (peer->status == Established && peer->afc_nego[afi][safi]) {
4772 update_group_adjust_peer(peer_af_find(peer, afi, safi));
4773 bgp_default_originate(peer, afi, safi, 1);
4774 bgp_announce_route(peer, afi, safi);
4775 }
4776 }
598ce6bd 4777
d62a17ae 4778 return 0;
4779}
4780
d7c0a89a 4781int peer_port_set(struct peer *peer, uint16_t port)
d62a17ae 4782{
4783 peer->port = port;
4784 return 0;
4785}
4786
4787int peer_port_unset(struct peer *peer)
4788{
4789 peer->port = BGP_PORT_DEFAULT;
4790 return 0;
4791}
4792
4793/*
4794 * Helper function that is called after the name of the policy
4795 * being used by a peer has changed (AF specific). Automatically
4796 * initiates inbound or outbound processing as needed.
4797 */
4798static void peer_on_policy_change(struct peer *peer, afi_t afi, safi_t safi,
4799 int outbound)
4800{
4801 if (outbound) {
4802 update_group_adjust_peer(peer_af_find(peer, afi, safi));
4803 if (peer->status == Established)
4804 bgp_announce_route(peer, afi, safi);
4805 } else {
4806 if (peer->status != Established)
4807 return;
4808
4809 if (CHECK_FLAG(peer->af_flags[afi][safi],
4810 PEER_FLAG_SOFT_RECONFIG))
4811 bgp_soft_reconfig_in(peer, afi, safi);
4812 else if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4813 || CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4814 bgp_route_refresh_send(peer, afi, safi, 0, 0, 0);
4815 }
4816}
4817
4818
4819/* neighbor weight. */
d7c0a89a 4820int peer_weight_set(struct peer *peer, afi_t afi, safi_t safi, uint16_t weight)
d62a17ae 4821{
598ce6bd 4822 struct peer *member;
d62a17ae 4823 struct listnode *node, *nnode;
4824
598ce6bd
PM
4825 /* Set flag and configuration on peer. */
4826 peer_af_flag_set(peer, afi, safi, PEER_FLAG_WEIGHT);
d62a17ae 4827 if (peer->weight[afi][safi] != weight) {
4828 peer->weight[afi][safi] = weight;
d62a17ae 4829 peer_on_policy_change(peer, afi, safi, 0);
4830 }
4831
598ce6bd 4832 /* Skip peer-group mechanics for regular peers. */
d62a17ae 4833 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4834 return 0;
4835
598ce6bd
PM
4836 /*
4837 * Set flag and configuration on all peer-group members, unless they are
4838 * explicitely overriding peer-group configuration.
4839 */
4840 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
4841 /* Skip peers with overridden configuration. */
4842 if (CHECK_FLAG(member->af_flags_override[afi][safi],
4843 PEER_FLAG_WEIGHT))
4844 continue;
4845
4846 /* Set flag and configuration on peer-group member. */
4847 SET_FLAG(member->af_flags[afi][safi], PEER_FLAG_WEIGHT);
4848 if (member->weight[afi][safi] != weight) {
4849 member->weight[afi][safi] = weight;
4850 peer_on_policy_change(member, afi, safi, 0);
d62a17ae 4851 }
4852 }
598ce6bd 4853
d62a17ae 4854 return 0;
4855}
4856
4857int peer_weight_unset(struct peer *peer, afi_t afi, safi_t safi)
4858{
598ce6bd 4859 struct peer *member;
d62a17ae 4860 struct listnode *node, *nnode;
4861
598ce6bd
PM
4862 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_WEIGHT))
4863 return 0;
4864
4865 /* Inherit configuration from peer-group if peer is member. */
d62a17ae 4866 if (peer_group_active(peer)) {
598ce6bd 4867 peer_af_flag_inherit(peer, afi, safi, PEER_FLAG_WEIGHT);
e7103a96 4868 PEER_ATTR_INHERIT(peer, peer->group, weight[afi][safi]);
d62a17ae 4869
598ce6bd
PM
4870 peer_on_policy_change(peer, afi, safi, 0);
4871 return 0;
d62a17ae 4872 }
4873
598ce6bd
PM
4874 /* Remove flag and configuration from peer. */
4875 peer_af_flag_unset(peer, afi, safi, PEER_FLAG_WEIGHT);
4876 peer->weight[afi][safi] = 0;
4877 peer_on_policy_change(peer, afi, safi, 0);
d62a17ae 4878
598ce6bd
PM
4879 /* Skip peer-group mechanics for regular peers. */
4880 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4881 return 0;
d62a17ae 4882
598ce6bd
PM
4883 /*
4884 * Remove flag and configuration from all peer-group members, unless
4885 * they are explicitely overriding peer-group configuration.
4886 */
4887 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
4888 /* Skip peers with overridden configuration. */
4889 if (CHECK_FLAG(member->af_flags_override[afi][safi],
4890 PEER_FLAG_WEIGHT))
4891 continue;
4892
4893 /* Skip peers where flag is already disabled. */
4894 if (!CHECK_FLAG(member->af_flags[afi][safi], PEER_FLAG_WEIGHT))
4895 continue;
4896
4897 /* Remove flag and configuration on peer-group member. */
4898 UNSET_FLAG(member->af_flags[afi][safi], PEER_FLAG_WEIGHT);
4899 member->weight[afi][safi] = 0;
4900 peer_on_policy_change(member, afi, safi, 0);
d62a17ae 4901 }
598ce6bd 4902
d62a17ae 4903 return 0;
4904}
4905
d7c0a89a 4906int peer_timers_set(struct peer *peer, uint32_t keepalive, uint32_t holdtime)
d62a17ae 4907{
b90a8e13 4908 struct peer *member;
d62a17ae 4909 struct listnode *node, *nnode;
4910
d62a17ae 4911 if (keepalive > 65535)
4912 return BGP_ERR_INVALID_VALUE;
4913
d62a17ae 4914 if (holdtime > 65535)
4915 return BGP_ERR_INVALID_VALUE;
4916
d62a17ae 4917 if (holdtime < 3 && holdtime != 0)
4918 return BGP_ERR_INVALID_VALUE;
4919
b90a8e13
PM
4920 /* Set flag and configuration on peer. */
4921 peer_flag_set(peer, PEER_FLAG_TIMER);
d62a17ae 4922 peer->holdtime = holdtime;
4923 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
4924
b90a8e13
PM
4925 /* Skip peer-group mechanics for regular peers. */
4926 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4927 return 0;
d25e4efc 4928
b90a8e13
PM
4929 /*
4930 * Set flag and configuration on all peer-group members, unless they are
4931 * explicitely overriding peer-group configuration.
4932 */
4933 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
4934 /* Skip peers with overridden configuration. */
4935 if (CHECK_FLAG(member->flags_override, PEER_FLAG_TIMER))
4936 continue;
d25e4efc 4937
b90a8e13
PM
4938 /* Set flag and configuration on peer-group member. */
4939 SET_FLAG(member->flags, PEER_FLAG_TIMER);
4940 PEER_ATTR_INHERIT(peer, peer->group, holdtime);
4941 PEER_ATTR_INHERIT(peer, peer->group, keepalive);
d62a17ae 4942 }
d25e4efc 4943
d62a17ae 4944 return 0;
4945}
4946
4947int peer_timers_unset(struct peer *peer)
4948{
b90a8e13 4949 struct peer *member;
d62a17ae 4950 struct listnode *node, *nnode;
4951
b90a8e13
PM
4952 /* Inherit configuration from peer-group if peer is member. */
4953 if (peer_group_active(peer)) {
4954 peer_flag_inherit(peer, PEER_FLAG_TIMER);
4955 PEER_ATTR_INHERIT(peer, peer->group, holdtime);
4956 PEER_ATTR_INHERIT(peer, peer->group, keepalive);
4957 } else {
4958 /* Otherwise remove flag and configuration from peer. */
4959 peer_flag_unset(peer, PEER_FLAG_TIMER);
d25e4efc 4960 peer->holdtime = 0;
b90a8e13
PM
4961 peer->keepalive = 0;
4962 }
d25e4efc 4963
b90a8e13
PM
4964 /* Skip peer-group mechanics for regular peers. */
4965 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4966 return 0;
4967
4968 /*
4969 * Remove flag and configuration from all peer-group members, unless
4970 * they are explicitely overriding peer-group configuration.
4971 */
4972 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
4973 /* Skip peers with overridden configuration. */
4974 if (CHECK_FLAG(member->flags_override, PEER_FLAG_TIMER))
4975 continue;
d25e4efc 4976
b90a8e13
PM
4977 /* Remove flag and configuration on peer-group member. */
4978 UNSET_FLAG(member->flags, PEER_FLAG_TIMER);
4979 member->holdtime = 0;
4980 member->keepalive = 0;
d62a17ae 4981 }
4982
4983 return 0;
4984}
4985
d7c0a89a 4986int peer_timers_connect_set(struct peer *peer, uint32_t connect)
d62a17ae 4987{
b90a8e13 4988 struct peer *member;
d62a17ae 4989 struct listnode *node, *nnode;
4990
4991 if (connect > 65535)
4992 return BGP_ERR_INVALID_VALUE;
4993
b90a8e13
PM
4994 /* Set flag and configuration on peer. */
4995 peer_flag_set(peer, PEER_FLAG_TIMER_CONNECT);
d62a17ae 4996 peer->connect = connect;
d62a17ae 4997 peer->v_connect = connect;
4998
b90a8e13 4999 /* Skip peer-group mechanics for regular peers. */
d62a17ae 5000 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
5001 return 0;
5002
b90a8e13
PM
5003 /*
5004 * Set flag and configuration on all peer-group members, unless they are
5005 * explicitely overriding peer-group configuration.
5006 */
5007 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5008 /* Skip peers with overridden configuration. */
5009 if (CHECK_FLAG(member->flags_override, PEER_FLAG_TIMER_CONNECT))
5010 continue;
5011
5012 /* Set flag and configuration on peer-group member. */
5013 SET_FLAG(member->flags, PEER_FLAG_TIMER_CONNECT);
5014 member->connect = connect;
5015 member->v_connect = connect;
d62a17ae 5016 }
b90a8e13 5017
d62a17ae 5018 return 0;
5019}
5020
5021int peer_timers_connect_unset(struct peer *peer)
5022{
b90a8e13 5023 struct peer *member;
d62a17ae 5024 struct listnode *node, *nnode;
5025
b90a8e13
PM
5026 /* Inherit configuration from peer-group if peer is member. */
5027 if (peer_group_active(peer)) {
5028 peer_flag_inherit(peer, PEER_FLAG_TIMER_CONNECT);
5029 PEER_ATTR_INHERIT(peer, peer->group, connect);
5030 } else {
5031 /* Otherwise remove flag and configuration from peer. */
5032 peer_flag_unset(peer, PEER_FLAG_TIMER_CONNECT);
5033 peer->connect = 0;
5034 }
d62a17ae 5035
b90a8e13
PM
5036 /* Set timer with fallback to default value. */
5037 if (peer->connect)
5038 peer->v_connect = peer->connect;
5039 else
5040 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
d62a17ae 5041
b90a8e13 5042 /* Skip peer-group mechanics for regular peers. */
d62a17ae 5043 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
5044 return 0;
5045
b90a8e13
PM
5046 /*
5047 * Remove flag and configuration from all peer-group members, unless
5048 * they are explicitely overriding peer-group configuration.
5049 */
5050 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5051 /* Skip peers with overridden configuration. */
5052 if (CHECK_FLAG(member->flags_override, PEER_FLAG_TIMER_CONNECT))
5053 continue;
5054
5055 /* Remove flag and configuration on peer-group member. */
5056 UNSET_FLAG(member->flags, PEER_FLAG_TIMER_CONNECT);
5057 member->connect = 0;
5058 member->v_connect = BGP_DEFAULT_CONNECT_RETRY;
d62a17ae 5059 }
b90a8e13 5060
d62a17ae 5061 return 0;
5062}
5063
d7c0a89a 5064int peer_advertise_interval_set(struct peer *peer, uint32_t routeadv)
d62a17ae 5065{
b90a8e13 5066 struct peer *member;
d62a17ae 5067 struct listnode *node, *nnode;
5068
5069 if (routeadv > 600)
5070 return BGP_ERR_INVALID_VALUE;
5071
b90a8e13
PM
5072 /* Set flag and configuration on peer. */
5073 peer_flag_set(peer, PEER_FLAG_ROUTEADV);
d62a17ae 5074 peer->routeadv = routeadv;
5075 peer->v_routeadv = routeadv;
5076
b90a8e13 5077 /* Check if handling a regular peer. */
d62a17ae 5078 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
b90a8e13 5079 /* Update peer route announcements. */
d62a17ae 5080 update_group_adjust_peer_afs(peer);
5081 if (peer->status == Established)
5082 bgp_announce_route_all(peer);
b90a8e13
PM
5083
5084 /* Skip peer-group mechanics for regular peers. */
d62a17ae 5085 return 0;
5086 }
5087
b90a8e13
PM
5088 /*
5089 * Set flag and configuration on all peer-group members, unless they are
5090 * explicitely overriding peer-group configuration.
5091 */
5092 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5093 /* Skip peers with overridden configuration. */
5094 if (CHECK_FLAG(member->flags_override, PEER_FLAG_ROUTEADV))
5095 continue;
5096
5097 /* Set flag and configuration on peer-group member. */
5098 SET_FLAG(member->flags, PEER_FLAG_ROUTEADV);
5099 member->routeadv = routeadv;
5100 member->v_routeadv = routeadv;
5101
5102 /* Update peer route announcements. */
5103 update_group_adjust_peer_afs(member);
5104 if (member->status == Established)
5105 bgp_announce_route_all(member);
d62a17ae 5106 }
5107
5108 return 0;
5109}
5110
5111int peer_advertise_interval_unset(struct peer *peer)
5112{
b90a8e13 5113 struct peer *member;
d62a17ae 5114 struct listnode *node, *nnode;
5115
b90a8e13
PM
5116 /* Inherit configuration from peer-group if peer is member. */
5117 if (peer_group_active(peer)) {
5118 peer_flag_inherit(peer, PEER_FLAG_ROUTEADV);
5119 PEER_ATTR_INHERIT(peer, peer->group, routeadv);
5120 } else {
5121 /* Otherwise remove flag and configuration from peer. */
5122 peer_flag_unset(peer, PEER_FLAG_ROUTEADV);
5123 peer->routeadv = 0;
5124 }
d62a17ae 5125
b90a8e13
PM
5126 /* Set timer with fallback to default value. */
5127 if (peer->routeadv)
5128 peer->v_routeadv = peer->routeadv;
d62a17ae 5129 else
b90a8e13
PM
5130 peer->v_routeadv = (peer->sort == BGP_PEER_IBGP)
5131 ? BGP_DEFAULT_IBGP_ROUTEADV
5132 : BGP_DEFAULT_EBGP_ROUTEADV;
d62a17ae 5133
b90a8e13 5134 /* Check if handling a regular peer. */
d62a17ae 5135 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
b90a8e13 5136 /* Update peer route announcements. */
d62a17ae 5137 update_group_adjust_peer_afs(peer);
5138 if (peer->status == Established)
5139 bgp_announce_route_all(peer);
b90a8e13
PM
5140
5141 /* Skip peer-group mechanics for regular peers. */
d62a17ae 5142 return 0;
5143 }
5144
b90a8e13
PM
5145 /*
5146 * Remove flag and configuration from all peer-group members, unless
5147 * they are explicitely overriding peer-group configuration.
5148 */
5149 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5150 /* Skip peers with overridden configuration. */
5151 if (CHECK_FLAG(member->flags_override, PEER_FLAG_ROUTEADV))
5152 continue;
d62a17ae 5153
b90a8e13
PM
5154 /* Remove flag and configuration on peer-group member. */
5155 UNSET_FLAG(member->flags, PEER_FLAG_ROUTEADV);
5156 member->routeadv = 0;
5157 member->v_routeadv = (member->sort == BGP_PEER_IBGP)
5158 ? BGP_DEFAULT_IBGP_ROUTEADV
5159 : BGP_DEFAULT_EBGP_ROUTEADV;
d62a17ae 5160
b90a8e13
PM
5161 /* Update peer route announcements. */
5162 update_group_adjust_peer_afs(member);
5163 if (member->status == Established)
5164 bgp_announce_route_all(member);
d62a17ae 5165 }
5166
5167 return 0;
5168}
5169
5170/* neighbor interface */
5171void peer_interface_set(struct peer *peer, const char *str)
5172{
0a22ddfb 5173 XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
d62a17ae 5174 peer->ifname = XSTRDUP(MTYPE_BGP_PEER_IFNAME, str);
5175}
5176
5177void peer_interface_unset(struct peer *peer)
5178{
0a22ddfb 5179 XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
d62a17ae 5180 peer->ifname = NULL;
5181}
5182
5183/* Allow-as in. */
5184int peer_allowas_in_set(struct peer *peer, afi_t afi, safi_t safi,
5185 int allow_num, int origin)
5186{
598ce6bd 5187 struct peer *member;
d62a17ae 5188 struct listnode *node, *nnode;
5189
598ce6bd
PM
5190 if (!origin && (allow_num < 1 || allow_num > 10))
5191 return BGP_ERR_INVALID_VALUE;
5192
5193 /* Set flag and configuration on peer. */
5194 peer_af_flag_set(peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
d62a17ae 5195 if (origin) {
598ce6bd 5196 if (peer->allowas_in[afi][safi] != 0
d62a17ae 5197 || !CHECK_FLAG(peer->af_flags[afi][safi],
5198 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
d62a17ae 5199 peer_af_flag_set(peer, afi, safi,
5200 PEER_FLAG_ALLOWAS_IN_ORIGIN);
598ce6bd 5201 peer->allowas_in[afi][safi] = 0;
d62a17ae 5202 peer_on_policy_change(peer, afi, safi, 0);
5203 }
d62a17ae 5204 } else {
d62a17ae 5205 if (peer->allowas_in[afi][safi] != allow_num
5206 || CHECK_FLAG(peer->af_flags[afi][safi],
5207 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
598ce6bd 5208
d62a17ae 5209 peer_af_flag_unset(peer, afi, safi,
5210 PEER_FLAG_ALLOWAS_IN_ORIGIN);
598ce6bd 5211 peer->allowas_in[afi][safi] = allow_num;
d62a17ae 5212 peer_on_policy_change(peer, afi, safi, 0);
5213 }
598ce6bd 5214 }
d62a17ae 5215
598ce6bd
PM
5216 /* Skip peer-group mechanics for regular peers. */
5217 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
5218 return 0;
d62a17ae 5219
598ce6bd
PM
5220 /*
5221 * Set flag and configuration on all peer-group members, unless
5222 * they are explicitely overriding peer-group configuration.
5223 */
5224 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5225 /* Skip peers with overridden configuration. */
5226 if (CHECK_FLAG(member->af_flags_override[afi][safi],
246bb5f0 5227 PEER_FLAG_ALLOWAS_IN))
598ce6bd
PM
5228 continue;
5229
5230 /* Set flag and configuration on peer-group member. */
5231 SET_FLAG(member->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
5232 if (origin) {
5233 if (member->allowas_in[afi][safi] != 0
5234 || !CHECK_FLAG(member->af_flags[afi][safi],
cf9ac8bf 5235 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
598ce6bd 5236 SET_FLAG(member->af_flags[afi][safi],
cf9ac8bf 5237 PEER_FLAG_ALLOWAS_IN_ORIGIN);
598ce6bd
PM
5238 member->allowas_in[afi][safi] = 0;
5239 peer_on_policy_change(peer, afi, safi, 0);
5240 }
5241 } else {
5242 if (member->allowas_in[afi][safi] != allow_num
5243 || CHECK_FLAG(member->af_flags[afi][safi],
d62a17ae 5244 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
598ce6bd
PM
5245 UNSET_FLAG(member->af_flags[afi][safi],
5246 PEER_FLAG_ALLOWAS_IN_ORIGIN);
5247 member->allowas_in[afi][safi] = allow_num;
d62a17ae 5248 peer_on_policy_change(peer, afi, safi, 0);
5249 }
5250 }
5251 }
5252
5253 return 0;
5254}
5255
5256int peer_allowas_in_unset(struct peer *peer, afi_t afi, safi_t safi)
5257{
598ce6bd 5258 struct peer *member;
d62a17ae 5259 struct listnode *node, *nnode;
5260
598ce6bd
PM
5261 /* Skip peer if flag is already disabled. */
5262 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
5263 return 0;
d62a17ae 5264
598ce6bd
PM
5265 /* Inherit configuration from peer-group if peer is member. */
5266 if (peer_group_active(peer)) {
5267 peer_af_flag_inherit(peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
5268 peer_af_flag_inherit(peer, afi, safi,
cf9ac8bf 5269 PEER_FLAG_ALLOWAS_IN_ORIGIN);
e7103a96 5270 PEER_ATTR_INHERIT(peer, peer->group, allowas_in[afi][safi]);
d62a17ae 5271 peer_on_policy_change(peer, afi, safi, 0);
598ce6bd
PM
5272
5273 return 0;
5274 }
5275
5276 /* Remove flag and configuration from peer. */
5277 peer_af_flag_unset(peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
5278 peer_af_flag_unset(peer, afi, safi, PEER_FLAG_ALLOWAS_IN_ORIGIN);
5279 peer->allowas_in[afi][safi] = 0;
5280 peer_on_policy_change(peer, afi, safi, 0);
5281
5282 /* Skip peer-group mechanics if handling a regular peer. */
5283 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
5284 return 0;
5285
5286 /*
5287 * Remove flags and configuration from all peer-group members, unless
5288 * they are explicitely overriding peer-group configuration.
5289 */
5290 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5291 /* Skip peers with overridden configuration. */
5292 if (CHECK_FLAG(member->af_flags_override[afi][safi],
cf9ac8bf 5293 PEER_FLAG_ALLOWAS_IN))
598ce6bd
PM
5294 continue;
5295
5296 /* Skip peers where flag is already disabled. */
5297 if (!CHECK_FLAG(member->af_flags[afi][safi],
cf9ac8bf 5298 PEER_FLAG_ALLOWAS_IN))
598ce6bd
PM
5299 continue;
5300
5301 /* Remove flags and configuration on peer-group member. */
cf9ac8bf 5302 UNSET_FLAG(member->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
598ce6bd 5303 UNSET_FLAG(member->af_flags[afi][safi],
cf9ac8bf 5304 PEER_FLAG_ALLOWAS_IN_ORIGIN);
598ce6bd
PM
5305 member->allowas_in[afi][safi] = 0;
5306 peer_on_policy_change(member, afi, safi, 0);
d62a17ae 5307 }
5308
5309 return 0;
5310}
5311
5312int peer_local_as_set(struct peer *peer, as_t as, int no_prepend,
5313 int replace_as)
5314{
a14810f4 5315 bool old_no_prepend, old_replace_as;
d62a17ae 5316 struct bgp *bgp = peer->bgp;
a14810f4 5317 struct peer *member;
d62a17ae 5318 struct listnode *node, *nnode;
5319
5320 if (peer_sort(peer) != BGP_PEER_EBGP
5321 && peer_sort(peer) != BGP_PEER_INTERNAL)
5322 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
5323
5324 if (bgp->as == as)
5325 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
5326
5327 if (peer->as == as)
5328 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
5329
a14810f4
PM
5330 /* Save previous flag states. */
5331 old_no_prepend =
5332 !!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
5333 old_replace_as =
5334 !!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
d62a17ae 5335
a14810f4
PM
5336 /* Set flag and configuration on peer. */
5337 peer_flag_set(peer, PEER_FLAG_LOCAL_AS);
5338 peer_flag_modify(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND, no_prepend);
5339 peer_flag_modify(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS, replace_as);
d62a17ae 5340
a14810f4
PM
5341 if (peer->change_local_as == as && old_no_prepend == no_prepend
5342 && old_replace_as == replace_as)
5343 return 0;
5344 peer->change_local_as = as;
d62a17ae 5345
a14810f4 5346 /* Check if handling a regular peer. */
d62a17ae 5347 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
a14810f4 5348 /* Send notification or reset peer depending on state. */
d62a17ae 5349 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
5350 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
5351 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
5352 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5353 } else
5354 bgp_session_reset(peer);
a14810f4
PM
5355
5356 /* Skip peer-group mechanics for regular peers. */
d62a17ae 5357 return 0;
5358 }
5359
a14810f4
PM
5360 /*
5361 * Set flag and configuration on all peer-group members, unless they are
5362 * explicitely overriding peer-group configuration.
5363 */
5364 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5365 /* Skip peers with overridden configuration. */
5366 if (CHECK_FLAG(member->flags_override, PEER_FLAG_LOCAL_AS))
5367 continue;
d62a17ae 5368
a14810f4
PM
5369 /* Skip peers with the same configuration. */
5370 old_no_prepend = CHECK_FLAG(member->flags,
5371 PEER_FLAG_LOCAL_AS_NO_PREPEND);
5372 old_replace_as = CHECK_FLAG(member->flags,
5373 PEER_FLAG_LOCAL_AS_REPLACE_AS);
5374 if (member->change_local_as == as
5375 && CHECK_FLAG(member->flags, PEER_FLAG_LOCAL_AS)
5376 && old_no_prepend == no_prepend
5377 && old_replace_as == replace_as)
5378 continue;
d62a17ae 5379
a14810f4
PM
5380 /* Set flag and configuration on peer-group member. */
5381 SET_FLAG(member->flags, PEER_FLAG_LOCAL_AS);
5382 COND_FLAG(member->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND,
5383 no_prepend);
5384 COND_FLAG(member->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS,
5385 replace_as);
5386 member->change_local_as = as;
5387
5388 /* Send notification or stop peer depending on state. */
5389 if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) {
5390 member->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
5391 bgp_notify_send(member, BGP_NOTIFY_CEASE,
d62a17ae 5392 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5393 } else
a14810f4 5394 BGP_EVENT_ADD(member, BGP_Stop);
d62a17ae 5395 }
5396
5397 return 0;
5398}
5399
5400int peer_local_as_unset(struct peer *peer)
5401{
a14810f4 5402 struct peer *member;
d62a17ae 5403 struct listnode *node, *nnode;
5404
a14810f4 5405 if (!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS))
d62a17ae 5406 return 0;
5407
a14810f4
PM
5408 /* Inherit configuration from peer-group if peer is member. */
5409 if (peer_group_active(peer)) {
5410 peer_flag_inherit(peer, PEER_FLAG_LOCAL_AS);
5411 peer_flag_inherit(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND);
5412 peer_flag_inherit(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS);
5413 PEER_ATTR_INHERIT(peer, peer->group, change_local_as);
5414 } else {
5415 /* Otherwise remove flag and configuration from peer. */
5416 peer_flag_unset(peer, PEER_FLAG_LOCAL_AS);
5417 peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND);
5418 peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS);
5419 peer->change_local_as = 0;
5420 }
d62a17ae 5421
a14810f4 5422 /* Check if handling a regular peer. */
d62a17ae 5423 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
a14810f4 5424 /* Send notification or stop peer depending on state. */
d62a17ae 5425 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
5426 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
5427 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
5428 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5429 } else
5430 BGP_EVENT_ADD(peer, BGP_Stop);
5431
a14810f4 5432 /* Skip peer-group mechanics for regular peers. */
d62a17ae 5433 return 0;
5434 }
5435
a14810f4
PM
5436 /*
5437 * Remove flag and configuration from all peer-group members, unless
5438 * they are explicitely overriding peer-group configuration.
5439 */
5440 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5441 /* Skip peers with overridden configuration. */
5442 if (CHECK_FLAG(member->flags_override, PEER_FLAG_LOCAL_AS))
5443 continue;
d62a17ae 5444
a14810f4
PM
5445 /* Remove flag and configuration on peer-group member. */
5446 UNSET_FLAG(member->flags, PEER_FLAG_LOCAL_AS);
5447 UNSET_FLAG(member->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
5448 UNSET_FLAG(member->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
5449 member->change_local_as = 0;
5450
5451 /* Send notification or stop peer depending on state. */
5452 if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status)) {
5453 member->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
5454 bgp_notify_send(member, BGP_NOTIFY_CEASE,
d62a17ae 5455 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5456 } else
a14810f4 5457 bgp_session_reset(member);
d62a17ae 5458 }
a14810f4 5459
d62a17ae 5460 return 0;
5461}
5462
5463/* Set password for authenticating with the peer. */
5464int peer_password_set(struct peer *peer, const char *password)
5465{
a14810f4
PM
5466 struct peer *member;
5467 struct listnode *node, *nnode;
d62a17ae 5468 int len = password ? strlen(password) : 0;
5469 int ret = BGP_SUCCESS;
5470
5471 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
5472 return BGP_ERR_INVALID_VALUE;
5473
a14810f4
PM
5474 /* Set flag and configuration on peer. */
5475 peer_flag_set(peer, PEER_FLAG_PASSWORD);
5476 if (peer->password && strcmp(peer->password, password) == 0)
d62a17ae 5477 return 0;
a14810f4 5478 XFREE(MTYPE_PEER_PASSWORD, peer->password);
d62a17ae 5479 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
5480
a14810f4 5481 /* Check if handling a regular peer. */
d62a17ae 5482 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
a14810f4 5483 /* Send notification or reset peer depending on state. */
d62a17ae 5484 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
5485 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
5486 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5487 else
5488 bgp_session_reset(peer);
5489
a14810f4
PM
5490 /*
5491 * Attempt to install password on socket and skip peer-group
5492 * mechanics.
5493 */
d62a17ae 5494 if (BGP_PEER_SU_UNSPEC(peer))
5495 return BGP_SUCCESS;
d62a17ae 5496 return (bgp_md5_set(peer) >= 0) ? BGP_SUCCESS
5497 : BGP_ERR_TCPSIG_FAILED;
5498 }
5499
a14810f4
PM
5500 /*
5501 * Set flag and configuration on all peer-group members, unless they are
5502 * explicitely overriding peer-group configuration.
5503 */
5504 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5505 /* Skip peers with overridden configuration. */
5506 if (CHECK_FLAG(member->flags_override, PEER_FLAG_PASSWORD))
d62a17ae 5507 continue;
5508
a14810f4
PM
5509 /* Skip peers with the same password. */
5510 if (member->password && strcmp(member->password, password) == 0)
5511 continue;
d62a17ae 5512
a14810f4
PM
5513 /* Set flag and configuration on peer-group member. */
5514 SET_FLAG(member->flags, PEER_FLAG_PASSWORD);
5515 if (member->password)
5516 XFREE(MTYPE_PEER_PASSWORD, member->password);
5517 member->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
5518
5519 /* Send notification or reset peer depending on state. */
5520 if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status))
5521 bgp_notify_send(member, BGP_NOTIFY_CEASE,
d62a17ae 5522 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5523 else
a14810f4 5524 bgp_session_reset(member);
d62a17ae 5525
a14810f4
PM
5526 /* Attempt to install password on socket. */
5527 if (!BGP_PEER_SU_UNSPEC(member) && bgp_md5_set(member) < 0)
5528 ret = BGP_ERR_TCPSIG_FAILED;
d62a17ae 5529 }
5530
9e7d9a61
QY
5531 /* Set flag and configuration on all peer-group listen ranges */
5532 struct listnode *ln;
5533 struct prefix *lr;
5534
5535 for (ALL_LIST_ELEMENTS_RO(peer->group->listen_range[AFI_IP], ln, lr))
5536 bgp_md5_set_prefix(lr, password);
5537 for (ALL_LIST_ELEMENTS_RO(peer->group->listen_range[AFI_IP6], ln, lr))
5538 bgp_md5_set_prefix(lr, password);
5539
d62a17ae 5540 return ret;
5541}
5542
5543int peer_password_unset(struct peer *peer)
5544{
a14810f4
PM
5545 struct peer *member;
5546 struct listnode *node, *nnode;
d62a17ae 5547
a14810f4 5548 if (!CHECK_FLAG(peer->flags, PEER_FLAG_PASSWORD))
d62a17ae 5549 return 0;
5550
a14810f4
PM
5551 /* Inherit configuration from peer-group if peer is member. */
5552 if (peer_group_active(peer)) {
5553 peer_flag_inherit(peer, PEER_FLAG_PASSWORD);
5554 PEER_STR_ATTR_INHERIT(peer, peer->group, password,
5555 MTYPE_PEER_PASSWORD);
5556 } else {
5557 /* Otherwise remove flag and configuration from peer. */
5558 peer_flag_unset(peer, PEER_FLAG_PASSWORD);
5559 XFREE(MTYPE_PEER_PASSWORD, peer->password);
5560 }
5561
5562 /* Check if handling a regular peer. */
d62a17ae 5563 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
a14810f4 5564 /* Send notification or reset peer depending on state. */
d62a17ae 5565 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
5566 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
5567 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5568 else
5569 bgp_session_reset(peer);
5570
a14810f4 5571 /* Attempt to uninstall password on socket. */
d62a17ae 5572 if (!BGP_PEER_SU_UNSPEC(peer))
5573 bgp_md5_unset(peer);
5574
a14810f4 5575 /* Skip peer-group mechanics for regular peers. */
d62a17ae 5576 return 0;
5577 }
5578
a14810f4
PM
5579 /*
5580 * Remove flag and configuration from all peer-group members, unless
5581 * they are explicitely overriding peer-group configuration.
5582 */
5583 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5584 /* Skip peers with overridden configuration. */
5585 if (CHECK_FLAG(member->flags_override, PEER_FLAG_PASSWORD))
d62a17ae 5586 continue;
5587
a14810f4
PM
5588 /* Remove flag and configuration on peer-group member. */
5589 UNSET_FLAG(member->flags, PEER_FLAG_PASSWORD);
5590 XFREE(MTYPE_PEER_PASSWORD, member->password);
5591
5592 /* Send notification or reset peer depending on state. */
5593 if (BGP_IS_VALID_STATE_FOR_NOTIF(member->status))
5594 bgp_notify_send(member, BGP_NOTIFY_CEASE,
d62a17ae 5595 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5596 else
a14810f4 5597 bgp_session_reset(member);
d62a17ae 5598
a14810f4
PM
5599 /* Attempt to uninstall password on socket. */
5600 if (!BGP_PEER_SU_UNSPEC(member))
5601 bgp_md5_unset(member);
d62a17ae 5602 }
5603
9e7d9a61
QY
5604 /* Set flag and configuration on all peer-group listen ranges */
5605 struct listnode *ln;
5606 struct prefix *lr;
5607
5608 for (ALL_LIST_ELEMENTS_RO(peer->group->listen_range[AFI_IP], ln, lr))
5609 bgp_md5_unset_prefix(lr);
5610 for (ALL_LIST_ELEMENTS_RO(peer->group->listen_range[AFI_IP6], ln, lr))
5611 bgp_md5_unset_prefix(lr);
5612
d62a17ae 5613 return 0;
5614}
6b0655a2 5615
3f9c7369 5616
718e3744 5617/* Set distribute list to the peer. */
d62a17ae 5618int peer_distribute_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
5619 const char *name)
5620{
70ee29b4 5621 struct peer *member;
d62a17ae 5622 struct bgp_filter *filter;
d62a17ae 5623 struct listnode *node, *nnode;
5624
5625 if (direct != FILTER_IN && direct != FILTER_OUT)
5626 return BGP_ERR_INVALID_VALUE;
5627
70ee29b4 5628 /* Set configuration on peer. */
d62a17ae 5629 filter = &peer->filter[afi][safi];
d62a17ae 5630 if (filter->plist[direct].name)
5631 return BGP_ERR_PEER_FILTER_CONFLICT;
d62a17ae 5632 if (filter->dlist[direct].name)
5633 XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name);
5634 filter->dlist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
5635 filter->dlist[direct].alist = access_list_lookup(afi, name);
5636
70ee29b4 5637 /* Check if handling a regular peer. */
d62a17ae 5638 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
70ee29b4
PM
5639 /* Set override-flag and process peer route updates. */
5640 SET_FLAG(peer->filter_override[afi][safi][direct],
5641 PEER_FT_DISTRIBUTE_LIST);
d62a17ae 5642 peer_on_policy_change(peer, afi, safi,
5643 (direct == FILTER_OUT) ? 1 : 0);
70ee29b4
PM
5644
5645 /* Skip peer-group mechanics for regular peers. */
d62a17ae 5646 return 0;
5647 }
5648
70ee29b4
PM
5649 /*
5650 * Set configuration on all peer-group members, un less they are
5651 * explicitely overriding peer-group configuration.
5652 */
5653 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5654 /* Skip peers with overridden configuration. */
5655 if (CHECK_FLAG(member->filter_override[afi][safi][direct],
5656 PEER_FT_DISTRIBUTE_LIST))
5657 continue;
d62a17ae 5658
70ee29b4
PM
5659 /* Set configuration on peer-group member. */
5660 filter = &member->filter[afi][safi];
d62a17ae 5661 if (filter->dlist[direct].name)
5662 XFREE(MTYPE_BGP_FILTER_NAME,
5663 filter->dlist[direct].name);
5664 filter->dlist[direct].name =
5665 XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
5666 filter->dlist[direct].alist = access_list_lookup(afi, name);
70ee29b4
PM
5667
5668 /* Process peer route updates. */
5669 peer_on_policy_change(member, afi, safi,
d62a17ae 5670 (direct == FILTER_OUT) ? 1 : 0);
5671 }
5672
5673 return 0;
5674}
5675
5676int peer_distribute_unset(struct peer *peer, afi_t afi, safi_t safi, int direct)
5677{
70ee29b4 5678 struct peer *member;
d62a17ae 5679 struct bgp_filter *filter;
d62a17ae 5680 struct listnode *node, *nnode;
5681
5682 if (direct != FILTER_IN && direct != FILTER_OUT)
5683 return BGP_ERR_INVALID_VALUE;
5684
70ee29b4
PM
5685 /* Unset override-flag unconditionally. */
5686 UNSET_FLAG(peer->filter_override[afi][safi][direct],
5687 PEER_FT_DISTRIBUTE_LIST);
d62a17ae 5688
70ee29b4 5689 /* Inherit configuration from peer-group if peer is member. */
d62a17ae 5690 if (peer_group_active(peer)) {
e7103a96
PM
5691 PEER_STR_ATTR_INHERIT(peer, peer->group,
5692 filter[afi][safi].dlist[direct].name,
5693 MTYPE_BGP_FILTER_NAME);
5694 PEER_ATTR_INHERIT(peer, peer->group,
5695 filter[afi][safi].dlist[direct].alist);
70ee29b4
PM
5696 } else {
5697 /* Otherwise remove configuration from peer. */
5698 filter = &peer->filter[afi][safi];
5699 if (filter->dlist[direct].name)
5700 XFREE(MTYPE_BGP_FILTER_NAME,
5701 filter->dlist[direct].name);
5702 filter->dlist[direct].name = NULL;
5703 filter->dlist[direct].alist = NULL;
d62a17ae 5704 }
5705
70ee29b4 5706 /* Check if handling a regular peer. */
d62a17ae 5707 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
70ee29b4 5708 /* Process peer route updates. */
d62a17ae 5709 peer_on_policy_change(peer, afi, safi,
5710 (direct == FILTER_OUT) ? 1 : 0);
70ee29b4
PM
5711
5712 /* Skip peer-group mechanics for regular peers. */
d62a17ae 5713 return 0;
5714 }
5715
70ee29b4
PM
5716 /*
5717 * Remove configuration on all peer-group members, unless they are
5718 * explicitely overriding peer-group configuration.
5719 */
5720 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5721 /* Skip peers with overridden configuration. */
5722 if (CHECK_FLAG(member->filter_override[afi][safi][direct],
5723 PEER_FT_DISTRIBUTE_LIST))
5724 continue;
d62a17ae 5725
70ee29b4
PM
5726 /* Remove configuration on peer-group member. */
5727 filter = &member->filter[afi][safi];
d62a17ae 5728 if (filter->dlist[direct].name)
5729 XFREE(MTYPE_BGP_FILTER_NAME,
5730 filter->dlist[direct].name);
5731 filter->dlist[direct].name = NULL;
5732 filter->dlist[direct].alist = NULL;
70ee29b4
PM
5733
5734 /* Process peer route updates. */
5735 peer_on_policy_change(member, afi, safi,
d62a17ae 5736 (direct == FILTER_OUT) ? 1 : 0);
5737 }
5738
5739 return 0;
5740}
5741
5742/* Update distribute list. */
5743static void peer_distribute_update(struct access_list *access)
5744{
5745 afi_t afi;
5746 safi_t safi;
5747 int direct;
5748 struct listnode *mnode, *mnnode;
5749 struct listnode *node, *nnode;
5750 struct bgp *bgp;
5751 struct peer *peer;
5752 struct peer_group *group;
5753 struct bgp_filter *filter;
5754
5755 for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
5756 if (access->name)
5757 update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST,
5758 access->name, 0, 0);
5759 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
05c7a1cc
QY
5760 FOREACH_AFI_SAFI (afi, safi) {
5761 filter = &peer->filter[afi][safi];
5762
5763 for (direct = FILTER_IN; direct < FILTER_MAX;
5764 direct++) {
5765 if (filter->dlist[direct].name)
5766 filter->dlist[direct]
5767 .alist = access_list_lookup(
5768 afi,
d62a17ae 5769 filter->dlist[direct]
05c7a1cc
QY
5770 .name);
5771 else
5772 filter->dlist[direct].alist =
5773 NULL;
d62a17ae 5774 }
05c7a1cc 5775 }
d62a17ae 5776 }
5777 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
05c7a1cc
QY
5778 FOREACH_AFI_SAFI (afi, safi) {
5779 filter = &group->conf->filter[afi][safi];
5780
5781 for (direct = FILTER_IN; direct < FILTER_MAX;
5782 direct++) {
5783 if (filter->dlist[direct].name)
5784 filter->dlist[direct]
5785 .alist = access_list_lookup(
5786 afi,
d62a17ae 5787 filter->dlist[direct]
05c7a1cc
QY
5788 .name);
5789 else
5790 filter->dlist[direct].alist =
5791 NULL;
d62a17ae 5792 }
05c7a1cc 5793 }
d62a17ae 5794 }
5795#if ENABLE_BGP_VNC
5796 vnc_prefix_list_update(bgp);
5797#endif
5798 }
5799}
5800
5801/* Set prefix list to the peer. */
5802int peer_prefix_list_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
5803 const char *name)
5804{
70ee29b4 5805 struct peer *member;
d62a17ae 5806 struct bgp_filter *filter;
d62a17ae 5807 struct listnode *node, *nnode;
5808
5809 if (direct != FILTER_IN && direct != FILTER_OUT)
5810 return BGP_ERR_INVALID_VALUE;
5811
70ee29b4 5812 /* Set configuration on peer. */
d62a17ae 5813 filter = &peer->filter[afi][safi];
d62a17ae 5814 if (filter->dlist[direct].name)
5815 return BGP_ERR_PEER_FILTER_CONFLICT;
d62a17ae 5816 if (filter->plist[direct].name)
5817 XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name);
5818 filter->plist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
5819 filter->plist[direct].plist = prefix_list_lookup(afi, name);
5820
70ee29b4 5821 /* Check if handling a regular peer. */
d62a17ae 5822 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
70ee29b4
PM
5823 /* Set override-flag and process peer route updates. */
5824 SET_FLAG(peer->filter_override[afi][safi][direct],
5825 PEER_FT_PREFIX_LIST);
d62a17ae 5826 peer_on_policy_change(peer, afi, safi,
5827 (direct == FILTER_OUT) ? 1 : 0);
70ee29b4
PM
5828
5829 /* Skip peer-group mechanics for regular peers. */
d62a17ae 5830 return 0;
5831 }
5832
70ee29b4
PM
5833 /*
5834 * Set configuration on all peer-group members, unless they are
5835 * explicitely overriding peer-group configuration.
5836 */
5837 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5838 /* Skip peers with overridden configuration. */
5839 if (CHECK_FLAG(member->filter_override[afi][safi][direct],
5840 PEER_FT_PREFIX_LIST))
5841 continue;
d62a17ae 5842
70ee29b4
PM
5843 /* Set configuration on peer-group member. */
5844 filter = &member->filter[afi][safi];
d62a17ae 5845 if (filter->plist[direct].name)
5846 XFREE(MTYPE_BGP_FILTER_NAME,
5847 filter->plist[direct].name);
5848 filter->plist[direct].name =
5849 XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
5850 filter->plist[direct].plist = prefix_list_lookup(afi, name);
70ee29b4
PM
5851
5852 /* Process peer route updates. */
5853 peer_on_policy_change(member, afi, safi,
d62a17ae 5854 (direct == FILTER_OUT) ? 1 : 0);
5855 }
70ee29b4 5856
d62a17ae 5857 return 0;
5858}
5859
5860int peer_prefix_list_unset(struct peer *peer, afi_t afi, safi_t safi,
5861 int direct)
5862{
70ee29b4 5863 struct peer *member;
d62a17ae 5864 struct bgp_filter *filter;
d62a17ae 5865 struct listnode *node, *nnode;
5866
5867 if (direct != FILTER_IN && direct != FILTER_OUT)
5868 return BGP_ERR_INVALID_VALUE;
5869
70ee29b4
PM
5870 /* Unset override-flag unconditionally. */
5871 UNSET_FLAG(peer->filter_override[afi][safi][direct],
5872 PEER_FT_PREFIX_LIST);
d62a17ae 5873
70ee29b4 5874 /* Inherit configuration from peer-group if peer is member. */
d62a17ae 5875 if (peer_group_active(peer)) {
e7103a96
PM
5876 PEER_STR_ATTR_INHERIT(peer, peer->group,
5877 filter[afi][safi].plist[direct].name,
5878 MTYPE_BGP_FILTER_NAME);
5879 PEER_ATTR_INHERIT(peer, peer->group,
5880 filter[afi][safi].plist[direct].plist);
70ee29b4
PM
5881 } else {
5882 /* Otherwise remove configuration from peer. */
5883 filter = &peer->filter[afi][safi];
5884 if (filter->plist[direct].name)
5885 XFREE(MTYPE_BGP_FILTER_NAME,
5886 filter->plist[direct].name);
5887 filter->plist[direct].name = NULL;
5888 filter->plist[direct].plist = NULL;
d62a17ae 5889 }
5890
70ee29b4 5891 /* Check if handling a regular peer. */
d62a17ae 5892 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
70ee29b4 5893 /* Process peer route updates. */
d62a17ae 5894 peer_on_policy_change(peer, afi, safi,
5895 (direct == FILTER_OUT) ? 1 : 0);
70ee29b4
PM
5896
5897 /* Skip peer-group mechanics for regular peers. */
d62a17ae 5898 return 0;
5899 }
5900
70ee29b4
PM
5901 /*
5902 * Remove configuration on all peer-group members, unless they are
5903 * explicitely overriding peer-group configuration.
5904 */
5905 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
5906 /* Skip peers with overridden configuration. */
5907 if (CHECK_FLAG(member->filter_override[afi][safi][direct],
5908 PEER_FT_PREFIX_LIST))
5909 continue;
d62a17ae 5910
70ee29b4
PM
5911 /* Remove configuration on peer-group member. */
5912 filter = &member->filter[afi][safi];
d62a17ae 5913 if (filter->plist[direct].name)
5914 XFREE(MTYPE_BGP_FILTER_NAME,
5915 filter->plist[direct].name);
5916 filter->plist[direct].name = NULL;
5917 filter->plist[direct].plist = NULL;
70ee29b4
PM
5918
5919 /* Process peer route updates. */
5920 peer_on_policy_change(member, afi, safi,
d62a17ae 5921 (direct == FILTER_OUT) ? 1 : 0);
5922 }
5923
5924 return 0;
5925}
5926
5927/* Update prefix-list list. */
5928static void peer_prefix_list_update(struct prefix_list *plist)
5929{
5930 struct listnode *mnode, *mnnode;
5931 struct listnode *node, *nnode;
5932 struct bgp *bgp;
5933 struct peer *peer;
5934 struct peer_group *group;
5935 struct bgp_filter *filter;
5936 afi_t afi;
5937 safi_t safi;
5938 int direct;
5939
5940 for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
5941
5942 /*
5943 * Update the prefix-list on update groups.
5944 */
5945 update_group_policy_update(
5946 bgp, BGP_POLICY_PREFIX_LIST,
5947 plist ? prefix_list_name(plist) : NULL, 0, 0);
5948
5949 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
05c7a1cc
QY
5950 FOREACH_AFI_SAFI (afi, safi) {
5951 filter = &peer->filter[afi][safi];
5952
5953 for (direct = FILTER_IN; direct < FILTER_MAX;
5954 direct++) {
5955 if (filter->plist[direct].name)
5956 filter->plist[direct]
5957 .plist = prefix_list_lookup(
5958 afi,
d62a17ae 5959 filter->plist[direct]
05c7a1cc
QY
5960 .name);
5961 else
5962 filter->plist[direct].plist =
5963 NULL;
d62a17ae 5964 }
05c7a1cc 5965 }
d62a17ae 5966 }
5967 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
05c7a1cc
QY
5968 FOREACH_AFI_SAFI (afi, safi) {
5969 filter = &group->conf->filter[afi][safi];
5970
5971 for (direct = FILTER_IN; direct < FILTER_MAX;
5972 direct++) {
5973 if (filter->plist[direct].name)
5974 filter->plist[direct]
5975 .plist = prefix_list_lookup(
5976 afi,
d62a17ae 5977 filter->plist[direct]
05c7a1cc
QY
5978 .name);
5979 else
5980 filter->plist[direct].plist =
5981 NULL;
d62a17ae 5982 }
05c7a1cc 5983 }
d62a17ae 5984 }
5985 }
5986}
5987
5988int peer_aslist_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
5989 const char *name)
5990{
70ee29b4 5991 struct peer *member;
d62a17ae 5992 struct bgp_filter *filter;
d62a17ae 5993 struct listnode *node, *nnode;
5994
5995 if (direct != FILTER_IN && direct != FILTER_OUT)
5996 return BGP_ERR_INVALID_VALUE;
5997
70ee29b4 5998 /* Set configuration on peer. */
d62a17ae 5999 filter = &peer->filter[afi][safi];
d62a17ae 6000 if (filter->aslist[direct].name)
6001 XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name);
6002 filter->aslist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
6003 filter->aslist[direct].aslist = as_list_lookup(name);
6004
70ee29b4 6005 /* Check if handling a regular peer. */
d62a17ae 6006 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
70ee29b4
PM
6007 /* Set override-flag and process peer route updates. */
6008 SET_FLAG(peer->filter_override[afi][safi][direct],
6009 PEER_FT_FILTER_LIST);
d62a17ae 6010 peer_on_policy_change(peer, afi, safi,
6011 (direct == FILTER_OUT) ? 1 : 0);
70ee29b4
PM
6012
6013 /* Skip peer-group mechanics for regular peers. */
d62a17ae 6014 return 0;
6015 }
6016
70ee29b4
PM
6017 /*
6018 * Set configuration on all peer-group members, unless they are
6019 * explicitely overriding peer-group configuration.
6020 */
6021 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
6022 /* Skip peers with overridden configuration. */
6023 if (CHECK_FLAG(member->filter_override[afi][safi][direct],
6024 PEER_FT_FILTER_LIST))
6025 continue;
d62a17ae 6026
70ee29b4
PM
6027 /* Set configuration on peer-group member. */
6028 filter = &member->filter[afi][safi];
d62a17ae 6029 if (filter->aslist[direct].name)
6030 XFREE(MTYPE_BGP_FILTER_NAME,
6031 filter->aslist[direct].name);
6032 filter->aslist[direct].name =
6033 XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
6034 filter->aslist[direct].aslist = as_list_lookup(name);
70ee29b4
PM
6035
6036 /* Process peer route updates. */
6037 peer_on_policy_change(member, afi, safi,
d62a17ae 6038 (direct == FILTER_OUT) ? 1 : 0);
6039 }
70ee29b4 6040
d62a17ae 6041 return 0;
6042}
6043
6044int peer_aslist_unset(struct peer *peer, afi_t afi, safi_t safi, int direct)
6045{
70ee29b4 6046 struct peer *member;
d62a17ae 6047 struct bgp_filter *filter;
d62a17ae 6048 struct listnode *node, *nnode;
6049
6050 if (direct != FILTER_IN && direct != FILTER_OUT)
6051 return BGP_ERR_INVALID_VALUE;
6052
70ee29b4
PM
6053 /* Unset override-flag unconditionally. */
6054 UNSET_FLAG(peer->filter_override[afi][safi][direct],
6055 PEER_FT_FILTER_LIST);
d62a17ae 6056
70ee29b4 6057 /* Inherit configuration from peer-group if peer is member. */
d62a17ae 6058 if (peer_group_active(peer)) {
e7103a96
PM
6059 PEER_STR_ATTR_INHERIT(peer, peer->group,
6060 filter[afi][safi].aslist[direct].name,
6061 MTYPE_BGP_FILTER_NAME);
6062 PEER_ATTR_INHERIT(peer, peer->group,
70ee29b4
PM
6063 filter[afi][safi].aslist[direct].aslist);
6064 } else {
6065 /* Otherwise remove configuration from peer. */
6066 filter = &peer->filter[afi][safi];
6067 if (filter->aslist[direct].name)
6068 XFREE(MTYPE_BGP_FILTER_NAME,
6069 filter->aslist[direct].name);
6070 filter->aslist[direct].name = NULL;
6071 filter->aslist[direct].aslist = NULL;
d62a17ae 6072 }
6073
70ee29b4 6074 /* Check if handling a regular peer. */
d62a17ae 6075 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
70ee29b4 6076 /* Process peer route updates. */
d62a17ae 6077 peer_on_policy_change(peer, afi, safi,
6078 (direct == FILTER_OUT) ? 1 : 0);
70ee29b4
PM
6079
6080 /* Skip peer-group mechanics for regular peers. */
d62a17ae 6081 return 0;
6082 }
6083
70ee29b4
PM
6084 /*
6085 * Remove configuration on all peer-group members, unless they are
6086 * explicitely overriding peer-group configuration.
6087 */
6088 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
6089 /* Skip peers with overridden configuration. */
6090 if (CHECK_FLAG(member->filter_override[afi][safi][direct],
6091 PEER_FT_FILTER_LIST))
6092 continue;
d62a17ae 6093
70ee29b4
PM
6094 /* Remove configuration on peer-group member. */
6095 filter = &member->filter[afi][safi];
d62a17ae 6096 if (filter->aslist[direct].name)
6097 XFREE(MTYPE_BGP_FILTER_NAME,
6098 filter->aslist[direct].name);
6099 filter->aslist[direct].name = NULL;
6100 filter->aslist[direct].aslist = NULL;
70ee29b4
PM
6101
6102 /* Process peer route updates. */
6103 peer_on_policy_change(member, afi, safi,
d62a17ae 6104 (direct == FILTER_OUT) ? 1 : 0);
6105 }
6106
6107 return 0;
6108}
6109
6110static void peer_aslist_update(const char *aslist_name)
6111{
6112 afi_t afi;
6113 safi_t safi;
6114 int direct;
6115 struct listnode *mnode, *mnnode;
6116 struct listnode *node, *nnode;
6117 struct bgp *bgp;
6118 struct peer *peer;
6119 struct peer_group *group;
6120 struct bgp_filter *filter;
6121
6122 for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
6123 update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST,
6124 aslist_name, 0, 0);
6125
6126 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
05c7a1cc
QY
6127 FOREACH_AFI_SAFI (afi, safi) {
6128 filter = &peer->filter[afi][safi];
6129
6130 for (direct = FILTER_IN; direct < FILTER_MAX;
6131 direct++) {
6132 if (filter->aslist[direct].name)
6133 filter->aslist[direct]
6134 .aslist = as_list_lookup(
d62a17ae 6135 filter->aslist[direct]
05c7a1cc
QY
6136 .name);
6137 else
6138 filter->aslist[direct].aslist =
6139 NULL;
d62a17ae 6140 }
05c7a1cc 6141 }
d62a17ae 6142 }
6143 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
05c7a1cc
QY
6144 FOREACH_AFI_SAFI (afi, safi) {
6145 filter = &group->conf->filter[afi][safi];
6146
6147 for (direct = FILTER_IN; direct < FILTER_MAX;
6148 direct++) {
6149 if (filter->aslist[direct].name)
6150 filter->aslist[direct]
6151 .aslist = as_list_lookup(
d62a17ae 6152 filter->aslist[direct]
05c7a1cc
QY
6153 .name);
6154 else
6155 filter->aslist[direct].aslist =
6156 NULL;
d62a17ae 6157 }
05c7a1cc 6158 }
d62a17ae 6159 }
6160 }
6161}
6162
6163static void peer_aslist_add(char *aslist_name)
6164{
6165 peer_aslist_update(aslist_name);
6166 route_map_notify_dependencies((char *)aslist_name,
6167 RMAP_EVENT_ASLIST_ADDED);
6168}
6169
6170static void peer_aslist_del(const char *aslist_name)
6171{
6172 peer_aslist_update(aslist_name);
6173 route_map_notify_dependencies(aslist_name, RMAP_EVENT_ASLIST_DELETED);
6174}
6175
6176
6177int peer_route_map_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
1de27621 6178 const char *name, struct route_map *route_map)
d62a17ae 6179{
70ee29b4 6180 struct peer *member;
d62a17ae 6181 struct bgp_filter *filter;
d62a17ae 6182 struct listnode *node, *nnode;
6183
6184 if (direct != RMAP_IN && direct != RMAP_OUT)
6185 return BGP_ERR_INVALID_VALUE;
6186
70ee29b4 6187 /* Set configuration on peer. */
d62a17ae 6188 filter = &peer->filter[afi][safi];
1dc02a55
NT
6189 if (filter->map[direct].name) {
6190 /* If the neighbor is configured with the same route-map
6191 * again then, ignore the duplicate configuration.
6192 */
6193 if (strcmp(filter->map[direct].name, name) == 0)
6194 return 0;
6195
d62a17ae 6196 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
1dc02a55 6197 }
b4897fa5 6198 route_map_counter_decrement(filter->map[direct].map);
d62a17ae 6199 filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
1de27621 6200 filter->map[direct].map = route_map;
b4897fa5 6201 route_map_counter_increment(route_map);
d62a17ae 6202
70ee29b4 6203 /* Check if handling a regular peer. */
d62a17ae 6204 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
70ee29b4
PM
6205 /* Set override-flag and process peer route updates. */
6206 SET_FLAG(peer->filter_override[afi][safi][direct],
6207 PEER_FT_ROUTE_MAP);
d62a17ae 6208 peer_on_policy_change(peer, afi, safi,
6209 (direct == RMAP_OUT) ? 1 : 0);
70ee29b4
PM
6210
6211 /* Skip peer-group mechanics for regular peers. */
d62a17ae 6212 return 0;
6213 }
6214
70ee29b4
PM
6215 /*
6216 * Set configuration on all peer-group members, unless they are
6217 * explicitely overriding peer-group configuration.
6218 */
6219 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
6220 /* Skip peers with overridden configuration. */
6221 if (CHECK_FLAG(member->filter_override[afi][safi][direct],
6222 PEER_FT_ROUTE_MAP))
6223 continue;
d62a17ae 6224
70ee29b4
PM
6225 /* Set configuration on peer-group member. */
6226 filter = &member->filter[afi][safi];
d62a17ae 6227 if (filter->map[direct].name)
6228 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
b4897fa5 6229 route_map_counter_decrement(filter->map[direct].map);
d62a17ae 6230 filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
1de27621 6231 filter->map[direct].map = route_map;
b4897fa5 6232 route_map_counter_increment(route_map);
70ee29b4
PM
6233
6234 /* Process peer route updates. */
6235 peer_on_policy_change(member, afi, safi,
d62a17ae 6236 (direct == RMAP_OUT) ? 1 : 0);
6237 }
6238 return 0;
6239}
6240
6241/* Unset route-map from the peer. */
6242int peer_route_map_unset(struct peer *peer, afi_t afi, safi_t safi, int direct)
6243{
70ee29b4 6244 struct peer *member;
d62a17ae 6245 struct bgp_filter *filter;
d62a17ae 6246 struct listnode *node, *nnode;
6247
6248 if (direct != RMAP_IN && direct != RMAP_OUT)
6249 return BGP_ERR_INVALID_VALUE;
6250
70ee29b4
PM
6251 /* Unset override-flag unconditionally. */
6252 UNSET_FLAG(peer->filter_override[afi][safi][direct], PEER_FT_ROUTE_MAP);
d62a17ae 6253
70ee29b4 6254 /* Inherit configuration from peer-group if peer is member. */
d62a17ae 6255 if (peer_group_active(peer)) {
e7103a96
PM
6256 PEER_STR_ATTR_INHERIT(peer, peer->group,
6257 filter[afi][safi].map[direct].name,
6258 MTYPE_BGP_FILTER_NAME);
6259 PEER_ATTR_INHERIT(peer, peer->group,
6260 filter[afi][safi].map[direct].map);
70ee29b4
PM
6261 } else {
6262 /* Otherwise remove configuration from peer. */
6263 filter = &peer->filter[afi][safi];
6264 if (filter->map[direct].name)
6265 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
b4897fa5 6266 route_map_counter_decrement(filter->map[direct].map);
70ee29b4
PM
6267 filter->map[direct].name = NULL;
6268 filter->map[direct].map = NULL;
d62a17ae 6269 }
6270
70ee29b4 6271 /* Check if handling a regular peer. */
d62a17ae 6272 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
70ee29b4 6273 /* Process peer route updates. */
d62a17ae 6274 peer_on_policy_change(peer, afi, safi,
6275 (direct == RMAP_OUT) ? 1 : 0);
70ee29b4
PM
6276
6277 /* Skip peer-group mechanics for regular peers. */
d62a17ae 6278 return 0;
6279 }
6280
70ee29b4
PM
6281 /*
6282 * Remove configuration on all peer-group members, unless they are
6283 * explicitely overriding peer-group configuration.
6284 */
6285 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
6286 /* Skip peers with overridden configuration. */
6287 if (CHECK_FLAG(member->filter_override[afi][safi][direct],
6288 PEER_FT_ROUTE_MAP))
6289 continue;
d62a17ae 6290
70ee29b4
PM
6291 /* Remove configuration on peer-group member. */
6292 filter = &member->filter[afi][safi];
d62a17ae 6293 if (filter->map[direct].name)
6294 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
b4897fa5 6295 route_map_counter_decrement(filter->map[direct].map);
d62a17ae 6296 filter->map[direct].name = NULL;
6297 filter->map[direct].map = NULL;
70ee29b4
PM
6298
6299 /* Process peer route updates. */
6300 peer_on_policy_change(member, afi, safi,
d62a17ae 6301 (direct == RMAP_OUT) ? 1 : 0);
6302 }
70ee29b4 6303
d62a17ae 6304 return 0;
6305}
6306
6307/* Set unsuppress-map to the peer. */
6308int peer_unsuppress_map_set(struct peer *peer, afi_t afi, safi_t safi,
1de27621 6309 const char *name, struct route_map *route_map)
d62a17ae 6310{
70ee29b4 6311 struct peer *member;
d62a17ae 6312 struct bgp_filter *filter;
d62a17ae 6313 struct listnode *node, *nnode;
6314
70ee29b4 6315 /* Set configuration on peer. */
d62a17ae 6316 filter = &peer->filter[afi][safi];
d62a17ae 6317 if (filter->usmap.name)
6318 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
b4897fa5 6319 route_map_counter_decrement(filter->usmap.map);
d62a17ae 6320 filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
1de27621 6321 filter->usmap.map = route_map;
b4897fa5 6322 route_map_counter_increment(route_map);
d62a17ae 6323
70ee29b4 6324 /* Check if handling a regular peer. */
d62a17ae 6325 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
70ee29b4
PM
6326 /* Set override-flag and process peer route updates. */
6327 SET_FLAG(peer->filter_override[afi][safi][0],
6328 PEER_FT_UNSUPPRESS_MAP);
d62a17ae 6329 peer_on_policy_change(peer, afi, safi, 1);
70ee29b4
PM
6330
6331 /* Skip peer-group mechanics for regular peers. */
d62a17ae 6332 return 0;
6333 }
6334
70ee29b4
PM
6335 /*
6336 * Set configuration on all peer-group members, unless they are
6337 * explicitely overriding peer-group configuration.
6338 */
6339 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
6340 /* Skip peers with overridden configuration. */
246bb5f0 6341 if (CHECK_FLAG(member->filter_override[afi][safi][0],
70ee29b4
PM
6342 PEER_FT_UNSUPPRESS_MAP))
6343 continue;
d62a17ae 6344
70ee29b4
PM
6345 /* Set configuration on peer-group member. */
6346 filter = &member->filter[afi][safi];
d62a17ae 6347 if (filter->usmap.name)
6348 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
b4897fa5 6349 route_map_counter_decrement(filter->usmap.map);
d62a17ae 6350 filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
1de27621 6351 filter->usmap.map = route_map;
b4897fa5 6352 route_map_counter_increment(route_map);
70ee29b4
PM
6353
6354 /* Process peer route updates. */
6355 peer_on_policy_change(member, afi, safi, 1);
d62a17ae 6356 }
70ee29b4 6357
d62a17ae 6358 return 0;
6359}
6360
6361/* Unset route-map from the peer. */
6362int peer_unsuppress_map_unset(struct peer *peer, afi_t afi, safi_t safi)
718e3744 6363{
70ee29b4 6364 struct peer *member;
d62a17ae 6365 struct bgp_filter *filter;
d62a17ae 6366 struct listnode *node, *nnode;
6367
70ee29b4
PM
6368 /* Unset override-flag unconditionally. */
6369 UNSET_FLAG(peer->filter_override[afi][safi][0], PEER_FT_UNSUPPRESS_MAP);
718e3744 6370
70ee29b4
PM
6371 /* Inherit configuration from peer-group if peer is member. */
6372 if (peer_group_active(peer)) {
e7103a96
PM
6373 PEER_STR_ATTR_INHERIT(peer, peer->group,
6374 filter[afi][safi].usmap.name,
6375 MTYPE_BGP_FILTER_NAME);
6376 PEER_ATTR_INHERIT(peer, peer->group,
6377 filter[afi][safi].usmap.map);
70ee29b4
PM
6378 } else {
6379 /* Otherwise remove configuration from peer. */
6380 filter = &peer->filter[afi][safi];
6381 if (filter->usmap.name)
6382 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
b4897fa5 6383 route_map_counter_decrement(filter->usmap.map);
70ee29b4
PM
6384 filter->usmap.name = NULL;
6385 filter->usmap.map = NULL;
6386 }
718e3744 6387
70ee29b4 6388 /* Check if handling a regular peer. */
d62a17ae 6389 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
70ee29b4 6390 /* Process peer route updates. */
d62a17ae 6391 peer_on_policy_change(peer, afi, safi, 1);
70ee29b4
PM
6392
6393 /* Skip peer-group mechanics for regular peers. */
d62a17ae 6394 return 0;
6395 }
718e3744 6396
70ee29b4
PM
6397 /*
6398 * Remove configuration on all peer-group members, unless they are
6399 * explicitely overriding peer-group configuration.
6400 */
6401 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
6402 /* Skip peers with overridden configuration. */
6403 if (CHECK_FLAG(member->filter_override[afi][safi][0],
6404 PEER_FT_UNSUPPRESS_MAP))
6405 continue;
718e3744 6406
70ee29b4
PM
6407 /* Remove configuration on peer-group member. */
6408 filter = &member->filter[afi][safi];
d62a17ae 6409 if (filter->usmap.name)
6410 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
b4897fa5 6411 route_map_counter_decrement(filter->usmap.map);
d62a17ae 6412 filter->usmap.name = NULL;
6413 filter->usmap.map = NULL;
70ee29b4
PM
6414
6415 /* Process peer route updates. */
6416 peer_on_policy_change(member, afi, safi, 1);
d62a17ae 6417 }
70ee29b4 6418
d62a17ae 6419 return 0;
6420}
718e3744 6421
d62a17ae 6422int peer_maximum_prefix_set(struct peer *peer, afi_t afi, safi_t safi,
d7c0a89a
QY
6423 uint32_t max, uint8_t threshold, int warning,
6424 uint16_t restart)
d62a17ae 6425{
598ce6bd 6426 struct peer *member;
d62a17ae 6427 struct listnode *node, *nnode;
6428
598ce6bd
PM
6429 /* Set flags and configuration on peer. */
6430 peer_af_flag_set(peer, afi, safi, PEER_FLAG_MAX_PREFIX);
d62a17ae 6431 if (warning)
598ce6bd 6432 peer_af_flag_set(peer, afi, safi, PEER_FLAG_MAX_PREFIX_WARNING);
d62a17ae 6433 else
598ce6bd
PM
6434 peer_af_flag_unset(peer, afi, safi,
6435 PEER_FLAG_MAX_PREFIX_WARNING);
6436
04e1c5bb
QY
6437 peer->pmax[afi][safi] = max;
6438 peer->pmax_threshold[afi][safi] = threshold;
6439 peer->pmax_restart[afi][safi] = restart;
d62a17ae 6440
598ce6bd
PM
6441 /* Check if handling a regular peer. */
6442 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
6443 /* Re-check if peer violates maximum-prefix. */
d62a17ae 6444 if ((peer->status == Established) && (peer->afc[afi][safi]))
6445 bgp_maximum_prefix_overflow(peer, afi, safi, 1);
04e1c5bb 6446
598ce6bd
PM
6447 /* Skip peer-group mechanics for regular peers. */
6448 return 0;
6449 }
04e1c5bb 6450
598ce6bd
PM
6451 /*
6452 * Set flags and configuration on all peer-group members, unless they
6453 * are explicitely overriding peer-group configuration.
6454 */
6455 for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
6456 /* Skip peers with overridden configuration. */
6457 if (CHECK_FLAG(member->af_flags_override[afi][safi],
6458 PEER_FLAG_MAX_PREFIX))
6459 continue;
04e1c5bb 6460
598ce6bd
PM
6461 /* Set flag and configuration on peer-group member. */
6462 member->pmax[afi][safi] = max;
6463 member->pmax_threshold[afi][safi] = threshold;
6464 member->pmax_restart[afi][safi] = restart;
04e1c5bb 6465 if (warning)
598ce6bd 6466 SET_FLAG(member->af_flags[afi][safi],
04e1c5bb
QY
6467 PEER_FLAG_MAX_PREFIX_WARNING);
6468 else
598ce6bd 6469 UNSET_FLAG(member->af_flags[afi][safi],
04e1c5bb 6470 PEER_FLAG_MAX_PREFIX_WARNING);
598ce6bd
PM
6471
6472 /* Re-check if peer violates maximum-prefix. */
6473 if ((member->status == Established) && (member->afc[afi][safi]))
6474 bgp_maximum_prefix_overflow(member, afi, safi, 1);
d62a17ae 6475 }
718e3744 6476
d62a17ae 6477 return 0;
6478}
718e3744 6479
d62a17ae 6480int peer_maximum_prefix_unset(struct peer *peer, afi_t afi, safi_t safi)
6481{
598ce6bd
PM
6482 /* Inherit configuration from peer-group if peer is member. */
6483 if (peer_group_active(peer)) {
6484 peer_af_flag_inherit(peer, afi, safi, PEER_FLAG_MAX_PREFIX);
6485 peer_af_flag_inherit(peer, afi, safi,
6486 PEER_FLAG_MAX_PREFIX_WARNING);
e7103a96
PM
6487 PEER_ATTR_INHERIT(peer, peer->group, pmax[afi][safi]);
6488 PEER_ATTR_INHERIT(peer, peer->group, pmax_threshold[afi][safi]);
6489 PEER_ATTR_INHERIT(peer, peer->group, pmax_restart[afi][safi]);
04e1c5bb 6490
d62a17ae 6491 return 0;
04e1c5bb 6492 }
d62a17ae 6493
598ce6bd
PM
6494 /* Remove flags and configuration from peer. */
6495 peer_af_flag_unset(peer, afi, safi, PEER_FLAG_MAX_PREFIX);
6496 peer_af_flag_unset(peer, afi, safi, PEER_FLAG_MAX_PREFIX_WARNING);
6497 peer->pmax[afi][safi] = 0;
6498 peer->pmax_threshold[afi][safi] = 0;
6499 peer->pmax_restart[afi][safi] = 0;
6500
04e1c5bb 6501 /*
598ce6bd
PM
6502 * Remove flags and configuration from all peer-group members, unless
6503 * they are explicitely overriding peer-group configuration.
04e1c5bb 6504 */
6282637d
RW
6505 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
6506 struct peer *member;
6507 struct listnode *node;
598ce6bd 6508
6282637d
RW
6509 for (ALL_LIST_ELEMENTS_RO(peer->group->peer, node, member)) {
6510 /* Skip peers with overridden configuration. */
6511 if (CHECK_FLAG(member->af_flags_override[afi][safi],
6512 PEER_FLAG_MAX_PREFIX))
6513 continue;
6514
6515 /* Remove flag and configuration on peer-group member.
6516 */
6517 UNSET_FLAG(member->af_flags[afi][safi],
6518 PEER_FLAG_MAX_PREFIX);
6519 UNSET_FLAG(member->af_flags[afi][safi],
6520 PEER_FLAG_MAX_PREFIX_WARNING);
6521 member->pmax[afi][safi] = 0;
6522 member->pmax_threshold[afi][safi] = 0;
6523 member->pmax_restart[afi][safi] = 0;
6524 }
d62a17ae 6525 }
598ce6bd 6526
d62a17ae 6527 return 0;
718e3744 6528}
6529
d62a17ae 6530int is_ebgp_multihop_configured(struct peer *peer)
718e3744 6531{
d62a17ae 6532 struct peer_group *group;
6533 struct listnode *node, *nnode;
6534 struct peer *peer1;
718e3744 6535
d62a17ae 6536 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
6537 group = peer->group;
6538 if ((peer_sort(peer) != BGP_PEER_IBGP)
6539 && (group->conf->ttl != 1))
6540 return 1;
718e3744 6541
d62a17ae 6542 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer1)) {
6543 if ((peer_sort(peer1) != BGP_PEER_IBGP)
6544 && (peer1->ttl != 1))
6545 return 1;
6546 }
6547 } else {
6548 if ((peer_sort(peer) != BGP_PEER_IBGP) && (peer->ttl != 1))
6549 return 1;
6550 }
6551 return 0;
6552}
718e3744 6553
d62a17ae 6554/* Set # of hops between us and BGP peer. */
6555int peer_ttl_security_hops_set(struct peer *peer, int gtsm_hops)
6556{
6557 struct peer_group *group;
6558 struct listnode *node, *nnode;
6559 int ret;
6560
6561 zlog_debug("peer_ttl_security_hops_set: set gtsm_hops to %d for %s",
6562 gtsm_hops, peer->host);
6563
6564 /* We cannot configure ttl-security hops when ebgp-multihop is already
6565 set. For non peer-groups, the check is simple. For peer-groups,
6566 it's
6567 slightly messy, because we need to check both the peer-group
6568 structure
6569 and all peer-group members for any trace of ebgp-multihop
6570 configuration
6571 before actually applying the ttl-security rules. Cisco really made a
6572 mess of this configuration parameter, and OpenBGPD got it right.
6573 */
6574
6575 if ((peer->gtsm_hops == 0) && (peer->sort != BGP_PEER_IBGP)) {
6576 if (is_ebgp_multihop_configured(peer))
6577 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
6578
6579 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
6580 peer->gtsm_hops = gtsm_hops;
6581
6582 /* Calling ebgp multihop also resets the session.
6583 * On restart, NHT will get setup correctly as will the
6584 * min & max ttls on the socket. The return value is
6585 * irrelevant.
6586 */
6587 ret = peer_ebgp_multihop_set(peer, MAXTTL);
6588
6589 if (ret != 0)
6590 return ret;
6591 } else {
6592 group = peer->group;
6593 for (ALL_LIST_ELEMENTS(group->peer, node, nnode,
6594 peer)) {
6595 peer->gtsm_hops = group->conf->gtsm_hops;
6596
6597 /* Calling ebgp multihop also resets the
6598 * session.
6599 * On restart, NHT will get setup correctly as
6600 * will the
6601 * min & max ttls on the socket. The return
6602 * value is
6603 * irrelevant.
6604 */
6605 peer_ebgp_multihop_set(peer, MAXTTL);
6606 }
6607 }
6608 } else {
6609 /* Post the first gtsm setup or if its ibgp, maxttl setting
6610 * isn't
6611 * necessary, just set the minttl.
6612 */
6613 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
6614 peer->gtsm_hops = gtsm_hops;
6615
6616 if (peer->fd >= 0)
6617 sockopt_minttl(peer->su.sa.sa_family, peer->fd,
6618 MAXTTL + 1 - gtsm_hops);
6619 if ((peer->status < Established) && peer->doppelganger
6620 && (peer->doppelganger->fd >= 0))
6621 sockopt_minttl(peer->su.sa.sa_family,
6622 peer->doppelganger->fd,
6623 MAXTTL + 1 - gtsm_hops);
6624 } else {
6625 group = peer->group;
6626 for (ALL_LIST_ELEMENTS(group->peer, node, nnode,
6627 peer)) {
6628 peer->gtsm_hops = group->conf->gtsm_hops;
6629
6630 /* Change setting of existing peer
6631 * established then change value (may break
6632 * connectivity)
6633 * not established yet (teardown session and
6634 * restart)
6635 * no session then do nothing (will get
6636 * handled by next connection)
6637 */
6638 if (peer->fd >= 0 && peer->gtsm_hops != 0)
6639 sockopt_minttl(
6640 peer->su.sa.sa_family, peer->fd,
6641 MAXTTL + 1 - peer->gtsm_hops);
6642 if ((peer->status < Established)
6643 && peer->doppelganger
6644 && (peer->doppelganger->fd >= 0))
6645 sockopt_minttl(peer->su.sa.sa_family,
6646 peer->doppelganger->fd,
6647 MAXTTL + 1 - gtsm_hops);
6648 }
6649 }
6650 }
718e3744 6651
d62a17ae 6652 return 0;
718e3744 6653}
6654
d62a17ae 6655int peer_ttl_security_hops_unset(struct peer *peer)
6656{
6657 struct peer_group *group;
6658 struct listnode *node, *nnode;
6659 int ret = 0;
6660
6661 zlog_debug("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s",
6662 peer->host);
6663
6664 /* if a peer-group member, then reset to peer-group default rather than
6665 * 0 */
6666 if (peer_group_active(peer))
6667 peer->gtsm_hops = peer->group->conf->gtsm_hops;
6668 else
6669 peer->gtsm_hops = 0;
6670
6671 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
6672 /* Invoking ebgp_multihop_set will set the TTL back to the
6673 * original
6674 * value as well as restting the NHT and such. The session is
6675 * reset.
6676 */
6677 if (peer->sort == BGP_PEER_EBGP)
6678 ret = peer_ebgp_multihop_unset(peer);
6679 else {
6680 if (peer->fd >= 0)
6681 sockopt_minttl(peer->su.sa.sa_family, peer->fd,
6682 0);
6683
6684 if ((peer->status < Established) && peer->doppelganger
6685 && (peer->doppelganger->fd >= 0))
6686 sockopt_minttl(peer->su.sa.sa_family,
6687 peer->doppelganger->fd, 0);
6688 }
6689 } else {
6690 group = peer->group;
6691 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
6692 peer->gtsm_hops = 0;
6693 if (peer->sort == BGP_PEER_EBGP)
6694 ret = peer_ebgp_multihop_unset(peer);
6695 else {
6696 if (peer->fd >= 0)
6697 sockopt_minttl(peer->su.sa.sa_family,
6698 peer->fd, 0);
6699
6700 if ((peer->status < Established)
6701 && peer->doppelganger
6702 && (peer->doppelganger->fd >= 0))
6703 sockopt_minttl(peer->su.sa.sa_family,
6704 peer->doppelganger->fd,
6705 0);
6706 }
6707 }
6708 }
718e3744 6709
d62a17ae 6710 return ret;
6711}
6712
6713/*
6714 * If peer clear is invoked in a loop for all peers on the BGP instance,
6715 * it may end up freeing the doppelganger, and if this was the next node
6716 * to the current node, we would end up accessing the freed next node.
6717 * Pass along additional parameter which can be updated if next node
6718 * is freed; only required when walking the peer list on BGP instance.
6719 */
6720int peer_clear(struct peer *peer, struct listnode **nnode)
6721{
6722 if (!CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)) {
6723 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW)) {
6724 UNSET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
6725 if (peer->t_pmax_restart) {
6726 BGP_TIMER_OFF(peer->t_pmax_restart);
6727 if (bgp_debug_neighbor_events(peer))
6728 zlog_debug(
6729 "%s Maximum-prefix restart timer canceled",
6730 peer->host);
6731 }
6732 BGP_EVENT_ADD(peer, BGP_Start);
6733 return 0;
6734 }
6735
6736 peer->v_start = BGP_INIT_START_TIMER;
6737 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
6738 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
6739 BGP_NOTIFY_CEASE_ADMIN_RESET);
6740 else
6741 bgp_session_reset_safe(peer, nnode);
718e3744 6742 }
d62a17ae 6743 return 0;
718e3744 6744}
6b0655a2 6745
d62a17ae 6746int peer_clear_soft(struct peer *peer, afi_t afi, safi_t safi,
6747 enum bgp_clear_type stype)
718e3744 6748{
d62a17ae 6749 struct peer_af *paf;
718e3744 6750
d62a17ae 6751 if (peer->status != Established)
6752 return 0;
718e3744 6753
d62a17ae 6754 if (!peer->afc[afi][safi])
6755 return BGP_ERR_AF_UNCONFIGURED;
718e3744 6756
d62a17ae 6757 peer->rtt = sockopt_tcp_rtt(peer->fd);
718e3744 6758
d62a17ae 6759 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH) {
6760 /* Clear the "neighbor x.x.x.x default-originate" flag */
6761 paf = peer_af_find(peer, afi, safi);
6762 if (paf && paf->subgroup
6763 && CHECK_FLAG(paf->subgroup->sflags,
6764 SUBGRP_STATUS_DEFAULT_ORIGINATE))
6765 UNSET_FLAG(paf->subgroup->sflags,
6766 SUBGRP_STATUS_DEFAULT_ORIGINATE);
718e3744 6767
d62a17ae 6768 bgp_announce_route(peer, afi, safi);
6769 }
718e3744 6770
d62a17ae 6771 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX) {
6772 if (CHECK_FLAG(peer->af_cap[afi][safi],
6773 PEER_CAP_ORF_PREFIX_SM_ADV)
6774 && (CHECK_FLAG(peer->af_cap[afi][safi],
6775 PEER_CAP_ORF_PREFIX_RM_RCV)
6776 || CHECK_FLAG(peer->af_cap[afi][safi],
6777 PEER_CAP_ORF_PREFIX_RM_OLD_RCV))) {
6778 struct bgp_filter *filter = &peer->filter[afi][safi];
d7c0a89a 6779 uint8_t prefix_type;
d62a17ae 6780
6781 if (CHECK_FLAG(peer->af_cap[afi][safi],
6782 PEER_CAP_ORF_PREFIX_RM_RCV))
6783 prefix_type = ORF_TYPE_PREFIX;
6784 else
6785 prefix_type = ORF_TYPE_PREFIX_OLD;
6786
6787 if (filter->plist[FILTER_IN].plist) {
6788 if (CHECK_FLAG(peer->af_sflags[afi][safi],
6789 PEER_STATUS_ORF_PREFIX_SEND))
6790 bgp_route_refresh_send(
6791 peer, afi, safi, prefix_type,
6792 REFRESH_DEFER, 1);
6793 bgp_route_refresh_send(peer, afi, safi,
6794 prefix_type,
6795 REFRESH_IMMEDIATE, 0);
6796 } else {
6797 if (CHECK_FLAG(peer->af_sflags[afi][safi],
6798 PEER_STATUS_ORF_PREFIX_SEND))
6799 bgp_route_refresh_send(
6800 peer, afi, safi, prefix_type,
6801 REFRESH_IMMEDIATE, 1);
6802 else
6803 bgp_route_refresh_send(peer, afi, safi,
6804 0, 0, 0);
6805 }
6806 return 0;
6807 }
6808 }
718e3744 6809
d62a17ae 6810 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
6811 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX) {
6812 /* If neighbor has soft reconfiguration inbound flag.
6813 Use Adj-RIB-In database. */
6814 if (CHECK_FLAG(peer->af_flags[afi][safi],
6815 PEER_FLAG_SOFT_RECONFIG))
6816 bgp_soft_reconfig_in(peer, afi, safi);
6817 else {
6818 /* If neighbor has route refresh capability, send route
6819 refresh
6820 message to the peer. */
6821 if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV)
6822 || CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV))
6823 bgp_route_refresh_send(peer, afi, safi, 0, 0,
6824 0);
6825 else
6826 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
6827 }
6828 }
6829 return 0;
718e3744 6830}
6831
d62a17ae 6832/* Display peer uptime.*/
9f049418 6833char *peer_uptime(time_t uptime2, char *buf, size_t len, bool use_json,
d62a17ae 6834 json_object *json)
6835{
6836 time_t uptime1, epoch_tbuf;
6837 struct tm *tm;
6838
d62a17ae 6839 /* If there is no connection has been done before print `never'. */
6840 if (uptime2 == 0) {
6841 if (use_json) {
6842 json_object_string_add(json, "peerUptime", "never");
6843 json_object_int_add(json, "peerUptimeMsec", 0);
6844 } else
6845 snprintf(buf, len, "never");
6846 return buf;
6847 }
718e3744 6848
d62a17ae 6849 /* Get current time. */
6850 uptime1 = bgp_clock();
6851 uptime1 -= uptime2;
6852 tm = gmtime(&uptime1);
718e3744 6853
d62a17ae 6854 if (uptime1 < ONE_DAY_SECOND)
6855 snprintf(buf, len, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min,
6856 tm->tm_sec);
6857 else if (uptime1 < ONE_WEEK_SECOND)
6858 snprintf(buf, len, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour,
6859 tm->tm_min);
6860 else if (uptime1 < ONE_YEAR_SECOND)
6861 snprintf(buf, len, "%02dw%dd%02dh", tm->tm_yday / 7,
6862 tm->tm_yday - ((tm->tm_yday / 7) * 7), tm->tm_hour);
6863 else
6864 snprintf(buf, len, "%02dy%02dw%dd", tm->tm_year - 70,
6865 tm->tm_yday / 7,
6866 tm->tm_yday - ((tm->tm_yday / 7) * 7));
6867
6868 if (use_json) {
6869 epoch_tbuf = time(NULL) - uptime1;
6870 json_object_string_add(json, "peerUptime", buf);
6871 json_object_int_add(json, "peerUptimeMsec", uptime1 * 1000);
6872 json_object_int_add(json, "peerUptimeEstablishedEpoch",
6873 epoch_tbuf);
6874 }
718e3744 6875
d62a17ae 6876 return buf;
718e3744 6877}
6878
d62a17ae 6879static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
2b791107 6880 afi_t afi, safi_t safi)
518f0eb1 6881{
d62a17ae 6882 struct bgp_filter *filter;
d62a17ae 6883 char *addr;
518f0eb1 6884
d62a17ae 6885 addr = peer->host;
6886 filter = &peer->filter[afi][safi];
518f0eb1 6887
d62a17ae 6888 /* distribute-list. */
70ee29b4
PM
6889 if (peergroup_filter_check(peer, afi, safi, PEER_FT_DISTRIBUTE_LIST,
6890 FILTER_IN))
6891 vty_out(vty, " neighbor %s distribute-list %s in\n", addr,
6892 filter->dlist[FILTER_IN].name);
6b0655a2 6893
70ee29b4
PM
6894 if (peergroup_filter_check(peer, afi, safi, PEER_FT_DISTRIBUTE_LIST,
6895 FILTER_OUT))
2b791107 6896 vty_out(vty, " neighbor %s distribute-list %s out\n", addr,
70ee29b4 6897 filter->dlist[FILTER_OUT].name);
718e3744 6898
d62a17ae 6899 /* prefix-list. */
70ee29b4
PM
6900 if (peergroup_filter_check(peer, afi, safi, PEER_FT_PREFIX_LIST,
6901 FILTER_IN))
6902 vty_out(vty, " neighbor %s prefix-list %s in\n", addr,
6903 filter->plist[FILTER_IN].name);
718e3744 6904
70ee29b4
PM
6905 if (peergroup_filter_check(peer, afi, safi, PEER_FT_PREFIX_LIST,
6906 FILTER_OUT))
6907 vty_out(vty, " neighbor %s prefix-list %s out\n", addr,
6908 filter->plist[FILTER_OUT].name);
718e3744 6909
d62a17ae 6910 /* route-map. */
70ee29b4
PM
6911 if (peergroup_filter_check(peer, afi, safi, PEER_FT_ROUTE_MAP, RMAP_IN))
6912 vty_out(vty, " neighbor %s route-map %s in\n", addr,
6913 filter->map[RMAP_IN].name);
518f0eb1 6914
70ee29b4
PM
6915 if (peergroup_filter_check(peer, afi, safi, PEER_FT_ROUTE_MAP,
6916 RMAP_OUT))
6917 vty_out(vty, " neighbor %s route-map %s out\n", addr,
6918 filter->map[RMAP_OUT].name);
718e3744 6919
d62a17ae 6920 /* unsuppress-map */
70ee29b4 6921 if (peergroup_filter_check(peer, afi, safi, PEER_FT_UNSUPPRESS_MAP, 0))
2b791107
DL
6922 vty_out(vty, " neighbor %s unsuppress-map %s\n", addr,
6923 filter->usmap.name);
718e3744 6924
d62a17ae 6925 /* filter-list. */
70ee29b4
PM
6926 if (peergroup_filter_check(peer, afi, safi, PEER_FT_FILTER_LIST,
6927 FILTER_IN))
6928 vty_out(vty, " neighbor %s filter-list %s in\n", addr,
6929 filter->aslist[FILTER_IN].name);
718e3744 6930
70ee29b4
PM
6931 if (peergroup_filter_check(peer, afi, safi, PEER_FT_FILTER_LIST,
6932 FILTER_OUT))
2b791107 6933 vty_out(vty, " neighbor %s filter-list %s out\n", addr,
70ee29b4 6934 filter->aslist[FILTER_OUT].name);
718e3744 6935}
6936
d62a17ae 6937/* BGP peer configuration display function. */
6938static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
6939 struct peer *peer)
6940{
6941 struct peer *g_peer = NULL;
6942 char buf[SU_ADDRSTRLEN];
6943 char *addr;
6944 int if_pg_printed = FALSE;
6945 int if_ras_printed = FALSE;
6946
6947 /* Skip dynamic neighbors. */
6948 if (peer_dynamic_neighbor(peer))
6949 return;
6950
6951 if (peer->conf_if)
6952 addr = peer->conf_if;
6953 else
6954 addr = peer->host;
6955
6956 /************************************
6957 ****** Global to the neighbor ******
6958 ************************************/
6959 if (peer->conf_if) {
6960 if (CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))
6961 vty_out(vty, " neighbor %s interface v6only", addr);
6962 else
6963 vty_out(vty, " neighbor %s interface", addr);
6964
6965 if (peer_group_active(peer)) {
6966 vty_out(vty, " peer-group %s", peer->group->name);
6967 if_pg_printed = TRUE;
6968 } else if (peer->as_type == AS_SPECIFIED) {
6969 vty_out(vty, " remote-as %u", peer->as);
6970 if_ras_printed = TRUE;
6971 } else if (peer->as_type == AS_INTERNAL) {
6972 vty_out(vty, " remote-as internal");
6973 if_ras_printed = TRUE;
6974 } else if (peer->as_type == AS_EXTERNAL) {
6975 vty_out(vty, " remote-as external");
6976 if_ras_printed = TRUE;
6977 }
718e3744 6978
d62a17ae 6979 vty_out(vty, "\n");
6980 }
718e3744 6981
d62a17ae 6982 /* remote-as and peer-group */
6983 /* peer is a member of a peer-group */
6984 if (peer_group_active(peer)) {
6985 g_peer = peer->group->conf;
6986
6987 if (g_peer->as_type == AS_UNSPECIFIED && !if_ras_printed) {
6988 if (peer->as_type == AS_SPECIFIED) {
6989 vty_out(vty, " neighbor %s remote-as %u\n",
6990 addr, peer->as);
6991 } else if (peer->as_type == AS_INTERNAL) {
6992 vty_out(vty,
6993 " neighbor %s remote-as internal\n",
6994 addr);
6995 } else if (peer->as_type == AS_EXTERNAL) {
6996 vty_out(vty,
6997 " neighbor %s remote-as external\n",
6998 addr);
6999 }
7000 }
718e3744 7001
d62a17ae 7002 /* For swpX peers we displayed the peer-group
7003 * via 'neighbor swpX interface peer-group WORD' */
7004 if (!if_pg_printed)
7005 vty_out(vty, " neighbor %s peer-group %s\n", addr,
7006 peer->group->name);
7007 }
718e3744 7008
d62a17ae 7009 /* peer is NOT a member of a peer-group */
7010 else {
7011 /* peer is a peer-group, declare the peer-group */
7012 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
7013 vty_out(vty, " neighbor %s peer-group\n", addr);
7014 }
6b0655a2 7015
d62a17ae 7016 if (!if_ras_printed) {
7017 if (peer->as_type == AS_SPECIFIED) {
7018 vty_out(vty, " neighbor %s remote-as %u\n",
7019 addr, peer->as);
7020 } else if (peer->as_type == AS_INTERNAL) {
7021 vty_out(vty,
7022 " neighbor %s remote-as internal\n",
7023 addr);
7024 } else if (peer->as_type == AS_EXTERNAL) {
7025 vty_out(vty,
7026 " neighbor %s remote-as external\n",
7027 addr);
7028 }
7029 }
7030 }
718e3744 7031
d62a17ae 7032 /* local-as */
a14810f4
PM
7033 if (peergroup_flag_check(peer, PEER_FLAG_LOCAL_AS)) {
7034 vty_out(vty, " neighbor %s local-as %u", addr,
7035 peer->change_local_as);
7036 if (peergroup_flag_check(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND))
7037 vty_out(vty, " no-prepend");
7038 if (peergroup_flag_check(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS))
7039 vty_out(vty, " replace-as");
7040 vty_out(vty, "\n");
5f9adb5d 7041 }
5f9adb5d 7042
d62a17ae 7043 /* description */
7044 if (peer->desc) {
7045 vty_out(vty, " neighbor %s description %s\n", addr, peer->desc);
7046 }
fa411a21 7047
d62a17ae 7048 /* shutdown */
9fb964de
PM
7049 if (peergroup_flag_check(peer, PEER_FLAG_SHUTDOWN)) {
7050 if (peer->tx_shutdown_message)
7051 vty_out(vty, " neighbor %s shutdown message %s\n", addr,
7052 peer->tx_shutdown_message);
7053 else
7054 vty_out(vty, " neighbor %s shutdown\n", addr);
d62a17ae 7055 }
fa411a21 7056
d62a17ae 7057 /* bfd */
7058 if (peer->bfd_info) {
7059 if (!peer_group_active(peer) || !g_peer->bfd_info) {
7060 bgp_bfd_peer_config_write(vty, peer, addr);
7061 }
7062 }
e5cc509c 7063
d62a17ae 7064 /* password */
a14810f4
PM
7065 if (peergroup_flag_check(peer, PEER_FLAG_PASSWORD))
7066 vty_out(vty, " neighbor %s password %s\n", addr,
7067 peer->password);
fa411a21 7068
d62a17ae 7069 /* neighbor solo */
7070 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL)) {
7071 if (!peer_group_active(peer)) {
7072 vty_out(vty, " neighbor %s solo\n", addr);
7073 }
7074 }
fa411a21 7075
d62a17ae 7076 /* BGP port */
7077 if (peer->port != BGP_PORT_DEFAULT) {
7078 vty_out(vty, " neighbor %s port %d\n", addr, peer->port);
7079 }
e5cc509c 7080
d62a17ae 7081 /* Local interface name */
7082 if (peer->ifname) {
7083 vty_out(vty, " neighbor %s interface %s\n", addr, peer->ifname);
e5cc509c 7084 }
fa411a21 7085
d62a17ae 7086 /* passive */
9fb964de
PM
7087 if (peergroup_flag_check(peer, PEER_FLAG_PASSIVE))
7088 vty_out(vty, " neighbor %s passive\n", addr);
1ff9a340 7089
d62a17ae 7090 /* ebgp-multihop */
7091 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1
7092 && !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL)) {
7093 if (!peer_group_active(peer) || g_peer->ttl != peer->ttl) {
7094 vty_out(vty, " neighbor %s ebgp-multihop %d\n", addr,
7095 peer->ttl);
7096 }
fa411a21 7097 }
fa411a21 7098
d62a17ae 7099 /* ttl-security hops */
7100 if (peer->gtsm_hops != 0) {
7101 if (!peer_group_active(peer)
7102 || g_peer->gtsm_hops != peer->gtsm_hops) {
7103 vty_out(vty, " neighbor %s ttl-security hops %d\n",
7104 addr, peer->gtsm_hops);
7105 }
7106 }
7107
7108 /* disable-connected-check */
9fb964de
PM
7109 if (peergroup_flag_check(peer, PEER_FLAG_DISABLE_CONNECTED_CHECK))
7110 vty_out(vty, " neighbor %s disable-connected-check\n", addr);
d62a17ae 7111
47cbc09b 7112 /* enforce-first-as */
9fb964de
PM
7113 if (peergroup_flag_check(peer, PEER_FLAG_ENFORCE_FIRST_AS))
7114 vty_out(vty, " neighbor %s enforce-first-as\n", addr);
47cbc09b 7115
d62a17ae 7116 /* update-source */
a14810f4
PM
7117 if (peergroup_flag_check(peer, PEER_FLAG_UPDATE_SOURCE)) {
7118 if (peer->update_source)
d62a17ae 7119 vty_out(vty, " neighbor %s update-source %s\n", addr,
7120 sockunion2str(peer->update_source, buf,
7121 SU_ADDRSTRLEN));
a14810f4
PM
7122 else if (peer->update_if)
7123 vty_out(vty, " neighbor %s update-source %s\n", addr,
7124 peer->update_if);
d62a17ae 7125 }
7126
7127 /* advertisement-interval */
b90a8e13 7128 if (peergroup_flag_check(peer, PEER_FLAG_ROUTEADV))
d62a17ae 7129 vty_out(vty, " neighbor %s advertisement-interval %u\n", addr,
b90a8e13 7130 peer->routeadv);
d62a17ae 7131
7132 /* timers */
b90a8e13 7133 if (peergroup_flag_check(peer, PEER_FLAG_TIMER))
d62a17ae 7134 vty_out(vty, " neighbor %s timers %u %u\n", addr,
7135 peer->keepalive, peer->holdtime);
d62a17ae 7136
b90a8e13
PM
7137 /* timers connect */
7138 if (peergroup_flag_check(peer, PEER_FLAG_TIMER_CONNECT))
d62a17ae 7139 vty_out(vty, " neighbor %s timers connect %u\n", addr,
7140 peer->connect);
6b0655a2 7141
d62a17ae 7142 /* capability dynamic */
9fb964de
PM
7143 if (peergroup_flag_check(peer, PEER_FLAG_DYNAMIC_CAPABILITY))
7144 vty_out(vty, " neighbor %s capability dynamic\n", addr);
718e3744 7145
d62a17ae 7146 /* capability extended-nexthop */
9fb964de 7147 if (peergroup_flag_check(peer, PEER_FLAG_CAPABILITY_ENHE)) {
dc2f50f3
DS
7148 if (!peer->conf_if) {
7149 if (CHECK_FLAG(peer->flags_invert,
7150 PEER_FLAG_CAPABILITY_ENHE))
7151 vty_out(vty,
7152 " no neighbor %s capability extended-nexthop\n",
7153 addr);
7154 else
7155 vty_out(vty,
7156 " neighbor %s capability extended-nexthop\n",
7157 addr);
7158 }
d62a17ae 7159 }
7160
7161 /* dont-capability-negotiation */
9fb964de
PM
7162 if (peergroup_flag_check(peer, PEER_FLAG_DONT_CAPABILITY))
7163 vty_out(vty, " neighbor %s dont-capability-negotiate\n", addr);
d62a17ae 7164
7165 /* override-capability */
9fb964de
PM
7166 if (peergroup_flag_check(peer, PEER_FLAG_OVERRIDE_CAPABILITY))
7167 vty_out(vty, " neighbor %s override-capability\n", addr);
d62a17ae 7168
7169 /* strict-capability-match */
9fb964de
PM
7170 if (peergroup_flag_check(peer, PEER_FLAG_STRICT_CAP_MATCH))
7171 vty_out(vty, " neighbor %s strict-capability-match\n", addr);
0b960b4d
DW
7172}
7173
0b960b4d 7174/* BGP peer configuration display function. */
d62a17ae 7175static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
2b791107 7176 struct peer *peer, afi_t afi, safi_t safi)
d62a17ae 7177{
7178 struct peer *g_peer = NULL;
7179 char *addr;
27c05d4d 7180 bool flag_scomm, flag_secomm, flag_slcomm;
d62a17ae 7181
7182 /* Skip dynamic neighbors. */
7183 if (peer_dynamic_neighbor(peer))
7184 return;
7185
7186 if (peer->conf_if)
7187 addr = peer->conf_if;
7188 else
7189 addr = peer->host;
7190
7191 /************************************
7192 ****** Per AF to the neighbor ******
7193 ************************************/
7194 if (peer_group_active(peer)) {
7195 g_peer = peer->group->conf;
7196
7197 /* If the peer-group is active but peer is not, print a 'no
7198 * activate' */
7199 if (g_peer->afc[afi][safi] && !peer->afc[afi][safi]) {
2b791107 7200 vty_out(vty, " no neighbor %s activate\n", addr);
d62a17ae 7201 }
7202
7203 /* If the peer-group is not active but peer is, print an
7204 'activate' */
7205 else if (!g_peer->afc[afi][safi] && peer->afc[afi][safi]) {
2b791107 7206 vty_out(vty, " neighbor %s activate\n", addr);
d62a17ae 7207 }
7208 } else {
7209 if (peer->afc[afi][safi]) {
7210 if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) {
7211 if (bgp_flag_check(bgp,
7212 BGP_FLAG_NO_DEFAULT_IPV4)) {
2b791107 7213 vty_out(vty, " neighbor %s activate\n",
d62a17ae 7214 addr);
7215 }
7216 } else
2b791107 7217 vty_out(vty, " neighbor %s activate\n", addr);
d62a17ae 7218 } else {
7219 if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) {
7220 if (!bgp_flag_check(bgp,
7221 BGP_FLAG_NO_DEFAULT_IPV4)) {
2b791107 7222 vty_out(vty,
d62a17ae 7223 " no neighbor %s activate\n",
7224 addr);
7225 }
7226 }
7227 }
7228 }
7229
7230 /* addpath TX knobs */
dcc68b5e
MS
7231 if (peergroup_af_addpath_check(peer, afi, safi)) {
7232 switch (peer->addpath_type[afi][safi]) {
7233 case BGP_ADDPATH_ALL:
7234 vty_out(vty, " neighbor %s addpath-tx-all-paths\n",
7235 addr);
7236 break;
7237 case BGP_ADDPATH_BEST_PER_AS:
7238 vty_out(vty,
7239 " neighbor %s addpath-tx-bestpath-per-AS\n",
7240 addr);
7241 break;
7242 case BGP_ADDPATH_MAX:
7243 case BGP_ADDPATH_NONE:
7244 break;
7245 }
d62a17ae 7246 }
7247
7248 /* ORF capability. */
7249 if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM)
7250 || peergroup_af_flag_check(peer, afi, safi,
7251 PEER_FLAG_ORF_PREFIX_RM)) {
2b791107 7252 vty_out(vty, " neighbor %s capability orf prefix-list", addr);
d62a17ae 7253
7254 if (peergroup_af_flag_check(peer, afi, safi,
7255 PEER_FLAG_ORF_PREFIX_SM)
7256 && peergroup_af_flag_check(peer, afi, safi,
7257 PEER_FLAG_ORF_PREFIX_RM))
7258 vty_out(vty, " both");
7259 else if (peergroup_af_flag_check(peer, afi, safi,
7260 PEER_FLAG_ORF_PREFIX_SM))
7261 vty_out(vty, " send");
7262 else
7263 vty_out(vty, " receive");
7264 vty_out(vty, "\n");
7265 }
7266
7267 /* Route reflector client. */
7268 if (peergroup_af_flag_check(peer, afi, safi,
7269 PEER_FLAG_REFLECTOR_CLIENT)) {
2b791107 7270 vty_out(vty, " neighbor %s route-reflector-client\n", addr);
d62a17ae 7271 }
7272
7273 /* next-hop-self force */
7274 if (peergroup_af_flag_check(peer, afi, safi,
7275 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2b791107 7276 vty_out(vty, " neighbor %s next-hop-self force\n", addr);
d62a17ae 7277 }
7278
7279 /* next-hop-self */
7280 if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)) {
2b791107 7281 vty_out(vty, " neighbor %s next-hop-self\n", addr);
d62a17ae 7282 }
7283
7284 /* remove-private-AS */
7285 if (peergroup_af_flag_check(peer, afi, safi,
7286 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)) {
2b791107 7287 vty_out(vty, " neighbor %s remove-private-AS all replace-AS\n",
d62a17ae 7288 addr);
7289 }
7290
7291 else if (peergroup_af_flag_check(peer, afi, safi,
7292 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) {
2b791107
DL
7293 vty_out(vty, " neighbor %s remove-private-AS replace-AS\n",
7294 addr);
d62a17ae 7295 }
7296
7297 else if (peergroup_af_flag_check(peer, afi, safi,
7298 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
2b791107 7299 vty_out(vty, " neighbor %s remove-private-AS all\n", addr);
d62a17ae 7300 }
7301
7302 else if (peergroup_af_flag_check(peer, afi, safi,
7303 PEER_FLAG_REMOVE_PRIVATE_AS)) {
2b791107 7304 vty_out(vty, " neighbor %s remove-private-AS\n", addr);
d62a17ae 7305 }
7306
7307 /* as-override */
7308 if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
2b791107 7309 vty_out(vty, " neighbor %s as-override\n", addr);
d62a17ae 7310 }
7311
7312 /* send-community print. */
27c05d4d 7313 flag_scomm = peergroup_af_flag_check(peer, afi, safi,
cf9ac8bf 7314 PEER_FLAG_SEND_COMMUNITY);
27c05d4d 7315 flag_secomm = peergroup_af_flag_check(peer, afi, safi,
cf9ac8bf 7316 PEER_FLAG_SEND_EXT_COMMUNITY);
27c05d4d 7317 flag_slcomm = peergroup_af_flag_check(peer, afi, safi,
cf9ac8bf 7318 PEER_FLAG_SEND_LARGE_COMMUNITY);
27c05d4d
PM
7319
7320 if (!bgp_option_check(BGP_OPT_CONFIG_CISCO)) {
7321 if (flag_scomm && flag_secomm && flag_slcomm) {
2b791107
DL
7322 vty_out(vty, " no neighbor %s send-community all\n",
7323 addr);
d62a17ae 7324 } else {
27c05d4d 7325 if (flag_scomm)
2b791107 7326 vty_out(vty,
27c05d4d 7327 " no neighbor %s send-community\n",
d62a17ae 7328 addr);
27c05d4d 7329 if (flag_secomm)
2b791107 7330 vty_out(vty,
d62a17ae 7331 " no neighbor %s send-community extended\n",
7332 addr);
d62a17ae 7333
27c05d4d 7334 if (flag_slcomm)
2b791107 7335 vty_out(vty,
27c05d4d
PM
7336 " no neighbor %s send-community large\n",
7337 addr);
7338 }
7339 } else {
7340 if (flag_scomm && flag_secomm && flag_slcomm) {
7341 vty_out(vty, " neighbor %s send-community all\n",
7342 addr);
7343 } else if (flag_scomm && flag_secomm) {
7344 vty_out(vty, " neighbor %s send-community both\n",
7345 addr);
7346 } else {
7347 if (flag_scomm)
7348 vty_out(vty, " neighbor %s send-community\n",
7349 addr);
7350 if (flag_secomm)
7351 vty_out(vty,
7352 " neighbor %s send-community extended\n",
7353 addr);
7354 if (flag_slcomm)
7355 vty_out(vty,
7356 " neighbor %s send-community large\n",
d62a17ae 7357 addr);
d62a17ae 7358 }
7359 }
7360
7361 /* Default information */
7362 if (peergroup_af_flag_check(peer, afi, safi,
598ce6bd 7363 PEER_FLAG_DEFAULT_ORIGINATE)) {
2b791107 7364 vty_out(vty, " neighbor %s default-originate", addr);
598ce6bd 7365
d62a17ae 7366 if (peer->default_rmap[afi][safi].name)
7367 vty_out(vty, " route-map %s",
7368 peer->default_rmap[afi][safi].name);
598ce6bd 7369
d62a17ae 7370 vty_out(vty, "\n");
7371 }
7372
7373 /* Soft reconfiguration inbound. */
7374 if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_SOFT_RECONFIG)) {
2b791107
DL
7375 vty_out(vty, " neighbor %s soft-reconfiguration inbound\n",
7376 addr);
d62a17ae 7377 }
7378
7379 /* maximum-prefix. */
598ce6bd
PM
7380 if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_MAX_PREFIX)) {
7381 vty_out(vty, " neighbor %s maximum-prefix %lu", addr,
7382 peer->pmax[afi][safi]);
7383
7384 if (peer->pmax_threshold[afi][safi]
7385 != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
7386 vty_out(vty, " %u", peer->pmax_threshold[afi][safi]);
7387 if (peer_af_flag_check(peer, afi, safi,
d62a17ae 7388 PEER_FLAG_MAX_PREFIX_WARNING))
598ce6bd
PM
7389 vty_out(vty, " warning-only");
7390 if (peer->pmax_restart[afi][safi])
7391 vty_out(vty, " restart %u",
7392 peer->pmax_restart[afi][safi]);
7393
7394 vty_out(vty, "\n");
7395 }
d62a17ae 7396
7397 /* Route server client. */
7398 if (peergroup_af_flag_check(peer, afi, safi,
7399 PEER_FLAG_RSERVER_CLIENT)) {
2b791107 7400 vty_out(vty, " neighbor %s route-server-client\n", addr);
d62a17ae 7401 }
7402
7403 /* Nexthop-local unchanged. */
7404 if (peergroup_af_flag_check(peer, afi, safi,
7405 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)) {
2b791107 7406 vty_out(vty, " neighbor %s nexthop-local unchanged\n", addr);
d62a17ae 7407 }
7408
7409 /* allowas-in <1-10> */
598ce6bd
PM
7410 if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ALLOWAS_IN)) {
7411 if (peer_af_flag_check(peer, afi, safi,
7412 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
2b791107 7413 vty_out(vty, " neighbor %s allowas-in origin\n", addr);
598ce6bd
PM
7414 } else if (peer->allowas_in[afi][safi] == 3) {
7415 vty_out(vty, " neighbor %s allowas-in\n", addr);
7416 } else {
7417 vty_out(vty, " neighbor %s allowas-in %d\n", addr,
cf9ac8bf 7418 peer->allowas_in[afi][safi]);
d62a17ae 7419 }
7420 }
7421
7422 /* weight */
598ce6bd
PM
7423 if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_WEIGHT))
7424 vty_out(vty, " neighbor %s weight %lu\n", addr,
7425 peer->weight[afi][safi]);
d62a17ae 7426
7427 /* Filter. */
2b791107 7428 bgp_config_write_filter(vty, peer, afi, safi);
d62a17ae 7429
7430 /* atribute-unchanged. */
a4d82a8a 7431 if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED)
3518f352
DS
7432 || (safi != SAFI_EVPN
7433 && peer_af_flag_check(peer, afi, safi,
7434 PEER_FLAG_NEXTHOP_UNCHANGED))
a4d82a8a
PZ
7435 || peer_af_flag_check(peer, afi, safi, PEER_FLAG_MED_UNCHANGED)) {
7436
7437 if (!peer_group_active(peer)
7438 || peergroup_af_flag_check(peer, afi, safi,
7439 PEER_FLAG_AS_PATH_UNCHANGED)
7440 || peergroup_af_flag_check(peer, afi, safi,
7441 PEER_FLAG_NEXTHOP_UNCHANGED)
7442 || peergroup_af_flag_check(peer, afi, safi,
7443 PEER_FLAG_MED_UNCHANGED)) {
8eeb0335 7444
2b791107 7445 vty_out(vty,
d62a17ae 7446 " neighbor %s attribute-unchanged%s%s%s\n",
7447 addr,
60466a63
QY
7448 peer_af_flag_check(peer, afi, safi,
7449 PEER_FLAG_AS_PATH_UNCHANGED)
d62a17ae 7450 ? " as-path"
7451 : "",
60466a63
QY
7452 peer_af_flag_check(peer, afi, safi,
7453 PEER_FLAG_NEXTHOP_UNCHANGED)
d62a17ae 7454 ? " next-hop"
7455 : "",
8eeb0335
DW
7456 peer_af_flag_check(peer, afi, safi,
7457 PEER_FLAG_MED_UNCHANGED)
d62a17ae 7458 ? " med"
7459 : "");
7460 }
7461 }
718e3744 7462}
7463
2b791107
DL
7464/* Address family based peer configuration display. */
7465static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
7466 safi_t safi)
d62a17ae 7467{
2b791107
DL
7468 struct peer *peer;
7469 struct peer_group *group;
7470 struct listnode *node, *nnode;
d62a17ae 7471
d62a17ae 7472
2b791107 7473 vty_frame(vty, " !\n address-family ");
d62a17ae 7474 if (afi == AFI_IP) {
7475 if (safi == SAFI_UNICAST)
2b791107 7476 vty_frame(vty, "ipv4 unicast");
d62a17ae 7477 else if (safi == SAFI_LABELED_UNICAST)
2b791107 7478 vty_frame(vty, "ipv4 labeled-unicast");
d62a17ae 7479 else if (safi == SAFI_MULTICAST)
2b791107 7480 vty_frame(vty, "ipv4 multicast");
d62a17ae 7481 else if (safi == SAFI_MPLS_VPN)
2b791107 7482 vty_frame(vty, "ipv4 vpn");
d62a17ae 7483 else if (safi == SAFI_ENCAP)
2b791107 7484 vty_frame(vty, "ipv4 encap");
7c40bf39 7485 else if (safi == SAFI_FLOWSPEC)
7486 vty_frame(vty, "ipv4 flowspec");
d62a17ae 7487 } else if (afi == AFI_IP6) {
7488 if (safi == SAFI_UNICAST)
2b791107 7489 vty_frame(vty, "ipv6 unicast");
d62a17ae 7490 else if (safi == SAFI_LABELED_UNICAST)
2b791107 7491 vty_frame(vty, "ipv6 labeled-unicast");
d62a17ae 7492 else if (safi == SAFI_MULTICAST)
2b791107 7493 vty_frame(vty, "ipv6 multicast");
d62a17ae 7494 else if (safi == SAFI_MPLS_VPN)
2b791107 7495 vty_frame(vty, "ipv6 vpn");
d62a17ae 7496 else if (safi == SAFI_ENCAP)
2b791107 7497 vty_frame(vty, "ipv6 encap");
7c40bf39 7498 else if (safi == SAFI_FLOWSPEC)
7499 vty_frame(vty, "ipv6 flowspec");
d62a17ae 7500 } else if (afi == AFI_L2VPN) {
7501 if (safi == SAFI_EVPN)
2b791107 7502 vty_frame(vty, "l2vpn evpn");
d62a17ae 7503 }
2b791107 7504 vty_frame(vty, "\n");
718e3744 7505
2b791107 7506 bgp_config_write_distance(vty, bgp, afi, safi);
718e3744 7507
2b791107 7508 bgp_config_write_network(vty, bgp, afi, safi);
734b349e 7509
2b791107 7510 bgp_config_write_redistribute(vty, bgp, afi, safi);
718e3744 7511
d62a17ae 7512 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group))
2b791107 7513 bgp_config_write_peer_af(vty, bgp, group->conf, afi, safi);
400b1fad 7514
d62a17ae 7515 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
7516 /* Skip dynamic neighbors. */
7517 if (peer_dynamic_neighbor(peer))
7518 continue;
f14e6fdb 7519
d62a17ae 7520 /* Do not display doppelganger peers */
7521 if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
2b791107 7522 bgp_config_write_peer_af(vty, bgp, peer, afi, safi);
d62a17ae 7523 }
165b5fff 7524
2b791107
DL
7525 bgp_config_write_maxpaths(vty, bgp, afi, safi);
7526 bgp_config_write_table_map(vty, bgp, afi, safi);
165b5fff 7527
d62a17ae 7528 if (safi == SAFI_EVPN)
2b791107 7529 bgp_config_write_evpn_info(vty, bgp, afi, safi);
718e3744 7530
4762c213
PG
7531 if (safi == SAFI_FLOWSPEC)
7532 bgp_fs_config_write_pbr(vty, bgp, afi, safi);
7533
b9c7bc5a
PZ
7534 if (safi == SAFI_UNICAST) {
7535 bgp_vpn_policy_config_write_afi(vty, bgp, afi);
7536 if (CHECK_FLAG(bgp->af_flags[afi][safi],
7537 BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)) {
ddb5b488 7538
b9c7bc5a
PZ
7539 vty_out(vty, " export vpn\n");
7540 }
7541 if (CHECK_FLAG(bgp->af_flags[afi][safi],
7542 BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT)) {
7543
7544 vty_out(vty, " import vpn\n");
7545 }
12a844a5
DS
7546 if (CHECK_FLAG(bgp->af_flags[afi][safi],
7547 BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
12a844a5
DS
7548 char *name;
7549
7550 for (ALL_LIST_ELEMENTS_RO(
7551 bgp->vpn_policy[afi].import_vrf, node,
7552 name))
7553 vty_out(vty, " import vrf %s\n", name);
7554 }
ddb5b488
PZ
7555 }
7556
2b791107 7557 vty_endframe(vty, " exit-address-family\n");
718e3744 7558}
7559
47cbc09b 7560/* clang-format off */
ec4f0750 7561#if CONFDATE > 20190517
47cbc09b
PM
7562CPP_NOTICE("bgpd: remove 'bgp enforce-first-as' config migration from bgp_config_write")
7563#endif
7564/* clang-format on */
7565
d62a17ae 7566int bgp_config_write(struct vty *vty)
718e3744 7567{
d62a17ae 7568 int write = 0;
7569 struct bgp *bgp;
7570 struct peer_group *group;
7571 struct peer *peer;
7572 struct listnode *node, *nnode;
7573 struct listnode *mnode, *mnnode;
718e3744 7574
d62a17ae 7575 /* BGP Multiple instance. */
7576 if (!bgp_option_check(BGP_OPT_MULTIPLE_INSTANCE)) {
7577 vty_out(vty, "no bgp multiple-instance\n");
7578 write++;
7579 }
718e3744 7580
d62a17ae 7581 /* BGP Config type. */
7582 if (bgp_option_check(BGP_OPT_CONFIG_CISCO)) {
7583 vty_out(vty, "bgp config-type cisco\n");
7584 write++;
7585 }
718e3744 7586
d62a17ae 7587 if (bm->rmap_update_timer != RMAP_DEFAULT_UPDATE_TIMER)
7588 vty_out(vty, "bgp route-map delay-timer %u\n",
7589 bm->rmap_update_timer);
7590
2b791107
DL
7591 if (write)
7592 vty_out(vty, "!\n");
7593
d62a17ae 7594 /* BGP configuration. */
7595 for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
0b5131c9
MK
7596
7597 /* skip all auto created vrf as they dont have user config */
7598 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO))
7599 continue;
7600
47cbc09b
PM
7601 /* Migrate deprecated 'bgp enforce-first-as'
7602 * config to 'neighbor * enforce-first-as' configs
7603 */
7604 if (bgp_flag_check(bgp, BGP_FLAG_ENFORCE_FIRST_AS)) {
7605 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
7606 peer_flag_set(peer, PEER_FLAG_ENFORCE_FIRST_AS);
7607 bgp_flag_unset(bgp, BGP_FLAG_ENFORCE_FIRST_AS);
7608 }
7609
d62a17ae 7610 /* Router bgp ASN */
7611 vty_out(vty, "router bgp %u", bgp->as);
7612
7613 if (bgp_option_check(BGP_OPT_MULTIPLE_INSTANCE)) {
7614 if (bgp->name)
7615 vty_out(vty, " %s %s",
7616 (bgp->inst_type
7617 == BGP_INSTANCE_TYPE_VIEW)
7618 ? "view"
7619 : "vrf",
7620 bgp->name);
7621 }
7622 vty_out(vty, "\n");
7623
7624 /* No Synchronization */
7625 if (bgp_option_check(BGP_OPT_CONFIG_CISCO))
7626 vty_out(vty, " no synchronization\n");
7627
7628 /* BGP fast-external-failover. */
7629 if (CHECK_FLAG(bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
7630 vty_out(vty, " no bgp fast-external-failover\n");
7631
7632 /* BGP router ID. */
7633 if (bgp->router_id_static.s_addr != 0)
7634 vty_out(vty, " bgp router-id %s\n",
7635 inet_ntoa(bgp->router_id_static));
7636
7637 /* BGP log-neighbor-changes. */
7638 if (!!bgp_flag_check(bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES)
7639 != DFLT_BGP_LOG_NEIGHBOR_CHANGES)
7640 vty_out(vty, " %sbgp log-neighbor-changes\n",
7641 bgp_flag_check(bgp,
7642 BGP_FLAG_LOG_NEIGHBOR_CHANGES)
7643 ? ""
7644 : "no ");
7645
7646 /* BGP configuration. */
7647 if (bgp_flag_check(bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
7648 vty_out(vty, " bgp always-compare-med\n");
7649
9dac9fc8
DA
7650 /* RFC8212 default eBGP policy. */
7651 if (bgp->ebgp_requires_policy
7652 == DEFAULT_EBGP_POLICY_ENABLED)
7653 vty_out(vty, " bgp ebgp-requires-policy\n");
7654
d62a17ae 7655 /* BGP default ipv4-unicast. */
7656 if (bgp_flag_check(bgp, BGP_FLAG_NO_DEFAULT_IPV4))
7657 vty_out(vty, " no bgp default ipv4-unicast\n");
7658
7659 /* BGP default local-preference. */
7660 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
7661 vty_out(vty, " bgp default local-preference %u\n",
7662 bgp->default_local_pref);
7663
7664 /* BGP default show-hostname */
7665 if (!!bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME)
7666 != DFLT_BGP_SHOW_HOSTNAME)
7667 vty_out(vty, " %sbgp default show-hostname\n",
7668 bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME)
7669 ? ""
7670 : "no ");
7671
7672 /* BGP default subgroup-pkt-queue-max. */
7673 if (bgp->default_subgroup_pkt_queue_max
7674 != BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX)
7675 vty_out(vty, " bgp default subgroup-pkt-queue-max %u\n",
7676 bgp->default_subgroup_pkt_queue_max);
7677
7678 /* BGP client-to-client reflection. */
7679 if (bgp_flag_check(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
7680 vty_out(vty, " no bgp client-to-client reflection\n");
7681
7682 /* BGP cluster ID. */
7683 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CLUSTER_ID))
7684 vty_out(vty, " bgp cluster-id %s\n",
7685 inet_ntoa(bgp->cluster_id));
7686
7687 /* Disable ebgp connected nexthop check */
7688 if (bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
7689 vty_out(vty,
7690 " bgp disable-ebgp-connected-route-check\n");
7691
7692 /* Confederation identifier*/
7693 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
3c195d60 7694 vty_out(vty, " bgp confederation identifier %u\n",
d62a17ae 7695 bgp->confed_id);
7696
7697 /* Confederation peer */
7698 if (bgp->confed_peers_cnt > 0) {
7699 int i;
7700
7701 vty_out(vty, " bgp confederation peers");
7702
7703 for (i = 0; i < bgp->confed_peers_cnt; i++)
7704 vty_out(vty, " %u", bgp->confed_peers[i]);
7705
7706 vty_out(vty, "\n");
7707 }
5fe9f963 7708
d62a17ae 7709 /* BGP deterministic-med. */
7710 if (!!bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)
7711 != DFLT_BGP_DETERMINISTIC_MED)
7712 vty_out(vty, " %sbgp deterministic-med\n",
7713 bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)
7714 ? ""
7715 : "no ");
7716
7717 /* BGP update-delay. */
7718 bgp_config_write_update_delay(vty, bgp);
7719
7720 if (bgp->v_maxmed_onstartup
7721 != BGP_MAXMED_ONSTARTUP_UNCONFIGURED) {
7722 vty_out(vty, " bgp max-med on-startup %u",
7723 bgp->v_maxmed_onstartup);
7724 if (bgp->maxmed_onstartup_value
7725 != BGP_MAXMED_VALUE_DEFAULT)
7726 vty_out(vty, " %u",
7727 bgp->maxmed_onstartup_value);
7728 vty_out(vty, "\n");
7729 }
7730 if (bgp->v_maxmed_admin != BGP_MAXMED_ADMIN_UNCONFIGURED) {
7731 vty_out(vty, " bgp max-med administrative");
7732 if (bgp->maxmed_admin_value != BGP_MAXMED_VALUE_DEFAULT)
7733 vty_out(vty, " %u", bgp->maxmed_admin_value);
7734 vty_out(vty, "\n");
7735 }
718e3744 7736
d62a17ae 7737 /* write quanta */
7738 bgp_config_write_wpkt_quanta(vty, bgp);
555e09d4
QY
7739 /* read quanta */
7740 bgp_config_write_rpkt_quanta(vty, bgp);
d62a17ae 7741
7742 /* coalesce time */
7743 bgp_config_write_coalesce_time(vty, bgp);
7744
7745 /* BGP graceful-restart. */
7746 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
7747 vty_out(vty,
7748 " bgp graceful-restart stalepath-time %u\n",
7749 bgp->stalepath_time);
7750 if (bgp->restart_time != BGP_DEFAULT_RESTART_TIME)
7751 vty_out(vty, " bgp graceful-restart restart-time %u\n",
7752 bgp->restart_time);
7753 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_RESTART))
7754 vty_out(vty, " bgp graceful-restart\n");
7755
7f323236
DW
7756 /* BGP graceful-shutdown */
7757 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
7758 vty_out(vty, " bgp graceful-shutdown\n");
7759
d62a17ae 7760 /* BGP graceful-restart Preserve State F bit. */
7761 if (bgp_flag_check(bgp, BGP_FLAG_GR_PRESERVE_FWD))
7762 vty_out(vty,
7763 " bgp graceful-restart preserve-fw-state\n");
7764
7765 /* BGP bestpath method. */
7766 if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_IGNORE))
7767 vty_out(vty, " bgp bestpath as-path ignore\n");
7768 if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_CONFED))
7769 vty_out(vty, " bgp bestpath as-path confed\n");
7770
7771 if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
7772 if (bgp_flag_check(bgp,
7773 BGP_FLAG_MULTIPATH_RELAX_AS_SET)) {
7774 vty_out(vty,
7775 " bgp bestpath as-path multipath-relax as-set\n");
7776 } else {
7777 vty_out(vty,
7778 " bgp bestpath as-path multipath-relax\n");
7779 }
7780 }
718e3744 7781
d62a17ae 7782 if (bgp_flag_check(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
7783 vty_out(vty,
7784 " bgp route-reflector allow-outbound-policy\n");
7785 }
7786 if (bgp_flag_check(bgp, BGP_FLAG_COMPARE_ROUTER_ID))
7787 vty_out(vty, " bgp bestpath compare-routerid\n");
7788 if (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED)
7789 || bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST)) {
7790 vty_out(vty, " bgp bestpath med");
7791 if (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED))
7792 vty_out(vty, " confed");
7793 if (bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST))
7794 vty_out(vty, " missing-as-worst");
7795 vty_out(vty, "\n");
7796 }
718e3744 7797
d62a17ae 7798 /* BGP network import check. */
7799 if (!!bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
7800 != DFLT_BGP_IMPORT_CHECK)
7801 vty_out(vty, " %sbgp network import-check\n",
7802 bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
7803 ? ""
7804 : "no ");
7805
7806 /* BGP flag dampening. */
7807 if (CHECK_FLAG(bgp->af_flags[AFI_IP][SAFI_UNICAST],
7808 BGP_CONFIG_DAMPENING))
7809 bgp_config_write_damp(vty);
7810
7811 /* BGP timers configuration. */
7812 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
7813 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
7814 vty_out(vty, " timers bgp %u %u\n",
7815 bgp->default_keepalive, bgp->default_holdtime);
7816
7817 /* peer-group */
7818 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
7819 bgp_config_write_peer_global(vty, bgp, group->conf);
7820 }
7821
7822 /* Normal neighbor configuration. */
7823 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
7824 if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
7825 bgp_config_write_peer_global(vty, bgp, peer);
7826 }
718e3744 7827
d62a17ae 7828 /* listen range and limit for dynamic BGP neighbors */
7829 bgp_config_write_listen(vty, bgp);
f14e6fdb 7830
76af525b
PM
7831 /*
7832 * BGP default autoshutdown neighbors
7833 *
7834 * This must be placed after any peer and peer-group
7835 * configuration, to avoid setting all peers to shutdown after
7836 * a daemon restart, which is undesired behavior. (see #2286)
7837 */
7838 if (bgp->autoshutdown)
7839 vty_out(vty, " bgp default shutdown\n");
7840
d62a17ae 7841 /* No auto-summary */
7842 if (bgp_option_check(BGP_OPT_CONFIG_CISCO))
7843 vty_out(vty, " no auto-summary\n");
718e3744 7844
d62a17ae 7845 /* IPv4 unicast configuration. */
2b791107 7846 bgp_config_write_family(vty, bgp, AFI_IP, SAFI_UNICAST);
0b960b4d 7847
d62a17ae 7848 /* IPv4 multicast configuration. */
2b791107 7849 bgp_config_write_family(vty, bgp, AFI_IP, SAFI_MULTICAST);
718e3744 7850
d62a17ae 7851 /* IPv4 labeled-unicast configuration. */
2b791107 7852 bgp_config_write_family(vty, bgp, AFI_IP, SAFI_LABELED_UNICAST);
f51bae9c 7853
d62a17ae 7854 /* IPv4 VPN configuration. */
2b791107 7855 bgp_config_write_family(vty, bgp, AFI_IP, SAFI_MPLS_VPN);
718e3744 7856
d62a17ae 7857 /* ENCAPv4 configuration. */
2b791107 7858 bgp_config_write_family(vty, bgp, AFI_IP, SAFI_ENCAP);
8b1fb8be 7859
7c40bf39 7860 /* FLOWSPEC v4 configuration. */
7861 bgp_config_write_family(vty, bgp, AFI_IP, SAFI_FLOWSPEC);
7862
d62a17ae 7863 /* IPv6 unicast configuration. */
2b791107 7864 bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_UNICAST);
718e3744 7865
d62a17ae 7866 /* IPv6 multicast configuration. */
2b791107 7867 bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_MULTICAST);
37a217a5 7868
d62a17ae 7869 /* IPv6 labeled-unicast configuration. */
2b791107
DL
7870 bgp_config_write_family(vty, bgp, AFI_IP6,
7871 SAFI_LABELED_UNICAST);
f51bae9c 7872
d62a17ae 7873 /* IPv6 VPN configuration. */
2b791107 7874 bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_MPLS_VPN);
8ecd3266 7875
d62a17ae 7876 /* ENCAPv6 configuration. */
2b791107 7877 bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_ENCAP);
8b1fb8be 7878
7c40bf39 7879 /* FLOWSPEC v6 configuration. */
7880 bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_FLOWSPEC);
7881
d62a17ae 7882 /* EVPN configuration. */
2b791107 7883 bgp_config_write_family(vty, bgp, AFI_L2VPN, SAFI_EVPN);
3d6c0dfa 7884
65efcfce 7885#if ENABLE_BGP_VNC
2b791107 7886 bgp_rfapi_cfg_write(vty, bgp);
65efcfce
LB
7887#endif
7888
2b791107 7889 vty_out(vty, "!\n");
d62a17ae 7890 }
2b791107 7891 return 0;
718e3744 7892}
7893
d62a17ae 7894void bgp_master_init(struct thread_master *master)
718e3744 7895{
d62a17ae 7896 qobj_init();
0e64d123 7897
d62a17ae 7898 memset(&bgp_master, 0, sizeof(struct bgp_master));
718e3744 7899
d62a17ae 7900 bm = &bgp_master;
7901 bm->bgp = list_new();
7902 bm->listen_sockets = list_new();
7903 bm->port = BGP_PORT_DEFAULT;
7904 bm->master = master;
7905 bm->start_time = bgp_clock();
7906 bm->t_rmap_update = NULL;
7907 bm->rmap_update_timer = RMAP_DEFAULT_UPDATE_TIMER;
97b4a0ec 7908 bm->terminating = false;
495f0b13 7909
d62a17ae 7910 bgp_process_queue_init();
b8fd6a15 7911
48ecf8f5 7912 bgp_mac_init();
e9eb5f63 7913 /* init the rd id space.
7914 assign 0th index in the bitfield,
523cafc4 7915 so that we start with id 1
7916 */
e9eb5f63 7917 bf_init(bm->rd_idspace, UINT16_MAX);
7918 bf_assign_zero_index(bm->rd_idspace);
7919
d62a17ae 7920 /* Enable multiple instances by default. */
7921 bgp_option_set(BGP_OPT_MULTIPLE_INSTANCE);
19df7279 7922
955bfd98 7923 /* mpls label dynamic allocation pool */
e70e9f8e 7924 bgp_lp_init(bm->master, &bm->labelpool);
955bfd98 7925
d62a17ae 7926 QOBJ_REG(bm, bgp_master);
718e3744 7927}
200df115 7928
ad4cbda1 7929/*
009b18fc 7930 * Free up connected routes and interfaces for a BGP instance. Invoked upon
7931 * instance delete (non-default only) or BGP exit.
ad4cbda1 7932 */
d62a17ae 7933static void bgp_if_finish(struct bgp *bgp)
ad4cbda1 7934{
ee66b77f 7935 struct vrf *vrf;
d62a17ae 7936 struct interface *ifp;
7937
ee66b77f
PG
7938 vrf = bgp_vrf_lookup_by_instance_type(bgp);
7939
f4e14fdb 7940 if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW || !vrf)
d62a17ae 7941 return;
ad4cbda1 7942
451fda4f 7943 FOR_ALL_INTERFACES (vrf, ifp) {
d62a17ae 7944 struct listnode *c_node, *c_nnode;
7945 struct connected *c;
ad4cbda1 7946
d62a17ae 7947 for (ALL_LIST_ELEMENTS(ifp->connected, c_node, c_nnode, c))
7948 bgp_connected_delete(bgp, c);
7949 }
ad4cbda1 7950}
6b0655a2 7951
d62a17ae 7952static void bgp_viewvrf_autocomplete(vector comps, struct cmd_token *token)
18c57037 7953{
d62a17ae 7954 struct vrf *vrf = NULL;
7955 struct listnode *next;
7956 struct bgp *bgp;
18c57037 7957
6a8ca00f
PG
7958 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
7959 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, vrf->name));
18c57037 7960
d62a17ae 7961 for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) {
7962 if (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
7963 continue;
18c57037 7964
d62a17ae 7965 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, bgp->name));
7966 }
18c57037
DS
7967}
7968
7969static const struct cmd_variable_handler bgp_viewvrf_var_handlers[] = {
d62a17ae 7970 {.tokenname = "VIEWVRFNAME", .completions = bgp_viewvrf_autocomplete},
7971 {.completions = NULL},
18c57037
DS
7972};
7973
1ac267a2
DL
7974struct frr_pthread *bgp_pth_io;
7975struct frr_pthread *bgp_pth_ka;
7976
4d762f26 7977static void bgp_pthreads_init(void)
2d4ee774 7978{
1ac267a2
DL
7979 assert(!bgp_pth_io);
7980 assert(!bgp_pth_ka);
7981
0ca8b79f
QY
7982 frr_pthread_init();
7983
a715eab3 7984 struct frr_pthread_attr io = {
a715eab3
QY
7985 .start = frr_pthread_attr_default.start,
7986 .stop = frr_pthread_attr_default.stop,
a715eab3
QY
7987 };
7988 struct frr_pthread_attr ka = {
a715eab3
QY
7989 .start = bgp_keepalives_start,
7990 .stop = bgp_keepalives_stop,
a715eab3 7991 };
1ac267a2
DL
7992 bgp_pth_io = frr_pthread_new(&io, "BGP I/O thread", "bgpd_io");
7993 bgp_pth_ka = frr_pthread_new(&ka, "BGP Keepalives thread", "bgpd_ka");
419dfe6a
QY
7994}
7995
4d762f26 7996void bgp_pthreads_run(void)
419dfe6a 7997{
1ac267a2
DL
7998 frr_pthread_run(bgp_pth_io, NULL);
7999 frr_pthread_run(bgp_pth_ka, NULL);
88b24dee 8000
a715eab3 8001 /* Wait until threads are ready. */
1ac267a2
DL
8002 frr_pthread_wait_running(bgp_pth_io);
8003 frr_pthread_wait_running(bgp_pth_ka);
2d4ee774
QY
8004}
8005
4d762f26 8006void bgp_pthreads_finish(void)
2d4ee774 8007{
0ca8b79f
QY
8008 frr_pthread_stop_all();
8009 frr_pthread_finish();
2d4ee774
QY
8010}
8011
f533be73 8012void bgp_init(unsigned short instance)
718e3744 8013{
fc9a856f 8014
d62a17ae 8015 /* allocates some vital data structures used by peer commands in
8016 * vty_init */
718e3744 8017
419dfe6a
QY
8018 /* pre-init pthreads */
8019 bgp_pthreads_init();
8020
d62a17ae 8021 /* Init zebra. */
f533be73 8022 bgp_zebra_init(bm->master, instance);
718e3744 8023
65efcfce 8024#if ENABLE_BGP_VNC
d62a17ae 8025 vnc_zebra_init(bm->master);
65efcfce
LB
8026#endif
8027
d62a17ae 8028 /* BGP VTY commands installation. */
8029 bgp_vty_init();
8030
8031 /* BGP inits. */
8032 bgp_attr_init();
8033 bgp_debug_init();
8034 bgp_dump_init();
8035 bgp_route_init();
8036 bgp_route_map_init();
8037 bgp_scan_vty_init();
8038 bgp_mplsvpn_init();
65efcfce 8039#if ENABLE_BGP_VNC
d62a17ae 8040 rfapi_init();
65efcfce 8041#endif
d62a17ae 8042 bgp_ethernetvpn_init();
7c40bf39 8043 bgp_flowspec_vty_init();
d62a17ae 8044
8045 /* Access list initialize. */
8046 access_list_init();
8047 access_list_add_hook(peer_distribute_update);
8048 access_list_delete_hook(peer_distribute_update);
8049
8050 /* Filter list initialize. */
8051 bgp_filter_init();
8052 as_list_add_hook(peer_aslist_add);
8053 as_list_delete_hook(peer_aslist_del);
8054
8055 /* Prefix list initialize.*/
8056 prefix_list_init();
8057 prefix_list_add_hook(peer_prefix_list_update);
8058 prefix_list_delete_hook(peer_prefix_list_update);
8059
8060 /* Community list initialize. */
8061 bgp_clist = community_list_init();
8062
8063 /* BFD init */
8064 bgp_bfd_init();
8065
8066 cmd_variable_handler_register(bgp_viewvrf_var_handlers);
8067}
8068
8069void bgp_terminate(void)
8070{
8071 struct bgp *bgp;
8072 struct peer *peer;
8073 struct listnode *node, *nnode;
8074 struct listnode *mnode, *mnnode;
8075
8076 QOBJ_UNREG(bm);
8077
8078 /* Close the listener sockets first as this prevents peers from
8079 * attempting
8080 * to reconnect on receiving the peer unconfig message. In the presence
8081 * of a large number of peers this will ensure that no peer is left with
8082 * a dangling connection
8083 */
8084 /* reverse bgp_master_init */
8085 bgp_close();
c3004bc4 8086
d62a17ae 8087 if (bm->listen_sockets)
6a154c88 8088 list_delete(&bm->listen_sockets);
d62a17ae 8089
8090 for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp))
8091 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
8092 if (peer->status == Established
8093 || peer->status == OpenSent
8094 || peer->status == OpenConfirm)
8095 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
8096 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
8097
e208c8f9
DS
8098 if (bm->process_main_queue)
8099 work_queue_free_and_null(&bm->process_main_queue);
d62a17ae 8100
8101 if (bm->t_rmap_update)
8102 BGP_TIMER_OFF(bm->t_rmap_update);
955bfd98 8103
48ecf8f5 8104 bgp_mac_finish();
545acafb 8105}