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