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