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