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