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