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