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