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