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