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