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