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