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