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