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