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