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