]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgpd.c
bgpd: wire up VPNv6 protocol processing
[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 }
04b6bdc0 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{
2489 struct prefix *prefix, *prefix2;
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
2515 prefix2 = sockunion2hostprefix(&peer->su);
2516 if (prefix_match(prefix, prefix2))
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
7cb43556 3047 THREAD_OFF (bgp->t_startup);
3048
ad4cbda1 3049 if (BGP_DEBUG (zebra, ZEBRA))
3050 {
3051 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
3052 zlog_debug("Deleting Default VRF");
3053 else
3054 zlog_debug("Deleting %s %s",
3055 (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) ? "VRF" : "VIEW",
3056 bgp->name);
3057 }
3058
3059 /* Stop timers. */
ad4cbda1 3060 if (bgp->t_rmap_def_originate_eval)
3061 {
3062 BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval);
3063 bgp_unlock(bgp); /* TODO - This timer is started with a lock - why? */
3064 }
3065
3066 /* Inform peers we're going down. */
3067 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
3068 {
3069 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3070 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
3071 }
7cb43556 3072
ad4cbda1 3073 /* Delete static routes (networks). */
6aeb9e78
DS
3074 bgp_static_delete (bgp);
3075
3076 /* Unset redistribution. */
3077 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3078 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3079 if (i != ZEBRA_ROUTE_BGP)
3080 bgp_redistribute_unset (bgp, afi, i, 0);
3081
ad4cbda1 3082 /* Free peers and peer-groups. */
6aeb9e78 3083 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
ad4cbda1 3084 peer_group_delete (group);
6aeb9e78
DS
3085
3086 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
ad4cbda1 3087 peer_delete (peer);
1ff9a340 3088
0088b5dc
SH
3089 if (bgp->peer_self) {
3090 peer_delete(bgp->peer_self);
3091 bgp->peer_self = NULL;
3092 }
0de4848d 3093
3d68677e 3094 update_bgp_group_free (bgp);
ad4cbda1 3095
3096 /* TODO - Other memory may need to be freed - e.g., NHT */
3097
fd35b948
PJ
3098 /* Remove visibility via the master list - there may however still be
3099 * routes to be processed still referencing the struct bgp.
3100 */
3101 listnode_delete (bm->bgp, bgp);
d023aec4
SH
3102 if (list_isempty(bm->bgp))
3103 bgp_close ();
3104
ad4cbda1 3105 /* Deregister from Zebra, if needed */
3106 if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
3107 bgp_zebra_instance_deregister (bgp);
3108
009b18fc 3109 /* Free interfaces in this instance. */
3110 bgp_if_finish (bgp);
3111
87d4a781 3112 thread_master_free_unused(bm->master);
0088b5dc 3113 bgp_unlock(bgp); /* initial reference */
6410e93a 3114
0088b5dc
SH
3115 return 0;
3116}
3117
3118static void bgp_free (struct bgp *);
3119
3120void
3121bgp_lock (struct bgp *bgp)
3122{
3123 ++bgp->lock;
3124}
3125
3126void
3127bgp_unlock(struct bgp *bgp)
3128{
228da428 3129 assert(bgp->lock > 0);
0088b5dc
SH
3130 if (--bgp->lock == 0)
3131 bgp_free (bgp);
3132}
3133
3134static void
3135bgp_free (struct bgp *bgp)
3136{
3137 afi_t afi;
3138 safi_t safi;
d3f5a0d3 3139 struct vrf *vrf;
0088b5dc
SH
3140
3141 list_delete (bgp->group);
3142 list_delete (bgp->peer);
3ffe142a
DW
3143
3144 if (bgp->peerhash)
3145 {
3146 hash_free(bgp->peerhash);
3147 bgp->peerhash = NULL;
3148 }
fee0f4c6 3149
718e3744 3150 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3151 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3152 {
3153 if (bgp->route[afi][safi])
228da428 3154 bgp_table_finish (&bgp->route[afi][safi]);
718e3744 3155 if (bgp->aggregate[afi][safi])
228da428 3156 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
718e3744 3157 if (bgp->rib[afi][safi])
228da428 3158 bgp_table_finish (&bgp->rib[afi][safi]);
718e3744 3159 }
d3f5a0d3 3160
3161 /* If Default instance or VRF, unlink from the VRF structure. */
3162 vrf = bgp_vrf_lookup_by_instance_type (bgp);
3163 if (vrf)
3164 bgp_vrf_unlink (bgp, vrf);
3165
4ac82321 3166 if (bgp->name)
3167 XFREE(MTYPE_BGP, bgp->name);
3168
718e3744 3169 XFREE (MTYPE_BGP, bgp);
718e3744 3170}
6b0655a2 3171
a80beece
DS
3172struct peer *
3173peer_lookup_by_conf_if (struct bgp *bgp, const char *conf_if)
3174{
3175 struct peer *peer;
3176 struct listnode *node, *nnode;
3177
3178 if (!conf_if)
3179 return NULL;
3180
3181 if (bgp != NULL)
3182 {
3183 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
3184 if (peer->conf_if && !strcmp(peer->conf_if, conf_if)
3185 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
3186 return peer;
3187 }
3188 else if (bm->bgp != NULL)
3189 {
3190 struct listnode *bgpnode, *nbgpnode;
3191
3192 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
3193 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
3194 if (peer->conf_if && !strcmp(peer->conf_if, conf_if)
3195 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
3196 return peer;
3197 }
3198 return NULL;
3199}
3200
04b6bdc0
DW
3201struct peer *
3202peer_lookup_by_hostname (struct bgp *bgp, const char *hostname)
3203{
3204 struct peer *peer;
3205 struct listnode *node, *nnode;
3206
3207 if (!hostname)
3208 return NULL;
3209
3210 if (bgp != NULL)
3211 {
3212 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
3213 if (peer->hostname && !strcmp(peer->hostname, hostname)
3214 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
3215 return peer;
3216 }
3217 else if (bm->bgp != NULL)
3218 {
3219 struct listnode *bgpnode, *nbgpnode;
3220
3221 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
3222 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
3223 if (peer->hostname && !strcmp(peer->hostname, hostname)
3224 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
3225 return peer;
3226 }
3227 return NULL;
3228}
3229
718e3744 3230struct peer *
3231peer_lookup (struct bgp *bgp, union sockunion *su)
3232{
dd793e4a
DW
3233 struct peer *peer = NULL;
3234 struct peer tmp_peer;
3235
3236 memset(&tmp_peer, 0, sizeof(struct peer));
3237
3238 /*
3239 * We do not want to find the doppelganger peer so search for the peer in
3240 * the hash that has PEER_FLAG_CONFIG_NODE
3241 */
3242 SET_FLAG (tmp_peer.flags, PEER_FLAG_CONFIG_NODE);
3243
3244 tmp_peer.su = *su;
718e3744 3245
fc4dc59d 3246 if (bgp != NULL)
fc4dc59d 3247 {
dd793e4a 3248 peer = hash_lookup(bgp->peerhash, &tmp_peer);
fc4dc59d 3249 }
fc4dc59d 3250 else if (bm->bgp != NULL)
718e3744 3251 {
2158ad23
PJ
3252 struct listnode *bgpnode, *nbgpnode;
3253
3254 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
dd793e4a 3255 {
ad4cbda1 3256 /* Skip VRFs, this function will not be invoked without an instance
3257 * when examining VRFs.
6aeb9e78 3258 */
ad4cbda1 3259 if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6aeb9e78
DS
3260 continue;
3261
dd793e4a
DW
3262 peer = hash_lookup(bgp->peerhash, &tmp_peer);
3263
3264 if (peer)
3265 break;
3266 }
fc4dc59d 3267 }
dd793e4a
DW
3268
3269 return peer;
718e3744 3270}
3271
f14e6fdb
DS
3272struct peer *
3273peer_create_bind_dynamic_neighbor (struct bgp *bgp, union sockunion *su,
3274 struct peer_group *group)
3275{
3276 struct peer *peer;
3277 afi_t afi;
3278 safi_t safi;
f14e6fdb
DS
3279
3280 /* Create peer first; we've already checked group config is valid. */
f813b13b 3281 peer = peer_create (su, NULL, bgp, bgp->as, group->conf->as, group->conf->as_type, 0, 0, group);
f14e6fdb
DS
3282 if (!peer)
3283 return NULL;
3284
3285 /* Link to group */
f14e6fdb
DS
3286 peer = peer_lock (peer);
3287 listnode_add (group->peer, peer);
3288
a4ed4829
DW
3289 peer_group2peer_config_copy(group, peer);
3290
f14e6fdb
DS
3291 /*
3292 * Bind peer for all AFs configured for the group. We don't call
3293 * peer_group_bind as that is sub-optimal and does some stuff we don't want.
3294 */
3295 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3296 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3297 {
3298 if (!group->conf->afc[afi][safi])
3299 continue;
f14e6fdb 3300 peer->afc[afi][safi] = 1;
c8560b44
DW
3301
3302 if (!peer_af_find(peer, afi, safi))
3303 peer_af_create(peer, afi, safi);
3304
a4ed4829 3305 peer_group2peer_config_copy_af (group, peer, afi, safi);
f14e6fdb
DS
3306 }
3307
3308 /* Mark as dynamic, but also as a "config node" for other things to work. */
3309 SET_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR);
3310 SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
3311
3312 return peer;
3313}
3314
3315struct prefix *
3316peer_group_lookup_dynamic_neighbor_range (struct peer_group * group,
3317 struct prefix * prefix)
3318{
3319 struct listnode *node, *nnode;
3320 struct prefix *range;
3321 afi_t afi;
3322
3323 afi = family2afi(prefix->family);
3324
3325 if (group->listen_range[afi])
3326 for (ALL_LIST_ELEMENTS (group->listen_range[afi], node, nnode, range))
3327 if (prefix_match(range, prefix))
3328 return range;
3329
3330 return NULL;
3331}
3332
3333struct peer_group *
3334peer_group_lookup_dynamic_neighbor (struct bgp *bgp, struct prefix *prefix,
3335 struct prefix **listen_range)
3336{
3337 struct prefix *range = NULL;
3338 struct peer_group *group = NULL;
3339 struct listnode *node, *nnode;
3340
3341 *listen_range = NULL;
3342 if (bgp != NULL)
3343 {
3344 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
3345 if ((range = peer_group_lookup_dynamic_neighbor_range(group, prefix)))
3346 break;
3347 }
3348 else if (bm->bgp != NULL)
3349 {
3350 struct listnode *bgpnode, *nbgpnode;
3351
3352 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
3353 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
3354 if ((range = peer_group_lookup_dynamic_neighbor_range(group, prefix)))
2aab8d2b 3355 goto found_range;
f14e6fdb
DS
3356 }
3357
2aab8d2b 3358 found_range:
f14e6fdb
DS
3359 *listen_range = range;
3360 return (group && range) ? group : NULL;
3361}
3362
3363struct peer *
3364peer_lookup_dynamic_neighbor (struct bgp *bgp, union sockunion *su)
3365{
3366 struct peer_group *group;
3367 struct bgp *gbgp;
3368 struct peer *peer;
3369 struct prefix *prefix;
3370 struct prefix *listen_range;
3371 int dncount;
4690c7d7
DS
3372 char buf[PREFIX2STR_BUFFER];
3373 char buf1[PREFIX2STR_BUFFER];
f14e6fdb
DS
3374
3375 prefix = sockunion2hostprefix(su);
0299c004 3376 if (!prefix) {
f14e6fdb 3377 return NULL;
0299c004 3378 }
f14e6fdb
DS
3379
3380 /* See if incoming connection matches a configured listen range. */
3381 group = peer_group_lookup_dynamic_neighbor (bgp, prefix, &listen_range);
3382
3383 if (! group)
3384 return NULL;
3385
0299c004 3386
f14e6fdb
DS
3387 gbgp = group->bgp;
3388
3389 if (! gbgp)
3390 return NULL;
3391
3392 prefix2str(prefix, buf, sizeof(buf));
3393 prefix2str(listen_range, buf1, sizeof(buf1));
3394
3395 if (bgp_debug_neighbor_events(NULL))
3396 zlog_debug ("Dynamic Neighbor %s matches group %s listen range %s",
3397 buf, group->name, buf1);
3398
3399 /* Are we within the listen limit? */
3400 dncount = gbgp->dynamic_neighbors_count;
3401
3402 if (dncount >= gbgp->dynamic_neighbors_limit)
3403 {
3404 if (bgp_debug_neighbor_events(NULL))
3405 zlog_debug ("Dynamic Neighbor %s rejected - at limit %d",
3406 inet_sutop (su, buf), gbgp->dynamic_neighbors_limit);
3407 return NULL;
3408 }
3409
3410 /* Ensure group is not disabled. */
3411 if (CHECK_FLAG (group->conf->flags, PEER_FLAG_SHUTDOWN))
3412 {
3413 if (bgp_debug_neighbor_events(NULL))
3414 zlog_debug ("Dynamic Neighbor %s rejected - group %s disabled",
3415 buf, group->name);
3416 return NULL;
3417 }
3418
3419 /* Check that at least one AF is activated for the group. */
3420 if (!peer_group_af_configured (group))
3421 {
3422 if (bgp_debug_neighbor_events(NULL))
3423 zlog_debug ("Dynamic Neighbor %s rejected - no AF activated for group %s",
3424 buf, group->name);
3425 return NULL;
3426 }
3427
3428 /* Create dynamic peer and bind to associated group. */
3429 peer = peer_create_bind_dynamic_neighbor (gbgp, su, group);
3430 assert (peer);
3431
3432 gbgp->dynamic_neighbors_count = ++dncount;
3433
3434 if (bgp_debug_neighbor_events(peer))
3435 zlog_debug ("%s Dynamic Neighbor added, group %s count %d",
3436 peer->host, group->name, dncount);
3437
3438 return peer;
3439}
3440
3441void peer_drop_dynamic_neighbor (struct peer *peer)
3442{
3443 int dncount = -1;
3444 if (peer->group && peer->group->bgp)
3445 {
3446 dncount = peer->group->bgp->dynamic_neighbors_count;
3447 if (dncount)
3448 peer->group->bgp->dynamic_neighbors_count = --dncount;
3449 }
3450 if (bgp_debug_neighbor_events(peer))
3451 zlog_debug ("%s dropped from group %s, count %d",
3452 peer->host, peer->group->name, dncount);
3453}
3454
3455
718e3744 3456/* If peer is configured at least one address family return 1. */
3457int
3458peer_active (struct peer *peer)
3459{
a80beece
DS
3460 if (BGP_PEER_SU_UNSPEC(peer))
3461 return 0;
718e3744 3462 if (peer->afc[AFI_IP][SAFI_UNICAST]
3463 || peer->afc[AFI_IP][SAFI_MULTICAST]
3464 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
3465 || peer->afc[AFI_IP6][SAFI_UNICAST]
945c8fe9
LB
3466 || peer->afc[AFI_IP6][SAFI_MULTICAST]
3467 || peer->afc[AFI_IP6][SAFI_MPLS_VPN])
718e3744 3468 return 1;
3469 return 0;
3470}
3471
3472/* If peer is negotiated at least one address family return 1. */
3473int
3474peer_active_nego (struct peer *peer)
3475{
3476 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
3477 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
3478 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
3479 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
945c8fe9
LB
3480 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
3481 || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN])
718e3744 3482 return 1;
3483 return 0;
3484}
6b0655a2 3485
718e3744 3486/* peer_flag_change_type. */
3487enum peer_change_type
3488{
3489 peer_change_none,
3490 peer_change_reset,
3491 peer_change_reset_in,
3492 peer_change_reset_out,
3493};
3494
94f2b392 3495static void
718e3744 3496peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
3497 enum peer_change_type type)
3498{
3499 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3500 return;
3501
d9d4ae51
SH
3502 if (peer->status != Established)
3503 return;
3504
718e3744 3505 if (type == peer_change_reset)
1ff9a340
DS
3506 {
3507 /* If we're resetting session, we've to delete both peer struct */
3508 if ((peer->doppelganger) && (peer->doppelganger->status != Deleted)
3509 && (!CHECK_FLAG(peer->doppelganger->flags,
3510 PEER_FLAG_CONFIG_NODE)))
3511 peer_delete(peer->doppelganger);
3512
3513 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3514 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3515 }
718e3744 3516 else if (type == peer_change_reset_in)
3517 {
3518 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
3519 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
3520 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
3521 else
1ff9a340
DS
3522 {
3523 if ((peer->doppelganger) && (peer->doppelganger->status != Deleted)
3524 && (!CHECK_FLAG(peer->doppelganger->flags,
3525 PEER_FLAG_CONFIG_NODE)))
3526 peer_delete(peer->doppelganger);
3527
3528 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3529 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3530 }
718e3744 3531 }
3532 else if (type == peer_change_reset_out)
3f9c7369
DS
3533 {
3534 update_group_adjust_peer(peer_af_find(peer, afi, safi));
3535 bgp_announce_route (peer, afi, safi);
3536 }
718e3744 3537}
3538
3539struct peer_flag_action
3540{
3541 /* Peer's flag. */
3542 u_int32_t flag;
3543
3544 /* This flag can be set for peer-group member. */
3545 u_char not_for_member;
3546
3547 /* Action when the flag is changed. */
3548 enum peer_change_type type;
e0701b79 3549
3550 /* Peer down cause */
3551 u_char peer_down;
718e3744 3552};
3553
03621955 3554static const struct peer_flag_action peer_flag_action_list[] =
718e3744 3555 {
3556 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
3557 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
3558 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
3559 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
3560 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
718e3744 3561 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
6ffd2079 3562 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
8a92a8a0 3563 { PEER_FLAG_CAPABILITY_ENHE, 0, peer_change_reset },
718e3744 3564 { 0, 0, 0 }
3565 };
3566
03621955 3567static const struct peer_flag_action peer_af_flag_action_list[] =
718e3744 3568 {
718e3744 3569 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
3570 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
adbac85e 3571 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
718e3744 3572 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
3573 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
adbac85e 3574 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
718e3744 3575 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
3576 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
3577 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
adbac85e 3578 // PEER_FLAG_DEFAULT_ORIGINATE
718e3744 3579 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
3580 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
3581 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
3582 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
adbac85e
DW
3583 // PEER_FLAG_MAX_PREFIX
3584 // PEER_FLAG_MAX_PREFIX_WARNING
fee0f4c6 3585 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
a538debe 3586 { PEER_FLAG_FORCE_NEXTHOP_SELF, 1, peer_change_reset_out },
adbac85e
DW
3587 { PEER_FLAG_REMOVE_PRIVATE_AS_ALL, 1, peer_change_reset_out },
3588 { PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE,1, peer_change_reset_out },
c7122e14 3589 { PEER_FLAG_AS_OVERRIDE, 1, peer_change_reset_out },
88b8ed8d 3590 { PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE,1, peer_change_reset_out },
adbac85e 3591 { PEER_FLAG_ADDPATH_TX_ALL_PATHS, 1, peer_change_reset },
06370dac 3592 { PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS, 1, peer_change_reset },
718e3744 3593 { 0, 0, 0 }
3594 };
3595
3596/* Proper action set. */
94f2b392 3597static int
03621955 3598peer_flag_action_set (const struct peer_flag_action *action_list, int size,
718e3744 3599 struct peer_flag_action *action, u_int32_t flag)
3600{
3601 int i;
3602 int found = 0;
3603 int reset_in = 0;
3604 int reset_out = 0;
03621955 3605 const struct peer_flag_action *match = NULL;
718e3744 3606
3607 /* Check peer's frag action. */
3608 for (i = 0; i < size; i++)
3609 {
3610 match = &action_list[i];
3611
3612 if (match->flag == 0)
3613 break;
3614
3615 if (match->flag & flag)
3616 {
3617 found = 1;
3618
3619 if (match->type == peer_change_reset_in)
3620 reset_in = 1;
3621 if (match->type == peer_change_reset_out)
3622 reset_out = 1;
3623 if (match->type == peer_change_reset)
3624 {
3625 reset_in = 1;
3626 reset_out = 1;
3627 }
3628 if (match->not_for_member)
3629 action->not_for_member = 1;
3630 }
3631 }
3632
3633 /* Set peer clear type. */
3634 if (reset_in && reset_out)
3635 action->type = peer_change_reset;
3636 else if (reset_in)
3637 action->type = peer_change_reset_in;
3638 else if (reset_out)
3639 action->type = peer_change_reset_out;
3640 else
3641 action->type = peer_change_none;
3642
3643 return found;
3644}
3645
94f2b392 3646static void
718e3744 3647peer_flag_modify_action (struct peer *peer, u_int32_t flag)
3648{
3649 if (flag == PEER_FLAG_SHUTDOWN)
3650 {
3651 if (CHECK_FLAG (peer->flags, flag))
3652 {
93406d87 3653 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
3654 peer_nsf_stop (peer);
3655
0a486e5f 3656 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3657 if (peer->t_pmax_restart)
3658 {
3659 BGP_TIMER_OFF (peer->t_pmax_restart);
16286195 3660 if (bgp_debug_neighbor_events(peer))
0a486e5f 3661 zlog_debug ("%s Maximum-prefix restart timer canceled",
3662 peer->host);
3663 }
3664
1ff9a340
DS
3665 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
3666 peer_nsf_stop (peer);
93406d87 3667
6aa136f1 3668 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
718e3744 3669 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3670 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
3671 else
1ff9a340 3672 bgp_session_reset(peer);
718e3744 3673 }
3674 else
3675 {
3676 peer->v_start = BGP_INIT_START_TIMER;
3677 BGP_EVENT_ADD (peer, BGP_Stop);
3678 }
3679 }
6aa136f1 3680 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
718e3744 3681 {
c9502438 3682 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
3683 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
3684 else if (flag == PEER_FLAG_PASSIVE)
3685 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
6ffd2079 3686 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
c9502438 3687 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
e0701b79 3688
c9502438 3689 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3690 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
718e3744 3691 }
3692 else
1ff9a340 3693 bgp_session_reset(peer);
718e3744 3694}
3695
3696/* Change specified peer flag. */
94f2b392 3697static int
718e3744 3698peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
3699{
3700 int found;
3701 int size;
3702 struct peer_group *group;
a4ed4829 3703 struct peer *tmp_peer;
1eb8ef25 3704 struct listnode *node, *nnode;
718e3744 3705 struct peer_flag_action action;
3706
3707 memset (&action, 0, sizeof (struct peer_flag_action));
3708 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
3709
3710 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
3711
3712 /* No flag action is found. */
3713 if (! found)
3714 return BGP_ERR_INVALID_FLAG;
3715
718e3744 3716 /* When unset the peer-group member's flag we have to check
3717 peer-group configuration. */
3718 if (! set && peer_group_active (peer))
3719 if (CHECK_FLAG (peer->group->conf->flags, flag))
3720 {
3721 if (flag == PEER_FLAG_SHUTDOWN)
3722 return BGP_ERR_PEER_GROUP_SHUTDOWN;
718e3744 3723 }
3724
3725 /* Flag conflict check. */
3726 if (set
3727 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
3728 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
3729 return BGP_ERR_PEER_FLAG_CONFLICT;
3730
3731 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3732 {
3733 if (set && CHECK_FLAG (peer->flags, flag) == flag)
3734 return 0;
3735 if (! set && ! CHECK_FLAG (peer->flags, flag))
3736 return 0;
3737 }
3738
3739 if (set)
3740 SET_FLAG (peer->flags, flag);
3741 else
3742 UNSET_FLAG (peer->flags, flag);
3743
3744 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3745 {
3746 if (action.type == peer_change_reset)
3747 peer_flag_modify_action (peer, flag);
3748
3749 return 0;
3750 }
3751
3752 /* peer-group member updates. */
3753 group = peer->group;
3754
a4ed4829 3755 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, tmp_peer))
718e3744 3756 {
a4ed4829 3757
1a79ce38 3758 if (set && CHECK_FLAG (tmp_peer->flags, flag) == flag)
718e3744 3759 continue;
3760
1a79ce38 3761 if (! set && ! CHECK_FLAG (tmp_peer->flags, flag))
718e3744 3762 continue;
3763
3764 if (set)
a4ed4829 3765 SET_FLAG (tmp_peer->flags, flag);
718e3744 3766 else
a4ed4829 3767 UNSET_FLAG (tmp_peer->flags, flag);
718e3744 3768
3769 if (action.type == peer_change_reset)
a4ed4829 3770 peer_flag_modify_action (tmp_peer, flag);
718e3744 3771 }
3772 return 0;
3773}
3774
3775int
3776peer_flag_set (struct peer *peer, u_int32_t flag)
3777{
3778 return peer_flag_modify (peer, flag, 1);
3779}
3780
3781int
3782peer_flag_unset (struct peer *peer, u_int32_t flag)
3783{
3784 return peer_flag_modify (peer, flag, 0);
3785}
3786
94f2b392 3787static int
718e3744 3788peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
3789 int set)
3790{
3791 int found;
3792 int size;
1eb8ef25 3793 struct listnode *node, *nnode;
718e3744 3794 struct peer_group *group;
3795 struct peer_flag_action action;
adbac85e
DW
3796 struct peer *tmp_peer;
3797 struct bgp *bgp;
3798 int addpath_tx_used;
718e3744 3799
3800 memset (&action, 0, sizeof (struct peer_flag_action));
3801 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
3802
3803 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
3804
3805 /* No flag action is found. */
3806 if (! found)
3807 return BGP_ERR_INVALID_FLAG;
3808
400b1fad 3809 /* Special check for reflector client. */
718e3744 3810 if (flag & PEER_FLAG_REFLECTOR_CLIENT
3811 && peer_sort (peer) != BGP_PEER_IBGP)
3812 return BGP_ERR_NOT_INTERNAL_PEER;
3813
400b1fad 3814 /* Special check for remove-private-AS. */
718e3744 3815 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
3816 && peer_sort (peer) == BGP_PEER_IBGP)
3817 return BGP_ERR_REMOVE_PRIVATE_AS;
3818
c7122e14
DS
3819 /* as-override is not allowed for IBGP peers */
3820 if (flag & PEER_FLAG_AS_OVERRIDE
3821 && peer_sort (peer) == BGP_PEER_IBGP)
3822 return BGP_ERR_AS_OVERRIDE;
3823
718e3744 3824 /* When current flag configuration is same as requested one. */
3825 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3826 {
3827 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
3828 return 0;
3829 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
3830 return 0;
3831 }
3832
3833 if (set)
3834 SET_FLAG (peer->af_flags[afi][safi], flag);
3835 else
3836 UNSET_FLAG (peer->af_flags[afi][safi], flag);
3837
3838 /* Execute action when peer is established. */
3839 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3840 && peer->status == Established)
3841 {
3842 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
3843 bgp_clear_adj_in (peer, afi, safi);
3844 else
e0701b79 3845 {
3846 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
3847 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
3848 else if (flag == PEER_FLAG_RSERVER_CLIENT)
3849 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
3850 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
3851 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
3852 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
3853 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
3854
3855 peer_change_action (peer, afi, safi, action.type);
3856 }
3857
718e3744 3858 }
3859
3860 /* Peer group member updates. */
3861 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3862 {
3863 group = peer->group;
3864
adbac85e 3865 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, tmp_peer))
718e3744 3866 {
adbac85e 3867 if (set && CHECK_FLAG (tmp_peer->af_flags[afi][safi], flag) == flag)
718e3744 3868 continue;
3869
adbac85e 3870 if (! set && ! CHECK_FLAG (tmp_peer->af_flags[afi][safi], flag))
718e3744 3871 continue;
3872
3873 if (set)
adbac85e 3874 SET_FLAG (tmp_peer->af_flags[afi][safi], flag);
718e3744 3875 else
adbac85e 3876 UNSET_FLAG (tmp_peer->af_flags[afi][safi], flag);
718e3744 3877
adbac85e 3878 if (tmp_peer->status == Established)
718e3744 3879 {
3880 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
adbac85e 3881 bgp_clear_adj_in (tmp_peer, afi, safi);
718e3744 3882 else
e0701b79 3883 {
3884 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
adbac85e 3885 tmp_peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
e0701b79 3886 else if (flag == PEER_FLAG_RSERVER_CLIENT)
adbac85e 3887 tmp_peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
e0701b79 3888 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
adbac85e 3889 tmp_peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
e0701b79 3890 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
adbac85e 3891 tmp_peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
e0701b79 3892
adbac85e 3893 peer_change_action (tmp_peer, afi, safi, action.type);
e0701b79 3894 }
718e3744 3895 }
3896 }
3897 }
adbac85e
DW
3898
3899 /* Track if addpath TX is in use */
06370dac 3900 if (flag & (PEER_FLAG_ADDPATH_TX_ALL_PATHS|PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS))
adbac85e
DW
3901 {
3902 bgp = peer->bgp;
3903 addpath_tx_used = 0;
3904
3905 if (set)
3906 {
3907 addpath_tx_used = 1;
06370dac
DW
3908
3909 if (flag & PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)
3910 {
3911 if (!bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
3912 {
3913 zlog_warn("%s: enabling bgp deterministic-med, this is required"\
3914 " for addpath-tx-bestpath-per-AS",
3915 peer->host);
3916 bgp_flag_set (bgp, BGP_FLAG_DETERMINISTIC_MED);
3917 bgp_recalculate_all_bestpaths (bgp);
3918 }
3919 }
adbac85e
DW
3920 }
3921 else
3922 {
3923 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, tmp_peer))
3924 {
06370dac
DW
3925 if (CHECK_FLAG (tmp_peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_ALL_PATHS) ||
3926 CHECK_FLAG (tmp_peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS))
adbac85e
DW
3927 {
3928 addpath_tx_used = 1;
3929 break;
3930 }
3931 }
3932 }
3933
3934 bgp->addpath_tx_used[afi][safi] = addpath_tx_used;
3935 }
3936
718e3744 3937 return 0;
3938}
3939
3940int
3941peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
3942{
3943 return peer_af_flag_modify (peer, afi, safi, flag, 1);
3944}
3945
3946int
3947peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
3948{
3949 return peer_af_flag_modify (peer, afi, safi, flag, 0);
3950}
6b0655a2 3951
718e3744 3952/* EBGP multihop configuration. */
3953int
3954peer_ebgp_multihop_set (struct peer *peer, int ttl)
3955{
3956 struct peer_group *group;
1eb8ef25 3957 struct listnode *node, *nnode;
fa411a21 3958 struct peer *peer1;
718e3744 3959
a80beece 3960 if (peer->sort == BGP_PEER_IBGP || peer->conf_if)
718e3744 3961 return 0;
3962
fa411a21
NH
3963 /* see comment in peer_ttl_security_hops_set() */
3964 if (ttl != MAXTTL)
3965 {
3966 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3967 {
3968 group = peer->group;
3969 if (group->conf->gtsm_hops != 0)
3970 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
3971
3972 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
3973 {
6d85b15b 3974 if (peer1->sort == BGP_PEER_IBGP)
fa411a21
NH
3975 continue;
3976
3977 if (peer1->gtsm_hops != 0)
3978 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
3979 }
3980 }
3981 else
3982 {
3983 if (peer->gtsm_hops != 0)
3984 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
3985 }
3986 }
3987
718e3744 3988 peer->ttl = ttl;
3989
3990 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3991 {
6d85b15b 3992 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
e5cc509c
DS
3993 {
3994 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3995 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3996 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3997 else
3998 bgp_session_reset(peer);
3999 }
718e3744 4000 }
4001 else
4002 {
4003 group = peer->group;
1eb8ef25 4004 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
eb821189 4005 {
6d85b15b 4006 if (peer->sort == BGP_PEER_IBGP)
eb821189 4007 continue;
718e3744 4008
eb821189 4009 peer->ttl = group->conf->ttl;
718e3744 4010
e5cc509c
DS
4011 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4012 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4013 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4014 else
4015 bgp_session_reset(peer);
eb821189 4016 }
718e3744 4017 }
4018 return 0;
4019}
4020
4021int
4022peer_ebgp_multihop_unset (struct peer *peer)
4023{
4024 struct peer_group *group;
1eb8ef25 4025 struct listnode *node, *nnode;
718e3744 4026
6d85b15b 4027 if (peer->sort == BGP_PEER_IBGP)
718e3744 4028 return 0;
4029
fa411a21
NH
4030 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
4031 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4032
718e3744 4033 if (peer_group_active (peer))
4034 peer->ttl = peer->group->conf->ttl;
4035 else
4036 peer->ttl = 1;
4037
4038 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4039 {
e5cc509c
DS
4040 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4041 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4042 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4043 else
4044 bgp_session_reset(peer);
718e3744 4045 }
4046 else
4047 {
4048 group = peer->group;
1eb8ef25 4049 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
eb821189 4050 {
6d85b15b 4051 if (peer->sort == BGP_PEER_IBGP)
eb821189 4052 continue;
4053
4054 peer->ttl = 1;
e5cc509c 4055
eb821189 4056 if (peer->fd >= 0)
e5cc509c
DS
4057 {
4058 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4059 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4060 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4061 else
4062 bgp_session_reset(peer);
4063 }
eb821189 4064 }
718e3744 4065 }
4066 return 0;
4067}
6b0655a2 4068
718e3744 4069/* Neighbor description. */
4070int
4071peer_description_set (struct peer *peer, char *desc)
4072{
4073 if (peer->desc)
4074 XFREE (MTYPE_PEER_DESC, peer->desc);
4075
4076 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
4077
4078 return 0;
4079}
4080
4081int
4082peer_description_unset (struct peer *peer)
4083{
4084 if (peer->desc)
4085 XFREE (MTYPE_PEER_DESC, peer->desc);
4086
4087 peer->desc = NULL;
4088
4089 return 0;
4090}
6b0655a2 4091
718e3744 4092/* Neighbor update-source. */
4093int
fd79ac91 4094peer_update_source_if_set (struct peer *peer, const char *ifname)
718e3744 4095{
4096 struct peer_group *group;
1eb8ef25 4097 struct listnode *node, *nnode;
718e3744 4098
4099 if (peer->update_if)
4100 {
4101 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
4102 && strcmp (peer->update_if, ifname) == 0)
4103 return 0;
4104
4105 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
4106 peer->update_if = NULL;
4107 }
4108
4109 if (peer->update_source)
4110 {
4111 sockunion_free (peer->update_source);
4112 peer->update_source = NULL;
4113 }
4114
4115 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
4116
4117 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4118 {
6aa136f1 4119 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4120 {
4121 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4122 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4123 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4124 }
718e3744 4125 else
1ff9a340 4126 bgp_session_reset(peer);
718e3744 4127 return 0;
4128 }
4129
4130 /* peer-group member updates. */
4131 group = peer->group;
1eb8ef25 4132 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4133 {
4134 if (peer->update_if)
4135 {
4136 if (strcmp (peer->update_if, ifname) == 0)
4137 continue;
4138
4139 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
4140 peer->update_if = NULL;
4141 }
4142
4143 if (peer->update_source)
4144 {
4145 sockunion_free (peer->update_source);
4146 peer->update_source = NULL;
4147 }
4148
4149 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
4150
6aa136f1 4151 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4152 {
4153 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4154 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4155 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4156 }
718e3744 4157 else
1ff9a340 4158 bgp_session_reset(peer);
718e3744 4159 }
4160 return 0;
4161}
4162
4163int
4164peer_update_source_addr_set (struct peer *peer, union sockunion *su)
4165{
4166 struct peer_group *group;
1eb8ef25 4167 struct listnode *node, *nnode;
718e3744 4168
4169 if (peer->update_source)
4170 {
4171 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
4172 && sockunion_cmp (peer->update_source, su) == 0)
4173 return 0;
4174 sockunion_free (peer->update_source);
4175 peer->update_source = NULL;
4176 }
4177
4178 if (peer->update_if)
4179 {
4180 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
4181 peer->update_if = NULL;
1ff9a340 4182
718e3744 4183 }
4184
4185 peer->update_source = sockunion_dup (su);
4186
4187 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4188 {
6aa136f1 4189 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4190 {
4191 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4192 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4193 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4194 }
718e3744 4195 else
1ff9a340 4196 bgp_session_reset(peer);
718e3744 4197 return 0;
4198 }
4199
4200 /* peer-group member updates. */
4201 group = peer->group;
1eb8ef25 4202 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4203 {
4204 if (peer->update_source)
4205 {
4206 if (sockunion_cmp (peer->update_source, su) == 0)
4207 continue;
4208 sockunion_free (peer->update_source);
4209 peer->update_source = NULL;
4210 }
4211
4212 if (peer->update_if)
4213 {
4214 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
4215 peer->update_if = NULL;
4216 }
4217
4218 peer->update_source = sockunion_dup (su);
4219
6aa136f1 4220 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4221 {
4222 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4223 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4224 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4225 }
718e3744 4226 else
1ff9a340 4227 bgp_session_reset(peer);
718e3744 4228 }
4229 return 0;
4230}
4231
4232int
4233peer_update_source_unset (struct peer *peer)
4234{
4235 union sockunion *su;
4236 struct peer_group *group;
1eb8ef25 4237 struct listnode *node, *nnode;
718e3744 4238
4239 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
4240 && ! peer->update_source
4241 && ! peer->update_if)
4242 return 0;
4243
4244 if (peer->update_source)
4245 {
4246 sockunion_free (peer->update_source);
4247 peer->update_source = NULL;
4248 }
4249 if (peer->update_if)
4250 {
4251 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
4252 peer->update_if = NULL;
4253 }
4254
4255 if (peer_group_active (peer))
4256 {
4257 group = peer->group;
4258
4259 if (group->conf->update_source)
4260 {
4261 su = sockunion_dup (group->conf->update_source);
4262 peer->update_source = su;
4263 }
4264 else if (group->conf->update_if)
4265 peer->update_if =
4266 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
4267 }
4268
4269 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4270 {
6aa136f1 4271 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4272 {
4273 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4274 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4275 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4276 }
718e3744 4277 else
1ff9a340 4278 bgp_session_reset(peer);
718e3744 4279 return 0;
4280 }
4281
4282 /* peer-group member updates. */
4283 group = peer->group;
1eb8ef25 4284 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4285 {
4286 if (! peer->update_source && ! peer->update_if)
4287 continue;
4288
4289 if (peer->update_source)
4290 {
4291 sockunion_free (peer->update_source);
4292 peer->update_source = NULL;
4293 }
4294
4295 if (peer->update_if)
4296 {
4297 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
4298 peer->update_if = NULL;
4299 }
4300
6aa136f1 4301 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4302 {
4303 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4304 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4305 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4306 }
718e3744 4307 else
1ff9a340 4308 bgp_session_reset(peer);
718e3744 4309 }
4310 return 0;
4311}
6b0655a2 4312
718e3744 4313int
4314peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
fd79ac91 4315 const char *rmap)
718e3744 4316{
4317 struct peer_group *group;
1eb8ef25 4318 struct listnode *node, *nnode;
718e3744 4319
718e3744 4320 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
4321 || (rmap && ! peer->default_rmap[afi][safi].name)
4322 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
4323 {
4324 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
4325
4326 if (rmap)
4327 {
4328 if (peer->default_rmap[afi][safi].name)
6e919709
DS
4329 XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name);
4330 peer->default_rmap[afi][safi].name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
718e3744 4331 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
4332 }
4333 }
4334
4335 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4336 {
3f9c7369
DS
4337 if (peer->status == Established && peer->afc_nego[afi][safi]) {
4338 update_group_adjust_peer(peer_af_find(peer, afi, safi));
718e3744 4339 bgp_default_originate (peer, afi, safi, 0);
3f9c7369
DS
4340 bgp_announce_route (peer, afi, safi);
4341 }
718e3744 4342 return 0;
4343 }
4344
4345 /* peer-group member updates. */
4346 group = peer->group;
1eb8ef25 4347 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4348 {
4349 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
4350
4351 if (rmap)
4352 {
4353 if (peer->default_rmap[afi][safi].name)
6e919709
DS
4354 XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name);
4355 peer->default_rmap[afi][safi].name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
718e3744 4356 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
4357 }
4358
3f9c7369
DS
4359 if (peer->status == Established && peer->afc_nego[afi][safi]) {
4360 update_group_adjust_peer(peer_af_find(peer, afi, safi));
718e3744 4361 bgp_default_originate (peer, afi, safi, 0);
3f9c7369
DS
4362 bgp_announce_route (peer, afi, safi);
4363 }
718e3744 4364 }
4365 return 0;
4366}
4367
4368int
4369peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
4370{
4371 struct peer_group *group;
1eb8ef25 4372 struct listnode *node, *nnode;
718e3744 4373
718e3744 4374 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
4375 {
4376 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
4377
4378 if (peer->default_rmap[afi][safi].name)
6e919709 4379 XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name);
718e3744 4380 peer->default_rmap[afi][safi].name = NULL;
4381 peer->default_rmap[afi][safi].map = NULL;
4382 }
4383
4384 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4385 {
3f9c7369
DS
4386 if (peer->status == Established && peer->afc_nego[afi][safi]) {
4387 update_group_adjust_peer(peer_af_find(peer, afi, safi));
718e3744 4388 bgp_default_originate (peer, afi, safi, 1);
3f9c7369
DS
4389 bgp_announce_route (peer, afi, safi);
4390 }
718e3744 4391 return 0;
4392 }
4393
4394 /* peer-group member updates. */
4395 group = peer->group;
1eb8ef25 4396 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4397 {
4398 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
4399
4400 if (peer->default_rmap[afi][safi].name)
6e919709 4401 XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name);
718e3744 4402 peer->default_rmap[afi][safi].name = NULL;
4403 peer->default_rmap[afi][safi].map = NULL;
4404
3f9c7369
DS
4405 if (peer->status == Established && peer->afc_nego[afi][safi]) {
4406 update_group_adjust_peer(peer_af_find(peer, afi, safi));
718e3744 4407 bgp_default_originate (peer, afi, safi, 1);
3f9c7369
DS
4408 bgp_announce_route (peer, afi, safi);
4409 }
718e3744 4410 }
4411 return 0;
4412}
6b0655a2 4413
718e3744 4414int
4415peer_port_set (struct peer *peer, u_int16_t port)
4416{
4417 peer->port = port;
4418 return 0;
4419}
4420
4421int
4422peer_port_unset (struct peer *peer)
4423{
4424 peer->port = BGP_PORT_DEFAULT;
4425 return 0;
4426}
6b0655a2 4427
718e3744 4428/* neighbor weight. */
1f9a9fff 4429int
718e3744 4430peer_weight_set (struct peer *peer, u_int16_t weight)
4431{
4432 struct peer_group *group;
1eb8ef25 4433 struct listnode *node, *nnode;
718e3744 4434
4435 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
4436 peer->weight = weight;
4437
4438 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1f9a9fff 4439 return 0;
718e3744 4440
4441 /* peer-group member updates. */
4442 group = peer->group;
1eb8ef25 4443 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4444 {
4445 peer->weight = group->conf->weight;
4446 }
1f9a9fff 4447 return 1;
718e3744 4448}
4449
1f9a9fff 4450int
718e3744 4451peer_weight_unset (struct peer *peer)
4452{
4453 struct peer_group *group;
1eb8ef25 4454 struct listnode *node, *nnode;
718e3744 4455
4456 /* Set default weight. */
4457 if (peer_group_active (peer))
4458 peer->weight = peer->group->conf->weight;
4459 else
4460 peer->weight = 0;
4461
4462 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
4463
4464 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1f9a9fff 4465 return 0;
718e3744 4466
4467 /* peer-group member updates. */
4468 group = peer->group;
1eb8ef25 4469 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4470 {
4471 peer->weight = 0;
4472 }
1f9a9fff 4473 return 1;
718e3744 4474}
6b0655a2 4475
718e3744 4476int
4477peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
4478{
4479 struct peer_group *group;
1eb8ef25 4480 struct listnode *node, *nnode;
718e3744 4481
718e3744 4482 /* keepalive value check. */
4483 if (keepalive > 65535)
4484 return BGP_ERR_INVALID_VALUE;
4485
4486 /* Holdtime value check. */
4487 if (holdtime > 65535)
4488 return BGP_ERR_INVALID_VALUE;
4489
4490 /* Holdtime value must be either 0 or greater than 3. */
4491 if (holdtime < 3 && holdtime != 0)
4492 return BGP_ERR_INVALID_VALUE;
4493
4494 /* Set value to the configuration. */
4495 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
4496 peer->holdtime = holdtime;
4497 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
4498
4499 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4500 return 0;
4501
4502 /* peer-group member updates. */
4503 group = peer->group;
1eb8ef25 4504 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4505 {
4506 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
4507 peer->holdtime = group->conf->holdtime;
4508 peer->keepalive = group->conf->keepalive;
4509 }
4510 return 0;
4511}
4512
4513int
4514peer_timers_unset (struct peer *peer)
4515{
4516 struct peer_group *group;
1eb8ef25 4517 struct listnode *node, *nnode;
718e3744 4518
718e3744 4519 /* Clear configuration. */
4520 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
4521 peer->keepalive = 0;
4522 peer->holdtime = 0;
4523
4524 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4525 return 0;
4526
4527 /* peer-group member updates. */
4528 group = peer->group;
1eb8ef25 4529 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4530 {
4531 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
4532 peer->holdtime = 0;
4533 peer->keepalive = 0;
4534 }
4535
4536 return 0;
4537}
6b0655a2 4538
718e3744 4539int
4540peer_timers_connect_set (struct peer *peer, u_int32_t connect)
4541{
966f821c
DS
4542 struct peer_group *group;
4543 struct listnode *node, *nnode;
4544
718e3744 4545 if (connect > 65535)
4546 return BGP_ERR_INVALID_VALUE;
4547
4548 /* Set value to the configuration. */
4549 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
4550 peer->connect = connect;
4551
4552 /* Set value to timer setting. */
4553 peer->v_connect = connect;
4554
966f821c
DS
4555 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4556 return 0;
4557
4558 /* peer-group member updates. */
4559 group = peer->group;
4560 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4561 {
4562 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
4563 peer->connect = connect;
4564 peer->v_connect = connect;
4565 }
718e3744 4566 return 0;
4567}
4568
4569int
4570peer_timers_connect_unset (struct peer *peer)
4571{
966f821c
DS
4572 struct peer_group *group;
4573 struct listnode *node, *nnode;
4574
718e3744 4575 /* Clear configuration. */
4576 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
4577 peer->connect = 0;
4578
4579 /* Set timer setting to default value. */
4580 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
4581
966f821c
DS
4582 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4583 return 0;
4584
4585 /* peer-group member updates. */
4586 group = peer->group;
4587 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4588 {
4589 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
4590 peer->connect = 0;
4591 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
4592 }
718e3744 4593 return 0;
4594}
6b0655a2 4595
718e3744 4596int
4597peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
4598{
966f821c
DS
4599 struct peer_group *group;
4600 struct listnode *node, *nnode;
4601
718e3744 4602 if (routeadv > 600)
4603 return BGP_ERR_INVALID_VALUE;
4604
4605 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
4606 peer->routeadv = routeadv;
4607 peer->v_routeadv = routeadv;
4608
3f9c7369
DS
4609 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) {
4610 update_group_adjust_peer_afs (peer);
4611 if (peer->status == Established)
4612 bgp_announce_route_all (peer);
966f821c 4613 return 0;
3f9c7369 4614 }
966f821c
DS
4615
4616 /* peer-group member updates. */
4617 group = peer->group;
4618 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4619 {
4620 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
4621 peer->routeadv = routeadv;
4622 peer->v_routeadv = routeadv;
3f9c7369
DS
4623 update_group_adjust_peer_afs (peer);
4624 if (peer->status == Established)
4625 bgp_announce_route_all (peer);
966f821c
DS
4626 }
4627
718e3744 4628 return 0;
4629}
4630
4631int
4632peer_advertise_interval_unset (struct peer *peer)
4633{
966f821c
DS
4634 struct peer_group *group;
4635 struct listnode *node, *nnode;
4636
718e3744 4637 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
4638 peer->routeadv = 0;
4639
6d85b15b 4640 if (peer->sort == BGP_PEER_IBGP)
718e3744 4641 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
4642 else
4643 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
966f821c 4644
3f9c7369
DS
4645 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) {
4646 update_group_adjust_peer_afs (peer);
4647 if (peer->status == Established)
4648 bgp_announce_route_all (peer);
966f821c 4649 return 0;
3f9c7369 4650 }
966f821c
DS
4651
4652 /* peer-group member updates. */
4653 group = peer->group;
4654 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4655 {
4656 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
4657 peer->routeadv = 0;
4658
4659 if (peer->sort == BGP_PEER_IBGP)
4660 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
4661 else
4662 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3f9c7369
DS
4663
4664 update_group_adjust_peer_afs (peer);
4665 if (peer->status == Established)
4666 bgp_announce_route_all (peer);
966f821c 4667 }
718e3744 4668
4669 return 0;
4670}
6b0655a2 4671
718e3744 4672/* neighbor interface */
ffd0c037 4673void
fd79ac91 4674peer_interface_set (struct peer *peer, const char *str)
718e3744 4675{
4676 if (peer->ifname)
6e919709
DS
4677 XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
4678 peer->ifname = XSTRDUP(MTYPE_BGP_PEER_IFNAME, str);
718e3744 4679}
4680
ffd0c037 4681void
718e3744 4682peer_interface_unset (struct peer *peer)
4683{
4684 if (peer->ifname)
6e919709 4685 XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
718e3744 4686 peer->ifname = NULL;
718e3744 4687}
6b0655a2 4688
718e3744 4689/* Allow-as in. */
4690int
4691peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
4692{
4693 struct peer_group *group;
1eb8ef25 4694 struct listnode *node, *nnode;
718e3744 4695
4696 if (allow_num < 1 || allow_num > 10)
4697 return BGP_ERR_INVALID_VALUE;
4698
4699 if (peer->allowas_in[afi][safi] != allow_num)
4700 {
4701 peer->allowas_in[afi][safi] = allow_num;
4702 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
4703 peer_change_action (peer, afi, safi, peer_change_reset_in);
4704 }
4705
4706 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4707 return 0;
4708
4709 group = peer->group;
1eb8ef25 4710 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4711 {
4712 if (peer->allowas_in[afi][safi] != allow_num)
4713 {
4714 peer->allowas_in[afi][safi] = allow_num;
4715 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
4716 peer_change_action (peer, afi, safi, peer_change_reset_in);
4717 }
4718
4719 }
4720 return 0;
4721}
4722
4723int
4724peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
4725{
4726 struct peer_group *group;
1eb8ef25 4727 struct listnode *node, *nnode;
718e3744 4728
4729 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
4730 {
4731 peer->allowas_in[afi][safi] = 0;
4732 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
4733 }
4734
4735 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4736 return 0;
4737
4738 group = peer->group;
1eb8ef25 4739 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4740 {
4741 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
4742 {
4743 peer->allowas_in[afi][safi] = 0;
4744 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
4745 }
4746 }
4747 return 0;
4748}
6b0655a2 4749
718e3744 4750int
9d3f9705 4751peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
718e3744 4752{
4753 struct bgp *bgp = peer->bgp;
4754 struct peer_group *group;
1eb8ef25 4755 struct listnode *node, *nnode;
718e3744 4756
4757 if (peer_sort (peer) != BGP_PEER_EBGP
4758 && peer_sort (peer) != BGP_PEER_INTERNAL)
4759 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
4760
4761 if (bgp->as == as)
4762 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
4763
9d3f9705
AC
4764 if (peer->as == as)
4765 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
4766
718e3744 4767 if (peer->change_local_as == as &&
4768 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
9d3f9705
AC
4769 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
4770 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
4771 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
718e3744 4772 return 0;
4773
4774 peer->change_local_as = as;
4775 if (no_prepend)
4776 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4777 else
4778 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4779
9d3f9705
AC
4780 if (replace_as)
4781 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4782 else
4783 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4784
718e3744 4785 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4786 {
6aa136f1 4787 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4788 {
4789 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
4790 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4791 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4792 }
718e3744 4793 else
1ff9a340 4794 bgp_session_reset(peer);
718e3744 4795 return 0;
4796 }
4797
4798 group = peer->group;
1eb8ef25 4799 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4800 {
4801 peer->change_local_as = as;
4802 if (no_prepend)
4803 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4804 else
4805 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4806
9d3f9705
AC
4807 if (replace_as)
4808 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4809 else
4810 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4811
6aa136f1 4812 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4813 {
4814 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
4815 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4816 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4817 }
718e3744 4818 else
4819 BGP_EVENT_ADD (peer, BGP_Stop);
4820 }
4821
4822 return 0;
4823}
4824
4825int
4826peer_local_as_unset (struct peer *peer)
4827{
4828 struct peer_group *group;
1eb8ef25 4829 struct listnode *node, *nnode;
718e3744 4830
718e3744 4831 if (! peer->change_local_as)
4832 return 0;
4833
4834 peer->change_local_as = 0;
4835 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
9d3f9705 4836 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
718e3744 4837
4838 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4839 {
6aa136f1 4840 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4841 {
4842 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
4843 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4844 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4845 }
718e3744 4846 else
4847 BGP_EVENT_ADD (peer, BGP_Stop);
4848
4849 return 0;
4850 }
4851
4852 group = peer->group;
1eb8ef25 4853 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4854 {
4855 peer->change_local_as = 0;
4856 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
9d3f9705 4857 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
718e3744 4858
6aa136f1 4859 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4860 {
4861 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
4862 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4863 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4864 }
718e3744 4865 else
1ff9a340 4866 bgp_session_reset(peer);
718e3744 4867 }
4868 return 0;
4869}
6b0655a2 4870
0df7c91f
PJ
4871/* Set password for authenticating with the peer. */
4872int
4873peer_password_set (struct peer *peer, const char *password)
4874{
4875 struct listnode *nn, *nnode;
4876 int len = password ? strlen(password) : 0;
4877 int ret = BGP_SUCCESS;
4878
4879 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
4880 return BGP_ERR_INVALID_VALUE;
4881
4882 if (peer->password && strcmp (peer->password, password) == 0
4883 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4884 return 0;
4885
4886 if (peer->password)
4887 XFREE (MTYPE_PEER_PASSWORD, peer->password);
4888
4889 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
4890
4891 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4892 {
6aa136f1
VS
4893 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4894 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
0df7c91f 4895 else
1ff9a340 4896 bgp_session_reset(peer);
0df7c91f 4897
89ca90fa 4898 if (BGP_PEER_SU_UNSPEC(peer))
4899 return BGP_SUCCESS;
4900
0df7c91f
PJ
4901 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
4902 }
4903
4904 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
4905 {
4906 if (peer->password && strcmp (peer->password, password) == 0)
4907 continue;
4908
4909 if (peer->password)
4910 XFREE (MTYPE_PEER_PASSWORD, peer->password);
4911
4912 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
4913
6aa136f1 4914 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
0df7c91f
PJ
4915 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4916 else
1ff9a340 4917 bgp_session_reset(peer);
0df7c91f 4918
89ca90fa 4919 if (! BGP_PEER_SU_UNSPEC(peer))
4920 {
4921 if (bgp_md5_set (peer) < 0)
4922 ret = BGP_ERR_TCPSIG_FAILED;
4923 }
0df7c91f
PJ
4924 }
4925
4926 return ret;
4927}
4928
4929int
4930peer_password_unset (struct peer *peer)
4931{
4932 struct listnode *nn, *nnode;
4933
4934 if (!peer->password
4935 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4936 return 0;
4937
4938 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4939 {
6aa136f1 4940 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
0df7c91f
PJ
4941 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4942 else
1ff9a340 4943 bgp_session_reset(peer);
0df7c91f
PJ
4944
4945 if (peer->password)
4946 XFREE (MTYPE_PEER_PASSWORD, peer->password);
4947
4948 peer->password = NULL;
4949
89ca90fa 4950 if (! BGP_PEER_SU_UNSPEC(peer))
4951 bgp_md5_unset (peer);
0df7c91f
PJ
4952
4953 return 0;
4954 }
4955
4956 XFREE (MTYPE_PEER_PASSWORD, peer->password);
4957 peer->password = NULL;
4958
4959 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
4960 {
4961 if (!peer->password)
4962 continue;
4963
6aa136f1 4964 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
0df7c91f
PJ
4965 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4966 else
1ff9a340 4967 bgp_session_reset(peer);
0df7c91f
PJ
4968
4969 XFREE (MTYPE_PEER_PASSWORD, peer->password);
4970 peer->password = NULL;
4971
89ca90fa 4972 if (! BGP_PEER_SU_UNSPEC(peer))
4973 bgp_md5_unset (peer);
0df7c91f
PJ
4974 }
4975
4976 return 0;
4977}
6b0655a2 4978
3f9c7369 4979/*
3f9c7369 4980 * Helper function that is called after the name of the policy
94f34286
DS
4981 * being used by a peer has changed (AF specific). Automatically
4982 * initiates inbound or outbound processing as needed.
3f9c7369
DS
4983 */
4984static void
94f34286 4985peer_on_policy_change (struct peer *peer, afi_t afi, safi_t safi, int outbound)
3f9c7369 4986{
94f34286 4987 if (outbound)
3f9c7369 4988 {
94f34286
DS
4989 update_group_adjust_peer (peer_af_find (peer, afi, safi));
4990 if (peer->status == Established)
4991 bgp_announce_route(peer, afi, safi);
3f9c7369
DS
4992 }
4993 else
94f34286
DS
4994 {
4995 if (peer->status != Established)
4996 return;
4997
4998 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4999 bgp_soft_reconfig_in (peer, afi, safi);
5000 else if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
5001 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
5002 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
5003 }
3f9c7369
DS
5004}
5005
5006
718e3744 5007/* Set distribute list to the peer. */
5008int
5009peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
fd79ac91 5010 const char *name)
718e3744 5011{
5012 struct bgp_filter *filter;
5013 struct peer_group *group;
1eb8ef25 5014 struct listnode *node, *nnode;
718e3744 5015
718e3744 5016 if (direct != FILTER_IN && direct != FILTER_OUT)
5017 return BGP_ERR_INVALID_VALUE;
5018
718e3744 5019 filter = &peer->filter[afi][safi];
5020
5021 if (filter->plist[direct].name)
5022 return BGP_ERR_PEER_FILTER_CONFLICT;
5023
5024 if (filter->dlist[direct].name)
6e919709
DS
5025 XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name);
5026 filter->dlist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5027 filter->dlist[direct].alist = access_list_lookup (afi, name);
5028
5029 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 5030 {
94f34286
DS
5031 peer_on_policy_change(peer, afi, safi,
5032 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
5033 return 0;
5034 }
718e3744 5035
5036 group = peer->group;
1eb8ef25 5037 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5038 {
5039 filter = &peer->filter[afi][safi];
5040
718e3744 5041 if (filter->dlist[direct].name)
6e919709
DS
5042 XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name);
5043 filter->dlist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5044 filter->dlist[direct].alist = access_list_lookup (afi, name);
94f34286
DS
5045 peer_on_policy_change(peer, afi, safi,
5046 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5047 }
5048
5049 return 0;
5050}
5051
5052int
5053peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
5054{
5055 struct bgp_filter *filter;
5056 struct bgp_filter *gfilter;
5057 struct peer_group *group;
1eb8ef25 5058 struct listnode *node, *nnode;
718e3744 5059
718e3744 5060 if (direct != FILTER_IN && direct != FILTER_OUT)
5061 return BGP_ERR_INVALID_VALUE;
5062
718e3744 5063 filter = &peer->filter[afi][safi];
5064
5065 /* apply peer-group filter */
c8560b44 5066 if (peer_group_active(peer))
718e3744 5067 {
5068 gfilter = &peer->group->conf->filter[afi][safi];
5069
5070 if (gfilter->dlist[direct].name)
5071 {
5072 if (filter->dlist[direct].name)
6e919709
DS
5073 XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name);
5074 filter->dlist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->dlist[direct].name);
718e3744 5075 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
94f34286
DS
5076 peer_on_policy_change(peer, afi, safi,
5077 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5078 return 0;
5079 }
5080 }
5081
5082 if (filter->dlist[direct].name)
6e919709 5083 XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name);
718e3744 5084 filter->dlist[direct].name = NULL;
5085 filter->dlist[direct].alist = NULL;
5086
5087 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 5088 {
94f34286
DS
5089 peer_on_policy_change(peer, afi, safi,
5090 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
5091 return 0;
5092 }
718e3744 5093
94f34286
DS
5094 group = peer->group;
5095 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
5096 {
5097 filter = &peer->filter[afi][safi];
718e3744 5098
94f34286 5099 if (filter->dlist[direct].name)
6e919709 5100 XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name);
94f34286
DS
5101 filter->dlist[direct].name = NULL;
5102 filter->dlist[direct].alist = NULL;
5103 peer_on_policy_change(peer, afi, safi,
5104 (direct == FILTER_OUT) ? 1 : 0);
5105 }
718e3744 5106
5107 return 0;
5108}
5109
5110/* Update distribute list. */
94f2b392 5111static void
718e3744 5112peer_distribute_update (struct access_list *access)
5113{
5114 afi_t afi;
5115 safi_t safi;
5116 int direct;
1eb8ef25 5117 struct listnode *mnode, *mnnode;
5118 struct listnode *node, *nnode;
718e3744 5119 struct bgp *bgp;
5120 struct peer *peer;
5121 struct peer_group *group;
5122 struct bgp_filter *filter;
5123
1eb8ef25 5124 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
718e3744 5125 {
3f9c7369
DS
5126 if (access->name)
5127 update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST, access->name,
5128 0, 0);
1eb8ef25 5129 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 5130 {
5131 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5132 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
5133 {
5134 filter = &peer->filter[afi][safi];
5135
5136 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
5137 {
5138 if (filter->dlist[direct].name)
5139 filter->dlist[direct].alist =
5140 access_list_lookup (afi, filter->dlist[direct].name);
5141 else
5142 filter->dlist[direct].alist = NULL;
5143 }
5144 }
5145 }
1eb8ef25 5146 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 5147 {
5148 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5149 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
5150 {
5151 filter = &group->conf->filter[afi][safi];
5152
5153 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
5154 {
5155 if (filter->dlist[direct].name)
5156 filter->dlist[direct].alist =
5157 access_list_lookup (afi, filter->dlist[direct].name);
5158 else
5159 filter->dlist[direct].alist = NULL;
5160 }
5161 }
5162 }
5163 }
5164}
6b0655a2 5165
718e3744 5166/* Set prefix list to the peer. */
5167int
5168peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
fd79ac91 5169 const char *name)
718e3744 5170{
5171 struct bgp_filter *filter;
5172 struct peer_group *group;
1eb8ef25 5173 struct listnode *node, *nnode;
718e3744 5174
718e3744 5175 if (direct != FILTER_IN && direct != FILTER_OUT)
5176 return BGP_ERR_INVALID_VALUE;
5177
718e3744 5178 filter = &peer->filter[afi][safi];
5179
5180 if (filter->dlist[direct].name)
5181 return BGP_ERR_PEER_FILTER_CONFLICT;
5182
5183 if (filter->plist[direct].name)
6e919709
DS
5184 XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name);
5185 filter->plist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5186 filter->plist[direct].plist = prefix_list_lookup (afi, name);
5187
5188 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 5189 {
94f34286
DS
5190 peer_on_policy_change(peer, afi, safi,
5191 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
5192 return 0;
5193 }
718e3744 5194
5195 group = peer->group;
1eb8ef25 5196 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5197 {
5198 filter = &peer->filter[afi][safi];
5199
718e3744 5200 if (filter->plist[direct].name)
6e919709
DS
5201 XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name);
5202 filter->plist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5203 filter->plist[direct].plist = prefix_list_lookup (afi, name);
94f34286
DS
5204 peer_on_policy_change(peer, afi, safi,
5205 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5206 }
5207 return 0;
5208}
5209
5210int
5211peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
5212{
5213 struct bgp_filter *filter;
5214 struct bgp_filter *gfilter;
5215 struct peer_group *group;
1eb8ef25 5216 struct listnode *node, *nnode;
718e3744 5217
718e3744 5218 if (direct != FILTER_IN && direct != FILTER_OUT)
5219 return BGP_ERR_INVALID_VALUE;
5220
718e3744 5221 filter = &peer->filter[afi][safi];
5222
5223 /* apply peer-group filter */
c8560b44 5224 if (peer_group_active(peer))
718e3744 5225 {
5226 gfilter = &peer->group->conf->filter[afi][safi];
5227
5228 if (gfilter->plist[direct].name)
5229 {
5230 if (filter->plist[direct].name)
6e919709
DS
5231 XSTRDUP(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name);
5232 filter->plist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->plist[direct].name);
718e3744 5233 filter->plist[direct].plist = gfilter->plist[direct].plist;
94f34286
DS
5234 peer_on_policy_change(peer, afi, safi,
5235 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5236 return 0;
5237 }
5238 }
5239
5240 if (filter->plist[direct].name)
6e919709 5241 XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name);
718e3744 5242 filter->plist[direct].name = NULL;
5243 filter->plist[direct].plist = NULL;
5244
5245 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 5246 {
94f34286
DS
5247 peer_on_policy_change(peer, afi, safi,
5248 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
5249 return 0;
5250 }
718e3744 5251
5252 group = peer->group;
1eb8ef25 5253 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5254 {
5255 filter = &peer->filter[afi][safi];
5256
718e3744 5257 if (filter->plist[direct].name)
6e919709 5258 XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name);
718e3744 5259 filter->plist[direct].name = NULL;
5260 filter->plist[direct].plist = NULL;
94f34286
DS
5261 peer_on_policy_change(peer, afi, safi,
5262 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5263 }
5264
5265 return 0;
5266}
5267
5268/* Update prefix-list list. */
94f2b392 5269static void
718e3744 5270peer_prefix_list_update (struct prefix_list *plist)
5271{
1eb8ef25 5272 struct listnode *mnode, *mnnode;
5273 struct listnode *node, *nnode;
718e3744 5274 struct bgp *bgp;
5275 struct peer *peer;
5276 struct peer_group *group;
5277 struct bgp_filter *filter;
5278 afi_t afi;
5279 safi_t safi;
5280 int direct;
5281
1eb8ef25 5282 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
718e3744 5283 {
3f9c7369
DS
5284
5285 /*
5286 * Update the prefix-list on update groups.
5287 */
5288 update_group_policy_update(bgp, BGP_POLICY_PREFIX_LIST,
a38401b6 5289 plist ? prefix_list_name(plist) : NULL, 0, 0);
3f9c7369 5290
1eb8ef25 5291 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 5292 {
5293 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5294 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
5295 {
5296 filter = &peer->filter[afi][safi];
5297
5298 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
5299 {
5300 if (filter->plist[direct].name)
5301 filter->plist[direct].plist =
5302 prefix_list_lookup (afi, filter->plist[direct].name);
5303 else
5304 filter->plist[direct].plist = NULL;
5305 }
5306 }
5307 }
1eb8ef25 5308 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 5309 {
5310 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5311 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
5312 {
5313 filter = &group->conf->filter[afi][safi];
5314
5315 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
5316 {
5317 if (filter->plist[direct].name)
5318 filter->plist[direct].plist =
5319 prefix_list_lookup (afi, filter->plist[direct].name);
5320 else
5321 filter->plist[direct].plist = NULL;
5322 }
5323 }
5324 }
5325 }
5326}
6b0655a2 5327
718e3744 5328int
5329peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
fd79ac91 5330 const char *name)
718e3744 5331{
5332 struct bgp_filter *filter;
5333 struct peer_group *group;
1eb8ef25 5334 struct listnode *node, *nnode;
718e3744 5335
718e3744 5336 if (direct != FILTER_IN && direct != FILTER_OUT)
5337 return BGP_ERR_INVALID_VALUE;
5338
718e3744 5339 filter = &peer->filter[afi][safi];
5340
5341 if (filter->aslist[direct].name)
6e919709
DS
5342 XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name);
5343 filter->aslist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5344 filter->aslist[direct].aslist = as_list_lookup (name);
5345
5346 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 5347 {
94f34286
DS
5348 peer_on_policy_change(peer, afi, safi,
5349 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
5350 return 0;
5351 }
718e3744 5352
5353 group = peer->group;
1eb8ef25 5354 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5355 {
5356 filter = &peer->filter[afi][safi];
5357
718e3744 5358 if (filter->aslist[direct].name)
6e919709
DS
5359 XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name);
5360 filter->aslist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5361 filter->aslist[direct].aslist = as_list_lookup (name);
94f34286
DS
5362 peer_on_policy_change(peer, afi, safi,
5363 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5364 }
5365 return 0;
5366}
5367
5368int
5369peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
5370{
5371 struct bgp_filter *filter;
5372 struct bgp_filter *gfilter;
5373 struct peer_group *group;
1eb8ef25 5374 struct listnode *node, *nnode;
718e3744 5375
b5f29603 5376 if (direct != FILTER_IN && direct != FILTER_OUT)
718e3744 5377 return BGP_ERR_INVALID_VALUE;
5378
718e3744 5379 filter = &peer->filter[afi][safi];
5380
5381 /* apply peer-group filter */
c8560b44 5382 if (peer_group_active(peer))
718e3744 5383 {
5384 gfilter = &peer->group->conf->filter[afi][safi];
5385
5386 if (gfilter->aslist[direct].name)
5387 {
5388 if (filter->aslist[direct].name)
6e919709
DS
5389 XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name);
5390 filter->aslist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->aslist[direct].name);
718e3744 5391 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
94f34286
DS
5392 peer_on_policy_change(peer, afi, safi,
5393 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5394 return 0;
5395 }
5396 }
5397
5398 if (filter->aslist[direct].name)
6e919709 5399 XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name);
718e3744 5400 filter->aslist[direct].name = NULL;
5401 filter->aslist[direct].aslist = NULL;
5402
5403 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 5404 {
94f34286
DS
5405 peer_on_policy_change(peer, afi, safi,
5406 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
5407 return 0;
5408 }
718e3744 5409
5410 group = peer->group;
1eb8ef25 5411 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5412 {
5413 filter = &peer->filter[afi][safi];
5414
718e3744 5415 if (filter->aslist[direct].name)
6e919709 5416 XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name);
718e3744 5417 filter->aslist[direct].name = NULL;
5418 filter->aslist[direct].aslist = NULL;
94f34286
DS
5419 peer_on_policy_change(peer, afi, safi,
5420 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5421 }
5422
5423 return 0;
5424}
5425
94f2b392 5426static void
ffd0c037 5427peer_aslist_update (const char *aslist_name)
718e3744 5428{
5429 afi_t afi;
5430 safi_t safi;
5431 int direct;
1eb8ef25 5432 struct listnode *mnode, *mnnode;
5433 struct listnode *node, *nnode;
718e3744 5434 struct bgp *bgp;
5435 struct peer *peer;
5436 struct peer_group *group;
5437 struct bgp_filter *filter;
5438
1eb8ef25 5439 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
718e3744 5440 {
3f9c7369
DS
5441 update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST, aslist_name,
5442 0, 0);
5443
1eb8ef25 5444 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 5445 {
5446 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5447 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
5448 {
5449 filter = &peer->filter[afi][safi];
5450
5451 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
5452 {
5453 if (filter->aslist[direct].name)
5454 filter->aslist[direct].aslist =
5455 as_list_lookup (filter->aslist[direct].name);
5456 else
5457 filter->aslist[direct].aslist = NULL;
5458 }
5459 }
5460 }
1eb8ef25 5461 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 5462 {
5463 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5464 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
5465 {
5466 filter = &group->conf->filter[afi][safi];
5467
5468 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
5469 {
5470 if (filter->aslist[direct].name)
5471 filter->aslist[direct].aslist =
5472 as_list_lookup (filter->aslist[direct].name);
5473 else
5474 filter->aslist[direct].aslist = NULL;
5475 }
5476 }
5477 }
5478 }
5479}
3f9c7369 5480
518f0eb1
DS
5481static void
5482peer_aslist_add (char *aslist_name)
5483{
5484 peer_aslist_update (aslist_name);
5485 route_map_notify_dependencies((char *)aslist_name, RMAP_EVENT_ASLIST_ADDED);
5486}
5487
5488static void
ffd0c037 5489peer_aslist_del (const char *aslist_name)
518f0eb1
DS
5490{
5491 peer_aslist_update (aslist_name);
ffd0c037 5492 route_map_notify_dependencies(aslist_name, RMAP_EVENT_ASLIST_DELETED);
518f0eb1
DS
5493}
5494
6b0655a2 5495
718e3744 5496int
5497peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
fd79ac91 5498 const char *name)
718e3744 5499{
5500 struct bgp_filter *filter;
5501 struct peer_group *group;
1eb8ef25 5502 struct listnode *node, *nnode;
718e3744 5503
2a3d5731 5504 if (direct != RMAP_IN && direct != RMAP_OUT)
718e3744 5505 return BGP_ERR_INVALID_VALUE;
5506
718e3744 5507 filter = &peer->filter[afi][safi];
5508
5509 if (filter->map[direct].name)
6e919709 5510 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
518f0eb1 5511
6e919709 5512 filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5513 filter->map[direct].map = route_map_lookup_by_name (name);
5514
5515 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
518f0eb1 5516 {
94f34286
DS
5517 peer_on_policy_change(peer, afi, safi,
5518 (direct == RMAP_OUT) ? 1 : 0);
518f0eb1
DS
5519 return 0;
5520 }
718e3744 5521
5522 group = peer->group;
1eb8ef25 5523 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5524 {
5525 filter = &peer->filter[afi][safi];
5526
718e3744 5527 if (filter->map[direct].name)
6e919709
DS
5528 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
5529 filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5530 filter->map[direct].map = route_map_lookup_by_name (name);
94f34286
DS
5531 peer_on_policy_change(peer, afi, safi,
5532 (direct == RMAP_OUT) ? 1 : 0);
718e3744 5533 }
5534 return 0;
5535}
5536
5537/* Unset route-map from the peer. */
5538int
5539peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
5540{
5541 struct bgp_filter *filter;
5542 struct bgp_filter *gfilter;
5543 struct peer_group *group;
1eb8ef25 5544 struct listnode *node, *nnode;
718e3744 5545
2a3d5731 5546 if (direct != RMAP_IN && direct != RMAP_OUT)
718e3744 5547 return BGP_ERR_INVALID_VALUE;
5548
718e3744 5549 filter = &peer->filter[afi][safi];
5550
5551 /* apply peer-group filter */
c8560b44 5552 if (peer_group_active(peer))
718e3744 5553 {
5554 gfilter = &peer->group->conf->filter[afi][safi];
5555
5556 if (gfilter->map[direct].name)
5557 {
5558 if (filter->map[direct].name)
6e919709
DS
5559 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
5560 filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->map[direct].name);
718e3744 5561 filter->map[direct].map = gfilter->map[direct].map;
94f34286
DS
5562 peer_on_policy_change(peer, afi, safi,
5563 (direct == RMAP_OUT) ? 1 : 0);
718e3744 5564 return 0;
5565 }
5566 }
5567
5568 if (filter->map[direct].name)
6e919709 5569 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
718e3744 5570 filter->map[direct].name = NULL;
5571 filter->map[direct].map = NULL;
5572
5573 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
518f0eb1 5574 {
94f34286
DS
5575 peer_on_policy_change(peer, afi, safi,
5576 (direct == RMAP_OUT) ? 1 : 0);
518f0eb1
DS
5577 return 0;
5578 }
718e3744 5579
5580 group = peer->group;
1eb8ef25 5581 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5582 {
5583 filter = &peer->filter[afi][safi];
5584
718e3744 5585 if (filter->map[direct].name)
6e919709 5586 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
718e3744 5587 filter->map[direct].name = NULL;
5588 filter->map[direct].map = NULL;
94f34286
DS
5589 peer_on_policy_change(peer, afi, safi,
5590 (direct == RMAP_OUT) ? 1 : 0);
718e3744 5591 }
5592 return 0;
5593}
6b0655a2 5594
718e3744 5595/* Set unsuppress-map to the peer. */
5596int
fd79ac91 5597peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
5598 const char *name)
718e3744 5599{
5600 struct bgp_filter *filter;
5601 struct peer_group *group;
1eb8ef25 5602 struct listnode *node, *nnode;
718e3744 5603
718e3744 5604 filter = &peer->filter[afi][safi];
5605
5606 if (filter->usmap.name)
6e919709 5607 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
718e3744 5608
6e919709 5609 filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5610 filter->usmap.map = route_map_lookup_by_name (name);
5611
5612 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
518f0eb1 5613 {
94f34286 5614 peer_on_policy_change(peer, afi, safi, 1);
518f0eb1
DS
5615 return 0;
5616 }
718e3744 5617
5618 group = peer->group;
1eb8ef25 5619 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5620 {
5621 filter = &peer->filter[afi][safi];
5622
718e3744 5623 if (filter->usmap.name)
6e919709
DS
5624 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
5625 filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5626 filter->usmap.map = route_map_lookup_by_name (name);
94f34286 5627 peer_on_policy_change(peer, afi, safi, 1);
718e3744 5628 }
5629 return 0;
5630}
5631
5632/* Unset route-map from the peer. */
5633int
5634peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
5635{
5636 struct bgp_filter *filter;
5637 struct peer_group *group;
1eb8ef25 5638 struct listnode *node, *nnode;
718e3744 5639
718e3744 5640 filter = &peer->filter[afi][safi];
5641
5642 if (filter->usmap.name)
6e919709 5643 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
718e3744 5644 filter->usmap.name = NULL;
5645 filter->usmap.map = NULL;
5646
5647 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
518f0eb1 5648 {
94f34286 5649 peer_on_policy_change(peer, afi, safi, 1);
518f0eb1
DS
5650 return 0;
5651 }
718e3744 5652
5653 group = peer->group;
1eb8ef25 5654 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5655 {
5656 filter = &peer->filter[afi][safi];
5657
718e3744 5658 if (filter->usmap.name)
6e919709 5659 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
718e3744 5660 filter->usmap.name = NULL;
5661 filter->usmap.map = NULL;
94f34286 5662 peer_on_policy_change(peer, afi, safi, 1);
718e3744 5663 }
5664 return 0;
5665}
6b0655a2 5666
718e3744 5667int
5668peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
0a486e5f 5669 u_int32_t max, u_char threshold,
5670 int warning, u_int16_t restart)
718e3744 5671{
5672 struct peer_group *group;
1eb8ef25 5673 struct listnode *node, *nnode;
718e3744 5674
718e3744 5675 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5676 peer->pmax[afi][safi] = max;
e0701b79 5677 peer->pmax_threshold[afi][safi] = threshold;
0a486e5f 5678 peer->pmax_restart[afi][safi] = restart;
718e3744 5679 if (warning)
5680 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5681 else
5682 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5683
fc9a856f 5684 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
718e3744 5685 {
fc9a856f
DS
5686 group = peer->group;
5687 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
5688 {
fc9a856f
DS
5689 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5690 peer->pmax[afi][safi] = max;
5691 peer->pmax_threshold[afi][safi] = threshold;
5692 peer->pmax_restart[afi][safi] = restart;
5693 if (warning)
5694 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5695 else
5696 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5697
5698 if ((peer->status == Established) && (peer->afc[afi][safi]))
5699 bgp_maximum_prefix_overflow (peer, afi, safi, 1);
5700 }
5701 }
5702 else
5703 {
5704 if ((peer->status == Established) && (peer->afc[afi][safi]))
5705 bgp_maximum_prefix_overflow (peer, afi, safi, 1);
718e3744 5706 }
fc9a856f 5707
718e3744 5708 return 0;
5709}
5710
5711int
5712peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
5713{
5714 struct peer_group *group;
1eb8ef25 5715 struct listnode *node, *nnode;
718e3744 5716
718e3744 5717 /* apply peer-group config */
c8560b44 5718 if (peer_group_active(peer))
718e3744 5719 {
5720 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
5721 PEER_FLAG_MAX_PREFIX))
5722 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5723 else
5724 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5725
5726 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
5727 PEER_FLAG_MAX_PREFIX_WARNING))
5728 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5729 else
5730 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5731
5732 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
e0701b79 5733 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
0a486e5f 5734 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
718e3744 5735 return 0;
5736 }
5737
5738 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5739 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5740 peer->pmax[afi][safi] = 0;
0a486e5f 5741 peer->pmax_threshold[afi][safi] = 0;
5742 peer->pmax_restart[afi][safi] = 0;
718e3744 5743
5744 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5745 return 0;
5746
5747 group = peer->group;
1eb8ef25 5748 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5749 {
718e3744 5750 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5751 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5752 peer->pmax[afi][safi] = 0;
0a486e5f 5753 peer->pmax_threshold[afi][safi] = 0;
5754 peer->pmax_restart[afi][safi] = 0;
718e3744 5755 }
5756 return 0;
5757}
5f9adb5d 5758
c43ed2e4 5759int is_ebgp_multihop_configured (struct peer *peer)
5f9adb5d
DL
5760{
5761 struct peer_group *group;
5762 struct listnode *node, *nnode;
5763 struct peer *peer1;
5764
5765 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5766 {
5767 group = peer->group;
5d804b43
PM
5768 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
5769 (group->conf->ttl != 1))
5f9adb5d
DL
5770 return 1;
5771
5772 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
5773 {
5d804b43
PM
5774 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
5775 (peer1->ttl != 1))
5f9adb5d
DL
5776 return 1;
5777 }
5778 }
5779 else
5780 {
5d804b43
PM
5781 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
5782 (peer->ttl != 1))
5f9adb5d
DL
5783 return 1;
5784 }
5785 return 0;
5786}
5787
fa411a21
NH
5788/* Set # of hops between us and BGP peer. */
5789int
5790peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
5791{
5792 struct peer_group *group;
5793 struct listnode *node, *nnode;
fa411a21
NH
5794 int ret;
5795
5796 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
5797
fa411a21
NH
5798 /* We cannot configure ttl-security hops when ebgp-multihop is already
5799 set. For non peer-groups, the check is simple. For peer-groups, it's
5800 slightly messy, because we need to check both the peer-group structure
5801 and all peer-group members for any trace of ebgp-multihop configuration
5802 before actually applying the ttl-security rules. Cisco really made a
5803 mess of this configuration parameter, and OpenBGPD got it right.
5804 */
e5cc509c
DS
5805
5806 if ((peer->gtsm_hops == 0) && (peer->sort != BGP_PEER_IBGP))
5f9adb5d
DL
5807 {
5808 if (is_ebgp_multihop_configured (peer))
5809 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
fa411a21 5810
e5cc509c
DS
5811 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5812 {
5813 peer->gtsm_hops = gtsm_hops;
fa411a21 5814
e5cc509c
DS
5815 /* Calling ebgp multihop also resets the session.
5816 * On restart, NHT will get setup correctly as will the
5817 * min & max ttls on the socket. The return value is
5818 * irrelevant.
5819 */
5820 ret = peer_ebgp_multihop_set (peer, MAXTTL);
5821
5822 if (ret != 0)
5823 return ret;
5824 }
5825 else
5826 {
5827 group = peer->group;
5828 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
5829 {
5830 peer->gtsm_hops = group->conf->gtsm_hops;
5831
5832 /* Calling ebgp multihop also resets the session.
5833 * On restart, NHT will get setup correctly as will the
5834 * min & max ttls on the socket. The return value is
5835 * irrelevant.
5836 */
5837 ret = peer_ebgp_multihop_set (peer, MAXTTL);
5838 }
5839 }
fa411a21
NH
5840 }
5841 else
5842 {
e5cc509c
DS
5843 /* Post the first gtsm setup or if its ibgp, maxttl setting isn't
5844 * necessary, just set the minttl.
5845 */
5846 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
fa411a21 5847 {
e5cc509c 5848 peer->gtsm_hops = gtsm_hops;
fa411a21 5849
e5cc509c
DS
5850 if (peer->fd >= 0)
5851 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
5852 MAXTTL + 1 - gtsm_hops);
5853 if ((peer->status < Established) && peer->doppelganger &&
5854 (peer->doppelganger->fd >= 0))
5855 sockopt_minttl (peer->su.sa.sa_family, peer->doppelganger->fd,
5856 MAXTTL + 1 - gtsm_hops);
5857 }
5858 else
5859 {
5860 group = peer->group;
5861 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
f5a4827d 5862 {
e5cc509c
DS
5863 peer->gtsm_hops = group->conf->gtsm_hops;
5864
5865 /* Change setting of existing peer
5866 * established then change value (may break connectivity)
5867 * not established yet (teardown session and restart)
5868 * no session then do nothing (will get handled by next connection)
5869 */
f5a4827d
SH
5870 if (peer->fd >= 0 && peer->gtsm_hops != 0)
5871 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
5872 MAXTTL + 1 - peer->gtsm_hops);
e5cc509c
DS
5873 if ((peer->status < Established) && peer->doppelganger &&
5874 (peer->doppelganger->fd >= 0))
5875 sockopt_minttl (peer->su.sa.sa_family, peer->doppelganger->fd,
5876 MAXTTL + 1 - gtsm_hops);
5877
f5a4827d 5878 }
fa411a21
NH
5879 }
5880 }
5881
5882 return 0;
5883}
5884
5885int
5886peer_ttl_security_hops_unset (struct peer *peer)
5887{
5888 struct peer_group *group;
5889 struct listnode *node, *nnode;
e5cc509c 5890 int ret = 0;
fa411a21
NH
5891
5892 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
5893
fa411a21
NH
5894 /* if a peer-group member, then reset to peer-group default rather than 0 */
5895 if (peer_group_active (peer))
5896 peer->gtsm_hops = peer->group->conf->gtsm_hops;
5897 else
5898 peer->gtsm_hops = 0;
5899
fa411a21
NH
5900 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5901 {
e5cc509c
DS
5902 /* Invoking ebgp_multihop_set will set the TTL back to the original
5903 * value as well as restting the NHT and such. The session is reset.
5904 */
5905 if (peer->sort == BGP_PEER_EBGP)
5906 ret = peer_ebgp_multihop_unset (peer);
5907 else
5908 {
5909 if (peer->fd >= 0)
5910 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
1ff9a340 5911
e5cc509c
DS
5912 if ((peer->status < Established) && peer->doppelganger &&
5913 (peer->doppelganger->fd >= 0))
5914 sockopt_minttl (peer->su.sa.sa_family,
5915 peer->doppelganger->fd, 0);
5916 }
fa411a21
NH
5917 }
5918 else
5919 {
5920 group = peer->group;
5921 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
5922 {
fa411a21 5923 peer->gtsm_hops = 0;
e5cc509c
DS
5924 if (peer->sort == BGP_PEER_EBGP)
5925 ret = peer_ebgp_multihop_unset (peer);
5926 else
5927 {
5928 if (peer->fd >= 0)
5929 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
1ff9a340 5930
e5cc509c
DS
5931 if ((peer->status < Established) && peer->doppelganger &&
5932 (peer->doppelganger->fd >= 0))
5933 sockopt_minttl (peer->su.sa.sa_family,
5934 peer->doppelganger->fd, 0);
5935 }
fa411a21
NH
5936 }
5937 }
5938
88177fe3 5939 return ret;
fa411a21 5940}
6b0655a2 5941
1ff9a340
DS
5942/*
5943 * If peer clear is invoked in a loop for all peers on the BGP instance,
5944 * it may end up freeing the doppelganger, and if this was the next node
5945 * to the current node, we would end up accessing the freed next node.
5946 * Pass along additional parameter which can be updated if next node
5947 * is freed; only required when walking the peer list on BGP instance.
5948 */
718e3744 5949int
1ff9a340 5950peer_clear (struct peer *peer, struct listnode **nnode)
718e3744 5951{
5952 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
5953 {
0a486e5f 5954 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
5955 {
5956 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
5957 if (peer->t_pmax_restart)
5958 {
5959 BGP_TIMER_OFF (peer->t_pmax_restart);
16286195 5960 if (bgp_debug_neighbor_events(peer))
0a486e5f 5961 zlog_debug ("%s Maximum-prefix restart timer canceled",
5962 peer->host);
5963 }
5964 BGP_EVENT_ADD (peer, BGP_Start);
5965 return 0;
5966 }
5967
718e3744 5968 peer->v_start = BGP_INIT_START_TIMER;
6aa136f1 5969 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
718e3744 5970 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5971 BGP_NOTIFY_CEASE_ADMIN_RESET);
5972 else
1ff9a340 5973 bgp_session_reset_safe(peer, nnode);
718e3744 5974 }
5975 return 0;
5976}
5977
5978int
5979peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
5980 enum bgp_clear_type stype)
5981{
6a646146
DS
5982 struct peer_af *paf;
5983
718e3744 5984 if (peer->status != Established)
5985 return 0;
5986
5987 if (! peer->afc[afi][safi])
5988 return BGP_ERR_AF_UNCONFIGURED;
5989
e9a0c656
TT
5990 peer->rtt = sockopt_tcp_rtt (peer->fd);
5991
718e3744 5992 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
6a646146
DS
5993 {
5994 /* Clear the "neighbor x.x.x.x default-originate" flag */
5995 paf = peer_af_find (peer, afi, safi);
5996 if (paf && paf->subgroup &&
5997 CHECK_FLAG (paf->subgroup->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE))
5998 UNSET_FLAG (paf->subgroup->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE);
5999
6000 bgp_announce_route (peer, afi, safi);
6001 }
718e3744 6002
6003 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
6004 {
6005 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
6006 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
6007 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
6008 {
6009 struct bgp_filter *filter = &peer->filter[afi][safi];
6010 u_char prefix_type;
6011
6012 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
6013 prefix_type = ORF_TYPE_PREFIX;
6014 else
6015 prefix_type = ORF_TYPE_PREFIX_OLD;
6016
6017 if (filter->plist[FILTER_IN].plist)
6018 {
6019 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
6020 bgp_route_refresh_send (peer, afi, safi,
6021 prefix_type, REFRESH_DEFER, 1);
6022 bgp_route_refresh_send (peer, afi, safi, prefix_type,
6023 REFRESH_IMMEDIATE, 0);
6024 }
6025 else
6026 {
6027 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
6028 bgp_route_refresh_send (peer, afi, safi,
6029 prefix_type, REFRESH_IMMEDIATE, 1);
6030 else
6031 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
6032 }
6033 return 0;
6034 }
6035 }
6036
6037 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
6038 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
6039 {
6040 /* If neighbor has soft reconfiguration inbound flag.
6041 Use Adj-RIB-In database. */
6042 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
6043 bgp_soft_reconfig_in (peer, afi, safi);
6044 else
6045 {
6046 /* If neighbor has route refresh capability, send route refresh
6047 message to the peer. */
6048 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
6049 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
6050 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
6051 else
6052 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
6053 }
6054 }
6055 return 0;
6056}
6b0655a2 6057
fd79ac91 6058/* Display peer uptime.*/
6059/* XXX: why does this function return char * when it takes buffer? */
718e3744 6060char *
856ca177 6061peer_uptime (time_t uptime2, char *buf, size_t len, u_char use_json, json_object *json)
718e3744 6062{
6063 time_t uptime1;
6064 struct tm *tm;
6065
6066 /* Check buffer length. */
6067 if (len < BGP_UPTIME_LEN)
6068 {
856ca177
MS
6069 if (!use_json)
6070 {
6071 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
6072 /* XXX: should return status instead of buf... */
6073 snprintf (buf, len, "<error> ");
6074 }
fd79ac91 6075 return buf;
718e3744 6076 }
6077
6078 /* If there is no connection has been done before print `never'. */
6079 if (uptime2 == 0)
6080 {
856ca177
MS
6081 if (use_json)
6082 json_object_string_add(json, "peerUptime", "never");
6083 else
6084 snprintf (buf, len, "never");
718e3744 6085 return buf;
6086 }
6087
6088 /* Get current time. */
65957886 6089 uptime1 = bgp_clock ();
718e3744 6090 uptime1 -= uptime2;
6091 tm = gmtime (&uptime1);
6092
6093 /* Making formatted timer strings. */
6094#define ONE_DAY_SECOND 60*60*24
3a6229da
PJ
6095#define ONE_WEEK_SECOND ONE_DAY_SECOND*7
6096#define ONE_YEAR_SECOND ONE_DAY_SECOND*365
718e3744 6097
856ca177
MS
6098 if (use_json)
6099 {
1d889348 6100 unsigned long time_store;
1d889348 6101 unsigned long sec_msec = 1000;
3a6229da
PJ
6102 unsigned long minute_msec = sec_msec * 60;
6103 unsigned long hour_msec = minute_msec * 60;
6104 unsigned long day_msec = hour_msec * 24;
6105 unsigned long year_msec = day_msec *365;
1d889348
DS
6106
6107 time_store =
3a6229da 6108 year_msec * tm->tm_year +
1d889348
DS
6109 day_msec * tm->tm_yday +
6110 hour_msec * tm->tm_hour +
6111 minute_msec * tm->tm_min +
6112 sec_msec * tm->tm_sec;
6113 json_object_int_add(json, "peerUptimeMsec", time_store);
6114 }
6115
6116 if (uptime1 < ONE_DAY_SECOND)
6117 snprintf (buf, len, "%02d:%02d:%02d",
6118 tm->tm_hour, tm->tm_min, tm->tm_sec);
6119 else if (uptime1 < ONE_WEEK_SECOND)
6120 snprintf (buf, len, "%dd%02dh%02dm",
6121 tm->tm_yday, tm->tm_hour, tm->tm_min);
3a6229da 6122 else if (uptime1 < ONE_YEAR_SECOND)
1d889348
DS
6123 snprintf (buf, len, "%02dw%dd%02dh",
6124 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
3a6229da
PJ
6125 else
6126 snprintf (buf, len, "%02dy%02dw%dd",
6127 tm->tm_year - 70, tm->tm_yday/7,
6128 tm->tm_yday - ((tm->tm_yday/7) * 7));
1d889348 6129
718e3744 6130 return buf;
6131}
6b0655a2 6132
400b1fad
DW
6133static void
6134afi_header_vty_out (struct vty *vty, afi_t afi, safi_t safi,
6135 int *write, const char *format, ...)
6136{
6137 va_list args;
6138 int len = 0;
6139 char buf[1024];
6140
6141 bgp_config_write_family_header (vty, afi, safi, write);
6142
6143 if (vty_shell (vty))
6144 {
6145 va_start (args, format);
6146 vprintf (format, args);
6147 va_end (args);
6148 }
6149 else
6150 {
6151 va_start (args, format);
6152 len = vsnprintf (buf, sizeof(buf), format, args);
6153 va_end (args);
6154
6155 buffer_put (vty->obuf, (u_char *) buf, len);
6156 }
6157}
6158
94f2b392 6159static void
718e3744 6160bgp_config_write_filter (struct vty *vty, struct peer *peer,
400b1fad 6161 afi_t afi, safi_t safi, int *write)
718e3744 6162{
6163 struct bgp_filter *filter;
6164 struct bgp_filter *gfilter = NULL;
6165 char *addr;
6166 int in = FILTER_IN;
6167 int out = FILTER_OUT;
6168
6169 addr = peer->host;
6170 filter = &peer->filter[afi][safi];
c8560b44
DW
6171
6172 if (peer_group_active(peer))
718e3744 6173 gfilter = &peer->group->conf->filter[afi][safi];
6174
6175 /* distribute-list. */
6176 if (filter->dlist[in].name)
6177 if (! gfilter || ! gfilter->dlist[in].name
6178 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
400b1fad
DW
6179 {
6180 afi_header_vty_out (vty, afi, safi, write,
6181 " neighbor %s distribute-list %s in%s",
6182 addr, filter->dlist[in].name, VTY_NEWLINE);
6183 }
6184
718e3744 6185 if (filter->dlist[out].name && ! gfilter)
400b1fad
DW
6186 {
6187 afi_header_vty_out (vty, afi, safi, write,
6188 " neighbor %s distribute-list %s out%s",
6189 addr, filter->dlist[out].name, VTY_NEWLINE);
6190 }
718e3744 6191
6192 /* prefix-list. */
6193 if (filter->plist[in].name)
6194 if (! gfilter || ! gfilter->plist[in].name
6195 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
400b1fad
DW
6196 {
6197 afi_header_vty_out (vty, afi, safi, write,
6198 " neighbor %s prefix-list %s in%s",
6199 addr, filter->plist[in].name, VTY_NEWLINE);
6200 }
6201
718e3744 6202 if (filter->plist[out].name && ! gfilter)
400b1fad
DW
6203 {
6204 afi_header_vty_out (vty, afi, safi, write,
6205 " neighbor %s prefix-list %s out%s",
6206 addr, filter->plist[out].name, VTY_NEWLINE);
6207 }
718e3744 6208
6209 /* route-map. */
fee0f4c6 6210 if (filter->map[RMAP_IN].name)
6211 if (! gfilter || ! gfilter->map[RMAP_IN].name
6212 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
400b1fad
DW
6213 {
6214 afi_header_vty_out (vty, afi, safi, write,
6215 " neighbor %s route-map %s in%s",
6216 addr, filter->map[RMAP_IN].name, VTY_NEWLINE);
6217 }
6218
2bd5af06
DS
6219 if (filter->map[RMAP_OUT].name)
6220 if (! gfilter || ! gfilter->map[RMAP_OUT].name
6221 || strcmp (filter->map[RMAP_OUT].name, gfilter->map[RMAP_OUT].name) != 0)
400b1fad
DW
6222 {
6223 afi_header_vty_out (vty, afi, safi, write,
6224 " neighbor %s route-map %s out%s",
6225 addr, filter->map[RMAP_OUT].name, VTY_NEWLINE);
6226 }
6227
718e3744 6228 /* unsuppress-map */
6229 if (filter->usmap.name && ! gfilter)
400b1fad
DW
6230 {
6231 afi_header_vty_out (vty, afi, safi, write,
6232 " neighbor %s unsuppress-map %s%s",
6233 addr, filter->usmap.name, VTY_NEWLINE);
6234 }
718e3744 6235
6236 /* filter-list. */
6237 if (filter->aslist[in].name)
6238 if (! gfilter || ! gfilter->aslist[in].name
6239 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
400b1fad
DW
6240 {
6241 afi_header_vty_out (vty, afi, safi, write,
6242 " neighbor %s filter-list %s in%s",
6243 addr, filter->aslist[in].name, VTY_NEWLINE);
6244 }
6245
718e3744 6246 if (filter->aslist[out].name && ! gfilter)
400b1fad
DW
6247 {
6248 afi_header_vty_out (vty, afi, safi, write,
6249 " neighbor %s filter-list %s out%s",
6250 addr, filter->aslist[out].name, VTY_NEWLINE);
6251 }
718e3744 6252}
6253
6254/* BGP peer configuration display function. */
94f2b392 6255static void
0b960b4d
DW
6256bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp,
6257 struct peer *peer)
718e3744 6258{
718e3744 6259 struct peer *g_peer = NULL;
6260 char buf[SU_ADDRSTRLEN];
6261 char *addr;
6262
f14e6fdb
DS
6263 /* Skip dynamic neighbors. */
6264 if (peer_dynamic_neighbor (peer))
6265 return;
6266
a80beece
DS
6267 if (peer->conf_if)
6268 addr = peer->conf_if;
6269 else
6270 addr = peer->host;
6271
718e3744 6272 /************************************
6273 ****** Global to the neighbor ******
6274 ************************************/
0b960b4d 6275 if (peer->conf_if)
718e3744 6276 {
0b960b4d 6277 if (CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))
4c48cf63 6278 vty_out (vty, " neighbor %s interface v6only", addr);
0b960b4d 6279 else
4c48cf63
DW
6280 vty_out (vty, " neighbor %s interface", addr);
6281
6282 if (peer_group_active (peer))
6283 vty_out (vty, " peer-group %s", peer->group->name);
6284
6285 vty_out (vty, "%s", VTY_NEWLINE);
0b960b4d 6286 }
a80beece 6287
c8560b44
DW
6288 /* remote-as and peer-group */
6289 /* peer is a member of a peer-group */
6290 if (peer_group_active (peer))
0b960b4d 6291 {
c8560b44 6292 g_peer = peer->group->conf;
0b960b4d 6293
ff40e335 6294 if (g_peer->as_type == AS_UNSPECIFIED)
0b960b4d
DW
6295 {
6296 if (peer->as_type == AS_SPECIFIED)
6297 {
6298 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
6299 VTY_NEWLINE);
6300 }
6301 else if (peer->as_type == AS_INTERNAL)
6302 {
6303 vty_out (vty, " neighbor %s remote-as internal%s", addr, VTY_NEWLINE);
6304 }
6305 else if (peer->as_type == AS_EXTERNAL)
6306 {
6307 vty_out (vty, " neighbor %s remote-as external%s", addr, VTY_NEWLINE);
6308 }
6309 }
c8560b44 6310
4c48cf63
DW
6311 /* For swpX peers we displayed the peer-group
6312 * via 'neighbor swpX interface peer-group WORD' */
6313 if (!peer->conf_if)
6314 vty_out (vty, " neighbor %s peer-group %s%s", addr,
6315 peer->group->name, VTY_NEWLINE);
c8560b44
DW
6316 }
6317
6318 /* peer is NOT a member of a peer-group */
6319 else
6320 {
6321 /* peer is a peer-group, declare the peer-group */
6322 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
6323 {
6324 vty_out (vty, " neighbor %s peer-group%s", addr,
6325 VTY_NEWLINE);
6326 }
6327
6328 if (peer->as_type == AS_SPECIFIED)
6329 {
6330 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
6331 VTY_NEWLINE);
6332 }
6333 else if (peer->as_type == AS_INTERNAL)
0b960b4d 6334 {
c8560b44
DW
6335 vty_out (vty, " neighbor %s remote-as internal%s", addr, VTY_NEWLINE);
6336 }
6337 else if (peer->as_type == AS_EXTERNAL)
6338 {
6339 vty_out (vty, " neighbor %s remote-as external%s", addr, VTY_NEWLINE);
0b960b4d
DW
6340 }
6341 }
718e3744 6342
0b960b4d
DW
6343 /* local-as */
6344 if (peer->change_local_as)
6345 {
06830cb8
DW
6346 if (! peer_group_active (peer)
6347 || peer->change_local_as != g_peer->change_local_as
6348 || (CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) !=
6349 CHECK_FLAG (g_peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
6350 || (CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) !=
6351 CHECK_FLAG (g_peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS)))
0b960b4d
DW
6352 {
6353 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
6354 peer->change_local_as,
6355 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
6356 " no-prepend" : "",
6357 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
6358 " replace-as" : "", VTY_NEWLINE);
6359 }
6360 }
718e3744 6361
0b960b4d
DW
6362 /* description */
6363 if (peer->desc)
6364 {
6365 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
6366 VTY_NEWLINE);
6367 }
718e3744 6368
0b960b4d
DW
6369 /* shutdown */
6370 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
6371 {
6372 if (! peer_group_active (peer) ||
6373 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
6374 {
6375 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
6376 }
6377 }
d5a5c8f0 6378
0b960b4d
DW
6379 /* bfd */
6380 if (peer->bfd_info)
6381 {
6382 if (! peer_group_active (peer) || ! g_peer->bfd_info)
6383 {
6384 bgp_bfd_peer_config_write(vty, peer, addr);
6385 }
6386 }
718e3744 6387
0b960b4d
DW
6388 /* password */
6389 if (peer->password)
6390 {
6391 if (!peer_group_active (peer)
6392 || ! g_peer->password
6393 || strcmp (peer->password, g_peer->password) != 0)
6394 {
6395 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
6396 VTY_NEWLINE);
6397 }
6398 }
6399
6400 /* neighbor solo */
6401 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
6402 {
6403 if (!peer_group_active (peer))
6404 {
6405 vty_out (vty, " neighbor %s solo%s", addr, VTY_NEWLINE);
6406 }
6407 }
6408
6409 /* BGP port */
6410 if (peer->port != BGP_PORT_DEFAULT)
6411 {
6412 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
6413 VTY_NEWLINE);
6414 }
6415
6416 /* Local interface name */
6417 if (peer->ifname)
6418 {
6419 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
6420 VTY_NEWLINE);
6421 }
6422
6423 /* passive */
6424 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
6425 {
6426 if (! peer_group_active (peer) ||
6427 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
6428 {
6429 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
6430 }
6431 }
6432
6433 /* ebgp-multihop */
6434 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
6435 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
6436 {
6437 if (! peer_group_active (peer) || g_peer->ttl != peer->ttl)
6438 {
6439 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
6440 VTY_NEWLINE);
6441 }
6442 }
6443
6444 /* ttl-security hops */
6445 if (peer->gtsm_hops != 0)
6446 {
6447 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
6448 {
89b6d1f8 6449 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
fa411a21 6450 peer->gtsm_hops, VTY_NEWLINE);
0b960b4d
DW
6451 }
6452 }
fa411a21 6453
0b960b4d
DW
6454 /* disable-connected-check */
6455 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
6456 {
6457 if (! peer_group_active (peer) ||
6458 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
6459 {
6460 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
6461 }
6462 }
718e3744 6463
0b960b4d
DW
6464 /* update-source */
6465 if (peer->update_if)
6466 {
6467 if (! peer_group_active (peer) || ! g_peer->update_if
6468 || strcmp (g_peer->update_if, peer->update_if) != 0)
6469 {
6470 vty_out (vty, " neighbor %s update-source %s%s", addr,
6471 peer->update_if, VTY_NEWLINE);
6472 }
6473 }
6474 if (peer->update_source)
6475 {
6476 if (! peer_group_active (peer) || ! g_peer->update_source
6477 || sockunion_cmp (g_peer->update_source,
6478 peer->update_source) != 0)
6479 {
6480 vty_out (vty, " neighbor %s update-source %s%s", addr,
6481 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
6482 VTY_NEWLINE);
6483 }
6484 }
718e3744 6485
0b960b4d 6486 /* advertisement-interval */
813d4307
DW
6487 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV)
6488 && peer->v_routeadv != BGP_DEFAULT_EBGP_ROUTEADV
6489 && ! peer_group_active (peer))
0b960b4d
DW
6490 {
6491 vty_out (vty, " neighbor %s advertisement-interval %d%s",
6492 addr, peer->v_routeadv, VTY_NEWLINE);
6493 }
8a92a8a0 6494
0b960b4d
DW
6495 /* timers */
6496 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
813d4307 6497 && (peer->keepalive != BGP_DEFAULT_KEEPALIVE || peer->holdtime != BGP_DEFAULT_HOLDTIME)
0b960b4d
DW
6498 && ! peer_group_active (peer))
6499 {
6500 vty_out (vty, " neighbor %s timers %d %d%s", addr,
6501 peer->keepalive, peer->holdtime, VTY_NEWLINE);
6502 }
718e3744 6503
0b960b4d 6504 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT) &&
400b1fad 6505 peer->connect != BGP_DEFAULT_CONNECT_RETRY &&
0b960b4d
DW
6506 ! peer_group_active (peer))
6507 {
6508 vty_out (vty, " neighbor %s timers connect %d%s", addr,
6509 peer->connect, VTY_NEWLINE);
6510 }
718e3744 6511
0b960b4d
DW
6512 /* weight */
6513 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
6514 {
6515 if (! peer_group_active (peer) || g_peer->weight != peer->weight)
6516 {
6517 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
6518 VTY_NEWLINE);
6519 }
6520 }
718e3744 6521
0b960b4d
DW
6522 /* capability dynamic */
6523 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
6524 {
6525 if (! peer_group_active (peer) ||
6526 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
6527 {
6528 vty_out (vty, " neighbor %s capability dynamic%s", addr,
6529 VTY_NEWLINE);
6530 }
6531 }
6532
6533 /* capability extended-nexthop */
6534 if (CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE))
6535 {
6536 if (! peer_group_active (peer) ||
6537 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_CAPABILITY_ENHE))
6538 {
6539 vty_out (vty, " neighbor %s capability extended-nexthop%s", addr,
6540 VTY_NEWLINE);
6541 }
718e3744 6542 }
6543
0b960b4d
DW
6544 /* dont-capability-negotiation */
6545 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
6546 {
6547 if (! peer_group_active (peer) ||
6548 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
6549 {
6550 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
6551 VTY_NEWLINE);
6552 }
6553 }
718e3744 6554
0b960b4d
DW
6555 /* override-capability */
6556 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
6557 {
6558 if (! peer_group_active (peer) ||
6559 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
6560 {
6561 vty_out (vty, " neighbor %s override-capability%s", addr,
6562 VTY_NEWLINE);
6563 }
6564 }
718e3744 6565
0b960b4d
DW
6566 /* strict-capability-match */
6567 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
718e3744 6568 {
0b960b4d
DW
6569 if (! peer_group_active (peer) ||
6570 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
6571 {
6572 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
6573 VTY_NEWLINE);
6574 }
718e3744 6575 }
0b960b4d
DW
6576}
6577
0b960b4d
DW
6578/* BGP peer configuration display function. */
6579static void
6580bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp,
400b1fad
DW
6581 struct peer *peer, afi_t afi, safi_t safi,
6582 int *write)
0b960b4d
DW
6583{
6584 struct peer *g_peer = NULL;
6585 char *addr;
6586
6587 /* Skip dynamic neighbors. */
6588 if (peer_dynamic_neighbor (peer))
6589 return;
6590
6591 if (peer->conf_if)
6592 addr = peer->conf_if;
6593 else
6594 addr = peer->host;
6595
0b960b4d
DW
6596 /************************************
6597 ****** Per AF to the neighbor ******
6598 ************************************/
c8560b44 6599 if (peer_group_active (peer))
400b1fad 6600 {
c8560b44
DW
6601 g_peer = peer->group->conf;
6602
6603 /* If the peer-group is active but peer is not, print a 'no activate' */
6604 if (g_peer->afc[afi][safi] && !peer->afc[afi][safi])
6605 {
6606 afi_header_vty_out (vty, afi, safi, write,
6607 " no neighbor %s activate%s",
6608 addr, VTY_NEWLINE);
6609 }
6610
6611 /* If the peer-group is not active but peer is, print an 'activate' */
6612 else if (!g_peer->afc[afi][safi] && peer->afc[afi][safi])
6613 {
6614 afi_header_vty_out (vty, afi, safi, write,
6615 " neighbor %s activate%s",
6616 addr, VTY_NEWLINE);
6617 }
400b1fad 6618 }
0b960b4d 6619 else
c8560b44
DW
6620 {
6621 if (peer->afc[afi][safi])
6622 {
6623 afi_header_vty_out (vty, afi, safi, write,
6624 " neighbor %s activate%s",
6625 addr, VTY_NEWLINE);
6626 }
6627 }
718e3744 6628
adbac85e
DW
6629 /* addpath TX knobs */
6630 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ADDPATH_TX_ALL_PATHS))
c8560b44
DW
6631 {
6632 afi_header_vty_out (vty, afi, safi, write,
6633 " neighbor %s addpath-tx-all-paths%s",
6634 addr, VTY_NEWLINE);
6635 }
06370dac
DW
6636
6637 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS))
c8560b44
DW
6638 {
6639 afi_header_vty_out (vty, afi, safi, write,
6640 " neighbor %s addpath-tx-bestpath-per-AS%s",
6641 addr, VTY_NEWLINE);
6642 }
adbac85e 6643
718e3744 6644 /* ORF capability. */
88b8ed8d
DW
6645 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM) ||
6646 peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_RM))
718e3744 6647 {
400b1fad
DW
6648 afi_header_vty_out (vty, afi, safi, write,
6649 " neighbor %s capability orf prefix-list",
6650 addr);
718e3744 6651
88b8ed8d
DW
6652 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM) &&
6653 peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_RM))
718e3744 6654 vty_out (vty, " both");
88b8ed8d 6655 else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM))
718e3744 6656 vty_out (vty, " send");
6657 else
6658 vty_out (vty, " receive");
6659 vty_out (vty, "%s", VTY_NEWLINE);
6660 }
6661
6662 /* Route reflector client. */
88b8ed8d 6663 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT))
400b1fad
DW
6664 {
6665 afi_header_vty_out (vty, afi, safi, write,
6666 " neighbor %s route-reflector-client%s",
6667 addr, VTY_NEWLINE);
6668 }
88b8ed8d
DW
6669
6670 /* next-hop-self force */
6671 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_FORCE_NEXTHOP_SELF))
400b1fad
DW
6672 {
6673 afi_header_vty_out (vty, afi, safi, write,
6674 " neighbor %s next-hop-self force%s",
6675 addr, VTY_NEWLINE);
6676 }
718e3744 6677
88b8ed8d
DW
6678 /* next-hop-self */
6679 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF))
400b1fad
DW
6680 {
6681 afi_header_vty_out (vty, afi, safi, write,
6682 " neighbor %s next-hop-self%s",
6683 addr, VTY_NEWLINE);
6684 }
718e3744 6685
5000f21c 6686 /* remove-private-AS */
88b8ed8d 6687 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
400b1fad
DW
6688 {
6689 afi_header_vty_out (vty, afi, safi, write,
6690 " neighbor %s remove-private-AS all replace-AS%s",
6691 addr, VTY_NEWLINE);
6692 }
5000f21c 6693
88b8ed8d 6694 else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
400b1fad
DW
6695 {
6696 afi_header_vty_out (vty, afi, safi, write,
6697 " neighbor %s remove-private-AS replace-AS%s",
6698 addr, VTY_NEWLINE);
6699 }
5000f21c 6700
88b8ed8d 6701 else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL))
400b1fad
DW
6702 {
6703 afi_header_vty_out (vty, afi, safi, write,
6704 " neighbor %s remove-private-AS all%s",
6705 addr, VTY_NEWLINE);
6706 }
5000f21c 6707
88b8ed8d 6708 else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS))
400b1fad
DW
6709 {
6710 afi_header_vty_out (vty, afi, safi, write,
6711 " neighbor %s remove-private-AS%s",
6712 addr, VTY_NEWLINE);
6713 }
718e3744 6714
c7122e14 6715 /* as-override */
88b8ed8d 6716 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_OVERRIDE))
400b1fad
DW
6717 {
6718 afi_header_vty_out (vty, afi, safi, write,
6719 " neighbor %s as-override%s",
6720 addr, VTY_NEWLINE);
6721 }
c7122e14 6722
718e3744 6723 /* send-community print. */
88b8ed8d 6724 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
718e3744 6725 {
88b8ed8d
DW
6726 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
6727 && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
400b1fad
DW
6728 {
6729 afi_header_vty_out (vty, afi, safi, write,
6730 " neighbor %s send-community both%s",
6731 addr, VTY_NEWLINE);
6732 }
88b8ed8d 6733 else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
400b1fad
DW
6734 {
6735 afi_header_vty_out (vty, afi, safi, write,
6736 " neighbor %s send-community extended%s",
6737 addr, VTY_NEWLINE);
6738 }
88b8ed8d 6739 else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
400b1fad
DW
6740 {
6741 afi_header_vty_out (vty, afi, safi, write,
6742 " neighbor %s send-community%s",
6743 addr, VTY_NEWLINE);
6744 }
88b8ed8d
DW
6745 }
6746 else
6747 {
6748 if (!peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY) &&
ad695d6e 6749 (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)) &&
88b8ed8d 6750 !peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY) &&
ad695d6e 6751 (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)))
400b1fad
DW
6752 {
6753 afi_header_vty_out (vty, afi, safi, write,
6754 " no neighbor %s send-community both%s",
6755 addr, VTY_NEWLINE);
6756 }
88b8ed8d 6757 else if (!peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY) &&
ad695d6e 6758 (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)))
400b1fad
DW
6759 {
6760 afi_header_vty_out (vty, afi, safi, write,
6761 " no neighbor %s send-community extended%s",
6762 addr, VTY_NEWLINE);
6763 }
88b8ed8d 6764 else if (!peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY) &&
ad695d6e 6765 (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)))
400b1fad
DW
6766 {
6767 afi_header_vty_out (vty, afi, safi, write,
6768 " no neighbor %s send-community%s",
6769 addr, VTY_NEWLINE);
6770 }
718e3744 6771 }
6772
6773 /* Default information */
88b8ed8d
DW
6774 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE) ||
6775 (g_peer &&
6776 ((peer->default_rmap[afi][safi].name && !g_peer->default_rmap[afi][safi].name) ||
6777 (!peer->default_rmap[afi][safi].name && g_peer->default_rmap[afi][safi].name) ||
6778 (peer->default_rmap[afi][safi].name &&
6779 strcmp(peer->default_rmap[afi][safi].name, g_peer->default_rmap[afi][safi].name)))))
718e3744 6780 {
400b1fad
DW
6781 afi_header_vty_out (vty, afi, safi, write,
6782 " neighbor %s default-originate", addr);
718e3744 6783 if (peer->default_rmap[afi][safi].name)
88b8ed8d 6784 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
718e3744 6785 vty_out (vty, "%s", VTY_NEWLINE);
6786 }
6787
6788 /* Soft reconfiguration inbound. */
88b8ed8d 6789 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SOFT_RECONFIG))
400b1fad
DW
6790 {
6791 afi_header_vty_out (vty, afi, safi, write,
6792 " neighbor %s soft-reconfiguration inbound%s",
6793 addr, VTY_NEWLINE);
6794 }
718e3744 6795
6796 /* maximum-prefix. */
6797 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
c8560b44 6798 if (! peer_group_active(peer)
718e3744 6799 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
e0701b79 6800 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
718e3744 6801 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
6802 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
e0701b79 6803 {
400b1fad 6804 afi_header_vty_out (vty, afi, safi, write,
85e11c23 6805 " neighbor %s maximum-prefix %lu",
400b1fad 6806 addr, peer->pmax[afi][safi]);
0a486e5f 6807 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
6808 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
6809 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
6810 vty_out (vty, " warning-only");
6811 if (peer->pmax_restart[afi][safi])
6812 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
6813 vty_out (vty, "%s", VTY_NEWLINE);
e0701b79 6814 }
718e3744 6815
6816 /* Route server client. */
88b8ed8d 6817 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_RSERVER_CLIENT))
400b1fad
DW
6818 {
6819 afi_header_vty_out (vty, afi, safi, write,
6820 " neighbor %s route-server-client%s",
6821 addr, VTY_NEWLINE);
6822 }
718e3744 6823
3cf1288b 6824 /* Nexthop-local unchanged. */
88b8ed8d 6825 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED))
400b1fad
DW
6826 {
6827 afi_header_vty_out (vty, afi, safi, write,
6828 " neighbor %s nexthop-local unchanged%s",
6829 addr, VTY_NEWLINE);
6830 }
3cf1288b 6831
718e3744 6832 /* Allow AS in. */
6833 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
6834 if (! peer_group_active (peer)
6835 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
6836 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
6837 {
6838 if (peer->allowas_in[afi][safi] == 3)
400b1fad
DW
6839 {
6840 afi_header_vty_out (vty, afi, safi, write,
6841 " neighbor %s allowas-in%s",
6842 addr, VTY_NEWLINE);
6843 }
6844 else
6845 {
6846 afi_header_vty_out (vty, afi, safi, write,
6847 " neighbor %s allowas-in %d%s",
6848 addr, peer->allowas_in[afi][safi], VTY_NEWLINE);
6849 }
718e3744 6850 }
6851
6852 /* Filter. */
400b1fad 6853 bgp_config_write_filter (vty, peer, afi, safi, write);
718e3744 6854
6855 /* atribute-unchanged. */
88b8ed8d 6856 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
718e3744 6857 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
6858 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
718e3744 6859 {
88b8ed8d
DW
6860 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED)
6861 && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_UNCHANGED)
6862 && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_MED_UNCHANGED))
400b1fad
DW
6863 {
6864 afi_header_vty_out (vty, afi, safi, write,
6865 " neighbor %s attribute-unchanged%s",
6866 addr, VTY_NEWLINE);
6867 }
718e3744 6868 else
400b1fad
DW
6869 {
6870 afi_header_vty_out (vty, afi, safi, write,
6871 " neighbor %s attribute-unchanged%s%s%s%s", addr,
6872 peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED) ?
6873 " as-path" : "",
6874 peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_UNCHANGED) ?
6875 " next-hop" : "",
6876 peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_MED_UNCHANGED) ?
6877 " med" : "", VTY_NEWLINE);
6878 }
718e3744 6879 }
6880}
6881
6882/* Display "address-family" configuration header. */
6883void
6884bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
6885 int *write)
6886{
6887 if (*write)
6888 return;
6889
3914b418 6890 vty_out (vty, " !%s address-family ", VTY_NEWLINE);
718e3744 6891
6892 if (afi == AFI_IP)
6893 {
0b960b4d
DW
6894 if (safi == SAFI_UNICAST)
6895 vty_out (vty, "ipv4 unicast");
6896 else if (safi == SAFI_MULTICAST)
718e3744 6897 vty_out (vty, "ipv4 multicast");
6898 else if (safi == SAFI_MPLS_VPN)
6899 vty_out (vty, "vpnv4 unicast");
6900 }
6901 else if (afi == AFI_IP6)
37a217a5 6902 {
0b960b4d
DW
6903 if (safi == SAFI_UNICAST)
6904 vty_out (vty, "ipv6 unicast");
6905 else if (safi == SAFI_MULTICAST)
6906 vty_out (vty, "ipv6 multicast");
37a217a5 6907 }
718e3744 6908
6909 vty_out (vty, "%s", VTY_NEWLINE);
6910
6911 *write = 1;
6912}
6913
6914/* Address family based peer configuration display. */
94f2b392 6915static int
718e3744 6916bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
6917 safi_t safi)
6918{
6919 int write = 0;
6920 struct peer *peer;
6921 struct peer_group *group;
1eb8ef25 6922 struct listnode *node, *nnode;
718e3744 6923
6924 bgp_config_write_network (vty, bgp, afi, safi, &write);
6925
6926 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
6927
1eb8ef25 6928 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
400b1fad
DW
6929 bgp_config_write_peer_af (vty, bgp, group->conf, afi, safi, &write);
6930
1eb8ef25 6931 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 6932 {
f14e6fdb
DS
6933 /* Skip dynamic neighbors. */
6934 if (peer_dynamic_neighbor (peer))
6935 continue;
6936
400b1fad
DW
6937 /* Do not display doppelganger peers */
6938 if (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE))
6939 bgp_config_write_peer_af (vty, bgp, peer, afi, safi, &write);
718e3744 6940 }
165b5fff
JB
6941
6942 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
73ac8160 6943 bgp_config_write_table_map (vty, bgp, afi, safi, &write);
165b5fff 6944
718e3744 6945 if (write)
6946 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
6947
6948 return write;
6949}
6950
6951int
6952bgp_config_write (struct vty *vty)
6953{
6954 int write = 0;
6955 struct bgp *bgp;
6956 struct peer_group *group;
6957 struct peer *peer;
1eb8ef25 6958 struct listnode *node, *nnode;
6959 struct listnode *mnode, *mnnode;
718e3744 6960
6961 /* BGP Multiple instance. */
b8fd6a15 6962 if (!bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
718e3744 6963 {
b8fd6a15 6964 vty_out (vty, "no bgp multiple-instance%s", VTY_NEWLINE);
718e3744 6965 write++;
6966 }
6967
6968 /* BGP Config type. */
6969 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
6970 {
6971 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
6972 write++;
6973 }
6974
5fe9f963 6975 if (bm->rmap_update_timer != RMAP_DEFAULT_UPDATE_TIMER)
6976 vty_out (vty, "bgp route-map delay-timer %d%s", bm->rmap_update_timer,
6977 VTY_NEWLINE);
6978
718e3744 6979 /* BGP configuration. */
1eb8ef25 6980 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
718e3744 6981 {
6982 if (write)
6983 vty_out (vty, "!%s", VTY_NEWLINE);
6984
6985 /* Router bgp ASN */
aea339f7 6986 vty_out (vty, "router bgp %u", bgp->as);
718e3744 6987
6988 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
6989 {
6990 if (bgp->name)
ad4cbda1 6991 vty_out (vty, " %s %s",
6992 (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) ?
6993 "view" : "vrf", bgp->name);
718e3744 6994 }
6995 vty_out (vty, "%s", VTY_NEWLINE);
6996
6997 /* No Synchronization */
6998 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
6999 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
7000
7001 /* BGP fast-external-failover. */
7002 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
7003 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
7004
7005 /* BGP router ID. */
c2d58d6d 7006 if (bgp->router_id_static.s_addr != 0)
7007 vty_out (vty, " bgp router-id %s%s",
7008 inet_ntoa (bgp->router_id_static), VTY_NEWLINE);
718e3744 7009
848973c7 7010 /* BGP log-neighbor-changes. */
6793fbe0
DW
7011 if (!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
7012 vty_out (vty, " no bgp log-neighbor-changes%s", VTY_NEWLINE);
848973c7 7013
718e3744 7014 /* BGP configuration. */
7015 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
7016 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
7017
7018 /* BGP default ipv4-unicast. */
7019 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
7020 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
7021
7022 /* BGP default local-preference. */
7023 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
7024 vty_out (vty, " bgp default local-preference %d%s",
7025 bgp->default_local_pref, VTY_NEWLINE);
7026
04b6bdc0 7027 /* BGP default show-hostname */
15f3b5c0
DW
7028 if (!bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME))
7029 vty_out (vty, " no bgp default show-hostname%s", VTY_NEWLINE);
04b6bdc0 7030
3f9c7369
DS
7031 /* BGP default subgroup-pkt-queue-max. */
7032 if (bgp->default_subgroup_pkt_queue_max != BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX)
7033 vty_out (vty, " bgp default subgroup-pkt-queue-max %d%s",
7034 bgp->default_subgroup_pkt_queue_max, VTY_NEWLINE);
7035
718e3744 7036 /* BGP client-to-client reflection. */
7037 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
7038 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
7039
7040 /* BGP cluster ID. */
7041 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
7042 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
7043 VTY_NEWLINE);
7044
907f92c8
DS
7045 /* Disable ebgp connected nexthop check */
7046 if (bgp_flag_check (bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
7047 vty_out (vty, " bgp disable-ebgp-connected-route-check%s", VTY_NEWLINE);
7048
e0701b79 7049 /* Confederation identifier*/
718e3744 7050 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
e0701b79 7051 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
7052 VTY_NEWLINE);
7053
7054 /* Confederation peer */
7055 if (bgp->confed_peers_cnt > 0)
718e3744 7056 {
e0701b79 7057 int i;
718e3744 7058
e0701b79 7059 vty_out (vty, " bgp confederation peers");
718e3744 7060
e0701b79 7061 for (i = 0; i < bgp->confed_peers_cnt; i++)
aea339f7 7062 vty_out(vty, " %u", bgp->confed_peers[i]);
718e3744 7063
e0701b79 7064 vty_out (vty, "%s", VTY_NEWLINE);
718e3744 7065 }
7066
7067 /* BGP enforce-first-as. */
7068 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
7069 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
7070
7071 /* BGP deterministic-med. */
1475ac87
DW
7072 if (!bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
7073 vty_out (vty, " no bgp deterministic-med%s", VTY_NEWLINE);
538621f2 7074
f188f2c4
DS
7075 /* BGP update-delay. */
7076 bgp_config_write_update_delay (vty, bgp);
7077
abc920f8
DS
7078 if (bgp->v_maxmed_onstartup != BGP_MAXMED_ONSTARTUP_UNCONFIGURED)
7079 {
7080 vty_out (vty, " bgp max-med on-startup %d", bgp->v_maxmed_onstartup);
7081 if (bgp->maxmed_onstartup_value != BGP_MAXMED_VALUE_DEFAULT)
7082 vty_out (vty, " %d", bgp->maxmed_onstartup_value);
7083 vty_out (vty, "%s", VTY_NEWLINE);
7084 }
7085 if (bgp->v_maxmed_admin != BGP_MAXMED_ADMIN_UNCONFIGURED)
7086 {
7087 vty_out (vty, " bgp max-med administrative");
7088 if (bgp->maxmed_admin_value != BGP_MAXMED_VALUE_DEFAULT)
7089 vty_out (vty, " %d", bgp->maxmed_admin_value);
7090 vty_out (vty, "%s", VTY_NEWLINE);
7091 }
7092
cb1faec9
DS
7093 /* write quanta */
7094 bgp_config_write_wpkt_quanta (vty, bgp);
7095
3f9c7369
DS
7096 /* coalesce time */
7097 bgp_config_write_coalesce_time(vty, bgp);
7098
538621f2 7099 /* BGP graceful-restart. */
93406d87 7100 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
7101 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
7102 bgp->stalepath_time, VTY_NEWLINE);
538621f2 7103 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
7104 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
7105
718e3744 7106 /* BGP bestpath method. */
7107 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
7108 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
6811845b 7109 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
7110 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
16fc1eec 7111
219178b6
DW
7112 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX))
7113 {
7114 if (bgp_flag_check (bgp, BGP_FLAG_MULTIPATH_RELAX_AS_SET))
7115 {
7116 vty_out (vty, " bgp bestpath as-path multipath-relax as-set%s", VTY_NEWLINE);
7117 }
7dc9d4e4
DW
7118 else
7119 {
7120 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
7121 }
16fc1eec 7122 }
16fc1eec 7123
8bd9d948
DS
7124 if (bgp_flag_check (bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
7125 vty_out (vty, " bgp route-reflector allow-outbound-policy%s",
7126 VTY_NEWLINE);
7127 }
718e3744 7128 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
7129 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
7130 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
7131 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
7132 {
7133 vty_out (vty, " bgp bestpath med");
7134 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
7135 vty_out (vty, " confed");
7136 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
7137 vty_out (vty, " missing-as-worst");
7138 vty_out (vty, "%s", VTY_NEWLINE);
7139 }
7140
7141 /* BGP network import check. */
5623e905
DW
7142 if (!bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
7143 vty_out (vty, " no bgp network import-check%s", VTY_NEWLINE);
718e3744 7144
718e3744 7145 /* BGP flag dampening. */
7146 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
7147 BGP_CONFIG_DAMPENING))
7148 bgp_config_write_damp (vty);
7149
718e3744 7150 /* BGP timers configuration. */
7151 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
7152 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
7153 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
7154 bgp->default_holdtime, VTY_NEWLINE);
7155
7156 /* peer-group */
1eb8ef25 7157 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 7158 {
0b960b4d 7159 bgp_config_write_peer_global (vty, bgp, group->conf);
718e3744 7160 }
7161
7162 /* Normal neighbor configuration. */
1eb8ef25 7163 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 7164 {
1ff9a340 7165 if (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE))
0b960b4d 7166 bgp_config_write_peer_global (vty, bgp, peer);
718e3744 7167 }
7168
7169 /* Distance configuration. */
7170 bgp_config_write_distance (vty, bgp);
7171
f14e6fdb
DS
7172 /* listen range and limit for dynamic BGP neighbors */
7173 bgp_config_write_listen (vty, bgp);
7174
718e3744 7175 /* No auto-summary */
7176 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
7177 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
7178
0b960b4d
DW
7179 /* IPv4 unicast configuration. */
7180 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_UNICAST);
7181
718e3744 7182 /* IPv4 multicast configuration. */
7183 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
7184
7185 /* IPv4 VPN configuration. */
7186 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
7187
7188 /* IPv6 unicast configuration. */
7189 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
7190
37a217a5
PJ
7191 /* IPv6 multicast configuration. */
7192 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
7193
718e3744 7194 write++;
7195 }
7196 return write;
7197}
7198
7199void
94f2b392 7200bgp_master_init (void)
718e3744 7201{
7202 memset (&bgp_master, 0, sizeof (struct bgp_master));
7203
7204 bm = &bgp_master;
7205 bm->bgp = list_new ();
0df7c91f 7206 bm->listen_sockets = list_new ();
718e3744 7207 bm->port = BGP_PORT_DEFAULT;
87d4a781 7208 bm->master = thread_master_create ();
65957886 7209 bm->start_time = bgp_clock ();
5fe9f963 7210 bm->t_rmap_update = NULL;
7211 bm->rmap_update_timer = RMAP_DEFAULT_UPDATE_TIMER;
495f0b13
DS
7212
7213 bgp_process_queue_init();
b8fd6a15 7214
7215 /* Enable multiple instances by default. */
7216 bgp_option_set (BGP_OPT_MULTIPLE_INSTANCE);
718e3744 7217}
200df115 7218
b33adb7c 7219/*
7220 * Initialize interface list for instance, if needed. Invoked upon
7221 * instance create.
7222 */
7223static void
7224bgp_if_init (struct bgp *bgp)
7225{
7226 if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
7227 return;
7228
7229 vrf_iflist_create (bgp->vrf_id);
7230}
7231
ad4cbda1 7232/*
009b18fc 7233 * Free up connected routes and interfaces for a BGP instance. Invoked upon
7234 * instance delete (non-default only) or BGP exit.
ad4cbda1 7235 */
b33adb7c 7236static void
009b18fc 7237bgp_if_finish (struct bgp *bgp)
ad4cbda1 7238{
009b18fc 7239 struct listnode *ifnode, *ifnnode;
7240 struct interface *ifp;
ad4cbda1 7241
009b18fc 7242 if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
7243 return;
ad4cbda1 7244
009b18fc 7245 for (ALL_LIST_ELEMENTS (vrf_iflist(bgp->vrf_id), ifnode, ifnnode, ifp))
7246 {
7247 struct listnode *c_node, *c_nnode;
7248 struct connected *c;
ad4cbda1 7249
009b18fc 7250 for (ALL_LIST_ELEMENTS (ifp->connected, c_node, c_nnode, c))
7251 bgp_connected_delete (bgp, c);
ad4cbda1 7252 }
009b18fc 7253 vrf_iflist_terminate (bgp->vrf_id);
ad4cbda1 7254}
6b0655a2 7255
718e3744 7256void
94f2b392 7257bgp_init (void)
718e3744 7258{
fc9a856f
DS
7259
7260 /* allocates some vital data structures used by peer commands in vty_init */
718e3744 7261
718e3744 7262 /* Init zebra. */
9229d914 7263 bgp_zebra_init(bm->master);
718e3744 7264
fc9a856f
DS
7265 /* BGP VTY commands installation. */
7266 bgp_vty_init ();
7267
718e3744 7268 /* BGP inits. */
7269 bgp_attr_init ();
7270 bgp_debug_init ();
7271 bgp_dump_init ();
7272 bgp_route_init ();
7273 bgp_route_map_init ();
fc9a856f 7274 bgp_scan_vty_init();
718e3744 7275 bgp_mplsvpn_init ();
7276
7277 /* Access list initialize. */
7278 access_list_init ();
7279 access_list_add_hook (peer_distribute_update);
7280 access_list_delete_hook (peer_distribute_update);
7281
7282 /* Filter list initialize. */
7283 bgp_filter_init ();
518f0eb1
DS
7284 as_list_add_hook (peer_aslist_add);
7285 as_list_delete_hook (peer_aslist_del);
718e3744 7286
7287 /* Prefix list initialize.*/
7288 prefix_list_init ();
7289 prefix_list_add_hook (peer_prefix_list_update);
7290 prefix_list_delete_hook (peer_prefix_list_update);
7291
7292 /* Community list initialize. */
7293 bgp_clist = community_list_init ();
7294
7295#ifdef HAVE_SNMP
7296 bgp_snmp_init ();
7297#endif /* HAVE_SNMP */
c43ed2e4
DS
7298
7299 /* BFD init */
7300 bgp_bfd_init();
718e3744 7301}
545acafb 7302
7303void
66e5cd87 7304bgp_terminate (void)
545acafb 7305{
545acafb 7306 struct bgp *bgp;
7307 struct peer *peer;
1eb8ef25 7308 struct listnode *node, *nnode;
7309 struct listnode *mnode, *mnnode;
545acafb 7310
1ff9a340
DS
7311 /* Close the listener sockets first as this prevents peers from attempting
7312 * to reconnect on receiving the peer unconfig message. In the presence
7313 * of a large number of peers this will ensure that no peer is left with
7314 * a dangling connection
7315 */
7316 /* reverse bgp_master_init */
7317 bgp_close();
7318 if (bm->listen_sockets)
7319 list_free(bm->listen_sockets);
7320 bm->listen_sockets = NULL;
7321
1eb8ef25 7322 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
7323 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
1ff9a340
DS
7324 if (peer->status == Established ||
7325 peer->status == OpenSent ||
7326 peer->status == OpenConfirm)
545acafb 7327 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
7328 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
1ff9a340 7329
545acafb 7330 bgp_cleanup_routes ();
acde4b86 7331
e210cf9f 7332 if (bm->process_main_queue)
acde4b86
SH
7333 {
7334 work_queue_free (bm->process_main_queue);
7335 bm->process_main_queue = NULL;
7336 }
5fe9f963 7337
7338 if (bm->t_rmap_update)
7339 BGP_TIMER_OFF(bm->t_rmap_update);
545acafb 7340}