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