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