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