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