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