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