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