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