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