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