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