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