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