]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgpd.c
Merge pull request #2169 from piotrjurkiewicz/eigrp_feasibility
[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
5950 SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5951 peer->pmax[afi][safi] = max;
5952 peer->pmax_threshold[afi][safi] = threshold;
5953 peer->pmax_restart[afi][safi] = restart;
5954 if (warning)
5955 SET_FLAG(peer->af_flags[afi][safi],
5956 PEER_FLAG_MAX_PREFIX_WARNING);
5957 else
5958 UNSET_FLAG(peer->af_flags[afi][safi],
5959 PEER_FLAG_MAX_PREFIX_WARNING);
5960
5961 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5962 group = peer->group;
5963 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5964 SET_FLAG(peer->af_flags[afi][safi],
5965 PEER_FLAG_MAX_PREFIX);
5966 peer->pmax[afi][safi] = max;
5967 peer->pmax_threshold[afi][safi] = threshold;
5968 peer->pmax_restart[afi][safi] = restart;
5969 if (warning)
5970 SET_FLAG(peer->af_flags[afi][safi],
5971 PEER_FLAG_MAX_PREFIX_WARNING);
5972 else
5973 UNSET_FLAG(peer->af_flags[afi][safi],
5974 PEER_FLAG_MAX_PREFIX_WARNING);
5975
5976 if ((peer->status == Established)
5977 && (peer->afc[afi][safi]))
5978 bgp_maximum_prefix_overflow(peer, afi, safi, 1);
5979 }
5980 } else {
5981 if ((peer->status == Established) && (peer->afc[afi][safi]))
5982 bgp_maximum_prefix_overflow(peer, afi, safi, 1);
5983 }
718e3744 5984
d62a17ae 5985 return 0;
5986}
718e3744 5987
d62a17ae 5988int peer_maximum_prefix_unset(struct peer *peer, afi_t afi, safi_t safi)
5989{
5990 struct peer_group *group;
5991 struct listnode *node, *nnode;
5992
5993 /* apply peer-group config */
5994 if (peer_group_active(peer)) {
5995 if (CHECK_FLAG(peer->group->conf->af_flags[afi][safi],
5996 PEER_FLAG_MAX_PREFIX))
5997 SET_FLAG(peer->af_flags[afi][safi],
5998 PEER_FLAG_MAX_PREFIX);
5999 else
6000 UNSET_FLAG(peer->af_flags[afi][safi],
6001 PEER_FLAG_MAX_PREFIX);
6002
6003 if (CHECK_FLAG(peer->group->conf->af_flags[afi][safi],
6004 PEER_FLAG_MAX_PREFIX_WARNING))
6005 SET_FLAG(peer->af_flags[afi][safi],
6006 PEER_FLAG_MAX_PREFIX_WARNING);
6007 else
6008 UNSET_FLAG(peer->af_flags[afi][safi],
6009 PEER_FLAG_MAX_PREFIX_WARNING);
6010
6011 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
6012 peer->pmax_threshold[afi][safi] =
6013 peer->group->conf->pmax_threshold[afi][safi];
6014 peer->pmax_restart[afi][safi] =
6015 peer->group->conf->pmax_restart[afi][safi];
6016 return 0;
6017 }
718e3744 6018
d62a17ae 6019 UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
6020 UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
6021 peer->pmax[afi][safi] = 0;
6022 peer->pmax_threshold[afi][safi] = 0;
6023 peer->pmax_restart[afi][safi] = 0;
6024
6025 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
6026 return 0;
6027
6028 group = peer->group;
6029 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
6030 UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
6031 UNSET_FLAG(peer->af_flags[afi][safi],
6032 PEER_FLAG_MAX_PREFIX_WARNING);
6033 peer->pmax[afi][safi] = 0;
6034 peer->pmax_threshold[afi][safi] = 0;
6035 peer->pmax_restart[afi][safi] = 0;
6036 }
6037 return 0;
718e3744 6038}
6039
d62a17ae 6040int is_ebgp_multihop_configured(struct peer *peer)
718e3744 6041{
d62a17ae 6042 struct peer_group *group;
6043 struct listnode *node, *nnode;
6044 struct peer *peer1;
718e3744 6045
d62a17ae 6046 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
6047 group = peer->group;
6048 if ((peer_sort(peer) != BGP_PEER_IBGP)
6049 && (group->conf->ttl != 1))
6050 return 1;
718e3744 6051
d62a17ae 6052 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer1)) {
6053 if ((peer_sort(peer1) != BGP_PEER_IBGP)
6054 && (peer1->ttl != 1))
6055 return 1;
6056 }
6057 } else {
6058 if ((peer_sort(peer) != BGP_PEER_IBGP) && (peer->ttl != 1))
6059 return 1;
6060 }
6061 return 0;
6062}
718e3744 6063
d62a17ae 6064/* Set # of hops between us and BGP peer. */
6065int peer_ttl_security_hops_set(struct peer *peer, int gtsm_hops)
6066{
6067 struct peer_group *group;
6068 struct listnode *node, *nnode;
6069 int ret;
6070
6071 zlog_debug("peer_ttl_security_hops_set: set gtsm_hops to %d for %s",
6072 gtsm_hops, peer->host);
6073
6074 /* We cannot configure ttl-security hops when ebgp-multihop is already
6075 set. For non peer-groups, the check is simple. For peer-groups,
6076 it's
6077 slightly messy, because we need to check both the peer-group
6078 structure
6079 and all peer-group members for any trace of ebgp-multihop
6080 configuration
6081 before actually applying the ttl-security rules. Cisco really made a
6082 mess of this configuration parameter, and OpenBGPD got it right.
6083 */
6084
6085 if ((peer->gtsm_hops == 0) && (peer->sort != BGP_PEER_IBGP)) {
6086 if (is_ebgp_multihop_configured(peer))
6087 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
6088
6089 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
6090 peer->gtsm_hops = gtsm_hops;
6091
6092 /* Calling ebgp multihop also resets the session.
6093 * On restart, NHT will get setup correctly as will the
6094 * min & max ttls on the socket. The return value is
6095 * irrelevant.
6096 */
6097 ret = peer_ebgp_multihop_set(peer, MAXTTL);
6098
6099 if (ret != 0)
6100 return ret;
6101 } else {
6102 group = peer->group;
6103 for (ALL_LIST_ELEMENTS(group->peer, node, nnode,
6104 peer)) {
6105 peer->gtsm_hops = group->conf->gtsm_hops;
6106
6107 /* Calling ebgp multihop also resets the
6108 * session.
6109 * On restart, NHT will get setup correctly as
6110 * will the
6111 * min & max ttls on the socket. The return
6112 * value is
6113 * irrelevant.
6114 */
6115 peer_ebgp_multihop_set(peer, MAXTTL);
6116 }
6117 }
6118 } else {
6119 /* Post the first gtsm setup or if its ibgp, maxttl setting
6120 * isn't
6121 * necessary, just set the minttl.
6122 */
6123 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
6124 peer->gtsm_hops = gtsm_hops;
6125
6126 if (peer->fd >= 0)
6127 sockopt_minttl(peer->su.sa.sa_family, peer->fd,
6128 MAXTTL + 1 - gtsm_hops);
6129 if ((peer->status < Established) && peer->doppelganger
6130 && (peer->doppelganger->fd >= 0))
6131 sockopt_minttl(peer->su.sa.sa_family,
6132 peer->doppelganger->fd,
6133 MAXTTL + 1 - gtsm_hops);
6134 } else {
6135 group = peer->group;
6136 for (ALL_LIST_ELEMENTS(group->peer, node, nnode,
6137 peer)) {
6138 peer->gtsm_hops = group->conf->gtsm_hops;
6139
6140 /* Change setting of existing peer
6141 * established then change value (may break
6142 * connectivity)
6143 * not established yet (teardown session and
6144 * restart)
6145 * no session then do nothing (will get
6146 * handled by next connection)
6147 */
6148 if (peer->fd >= 0 && peer->gtsm_hops != 0)
6149 sockopt_minttl(
6150 peer->su.sa.sa_family, peer->fd,
6151 MAXTTL + 1 - peer->gtsm_hops);
6152 if ((peer->status < Established)
6153 && 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 }
6159 }
6160 }
718e3744 6161
d62a17ae 6162 return 0;
718e3744 6163}
6164
d62a17ae 6165int peer_ttl_security_hops_unset(struct peer *peer)
6166{
6167 struct peer_group *group;
6168 struct listnode *node, *nnode;
6169 int ret = 0;
6170
6171 zlog_debug("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s",
6172 peer->host);
6173
6174 /* if a peer-group member, then reset to peer-group default rather than
6175 * 0 */
6176 if (peer_group_active(peer))
6177 peer->gtsm_hops = peer->group->conf->gtsm_hops;
6178 else
6179 peer->gtsm_hops = 0;
6180
6181 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
6182 /* Invoking ebgp_multihop_set will set the TTL back to the
6183 * original
6184 * value as well as restting the NHT and such. The session is
6185 * reset.
6186 */
6187 if (peer->sort == BGP_PEER_EBGP)
6188 ret = peer_ebgp_multihop_unset(peer);
6189 else {
6190 if (peer->fd >= 0)
6191 sockopt_minttl(peer->su.sa.sa_family, peer->fd,
6192 0);
6193
6194 if ((peer->status < Established) && peer->doppelganger
6195 && (peer->doppelganger->fd >= 0))
6196 sockopt_minttl(peer->su.sa.sa_family,
6197 peer->doppelganger->fd, 0);
6198 }
6199 } else {
6200 group = peer->group;
6201 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
6202 peer->gtsm_hops = 0;
6203 if (peer->sort == BGP_PEER_EBGP)
6204 ret = peer_ebgp_multihop_unset(peer);
6205 else {
6206 if (peer->fd >= 0)
6207 sockopt_minttl(peer->su.sa.sa_family,
6208 peer->fd, 0);
6209
6210 if ((peer->status < Established)
6211 && peer->doppelganger
6212 && (peer->doppelganger->fd >= 0))
6213 sockopt_minttl(peer->su.sa.sa_family,
6214 peer->doppelganger->fd,
6215 0);
6216 }
6217 }
6218 }
718e3744 6219
d62a17ae 6220 return ret;
6221}
6222
6223/*
6224 * If peer clear is invoked in a loop for all peers on the BGP instance,
6225 * it may end up freeing the doppelganger, and if this was the next node
6226 * to the current node, we would end up accessing the freed next node.
6227 * Pass along additional parameter which can be updated if next node
6228 * is freed; only required when walking the peer list on BGP instance.
6229 */
6230int peer_clear(struct peer *peer, struct listnode **nnode)
6231{
6232 if (!CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)) {
6233 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW)) {
6234 UNSET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
6235 if (peer->t_pmax_restart) {
6236 BGP_TIMER_OFF(peer->t_pmax_restart);
6237 if (bgp_debug_neighbor_events(peer))
6238 zlog_debug(
6239 "%s Maximum-prefix restart timer canceled",
6240 peer->host);
6241 }
6242 BGP_EVENT_ADD(peer, BGP_Start);
6243 return 0;
6244 }
6245
6246 peer->v_start = BGP_INIT_START_TIMER;
6247 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
6248 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
6249 BGP_NOTIFY_CEASE_ADMIN_RESET);
6250 else
6251 bgp_session_reset_safe(peer, nnode);
718e3744 6252 }
d62a17ae 6253 return 0;
718e3744 6254}
6b0655a2 6255
d62a17ae 6256int peer_clear_soft(struct peer *peer, afi_t afi, safi_t safi,
6257 enum bgp_clear_type stype)
718e3744 6258{
d62a17ae 6259 struct peer_af *paf;
718e3744 6260
d62a17ae 6261 if (peer->status != Established)
6262 return 0;
718e3744 6263
d62a17ae 6264 if (!peer->afc[afi][safi])
6265 return BGP_ERR_AF_UNCONFIGURED;
718e3744 6266
d62a17ae 6267 peer->rtt = sockopt_tcp_rtt(peer->fd);
718e3744 6268
d62a17ae 6269 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH) {
6270 /* Clear the "neighbor x.x.x.x default-originate" flag */
6271 paf = peer_af_find(peer, afi, safi);
6272 if (paf && paf->subgroup
6273 && CHECK_FLAG(paf->subgroup->sflags,
6274 SUBGRP_STATUS_DEFAULT_ORIGINATE))
6275 UNSET_FLAG(paf->subgroup->sflags,
6276 SUBGRP_STATUS_DEFAULT_ORIGINATE);
718e3744 6277
d62a17ae 6278 bgp_announce_route(peer, afi, safi);
6279 }
718e3744 6280
d62a17ae 6281 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX) {
6282 if (CHECK_FLAG(peer->af_cap[afi][safi],
6283 PEER_CAP_ORF_PREFIX_SM_ADV)
6284 && (CHECK_FLAG(peer->af_cap[afi][safi],
6285 PEER_CAP_ORF_PREFIX_RM_RCV)
6286 || CHECK_FLAG(peer->af_cap[afi][safi],
6287 PEER_CAP_ORF_PREFIX_RM_OLD_RCV))) {
6288 struct bgp_filter *filter = &peer->filter[afi][safi];
d7c0a89a 6289 uint8_t prefix_type;
d62a17ae 6290
6291 if (CHECK_FLAG(peer->af_cap[afi][safi],
6292 PEER_CAP_ORF_PREFIX_RM_RCV))
6293 prefix_type = ORF_TYPE_PREFIX;
6294 else
6295 prefix_type = ORF_TYPE_PREFIX_OLD;
6296
6297 if (filter->plist[FILTER_IN].plist) {
6298 if (CHECK_FLAG(peer->af_sflags[afi][safi],
6299 PEER_STATUS_ORF_PREFIX_SEND))
6300 bgp_route_refresh_send(
6301 peer, afi, safi, prefix_type,
6302 REFRESH_DEFER, 1);
6303 bgp_route_refresh_send(peer, afi, safi,
6304 prefix_type,
6305 REFRESH_IMMEDIATE, 0);
6306 } else {
6307 if (CHECK_FLAG(peer->af_sflags[afi][safi],
6308 PEER_STATUS_ORF_PREFIX_SEND))
6309 bgp_route_refresh_send(
6310 peer, afi, safi, prefix_type,
6311 REFRESH_IMMEDIATE, 1);
6312 else
6313 bgp_route_refresh_send(peer, afi, safi,
6314 0, 0, 0);
6315 }
6316 return 0;
6317 }
6318 }
718e3744 6319
d62a17ae 6320 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
6321 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX) {
6322 /* If neighbor has soft reconfiguration inbound flag.
6323 Use Adj-RIB-In database. */
6324 if (CHECK_FLAG(peer->af_flags[afi][safi],
6325 PEER_FLAG_SOFT_RECONFIG))
6326 bgp_soft_reconfig_in(peer, afi, safi);
6327 else {
6328 /* If neighbor has route refresh capability, send route
6329 refresh
6330 message to the peer. */
6331 if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV)
6332 || CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV))
6333 bgp_route_refresh_send(peer, afi, safi, 0, 0,
6334 0);
6335 else
6336 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
6337 }
6338 }
6339 return 0;
718e3744 6340}
6341
d62a17ae 6342/* Display peer uptime.*/
d7c0a89a 6343char *peer_uptime(time_t uptime2, char *buf, size_t len, uint8_t use_json,
d62a17ae 6344 json_object *json)
6345{
6346 time_t uptime1, epoch_tbuf;
6347 struct tm *tm;
6348
6349 /* Check buffer length. */
6350 if (len < BGP_UPTIME_LEN) {
6351 if (!use_json) {
6352 zlog_warn("peer_uptime (): buffer shortage %lu",
d7c0a89a 6353 (unsigned long)len);
d62a17ae 6354 /* XXX: should return status instead of buf... */
6355 snprintf(buf, len, "<error> ");
6356 }
6357 return buf;
6358 }
6359
6360 /* If there is no connection has been done before print `never'. */
6361 if (uptime2 == 0) {
6362 if (use_json) {
6363 json_object_string_add(json, "peerUptime", "never");
6364 json_object_int_add(json, "peerUptimeMsec", 0);
6365 } else
6366 snprintf(buf, len, "never");
6367 return buf;
6368 }
718e3744 6369
d62a17ae 6370 /* Get current time. */
6371 uptime1 = bgp_clock();
6372 uptime1 -= uptime2;
6373 tm = gmtime(&uptime1);
718e3744 6374
d62a17ae 6375 if (uptime1 < ONE_DAY_SECOND)
6376 snprintf(buf, len, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min,
6377 tm->tm_sec);
6378 else if (uptime1 < ONE_WEEK_SECOND)
6379 snprintf(buf, len, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour,
6380 tm->tm_min);
6381 else if (uptime1 < ONE_YEAR_SECOND)
6382 snprintf(buf, len, "%02dw%dd%02dh", tm->tm_yday / 7,
6383 tm->tm_yday - ((tm->tm_yday / 7) * 7), tm->tm_hour);
6384 else
6385 snprintf(buf, len, "%02dy%02dw%dd", tm->tm_year - 70,
6386 tm->tm_yday / 7,
6387 tm->tm_yday - ((tm->tm_yday / 7) * 7));
6388
6389 if (use_json) {
6390 epoch_tbuf = time(NULL) - uptime1;
6391 json_object_string_add(json, "peerUptime", buf);
6392 json_object_int_add(json, "peerUptimeMsec", uptime1 * 1000);
6393 json_object_int_add(json, "peerUptimeEstablishedEpoch",
6394 epoch_tbuf);
6395 }
718e3744 6396
d62a17ae 6397 return buf;
718e3744 6398}
6399
d62a17ae 6400static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
2b791107 6401 afi_t afi, safi_t safi)
518f0eb1 6402{
d62a17ae 6403 struct bgp_filter *filter;
6404 struct bgp_filter *gfilter = NULL;
6405 char *addr;
6406 int in = FILTER_IN;
6407 int out = FILTER_OUT;
518f0eb1 6408
d62a17ae 6409 addr = peer->host;
6410 filter = &peer->filter[afi][safi];
518f0eb1 6411
d62a17ae 6412 if (peer_group_active(peer))
6413 gfilter = &peer->group->conf->filter[afi][safi];
6414
6415 /* distribute-list. */
6416 if (filter->dlist[in].name)
6417 if (!gfilter || !gfilter->dlist[in].name
6418 || strcmp(filter->dlist[in].name, gfilter->dlist[in].name)
6419 != 0) {
2b791107
DL
6420 vty_out(vty, " neighbor %s distribute-list %s in\n",
6421 addr, filter->dlist[in].name);
d62a17ae 6422 }
6b0655a2 6423
d62a17ae 6424 if (filter->dlist[out].name && !gfilter) {
2b791107
DL
6425 vty_out(vty, " neighbor %s distribute-list %s out\n", addr,
6426 filter->dlist[out].name);
d62a17ae 6427 }
718e3744 6428
d62a17ae 6429 /* prefix-list. */
6430 if (filter->plist[in].name)
6431 if (!gfilter || !gfilter->plist[in].name
6432 || strcmp(filter->plist[in].name, gfilter->plist[in].name)
6433 != 0) {
2b791107
DL
6434 vty_out(vty, " neighbor %s prefix-list %s in\n", addr,
6435 filter->plist[in].name);
d62a17ae 6436 }
718e3744 6437
2b791107
DL
6438 if (filter->plist[out].name)
6439 if (!gfilter || !gfilter->plist[out].name
6440 || strcmp(filter->plist[out].name, gfilter->plist[out].name)
6441 != 0) {
6442 vty_out(vty, " neighbor %s prefix-list %s out\n", addr,
6443 filter->plist[out].name);
6444 }
718e3744 6445
d62a17ae 6446 /* route-map. */
6447 if (filter->map[RMAP_IN].name)
6448 if (!gfilter || !gfilter->map[RMAP_IN].name
6449 || strcmp(filter->map[RMAP_IN].name,
6450 gfilter->map[RMAP_IN].name)
6451 != 0) {
2b791107
DL
6452 vty_out(vty, " neighbor %s route-map %s in\n", addr,
6453 filter->map[RMAP_IN].name);
d62a17ae 6454 }
518f0eb1 6455
d62a17ae 6456 if (filter->map[RMAP_OUT].name)
6457 if (!gfilter || !gfilter->map[RMAP_OUT].name
6458 || strcmp(filter->map[RMAP_OUT].name,
6459 gfilter->map[RMAP_OUT].name)
6460 != 0) {
2b791107
DL
6461 vty_out(vty, " neighbor %s route-map %s out\n", addr,
6462 filter->map[RMAP_OUT].name);
d62a17ae 6463 }
718e3744 6464
d62a17ae 6465 /* unsuppress-map */
6466 if (filter->usmap.name && !gfilter) {
2b791107
DL
6467 vty_out(vty, " neighbor %s unsuppress-map %s\n", addr,
6468 filter->usmap.name);
d62a17ae 6469 }
718e3744 6470
d62a17ae 6471 /* filter-list. */
6472 if (filter->aslist[in].name)
6473 if (!gfilter || !gfilter->aslist[in].name
6474 || strcmp(filter->aslist[in].name, gfilter->aslist[in].name)
6475 != 0) {
2b791107
DL
6476 vty_out(vty, " neighbor %s filter-list %s in\n", addr,
6477 filter->aslist[in].name);
d62a17ae 6478 }
718e3744 6479
d62a17ae 6480 if (filter->aslist[out].name && !gfilter) {
2b791107
DL
6481 vty_out(vty, " neighbor %s filter-list %s out\n", addr,
6482 filter->aslist[out].name);
d62a17ae 6483 }
718e3744 6484}
6485
d62a17ae 6486/* BGP peer configuration display function. */
6487static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
6488 struct peer *peer)
6489{
6490 struct peer *g_peer = NULL;
6491 char buf[SU_ADDRSTRLEN];
6492 char *addr;
6493 int if_pg_printed = FALSE;
6494 int if_ras_printed = FALSE;
6495
6496 /* Skip dynamic neighbors. */
6497 if (peer_dynamic_neighbor(peer))
6498 return;
6499
6500 if (peer->conf_if)
6501 addr = peer->conf_if;
6502 else
6503 addr = peer->host;
6504
6505 /************************************
6506 ****** Global to the neighbor ******
6507 ************************************/
6508 if (peer->conf_if) {
6509 if (CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))
6510 vty_out(vty, " neighbor %s interface v6only", addr);
6511 else
6512 vty_out(vty, " neighbor %s interface", addr);
6513
6514 if (peer_group_active(peer)) {
6515 vty_out(vty, " peer-group %s", peer->group->name);
6516 if_pg_printed = TRUE;
6517 } else if (peer->as_type == AS_SPECIFIED) {
6518 vty_out(vty, " remote-as %u", peer->as);
6519 if_ras_printed = TRUE;
6520 } else if (peer->as_type == AS_INTERNAL) {
6521 vty_out(vty, " remote-as internal");
6522 if_ras_printed = TRUE;
6523 } else if (peer->as_type == AS_EXTERNAL) {
6524 vty_out(vty, " remote-as external");
6525 if_ras_printed = TRUE;
6526 }
718e3744 6527
d62a17ae 6528 vty_out(vty, "\n");
6529 }
718e3744 6530
d62a17ae 6531 /* remote-as and peer-group */
6532 /* peer is a member of a peer-group */
6533 if (peer_group_active(peer)) {
6534 g_peer = peer->group->conf;
6535
6536 if (g_peer->as_type == AS_UNSPECIFIED && !if_ras_printed) {
6537 if (peer->as_type == AS_SPECIFIED) {
6538 vty_out(vty, " neighbor %s remote-as %u\n",
6539 addr, peer->as);
6540 } else if (peer->as_type == AS_INTERNAL) {
6541 vty_out(vty,
6542 " neighbor %s remote-as internal\n",
6543 addr);
6544 } else if (peer->as_type == AS_EXTERNAL) {
6545 vty_out(vty,
6546 " neighbor %s remote-as external\n",
6547 addr);
6548 }
6549 }
718e3744 6550
d62a17ae 6551 /* For swpX peers we displayed the peer-group
6552 * via 'neighbor swpX interface peer-group WORD' */
6553 if (!if_pg_printed)
6554 vty_out(vty, " neighbor %s peer-group %s\n", addr,
6555 peer->group->name);
6556 }
718e3744 6557
d62a17ae 6558 /* peer is NOT a member of a peer-group */
6559 else {
6560 /* peer is a peer-group, declare the peer-group */
6561 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
6562 vty_out(vty, " neighbor %s peer-group\n", addr);
6563 }
6b0655a2 6564
d62a17ae 6565 if (!if_ras_printed) {
6566 if (peer->as_type == AS_SPECIFIED) {
6567 vty_out(vty, " neighbor %s remote-as %u\n",
6568 addr, peer->as);
6569 } else if (peer->as_type == AS_INTERNAL) {
6570 vty_out(vty,
6571 " neighbor %s remote-as internal\n",
6572 addr);
6573 } else if (peer->as_type == AS_EXTERNAL) {
6574 vty_out(vty,
6575 " neighbor %s remote-as external\n",
6576 addr);
6577 }
6578 }
6579 }
718e3744 6580
d62a17ae 6581 /* local-as */
6582 if (peer->change_local_as) {
6583 if (!peer_group_active(peer)
6584 || peer->change_local_as != g_peer->change_local_as
6585 || (CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)
6586 != CHECK_FLAG(g_peer->flags,
6587 PEER_FLAG_LOCAL_AS_NO_PREPEND))
6588 || (CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS)
6589 != CHECK_FLAG(g_peer->flags,
6590 PEER_FLAG_LOCAL_AS_REPLACE_AS))) {
6591 vty_out(vty, " neighbor %s local-as %u%s%s\n", addr,
6592 peer->change_local_as,
6593 CHECK_FLAG(peer->flags,
6594 PEER_FLAG_LOCAL_AS_NO_PREPEND)
6595 ? " no-prepend"
6596 : "",
6597 CHECK_FLAG(peer->flags,
6598 PEER_FLAG_LOCAL_AS_REPLACE_AS)
6599 ? " replace-as"
6600 : "");
6601 }
5f9adb5d 6602 }
5f9adb5d 6603
d62a17ae 6604 /* description */
6605 if (peer->desc) {
6606 vty_out(vty, " neighbor %s description %s\n", addr, peer->desc);
6607 }
fa411a21 6608
d62a17ae 6609 /* shutdown */
6610 if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)) {
6611 if (!peer_group_active(peer)
6612 || !CHECK_FLAG(g_peer->flags, PEER_FLAG_SHUTDOWN)
6613 || peer->tx_shutdown_message) {
6614 if (peer->tx_shutdown_message)
6615 vty_out(vty,
6616 " neighbor %s shutdown message %s\n",
6617 addr, peer->tx_shutdown_message);
6618 else
6619 vty_out(vty, " neighbor %s shutdown\n", addr);
6620 }
6621 }
fa411a21 6622
d62a17ae 6623 /* bfd */
6624 if (peer->bfd_info) {
6625 if (!peer_group_active(peer) || !g_peer->bfd_info) {
6626 bgp_bfd_peer_config_write(vty, peer, addr);
6627 }
6628 }
e5cc509c 6629
d62a17ae 6630 /* password */
6631 if (peer->password) {
6632 if (!peer_group_active(peer) || !g_peer->password
6633 || strcmp(peer->password, g_peer->password) != 0) {
6634 vty_out(vty, " neighbor %s password %s\n", addr,
6635 peer->password);
6636 }
6637 }
fa411a21 6638
d62a17ae 6639 /* neighbor solo */
6640 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL)) {
6641 if (!peer_group_active(peer)) {
6642 vty_out(vty, " neighbor %s solo\n", addr);
6643 }
6644 }
fa411a21 6645
d62a17ae 6646 /* BGP port */
6647 if (peer->port != BGP_PORT_DEFAULT) {
6648 vty_out(vty, " neighbor %s port %d\n", addr, peer->port);
6649 }
e5cc509c 6650
d62a17ae 6651 /* Local interface name */
6652 if (peer->ifname) {
6653 vty_out(vty, " neighbor %s interface %s\n", addr, peer->ifname);
e5cc509c 6654 }
fa411a21 6655
d62a17ae 6656 /* passive */
6657 if (CHECK_FLAG(peer->flags, PEER_FLAG_PASSIVE)) {
6658 if (!peer_group_active(peer)
6659 || !CHECK_FLAG(g_peer->flags, PEER_FLAG_PASSIVE)) {
6660 vty_out(vty, " neighbor %s passive\n", addr);
6661 }
e5cc509c 6662 }
1ff9a340 6663
d62a17ae 6664 /* ebgp-multihop */
6665 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1
6666 && !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL)) {
6667 if (!peer_group_active(peer) || g_peer->ttl != peer->ttl) {
6668 vty_out(vty, " neighbor %s ebgp-multihop %d\n", addr,
6669 peer->ttl);
6670 }
fa411a21 6671 }
fa411a21 6672
d62a17ae 6673 /* ttl-security hops */
6674 if (peer->gtsm_hops != 0) {
6675 if (!peer_group_active(peer)
6676 || g_peer->gtsm_hops != peer->gtsm_hops) {
6677 vty_out(vty, " neighbor %s ttl-security hops %d\n",
6678 addr, peer->gtsm_hops);
6679 }
6680 }
6681
6682 /* disable-connected-check */
6683 if (CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)) {
6684 if (!peer_group_active(peer)
6685 || !CHECK_FLAG(g_peer->flags,
6686 PEER_FLAG_DISABLE_CONNECTED_CHECK)) {
6687 vty_out(vty, " neighbor %s disable-connected-check\n",
6688 addr);
6689 }
6690 }
6691
6692 /* update-source */
6693 if (peer->update_if) {
6694 if (!peer_group_active(peer) || !g_peer->update_if
6695 || strcmp(g_peer->update_if, peer->update_if) != 0) {
6696 vty_out(vty, " neighbor %s update-source %s\n", addr,
6697 peer->update_if);
6698 }
6699 }
6700 if (peer->update_source) {
6701 if (!peer_group_active(peer) || !g_peer->update_source
6702 || sockunion_cmp(g_peer->update_source, peer->update_source)
6703 != 0) {
6704 vty_out(vty, " neighbor %s update-source %s\n", addr,
6705 sockunion2str(peer->update_source, buf,
6706 SU_ADDRSTRLEN));
6707 }
6708 }
6709
6710 /* advertisement-interval */
6711 if (CHECK_FLAG(peer->config, PEER_CONFIG_ROUTEADV)
6712 && ((!peer_group_active(peer)
6713 && peer->v_routeadv != BGP_DEFAULT_EBGP_ROUTEADV)
6714 || (peer_group_active(peer)
6715 && peer->v_routeadv != g_peer->v_routeadv))) {
6716 vty_out(vty, " neighbor %s advertisement-interval %u\n", addr,
6717 peer->v_routeadv);
6718 }
6719
6720 /* timers */
d25e4efc 6721 if ((PEER_OR_GROUP_TIMER_SET(peer))
d62a17ae 6722 && ((!peer_group_active(peer)
6723 && (peer->keepalive != BGP_DEFAULT_KEEPALIVE
6724 || peer->holdtime != BGP_DEFAULT_HOLDTIME))
6725 || (peer_group_active(peer)
6726 && (peer->keepalive != g_peer->keepalive
6727 || peer->holdtime != g_peer->holdtime)))) {
6728 vty_out(vty, " neighbor %s timers %u %u\n", addr,
6729 peer->keepalive, peer->holdtime);
6730 }
6731
6732 if (CHECK_FLAG(peer->config, PEER_CONFIG_CONNECT)
6733 && ((!peer_group_active(peer)
6734 && peer->connect != BGP_DEFAULT_CONNECT_RETRY)
6735 || (peer_group_active(peer)
6736 && peer->connect != g_peer->connect)))
6b0655a2 6737
718e3744 6738 {
d62a17ae 6739 vty_out(vty, " neighbor %s timers connect %u\n", addr,
6740 peer->connect);
718e3744 6741 }
6b0655a2 6742
d62a17ae 6743 /* capability dynamic */
6744 if (CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY)) {
6745 if (!peer_group_active(peer)
6746 || !CHECK_FLAG(g_peer->flags,
6747 PEER_FLAG_DYNAMIC_CAPABILITY)) {
6748 vty_out(vty, " neighbor %s capability dynamic\n", addr);
6749 }
6750 }
718e3744 6751
d62a17ae 6752 /* capability extended-nexthop */
6753 if (peer->ifp && !CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE)) {
6754 if (!peer_group_active(peer)
6755 || !CHECK_FLAG(g_peer->flags, PEER_FLAG_CAPABILITY_ENHE)) {
6756 vty_out(vty,
6757 " no neighbor %s capability extended-nexthop\n",
6758 addr);
6759 }
6760 }
718e3744 6761
d62a17ae 6762 if (!peer->ifp && CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE)) {
6763 if (!peer_group_active(peer)
6764 || !CHECK_FLAG(g_peer->flags, PEER_FLAG_CAPABILITY_ENHE)) {
6765 vty_out(vty,
6766 " neighbor %s capability extended-nexthop\n",
6767 addr);
6768 }
6769 }
6770
6771 /* dont-capability-negotiation */
6772 if (CHECK_FLAG(peer->flags, PEER_FLAG_DONT_CAPABILITY)) {
6773 if (!peer_group_active(peer)
6774 || !CHECK_FLAG(g_peer->flags, PEER_FLAG_DONT_CAPABILITY)) {
6775 vty_out(vty, " neighbor %s dont-capability-negotiate\n",
6776 addr);
6777 }
6778 }
6779
6780 /* override-capability */
6781 if (CHECK_FLAG(peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) {
6782 if (!peer_group_active(peer)
6783 || !CHECK_FLAG(g_peer->flags,
6784 PEER_FLAG_OVERRIDE_CAPABILITY)) {
6785 vty_out(vty, " neighbor %s override-capability\n",
6786 addr);
6787 }
6788 }
6789
6790 /* strict-capability-match */
6791 if (CHECK_FLAG(peer->flags, PEER_FLAG_STRICT_CAP_MATCH)) {
6792 if (!peer_group_active(peer)
6793 || !CHECK_FLAG(g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH)) {
6794 vty_out(vty, " neighbor %s strict-capability-match\n",
6795 addr);
6796 }
6797 }
0b960b4d
DW
6798}
6799
0b960b4d 6800/* BGP peer configuration display function. */
d62a17ae 6801static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
2b791107 6802 struct peer *peer, afi_t afi, safi_t safi)
d62a17ae 6803{
6804 struct peer *g_peer = NULL;
6805 char *addr;
6806
6807 /* Skip dynamic neighbors. */
6808 if (peer_dynamic_neighbor(peer))
6809 return;
6810
6811 if (peer->conf_if)
6812 addr = peer->conf_if;
6813 else
6814 addr = peer->host;
6815
6816 /************************************
6817 ****** Per AF to the neighbor ******
6818 ************************************/
6819 if (peer_group_active(peer)) {
6820 g_peer = peer->group->conf;
6821
6822 /* If the peer-group is active but peer is not, print a 'no
6823 * activate' */
6824 if (g_peer->afc[afi][safi] && !peer->afc[afi][safi]) {
2b791107 6825 vty_out(vty, " no neighbor %s activate\n", addr);
d62a17ae 6826 }
6827
6828 /* If the peer-group is not active but peer is, print an
6829 'activate' */
6830 else if (!g_peer->afc[afi][safi] && peer->afc[afi][safi]) {
2b791107 6831 vty_out(vty, " neighbor %s activate\n", addr);
d62a17ae 6832 }
6833 } else {
6834 if (peer->afc[afi][safi]) {
6835 if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) {
6836 if (bgp_flag_check(bgp,
6837 BGP_FLAG_NO_DEFAULT_IPV4)) {
2b791107 6838 vty_out(vty, " neighbor %s activate\n",
d62a17ae 6839 addr);
6840 }
6841 } else
2b791107 6842 vty_out(vty, " neighbor %s activate\n", addr);
d62a17ae 6843 } else {
6844 if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) {
6845 if (!bgp_flag_check(bgp,
6846 BGP_FLAG_NO_DEFAULT_IPV4)) {
2b791107 6847 vty_out(vty,
d62a17ae 6848 " no neighbor %s activate\n",
6849 addr);
6850 }
6851 }
6852 }
6853 }
6854
6855 /* addpath TX knobs */
6856 if (peergroup_af_flag_check(peer, afi, safi,
6857 PEER_FLAG_ADDPATH_TX_ALL_PATHS)) {
2b791107 6858 vty_out(vty, " neighbor %s addpath-tx-all-paths\n", addr);
d62a17ae 6859 }
6860
6861 if (peergroup_af_flag_check(peer, afi, safi,
6862 PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) {
2b791107
DL
6863 vty_out(vty, " neighbor %s addpath-tx-bestpath-per-AS\n",
6864 addr);
d62a17ae 6865 }
6866
6867 /* ORF capability. */
6868 if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM)
6869 || peergroup_af_flag_check(peer, afi, safi,
6870 PEER_FLAG_ORF_PREFIX_RM)) {
2b791107 6871 vty_out(vty, " neighbor %s capability orf prefix-list", addr);
d62a17ae 6872
6873 if (peergroup_af_flag_check(peer, afi, safi,
6874 PEER_FLAG_ORF_PREFIX_SM)
6875 && peergroup_af_flag_check(peer, afi, safi,
6876 PEER_FLAG_ORF_PREFIX_RM))
6877 vty_out(vty, " both");
6878 else if (peergroup_af_flag_check(peer, afi, safi,
6879 PEER_FLAG_ORF_PREFIX_SM))
6880 vty_out(vty, " send");
6881 else
6882 vty_out(vty, " receive");
6883 vty_out(vty, "\n");
6884 }
6885
6886 /* Route reflector client. */
6887 if (peergroup_af_flag_check(peer, afi, safi,
6888 PEER_FLAG_REFLECTOR_CLIENT)) {
2b791107 6889 vty_out(vty, " neighbor %s route-reflector-client\n", addr);
d62a17ae 6890 }
6891
6892 /* next-hop-self force */
6893 if (peergroup_af_flag_check(peer, afi, safi,
6894 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
2b791107 6895 vty_out(vty, " neighbor %s next-hop-self force\n", addr);
d62a17ae 6896 }
6897
6898 /* next-hop-self */
6899 if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)) {
2b791107 6900 vty_out(vty, " neighbor %s next-hop-self\n", addr);
d62a17ae 6901 }
6902
6903 /* remove-private-AS */
6904 if (peergroup_af_flag_check(peer, afi, safi,
6905 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)) {
2b791107 6906 vty_out(vty, " neighbor %s remove-private-AS all replace-AS\n",
d62a17ae 6907 addr);
6908 }
6909
6910 else if (peergroup_af_flag_check(peer, afi, safi,
6911 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) {
2b791107
DL
6912 vty_out(vty, " neighbor %s remove-private-AS replace-AS\n",
6913 addr);
d62a17ae 6914 }
6915
6916 else if (peergroup_af_flag_check(peer, afi, safi,
6917 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
2b791107 6918 vty_out(vty, " neighbor %s remove-private-AS all\n", addr);
d62a17ae 6919 }
6920
6921 else if (peergroup_af_flag_check(peer, afi, safi,
6922 PEER_FLAG_REMOVE_PRIVATE_AS)) {
2b791107 6923 vty_out(vty, " neighbor %s remove-private-AS\n", addr);
d62a17ae 6924 }
6925
6926 /* as-override */
6927 if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
2b791107 6928 vty_out(vty, " neighbor %s as-override\n", addr);
d62a17ae 6929 }
6930
6931 /* send-community print. */
6932 if (bgp_option_check(BGP_OPT_CONFIG_CISCO)) {
6933 if (peergroup_af_flag_check(peer, afi, safi,
6934 PEER_FLAG_SEND_COMMUNITY)
6935 && peergroup_af_flag_check(peer, afi, safi,
6936 PEER_FLAG_SEND_EXT_COMMUNITY)
6937 && peergroup_af_flag_check(
6938 peer, afi, safi,
6939 PEER_FLAG_SEND_LARGE_COMMUNITY)) {
2b791107
DL
6940 vty_out(vty, " neighbor %s send-community all\n",
6941 addr);
d62a17ae 6942 } else if (peergroup_af_flag_check(
6943 peer, afi, safi,
6944 PEER_FLAG_SEND_LARGE_COMMUNITY)) {
2b791107
DL
6945 vty_out(vty, " neighbor %s send-community large\n",
6946 addr);
d62a17ae 6947 } else if (peergroup_af_flag_check(
6948 peer, afi, safi,
6949 PEER_FLAG_SEND_EXT_COMMUNITY)) {
2b791107 6950 vty_out(vty, " neighbor %s send-community extended\n",
d62a17ae 6951 addr);
6952 } else if (peergroup_af_flag_check(peer, afi, safi,
6953 PEER_FLAG_SEND_COMMUNITY)) {
2b791107 6954 vty_out(vty, " neighbor %s send-community\n", addr);
d62a17ae 6955 }
6956 } else {
6957 if (!peer_af_flag_check(peer, afi, safi,
6958 PEER_FLAG_SEND_COMMUNITY)
996c9314
LB
6959 && (!g_peer || peer_af_flag_check(g_peer, afi, safi,
6960 PEER_FLAG_SEND_COMMUNITY))
d62a17ae 6961 && !peer_af_flag_check(peer, afi, safi,
6962 PEER_FLAG_SEND_EXT_COMMUNITY)
6963 && (!g_peer
6964 || peer_af_flag_check(g_peer, afi, safi,
6965 PEER_FLAG_SEND_EXT_COMMUNITY))
6966 && !peer_af_flag_check(peer, afi, safi,
6967 PEER_FLAG_SEND_LARGE_COMMUNITY)
996c9314
LB
6968 && (!g_peer || peer_af_flag_check(
6969 g_peer, afi, safi,
6970 PEER_FLAG_SEND_LARGE_COMMUNITY))) {
2b791107
DL
6971 vty_out(vty, " no neighbor %s send-community all\n",
6972 addr);
d62a17ae 6973 } else {
6974 if (!peer_af_flag_check(peer, afi, safi,
6975 PEER_FLAG_SEND_LARGE_COMMUNITY)
6976 && (!g_peer
6977 || peer_af_flag_check(
6978 g_peer, afi, safi,
6979 PEER_FLAG_SEND_LARGE_COMMUNITY))) {
2b791107 6980 vty_out(vty,
d62a17ae 6981 " no neighbor %s send-community large\n",
6982 addr);
6983 }
6984
6985 if (!peer_af_flag_check(peer, afi, safi,
6986 PEER_FLAG_SEND_EXT_COMMUNITY)
6987 && (!g_peer
6988 || peer_af_flag_check(
6989 g_peer, afi, safi,
6990 PEER_FLAG_SEND_EXT_COMMUNITY))) {
2b791107 6991 vty_out(vty,
d62a17ae 6992 " no neighbor %s send-community extended\n",
6993 addr);
6994 }
6995
6996 if (!peer_af_flag_check(peer, afi, safi,
6997 PEER_FLAG_SEND_COMMUNITY)
996c9314
LB
6998 && (!g_peer || peer_af_flag_check(
6999 g_peer, afi, safi,
7000 PEER_FLAG_SEND_COMMUNITY))) {
2b791107 7001 vty_out(vty,
d62a17ae 7002 " no neighbor %s send-community\n",
7003 addr);
7004 }
7005 }
7006 }
7007
7008 /* Default information */
7009 if (peergroup_af_flag_check(peer, afi, safi,
7010 PEER_FLAG_DEFAULT_ORIGINATE)
7011 || (g_peer
7012 && ((peer->default_rmap[afi][safi].name
7013 && !g_peer->default_rmap[afi][safi].name)
7014 || (!peer->default_rmap[afi][safi].name
7015 && g_peer->default_rmap[afi][safi].name)
7016 || (peer->default_rmap[afi][safi].name
7017 && strcmp(peer->default_rmap[afi][safi].name,
7018 g_peer->default_rmap[afi][safi].name))))) {
2b791107 7019 vty_out(vty, " neighbor %s default-originate", addr);
d62a17ae 7020 if (peer->default_rmap[afi][safi].name)
7021 vty_out(vty, " route-map %s",
7022 peer->default_rmap[afi][safi].name);
7023 vty_out(vty, "\n");
7024 }
7025
7026 /* Soft reconfiguration inbound. */
7027 if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_SOFT_RECONFIG)) {
2b791107
DL
7028 vty_out(vty, " neighbor %s soft-reconfiguration inbound\n",
7029 addr);
d62a17ae 7030 }
7031
7032 /* maximum-prefix. */
7033 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
7034 if (!peer_group_active(peer)
7035 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
7036 || g_peer->pmax_threshold[afi][safi]
7037 != peer->pmax_threshold[afi][safi]
7038 || CHECK_FLAG(g_peer->af_flags[afi][safi],
7039 PEER_FLAG_MAX_PREFIX_WARNING)
7040 != CHECK_FLAG(peer->af_flags[afi][safi],
7041 PEER_FLAG_MAX_PREFIX_WARNING)) {
2b791107
DL
7042 vty_out(vty, " neighbor %s maximum-prefix %lu", addr,
7043 peer->pmax[afi][safi]);
d62a17ae 7044 if (peer->pmax_threshold[afi][safi]
7045 != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
7046 vty_out(vty, " %u",
7047 peer->pmax_threshold[afi][safi]);
7048 if (CHECK_FLAG(peer->af_flags[afi][safi],
7049 PEER_FLAG_MAX_PREFIX_WARNING))
7050 vty_out(vty, " warning-only");
7051 if (peer->pmax_restart[afi][safi])
7052 vty_out(vty, " restart %u",
7053 peer->pmax_restart[afi][safi]);
7054 vty_out(vty, "\n");
7055 }
7056
7057 /* Route server client. */
7058 if (peergroup_af_flag_check(peer, afi, safi,
7059 PEER_FLAG_RSERVER_CLIENT)) {
2b791107 7060 vty_out(vty, " neighbor %s route-server-client\n", addr);
d62a17ae 7061 }
7062
7063 /* Nexthop-local unchanged. */
7064 if (peergroup_af_flag_check(peer, afi, safi,
7065 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)) {
2b791107 7066 vty_out(vty, " neighbor %s nexthop-local unchanged\n", addr);
d62a17ae 7067 }
7068
7069 /* allowas-in <1-10> */
7070 if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_ALLOWAS_IN)) {
7071 if (!peer_group_active(peer)
7072 || !peer_af_flag_check(g_peer, afi, safi,
7073 PEER_FLAG_ALLOWAS_IN)
7074 || peer->allowas_in[afi][safi]
7075 != g_peer->allowas_in[afi][safi]) {
7076 if (peer->allowas_in[afi][safi] == 3) {
2b791107
DL
7077 vty_out(vty, " neighbor %s allowas-in\n",
7078 addr);
d62a17ae 7079 } else {
2b791107
DL
7080 vty_out(vty, " neighbor %s allowas-in %d\n",
7081 addr, peer->allowas_in[afi][safi]);
d62a17ae 7082 }
7083 }
7084 }
7085
7086 /* allowas-in origin */
7087 else if (peer_af_flag_check(peer, afi, safi,
7088 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
7089 if (!peer_group_active(peer)
7090 || !peer_af_flag_check(g_peer, afi, safi,
7091 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
2b791107 7092 vty_out(vty, " neighbor %s allowas-in origin\n", addr);
d62a17ae 7093 }
7094 }
7095
7096 /* weight */
7097 if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_WEIGHT))
7098 if (!peer_group_active(peer)
7099 || !peer_af_flag_check(g_peer, afi, safi, PEER_FLAG_WEIGHT)
7100 || peer->weight[afi][safi] != g_peer->weight[afi][safi]) {
7101 if (peer->weight[afi][safi]) {
2b791107
DL
7102 vty_out(vty, " neighbor %s weight %lu\n", addr,
7103 peer->weight[afi][safi]);
d62a17ae 7104 }
7105 }
7106
7107 /* Filter. */
2b791107 7108 bgp_config_write_filter(vty, peer, afi, safi);
d62a17ae 7109
7110 /* atribute-unchanged. */
a4d82a8a
PZ
7111 if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED)
7112 || peer_af_flag_check(peer, afi, safi, PEER_FLAG_NEXTHOP_UNCHANGED)
7113 || peer_af_flag_check(peer, afi, safi, PEER_FLAG_MED_UNCHANGED)) {
7114
7115 if (!peer_group_active(peer)
7116 || peergroup_af_flag_check(peer, afi, safi,
7117 PEER_FLAG_AS_PATH_UNCHANGED)
7118 || peergroup_af_flag_check(peer, afi, safi,
7119 PEER_FLAG_NEXTHOP_UNCHANGED)
7120 || peergroup_af_flag_check(peer, afi, safi,
7121 PEER_FLAG_MED_UNCHANGED)) {
8eeb0335 7122
2b791107 7123 vty_out(vty,
d62a17ae 7124 " neighbor %s attribute-unchanged%s%s%s\n",
7125 addr,
60466a63
QY
7126 peer_af_flag_check(peer, afi, safi,
7127 PEER_FLAG_AS_PATH_UNCHANGED)
d62a17ae 7128 ? " as-path"
7129 : "",
60466a63
QY
7130 peer_af_flag_check(peer, afi, safi,
7131 PEER_FLAG_NEXTHOP_UNCHANGED)
d62a17ae 7132 ? " next-hop"
7133 : "",
8eeb0335
DW
7134 peer_af_flag_check(peer, afi, safi,
7135 PEER_FLAG_MED_UNCHANGED)
d62a17ae 7136 ? " med"
7137 : "");
7138 }
7139 }
718e3744 7140}
7141
2b791107
DL
7142/* Address family based peer configuration display. */
7143static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
7144 safi_t safi)
d62a17ae 7145{
2b791107
DL
7146 struct peer *peer;
7147 struct peer_group *group;
7148 struct listnode *node, *nnode;
d62a17ae 7149
d62a17ae 7150
2b791107 7151 vty_frame(vty, " !\n address-family ");
d62a17ae 7152 if (afi == AFI_IP) {
7153 if (safi == SAFI_UNICAST)
2b791107 7154 vty_frame(vty, "ipv4 unicast");
d62a17ae 7155 else if (safi == SAFI_LABELED_UNICAST)
2b791107 7156 vty_frame(vty, "ipv4 labeled-unicast");
d62a17ae 7157 else if (safi == SAFI_MULTICAST)
2b791107 7158 vty_frame(vty, "ipv4 multicast");
d62a17ae 7159 else if (safi == SAFI_MPLS_VPN)
2b791107 7160 vty_frame(vty, "ipv4 vpn");
d62a17ae 7161 else if (safi == SAFI_ENCAP)
2b791107 7162 vty_frame(vty, "ipv4 encap");
7c40bf39 7163 else if (safi == SAFI_FLOWSPEC)
7164 vty_frame(vty, "ipv4 flowspec");
d62a17ae 7165 } else if (afi == AFI_IP6) {
7166 if (safi == SAFI_UNICAST)
2b791107 7167 vty_frame(vty, "ipv6 unicast");
d62a17ae 7168 else if (safi == SAFI_LABELED_UNICAST)
2b791107 7169 vty_frame(vty, "ipv6 labeled-unicast");
d62a17ae 7170 else if (safi == SAFI_MULTICAST)
2b791107 7171 vty_frame(vty, "ipv6 multicast");
d62a17ae 7172 else if (safi == SAFI_MPLS_VPN)
2b791107 7173 vty_frame(vty, "ipv6 vpn");
d62a17ae 7174 else if (safi == SAFI_ENCAP)
2b791107 7175 vty_frame(vty, "ipv6 encap");
7c40bf39 7176 else if (safi == SAFI_FLOWSPEC)
7177 vty_frame(vty, "ipv6 flowspec");
d62a17ae 7178 } else if (afi == AFI_L2VPN) {
7179 if (safi == SAFI_EVPN)
2b791107 7180 vty_frame(vty, "l2vpn evpn");
d62a17ae 7181 }
2b791107 7182 vty_frame(vty, "\n");
718e3744 7183
2b791107 7184 bgp_config_write_distance(vty, bgp, afi, safi);
718e3744 7185
2b791107 7186 bgp_config_write_network(vty, bgp, afi, safi);
734b349e 7187
2b791107 7188 bgp_config_write_redistribute(vty, bgp, afi, safi);
718e3744 7189
d62a17ae 7190 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group))
2b791107 7191 bgp_config_write_peer_af(vty, bgp, group->conf, afi, safi);
400b1fad 7192
d62a17ae 7193 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
7194 /* Skip dynamic neighbors. */
7195 if (peer_dynamic_neighbor(peer))
7196 continue;
f14e6fdb 7197
d62a17ae 7198 /* Do not display doppelganger peers */
7199 if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
2b791107 7200 bgp_config_write_peer_af(vty, bgp, peer, afi, safi);
d62a17ae 7201 }
165b5fff 7202
2b791107
DL
7203 bgp_config_write_maxpaths(vty, bgp, afi, safi);
7204 bgp_config_write_table_map(vty, bgp, afi, safi);
165b5fff 7205
d62a17ae 7206 if (safi == SAFI_EVPN)
2b791107 7207 bgp_config_write_evpn_info(vty, bgp, afi, safi);
718e3744 7208
b9c7bc5a
PZ
7209 if (safi == SAFI_UNICAST) {
7210 bgp_vpn_policy_config_write_afi(vty, bgp, afi);
7211 if (CHECK_FLAG(bgp->af_flags[afi][safi],
7212 BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT)) {
ddb5b488 7213
b9c7bc5a
PZ
7214 vty_out(vty, " export vpn\n");
7215 }
7216 if (CHECK_FLAG(bgp->af_flags[afi][safi],
7217 BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT)) {
7218
7219 vty_out(vty, " import vpn\n");
7220 }
12a844a5
DS
7221 if (CHECK_FLAG(bgp->af_flags[afi][safi],
7222 BGP_CONFIG_VRF_TO_VRF_IMPORT)) {
7223 struct listnode *node;
7224 char *name;
7225
7226 for (ALL_LIST_ELEMENTS_RO(
7227 bgp->vpn_policy[afi].import_vrf, node,
7228 name))
7229 vty_out(vty, " import vrf %s\n", name);
7230 }
ddb5b488
PZ
7231 }
7232
2b791107 7233 vty_endframe(vty, " exit-address-family\n");
718e3744 7234}
7235
d62a17ae 7236int bgp_config_write(struct vty *vty)
718e3744 7237{
d62a17ae 7238 int write = 0;
7239 struct bgp *bgp;
7240 struct peer_group *group;
7241 struct peer *peer;
7242 struct listnode *node, *nnode;
7243 struct listnode *mnode, *mnnode;
718e3744 7244
d62a17ae 7245 /* BGP Multiple instance. */
7246 if (!bgp_option_check(BGP_OPT_MULTIPLE_INSTANCE)) {
7247 vty_out(vty, "no bgp multiple-instance\n");
7248 write++;
7249 }
718e3744 7250
d62a17ae 7251 /* BGP Config type. */
7252 if (bgp_option_check(BGP_OPT_CONFIG_CISCO)) {
7253 vty_out(vty, "bgp config-type cisco\n");
7254 write++;
7255 }
718e3744 7256
d62a17ae 7257 if (bm->rmap_update_timer != RMAP_DEFAULT_UPDATE_TIMER)
7258 vty_out(vty, "bgp route-map delay-timer %u\n",
7259 bm->rmap_update_timer);
7260
2b791107
DL
7261 if (write)
7262 vty_out(vty, "!\n");
7263
d62a17ae 7264 /* BGP configuration. */
7265 for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
0b5131c9
MK
7266
7267 /* skip all auto created vrf as they dont have user config */
7268 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO))
7269 continue;
7270
d62a17ae 7271 /* Router bgp ASN */
7272 vty_out(vty, "router bgp %u", bgp->as);
7273
7274 if (bgp_option_check(BGP_OPT_MULTIPLE_INSTANCE)) {
7275 if (bgp->name)
7276 vty_out(vty, " %s %s",
7277 (bgp->inst_type
7278 == BGP_INSTANCE_TYPE_VIEW)
7279 ? "view"
7280 : "vrf",
7281 bgp->name);
7282 }
7283 vty_out(vty, "\n");
7284
7285 /* No Synchronization */
7286 if (bgp_option_check(BGP_OPT_CONFIG_CISCO))
7287 vty_out(vty, " no synchronization\n");
7288
7289 /* BGP fast-external-failover. */
7290 if (CHECK_FLAG(bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
7291 vty_out(vty, " no bgp fast-external-failover\n");
7292
7293 /* BGP router ID. */
7294 if (bgp->router_id_static.s_addr != 0)
7295 vty_out(vty, " bgp router-id %s\n",
7296 inet_ntoa(bgp->router_id_static));
7297
7298 /* BGP log-neighbor-changes. */
7299 if (!!bgp_flag_check(bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES)
7300 != DFLT_BGP_LOG_NEIGHBOR_CHANGES)
7301 vty_out(vty, " %sbgp log-neighbor-changes\n",
7302 bgp_flag_check(bgp,
7303 BGP_FLAG_LOG_NEIGHBOR_CHANGES)
7304 ? ""
7305 : "no ");
7306
7307 /* BGP configuration. */
7308 if (bgp_flag_check(bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
7309 vty_out(vty, " bgp always-compare-med\n");
7310
7311 /* BGP default ipv4-unicast. */
7312 if (bgp_flag_check(bgp, BGP_FLAG_NO_DEFAULT_IPV4))
7313 vty_out(vty, " no bgp default ipv4-unicast\n");
7314
7315 /* BGP default local-preference. */
7316 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
7317 vty_out(vty, " bgp default local-preference %u\n",
7318 bgp->default_local_pref);
7319
7320 /* BGP default show-hostname */
7321 if (!!bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME)
7322 != DFLT_BGP_SHOW_HOSTNAME)
7323 vty_out(vty, " %sbgp default show-hostname\n",
7324 bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME)
7325 ? ""
7326 : "no ");
7327
7328 /* BGP default subgroup-pkt-queue-max. */
7329 if (bgp->default_subgroup_pkt_queue_max
7330 != BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX)
7331 vty_out(vty, " bgp default subgroup-pkt-queue-max %u\n",
7332 bgp->default_subgroup_pkt_queue_max);
7333
f26845f9
QY
7334 /* BGP default autoshutdown neighbors */
7335 if (bgp->autoshutdown)
8175f54a 7336 vty_out(vty, " bgp default shutdown\n");
f26845f9 7337
d62a17ae 7338 /* BGP client-to-client reflection. */
7339 if (bgp_flag_check(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
7340 vty_out(vty, " no bgp client-to-client reflection\n");
7341
7342 /* BGP cluster ID. */
7343 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CLUSTER_ID))
7344 vty_out(vty, " bgp cluster-id %s\n",
7345 inet_ntoa(bgp->cluster_id));
7346
7347 /* Disable ebgp connected nexthop check */
7348 if (bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
7349 vty_out(vty,
7350 " bgp disable-ebgp-connected-route-check\n");
7351
7352 /* Confederation identifier*/
7353 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
7354 vty_out(vty, " bgp confederation identifier %i\n",
7355 bgp->confed_id);
7356
7357 /* Confederation peer */
7358 if (bgp->confed_peers_cnt > 0) {
7359 int i;
7360
7361 vty_out(vty, " bgp confederation peers");
7362
7363 for (i = 0; i < bgp->confed_peers_cnt; i++)
7364 vty_out(vty, " %u", bgp->confed_peers[i]);
7365
7366 vty_out(vty, "\n");
7367 }
5fe9f963 7368
d62a17ae 7369 /* BGP enforce-first-as. */
7370 if (bgp_flag_check(bgp, BGP_FLAG_ENFORCE_FIRST_AS))
7371 vty_out(vty, " bgp enforce-first-as\n");
7372
7373 /* BGP deterministic-med. */
7374 if (!!bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)
7375 != DFLT_BGP_DETERMINISTIC_MED)
7376 vty_out(vty, " %sbgp deterministic-med\n",
7377 bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)
7378 ? ""
7379 : "no ");
7380
7381 /* BGP update-delay. */
7382 bgp_config_write_update_delay(vty, bgp);
7383
7384 if (bgp->v_maxmed_onstartup
7385 != BGP_MAXMED_ONSTARTUP_UNCONFIGURED) {
7386 vty_out(vty, " bgp max-med on-startup %u",
7387 bgp->v_maxmed_onstartup);
7388 if (bgp->maxmed_onstartup_value
7389 != BGP_MAXMED_VALUE_DEFAULT)
7390 vty_out(vty, " %u",
7391 bgp->maxmed_onstartup_value);
7392 vty_out(vty, "\n");
7393 }
7394 if (bgp->v_maxmed_admin != BGP_MAXMED_ADMIN_UNCONFIGURED) {
7395 vty_out(vty, " bgp max-med administrative");
7396 if (bgp->maxmed_admin_value != BGP_MAXMED_VALUE_DEFAULT)
7397 vty_out(vty, " %u", bgp->maxmed_admin_value);
7398 vty_out(vty, "\n");
7399 }
718e3744 7400
d62a17ae 7401 /* write quanta */
7402 bgp_config_write_wpkt_quanta(vty, bgp);
555e09d4
QY
7403 /* read quanta */
7404 bgp_config_write_rpkt_quanta(vty, bgp);
d62a17ae 7405
7406 /* coalesce time */
7407 bgp_config_write_coalesce_time(vty, bgp);
7408
7409 /* BGP graceful-restart. */
7410 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
7411 vty_out(vty,
7412 " bgp graceful-restart stalepath-time %u\n",
7413 bgp->stalepath_time);
7414 if (bgp->restart_time != BGP_DEFAULT_RESTART_TIME)
7415 vty_out(vty, " bgp graceful-restart restart-time %u\n",
7416 bgp->restart_time);
7417 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_RESTART))
7418 vty_out(vty, " bgp graceful-restart\n");
7419
7f323236
DW
7420 /* BGP graceful-shutdown */
7421 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN))
7422 vty_out(vty, " bgp graceful-shutdown\n");
7423
d62a17ae 7424 /* BGP graceful-restart Preserve State F bit. */
7425 if (bgp_flag_check(bgp, BGP_FLAG_GR_PRESERVE_FWD))
7426 vty_out(vty,
7427 " bgp graceful-restart preserve-fw-state\n");
7428
7429 /* BGP bestpath method. */
7430 if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_IGNORE))
7431 vty_out(vty, " bgp bestpath as-path ignore\n");
7432 if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_CONFED))
7433 vty_out(vty, " bgp bestpath as-path confed\n");
7434
7435 if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
7436 if (bgp_flag_check(bgp,
7437 BGP_FLAG_MULTIPATH_RELAX_AS_SET)) {
7438 vty_out(vty,
7439 " bgp bestpath as-path multipath-relax as-set\n");
7440 } else {
7441 vty_out(vty,
7442 " bgp bestpath as-path multipath-relax\n");
7443 }
7444 }
718e3744 7445
d62a17ae 7446 if (bgp_flag_check(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
7447 vty_out(vty,
7448 " bgp route-reflector allow-outbound-policy\n");
7449 }
7450 if (bgp_flag_check(bgp, BGP_FLAG_COMPARE_ROUTER_ID))
7451 vty_out(vty, " bgp bestpath compare-routerid\n");
7452 if (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED)
7453 || bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST)) {
7454 vty_out(vty, " bgp bestpath med");
7455 if (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED))
7456 vty_out(vty, " confed");
7457 if (bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST))
7458 vty_out(vty, " missing-as-worst");
7459 vty_out(vty, "\n");
7460 }
718e3744 7461
d62a17ae 7462 /* BGP network import check. */
7463 if (!!bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
7464 != DFLT_BGP_IMPORT_CHECK)
7465 vty_out(vty, " %sbgp network import-check\n",
7466 bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
7467 ? ""
7468 : "no ");
7469
7470 /* BGP flag dampening. */
7471 if (CHECK_FLAG(bgp->af_flags[AFI_IP][SAFI_UNICAST],
7472 BGP_CONFIG_DAMPENING))
7473 bgp_config_write_damp(vty);
7474
7475 /* BGP timers configuration. */
7476 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
7477 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
7478 vty_out(vty, " timers bgp %u %u\n",
7479 bgp->default_keepalive, bgp->default_holdtime);
7480
7481 /* peer-group */
7482 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
7483 bgp_config_write_peer_global(vty, bgp, group->conf);
7484 }
7485
7486 /* Normal neighbor configuration. */
7487 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
7488 if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
7489 bgp_config_write_peer_global(vty, bgp, peer);
7490 }
718e3744 7491
d62a17ae 7492 /* listen range and limit for dynamic BGP neighbors */
7493 bgp_config_write_listen(vty, bgp);
f14e6fdb 7494
d62a17ae 7495 /* No auto-summary */
7496 if (bgp_option_check(BGP_OPT_CONFIG_CISCO))
7497 vty_out(vty, " no auto-summary\n");
718e3744 7498
d62a17ae 7499 /* IPv4 unicast configuration. */
2b791107 7500 bgp_config_write_family(vty, bgp, AFI_IP, SAFI_UNICAST);
0b960b4d 7501
d62a17ae 7502 /* IPv4 multicast configuration. */
2b791107 7503 bgp_config_write_family(vty, bgp, AFI_IP, SAFI_MULTICAST);
718e3744 7504
d62a17ae 7505 /* IPv4 labeled-unicast configuration. */
2b791107 7506 bgp_config_write_family(vty, bgp, AFI_IP, SAFI_LABELED_UNICAST);
f51bae9c 7507
d62a17ae 7508 /* IPv4 VPN configuration. */
2b791107 7509 bgp_config_write_family(vty, bgp, AFI_IP, SAFI_MPLS_VPN);
718e3744 7510
d62a17ae 7511 /* ENCAPv4 configuration. */
2b791107 7512 bgp_config_write_family(vty, bgp, AFI_IP, SAFI_ENCAP);
8b1fb8be 7513
7c40bf39 7514 /* FLOWSPEC v4 configuration. */
7515 bgp_config_write_family(vty, bgp, AFI_IP, SAFI_FLOWSPEC);
7516
d62a17ae 7517 /* IPv6 unicast configuration. */
2b791107 7518 bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_UNICAST);
718e3744 7519
d62a17ae 7520 /* IPv6 multicast configuration. */
2b791107 7521 bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_MULTICAST);
37a217a5 7522
d62a17ae 7523 /* IPv6 labeled-unicast configuration. */
2b791107
DL
7524 bgp_config_write_family(vty, bgp, AFI_IP6,
7525 SAFI_LABELED_UNICAST);
f51bae9c 7526
d62a17ae 7527 /* IPv6 VPN configuration. */
2b791107 7528 bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_MPLS_VPN);
8ecd3266 7529
d62a17ae 7530 /* ENCAPv6 configuration. */
2b791107 7531 bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_ENCAP);
8b1fb8be 7532
7c40bf39 7533 /* FLOWSPEC v6 configuration. */
7534 bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_FLOWSPEC);
7535
d62a17ae 7536 /* EVPN configuration. */
2b791107 7537 bgp_config_write_family(vty, bgp, AFI_L2VPN, SAFI_EVPN);
3d6c0dfa 7538
65efcfce 7539#if ENABLE_BGP_VNC
2b791107 7540 bgp_rfapi_cfg_write(vty, bgp);
65efcfce
LB
7541#endif
7542
2b791107 7543 vty_out(vty, "!\n");
d62a17ae 7544 }
2b791107 7545 return 0;
718e3744 7546}
7547
d62a17ae 7548void bgp_master_init(struct thread_master *master)
718e3744 7549{
d62a17ae 7550 qobj_init();
0e64d123 7551
d62a17ae 7552 memset(&bgp_master, 0, sizeof(struct bgp_master));
718e3744 7553
d62a17ae 7554 bm = &bgp_master;
7555 bm->bgp = list_new();
7556 bm->listen_sockets = list_new();
7557 bm->port = BGP_PORT_DEFAULT;
7558 bm->master = master;
7559 bm->start_time = bgp_clock();
7560 bm->t_rmap_update = NULL;
7561 bm->rmap_update_timer = RMAP_DEFAULT_UPDATE_TIMER;
495f0b13 7562
d62a17ae 7563 bgp_process_queue_init();
b8fd6a15 7564
e9eb5f63 7565 /* init the rd id space.
7566 assign 0th index in the bitfield,
523cafc4 7567 so that we start with id 1
7568 */
e9eb5f63 7569 bf_init(bm->rd_idspace, UINT16_MAX);
7570 bf_assign_zero_index(bm->rd_idspace);
7571
d62a17ae 7572 /* Enable multiple instances by default. */
7573 bgp_option_set(BGP_OPT_MULTIPLE_INSTANCE);
19df7279 7574
955bfd98 7575 /* mpls label dynamic allocation pool */
e70e9f8e 7576 bgp_lp_init(bm->master, &bm->labelpool);
955bfd98 7577
d62a17ae 7578 QOBJ_REG(bm, bgp_master);
718e3744 7579}
200df115 7580
ad4cbda1 7581/*
009b18fc 7582 * Free up connected routes and interfaces for a BGP instance. Invoked upon
7583 * instance delete (non-default only) or BGP exit.
ad4cbda1 7584 */
d62a17ae 7585static void bgp_if_finish(struct bgp *bgp)
ad4cbda1 7586{
f4e14fdb 7587 struct vrf *vrf = vrf_lookup_by_id(bgp->vrf_id);
d62a17ae 7588 struct interface *ifp;
7589
f4e14fdb 7590 if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW || !vrf)
d62a17ae 7591 return;
ad4cbda1 7592
451fda4f 7593 FOR_ALL_INTERFACES (vrf, ifp) {
d62a17ae 7594 struct listnode *c_node, *c_nnode;
7595 struct connected *c;
ad4cbda1 7596
d62a17ae 7597 for (ALL_LIST_ELEMENTS(ifp->connected, c_node, c_nnode, c))
7598 bgp_connected_delete(bgp, c);
7599 }
ad4cbda1 7600}
6b0655a2 7601
d62a17ae 7602extern void bgp_snmp_init(void);
3012671f 7603
d62a17ae 7604static void bgp_viewvrf_autocomplete(vector comps, struct cmd_token *token)
18c57037 7605{
d62a17ae 7606 struct vrf *vrf = NULL;
7607 struct listnode *next;
7608 struct bgp *bgp;
18c57037 7609
a2addae8 7610 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
d62a17ae 7611 if (vrf->vrf_id != VRF_DEFAULT)
7612 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, vrf->name));
7613 }
18c57037 7614
d62a17ae 7615 for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) {
7616 if (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
7617 continue;
18c57037 7618
d62a17ae 7619 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, bgp->name));
7620 }
18c57037
DS
7621}
7622
7623static const struct cmd_variable_handler bgp_viewvrf_var_handlers[] = {
d62a17ae 7624 {.tokenname = "VIEWVRFNAME", .completions = bgp_viewvrf_autocomplete},
7625 {.completions = NULL},
18c57037
DS
7626};
7627
da22432d 7628static void bgp_pthreads_init()
2d4ee774 7629{
0ca8b79f
QY
7630 frr_pthread_init();
7631
a715eab3
QY
7632 struct frr_pthread_attr io = {
7633 .id = PTHREAD_IO,
7634 .start = frr_pthread_attr_default.start,
7635 .stop = frr_pthread_attr_default.stop,
a715eab3
QY
7636 };
7637 struct frr_pthread_attr ka = {
7638 .id = PTHREAD_KEEPALIVES,
7639 .start = bgp_keepalives_start,
7640 .stop = bgp_keepalives_stop,
a715eab3 7641 };
d8a8a8de
QY
7642 frr_pthread_new(&io, "BGP I/O thread");
7643 frr_pthread_new(&ka, "BGP Keepalives thread");
419dfe6a
QY
7644}
7645
7646void bgp_pthreads_run()
7647{
a715eab3
QY
7648 struct frr_pthread *io = frr_pthread_get(PTHREAD_IO);
7649 struct frr_pthread *ka = frr_pthread_get(PTHREAD_KEEPALIVES);
424ab01d 7650
a715eab3
QY
7651 frr_pthread_run(io, NULL);
7652 frr_pthread_run(ka, NULL);
88b24dee 7653
a715eab3
QY
7654 /* Wait until threads are ready. */
7655 frr_pthread_wait_running(io);
7656 frr_pthread_wait_running(ka);
2d4ee774
QY
7657}
7658
7659void bgp_pthreads_finish()
7660{
0ca8b79f
QY
7661 frr_pthread_stop_all();
7662 frr_pthread_finish();
2d4ee774
QY
7663}
7664
d62a17ae 7665void bgp_init(void)
718e3744 7666{
fc9a856f 7667
d62a17ae 7668 /* allocates some vital data structures used by peer commands in
7669 * vty_init */
718e3744 7670
419dfe6a
QY
7671 /* pre-init pthreads */
7672 bgp_pthreads_init();
7673
d62a17ae 7674 /* Init zebra. */
7675 bgp_zebra_init(bm->master);
718e3744 7676
65efcfce 7677#if ENABLE_BGP_VNC
d62a17ae 7678 vnc_zebra_init(bm->master);
65efcfce
LB
7679#endif
7680
d62a17ae 7681 /* BGP VTY commands installation. */
7682 bgp_vty_init();
7683
7684 /* BGP inits. */
7685 bgp_attr_init();
7686 bgp_debug_init();
7687 bgp_dump_init();
7688 bgp_route_init();
7689 bgp_route_map_init();
7690 bgp_scan_vty_init();
7691 bgp_mplsvpn_init();
65efcfce 7692#if ENABLE_BGP_VNC
d62a17ae 7693 rfapi_init();
65efcfce 7694#endif
d62a17ae 7695 bgp_ethernetvpn_init();
7c40bf39 7696 bgp_flowspec_vty_init();
d62a17ae 7697
7698 /* Access list initialize. */
7699 access_list_init();
7700 access_list_add_hook(peer_distribute_update);
7701 access_list_delete_hook(peer_distribute_update);
7702
7703 /* Filter list initialize. */
7704 bgp_filter_init();
7705 as_list_add_hook(peer_aslist_add);
7706 as_list_delete_hook(peer_aslist_del);
7707
7708 /* Prefix list initialize.*/
7709 prefix_list_init();
7710 prefix_list_add_hook(peer_prefix_list_update);
7711 prefix_list_delete_hook(peer_prefix_list_update);
7712
7713 /* Community list initialize. */
7714 bgp_clist = community_list_init();
7715
7716 /* BFD init */
7717 bgp_bfd_init();
7718
7719 cmd_variable_handler_register(bgp_viewvrf_var_handlers);
7720}
7721
7722void bgp_terminate(void)
7723{
7724 struct bgp *bgp;
7725 struct peer *peer;
7726 struct listnode *node, *nnode;
7727 struct listnode *mnode, *mnnode;
7728
7729 QOBJ_UNREG(bm);
7730
7731 /* Close the listener sockets first as this prevents peers from
7732 * attempting
7733 * to reconnect on receiving the peer unconfig message. In the presence
7734 * of a large number of peers this will ensure that no peer is left with
7735 * a dangling connection
7736 */
7737 /* reverse bgp_master_init */
7738 bgp_close();
c3004bc4 7739
d62a17ae 7740 if (bm->listen_sockets)
acdf5e25 7741 list_delete_and_null(&bm->listen_sockets);
d62a17ae 7742
7743 for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp))
7744 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
7745 if (peer->status == Established
7746 || peer->status == OpenSent
7747 || peer->status == OpenConfirm)
7748 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
7749 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
7750
e208c8f9
DS
7751 if (bm->process_main_queue)
7752 work_queue_free_and_null(&bm->process_main_queue);
d62a17ae 7753
7754 if (bm->t_rmap_update)
7755 BGP_TIMER_OFF(bm->t_rmap_update);
955bfd98 7756
e70e9f8e 7757 bgp_lp_finish();
545acafb 7758}