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