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