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