]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgpd.c
Handle hostname/domainname properly for FreeBSD
[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;
d62a17ae 2741
2742 if ((bgp = XCALLOC(MTYPE_BGP, sizeof(struct bgp))) == NULL)
2743 return NULL;
2744
2745 if (BGP_DEBUG(zebra, ZEBRA)) {
2746 if (inst_type == BGP_INSTANCE_TYPE_DEFAULT)
2747 zlog_debug("Creating Default VRF, AS %u", *as);
2748 else
2749 zlog_debug("Creating %s %s, AS %u",
2750 (inst_type == BGP_INSTANCE_TYPE_VRF)
2751 ? "VRF"
2752 : "VIEW",
2753 name, *as);
718e3744 2754 }
adbac85e 2755
d62a17ae 2756 bgp_lock(bgp);
2757 bgp->inst_type = inst_type;
2758 bgp->vrf_id = (inst_type == BGP_INSTANCE_TYPE_DEFAULT) ? VRF_DEFAULT
2759 : VRF_UNKNOWN;
2760 bgp->peer_self = peer_new(bgp);
2761 if (bgp->peer_self->host)
2762 XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->host);
2763 bgp->peer_self->host =
2764 XSTRDUP(MTYPE_BGP_PEER_HOST, "Static announcement");
d77114b7
MK
2765 if (bgp->peer_self->hostname != NULL) {
2766 XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->hostname);
2767 bgp->peer_self->hostname = NULL;
2768 }
0802e118
MK
2769 if (hostname_get())
2770 bgp->peer_self->hostname = XSTRDUP(MTYPE_BGP_PEER_HOST,
2771 hostname_get());
d77114b7
MK
2772
2773 if (bgp->peer_self->domainname != NULL) {
2774 XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->domainname);
2775 bgp->peer_self->domainname = NULL;
2776 }
0802e118
MK
2777 if (domainname_get())
2778 bgp->peer_self->domainname = XSTRDUP(MTYPE_BGP_PEER_HOST,
2779 domainname_get());
d62a17ae 2780 bgp->peer = list_new();
2781 bgp->peer->cmp = (int (*)(void *, void *))peer_cmp;
40520c36
DW
2782 bgp->peerhash = hash_create(peer_hash_key_make, peer_hash_same, NULL);
2783 bgp->peerhash->max_size = BGP_PEER_MAX_HASH_SIZE;
d62a17ae 2784
2785 bgp->group = list_new();
2786 bgp->group->cmp = (int (*)(void *, void *))peer_group_cmp;
2787
2788 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2789 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
2790 bgp->route[afi][safi] = bgp_table_init(afi, safi);
2791 bgp->aggregate[afi][safi] = bgp_table_init(afi, safi);
2792 bgp->rib[afi][safi] = bgp_table_init(afi, safi);
2793
2794 /* Enable maximum-paths */
2795 bgp_maximum_paths_set(bgp, afi, safi, BGP_PEER_EBGP,
2796 multipath_num, 0);
2797 bgp_maximum_paths_set(bgp, afi, safi, BGP_PEER_IBGP,
2798 multipath_num, 0);
2799 }
2800
2801 bgp->v_update_delay = BGP_UPDATE_DELAY_DEF;
2802 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
2803 bgp->default_subgroup_pkt_queue_max =
2804 BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX;
2805 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
2806 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
2807 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
2808 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
2809 bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT;
2810 bgp->dynamic_neighbors_count = 0;
2811#if DFLT_BGP_IMPORT_CHECK
2812 bgp_flag_set(bgp, BGP_FLAG_IMPORT_CHECK);
2813#endif
2814#if DFLT_BGP_SHOW_HOSTNAME
2815 bgp_flag_set(bgp, BGP_FLAG_SHOW_HOSTNAME);
2816#endif
2817#if DFLT_BGP_LOG_NEIGHBOR_CHANGES
2818 bgp_flag_set(bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES);
2819#endif
2820#if DFLT_BGP_DETERMINISTIC_MED
2821 bgp_flag_set(bgp, BGP_FLAG_DETERMINISTIC_MED);
2822#endif
2823 bgp->addpath_tx_id = BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE;
2824
2825 bgp->as = *as;
2826
2827#if ENABLE_BGP_VNC
2828 if (inst_type != BGP_INSTANCE_TYPE_VRF) {
2829 bgp->rfapi = bgp_rfapi_new(bgp);
2830 assert(bgp->rfapi);
2831 assert(bgp->rfapi_cfg);
2832 }
2833#endif /* ENABLE_BGP_VNC */
adbac85e 2834
d62a17ae 2835 if (name) {
2836 bgp->name = XSTRDUP(MTYPE_BGP, name);
2837 } else {
2838 /* TODO - The startup timer needs to be run for the whole of BGP
2839 */
2840 thread_add_timer(bm->master, bgp_startup_timer_expire, bgp,
2841 bgp->restart_time, &bgp->t_startup);
2842 }
06370dac 2843
d62a17ae 2844 bgp->wpkt_quanta = BGP_WRITE_PACKET_MAX;
2845 bgp->coalesce_time = BGP_DEFAULT_SUBGROUP_COALESCE_TIME;
adbac85e 2846
d62a17ae 2847 QOBJ_REG(bgp, bgp);
adbac85e 2848
d62a17ae 2849 update_bgp_group_init(bgp);
2850 bgp_evpn_init(bgp);
2851 return bgp;
718e3744 2852}
2853
d62a17ae 2854/* Return the "default VRF" instance of BGP. */
2855struct bgp *bgp_get_default(void)
718e3744 2856{
d62a17ae 2857 struct bgp *bgp;
2858 struct listnode *node, *nnode;
2859
2860 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
2861 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
2862 return bgp;
2863 return NULL;
718e3744 2864}
2865
d62a17ae 2866/* Lookup BGP entry. */
2867struct bgp *bgp_lookup(as_t as, const char *name)
718e3744 2868{
d62a17ae 2869 struct bgp *bgp;
2870 struct listnode *node, *nnode;
6b0655a2 2871
d62a17ae 2872 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
2873 if (bgp->as == as
2874 && ((bgp->name == NULL && name == NULL)
2875 || (bgp->name && name && strcmp(bgp->name, name) == 0)))
2876 return bgp;
2877 return NULL;
2878}
73d70fa6 2879
d62a17ae 2880/* Lookup BGP structure by view name. */
2881struct bgp *bgp_lookup_by_name(const char *name)
73d70fa6 2882{
d62a17ae 2883 struct bgp *bgp;
2884 struct listnode *node, *nnode;
2885
2886 for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
2887 if ((bgp->name == NULL && name == NULL)
2888 || (bgp->name && name && strcmp(bgp->name, name) == 0))
2889 return bgp;
2890 return NULL;
73d70fa6
DL
2891}
2892
d62a17ae 2893/* Lookup BGP instance based on VRF id. */
2894/* Note: Only to be used for incoming messages from Zebra. */
2895struct bgp *bgp_lookup_by_vrf_id(vrf_id_t vrf_id)
73d70fa6 2896{
d62a17ae 2897 struct vrf *vrf;
2898
2899 /* Lookup VRF (in tree) and follow link. */
2900 vrf = vrf_lookup_by_id(vrf_id);
2901 if (!vrf)
2902 return NULL;
2903 return (vrf->info) ? (struct bgp *)vrf->info : NULL;
73d70fa6
DL
2904}
2905
d62a17ae 2906/* Called from VTY commands. */
2907int bgp_get(struct bgp **bgp_val, as_t *as, const char *name,
2908 enum bgp_instance_type inst_type)
2909{
2910 struct bgp *bgp;
2911
2912 /* Multiple instance check. */
2913 if (bgp_option_check(BGP_OPT_MULTIPLE_INSTANCE)) {
2914 if (name)
2915 bgp = bgp_lookup_by_name(name);
2916 else
2917 bgp = bgp_get_default();
2918
2919 /* Already exists. */
2920 if (bgp) {
2921 if (bgp->as != *as) {
2922 *as = bgp->as;
2923 return BGP_ERR_INSTANCE_MISMATCH;
2924 }
2925 if (bgp->inst_type != inst_type)
2926 return BGP_ERR_INSTANCE_MISMATCH;
2927 *bgp_val = bgp;
2928 return 0;
2929 }
2930 } else {
2931 /* BGP instance name can not be specified for single instance.
2932 */
2933 if (name)
2934 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2935
2936 /* Get default BGP structure if exists. */
2937 bgp = bgp_get_default();
2938
2939 if (bgp) {
2940 if (bgp->as != *as) {
2941 *as = bgp->as;
2942 return BGP_ERR_AS_MISMATCH;
2943 }
2944 *bgp_val = bgp;
2945 return 0;
2946 }
2947 }
73d70fa6 2948
d62a17ae 2949 bgp = bgp_create(as, name, inst_type);
2950 bgp_router_id_set(bgp, &bgp->router_id_zebra);
2951 bgp_address_init(bgp);
db0e1937 2952 bgp_tip_hash_init(bgp);
d62a17ae 2953 bgp_scan_init(bgp);
2954 *bgp_val = bgp;
eb821189 2955
d62a17ae 2956 bgp->t_rmap_def_originate_eval = NULL;
e5cc509c 2957
d62a17ae 2958 /* Create BGP server socket, if first instance. */
2959 if (list_isempty(bm->bgp) && !bgp_option_check(BGP_OPT_NO_LISTEN)) {
2960 if (bgp_socket(bm->port, bm->address) < 0)
2961 return BGP_ERR_INVALID_VALUE;
eb821189 2962 }
6b0655a2 2963
d62a17ae 2964 listnode_add(bm->bgp, bgp);
718e3744 2965
d62a17ae 2966 /* If Default instance or VRF, link to the VRF structure, if present. */
2967 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT
2968 || bgp->inst_type == BGP_INSTANCE_TYPE_VRF) {
2969 struct vrf *vrf;
718e3744 2970
d62a17ae 2971 vrf = bgp_vrf_lookup_by_instance_type(bgp);
2972 if (vrf)
2973 bgp_vrf_link(bgp, vrf);
2974 }
718e3744 2975
d62a17ae 2976 /* Register with Zebra, if needed */
2977 if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
2978 bgp_zebra_instance_register(bgp);
718e3744 2979
718e3744 2980
d62a17ae 2981 return 0;
718e3744 2982}
6b0655a2 2983
d62a17ae 2984/*
2985 * Make BGP instance "up". Applies only to VRFs (non-default) and
2986 * implies the VRF has been learnt from Zebra.
2987 */
2988void bgp_instance_up(struct bgp *bgp)
718e3744 2989{
d62a17ae 2990 struct peer *peer;
2991 struct listnode *node, *next;
718e3744 2992
d62a17ae 2993 /* Register with zebra. */
2994 bgp_zebra_instance_register(bgp);
718e3744 2995
d62a17ae 2996 /* Kick off any peers that may have been configured. */
2997 for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) {
2998 if (!BGP_PEER_START_SUPPRESSED(peer))
2999 BGP_EVENT_ADD(peer, BGP_Start);
718e3744 3000 }
3001
d62a17ae 3002 /* Process any networks that have been configured. */
3003 bgp_static_add(bgp);
3004}
3005
3006/*
3007 * Make BGP instance "down". Applies only to VRFs (non-default) and
3008 * implies the VRF has been deleted by Zebra.
3009 */
3010void bgp_instance_down(struct bgp *bgp)
3011{
3012 struct peer *peer;
3013 struct listnode *node;
3014 struct listnode *next;
3015
3016 /* Stop timers. */
3017 if (bgp->t_rmap_def_originate_eval) {
3018 BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval);
3019 bgp_unlock(bgp); /* TODO - This timer is started with a lock -
3020 why? */
718e3744 3021 }
3022
d62a17ae 3023 /* Bring down peers, so corresponding routes are purged. */
3024 for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) {
3025 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3026 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
3027 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
3028 else
3029 bgp_session_reset(peer);
3030 }
718e3744 3031
d62a17ae 3032 /* Purge network and redistributed routes. */
3033 bgp_purge_static_redist_routes(bgp);
ee7ca6c0 3034
3035 /* Cleanup registered nexthops (flags) */
3036 bgp_cleanup_nexthops(bgp);
718e3744 3037}
3038
d62a17ae 3039/* Delete BGP instance. */
3040int bgp_delete(struct bgp *bgp)
3041{
3042 struct peer *peer;
3043 struct peer_group *group;
3044 struct listnode *node, *next;
3045 struct vrf *vrf;
3046 afi_t afi;
3047 int i;
3048
3049 THREAD_OFF(bgp->t_startup);
3050
3051 if (BGP_DEBUG(zebra, ZEBRA)) {
3052 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
3053 zlog_debug("Deleting Default VRF");
3054 else
3055 zlog_debug("Deleting %s %s",
3056 (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
3057 ? "VRF"
3058 : "VIEW",
3059 bgp->name);
718e3744 3060 }
3061
d62a17ae 3062 /* Stop timers. */
3063 if (bgp->t_rmap_def_originate_eval) {
3064 BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval);
3065 bgp_unlock(bgp); /* TODO - This timer is started with a lock -
3066 why? */
718e3744 3067 }
3068
d62a17ae 3069 /* Inform peers we're going down. */
3070 for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) {
3071 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3072 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
3073 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
718e3744 3074 }
3075
d62a17ae 3076 /* Delete static routes (networks). */
3077 bgp_static_delete(bgp);
6b0655a2 3078
d62a17ae 3079 /* Unset redistribution. */
3080 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3081 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3082 if (i != ZEBRA_ROUTE_BGP)
3083 bgp_redistribute_unset(bgp, afi, i, 0);
718e3744 3084
d62a17ae 3085 /* Free peers and peer-groups. */
3086 for (ALL_LIST_ELEMENTS(bgp->group, node, next, group))
3087 peer_group_delete(group);
718e3744 3088
d62a17ae 3089 for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer))
3090 peer_delete(peer);
3091
3092 if (bgp->peer_self) {
3093 peer_delete(bgp->peer_self);
3094 bgp->peer_self = NULL;
718e3744 3095 }
3096
d62a17ae 3097 update_bgp_group_free(bgp);
718e3744 3098
d62a17ae 3099/* TODO - Other memory may need to be freed - e.g., NHT */
3100
3101#if ENABLE_BGP_VNC
3102 rfapi_delete(bgp);
3103#endif
3104 bgp_cleanup_routes(bgp);
718e3744 3105
d62a17ae 3106 /* Remove visibility via the master list - there may however still be
3107 * routes to be processed still referencing the struct bgp.
3108 */
3109 listnode_delete(bm->bgp, bgp);
718e3744 3110
d62a17ae 3111 /* Deregister from Zebra, if needed */
3112 if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
3113 bgp_zebra_instance_deregister(bgp);
718e3744 3114
d62a17ae 3115 /* Free interfaces in this instance. */
3116 bgp_if_finish(bgp);
718e3744 3117
d62a17ae 3118 vrf = bgp_vrf_lookup_by_instance_type(bgp);
3119 if (vrf)
3120 bgp_vrf_unlink(bgp, vrf);
718e3744 3121
d62a17ae 3122 thread_master_free_unused(bm->master);
3123 bgp_unlock(bgp); /* initial reference */
718e3744 3124
d62a17ae 3125 return 0;
718e3744 3126}
6b0655a2 3127
d62a17ae 3128static void bgp_free(struct bgp *);
3129
3130void bgp_lock(struct bgp *bgp)
718e3744 3131{
d62a17ae 3132 ++bgp->lock;
718e3744 3133}
3134
d62a17ae 3135void bgp_unlock(struct bgp *bgp)
718e3744 3136{
d62a17ae 3137 assert(bgp->lock > 0);
3138 if (--bgp->lock == 0)
3139 bgp_free(bgp);
718e3744 3140}
6b0655a2 3141
d62a17ae 3142static void bgp_free(struct bgp *bgp)
d93f7ffc 3143{
d62a17ae 3144 afi_t afi;
3145 safi_t safi;
3146 struct bgp_table *table;
3147 struct bgp_node *rn;
d93f7ffc 3148
d62a17ae 3149 QOBJ_UNREG(bgp);
d93f7ffc 3150
d62a17ae 3151 list_delete(bgp->group);
3152 list_delete(bgp->peer);
966f821c 3153
d62a17ae 3154 if (bgp->peerhash) {
3155 hash_free(bgp->peerhash);
3156 bgp->peerhash = NULL;
3157 }
718e3744 3158
d62a17ae 3159 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3160 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
3161 /* Special handling for 2-level routing tables. */
3162 if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
3163 || safi == SAFI_EVPN) {
3164 for (rn = bgp_table_top(bgp->rib[afi][safi]);
3165 rn; rn = bgp_route_next(rn)) {
3166 table = (struct bgp_table *)rn->info;
3167 bgp_table_finish(&table);
3168 }
3169 }
3170 if (bgp->route[afi][safi])
3171 bgp_table_finish(&bgp->route[afi][safi]);
3172 if (bgp->aggregate[afi][safi])
3173 bgp_table_finish(&bgp->aggregate[afi][safi]);
3174 if (bgp->rib[afi][safi])
3175 bgp_table_finish(&bgp->rib[afi][safi]);
3176 }
718e3744 3177
d62a17ae 3178 bgp_scan_finish(bgp);
3179 bgp_address_destroy(bgp);
db0e1937 3180 bgp_tip_hash_destroy(bgp);
966f821c 3181
d62a17ae 3182 bgp_evpn_cleanup(bgp);
718e3744 3183
d62a17ae 3184 if (bgp->name)
3185 XFREE(MTYPE_BGP, bgp->name);
966f821c 3186
d62a17ae 3187 XFREE(MTYPE_BGP, bgp);
718e3744 3188}
3189
d62a17ae 3190struct peer *peer_lookup_by_conf_if(struct bgp *bgp, const char *conf_if)
718e3744 3191{
d62a17ae 3192 struct peer *peer;
3193 struct listnode *node, *nnode;
966f821c 3194
d62a17ae 3195 if (!conf_if)
3196 return NULL;
6b0655a2 3197
d62a17ae 3198 if (bgp != NULL) {
3199 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
3200 if (peer->conf_if && !strcmp(peer->conf_if, conf_if)
3201 && !CHECK_FLAG(peer->sflags,
3202 PEER_STATUS_ACCEPT_PEER))
3203 return peer;
3204 } else if (bm->bgp != NULL) {
3205 struct listnode *bgpnode, *nbgpnode;
3206
3207 for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp))
3208 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
3209 if (peer->conf_if
3210 && !strcmp(peer->conf_if, conf_if)
3211 && !CHECK_FLAG(peer->sflags,
3212 PEER_STATUS_ACCEPT_PEER))
3213 return peer;
3214 }
3215 return NULL;
718e3744 3216}
3217
d62a17ae 3218struct peer *peer_lookup_by_hostname(struct bgp *bgp, const char *hostname)
718e3744 3219{
d62a17ae 3220 struct peer *peer;
3221 struct listnode *node, *nnode;
6b0655a2 3222
d62a17ae 3223 if (!hostname)
3224 return NULL;
6b0655a2 3225
d62a17ae 3226 if (bgp != NULL) {
3227 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
3228 if (peer->hostname && !strcmp(peer->hostname, hostname)
3229 && !CHECK_FLAG(peer->sflags,
3230 PEER_STATUS_ACCEPT_PEER))
3231 return peer;
3232 } else if (bm->bgp != NULL) {
3233 struct listnode *bgpnode, *nbgpnode;
3234
3235 for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp))
3236 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
3237 if (peer->hostname
3238 && !strcmp(peer->hostname, hostname)
3239 && !CHECK_FLAG(peer->sflags,
3240 PEER_STATUS_ACCEPT_PEER))
3241 return peer;
3242 }
3243 return NULL;
3244}
3245
3246struct peer *peer_lookup(struct bgp *bgp, union sockunion *su)
3247{
3248 struct peer *peer = NULL;
3249 struct peer tmp_peer;
3250
3251 memset(&tmp_peer, 0, sizeof(struct peer));
3252
3253 /*
3254 * We do not want to find the doppelganger peer so search for the peer
3255 * in
3256 * the hash that has PEER_FLAG_CONFIG_NODE
3257 */
3258 SET_FLAG(tmp_peer.flags, PEER_FLAG_CONFIG_NODE);
3259
3260 tmp_peer.su = *su;
3261
3262 if (bgp != NULL) {
3263 peer = hash_lookup(bgp->peerhash, &tmp_peer);
3264 } else if (bm->bgp != NULL) {
3265 struct listnode *bgpnode, *nbgpnode;
3266
3267 for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp)) {
3268 /* Skip VRFs, this function will not be invoked without
3269 * an instance
3270 * when examining VRFs.
3271 */
3272 if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
3273 continue;
3274
3275 peer = hash_lookup(bgp->peerhash, &tmp_peer);
3276
3277 if (peer)
3278 break;
3279 }
3280 }
3281
3282 return peer;
3283}
3284
3285struct peer *peer_create_bind_dynamic_neighbor(struct bgp *bgp,
3286 union sockunion *su,
3287 struct peer_group *group)
3288{
3289 struct peer *peer;
3290 afi_t afi;
3291 safi_t safi;
3292
3293 /* Create peer first; we've already checked group config is valid. */
3294 peer = peer_create(su, NULL, bgp, bgp->as, group->conf->as,
3295 group->conf->as_type, 0, 0, group);
3296 if (!peer)
3297 return NULL;
3298
3299 /* Link to group */
3300 peer = peer_lock(peer);
3301 listnode_add(group->peer, peer);
3302
3303 peer_group2peer_config_copy(group, peer);
3304
3305 /*
3306 * Bind peer for all AFs configured for the group. We don't call
3307 * peer_group_bind as that is sub-optimal and does some stuff we don't
3308 * want.
3309 */
3310 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3311 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
3312 if (!group->conf->afc[afi][safi])
3313 continue;
3314 peer->afc[afi][safi] = 1;
3315
3316 if (!peer_af_find(peer, afi, safi))
3317 peer_af_create(peer, afi, safi);
3318
3319 peer_group2peer_config_copy_af(group, peer, afi, safi);
3320 }
3321
3322 /* Mark as dynamic, but also as a "config node" for other things to
3323 * work. */
3324 SET_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR);
3325 SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
3326
3327 return peer;
3328}
3329
3330struct prefix *
3331peer_group_lookup_dynamic_neighbor_range(struct peer_group *group,
3332 struct prefix *prefix)
3333{
3334 struct listnode *node, *nnode;
3335 struct prefix *range;
3336 afi_t afi;
3337
3338 afi = family2afi(prefix->family);
3339
3340 if (group->listen_range[afi])
3341 for (ALL_LIST_ELEMENTS(group->listen_range[afi], node, nnode,
3342 range))
3343 if (prefix_match(range, prefix))
3344 return range;
3345
3346 return NULL;
3347}
3348
3349struct peer_group *
3350peer_group_lookup_dynamic_neighbor(struct bgp *bgp, struct prefix *prefix,
3351 struct prefix **listen_range)
3352{
3353 struct prefix *range = NULL;
3354 struct peer_group *group = NULL;
3355 struct listnode *node, *nnode;
3356
3357 *listen_range = NULL;
3358 if (bgp != NULL) {
3359 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group))
3360 if ((range = peer_group_lookup_dynamic_neighbor_range(
3361 group, prefix)))
3362 break;
3363 } else if (bm->bgp != NULL) {
3364 struct listnode *bgpnode, *nbgpnode;
3365
3366 for (ALL_LIST_ELEMENTS(bm->bgp, bgpnode, nbgpnode, bgp))
3367 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group))
3368 if ((range = peer_group_lookup_dynamic_neighbor_range(
3369 group, prefix)))
3370 goto found_range;
3371 }
3372
3373found_range:
3374 *listen_range = range;
3375 return (group && range) ? group : NULL;
3376}
3377
3378struct peer *peer_lookup_dynamic_neighbor(struct bgp *bgp, union sockunion *su)
3379{
3380 struct peer_group *group;
3381 struct bgp *gbgp;
3382 struct peer *peer;
3383 struct prefix prefix;
3384 struct prefix *listen_range;
3385 int dncount;
3386 char buf[PREFIX2STR_BUFFER];
3387 char buf1[PREFIX2STR_BUFFER];
3388
3389 sockunion2hostprefix(su, &prefix);
3390
3391 /* See if incoming connection matches a configured listen range. */
3392 group = peer_group_lookup_dynamic_neighbor(bgp, &prefix, &listen_range);
3393
3394 if (!group)
3395 return NULL;
3396
3397
3398 gbgp = group->bgp;
3399
3400 if (!gbgp)
3401 return NULL;
3402
3403 prefix2str(&prefix, buf, sizeof(buf));
3404 prefix2str(listen_range, buf1, sizeof(buf1));
3405
3406 if (bgp_debug_neighbor_events(NULL))
3407 zlog_debug(
3408 "Dynamic Neighbor %s matches group %s listen range %s",
3409 buf, group->name, buf1);
3410
3411 /* Are we within the listen limit? */
3412 dncount = gbgp->dynamic_neighbors_count;
3413
3414 if (dncount >= gbgp->dynamic_neighbors_limit) {
3415 if (bgp_debug_neighbor_events(NULL))
3416 zlog_debug("Dynamic Neighbor %s rejected - at limit %d",
3417 inet_sutop(su, buf),
3418 gbgp->dynamic_neighbors_limit);
3419 return NULL;
3420 }
3421
3422 /* Ensure group is not disabled. */
3423 if (CHECK_FLAG(group->conf->flags, PEER_FLAG_SHUTDOWN)) {
3424 if (bgp_debug_neighbor_events(NULL))
3425 zlog_debug(
3426 "Dynamic Neighbor %s rejected - group %s disabled",
3427 buf, group->name);
3428 return NULL;
3429 }
3430
3431 /* Check that at least one AF is activated for the group. */
3432 if (!peer_group_af_configured(group)) {
3433 if (bgp_debug_neighbor_events(NULL))
3434 zlog_debug(
3435 "Dynamic Neighbor %s rejected - no AF activated for group %s",
3436 buf, group->name);
3437 return NULL;
3438 }
3439
3440 /* Create dynamic peer and bind to associated group. */
3441 peer = peer_create_bind_dynamic_neighbor(gbgp, su, group);
3442 assert(peer);
3443
3444 gbgp->dynamic_neighbors_count = ++dncount;
3445
3446 if (bgp_debug_neighbor_events(peer))
3447 zlog_debug("%s Dynamic Neighbor added, group %s count %d",
3448 peer->host, group->name, dncount);
3449
3450 return peer;
3451}
3452
3453void peer_drop_dynamic_neighbor(struct peer *peer)
3454{
3455 int dncount = -1;
3456 if (peer->group && peer->group->bgp) {
3457 dncount = peer->group->bgp->dynamic_neighbors_count;
3458 if (dncount)
3459 peer->group->bgp->dynamic_neighbors_count = --dncount;
3460 }
3461 if (bgp_debug_neighbor_events(peer))
3462 zlog_debug("%s dropped from group %s, count %d", peer->host,
3463 peer->group->name, dncount);
3464}
3465
3466
3467/* If peer is configured at least one address family return 1. */
3468int peer_active(struct peer *peer)
3469{
3470 if (BGP_PEER_SU_UNSPEC(peer))
3471 return 0;
3472 if (peer->afc[AFI_IP][SAFI_UNICAST] || peer->afc[AFI_IP][SAFI_MULTICAST]
3473 || peer->afc[AFI_IP][SAFI_LABELED_UNICAST]
3474 || peer->afc[AFI_IP][SAFI_MPLS_VPN] || peer->afc[AFI_IP][SAFI_ENCAP]
3475 || peer->afc[AFI_IP6][SAFI_UNICAST]
3476 || peer->afc[AFI_IP6][SAFI_MULTICAST]
3477 || peer->afc[AFI_IP6][SAFI_LABELED_UNICAST]
3478 || peer->afc[AFI_IP6][SAFI_MPLS_VPN]
3479 || peer->afc[AFI_IP6][SAFI_ENCAP]
3480 || peer->afc[AFI_L2VPN][SAFI_EVPN])
3481 return 1;
3482 return 0;
3483}
3484
3485/* If peer is negotiated at least one address family return 1. */
3486int peer_active_nego(struct peer *peer)
3487{
3488 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
3489 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
3490 || peer->afc_nego[AFI_IP][SAFI_LABELED_UNICAST]
3491 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
3492 || peer->afc_nego[AFI_IP][SAFI_ENCAP]
3493 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
3494 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
3495 || peer->afc_nego[AFI_IP6][SAFI_LABELED_UNICAST]
3496 || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
3497 || peer->afc_nego[AFI_IP6][SAFI_ENCAP]
3498 || peer->afc_nego[AFI_L2VPN][SAFI_EVPN])
3499 return 1;
3500 return 0;
3501}
3502
3503/* peer_flag_change_type. */
3504enum peer_change_type {
3505 peer_change_none,
3506 peer_change_reset,
3507 peer_change_reset_in,
3508 peer_change_reset_out,
3509};
3510
3511static void peer_change_action(struct peer *peer, afi_t afi, safi_t safi,
3512 enum peer_change_type type)
3513{
3514 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
3515 return;
3516
3517 if (peer->status != Established)
3518 return;
3519
3520 if (type == peer_change_reset) {
3521 /* If we're resetting session, we've to delete both peer struct
3522 */
3523 if ((peer->doppelganger)
3524 && (peer->doppelganger->status != Deleted)
3525 && (!CHECK_FLAG(peer->doppelganger->flags,
3526 PEER_FLAG_CONFIG_NODE)))
3527 peer_delete(peer->doppelganger);
3528
3529 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
3530 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3531 } else if (type == peer_change_reset_in) {
3532 if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV)
3533 || CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV))
3534 bgp_route_refresh_send(peer, afi, safi, 0, 0, 0);
3535 else {
3536 if ((peer->doppelganger)
3537 && (peer->doppelganger->status != Deleted)
3538 && (!CHECK_FLAG(peer->doppelganger->flags,
3539 PEER_FLAG_CONFIG_NODE)))
3540 peer_delete(peer->doppelganger);
3541
3542 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
3543 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3544 }
3545 } else if (type == peer_change_reset_out) {
3546 update_group_adjust_peer(peer_af_find(peer, afi, safi));
3547 bgp_announce_route(peer, afi, safi);
3548 }
3549}
3550
3551struct peer_flag_action {
3552 /* Peer's flag. */
3553 u_int32_t flag;
3554
3555 /* This flag can be set for peer-group member. */
3556 u_char not_for_member;
3557
3558 /* Action when the flag is changed. */
3559 enum peer_change_type type;
3560
3561 /* Peer down cause */
3562 u_char peer_down;
3563};
3564
3565static const struct peer_flag_action peer_flag_action_list[] = {
3566 {PEER_FLAG_PASSIVE, 0, peer_change_reset},
3567 {PEER_FLAG_SHUTDOWN, 0, peer_change_reset},
3568 {PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none},
3569 {PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none},
3570 {PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none},
3571 {PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset},
3572 {PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset},
3573 {PEER_FLAG_CAPABILITY_ENHE, 0, peer_change_reset},
3574 {0, 0, 0}};
3575
3576static const struct peer_flag_action peer_af_flag_action_list[] = {
3577 {PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out},
3578 {PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out},
3579 {PEER_FLAG_SEND_LARGE_COMMUNITY, 1, peer_change_reset_out},
3580 {PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out},
3581 {PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset},
3582 {PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset},
3583 {PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in},
3584 {PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out},
3585 {PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out},
3586 {PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out},
3587 // PEER_FLAG_DEFAULT_ORIGINATE
3588 {PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out},
3589 {PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in},
3590 {PEER_FLAG_ALLOWAS_IN_ORIGIN, 0, peer_change_reset_in},
3591 {PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset},
3592 {PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset},
3593 // PEER_FLAG_MAX_PREFIX
3594 // PEER_FLAG_MAX_PREFIX_WARNING
3595 {PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out},
3596 {PEER_FLAG_FORCE_NEXTHOP_SELF, 1, peer_change_reset_out},
3597 {PEER_FLAG_REMOVE_PRIVATE_AS_ALL, 1, peer_change_reset_out},
3598 {PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE, 1, peer_change_reset_out},
3599 {PEER_FLAG_AS_OVERRIDE, 1, peer_change_reset_out},
3600 {PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE, 1, peer_change_reset_out},
3601 {PEER_FLAG_ADDPATH_TX_ALL_PATHS, 1, peer_change_reset},
3602 {PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS, 1, peer_change_reset},
3603 {PEER_FLAG_WEIGHT, 0, peer_change_reset_in},
3604 {0, 0, 0}};
3605
3606/* Proper action set. */
3607static int peer_flag_action_set(const struct peer_flag_action *action_list,
3608 int size, struct peer_flag_action *action,
3609 u_int32_t flag)
3610{
3611 int i;
3612 int found = 0;
3613 int reset_in = 0;
3614 int reset_out = 0;
3615 const struct peer_flag_action *match = NULL;
3616
3617 /* Check peer's frag action. */
3618 for (i = 0; i < size; i++) {
3619 match = &action_list[i];
3620
3621 if (match->flag == 0)
3622 break;
3623
3624 if (match->flag & flag) {
3625 found = 1;
3626
3627 if (match->type == peer_change_reset_in)
3628 reset_in = 1;
3629 if (match->type == peer_change_reset_out)
3630 reset_out = 1;
3631 if (match->type == peer_change_reset) {
3632 reset_in = 1;
3633 reset_out = 1;
3634 }
3635 if (match->not_for_member)
3636 action->not_for_member = 1;
3637 }
3638 }
3639
3640 /* Set peer clear type. */
3641 if (reset_in && reset_out)
3642 action->type = peer_change_reset;
3643 else if (reset_in)
3644 action->type = peer_change_reset_in;
3645 else if (reset_out)
3646 action->type = peer_change_reset_out;
3647 else
3648 action->type = peer_change_none;
3649
3650 return found;
3651}
3652
3653static void peer_flag_modify_action(struct peer *peer, u_int32_t flag)
3654{
3655 if (flag == PEER_FLAG_SHUTDOWN) {
3656 if (CHECK_FLAG(peer->flags, flag)) {
3657 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT))
3658 peer_nsf_stop(peer);
3659
3660 UNSET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3661 if (peer->t_pmax_restart) {
3662 BGP_TIMER_OFF(peer->t_pmax_restart);
3663 if (bgp_debug_neighbor_events(peer))
3664 zlog_debug(
3665 "%s Maximum-prefix restart timer canceled",
3666 peer->host);
3667 }
3668
3669 if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT))
3670 peer_nsf_stop(peer);
3671
3672 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
3673 char *msg = peer->tx_shutdown_message;
3674 size_t msglen;
3675
3676 if (!msg && peer_group_active(peer))
3677 msg = peer->group->conf
3678 ->tx_shutdown_message;
3679 msglen = msg ? strlen(msg) : 0;
3680 if (msglen > 128)
3681 msglen = 128;
3682
3683 if (msglen) {
3684 u_char msgbuf[129];
3685
3686 msgbuf[0] = msglen;
3687 memcpy(msgbuf + 1, msg, msglen);
3688
3689 bgp_notify_send_with_data(
3690 peer, BGP_NOTIFY_CEASE,
3691 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN,
3692 msgbuf, msglen + 1);
3693 } else
3694 bgp_notify_send(
3695 peer, BGP_NOTIFY_CEASE,
3696 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
3697 } else
3698 bgp_session_reset(peer);
3699 } else {
3700 peer->v_start = BGP_INIT_START_TIMER;
3701 BGP_EVENT_ADD(peer, BGP_Stop);
3702 }
3703 } else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
3704 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
3705 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
3706 else if (flag == PEER_FLAG_PASSIVE)
3707 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
3708 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
3709 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
3710
3711 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
3712 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3713 } else
3714 bgp_session_reset(peer);
3715}
3716
3717/* Change specified peer flag. */
3718static int peer_flag_modify(struct peer *peer, u_int32_t flag, int set)
3719{
3720 int found;
3721 int size;
3722 struct peer_group *group;
3723 struct peer *tmp_peer;
3724 struct listnode *node, *nnode;
3725 struct peer_flag_action action;
3726
3727 memset(&action, 0, sizeof(struct peer_flag_action));
3728 size = sizeof peer_flag_action_list / sizeof(struct peer_flag_action);
3729
3730 found = peer_flag_action_set(peer_flag_action_list, size, &action,
3731 flag);
3732
3733 /* No flag action is found. */
3734 if (!found)
3735 return BGP_ERR_INVALID_FLAG;
3736
3737 /* When unset the peer-group member's flag we have to check
3738 peer-group configuration. */
3739 if (!set && peer_group_active(peer))
3740 if (CHECK_FLAG(peer->group->conf->flags, flag)) {
3741 if (flag == PEER_FLAG_SHUTDOWN)
3742 return BGP_ERR_PEER_GROUP_SHUTDOWN;
3743 }
3744
3745 /* Flag conflict check. */
3746 if (set && CHECK_FLAG(peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
3747 && CHECK_FLAG(peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
3748 return BGP_ERR_PEER_FLAG_CONFLICT;
3749
3750 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
3751 if (set && CHECK_FLAG(peer->flags, flag) == flag)
3752 return 0;
3753 if (!set && !CHECK_FLAG(peer->flags, flag))
3754 return 0;
3755 }
3756
3757 if (set)
3758 SET_FLAG(peer->flags, flag);
3759 else
3760 UNSET_FLAG(peer->flags, flag);
3761
3762 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
3763 if (action.type == peer_change_reset)
3764 peer_flag_modify_action(peer, flag);
3765
3766 return 0;
3767 }
3768
3769 /* peer-group member updates. */
3770 group = peer->group;
3771
3772 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, tmp_peer)) {
3773
3774 if (set && CHECK_FLAG(tmp_peer->flags, flag) == flag)
3775 continue;
3776
3777 if (!set && !CHECK_FLAG(tmp_peer->flags, flag))
3778 continue;
3779
3780 if (set)
3781 SET_FLAG(tmp_peer->flags, flag);
3782 else
3783 UNSET_FLAG(tmp_peer->flags, flag);
3784
3785 if (action.type == peer_change_reset)
3786 peer_flag_modify_action(tmp_peer, flag);
3787 }
3788 return 0;
3789}
3790
3791int peer_flag_set(struct peer *peer, u_int32_t flag)
3792{
3793 return peer_flag_modify(peer, flag, 1);
3794}
3795
3796int peer_flag_unset(struct peer *peer, u_int32_t flag)
3797{
3798 return peer_flag_modify(peer, flag, 0);
3799}
3800
3801static int peer_af_flag_modify(struct peer *peer, afi_t afi, safi_t safi,
3802 u_int32_t flag, int set)
3803{
3804 int found;
3805 int size;
3806 struct listnode *node, *nnode;
3807 struct peer_group *group;
3808 struct peer_flag_action action;
3809 struct peer *tmp_peer;
3810 struct bgp *bgp;
3811 int addpath_tx_used;
3812
3813 memset(&action, 0, sizeof(struct peer_flag_action));
3814 size = sizeof peer_af_flag_action_list
3815 / sizeof(struct peer_flag_action);
3816
3817 found = peer_flag_action_set(peer_af_flag_action_list, size, &action,
3818 flag);
3819
3820 /* No flag action is found. */
3821 if (!found)
3822 return BGP_ERR_INVALID_FLAG;
3823
3824 /* Special check for reflector client. */
3825 if (flag & PEER_FLAG_REFLECTOR_CLIENT
3826 && peer_sort(peer) != BGP_PEER_IBGP)
3827 return BGP_ERR_NOT_INTERNAL_PEER;
3828
3829 /* Special check for remove-private-AS. */
3830 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
3831 && peer_sort(peer) == BGP_PEER_IBGP)
3832 return BGP_ERR_REMOVE_PRIVATE_AS;
3833
3834 /* as-override is not allowed for IBGP peers */
3835 if (flag & PEER_FLAG_AS_OVERRIDE && peer_sort(peer) == BGP_PEER_IBGP)
3836 return BGP_ERR_AS_OVERRIDE;
3837
3838 /* When current flag configuration is same as requested one. */
3839 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
3840 if (set && CHECK_FLAG(peer->af_flags[afi][safi], flag) == flag)
3841 return 0;
3842 if (!set && !CHECK_FLAG(peer->af_flags[afi][safi], flag))
3843 return 0;
3844 }
3845
3846 if (set)
3847 SET_FLAG(peer->af_flags[afi][safi], flag);
3848 else
3849 UNSET_FLAG(peer->af_flags[afi][safi], flag);
3850
3851 /* Execute action when peer is established. */
3852 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)
3853 && peer->status == Established) {
3854 if (!set && flag == PEER_FLAG_SOFT_RECONFIG)
3855 bgp_clear_adj_in(peer, afi, safi);
3856 else {
3857 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
3858 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
3859 else if (flag == PEER_FLAG_RSERVER_CLIENT)
3860 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
3861 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
3862 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
3863 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
3864 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
3865
3866 peer_change_action(peer, afi, safi, action.type);
3867 }
3868 }
3869
3870 /* Peer group member updates. */
3871 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
3872 group = peer->group;
3873
3874 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, tmp_peer)) {
3875 if (set
3876 && CHECK_FLAG(tmp_peer->af_flags[afi][safi], flag)
3877 == flag)
3878 continue;
3879
3880 if (!set
3881 && !CHECK_FLAG(tmp_peer->af_flags[afi][safi], flag))
3882 continue;
3883
3884 if (set)
3885 SET_FLAG(tmp_peer->af_flags[afi][safi], flag);
3886 else
3887 UNSET_FLAG(tmp_peer->af_flags[afi][safi], flag);
3888
3889 if (tmp_peer->status == Established) {
3890 if (!set && flag == PEER_FLAG_SOFT_RECONFIG)
3891 bgp_clear_adj_in(tmp_peer, afi, safi);
3892 else {
3893 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
3894 tmp_peer->last_reset =
3895 PEER_DOWN_RR_CLIENT_CHANGE;
3896 else if (flag
3897 == PEER_FLAG_RSERVER_CLIENT)
3898 tmp_peer->last_reset =
3899 PEER_DOWN_RS_CLIENT_CHANGE;
3900 else if (flag
3901 == PEER_FLAG_ORF_PREFIX_SM)
3902 tmp_peer->last_reset =
3903 PEER_DOWN_CAPABILITY_CHANGE;
3904 else if (flag
3905 == PEER_FLAG_ORF_PREFIX_RM)
3906 tmp_peer->last_reset =
3907 PEER_DOWN_CAPABILITY_CHANGE;
3908
3909 peer_change_action(tmp_peer, afi, safi,
3910 action.type);
3911 }
3912 }
3913 }
3914 }
3915
3916 /* Track if addpath TX is in use */
9d303b37
DL
3917 if (flag & (PEER_FLAG_ADDPATH_TX_ALL_PATHS
3918 | PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) {
d62a17ae 3919 bgp = peer->bgp;
3920 addpath_tx_used = 0;
3921
3922 if (set) {
3923 addpath_tx_used = 1;
3924
3925 if (flag & PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS) {
3926 if (!bgp_flag_check(
3927 bgp, BGP_FLAG_DETERMINISTIC_MED)) {
3928 zlog_warn(
3929 "%s: enabling bgp deterministic-med, this is required"
3930 " for addpath-tx-bestpath-per-AS",
3931 peer->host);
3932 bgp_flag_set(
3933 bgp,
3934 BGP_FLAG_DETERMINISTIC_MED);
3935 bgp_recalculate_all_bestpaths(bgp);
3936 }
3937 }
3938 } else {
3939 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode,
3940 tmp_peer)) {
3941 if (CHECK_FLAG(tmp_peer->af_flags[afi][safi],
3942 PEER_FLAG_ADDPATH_TX_ALL_PATHS)
3943 || CHECK_FLAG(
3944 tmp_peer->af_flags[afi][safi],
3945 PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) {
3946 addpath_tx_used = 1;
3947 break;
3948 }
3949 }
3950 }
3951
3952 bgp->addpath_tx_used[afi][safi] = addpath_tx_used;
3953 }
3954
3955 return 0;
3956}
3957
3958int peer_af_flag_set(struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
3959{
3960 return peer_af_flag_modify(peer, afi, safi, flag, 1);
3961}
3962
3963int peer_af_flag_unset(struct peer *peer, afi_t afi, safi_t safi,
3964 u_int32_t flag)
3965{
3966 return peer_af_flag_modify(peer, afi, safi, flag, 0);
3967}
3968
3969
3970int peer_tx_shutdown_message_set(struct peer *peer, const char *msg)
3971{
3972 XFREE(MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message);
3973 peer->tx_shutdown_message =
3974 msg ? XSTRDUP(MTYPE_PEER_TX_SHUTDOWN_MSG, msg) : NULL;
3975 return 0;
3976}
3977
3978int peer_tx_shutdown_message_unset(struct peer *peer)
3979{
3980 XFREE(MTYPE_PEER_TX_SHUTDOWN_MSG, peer->tx_shutdown_message);
3981 return 0;
3982}
3983
3984
3985/* EBGP multihop configuration. */
3986int peer_ebgp_multihop_set(struct peer *peer, int ttl)
3987{
3988 struct peer_group *group;
3989 struct listnode *node, *nnode;
3990 struct peer *peer1;
3991
3992 if (peer->sort == BGP_PEER_IBGP || peer->conf_if)
3993 return 0;
3994
3995 /* see comment in peer_ttl_security_hops_set() */
3996 if (ttl != MAXTTL) {
3997 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
3998 group = peer->group;
3999 if (group->conf->gtsm_hops != 0)
4000 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4001
4002 for (ALL_LIST_ELEMENTS(group->peer, node, nnode,
4003 peer1)) {
4004 if (peer1->sort == BGP_PEER_IBGP)
4005 continue;
4006
4007 if (peer1->gtsm_hops != 0)
4008 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4009 }
4010 } else {
4011 if (peer->gtsm_hops != 0)
4012 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4013 }
4014 }
4015
4016 peer->ttl = ttl;
4017
4018 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4019 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP) {
4020 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4021 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4022 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4023 else
4024 bgp_session_reset(peer);
4025 }
4026 } else {
4027 group = peer->group;
4028 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4029 if (peer->sort == BGP_PEER_IBGP)
4030 continue;
4031
4032 peer->ttl = group->conf->ttl;
4033
4034 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4035 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4036 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4037 else
4038 bgp_session_reset(peer);
4039 }
4040 }
4041 return 0;
4042}
4043
4044int peer_ebgp_multihop_unset(struct peer *peer)
4045{
4046 struct peer_group *group;
4047 struct listnode *node, *nnode;
4048
4049 if (peer->sort == BGP_PEER_IBGP)
4050 return 0;
4051
4052 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
4053 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4054
4055 if (peer_group_active(peer))
4056 peer->ttl = peer->group->conf->ttl;
4057 else
4058 peer->ttl = 1;
4059
4060 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4061 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4062 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4063 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4064 else
4065 bgp_session_reset(peer);
4066 } else {
4067 group = peer->group;
4068 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4069 if (peer->sort == BGP_PEER_IBGP)
4070 continue;
4071
4072 peer->ttl = 1;
4073
4074 if (peer->fd >= 0) {
4075 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4076 bgp_notify_send(
4077 peer, BGP_NOTIFY_CEASE,
4078 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4079 else
4080 bgp_session_reset(peer);
4081 }
4082 }
4083 }
4084 return 0;
4085}
4086
4087/* Neighbor description. */
4088int peer_description_set(struct peer *peer, const char *desc)
4089{
4090 if (peer->desc)
4091 XFREE(MTYPE_PEER_DESC, peer->desc);
4092
4093 peer->desc = XSTRDUP(MTYPE_PEER_DESC, desc);
4094
4095 return 0;
4096}
4097
4098int peer_description_unset(struct peer *peer)
4099{
4100 if (peer->desc)
4101 XFREE(MTYPE_PEER_DESC, peer->desc);
4102
4103 peer->desc = NULL;
4104
4105 return 0;
4106}
4107
4108/* Neighbor update-source. */
4109int peer_update_source_if_set(struct peer *peer, const char *ifname)
4110{
4111 struct peer_group *group;
4112 struct listnode *node, *nnode;
4113
4114 if (peer->update_if) {
4115 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)
4116 && strcmp(peer->update_if, ifname) == 0)
4117 return 0;
4118
4119 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
4120 peer->update_if = NULL;
4121 }
4122
4123 if (peer->update_source) {
4124 sockunion_free(peer->update_source);
4125 peer->update_source = NULL;
4126 }
4127
4128 peer->update_if = XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, ifname);
4129
4130 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4131 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
4132 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4133 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4134 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4135 } else
4136 bgp_session_reset(peer);
4137 return 0;
4138 }
4139
4140 /* peer-group member updates. */
4141 group = peer->group;
4142 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4143 if (peer->update_if) {
4144 if (strcmp(peer->update_if, ifname) == 0)
4145 continue;
4146
4147 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
4148 peer->update_if = NULL;
4149 }
4150
4151 if (peer->update_source) {
4152 sockunion_free(peer->update_source);
4153 peer->update_source = NULL;
4154 }
4155
4156 peer->update_if = XSTRDUP(MTYPE_PEER_UPDATE_SOURCE, ifname);
4157
4158 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
4159 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4160 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4161 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4162 } else
4163 bgp_session_reset(peer);
4164 }
4165 return 0;
4166}
4167
4168int peer_update_source_addr_set(struct peer *peer, const union sockunion *su)
4169{
4170 struct peer_group *group;
4171 struct listnode *node, *nnode;
4172
4173 if (peer->update_source) {
4174 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)
4175 && sockunion_cmp(peer->update_source, su) == 0)
4176 return 0;
4177 sockunion_free(peer->update_source);
4178 peer->update_source = NULL;
4179 }
4180
4181 if (peer->update_if) {
4182 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
4183 peer->update_if = NULL;
4184 }
4185
4186 peer->update_source = sockunion_dup(su);
4187
4188 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4189 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
4190 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4191 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4192 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4193 } else
4194 bgp_session_reset(peer);
4195 return 0;
4196 }
4197
4198 /* peer-group member updates. */
4199 group = peer->group;
4200 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4201 if (peer->update_source) {
4202 if (sockunion_cmp(peer->update_source, su) == 0)
4203 continue;
4204 sockunion_free(peer->update_source);
4205 peer->update_source = NULL;
4206 }
4207
4208 if (peer->update_if) {
4209 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
4210 peer->update_if = NULL;
4211 }
4212
4213 peer->update_source = sockunion_dup(su);
4214
4215 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
4216 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4217 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4218 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4219 } else
4220 bgp_session_reset(peer);
4221 }
4222 return 0;
4223}
4224
4225int peer_update_source_unset(struct peer *peer)
4226{
4227 union sockunion *su;
4228 struct peer_group *group;
4229 struct listnode *node, *nnode;
4230
4231 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP) && !peer->update_source
4232 && !peer->update_if)
4233 return 0;
4234
4235 if (peer->update_source) {
4236 sockunion_free(peer->update_source);
4237 peer->update_source = NULL;
4238 }
4239 if (peer->update_if) {
4240 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
4241 peer->update_if = NULL;
4242 }
4243
4244 if (peer_group_active(peer)) {
4245 group = peer->group;
4246
4247 if (group->conf->update_source) {
4248 su = sockunion_dup(group->conf->update_source);
4249 peer->update_source = su;
4250 } else if (group->conf->update_if)
4251 peer->update_if = XSTRDUP(MTYPE_PEER_UPDATE_SOURCE,
4252 group->conf->update_if);
4253 }
4254
4255 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4256 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
4257 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4258 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4259 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4260 } else
4261 bgp_session_reset(peer);
4262 return 0;
4263 }
4264
4265 /* peer-group member updates. */
4266 group = peer->group;
4267 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4268 if (!peer->update_source && !peer->update_if)
4269 continue;
4270
4271 if (peer->update_source) {
4272 sockunion_free(peer->update_source);
4273 peer->update_source = NULL;
4274 }
4275
4276 if (peer->update_if) {
4277 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
4278 peer->update_if = NULL;
4279 }
4280
4281 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
4282 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4283 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4284 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4285 } else
4286 bgp_session_reset(peer);
4287 }
4288 return 0;
4289}
4290
4291int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi,
4292 const char *rmap)
4293{
4294 struct peer_group *group;
4295 struct listnode *node, *nnode;
4296
4297 if (!CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
4298 || (rmap && !peer->default_rmap[afi][safi].name)
4299 || (rmap
4300 && strcmp(rmap, peer->default_rmap[afi][safi].name) != 0)) {
4301 SET_FLAG(peer->af_flags[afi][safi],
4302 PEER_FLAG_DEFAULT_ORIGINATE);
4303
4304 if (rmap) {
4305 if (peer->default_rmap[afi][safi].name)
4306 XFREE(MTYPE_ROUTE_MAP_NAME,
4307 peer->default_rmap[afi][safi].name);
4308 peer->default_rmap[afi][safi].name =
4309 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
4310 peer->default_rmap[afi][safi].map =
4311 route_map_lookup_by_name(rmap);
4312 }
4313 }
4314
4315 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4316 if (peer->status == Established && peer->afc_nego[afi][safi]) {
4317 update_group_adjust_peer(peer_af_find(peer, afi, safi));
4318 bgp_default_originate(peer, afi, safi, 0);
4319 bgp_announce_route(peer, afi, safi);
4320 }
4321 return 0;
4322 }
4323
4324 /* peer-group member updates. */
4325 group = peer->group;
4326 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4327 SET_FLAG(peer->af_flags[afi][safi],
4328 PEER_FLAG_DEFAULT_ORIGINATE);
4329
4330 if (rmap) {
4331 if (peer->default_rmap[afi][safi].name)
4332 XFREE(MTYPE_ROUTE_MAP_NAME,
4333 peer->default_rmap[afi][safi].name);
4334 peer->default_rmap[afi][safi].name =
4335 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
4336 peer->default_rmap[afi][safi].map =
4337 route_map_lookup_by_name(rmap);
4338 }
4339
4340 if (peer->status == Established && peer->afc_nego[afi][safi]) {
4341 update_group_adjust_peer(peer_af_find(peer, afi, safi));
4342 bgp_default_originate(peer, afi, safi, 0);
4343 bgp_announce_route(peer, afi, safi);
4344 }
4345 }
4346 return 0;
4347}
4348
4349int peer_default_originate_unset(struct peer *peer, afi_t afi, safi_t safi)
4350{
4351 struct peer_group *group;
4352 struct listnode *node, *nnode;
4353
4354 if (CHECK_FLAG(peer->af_flags[afi][safi],
4355 PEER_FLAG_DEFAULT_ORIGINATE)) {
4356 UNSET_FLAG(peer->af_flags[afi][safi],
4357 PEER_FLAG_DEFAULT_ORIGINATE);
4358
4359 if (peer->default_rmap[afi][safi].name)
4360 XFREE(MTYPE_ROUTE_MAP_NAME,
4361 peer->default_rmap[afi][safi].name);
4362 peer->default_rmap[afi][safi].name = NULL;
4363 peer->default_rmap[afi][safi].map = NULL;
4364 }
4365
4366 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4367 if (peer->status == Established && peer->afc_nego[afi][safi]) {
4368 update_group_adjust_peer(peer_af_find(peer, afi, safi));
4369 bgp_default_originate(peer, afi, safi, 1);
4370 bgp_announce_route(peer, afi, safi);
4371 }
4372 return 0;
4373 }
4374
4375 /* peer-group member updates. */
4376 group = peer->group;
4377 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4378 UNSET_FLAG(peer->af_flags[afi][safi],
4379 PEER_FLAG_DEFAULT_ORIGINATE);
4380
4381 if (peer->default_rmap[afi][safi].name)
4382 XFREE(MTYPE_ROUTE_MAP_NAME,
4383 peer->default_rmap[afi][safi].name);
4384 peer->default_rmap[afi][safi].name = NULL;
4385 peer->default_rmap[afi][safi].map = NULL;
4386
4387 if (peer->status == Established && peer->afc_nego[afi][safi]) {
4388 update_group_adjust_peer(peer_af_find(peer, afi, safi));
4389 bgp_default_originate(peer, afi, safi, 1);
4390 bgp_announce_route(peer, afi, safi);
4391 }
4392 }
4393 return 0;
4394}
4395
4396int peer_port_set(struct peer *peer, u_int16_t port)
4397{
4398 peer->port = port;
4399 return 0;
4400}
4401
4402int peer_port_unset(struct peer *peer)
4403{
4404 peer->port = BGP_PORT_DEFAULT;
4405 return 0;
4406}
4407
4408/*
4409 * Helper function that is called after the name of the policy
4410 * being used by a peer has changed (AF specific). Automatically
4411 * initiates inbound or outbound processing as needed.
4412 */
4413static void peer_on_policy_change(struct peer *peer, afi_t afi, safi_t safi,
4414 int outbound)
4415{
4416 if (outbound) {
4417 update_group_adjust_peer(peer_af_find(peer, afi, safi));
4418 if (peer->status == Established)
4419 bgp_announce_route(peer, afi, safi);
4420 } else {
4421 if (peer->status != Established)
4422 return;
4423
4424 if (CHECK_FLAG(peer->af_flags[afi][safi],
4425 PEER_FLAG_SOFT_RECONFIG))
4426 bgp_soft_reconfig_in(peer, afi, safi);
4427 else if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4428 || CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4429 bgp_route_refresh_send(peer, afi, safi, 0, 0, 0);
4430 }
4431}
4432
4433
4434/* neighbor weight. */
4435int peer_weight_set(struct peer *peer, afi_t afi, safi_t safi, u_int16_t weight)
4436{
4437 struct peer_group *group;
4438 struct listnode *node, *nnode;
4439
4440 if (peer->weight[afi][safi] != weight) {
4441 peer->weight[afi][safi] = weight;
4442 SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_WEIGHT);
4443 peer_on_policy_change(peer, afi, safi, 0);
4444 }
4445
4446 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4447 return 0;
4448
4449 /* peer-group member updates. */
4450 group = peer->group;
4451 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4452 if (peer->weight[afi][safi] != weight) {
4453 peer->weight[afi][safi] = weight;
4454 SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_WEIGHT);
4455 peer_on_policy_change(peer, afi, safi, 0);
4456 }
4457 }
4458 return 0;
4459}
4460
4461int peer_weight_unset(struct peer *peer, afi_t afi, safi_t safi)
4462{
4463 struct peer_group *group;
4464 struct listnode *node, *nnode;
4465
4466 /* not the peer-group itself but a peer in a peer-group */
4467 if (peer_group_active(peer)) {
4468 group = peer->group;
4469
4470 /* inherit weight from the peer-group */
4471 if (CHECK_FLAG(group->conf->af_flags[afi][safi],
4472 PEER_FLAG_WEIGHT)) {
4473 peer->weight[afi][safi] =
4474 group->conf->weight[afi][safi];
4475 peer_af_flag_set(peer, afi, safi, PEER_FLAG_WEIGHT);
4476 peer_on_policy_change(peer, afi, safi, 0);
4477 } else {
4478 if (CHECK_FLAG(peer->af_flags[afi][safi],
4479 PEER_FLAG_WEIGHT)) {
4480 peer->weight[afi][safi] = 0;
4481 peer_af_flag_unset(peer, afi, safi,
4482 PEER_FLAG_WEIGHT);
4483 peer_on_policy_change(peer, afi, safi, 0);
4484 }
4485 }
4486 }
4487
4488 else {
4489 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_WEIGHT)) {
4490 peer->weight[afi][safi] = 0;
4491 peer_af_flag_unset(peer, afi, safi, PEER_FLAG_WEIGHT);
4492 peer_on_policy_change(peer, afi, safi, 0);
4493 }
4494
4495 /* peer-group member updates. */
4496 group = peer->group;
4497
4498 if (group) {
4499 for (ALL_LIST_ELEMENTS(group->peer, node, nnode,
4500 peer)) {
4501 if (CHECK_FLAG(peer->af_flags[afi][safi],
4502 PEER_FLAG_WEIGHT)) {
4503 peer->weight[afi][safi] = 0;
4504 peer_af_flag_unset(peer, afi, safi,
4505 PEER_FLAG_WEIGHT);
4506 peer_on_policy_change(peer, afi, safi,
4507 0);
4508 }
4509 }
4510 }
4511 }
4512 return 0;
4513}
4514
4515int peer_timers_set(struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
4516{
4517 struct peer_group *group;
4518 struct listnode *node, *nnode;
4519
4520 /* keepalive value check. */
4521 if (keepalive > 65535)
4522 return BGP_ERR_INVALID_VALUE;
4523
4524 /* Holdtime value check. */
4525 if (holdtime > 65535)
4526 return BGP_ERR_INVALID_VALUE;
4527
4528 /* Holdtime value must be either 0 or greater than 3. */
4529 if (holdtime < 3 && holdtime != 0)
4530 return BGP_ERR_INVALID_VALUE;
4531
4532 /* Set value to the configuration. */
4533 SET_FLAG(peer->config, PEER_CONFIG_TIMER);
4534 peer->holdtime = holdtime;
4535 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
4536
4537 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4538 return 0;
4539
4540 /* peer-group member updates. */
4541 group = peer->group;
4542 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4543 SET_FLAG(peer->config, PEER_CONFIG_TIMER);
4544 peer->holdtime = group->conf->holdtime;
4545 peer->keepalive = group->conf->keepalive;
4546 }
4547 return 0;
4548}
4549
4550int peer_timers_unset(struct peer *peer)
4551{
4552 struct peer_group *group;
4553 struct listnode *node, *nnode;
4554
4555 /* Clear configuration. */
4556 UNSET_FLAG(peer->config, PEER_CONFIG_TIMER);
4557 peer->keepalive = 0;
4558 peer->holdtime = 0;
4559
4560 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4561 return 0;
4562
4563 /* peer-group member updates. */
4564 group = peer->group;
4565 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4566 UNSET_FLAG(peer->config, PEER_CONFIG_TIMER);
4567 peer->holdtime = 0;
4568 peer->keepalive = 0;
4569 }
4570
4571 return 0;
4572}
4573
4574int peer_timers_connect_set(struct peer *peer, u_int32_t connect)
4575{
4576 struct peer_group *group;
4577 struct listnode *node, *nnode;
4578
4579 if (connect > 65535)
4580 return BGP_ERR_INVALID_VALUE;
4581
4582 /* Set value to the configuration. */
4583 SET_FLAG(peer->config, PEER_CONFIG_CONNECT);
4584 peer->connect = connect;
4585
4586 /* Set value to timer setting. */
4587 peer->v_connect = connect;
4588
4589 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4590 return 0;
4591
4592 /* peer-group member updates. */
4593 group = peer->group;
4594 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4595 SET_FLAG(peer->config, PEER_CONFIG_CONNECT);
4596 peer->connect = connect;
4597 peer->v_connect = connect;
4598 }
4599 return 0;
4600}
4601
4602int peer_timers_connect_unset(struct peer *peer)
4603{
4604 struct peer_group *group;
4605 struct listnode *node, *nnode;
4606
4607 /* Clear configuration. */
4608 UNSET_FLAG(peer->config, PEER_CONFIG_CONNECT);
4609 peer->connect = 0;
4610
4611 /* Set timer setting to default value. */
4612 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
4613
4614 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4615 return 0;
4616
4617 /* peer-group member updates. */
4618 group = peer->group;
4619 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4620 UNSET_FLAG(peer->config, PEER_CONFIG_CONNECT);
4621 peer->connect = 0;
4622 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
4623 }
4624 return 0;
4625}
4626
4627int peer_advertise_interval_set(struct peer *peer, u_int32_t routeadv)
4628{
4629 struct peer_group *group;
4630 struct listnode *node, *nnode;
4631
4632 if (routeadv > 600)
4633 return BGP_ERR_INVALID_VALUE;
4634
4635 SET_FLAG(peer->config, PEER_CONFIG_ROUTEADV);
4636 peer->routeadv = routeadv;
4637 peer->v_routeadv = routeadv;
4638
4639 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4640 update_group_adjust_peer_afs(peer);
4641 if (peer->status == Established)
4642 bgp_announce_route_all(peer);
4643 return 0;
4644 }
4645
4646 /* peer-group member updates. */
4647 group = peer->group;
4648 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4649 SET_FLAG(peer->config, PEER_CONFIG_ROUTEADV);
4650 peer->routeadv = routeadv;
4651 peer->v_routeadv = routeadv;
4652 update_group_adjust_peer_afs(peer);
4653 if (peer->status == Established)
4654 bgp_announce_route_all(peer);
4655 }
4656
4657 return 0;
4658}
4659
4660int peer_advertise_interval_unset(struct peer *peer)
4661{
4662 struct peer_group *group;
4663 struct listnode *node, *nnode;
4664
4665 UNSET_FLAG(peer->config, PEER_CONFIG_ROUTEADV);
4666 peer->routeadv = 0;
4667
4668 if (peer->sort == BGP_PEER_IBGP)
4669 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
4670 else
4671 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
4672
4673 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4674 update_group_adjust_peer_afs(peer);
4675 if (peer->status == Established)
4676 bgp_announce_route_all(peer);
4677 return 0;
4678 }
4679
4680 /* peer-group member updates. */
4681 group = peer->group;
4682 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4683 UNSET_FLAG(peer->config, PEER_CONFIG_ROUTEADV);
4684 peer->routeadv = 0;
4685
4686 if (peer->sort == BGP_PEER_IBGP)
4687 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
4688 else
4689 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
4690
4691 update_group_adjust_peer_afs(peer);
4692 if (peer->status == Established)
4693 bgp_announce_route_all(peer);
4694 }
4695
4696 return 0;
4697}
4698
4699/* neighbor interface */
4700void peer_interface_set(struct peer *peer, const char *str)
4701{
4702 if (peer->ifname)
4703 XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
4704 peer->ifname = XSTRDUP(MTYPE_BGP_PEER_IFNAME, str);
4705}
4706
4707void peer_interface_unset(struct peer *peer)
4708{
4709 if (peer->ifname)
4710 XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
4711 peer->ifname = NULL;
4712}
4713
4714/* Allow-as in. */
4715int peer_allowas_in_set(struct peer *peer, afi_t afi, safi_t safi,
4716 int allow_num, int origin)
4717{
4718 struct peer_group *group;
4719 struct listnode *node, *nnode;
4720
4721 if (origin) {
4722 if (peer->allowas_in[afi][safi]
4723 || CHECK_FLAG(peer->af_flags[afi][safi],
4724 PEER_FLAG_ALLOWAS_IN)
4725 || !CHECK_FLAG(peer->af_flags[afi][safi],
4726 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
4727 peer->allowas_in[afi][safi] = 0;
4728 peer_af_flag_unset(peer, afi, safi,
4729 PEER_FLAG_ALLOWAS_IN);
4730 peer_af_flag_set(peer, afi, safi,
4731 PEER_FLAG_ALLOWAS_IN_ORIGIN);
4732 peer_on_policy_change(peer, afi, safi, 0);
4733 }
4734
4735 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4736 return 0;
4737
4738 group = peer->group;
4739 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4740 if (peer->allowas_in[afi][safi]
4741 || CHECK_FLAG(peer->af_flags[afi][safi],
4742 PEER_FLAG_ALLOWAS_IN)
4743 || !CHECK_FLAG(peer->af_flags[afi][safi],
4744 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
4745 peer->allowas_in[afi][safi] = 0;
4746 peer_af_flag_unset(peer, afi, safi,
4747 PEER_FLAG_ALLOWAS_IN);
4748 peer_af_flag_set(peer, afi, safi,
4749 PEER_FLAG_ALLOWAS_IN_ORIGIN);
4750 peer_on_policy_change(peer, afi, safi, 0);
4751 }
4752 }
4753 } else {
4754 if (allow_num < 1 || allow_num > 10)
4755 return BGP_ERR_INVALID_VALUE;
4756
4757 if (peer->allowas_in[afi][safi] != allow_num
4758 || CHECK_FLAG(peer->af_flags[afi][safi],
4759 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
4760 peer->allowas_in[afi][safi] = allow_num;
4761 peer_af_flag_set(peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
4762 peer_af_flag_unset(peer, afi, safi,
4763 PEER_FLAG_ALLOWAS_IN_ORIGIN);
4764 peer_on_policy_change(peer, afi, safi, 0);
4765 }
4766
4767 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4768 return 0;
4769
4770 group = peer->group;
4771 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4772 if (peer->allowas_in[afi][safi] != allow_num
4773 || CHECK_FLAG(peer->af_flags[afi][safi],
4774 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
4775 peer->allowas_in[afi][safi] = allow_num;
4776 peer_af_flag_set(peer, afi, safi,
4777 PEER_FLAG_ALLOWAS_IN);
4778 peer_af_flag_unset(peer, afi, safi,
4779 PEER_FLAG_ALLOWAS_IN_ORIGIN);
4780 peer_on_policy_change(peer, afi, safi, 0);
4781 }
4782 }
4783 }
4784
4785 return 0;
4786}
4787
4788int peer_allowas_in_unset(struct peer *peer, afi_t afi, safi_t safi)
4789{
4790 struct peer_group *group;
4791 struct peer *tmp_peer;
4792 struct listnode *node, *nnode;
4793
4794 /* If this is a peer-group we must first clear the flags for all of the
4795 * peer-group members
4796 */
4797 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4798 group = peer->group;
4799 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, tmp_peer)) {
4800 if (CHECK_FLAG(tmp_peer->af_flags[afi][safi],
4801 PEER_FLAG_ALLOWAS_IN)
4802 || CHECK_FLAG(tmp_peer->af_flags[afi][safi],
4803 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
4804 tmp_peer->allowas_in[afi][safi] = 0;
4805 peer_af_flag_unset(tmp_peer, afi, safi,
4806 PEER_FLAG_ALLOWAS_IN);
4807 peer_af_flag_unset(tmp_peer, afi, safi,
4808 PEER_FLAG_ALLOWAS_IN_ORIGIN);
4809 peer_on_policy_change(tmp_peer, afi, safi, 0);
4810 }
4811 }
4812 }
4813
4814 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN)
4815 || CHECK_FLAG(peer->af_flags[afi][safi],
4816 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
4817 peer->allowas_in[afi][safi] = 0;
4818 peer_af_flag_unset(peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
4819 peer_af_flag_unset(peer, afi, safi,
4820 PEER_FLAG_ALLOWAS_IN_ORIGIN);
4821 peer_on_policy_change(peer, afi, safi, 0);
4822 }
4823
4824 return 0;
4825}
4826
4827int peer_local_as_set(struct peer *peer, as_t as, int no_prepend,
4828 int replace_as)
4829{
4830 struct bgp *bgp = peer->bgp;
4831 struct peer_group *group;
4832 struct listnode *node, *nnode;
4833
4834 if (peer_sort(peer) != BGP_PEER_EBGP
4835 && peer_sort(peer) != BGP_PEER_INTERNAL)
4836 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
4837
4838 if (bgp->as == as)
4839 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
4840
4841 if (peer->as == as)
4842 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
4843
4844 if (peer->change_local_as == as
4845 && ((CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)
4846 && no_prepend)
4847 || (!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)
4848 && !no_prepend))
4849 && ((CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS)
4850 && replace_as)
4851 || (!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS)
4852 && !replace_as)))
4853 return 0;
4854
4855 peer->change_local_as = as;
4856 if (no_prepend)
4857 SET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4858 else
4859 UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4860
4861 if (replace_as)
4862 SET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4863 else
4864 UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4865
4866 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4867 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
4868 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
4869 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4870 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4871 } else
4872 bgp_session_reset(peer);
4873 return 0;
4874 }
4875
4876 group = peer->group;
4877 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4878 peer->change_local_as = as;
4879 if (no_prepend)
4880 SET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4881 else
4882 UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4883
4884 if (replace_as)
4885 SET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4886 else
4887 UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4888
4889 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
4890 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
4891 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4892 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4893 } else
4894 BGP_EVENT_ADD(peer, BGP_Stop);
4895 }
4896
4897 return 0;
4898}
4899
4900int peer_local_as_unset(struct peer *peer)
4901{
4902 struct peer_group *group;
4903 struct listnode *node, *nnode;
4904
4905 if (!peer->change_local_as)
4906 return 0;
4907
4908 peer->change_local_as = 0;
4909 UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4910 UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4911
4912 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4913 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
4914 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
4915 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4916 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4917 } else
4918 BGP_EVENT_ADD(peer, BGP_Stop);
4919
4920 return 0;
4921 }
4922
4923 group = peer->group;
4924 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
4925 peer->change_local_as = 0;
4926 UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4927 UNSET_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4928
4929 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status)) {
4930 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
4931 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4932 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4933 } else
4934 bgp_session_reset(peer);
4935 }
4936 return 0;
4937}
4938
4939/* Set password for authenticating with the peer. */
4940int peer_password_set(struct peer *peer, const char *password)
4941{
4942 struct listnode *nn, *nnode;
4943 int len = password ? strlen(password) : 0;
4944 int ret = BGP_SUCCESS;
4945
4946 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
4947 return BGP_ERR_INVALID_VALUE;
4948
4949 if (peer->password && strcmp(peer->password, password) == 0
4950 && !CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
4951 return 0;
4952
4953 if (peer->password)
4954 XFREE(MTYPE_PEER_PASSWORD, peer->password);
4955
4956 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
4957
4958 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
4959 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4960 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4961 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4962 else
4963 bgp_session_reset(peer);
4964
4965 if (BGP_PEER_SU_UNSPEC(peer))
4966 return BGP_SUCCESS;
4967
4968 return (bgp_md5_set(peer) >= 0) ? BGP_SUCCESS
4969 : BGP_ERR_TCPSIG_FAILED;
4970 }
4971
4972 for (ALL_LIST_ELEMENTS(peer->group->peer, nn, nnode, peer)) {
4973 if (peer->password && strcmp(peer->password, password) == 0)
4974 continue;
4975
4976 if (peer->password)
4977 XFREE(MTYPE_PEER_PASSWORD, peer->password);
4978
4979 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
4980
4981 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4982 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
4983 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4984 else
4985 bgp_session_reset(peer);
4986
4987 if (!BGP_PEER_SU_UNSPEC(peer)) {
4988 if (bgp_md5_set(peer) < 0)
4989 ret = BGP_ERR_TCPSIG_FAILED;
4990 }
4991 }
4992
4993 return ret;
4994}
4995
4996int peer_password_unset(struct peer *peer)
4997{
4998 struct listnode *nn, *nnode;
4999
5000 if (!peer->password && !CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
5001 return 0;
5002
5003 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5004 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
5005 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
5006 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5007 else
5008 bgp_session_reset(peer);
5009
5010 if (peer->password)
5011 XFREE(MTYPE_PEER_PASSWORD, peer->password);
5012
5013 peer->password = NULL;
5014
5015 if (!BGP_PEER_SU_UNSPEC(peer))
5016 bgp_md5_unset(peer);
5017
5018 return 0;
5019 }
5020
5021 XFREE(MTYPE_PEER_PASSWORD, peer->password);
5022 peer->password = NULL;
5023
5024 for (ALL_LIST_ELEMENTS(peer->group->peer, nn, nnode, peer)) {
5025 if (!peer->password)
5026 continue;
5027
5028 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
5029 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
5030 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5031 else
5032 bgp_session_reset(peer);
5033
5034 XFREE(MTYPE_PEER_PASSWORD, peer->password);
5035 peer->password = NULL;
5036
5037 if (!BGP_PEER_SU_UNSPEC(peer))
5038 bgp_md5_unset(peer);
5039 }
5040
5041 return 0;
5042}
6b0655a2 5043
3f9c7369 5044
718e3744 5045/* Set distribute list to the peer. */
d62a17ae 5046int peer_distribute_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
5047 const char *name)
5048{
5049 struct bgp_filter *filter;
5050 struct peer_group *group;
5051 struct listnode *node, *nnode;
5052
5053 if (direct != FILTER_IN && direct != FILTER_OUT)
5054 return BGP_ERR_INVALID_VALUE;
5055
5056 filter = &peer->filter[afi][safi];
5057
5058 if (filter->plist[direct].name)
5059 return BGP_ERR_PEER_FILTER_CONFLICT;
5060
5061 if (filter->dlist[direct].name)
5062 XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name);
5063 filter->dlist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
5064 filter->dlist[direct].alist = access_list_lookup(afi, name);
5065
5066 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5067 peer_on_policy_change(peer, afi, safi,
5068 (direct == FILTER_OUT) ? 1 : 0);
5069 return 0;
5070 }
5071
5072 group = peer->group;
5073 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5074 filter = &peer->filter[afi][safi];
5075
5076 if (filter->dlist[direct].name)
5077 XFREE(MTYPE_BGP_FILTER_NAME,
5078 filter->dlist[direct].name);
5079 filter->dlist[direct].name =
5080 XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
5081 filter->dlist[direct].alist = access_list_lookup(afi, name);
5082 peer_on_policy_change(peer, afi, safi,
5083 (direct == FILTER_OUT) ? 1 : 0);
5084 }
5085
5086 return 0;
5087}
5088
5089int peer_distribute_unset(struct peer *peer, afi_t afi, safi_t safi, int direct)
5090{
5091 struct bgp_filter *filter;
5092 struct bgp_filter *gfilter;
5093 struct peer_group *group;
5094 struct listnode *node, *nnode;
5095
5096 if (direct != FILTER_IN && direct != FILTER_OUT)
5097 return BGP_ERR_INVALID_VALUE;
5098
5099 filter = &peer->filter[afi][safi];
5100
5101 /* apply peer-group filter */
5102 if (peer_group_active(peer)) {
5103 gfilter = &peer->group->conf->filter[afi][safi];
5104
5105 if (gfilter->dlist[direct].name) {
5106 if (filter->dlist[direct].name)
5107 XFREE(MTYPE_BGP_FILTER_NAME,
5108 filter->dlist[direct].name);
5109 filter->dlist[direct].name =
5110 XSTRDUP(MTYPE_BGP_FILTER_NAME,
5111 gfilter->dlist[direct].name);
5112 filter->dlist[direct].alist =
5113 gfilter->dlist[direct].alist;
5114 peer_on_policy_change(peer, afi, safi,
5115 (direct == FILTER_OUT) ? 1 : 0);
5116 return 0;
5117 }
5118 }
5119
5120 if (filter->dlist[direct].name)
5121 XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name);
5122 filter->dlist[direct].name = NULL;
5123 filter->dlist[direct].alist = NULL;
5124
5125 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5126 peer_on_policy_change(peer, afi, safi,
5127 (direct == FILTER_OUT) ? 1 : 0);
5128 return 0;
5129 }
5130
5131 group = peer->group;
5132 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5133 filter = &peer->filter[afi][safi];
5134
5135 if (filter->dlist[direct].name)
5136 XFREE(MTYPE_BGP_FILTER_NAME,
5137 filter->dlist[direct].name);
5138 filter->dlist[direct].name = NULL;
5139 filter->dlist[direct].alist = NULL;
5140 peer_on_policy_change(peer, afi, safi,
5141 (direct == FILTER_OUT) ? 1 : 0);
5142 }
5143
5144 return 0;
5145}
5146
5147/* Update distribute list. */
5148static void peer_distribute_update(struct access_list *access)
5149{
5150 afi_t afi;
5151 safi_t safi;
5152 int direct;
5153 struct listnode *mnode, *mnnode;
5154 struct listnode *node, *nnode;
5155 struct bgp *bgp;
5156 struct peer *peer;
5157 struct peer_group *group;
5158 struct bgp_filter *filter;
5159
5160 for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
5161 if (access->name)
5162 update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST,
5163 access->name, 0, 0);
5164 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
5165 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5166 for (safi = SAFI_UNICAST; safi < SAFI_MAX;
5167 safi++) {
5168 filter = &peer->filter[afi][safi];
5169
5170 for (direct = FILTER_IN;
5171 direct < FILTER_MAX; direct++) {
5172 if (filter->dlist[direct].name)
5173 filter->dlist[direct]
5174 .alist = access_list_lookup(
5175 afi,
5176 filter->dlist[direct]
5177 .name);
5178 else
5179 filter->dlist[direct]
5180 .alist = NULL;
5181 }
5182 }
5183 }
5184 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
5185 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5186 for (safi = SAFI_UNICAST; safi < SAFI_MAX;
5187 safi++) {
5188 filter =
5189 &group->conf->filter[afi][safi];
5190
5191 for (direct = FILTER_IN;
5192 direct < FILTER_MAX; direct++) {
5193 if (filter->dlist[direct].name)
5194 filter->dlist[direct]
5195 .alist = access_list_lookup(
5196 afi,
5197 filter->dlist[direct]
5198 .name);
5199 else
5200 filter->dlist[direct]
5201 .alist = NULL;
5202 }
5203 }
5204 }
5205#if ENABLE_BGP_VNC
5206 vnc_prefix_list_update(bgp);
5207#endif
5208 }
5209}
5210
5211/* Set prefix list to the peer. */
5212int peer_prefix_list_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
5213 const char *name)
5214{
5215 struct bgp_filter *filter;
5216 struct peer_group *group;
5217 struct listnode *node, *nnode;
5218
5219 if (direct != FILTER_IN && direct != FILTER_OUT)
5220 return BGP_ERR_INVALID_VALUE;
5221
5222 filter = &peer->filter[afi][safi];
5223
5224 if (filter->dlist[direct].name)
5225 return BGP_ERR_PEER_FILTER_CONFLICT;
5226
5227 if (filter->plist[direct].name)
5228 XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name);
5229 filter->plist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
5230 filter->plist[direct].plist = prefix_list_lookup(afi, name);
5231
5232 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5233 peer_on_policy_change(peer, afi, safi,
5234 (direct == FILTER_OUT) ? 1 : 0);
5235 return 0;
5236 }
5237
5238 group = peer->group;
5239 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5240 filter = &peer->filter[afi][safi];
5241
5242 if (filter->plist[direct].name)
5243 XFREE(MTYPE_BGP_FILTER_NAME,
5244 filter->plist[direct].name);
5245 filter->plist[direct].name =
5246 XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
5247 filter->plist[direct].plist = prefix_list_lookup(afi, name);
5248 peer_on_policy_change(peer, afi, safi,
5249 (direct == FILTER_OUT) ? 1 : 0);
5250 }
5251 return 0;
5252}
5253
5254int peer_prefix_list_unset(struct peer *peer, afi_t afi, safi_t safi,
5255 int direct)
5256{
5257 struct bgp_filter *filter;
5258 struct bgp_filter *gfilter;
5259 struct peer_group *group;
5260 struct listnode *node, *nnode;
5261
5262 if (direct != FILTER_IN && direct != FILTER_OUT)
5263 return BGP_ERR_INVALID_VALUE;
5264
5265 filter = &peer->filter[afi][safi];
5266
5267 /* apply peer-group filter */
5268 if (peer_group_active(peer)) {
5269 gfilter = &peer->group->conf->filter[afi][safi];
5270
5271 if (gfilter->plist[direct].name) {
5272 if (filter->plist[direct].name)
5273 XFREE(MTYPE_BGP_FILTER_NAME,
5274 filter->plist[direct].name);
5275 filter->plist[direct].name =
5276 XSTRDUP(MTYPE_BGP_FILTER_NAME,
5277 gfilter->plist[direct].name);
5278 filter->plist[direct].plist =
5279 gfilter->plist[direct].plist;
5280 peer_on_policy_change(peer, afi, safi,
5281 (direct == FILTER_OUT) ? 1 : 0);
5282 return 0;
5283 }
5284 }
5285
5286 if (filter->plist[direct].name)
5287 XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name);
5288 filter->plist[direct].name = NULL;
5289 filter->plist[direct].plist = NULL;
5290
5291 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5292 peer_on_policy_change(peer, afi, safi,
5293 (direct == FILTER_OUT) ? 1 : 0);
5294 return 0;
5295 }
5296
5297 group = peer->group;
5298 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5299 filter = &peer->filter[afi][safi];
5300
5301 if (filter->plist[direct].name)
5302 XFREE(MTYPE_BGP_FILTER_NAME,
5303 filter->plist[direct].name);
5304 filter->plist[direct].name = NULL;
5305 filter->plist[direct].plist = NULL;
5306 peer_on_policy_change(peer, afi, safi,
5307 (direct == FILTER_OUT) ? 1 : 0);
5308 }
5309
5310 return 0;
5311}
5312
5313/* Update prefix-list list. */
5314static void peer_prefix_list_update(struct prefix_list *plist)
5315{
5316 struct listnode *mnode, *mnnode;
5317 struct listnode *node, *nnode;
5318 struct bgp *bgp;
5319 struct peer *peer;
5320 struct peer_group *group;
5321 struct bgp_filter *filter;
5322 afi_t afi;
5323 safi_t safi;
5324 int direct;
5325
5326 for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
5327
5328 /*
5329 * Update the prefix-list on update groups.
5330 */
5331 update_group_policy_update(
5332 bgp, BGP_POLICY_PREFIX_LIST,
5333 plist ? prefix_list_name(plist) : NULL, 0, 0);
5334
5335 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
5336 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5337 for (safi = SAFI_UNICAST; safi < SAFI_MAX;
5338 safi++) {
5339 filter = &peer->filter[afi][safi];
5340
5341 for (direct = FILTER_IN;
5342 direct < FILTER_MAX; direct++) {
5343 if (filter->plist[direct].name)
5344 filter->plist[direct]
5345 .plist = prefix_list_lookup(
5346 afi,
5347 filter->plist[direct]
5348 .name);
5349 else
5350 filter->plist[direct]
5351 .plist = NULL;
5352 }
5353 }
5354 }
5355 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
5356 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5357 for (safi = SAFI_UNICAST; safi < SAFI_MAX;
5358 safi++) {
5359 filter =
5360 &group->conf->filter[afi][safi];
5361
5362 for (direct = FILTER_IN;
5363 direct < FILTER_MAX; direct++) {
5364 if (filter->plist[direct].name)
5365 filter->plist[direct]
5366 .plist = prefix_list_lookup(
5367 afi,
5368 filter->plist[direct]
5369 .name);
5370 else
5371 filter->plist[direct]
5372 .plist = NULL;
5373 }
5374 }
5375 }
5376 }
5377}
5378
5379int peer_aslist_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
5380 const char *name)
5381{
5382 struct bgp_filter *filter;
5383 struct peer_group *group;
5384 struct listnode *node, *nnode;
5385
5386 if (direct != FILTER_IN && direct != FILTER_OUT)
5387 return BGP_ERR_INVALID_VALUE;
5388
5389 filter = &peer->filter[afi][safi];
5390
5391 if (filter->aslist[direct].name)
5392 XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name);
5393 filter->aslist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
5394 filter->aslist[direct].aslist = as_list_lookup(name);
5395
5396 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5397 peer_on_policy_change(peer, afi, safi,
5398 (direct == FILTER_OUT) ? 1 : 0);
5399 return 0;
5400 }
5401
5402 group = peer->group;
5403 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5404 filter = &peer->filter[afi][safi];
5405
5406 if (filter->aslist[direct].name)
5407 XFREE(MTYPE_BGP_FILTER_NAME,
5408 filter->aslist[direct].name);
5409 filter->aslist[direct].name =
5410 XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
5411 filter->aslist[direct].aslist = as_list_lookup(name);
5412 peer_on_policy_change(peer, afi, safi,
5413 (direct == FILTER_OUT) ? 1 : 0);
5414 }
5415 return 0;
5416}
5417
5418int peer_aslist_unset(struct peer *peer, afi_t afi, safi_t safi, int direct)
5419{
5420 struct bgp_filter *filter;
5421 struct bgp_filter *gfilter;
5422 struct peer_group *group;
5423 struct listnode *node, *nnode;
5424
5425 if (direct != FILTER_IN && direct != FILTER_OUT)
5426 return BGP_ERR_INVALID_VALUE;
5427
5428 filter = &peer->filter[afi][safi];
5429
5430 /* apply peer-group filter */
5431 if (peer_group_active(peer)) {
5432 gfilter = &peer->group->conf->filter[afi][safi];
5433
5434 if (gfilter->aslist[direct].name) {
5435 if (filter->aslist[direct].name)
5436 XFREE(MTYPE_BGP_FILTER_NAME,
5437 filter->aslist[direct].name);
5438 filter->aslist[direct].name =
5439 XSTRDUP(MTYPE_BGP_FILTER_NAME,
5440 gfilter->aslist[direct].name);
5441 filter->aslist[direct].aslist =
5442 gfilter->aslist[direct].aslist;
5443 peer_on_policy_change(peer, afi, safi,
5444 (direct == FILTER_OUT) ? 1 : 0);
5445 return 0;
5446 }
5447 }
5448
5449 if (filter->aslist[direct].name)
5450 XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name);
5451 filter->aslist[direct].name = NULL;
5452 filter->aslist[direct].aslist = NULL;
5453
5454 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5455 peer_on_policy_change(peer, afi, safi,
5456 (direct == FILTER_OUT) ? 1 : 0);
5457 return 0;
5458 }
5459
5460 group = peer->group;
5461 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5462 filter = &peer->filter[afi][safi];
5463
5464 if (filter->aslist[direct].name)
5465 XFREE(MTYPE_BGP_FILTER_NAME,
5466 filter->aslist[direct].name);
5467 filter->aslist[direct].name = NULL;
5468 filter->aslist[direct].aslist = NULL;
5469 peer_on_policy_change(peer, afi, safi,
5470 (direct == FILTER_OUT) ? 1 : 0);
5471 }
5472
5473 return 0;
5474}
5475
5476static void peer_aslist_update(const char *aslist_name)
5477{
5478 afi_t afi;
5479 safi_t safi;
5480 int direct;
5481 struct listnode *mnode, *mnnode;
5482 struct listnode *node, *nnode;
5483 struct bgp *bgp;
5484 struct peer *peer;
5485 struct peer_group *group;
5486 struct bgp_filter *filter;
5487
5488 for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
5489 update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST,
5490 aslist_name, 0, 0);
5491
5492 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
5493 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5494 for (safi = SAFI_UNICAST; safi < SAFI_MAX;
5495 safi++) {
5496 filter = &peer->filter[afi][safi];
5497
5498 for (direct = FILTER_IN;
5499 direct < FILTER_MAX; direct++) {
5500 if (filter->aslist[direct].name)
5501 filter->aslist[direct]
5502 .aslist = as_list_lookup(
5503 filter->aslist[direct]
5504 .name);
5505 else
5506 filter->aslist[direct]
5507 .aslist = NULL;
5508 }
5509 }
5510 }
5511 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
5512 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5513 for (safi = SAFI_UNICAST; safi < SAFI_MAX;
5514 safi++) {
5515 filter =
5516 &group->conf->filter[afi][safi];
5517
5518 for (direct = FILTER_IN;
5519 direct < FILTER_MAX; direct++) {
5520 if (filter->aslist[direct].name)
5521 filter->aslist[direct]
5522 .aslist = as_list_lookup(
5523 filter->aslist[direct]
5524 .name);
5525 else
5526 filter->aslist[direct]
5527 .aslist = NULL;
5528 }
5529 }
5530 }
5531 }
5532}
5533
5534static void peer_aslist_add(char *aslist_name)
5535{
5536 peer_aslist_update(aslist_name);
5537 route_map_notify_dependencies((char *)aslist_name,
5538 RMAP_EVENT_ASLIST_ADDED);
5539}
5540
5541static void peer_aslist_del(const char *aslist_name)
5542{
5543 peer_aslist_update(aslist_name);
5544 route_map_notify_dependencies(aslist_name, RMAP_EVENT_ASLIST_DELETED);
5545}
5546
5547
5548int peer_route_map_set(struct peer *peer, afi_t afi, safi_t safi, int direct,
5549 const char *name)
5550{
5551 struct bgp_filter *filter;
5552 struct peer_group *group;
5553 struct listnode *node, *nnode;
5554
5555 if (direct != RMAP_IN && direct != RMAP_OUT)
5556 return BGP_ERR_INVALID_VALUE;
5557
5558 filter = &peer->filter[afi][safi];
5559
5560 if (filter->map[direct].name)
5561 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
5562
5563 filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
5564 filter->map[direct].map = route_map_lookup_by_name(name);
5565
5566 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5567 peer_on_policy_change(peer, afi, safi,
5568 (direct == RMAP_OUT) ? 1 : 0);
5569 return 0;
5570 }
5571
5572 group = peer->group;
5573 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5574 filter = &peer->filter[afi][safi];
5575
5576 if (filter->map[direct].name)
5577 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
5578 filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
5579 filter->map[direct].map = route_map_lookup_by_name(name);
5580 peer_on_policy_change(peer, afi, safi,
5581 (direct == RMAP_OUT) ? 1 : 0);
5582 }
5583 return 0;
5584}
5585
5586/* Unset route-map from the peer. */
5587int peer_route_map_unset(struct peer *peer, afi_t afi, safi_t safi, int direct)
5588{
5589 struct bgp_filter *filter;
5590 struct bgp_filter *gfilter;
5591 struct peer_group *group;
5592 struct listnode *node, *nnode;
5593
5594 if (direct != RMAP_IN && direct != RMAP_OUT)
5595 return BGP_ERR_INVALID_VALUE;
5596
5597 filter = &peer->filter[afi][safi];
5598
5599 /* apply peer-group filter */
5600 if (peer_group_active(peer)) {
5601 gfilter = &peer->group->conf->filter[afi][safi];
5602
5603 if (gfilter->map[direct].name) {
5604 if (filter->map[direct].name)
5605 XFREE(MTYPE_BGP_FILTER_NAME,
5606 filter->map[direct].name);
5607 filter->map[direct].name =
5608 XSTRDUP(MTYPE_BGP_FILTER_NAME,
5609 gfilter->map[direct].name);
5610 filter->map[direct].map = gfilter->map[direct].map;
5611 peer_on_policy_change(peer, afi, safi,
5612 (direct == RMAP_OUT) ? 1 : 0);
5613 return 0;
5614 }
5615 }
5616
5617 if (filter->map[direct].name)
5618 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
5619 filter->map[direct].name = NULL;
5620 filter->map[direct].map = NULL;
5621
5622 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5623 peer_on_policy_change(peer, afi, safi,
5624 (direct == RMAP_OUT) ? 1 : 0);
5625 return 0;
5626 }
5627
5628 group = peer->group;
5629 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5630 filter = &peer->filter[afi][safi];
5631
5632 if (filter->map[direct].name)
5633 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
5634 filter->map[direct].name = NULL;
5635 filter->map[direct].map = NULL;
5636 peer_on_policy_change(peer, afi, safi,
5637 (direct == RMAP_OUT) ? 1 : 0);
5638 }
5639 return 0;
5640}
5641
5642/* Set unsuppress-map to the peer. */
5643int peer_unsuppress_map_set(struct peer *peer, afi_t afi, safi_t safi,
5644 const char *name)
5645{
5646 struct bgp_filter *filter;
5647 struct peer_group *group;
5648 struct listnode *node, *nnode;
5649
5650 filter = &peer->filter[afi][safi];
5651
5652 if (filter->usmap.name)
5653 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
5654
5655 filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
5656 filter->usmap.map = route_map_lookup_by_name(name);
5657
5658 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5659 peer_on_policy_change(peer, afi, safi, 1);
5660 return 0;
5661 }
5662
5663 group = peer->group;
5664 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5665 filter = &peer->filter[afi][safi];
5666
5667 if (filter->usmap.name)
5668 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
5669 filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
5670 filter->usmap.map = route_map_lookup_by_name(name);
5671 peer_on_policy_change(peer, afi, safi, 1);
5672 }
5673 return 0;
5674}
5675
5676/* Unset route-map from the peer. */
5677int peer_unsuppress_map_unset(struct peer *peer, afi_t afi, safi_t safi)
718e3744 5678{
d62a17ae 5679 struct bgp_filter *filter;
5680 struct peer_group *group;
5681 struct listnode *node, *nnode;
5682
5683 filter = &peer->filter[afi][safi];
718e3744 5684
d62a17ae 5685 if (filter->usmap.name)
5686 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
5687 filter->usmap.name = NULL;
5688 filter->usmap.map = NULL;
718e3744 5689
d62a17ae 5690 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5691 peer_on_policy_change(peer, afi, safi, 1);
5692 return 0;
5693 }
718e3744 5694
d62a17ae 5695 group = peer->group;
5696 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5697 filter = &peer->filter[afi][safi];
718e3744 5698
d62a17ae 5699 if (filter->usmap.name)
5700 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
5701 filter->usmap.name = NULL;
5702 filter->usmap.map = NULL;
5703 peer_on_policy_change(peer, afi, safi, 1);
5704 }
5705 return 0;
5706}
718e3744 5707
d62a17ae 5708int peer_maximum_prefix_set(struct peer *peer, afi_t afi, safi_t safi,
5709 u_int32_t max, u_char threshold, int warning,
5710 u_int16_t restart)
5711{
5712 struct peer_group *group;
5713 struct listnode *node, *nnode;
5714
5715 SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5716 peer->pmax[afi][safi] = max;
5717 peer->pmax_threshold[afi][safi] = threshold;
5718 peer->pmax_restart[afi][safi] = restart;
5719 if (warning)
5720 SET_FLAG(peer->af_flags[afi][safi],
5721 PEER_FLAG_MAX_PREFIX_WARNING);
5722 else
5723 UNSET_FLAG(peer->af_flags[afi][safi],
5724 PEER_FLAG_MAX_PREFIX_WARNING);
5725
5726 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5727 group = peer->group;
5728 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5729 SET_FLAG(peer->af_flags[afi][safi],
5730 PEER_FLAG_MAX_PREFIX);
5731 peer->pmax[afi][safi] = max;
5732 peer->pmax_threshold[afi][safi] = threshold;
5733 peer->pmax_restart[afi][safi] = restart;
5734 if (warning)
5735 SET_FLAG(peer->af_flags[afi][safi],
5736 PEER_FLAG_MAX_PREFIX_WARNING);
5737 else
5738 UNSET_FLAG(peer->af_flags[afi][safi],
5739 PEER_FLAG_MAX_PREFIX_WARNING);
5740
5741 if ((peer->status == Established)
5742 && (peer->afc[afi][safi]))
5743 bgp_maximum_prefix_overflow(peer, afi, safi, 1);
5744 }
5745 } else {
5746 if ((peer->status == Established) && (peer->afc[afi][safi]))
5747 bgp_maximum_prefix_overflow(peer, afi, safi, 1);
5748 }
718e3744 5749
d62a17ae 5750 return 0;
5751}
718e3744 5752
d62a17ae 5753int peer_maximum_prefix_unset(struct peer *peer, afi_t afi, safi_t safi)
5754{
5755 struct peer_group *group;
5756 struct listnode *node, *nnode;
5757
5758 /* apply peer-group config */
5759 if (peer_group_active(peer)) {
5760 if (CHECK_FLAG(peer->group->conf->af_flags[afi][safi],
5761 PEER_FLAG_MAX_PREFIX))
5762 SET_FLAG(peer->af_flags[afi][safi],
5763 PEER_FLAG_MAX_PREFIX);
5764 else
5765 UNSET_FLAG(peer->af_flags[afi][safi],
5766 PEER_FLAG_MAX_PREFIX);
5767
5768 if (CHECK_FLAG(peer->group->conf->af_flags[afi][safi],
5769 PEER_FLAG_MAX_PREFIX_WARNING))
5770 SET_FLAG(peer->af_flags[afi][safi],
5771 PEER_FLAG_MAX_PREFIX_WARNING);
5772 else
5773 UNSET_FLAG(peer->af_flags[afi][safi],
5774 PEER_FLAG_MAX_PREFIX_WARNING);
5775
5776 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
5777 peer->pmax_threshold[afi][safi] =
5778 peer->group->conf->pmax_threshold[afi][safi];
5779 peer->pmax_restart[afi][safi] =
5780 peer->group->conf->pmax_restart[afi][safi];
5781 return 0;
5782 }
718e3744 5783
d62a17ae 5784 UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5785 UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5786 peer->pmax[afi][safi] = 0;
5787 peer->pmax_threshold[afi][safi] = 0;
5788 peer->pmax_restart[afi][safi] = 0;
5789
5790 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
5791 return 0;
5792
5793 group = peer->group;
5794 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5795 UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5796 UNSET_FLAG(peer->af_flags[afi][safi],
5797 PEER_FLAG_MAX_PREFIX_WARNING);
5798 peer->pmax[afi][safi] = 0;
5799 peer->pmax_threshold[afi][safi] = 0;
5800 peer->pmax_restart[afi][safi] = 0;
5801 }
5802 return 0;
718e3744 5803}
5804
d62a17ae 5805int is_ebgp_multihop_configured(struct peer *peer)
718e3744 5806{
d62a17ae 5807 struct peer_group *group;
5808 struct listnode *node, *nnode;
5809 struct peer *peer1;
718e3744 5810
d62a17ae 5811 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5812 group = peer->group;
5813 if ((peer_sort(peer) != BGP_PEER_IBGP)
5814 && (group->conf->ttl != 1))
5815 return 1;
718e3744 5816
d62a17ae 5817 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer1)) {
5818 if ((peer_sort(peer1) != BGP_PEER_IBGP)
5819 && (peer1->ttl != 1))
5820 return 1;
5821 }
5822 } else {
5823 if ((peer_sort(peer) != BGP_PEER_IBGP) && (peer->ttl != 1))
5824 return 1;
5825 }
5826 return 0;
5827}
718e3744 5828
d62a17ae 5829/* Set # of hops between us and BGP peer. */
5830int peer_ttl_security_hops_set(struct peer *peer, int gtsm_hops)
5831{
5832 struct peer_group *group;
5833 struct listnode *node, *nnode;
5834 int ret;
5835
5836 zlog_debug("peer_ttl_security_hops_set: set gtsm_hops to %d for %s",
5837 gtsm_hops, peer->host);
5838
5839 /* We cannot configure ttl-security hops when ebgp-multihop is already
5840 set. For non peer-groups, the check is simple. For peer-groups,
5841 it's
5842 slightly messy, because we need to check both the peer-group
5843 structure
5844 and all peer-group members for any trace of ebgp-multihop
5845 configuration
5846 before actually applying the ttl-security rules. Cisco really made a
5847 mess of this configuration parameter, and OpenBGPD got it right.
5848 */
5849
5850 if ((peer->gtsm_hops == 0) && (peer->sort != BGP_PEER_IBGP)) {
5851 if (is_ebgp_multihop_configured(peer))
5852 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
5853
5854 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5855 peer->gtsm_hops = gtsm_hops;
5856
5857 /* Calling ebgp multihop also resets the session.
5858 * On restart, NHT will get setup correctly as will the
5859 * min & max ttls on the socket. The return value is
5860 * irrelevant.
5861 */
5862 ret = peer_ebgp_multihop_set(peer, MAXTTL);
5863
5864 if (ret != 0)
5865 return ret;
5866 } else {
5867 group = peer->group;
5868 for (ALL_LIST_ELEMENTS(group->peer, node, nnode,
5869 peer)) {
5870 peer->gtsm_hops = group->conf->gtsm_hops;
5871
5872 /* Calling ebgp multihop also resets the
5873 * session.
5874 * On restart, NHT will get setup correctly as
5875 * will the
5876 * min & max ttls on the socket. The return
5877 * value is
5878 * irrelevant.
5879 */
5880 peer_ebgp_multihop_set(peer, MAXTTL);
5881 }
5882 }
5883 } else {
5884 /* Post the first gtsm setup or if its ibgp, maxttl setting
5885 * isn't
5886 * necessary, just set the minttl.
5887 */
5888 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5889 peer->gtsm_hops = gtsm_hops;
5890
5891 if (peer->fd >= 0)
5892 sockopt_minttl(peer->su.sa.sa_family, peer->fd,
5893 MAXTTL + 1 - gtsm_hops);
5894 if ((peer->status < Established) && peer->doppelganger
5895 && (peer->doppelganger->fd >= 0))
5896 sockopt_minttl(peer->su.sa.sa_family,
5897 peer->doppelganger->fd,
5898 MAXTTL + 1 - gtsm_hops);
5899 } else {
5900 group = peer->group;
5901 for (ALL_LIST_ELEMENTS(group->peer, node, nnode,
5902 peer)) {
5903 peer->gtsm_hops = group->conf->gtsm_hops;
5904
5905 /* Change setting of existing peer
5906 * established then change value (may break
5907 * connectivity)
5908 * not established yet (teardown session and
5909 * restart)
5910 * no session then do nothing (will get
5911 * handled by next connection)
5912 */
5913 if (peer->fd >= 0 && peer->gtsm_hops != 0)
5914 sockopt_minttl(
5915 peer->su.sa.sa_family, peer->fd,
5916 MAXTTL + 1 - peer->gtsm_hops);
5917 if ((peer->status < Established)
5918 && peer->doppelganger
5919 && (peer->doppelganger->fd >= 0))
5920 sockopt_minttl(peer->su.sa.sa_family,
5921 peer->doppelganger->fd,
5922 MAXTTL + 1 - gtsm_hops);
5923 }
5924 }
5925 }
718e3744 5926
d62a17ae 5927 return 0;
718e3744 5928}
5929
d62a17ae 5930int peer_ttl_security_hops_unset(struct peer *peer)
5931{
5932 struct peer_group *group;
5933 struct listnode *node, *nnode;
5934 int ret = 0;
5935
5936 zlog_debug("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s",
5937 peer->host);
5938
5939 /* if a peer-group member, then reset to peer-group default rather than
5940 * 0 */
5941 if (peer_group_active(peer))
5942 peer->gtsm_hops = peer->group->conf->gtsm_hops;
5943 else
5944 peer->gtsm_hops = 0;
5945
5946 if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
5947 /* Invoking ebgp_multihop_set will set the TTL back to the
5948 * original
5949 * value as well as restting the NHT and such. The session is
5950 * reset.
5951 */
5952 if (peer->sort == BGP_PEER_EBGP)
5953 ret = peer_ebgp_multihop_unset(peer);
5954 else {
5955 if (peer->fd >= 0)
5956 sockopt_minttl(peer->su.sa.sa_family, peer->fd,
5957 0);
5958
5959 if ((peer->status < Established) && peer->doppelganger
5960 && (peer->doppelganger->fd >= 0))
5961 sockopt_minttl(peer->su.sa.sa_family,
5962 peer->doppelganger->fd, 0);
5963 }
5964 } else {
5965 group = peer->group;
5966 for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
5967 peer->gtsm_hops = 0;
5968 if (peer->sort == BGP_PEER_EBGP)
5969 ret = peer_ebgp_multihop_unset(peer);
5970 else {
5971 if (peer->fd >= 0)
5972 sockopt_minttl(peer->su.sa.sa_family,
5973 peer->fd, 0);
5974
5975 if ((peer->status < Established)
5976 && peer->doppelganger
5977 && (peer->doppelganger->fd >= 0))
5978 sockopt_minttl(peer->su.sa.sa_family,
5979 peer->doppelganger->fd,
5980 0);
5981 }
5982 }
5983 }
718e3744 5984
d62a17ae 5985 return ret;
5986}
5987
5988/*
5989 * If peer clear is invoked in a loop for all peers on the BGP instance,
5990 * it may end up freeing the doppelganger, and if this was the next node
5991 * to the current node, we would end up accessing the freed next node.
5992 * Pass along additional parameter which can be updated if next node
5993 * is freed; only required when walking the peer list on BGP instance.
5994 */
5995int peer_clear(struct peer *peer, struct listnode **nnode)
5996{
5997 if (!CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)) {
5998 if (CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW)) {
5999 UNSET_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
6000 if (peer->t_pmax_restart) {
6001 BGP_TIMER_OFF(peer->t_pmax_restart);
6002 if (bgp_debug_neighbor_events(peer))
6003 zlog_debug(
6004 "%s Maximum-prefix restart timer canceled",
6005 peer->host);
6006 }
6007 BGP_EVENT_ADD(peer, BGP_Start);
6008 return 0;
6009 }
6010
6011 peer->v_start = BGP_INIT_START_TIMER;
6012 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
6013 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
6014 BGP_NOTIFY_CEASE_ADMIN_RESET);
6015 else
6016 bgp_session_reset_safe(peer, nnode);
718e3744 6017 }
d62a17ae 6018 return 0;
718e3744 6019}
6b0655a2 6020
d62a17ae 6021int peer_clear_soft(struct peer *peer, afi_t afi, safi_t safi,
6022 enum bgp_clear_type stype)
718e3744 6023{
d62a17ae 6024 struct peer_af *paf;
718e3744 6025
d62a17ae 6026 if (peer->status != Established)
6027 return 0;
718e3744 6028
d62a17ae 6029 if (!peer->afc[afi][safi])
6030 return BGP_ERR_AF_UNCONFIGURED;
718e3744 6031
d62a17ae 6032 peer->rtt = sockopt_tcp_rtt(peer->fd);
718e3744 6033
d62a17ae 6034 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH) {
6035 /* Clear the "neighbor x.x.x.x default-originate" flag */
6036 paf = peer_af_find(peer, afi, safi);
6037 if (paf && paf->subgroup
6038 && CHECK_FLAG(paf->subgroup->sflags,
6039 SUBGRP_STATUS_DEFAULT_ORIGINATE))
6040 UNSET_FLAG(paf->subgroup->sflags,
6041 SUBGRP_STATUS_DEFAULT_ORIGINATE);
718e3744 6042
d62a17ae 6043 bgp_announce_route(peer, afi, safi);
6044 }
718e3744 6045
d62a17ae 6046 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX) {
6047 if (CHECK_FLAG(peer->af_cap[afi][safi],
6048 PEER_CAP_ORF_PREFIX_SM_ADV)
6049 && (CHECK_FLAG(peer->af_cap[afi][safi],
6050 PEER_CAP_ORF_PREFIX_RM_RCV)
6051 || CHECK_FLAG(peer->af_cap[afi][safi],
6052 PEER_CAP_ORF_PREFIX_RM_OLD_RCV))) {
6053 struct bgp_filter *filter = &peer->filter[afi][safi];
6054 u_char prefix_type;
6055
6056 if (CHECK_FLAG(peer->af_cap[afi][safi],
6057 PEER_CAP_ORF_PREFIX_RM_RCV))
6058 prefix_type = ORF_TYPE_PREFIX;
6059 else
6060 prefix_type = ORF_TYPE_PREFIX_OLD;
6061
6062 if (filter->plist[FILTER_IN].plist) {
6063 if (CHECK_FLAG(peer->af_sflags[afi][safi],
6064 PEER_STATUS_ORF_PREFIX_SEND))
6065 bgp_route_refresh_send(
6066 peer, afi, safi, prefix_type,
6067 REFRESH_DEFER, 1);
6068 bgp_route_refresh_send(peer, afi, safi,
6069 prefix_type,
6070 REFRESH_IMMEDIATE, 0);
6071 } else {
6072 if (CHECK_FLAG(peer->af_sflags[afi][safi],
6073 PEER_STATUS_ORF_PREFIX_SEND))
6074 bgp_route_refresh_send(
6075 peer, afi, safi, prefix_type,
6076 REFRESH_IMMEDIATE, 1);
6077 else
6078 bgp_route_refresh_send(peer, afi, safi,
6079 0, 0, 0);
6080 }
6081 return 0;
6082 }
6083 }
718e3744 6084
d62a17ae 6085 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
6086 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX) {
6087 /* If neighbor has soft reconfiguration inbound flag.
6088 Use Adj-RIB-In database. */
6089 if (CHECK_FLAG(peer->af_flags[afi][safi],
6090 PEER_FLAG_SOFT_RECONFIG))
6091 bgp_soft_reconfig_in(peer, afi, safi);
6092 else {
6093 /* If neighbor has route refresh capability, send route
6094 refresh
6095 message to the peer. */
6096 if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV)
6097 || CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV))
6098 bgp_route_refresh_send(peer, afi, safi, 0, 0,
6099 0);
6100 else
6101 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
6102 }
6103 }
6104 return 0;
718e3744 6105}
6106
d62a17ae 6107/* Display peer uptime.*/
6108char *peer_uptime(time_t uptime2, char *buf, size_t len, u_char use_json,
6109 json_object *json)
6110{
6111 time_t uptime1, epoch_tbuf;
6112 struct tm *tm;
6113
6114 /* Check buffer length. */
6115 if (len < BGP_UPTIME_LEN) {
6116 if (!use_json) {
6117 zlog_warn("peer_uptime (): buffer shortage %lu",
6118 (u_long)len);
6119 /* XXX: should return status instead of buf... */
6120 snprintf(buf, len, "<error> ");
6121 }
6122 return buf;
6123 }
6124
6125 /* If there is no connection has been done before print `never'. */
6126 if (uptime2 == 0) {
6127 if (use_json) {
6128 json_object_string_add(json, "peerUptime", "never");
6129 json_object_int_add(json, "peerUptimeMsec", 0);
6130 } else
6131 snprintf(buf, len, "never");
6132 return buf;
6133 }
718e3744 6134
d62a17ae 6135 /* Get current time. */
6136 uptime1 = bgp_clock();
6137 uptime1 -= uptime2;
6138 tm = gmtime(&uptime1);
718e3744 6139
d62a17ae 6140 if (uptime1 < ONE_DAY_SECOND)
6141 snprintf(buf, len, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min,
6142 tm->tm_sec);
6143 else if (uptime1 < ONE_WEEK_SECOND)
6144 snprintf(buf, len, "%dd%02dh%02dm", tm->tm_yday, tm->tm_hour,
6145 tm->tm_min);
6146 else if (uptime1 < ONE_YEAR_SECOND)
6147 snprintf(buf, len, "%02dw%dd%02dh", tm->tm_yday / 7,
6148 tm->tm_yday - ((tm->tm_yday / 7) * 7), tm->tm_hour);
6149 else
6150 snprintf(buf, len, "%02dy%02dw%dd", tm->tm_year - 70,
6151 tm->tm_yday / 7,
6152 tm->tm_yday - ((tm->tm_yday / 7) * 7));
6153
6154 if (use_json) {
6155 epoch_tbuf = time(NULL) - uptime1;
6156 json_object_string_add(json, "peerUptime", buf);
6157 json_object_int_add(json, "peerUptimeMsec", uptime1 * 1000);
6158 json_object_int_add(json, "peerUptimeEstablishedEpoch",
6159 epoch_tbuf);
6160 }
718e3744 6161
d62a17ae 6162 return buf;
718e3744 6163}
6164
2cb5980f
DL
6165#define afi_header_vty_out(vty, afi, safi, write, format, ...) \
6166 do { \
6167 bgp_config_write_family_header(vty, afi, safi, write); \
6168 vty_out(vty, format, ## __VA_ARGS__); \
6169 } while (0)
3f9c7369 6170
d62a17ae 6171static void bgp_config_write_filter(struct vty *vty, struct peer *peer,
6172 afi_t afi, safi_t safi, int *write)
518f0eb1 6173{
d62a17ae 6174 struct bgp_filter *filter;
6175 struct bgp_filter *gfilter = NULL;
6176 char *addr;
6177 int in = FILTER_IN;
6178 int out = FILTER_OUT;
518f0eb1 6179
d62a17ae 6180 addr = peer->host;
6181 filter = &peer->filter[afi][safi];
518f0eb1 6182
d62a17ae 6183 if (peer_group_active(peer))
6184 gfilter = &peer->group->conf->filter[afi][safi];
6185
6186 /* distribute-list. */
6187 if (filter->dlist[in].name)
6188 if (!gfilter || !gfilter->dlist[in].name
6189 || strcmp(filter->dlist[in].name, gfilter->dlist[in].name)
6190 != 0) {
6191 afi_header_vty_out(
6192 vty, afi, safi, write,
6193 " neighbor %s distribute-list %s in\n", addr,
6194 filter->dlist[in].name);
6195 }
6b0655a2 6196
d62a17ae 6197 if (filter->dlist[out].name && !gfilter) {
6198 afi_header_vty_out(vty, afi, safi, write,
6199 " neighbor %s distribute-list %s out\n",
6200 addr, filter->dlist[out].name);
6201 }
718e3744 6202
d62a17ae 6203 /* prefix-list. */
6204 if (filter->plist[in].name)
6205 if (!gfilter || !gfilter->plist[in].name
6206 || strcmp(filter->plist[in].name, gfilter->plist[in].name)
6207 != 0) {
6208 afi_header_vty_out(vty, afi, safi, write,
6209 " neighbor %s prefix-list %s in\n",
6210 addr, filter->plist[in].name);
6211 }
718e3744 6212
a1e91fee
BR
6213 if (filter->plist[out].name)
6214 if (!gfilter || !gfilter->plist[out].name
6215 || strcmp(filter->plist[out].name, gfilter->plist[out].name)
6216 != 0) {
6217 afi_header_vty_out(vty, afi, safi, write,
6218 " neighbor %s prefix-list %s out\n",
6219 addr, filter->plist[out].name);
6220 }
718e3744 6221
d62a17ae 6222 /* route-map. */
6223 if (filter->map[RMAP_IN].name)
6224 if (!gfilter || !gfilter->map[RMAP_IN].name
6225 || strcmp(filter->map[RMAP_IN].name,
6226 gfilter->map[RMAP_IN].name)
6227 != 0) {
6228 afi_header_vty_out(vty, afi, safi, write,
6229 " neighbor %s route-map %s in\n",
6230 addr, filter->map[RMAP_IN].name);
6231 }
518f0eb1 6232
d62a17ae 6233 if (filter->map[RMAP_OUT].name)
6234 if (!gfilter || !gfilter->map[RMAP_OUT].name
6235 || strcmp(filter->map[RMAP_OUT].name,
6236 gfilter->map[RMAP_OUT].name)
6237 != 0) {
6238 afi_header_vty_out(vty, afi, safi, write,
6239 " neighbor %s route-map %s out\n",
6240 addr, filter->map[RMAP_OUT].name);
6241 }
718e3744 6242
d62a17ae 6243 /* unsuppress-map */
6244 if (filter->usmap.name && !gfilter) {
6245 afi_header_vty_out(vty, afi, safi, write,
6246 " neighbor %s unsuppress-map %s\n", addr,
6247 filter->usmap.name);
6248 }
718e3744 6249
d62a17ae 6250 /* filter-list. */
6251 if (filter->aslist[in].name)
6252 if (!gfilter || !gfilter->aslist[in].name
6253 || strcmp(filter->aslist[in].name, gfilter->aslist[in].name)
6254 != 0) {
6255 afi_header_vty_out(vty, afi, safi, write,
6256 " neighbor %s filter-list %s in\n",
6257 addr, filter->aslist[in].name);
6258 }
718e3744 6259
d62a17ae 6260 if (filter->aslist[out].name && !gfilter) {
6261 afi_header_vty_out(vty, afi, safi, write,
6262 " neighbor %s filter-list %s out\n", addr,
6263 filter->aslist[out].name);
6264 }
718e3744 6265}
6266
d62a17ae 6267/* BGP peer configuration display function. */
6268static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
6269 struct peer *peer)
6270{
6271 struct peer *g_peer = NULL;
6272 char buf[SU_ADDRSTRLEN];
6273 char *addr;
6274 int if_pg_printed = FALSE;
6275 int if_ras_printed = FALSE;
6276
6277 /* Skip dynamic neighbors. */
6278 if (peer_dynamic_neighbor(peer))
6279 return;
6280
6281 if (peer->conf_if)
6282 addr = peer->conf_if;
6283 else
6284 addr = peer->host;
6285
6286 /************************************
6287 ****** Global to the neighbor ******
6288 ************************************/
6289 if (peer->conf_if) {
6290 if (CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))
6291 vty_out(vty, " neighbor %s interface v6only", addr);
6292 else
6293 vty_out(vty, " neighbor %s interface", addr);
6294
6295 if (peer_group_active(peer)) {
6296 vty_out(vty, " peer-group %s", peer->group->name);
6297 if_pg_printed = TRUE;
6298 } else if (peer->as_type == AS_SPECIFIED) {
6299 vty_out(vty, " remote-as %u", peer->as);
6300 if_ras_printed = TRUE;
6301 } else if (peer->as_type == AS_INTERNAL) {
6302 vty_out(vty, " remote-as internal");
6303 if_ras_printed = TRUE;
6304 } else if (peer->as_type == AS_EXTERNAL) {
6305 vty_out(vty, " remote-as external");
6306 if_ras_printed = TRUE;
6307 }
718e3744 6308
d62a17ae 6309 vty_out(vty, "\n");
6310 }
718e3744 6311
d62a17ae 6312 /* remote-as and peer-group */
6313 /* peer is a member of a peer-group */
6314 if (peer_group_active(peer)) {
6315 g_peer = peer->group->conf;
6316
6317 if (g_peer->as_type == AS_UNSPECIFIED && !if_ras_printed) {
6318 if (peer->as_type == AS_SPECIFIED) {
6319 vty_out(vty, " neighbor %s remote-as %u\n",
6320 addr, peer->as);
6321 } else if (peer->as_type == AS_INTERNAL) {
6322 vty_out(vty,
6323 " neighbor %s remote-as internal\n",
6324 addr);
6325 } else if (peer->as_type == AS_EXTERNAL) {
6326 vty_out(vty,
6327 " neighbor %s remote-as external\n",
6328 addr);
6329 }
6330 }
718e3744 6331
d62a17ae 6332 /* For swpX peers we displayed the peer-group
6333 * via 'neighbor swpX interface peer-group WORD' */
6334 if (!if_pg_printed)
6335 vty_out(vty, " neighbor %s peer-group %s\n", addr,
6336 peer->group->name);
6337 }
718e3744 6338
d62a17ae 6339 /* peer is NOT a member of a peer-group */
6340 else {
6341 /* peer is a peer-group, declare the peer-group */
6342 if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
6343 vty_out(vty, " neighbor %s peer-group\n", addr);
6344 }
6b0655a2 6345
d62a17ae 6346 if (!if_ras_printed) {
6347 if (peer->as_type == AS_SPECIFIED) {
6348 vty_out(vty, " neighbor %s remote-as %u\n",
6349 addr, peer->as);
6350 } else if (peer->as_type == AS_INTERNAL) {
6351 vty_out(vty,
6352 " neighbor %s remote-as internal\n",
6353 addr);
6354 } else if (peer->as_type == AS_EXTERNAL) {
6355 vty_out(vty,
6356 " neighbor %s remote-as external\n",
6357 addr);
6358 }
6359 }
6360 }
718e3744 6361
d62a17ae 6362 /* local-as */
6363 if (peer->change_local_as) {
6364 if (!peer_group_active(peer)
6365 || peer->change_local_as != g_peer->change_local_as
6366 || (CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)
6367 != CHECK_FLAG(g_peer->flags,
6368 PEER_FLAG_LOCAL_AS_NO_PREPEND))
6369 || (CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS)
6370 != CHECK_FLAG(g_peer->flags,
6371 PEER_FLAG_LOCAL_AS_REPLACE_AS))) {
6372 vty_out(vty, " neighbor %s local-as %u%s%s\n", addr,
6373 peer->change_local_as,
6374 CHECK_FLAG(peer->flags,
6375 PEER_FLAG_LOCAL_AS_NO_PREPEND)
6376 ? " no-prepend"
6377 : "",
6378 CHECK_FLAG(peer->flags,
6379 PEER_FLAG_LOCAL_AS_REPLACE_AS)
6380 ? " replace-as"
6381 : "");
6382 }
5f9adb5d 6383 }
5f9adb5d 6384
d62a17ae 6385 /* description */
6386 if (peer->desc) {
6387 vty_out(vty, " neighbor %s description %s\n", addr, peer->desc);
6388 }
fa411a21 6389
d62a17ae 6390 /* shutdown */
6391 if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN)) {
6392 if (!peer_group_active(peer)
6393 || !CHECK_FLAG(g_peer->flags, PEER_FLAG_SHUTDOWN)
6394 || peer->tx_shutdown_message) {
6395 if (peer->tx_shutdown_message)
6396 vty_out(vty,
6397 " neighbor %s shutdown message %s\n",
6398 addr, peer->tx_shutdown_message);
6399 else
6400 vty_out(vty, " neighbor %s shutdown\n", addr);
6401 }
6402 }
fa411a21 6403
d62a17ae 6404 /* bfd */
6405 if (peer->bfd_info) {
6406 if (!peer_group_active(peer) || !g_peer->bfd_info) {
6407 bgp_bfd_peer_config_write(vty, peer, addr);
6408 }
6409 }
e5cc509c 6410
d62a17ae 6411 /* password */
6412 if (peer->password) {
6413 if (!peer_group_active(peer) || !g_peer->password
6414 || strcmp(peer->password, g_peer->password) != 0) {
6415 vty_out(vty, " neighbor %s password %s\n", addr,
6416 peer->password);
6417 }
6418 }
fa411a21 6419
d62a17ae 6420 /* neighbor solo */
6421 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL)) {
6422 if (!peer_group_active(peer)) {
6423 vty_out(vty, " neighbor %s solo\n", addr);
6424 }
6425 }
fa411a21 6426
d62a17ae 6427 /* BGP port */
6428 if (peer->port != BGP_PORT_DEFAULT) {
6429 vty_out(vty, " neighbor %s port %d\n", addr, peer->port);
6430 }
e5cc509c 6431
d62a17ae 6432 /* Local interface name */
6433 if (peer->ifname) {
6434 vty_out(vty, " neighbor %s interface %s\n", addr, peer->ifname);
e5cc509c 6435 }
fa411a21 6436
d62a17ae 6437 /* passive */
6438 if (CHECK_FLAG(peer->flags, PEER_FLAG_PASSIVE)) {
6439 if (!peer_group_active(peer)
6440 || !CHECK_FLAG(g_peer->flags, PEER_FLAG_PASSIVE)) {
6441 vty_out(vty, " neighbor %s passive\n", addr);
6442 }
e5cc509c 6443 }
1ff9a340 6444
d62a17ae 6445 /* ebgp-multihop */
6446 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1
6447 && !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL)) {
6448 if (!peer_group_active(peer) || g_peer->ttl != peer->ttl) {
6449 vty_out(vty, " neighbor %s ebgp-multihop %d\n", addr,
6450 peer->ttl);
6451 }
fa411a21 6452 }
fa411a21 6453
d62a17ae 6454 /* ttl-security hops */
6455 if (peer->gtsm_hops != 0) {
6456 if (!peer_group_active(peer)
6457 || g_peer->gtsm_hops != peer->gtsm_hops) {
6458 vty_out(vty, " neighbor %s ttl-security hops %d\n",
6459 addr, peer->gtsm_hops);
6460 }
6461 }
6462
6463 /* disable-connected-check */
6464 if (CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK)) {
6465 if (!peer_group_active(peer)
6466 || !CHECK_FLAG(g_peer->flags,
6467 PEER_FLAG_DISABLE_CONNECTED_CHECK)) {
6468 vty_out(vty, " neighbor %s disable-connected-check\n",
6469 addr);
6470 }
6471 }
6472
6473 /* update-source */
6474 if (peer->update_if) {
6475 if (!peer_group_active(peer) || !g_peer->update_if
6476 || strcmp(g_peer->update_if, peer->update_if) != 0) {
6477 vty_out(vty, " neighbor %s update-source %s\n", addr,
6478 peer->update_if);
6479 }
6480 }
6481 if (peer->update_source) {
6482 if (!peer_group_active(peer) || !g_peer->update_source
6483 || sockunion_cmp(g_peer->update_source, peer->update_source)
6484 != 0) {
6485 vty_out(vty, " neighbor %s update-source %s\n", addr,
6486 sockunion2str(peer->update_source, buf,
6487 SU_ADDRSTRLEN));
6488 }
6489 }
6490
6491 /* advertisement-interval */
6492 if (CHECK_FLAG(peer->config, PEER_CONFIG_ROUTEADV)
6493 && ((!peer_group_active(peer)
6494 && peer->v_routeadv != BGP_DEFAULT_EBGP_ROUTEADV)
6495 || (peer_group_active(peer)
6496 && peer->v_routeadv != g_peer->v_routeadv))) {
6497 vty_out(vty, " neighbor %s advertisement-interval %u\n", addr,
6498 peer->v_routeadv);
6499 }
6500
6501 /* timers */
6502 if (CHECK_FLAG(peer->config, PEER_CONFIG_TIMER)
6503 && ((!peer_group_active(peer)
6504 && (peer->keepalive != BGP_DEFAULT_KEEPALIVE
6505 || peer->holdtime != BGP_DEFAULT_HOLDTIME))
6506 || (peer_group_active(peer)
6507 && (peer->keepalive != g_peer->keepalive
6508 || peer->holdtime != g_peer->holdtime)))) {
6509 vty_out(vty, " neighbor %s timers %u %u\n", addr,
6510 peer->keepalive, peer->holdtime);
6511 }
6512
6513 if (CHECK_FLAG(peer->config, PEER_CONFIG_CONNECT)
6514 && ((!peer_group_active(peer)
6515 && peer->connect != BGP_DEFAULT_CONNECT_RETRY)
6516 || (peer_group_active(peer)
6517 && peer->connect != g_peer->connect)))
6b0655a2 6518
718e3744 6519 {
d62a17ae 6520 vty_out(vty, " neighbor %s timers connect %u\n", addr,
6521 peer->connect);
718e3744 6522 }
6b0655a2 6523
d62a17ae 6524 /* capability dynamic */
6525 if (CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY)) {
6526 if (!peer_group_active(peer)
6527 || !CHECK_FLAG(g_peer->flags,
6528 PEER_FLAG_DYNAMIC_CAPABILITY)) {
6529 vty_out(vty, " neighbor %s capability dynamic\n", addr);
6530 }
6531 }
718e3744 6532
d62a17ae 6533 /* capability extended-nexthop */
6534 if (peer->ifp && !CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE)) {
6535 if (!peer_group_active(peer)
6536 || !CHECK_FLAG(g_peer->flags, PEER_FLAG_CAPABILITY_ENHE)) {
6537 vty_out(vty,
6538 " no neighbor %s capability extended-nexthop\n",
6539 addr);
6540 }
6541 }
718e3744 6542
d62a17ae 6543 if (!peer->ifp && CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE)) {
6544 if (!peer_group_active(peer)
6545 || !CHECK_FLAG(g_peer->flags, PEER_FLAG_CAPABILITY_ENHE)) {
6546 vty_out(vty,
6547 " neighbor %s capability extended-nexthop\n",
6548 addr);
6549 }
6550 }
6551
6552 /* dont-capability-negotiation */
6553 if (CHECK_FLAG(peer->flags, PEER_FLAG_DONT_CAPABILITY)) {
6554 if (!peer_group_active(peer)
6555 || !CHECK_FLAG(g_peer->flags, PEER_FLAG_DONT_CAPABILITY)) {
6556 vty_out(vty, " neighbor %s dont-capability-negotiate\n",
6557 addr);
6558 }
6559 }
6560
6561 /* override-capability */
6562 if (CHECK_FLAG(peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY)) {
6563 if (!peer_group_active(peer)
6564 || !CHECK_FLAG(g_peer->flags,
6565 PEER_FLAG_OVERRIDE_CAPABILITY)) {
6566 vty_out(vty, " neighbor %s override-capability\n",
6567 addr);
6568 }
6569 }
6570
6571 /* strict-capability-match */
6572 if (CHECK_FLAG(peer->flags, PEER_FLAG_STRICT_CAP_MATCH)) {
6573 if (!peer_group_active(peer)
6574 || !CHECK_FLAG(g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH)) {
6575 vty_out(vty, " neighbor %s strict-capability-match\n",
6576 addr);
6577 }
6578 }
0b960b4d
DW
6579}
6580
0b960b4d 6581/* BGP peer configuration display function. */
d62a17ae 6582static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
6583 struct peer *peer, afi_t afi, safi_t safi,
6584 int *write)
6585{
6586 struct peer *g_peer = NULL;
6587 char *addr;
6588
6589 /* Skip dynamic neighbors. */
6590 if (peer_dynamic_neighbor(peer))
6591 return;
6592
6593 if (peer->conf_if)
6594 addr = peer->conf_if;
6595 else
6596 addr = peer->host;
6597
6598 /************************************
6599 ****** Per AF to the neighbor ******
6600 ************************************/
6601 if (peer_group_active(peer)) {
6602 g_peer = peer->group->conf;
6603
6604 /* If the peer-group is active but peer is not, print a 'no
6605 * activate' */
6606 if (g_peer->afc[afi][safi] && !peer->afc[afi][safi]) {
6607 afi_header_vty_out(vty, afi, safi, write,
6608 " no neighbor %s activate\n", addr);
6609 }
6610
6611 /* If the peer-group is not active but peer is, print an
6612 'activate' */
6613 else if (!g_peer->afc[afi][safi] && peer->afc[afi][safi]) {
6614 afi_header_vty_out(vty, afi, safi, write,
6615 " neighbor %s activate\n", addr);
6616 }
6617 } else {
6618 if (peer->afc[afi][safi]) {
6619 if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) {
6620 if (bgp_flag_check(bgp,
6621 BGP_FLAG_NO_DEFAULT_IPV4)) {
6622 afi_header_vty_out(
6623 vty, afi, safi, write,
6624 " neighbor %s activate\n",
6625 addr);
6626 }
6627 } else
6628 afi_header_vty_out(vty, afi, safi, write,
6629 " neighbor %s activate\n",
6630 addr);
6631 } else {
6632 if ((afi == AFI_IP) && (safi == SAFI_UNICAST)) {
6633 if (!bgp_flag_check(bgp,
6634 BGP_FLAG_NO_DEFAULT_IPV4)) {
6635 afi_header_vty_out(
6636 vty, afi, safi, write,
6637 " no neighbor %s activate\n",
6638 addr);
6639 }
6640 }
6641 }
6642 }
6643
6644 /* addpath TX knobs */
6645 if (peergroup_af_flag_check(peer, afi, safi,
6646 PEER_FLAG_ADDPATH_TX_ALL_PATHS)) {
6647 afi_header_vty_out(vty, afi, safi, write,
6648 " neighbor %s addpath-tx-all-paths\n",
6649 addr);
6650 }
6651
6652 if (peergroup_af_flag_check(peer, afi, safi,
6653 PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)) {
6654 afi_header_vty_out(vty, afi, safi, write,
6655 " neighbor %s addpath-tx-bestpath-per-AS\n",
6656 addr);
6657 }
6658
6659 /* ORF capability. */
6660 if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM)
6661 || peergroup_af_flag_check(peer, afi, safi,
6662 PEER_FLAG_ORF_PREFIX_RM)) {
6663 afi_header_vty_out(vty, afi, safi, write,
6664 " neighbor %s capability orf prefix-list",
6665 addr);
6666
6667 if (peergroup_af_flag_check(peer, afi, safi,
6668 PEER_FLAG_ORF_PREFIX_SM)
6669 && peergroup_af_flag_check(peer, afi, safi,
6670 PEER_FLAG_ORF_PREFIX_RM))
6671 vty_out(vty, " both");
6672 else if (peergroup_af_flag_check(peer, afi, safi,
6673 PEER_FLAG_ORF_PREFIX_SM))
6674 vty_out(vty, " send");
6675 else
6676 vty_out(vty, " receive");
6677 vty_out(vty, "\n");
6678 }
6679
6680 /* Route reflector client. */
6681 if (peergroup_af_flag_check(peer, afi, safi,
6682 PEER_FLAG_REFLECTOR_CLIENT)) {
6683 afi_header_vty_out(vty, afi, safi, write,
6684 " neighbor %s route-reflector-client\n",
6685 addr);
6686 }
6687
6688 /* next-hop-self force */
6689 if (peergroup_af_flag_check(peer, afi, safi,
6690 PEER_FLAG_FORCE_NEXTHOP_SELF)) {
6691 afi_header_vty_out(vty, afi, safi, write,
6692 " neighbor %s next-hop-self force\n", addr);
6693 }
6694
6695 /* next-hop-self */
6696 if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)) {
6697 afi_header_vty_out(vty, afi, safi, write,
6698 " neighbor %s next-hop-self\n", addr);
6699 }
6700
6701 /* remove-private-AS */
6702 if (peergroup_af_flag_check(peer, afi, safi,
6703 PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE)) {
6704 afi_header_vty_out(
6705 vty, afi, safi, write,
6706 " neighbor %s remove-private-AS all replace-AS\n",
6707 addr);
6708 }
6709
6710 else if (peergroup_af_flag_check(peer, afi, safi,
6711 PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE)) {
6712 afi_header_vty_out(
6713 vty, afi, safi, write,
6714 " neighbor %s remove-private-AS replace-AS\n", addr);
6715 }
6716
6717 else if (peergroup_af_flag_check(peer, afi, safi,
6718 PEER_FLAG_REMOVE_PRIVATE_AS_ALL)) {
6719 afi_header_vty_out(vty, afi, safi, write,
6720 " neighbor %s remove-private-AS all\n",
6721 addr);
6722 }
6723
6724 else if (peergroup_af_flag_check(peer, afi, safi,
6725 PEER_FLAG_REMOVE_PRIVATE_AS)) {
6726 afi_header_vty_out(vty, afi, safi, write,
6727 " neighbor %s remove-private-AS\n", addr);
6728 }
6729
6730 /* as-override */
6731 if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
6732 afi_header_vty_out(vty, afi, safi, write,
6733 " neighbor %s as-override\n", addr);
6734 }
6735
6736 /* send-community print. */
6737 if (bgp_option_check(BGP_OPT_CONFIG_CISCO)) {
6738 if (peergroup_af_flag_check(peer, afi, safi,
6739 PEER_FLAG_SEND_COMMUNITY)
6740 && peergroup_af_flag_check(peer, afi, safi,
6741 PEER_FLAG_SEND_EXT_COMMUNITY)
6742 && peergroup_af_flag_check(
6743 peer, afi, safi,
6744 PEER_FLAG_SEND_LARGE_COMMUNITY)) {
6745 afi_header_vty_out(vty, afi, safi, write,
6746 " neighbor %s send-community all\n",
6747 addr);
6748 } else if (peergroup_af_flag_check(
6749 peer, afi, safi,
6750 PEER_FLAG_SEND_LARGE_COMMUNITY)) {
6751 afi_header_vty_out(
6752 vty, afi, safi, write,
6753 " neighbor %s send-community large\n", addr);
6754 } else if (peergroup_af_flag_check(
6755 peer, afi, safi,
6756 PEER_FLAG_SEND_EXT_COMMUNITY)) {
6757 afi_header_vty_out(
6758 vty, afi, safi, write,
6759 " neighbor %s send-community extended\n",
6760 addr);
6761 } else if (peergroup_af_flag_check(peer, afi, safi,
6762 PEER_FLAG_SEND_COMMUNITY)) {
6763 afi_header_vty_out(vty, afi, safi, write,
6764 " neighbor %s send-community\n",
6765 addr);
6766 }
6767 } else {
6768 if (!peer_af_flag_check(peer, afi, safi,
6769 PEER_FLAG_SEND_COMMUNITY)
9d303b37
DL
6770 && (!g_peer || peer_af_flag_check(g_peer, afi, safi,
6771 PEER_FLAG_SEND_COMMUNITY))
d62a17ae 6772 && !peer_af_flag_check(peer, afi, safi,
6773 PEER_FLAG_SEND_EXT_COMMUNITY)
6774 && (!g_peer
6775 || peer_af_flag_check(g_peer, afi, safi,
6776 PEER_FLAG_SEND_EXT_COMMUNITY))
6777 && !peer_af_flag_check(peer, afi, safi,
6778 PEER_FLAG_SEND_LARGE_COMMUNITY)
9d303b37
DL
6779 && (!g_peer || peer_af_flag_check(
6780 g_peer, afi, safi,
6781 PEER_FLAG_SEND_LARGE_COMMUNITY))) {
d62a17ae 6782 afi_header_vty_out(
6783 vty, afi, safi, write,
6784 " no neighbor %s send-community all\n", addr);
6785 } else {
6786 if (!peer_af_flag_check(peer, afi, safi,
6787 PEER_FLAG_SEND_LARGE_COMMUNITY)
6788 && (!g_peer
6789 || peer_af_flag_check(
6790 g_peer, afi, safi,
6791 PEER_FLAG_SEND_LARGE_COMMUNITY))) {
6792 afi_header_vty_out(
6793 vty, afi, safi, write,
6794 " no neighbor %s send-community large\n",
6795 addr);
6796 }
6797
6798 if (!peer_af_flag_check(peer, afi, safi,
6799 PEER_FLAG_SEND_EXT_COMMUNITY)
6800 && (!g_peer
6801 || peer_af_flag_check(
6802 g_peer, afi, safi,
6803 PEER_FLAG_SEND_EXT_COMMUNITY))) {
6804 afi_header_vty_out(
6805 vty, afi, safi, write,
6806 " no neighbor %s send-community extended\n",
6807 addr);
6808 }
6809
6810 if (!peer_af_flag_check(peer, afi, safi,
6811 PEER_FLAG_SEND_COMMUNITY)
9d303b37
DL
6812 && (!g_peer || peer_af_flag_check(
6813 g_peer, afi, safi,
6814 PEER_FLAG_SEND_COMMUNITY))) {
d62a17ae 6815 afi_header_vty_out(
6816 vty, afi, safi, write,
6817 " no neighbor %s send-community\n",
6818 addr);
6819 }
6820 }
6821 }
6822
6823 /* Default information */
6824 if (peergroup_af_flag_check(peer, afi, safi,
6825 PEER_FLAG_DEFAULT_ORIGINATE)
6826 || (g_peer
6827 && ((peer->default_rmap[afi][safi].name
6828 && !g_peer->default_rmap[afi][safi].name)
6829 || (!peer->default_rmap[afi][safi].name
6830 && g_peer->default_rmap[afi][safi].name)
6831 || (peer->default_rmap[afi][safi].name
6832 && strcmp(peer->default_rmap[afi][safi].name,
6833 g_peer->default_rmap[afi][safi].name))))) {
6834 afi_header_vty_out(vty, afi, safi, write,
6835 " neighbor %s default-originate", addr);
6836 if (peer->default_rmap[afi][safi].name)
6837 vty_out(vty, " route-map %s",
6838 peer->default_rmap[afi][safi].name);
6839 vty_out(vty, "\n");
6840 }
6841
6842 /* Soft reconfiguration inbound. */
6843 if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_SOFT_RECONFIG)) {
6844 afi_header_vty_out(
6845 vty, afi, safi, write,
6846 " neighbor %s soft-reconfiguration inbound\n", addr);
6847 }
6848
6849 /* maximum-prefix. */
6850 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
6851 if (!peer_group_active(peer)
6852 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
6853 || g_peer->pmax_threshold[afi][safi]
6854 != peer->pmax_threshold[afi][safi]
6855 || CHECK_FLAG(g_peer->af_flags[afi][safi],
6856 PEER_FLAG_MAX_PREFIX_WARNING)
6857 != CHECK_FLAG(peer->af_flags[afi][safi],
6858 PEER_FLAG_MAX_PREFIX_WARNING)) {
6859 afi_header_vty_out(vty, afi, safi, write,
6860 " neighbor %s maximum-prefix %lu",
6861 addr, peer->pmax[afi][safi]);
6862 if (peer->pmax_threshold[afi][safi]
6863 != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
6864 vty_out(vty, " %u",
6865 peer->pmax_threshold[afi][safi]);
6866 if (CHECK_FLAG(peer->af_flags[afi][safi],
6867 PEER_FLAG_MAX_PREFIX_WARNING))
6868 vty_out(vty, " warning-only");
6869 if (peer->pmax_restart[afi][safi])
6870 vty_out(vty, " restart %u",
6871 peer->pmax_restart[afi][safi]);
6872 vty_out(vty, "\n");
6873 }
6874
6875 /* Route server client. */
6876 if (peergroup_af_flag_check(peer, afi, safi,
6877 PEER_FLAG_RSERVER_CLIENT)) {
6878 afi_header_vty_out(vty, afi, safi, write,
6879 " neighbor %s route-server-client\n", addr);
6880 }
6881
6882 /* Nexthop-local unchanged. */
6883 if (peergroup_af_flag_check(peer, afi, safi,
6884 PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)) {
6885 afi_header_vty_out(vty, afi, safi, write,
6886 " neighbor %s nexthop-local unchanged\n",
6887 addr);
6888 }
6889
6890 /* allowas-in <1-10> */
6891 if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_ALLOWAS_IN)) {
6892 if (!peer_group_active(peer)
6893 || !peer_af_flag_check(g_peer, afi, safi,
6894 PEER_FLAG_ALLOWAS_IN)
6895 || peer->allowas_in[afi][safi]
6896 != g_peer->allowas_in[afi][safi]) {
6897 if (peer->allowas_in[afi][safi] == 3) {
6898 afi_header_vty_out(vty, afi, safi, write,
6899 " neighbor %s allowas-in\n",
6900 addr);
6901 } else {
6902 afi_header_vty_out(
6903 vty, afi, safi, write,
6904 " neighbor %s allowas-in %d\n", addr,
6905 peer->allowas_in[afi][safi]);
6906 }
6907 }
6908 }
6909
6910 /* allowas-in origin */
6911 else if (peer_af_flag_check(peer, afi, safi,
6912 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
6913 if (!peer_group_active(peer)
6914 || !peer_af_flag_check(g_peer, afi, safi,
6915 PEER_FLAG_ALLOWAS_IN_ORIGIN)) {
6916 afi_header_vty_out(vty, afi, safi, write,
6917 " neighbor %s allowas-in origin\n",
6918 addr);
6919 }
6920 }
6921
6922 /* weight */
6923 if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_WEIGHT))
6924 if (!peer_group_active(peer)
6925 || !peer_af_flag_check(g_peer, afi, safi, PEER_FLAG_WEIGHT)
6926 || peer->weight[afi][safi] != g_peer->weight[afi][safi]) {
6927 if (peer->weight[afi][safi]) {
6928 afi_header_vty_out(vty, afi, safi, write,
6929 " neighbor %s weight %lu\n",
6930 addr,
6931 peer->weight[afi][safi]);
6932 }
6933 }
6934
6935 /* Filter. */
6936 bgp_config_write_filter(vty, peer, afi, safi, write);
6937
6938 /* atribute-unchanged. */
8eeb0335
DW
6939 if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED) ||
6940 peer_af_flag_check(peer, afi, safi, PEER_FLAG_NEXTHOP_UNCHANGED) ||
6941 peer_af_flag_check(peer, afi, safi, PEER_FLAG_MED_UNCHANGED)) {
6942
6943 if (!peer_group_active(peer) ||
6944 peergroup_af_flag_check(peer, afi, safi,
6945 PEER_FLAG_AS_PATH_UNCHANGED) ||
6946 peergroup_af_flag_check(peer, afi, safi,
6947 PEER_FLAG_NEXTHOP_UNCHANGED) ||
6948 peergroup_af_flag_check(peer, afi, safi,
6949 PEER_FLAG_MED_UNCHANGED)) {
6950
d62a17ae 6951 afi_header_vty_out(
6952 vty, afi, safi, write,
6953 " neighbor %s attribute-unchanged%s%s%s\n",
6954 addr,
8eeb0335 6955 peer_af_flag_check(
d62a17ae 6956 peer, afi, safi,
6957 PEER_FLAG_AS_PATH_UNCHANGED)
6958 ? " as-path"
6959 : "",
8eeb0335 6960 peer_af_flag_check(
d62a17ae 6961 peer, afi, safi,
6962 PEER_FLAG_NEXTHOP_UNCHANGED)
6963 ? " next-hop"
6964 : "",
8eeb0335
DW
6965 peer_af_flag_check(peer, afi, safi,
6966 PEER_FLAG_MED_UNCHANGED)
d62a17ae 6967 ? " med"
6968 : "");
6969 }
6970 }
718e3744 6971}
6972
6973/* Display "address-family" configuration header. */
d62a17ae 6974void bgp_config_write_family_header(struct vty *vty, afi_t afi, safi_t safi,
6975 int *write)
6976{
6977 if (*write)
6978 return;
6979
6980 vty_out(vty, " !\n address-family ");
6981
6982 if (afi == AFI_IP) {
6983 if (safi == SAFI_UNICAST)
6984 vty_out(vty, "ipv4 unicast");
6985 else if (safi == SAFI_LABELED_UNICAST)
6986 vty_out(vty, "ipv4 labeled-unicast");
6987 else if (safi == SAFI_MULTICAST)
6988 vty_out(vty, "ipv4 multicast");
6989 else if (safi == SAFI_MPLS_VPN)
6990 vty_out(vty, "ipv4 vpn");
6991 else if (safi == SAFI_ENCAP)
6992 vty_out(vty, "ipv4 encap");
6993 } else if (afi == AFI_IP6) {
6994 if (safi == SAFI_UNICAST)
6995 vty_out(vty, "ipv6 unicast");
6996 else if (safi == SAFI_LABELED_UNICAST)
6997 vty_out(vty, "ipv6 labeled-unicast");
6998 else if (safi == SAFI_MULTICAST)
6999 vty_out(vty, "ipv6 multicast");
7000 else if (safi == SAFI_MPLS_VPN)
7001 vty_out(vty, "ipv6 vpn");
7002 else if (safi == SAFI_ENCAP)
7003 vty_out(vty, "ipv6 encap");
7004 } else if (afi == AFI_L2VPN) {
7005 if (safi == SAFI_EVPN)
7006 vty_out(vty, "l2vpn evpn");
7007 }
7008 vty_out(vty, "\n");
7009
7010 *write = 1;
718e3744 7011}
7012
7013/* Address family based peer configuration display. */
d62a17ae 7014static int bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
7015 safi_t safi)
718e3744 7016{
d62a17ae 7017 int write = 0;
7018 struct peer *peer;
7019 struct peer_group *group;
7020 struct listnode *node, *nnode;
718e3744 7021
d62a17ae 7022 bgp_config_write_distance(vty, bgp, afi, safi, &write);
734b349e 7023
d62a17ae 7024 bgp_config_write_network(vty, bgp, afi, safi, &write);
718e3744 7025
d62a17ae 7026 bgp_config_write_redistribute(vty, bgp, afi, safi, &write);
718e3744 7027
d62a17ae 7028 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group))
7029 bgp_config_write_peer_af(vty, bgp, group->conf, afi, safi,
7030 &write);
400b1fad 7031
d62a17ae 7032 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
7033 /* Skip dynamic neighbors. */
7034 if (peer_dynamic_neighbor(peer))
7035 continue;
f14e6fdb 7036
d62a17ae 7037 /* Do not display doppelganger peers */
7038 if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
7039 bgp_config_write_peer_af(vty, bgp, peer, afi, safi,
7040 &write);
7041 }
165b5fff 7042
d62a17ae 7043 bgp_config_write_maxpaths(vty, bgp, afi, safi, &write);
7044 bgp_config_write_table_map(vty, bgp, afi, safi, &write);
165b5fff 7045
d62a17ae 7046 if (safi == SAFI_EVPN)
7047 bgp_config_write_evpn_info(vty, bgp, afi, safi, &write);
90e60aa7 7048
d62a17ae 7049 if (write)
7050 vty_out(vty, " exit-address-family\n");
718e3744 7051
d62a17ae 7052 return write;
718e3744 7053}
7054
d62a17ae 7055int bgp_config_write(struct vty *vty)
718e3744 7056{
d62a17ae 7057 int write = 0;
7058 struct bgp *bgp;
7059 struct peer_group *group;
7060 struct peer *peer;
7061 struct listnode *node, *nnode;
7062 struct listnode *mnode, *mnnode;
718e3744 7063
d62a17ae 7064 /* BGP Multiple instance. */
7065 if (!bgp_option_check(BGP_OPT_MULTIPLE_INSTANCE)) {
7066 vty_out(vty, "no bgp multiple-instance\n");
7067 write++;
7068 }
718e3744 7069
d62a17ae 7070 /* BGP Config type. */
7071 if (bgp_option_check(BGP_OPT_CONFIG_CISCO)) {
7072 vty_out(vty, "bgp config-type cisco\n");
7073 write++;
7074 }
718e3744 7075
d62a17ae 7076 if (bm->rmap_update_timer != RMAP_DEFAULT_UPDATE_TIMER)
7077 vty_out(vty, "bgp route-map delay-timer %u\n",
7078 bm->rmap_update_timer);
7079
7080 /* BGP configuration. */
7081 for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
7082 if (write)
7083 vty_out(vty, "!\n");
7084
7085 /* Router bgp ASN */
7086 vty_out(vty, "router bgp %u", bgp->as);
7087
7088 if (bgp_option_check(BGP_OPT_MULTIPLE_INSTANCE)) {
7089 if (bgp->name)
7090 vty_out(vty, " %s %s",
7091 (bgp->inst_type
7092 == BGP_INSTANCE_TYPE_VIEW)
7093 ? "view"
7094 : "vrf",
7095 bgp->name);
7096 }
7097 vty_out(vty, "\n");
7098
7099 /* No Synchronization */
7100 if (bgp_option_check(BGP_OPT_CONFIG_CISCO))
7101 vty_out(vty, " no synchronization\n");
7102
7103 /* BGP fast-external-failover. */
7104 if (CHECK_FLAG(bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
7105 vty_out(vty, " no bgp fast-external-failover\n");
7106
7107 /* BGP router ID. */
7108 if (bgp->router_id_static.s_addr != 0)
7109 vty_out(vty, " bgp router-id %s\n",
7110 inet_ntoa(bgp->router_id_static));
7111
7112 /* BGP log-neighbor-changes. */
7113 if (!!bgp_flag_check(bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES)
7114 != DFLT_BGP_LOG_NEIGHBOR_CHANGES)
7115 vty_out(vty, " %sbgp log-neighbor-changes\n",
7116 bgp_flag_check(bgp,
7117 BGP_FLAG_LOG_NEIGHBOR_CHANGES)
7118 ? ""
7119 : "no ");
7120
7121 /* BGP configuration. */
7122 if (bgp_flag_check(bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
7123 vty_out(vty, " bgp always-compare-med\n");
7124
7125 /* BGP default ipv4-unicast. */
7126 if (bgp_flag_check(bgp, BGP_FLAG_NO_DEFAULT_IPV4))
7127 vty_out(vty, " no bgp default ipv4-unicast\n");
7128
7129 /* BGP default local-preference. */
7130 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
7131 vty_out(vty, " bgp default local-preference %u\n",
7132 bgp->default_local_pref);
7133
7134 /* BGP default show-hostname */
7135 if (!!bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME)
7136 != DFLT_BGP_SHOW_HOSTNAME)
7137 vty_out(vty, " %sbgp default show-hostname\n",
7138 bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME)
7139 ? ""
7140 : "no ");
7141
7142 /* BGP default subgroup-pkt-queue-max. */
7143 if (bgp->default_subgroup_pkt_queue_max
7144 != BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX)
7145 vty_out(vty, " bgp default subgroup-pkt-queue-max %u\n",
7146 bgp->default_subgroup_pkt_queue_max);
7147
7148 /* BGP client-to-client reflection. */
7149 if (bgp_flag_check(bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
7150 vty_out(vty, " no bgp client-to-client reflection\n");
7151
7152 /* BGP cluster ID. */
7153 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CLUSTER_ID))
7154 vty_out(vty, " bgp cluster-id %s\n",
7155 inet_ntoa(bgp->cluster_id));
7156
7157 /* Disable ebgp connected nexthop check */
7158 if (bgp_flag_check(bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
7159 vty_out(vty,
7160 " bgp disable-ebgp-connected-route-check\n");
7161
7162 /* Confederation identifier*/
7163 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION))
7164 vty_out(vty, " bgp confederation identifier %i\n",
7165 bgp->confed_id);
7166
7167 /* Confederation peer */
7168 if (bgp->confed_peers_cnt > 0) {
7169 int i;
7170
7171 vty_out(vty, " bgp confederation peers");
7172
7173 for (i = 0; i < bgp->confed_peers_cnt; i++)
7174 vty_out(vty, " %u", bgp->confed_peers[i]);
7175
7176 vty_out(vty, "\n");
7177 }
5fe9f963 7178
d62a17ae 7179 /* BGP enforce-first-as. */
7180 if (bgp_flag_check(bgp, BGP_FLAG_ENFORCE_FIRST_AS))
7181 vty_out(vty, " bgp enforce-first-as\n");
7182
7183 /* BGP deterministic-med. */
7184 if (!!bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)
7185 != DFLT_BGP_DETERMINISTIC_MED)
7186 vty_out(vty, " %sbgp deterministic-med\n",
7187 bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)
7188 ? ""
7189 : "no ");
7190
7191 /* BGP update-delay. */
7192 bgp_config_write_update_delay(vty, bgp);
7193
7194 if (bgp->v_maxmed_onstartup
7195 != BGP_MAXMED_ONSTARTUP_UNCONFIGURED) {
7196 vty_out(vty, " bgp max-med on-startup %u",
7197 bgp->v_maxmed_onstartup);
7198 if (bgp->maxmed_onstartup_value
7199 != BGP_MAXMED_VALUE_DEFAULT)
7200 vty_out(vty, " %u",
7201 bgp->maxmed_onstartup_value);
7202 vty_out(vty, "\n");
7203 }
7204 if (bgp->v_maxmed_admin != BGP_MAXMED_ADMIN_UNCONFIGURED) {
7205 vty_out(vty, " bgp max-med administrative");
7206 if (bgp->maxmed_admin_value != BGP_MAXMED_VALUE_DEFAULT)
7207 vty_out(vty, " %u", bgp->maxmed_admin_value);
7208 vty_out(vty, "\n");
7209 }
718e3744 7210
d62a17ae 7211 /* write quanta */
7212 bgp_config_write_wpkt_quanta(vty, bgp);
7213
7214 /* coalesce time */
7215 bgp_config_write_coalesce_time(vty, bgp);
7216
7217 /* BGP graceful-restart. */
7218 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
7219 vty_out(vty,
7220 " bgp graceful-restart stalepath-time %u\n",
7221 bgp->stalepath_time);
7222 if (bgp->restart_time != BGP_DEFAULT_RESTART_TIME)
7223 vty_out(vty, " bgp graceful-restart restart-time %u\n",
7224 bgp->restart_time);
7225 if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_RESTART))
7226 vty_out(vty, " bgp graceful-restart\n");
7227
7228 /* BGP graceful-restart Preserve State F bit. */
7229 if (bgp_flag_check(bgp, BGP_FLAG_GR_PRESERVE_FWD))
7230 vty_out(vty,
7231 " bgp graceful-restart preserve-fw-state\n");
7232
7233 /* BGP bestpath method. */
7234 if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_IGNORE))
7235 vty_out(vty, " bgp bestpath as-path ignore\n");
7236 if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_CONFED))
7237 vty_out(vty, " bgp bestpath as-path confed\n");
7238
7239 if (bgp_flag_check(bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
7240 if (bgp_flag_check(bgp,
7241 BGP_FLAG_MULTIPATH_RELAX_AS_SET)) {
7242 vty_out(vty,
7243 " bgp bestpath as-path multipath-relax as-set\n");
7244 } else {
7245 vty_out(vty,
7246 " bgp bestpath as-path multipath-relax\n");
7247 }
7248 }
718e3744 7249
d62a17ae 7250 if (bgp_flag_check(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
7251 vty_out(vty,
7252 " bgp route-reflector allow-outbound-policy\n");
7253 }
7254 if (bgp_flag_check(bgp, BGP_FLAG_COMPARE_ROUTER_ID))
7255 vty_out(vty, " bgp bestpath compare-routerid\n");
7256 if (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED)
7257 || bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST)) {
7258 vty_out(vty, " bgp bestpath med");
7259 if (bgp_flag_check(bgp, BGP_FLAG_MED_CONFED))
7260 vty_out(vty, " confed");
7261 if (bgp_flag_check(bgp, BGP_FLAG_MED_MISSING_AS_WORST))
7262 vty_out(vty, " missing-as-worst");
7263 vty_out(vty, "\n");
7264 }
718e3744 7265
d62a17ae 7266 /* BGP network import check. */
7267 if (!!bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
7268 != DFLT_BGP_IMPORT_CHECK)
7269 vty_out(vty, " %sbgp network import-check\n",
7270 bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK)
7271 ? ""
7272 : "no ");
7273
7274 /* BGP flag dampening. */
7275 if (CHECK_FLAG(bgp->af_flags[AFI_IP][SAFI_UNICAST],
7276 BGP_CONFIG_DAMPENING))
7277 bgp_config_write_damp(vty);
7278
7279 /* BGP timers configuration. */
7280 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
7281 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
7282 vty_out(vty, " timers bgp %u %u\n",
7283 bgp->default_keepalive, bgp->default_holdtime);
7284
7285 /* peer-group */
7286 for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
7287 bgp_config_write_peer_global(vty, bgp, group->conf);
7288 }
7289
7290 /* Normal neighbor configuration. */
7291 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
7292 if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
7293 bgp_config_write_peer_global(vty, bgp, peer);
7294 }
718e3744 7295
d62a17ae 7296 /* listen range and limit for dynamic BGP neighbors */
7297 bgp_config_write_listen(vty, bgp);
f14e6fdb 7298
d62a17ae 7299 /* No auto-summary */
7300 if (bgp_option_check(BGP_OPT_CONFIG_CISCO))
7301 vty_out(vty, " no auto-summary\n");
718e3744 7302
d62a17ae 7303 /* IPv4 unicast configuration. */
7304 write +=
7305 bgp_config_write_family(vty, bgp, AFI_IP, SAFI_UNICAST);
0b960b4d 7306
d62a17ae 7307 /* IPv4 multicast configuration. */
7308 write += bgp_config_write_family(vty, bgp, AFI_IP,
7309 SAFI_MULTICAST);
718e3744 7310
d62a17ae 7311 /* IPv4 labeled-unicast configuration. */
7312 write += bgp_config_write_family(vty, bgp, AFI_IP,
7313 SAFI_LABELED_UNICAST);
f51bae9c 7314
d62a17ae 7315 /* IPv4 VPN configuration. */
7316 write += bgp_config_write_family(vty, bgp, AFI_IP,
7317 SAFI_MPLS_VPN);
718e3744 7318
d62a17ae 7319 /* ENCAPv4 configuration. */
7320 write += bgp_config_write_family(vty, bgp, AFI_IP, SAFI_ENCAP);
8b1fb8be 7321
d62a17ae 7322 /* IPv6 unicast configuration. */
7323 write += bgp_config_write_family(vty, bgp, AFI_IP6,
7324 SAFI_UNICAST);
718e3744 7325
d62a17ae 7326 /* IPv6 multicast configuration. */
7327 write += bgp_config_write_family(vty, bgp, AFI_IP6,
7328 SAFI_MULTICAST);
37a217a5 7329
d62a17ae 7330 /* IPv6 labeled-unicast configuration. */
7331 write += bgp_config_write_family(vty, bgp, AFI_IP6,
7332 SAFI_LABELED_UNICAST);
f51bae9c 7333
d62a17ae 7334 /* IPv6 VPN configuration. */
7335 write += bgp_config_write_family(vty, bgp, AFI_IP6,
7336 SAFI_MPLS_VPN);
8ecd3266 7337
d62a17ae 7338 /* ENCAPv6 configuration. */
7339 write += bgp_config_write_family(vty, bgp, AFI_IP6, SAFI_ENCAP);
8b1fb8be 7340
d62a17ae 7341 /* EVPN configuration. */
7342 write +=
7343 bgp_config_write_family(vty, bgp, AFI_L2VPN, SAFI_EVPN);
3d6c0dfa 7344
65efcfce 7345#if ENABLE_BGP_VNC
d62a17ae 7346 write += bgp_rfapi_cfg_write(vty, bgp);
65efcfce
LB
7347#endif
7348
d62a17ae 7349 write++;
7350 }
7351 return write;
718e3744 7352}
7353
d62a17ae 7354void bgp_master_init(struct thread_master *master)
718e3744 7355{
d62a17ae 7356 qobj_init();
0e64d123 7357
d62a17ae 7358 memset(&bgp_master, 0, sizeof(struct bgp_master));
718e3744 7359
d62a17ae 7360 bm = &bgp_master;
7361 bm->bgp = list_new();
7362 bm->listen_sockets = list_new();
7363 bm->port = BGP_PORT_DEFAULT;
7364 bm->master = master;
7365 bm->start_time = bgp_clock();
7366 bm->t_rmap_update = NULL;
7367 bm->rmap_update_timer = RMAP_DEFAULT_UPDATE_TIMER;
495f0b13 7368
d62a17ae 7369 bgp_process_queue_init();
b8fd6a15 7370
d62a17ae 7371 /* Enable multiple instances by default. */
7372 bgp_option_set(BGP_OPT_MULTIPLE_INSTANCE);
19df7279 7373
d62a17ae 7374 QOBJ_REG(bm, bgp_master);
718e3744 7375}
200df115 7376
ad4cbda1 7377/*
009b18fc 7378 * Free up connected routes and interfaces for a BGP instance. Invoked upon
7379 * instance delete (non-default only) or BGP exit.
ad4cbda1 7380 */
d62a17ae 7381static void bgp_if_finish(struct bgp *bgp)
ad4cbda1 7382{
d62a17ae 7383 struct listnode *ifnode, *ifnnode;
7384 struct interface *ifp;
7385
7386 if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
7387 return;
ad4cbda1 7388
d62a17ae 7389 for (ALL_LIST_ELEMENTS(vrf_iflist(bgp->vrf_id), ifnode, ifnnode, ifp)) {
7390 struct listnode *c_node, *c_nnode;
7391 struct connected *c;
ad4cbda1 7392
d62a17ae 7393 for (ALL_LIST_ELEMENTS(ifp->connected, c_node, c_nnode, c))
7394 bgp_connected_delete(bgp, c);
7395 }
ad4cbda1 7396}
6b0655a2 7397
d62a17ae 7398extern void bgp_snmp_init(void);
3012671f 7399
d62a17ae 7400static void bgp_viewvrf_autocomplete(vector comps, struct cmd_token *token)
18c57037 7401{
d62a17ae 7402 struct vrf *vrf = NULL;
7403 struct listnode *next;
7404 struct bgp *bgp;
18c57037 7405
d62a17ae 7406 RB_FOREACH(vrf, vrf_name_head, &vrfs_by_name)
7407 {
7408 if (vrf->vrf_id != VRF_DEFAULT)
7409 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, vrf->name));
7410 }
18c57037 7411
d62a17ae 7412 for (ALL_LIST_ELEMENTS_RO(bm->bgp, next, bgp)) {
7413 if (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
7414 continue;
18c57037 7415
d62a17ae 7416 vector_set(comps, XSTRDUP(MTYPE_COMPLETION, bgp->name));
7417 }
18c57037
DS
7418}
7419
7420static const struct cmd_variable_handler bgp_viewvrf_var_handlers[] = {
d62a17ae 7421 {.tokenname = "VIEWVRFNAME", .completions = bgp_viewvrf_autocomplete},
7422 {.completions = NULL},
18c57037
DS
7423};
7424
d62a17ae 7425void bgp_init(void)
718e3744 7426{
fc9a856f 7427
d62a17ae 7428 /* allocates some vital data structures used by peer commands in
7429 * vty_init */
718e3744 7430
d62a17ae 7431 /* Init zebra. */
7432 bgp_zebra_init(bm->master);
718e3744 7433
65efcfce 7434#if ENABLE_BGP_VNC
d62a17ae 7435 vnc_zebra_init(bm->master);
65efcfce
LB
7436#endif
7437
d62a17ae 7438 /* BGP VTY commands installation. */
7439 bgp_vty_init();
7440
7441 /* BGP inits. */
7442 bgp_attr_init();
7443 bgp_debug_init();
7444 bgp_dump_init();
7445 bgp_route_init();
7446 bgp_route_map_init();
7447 bgp_scan_vty_init();
7448 bgp_mplsvpn_init();
65efcfce 7449#if ENABLE_BGP_VNC
d62a17ae 7450 rfapi_init();
65efcfce 7451#endif
d62a17ae 7452 bgp_ethernetvpn_init();
7453
7454 /* Access list initialize. */
7455 access_list_init();
7456 access_list_add_hook(peer_distribute_update);
7457 access_list_delete_hook(peer_distribute_update);
7458
7459 /* Filter list initialize. */
7460 bgp_filter_init();
7461 as_list_add_hook(peer_aslist_add);
7462 as_list_delete_hook(peer_aslist_del);
7463
7464 /* Prefix list initialize.*/
7465 prefix_list_init();
7466 prefix_list_add_hook(peer_prefix_list_update);
7467 prefix_list_delete_hook(peer_prefix_list_update);
7468
7469 /* Community list initialize. */
7470 bgp_clist = community_list_init();
7471
7472 /* BFD init */
7473 bgp_bfd_init();
7474
7475 cmd_variable_handler_register(bgp_viewvrf_var_handlers);
7476}
7477
7478void bgp_terminate(void)
7479{
7480 struct bgp *bgp;
7481 struct peer *peer;
7482 struct listnode *node, *nnode;
7483 struct listnode *mnode, *mnnode;
7484
7485 QOBJ_UNREG(bm);
7486
7487 /* Close the listener sockets first as this prevents peers from
7488 * attempting
7489 * to reconnect on receiving the peer unconfig message. In the presence
7490 * of a large number of peers this will ensure that no peer is left with
7491 * a dangling connection
7492 */
7493 /* reverse bgp_master_init */
7494 bgp_close();
7495 if (bm->listen_sockets)
7496 list_free(bm->listen_sockets);
7497 bm->listen_sockets = NULL;
7498
7499 for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp))
7500 for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
7501 if (peer->status == Established
7502 || peer->status == OpenSent
7503 || peer->status == OpenConfirm)
7504 bgp_notify_send(peer, BGP_NOTIFY_CEASE,
7505 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
7506
7507 if (bm->process_main_queue) {
7508 work_queue_free(bm->process_main_queue);
7509 bm->process_main_queue = NULL;
7510 }
7511
7512 if (bm->t_rmap_update)
7513 BGP_TIMER_OFF(bm->t_rmap_update);
545acafb 7514}