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