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