]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgpd.c
bgpd: Fix crash in 'show ip bgp nexthop'
[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->change_local_as = 0;
9b1be336 894 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? MAXTTL : 1);
718e3744 895 if (peer->update_source)
896 {
897 sockunion_free (peer->update_source);
898 peer->update_source = NULL;
899 }
900 if (peer->update_if)
901 {
902 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
903 peer->update_if = NULL;
904 }
905
906 if (peer_sort (peer) == BGP_PEER_IBGP)
907 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
908 else
909 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
910
8ffedcea
DS
911 /* This is a per-peer specific flag and so we must preserve it */
912 v6only = CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
913
718e3744 914 peer->flags = 0;
8ffedcea
DS
915
916 if (v6only)
917 SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
918
718e3744 919 peer->config = 0;
920 peer->holdtime = 0;
921 peer->keepalive = 0;
922 peer->connect = 0;
923 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
821a359a
DS
924
925 /* Reset some other configs back to defaults. */
926 peer->v_start = BGP_INIT_START_TIMER;
821a359a
DS
927 peer->password = NULL;
928 peer->local_id = peer->bgp->router_id;
929 peer->v_holdtime = peer->bgp->default_holdtime;
930 peer->v_keepalive = peer->bgp->default_keepalive;
931
7f342629
DS
932 bfd_info_free(&(peer->bfd_info));
933
821a359a
DS
934 /* Set back the CONFIG_NODE flag. */
935 SET_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE);
718e3744 936}
937
6d85b15b
JBD
938/* Check peer's AS number and determines if this peer is IBGP or EBGP */
939static bgp_peer_sort_t
940peer_calc_sort (struct peer *peer)
718e3744 941{
942 struct bgp *bgp;
943
944 bgp = peer->bgp;
945
946 /* Peer-group */
947 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
948 {
66b199b2
DS
949 if (peer->as_type == AS_INTERNAL)
950 return BGP_PEER_IBGP;
951
952 else if (peer->as_type == AS_EXTERNAL)
953 return BGP_PEER_EBGP;
954
955 else if (peer->as_type == AS_SPECIFIED && peer->as)
718e3744 956 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
66b199b2 957
718e3744 958 else
959 {
960 struct peer *peer1;
961 peer1 = listnode_head (peer->group->peer);
66b199b2 962
718e3744 963 if (peer1)
66b199b2 964 return peer1->sort;
718e3744 965 }
966 return BGP_PEER_INTERNAL;
967 }
968
969 /* Normal peer */
970 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
971 {
972 if (peer->local_as == 0)
973 return BGP_PEER_INTERNAL;
974
975 if (peer->local_as == peer->as)
976 {
66b199b2
DS
977 if (bgp->as == bgp->confed_id)
978 {
979 if (peer->local_as == bgp->as)
980 return BGP_PEER_IBGP;
981 else
982 return BGP_PEER_EBGP;
983 }
984 else
985 {
986 if (peer->local_as == bgp->confed_id)
987 return BGP_PEER_EBGP;
988 else
989 return BGP_PEER_IBGP;
990 }
718e3744 991 }
992
993 if (bgp_confederation_peers_check (bgp, peer->as))
994 return BGP_PEER_CONFED;
995
996 return BGP_PEER_EBGP;
997 }
998 else
999 {
0299c004
DS
1000 if (peer->as_type != AS_SPECIFIED)
1001 return (peer->as_type == AS_INTERNAL ? BGP_PEER_IBGP : BGP_PEER_EBGP);
1002
718e3744 1003 return (peer->local_as == 0
1004 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
1005 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
1006 }
1007}
1008
6d85b15b
JBD
1009/* Calculate and cache the peer "sort" */
1010bgp_peer_sort_t
1011peer_sort (struct peer *peer)
1012{
1013 peer->sort = peer_calc_sort (peer);
1014 return peer->sort;
1015}
1016
f63f06da 1017static void
200df115 1018peer_free (struct peer *peer)
1019{
ca058a30 1020 assert (peer->status == Deleted);
0088b5dc
SH
1021
1022 bgp_unlock(peer->bgp);
1023
ca058a30
PJ
1024 /* this /ought/ to have been done already through bgp_stop earlier,
1025 * but just to be sure..
1026 */
1027 bgp_timer_set (peer);
1028 BGP_READ_OFF (peer->t_read);
1029 BGP_WRITE_OFF (peer->t_write);
9fde6624 1030 BGP_EVENT_FLUSH (peer);
ca058a30 1031
9a233a02
DS
1032 /* Free connected nexthop, if present */
1033 if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE) &&
1034 !peer_dynamic_neighbor (peer))
1035 bgp_delete_connected_nexthop (family2afi(peer->su.sa.sa_family), peer);
1036
200df115 1037 if (peer->desc)
9e08021c
DW
1038 {
1039 XFREE (MTYPE_PEER_DESC, peer->desc);
1040 peer->desc = NULL;
1041 }
200df115 1042
1043 /* Free allocated host character. */
1044 if (peer->host)
9e08021c
DW
1045 {
1046 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
1047 peer->host = NULL;
1048 }
6e919709
DS
1049
1050 if (peer->ifname)
9e08021c
DW
1051 {
1052 XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
1053 peer->ifname = NULL;
1054 }
6e919709 1055
200df115 1056 /* Update source configuration. */
1057 if (peer->update_source)
9e08021c
DW
1058 {
1059 sockunion_free (peer->update_source);
1060 peer->update_source = NULL;
1061 }
200df115 1062
1063 if (peer->update_if)
9e08021c
DW
1064 {
1065 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1066 peer->update_if = NULL;
1067 }
6e919709
DS
1068
1069 if (peer->notify.data)
1070 XFREE(MTYPE_TMP, peer->notify.data);
9e08021c 1071 memset (&peer->notify, 0, sizeof (struct bgp_notify));
6e919709 1072
495f0b13 1073 if (peer->clear_node_queue)
9e08021c
DW
1074 {
1075 work_queue_free(peer->clear_node_queue);
1076 peer->clear_node_queue = NULL;
1077 }
495f0b13 1078
ca058a30 1079 bgp_sync_delete (peer);
a80beece
DS
1080
1081 if (peer->conf_if)
9e08021c
DW
1082 {
1083 XFREE (MTYPE_PEER_CONF_IF, peer->conf_if);
1084 peer->conf_if = NULL;
1085 }
a80beece 1086
7f342629 1087 bfd_info_free(&(peer->bfd_info));
c43ed2e4 1088
200df115 1089 memset (peer, 0, sizeof (struct peer));
1090
1091 XFREE (MTYPE_BGP_PEER, peer);
1092}
1093
1094/* increase reference count on a struct peer */
1095struct peer *
28066f4b 1096peer_lock_with_caller (const char *name, struct peer *peer)
200df115 1097{
1098 assert (peer && (peer->lock >= 0));
28066f4b
DS
1099
1100#if 0
1101 zlog_debug("%s peer_lock %p %d", name, peer, peer->lock);
1102#endif
ca058a30 1103
200df115 1104 peer->lock++;
1105
1106 return peer;
1107}
1108
1109/* decrease reference count on a struct peer
1110 * struct peer is freed and NULL returned if last reference
1111 */
1112struct peer *
28066f4b 1113peer_unlock_with_caller (const char *name, struct peer *peer)
200df115 1114{
1115 assert (peer && (peer->lock > 0));
28066f4b
DS
1116
1117#if 0
1118 zlog_debug("%s peer_unlock %p %d", name, peer, peer->lock);
1119#endif
200df115 1120
1121 peer->lock--;
1122
1123 if (peer->lock == 0)
1124 {
200df115 1125 peer_free (peer);
1126 return NULL;
1127 }
1128
200df115 1129 return peer;
1130}
1ff9a340 1131
200df115 1132/* Allocate new peer object, implicitely locked. */
65efcfce 1133struct peer *
6f58544d 1134peer_new (struct bgp *bgp)
718e3744 1135{
1136 afi_t afi;
1137 safi_t safi;
1138 struct peer *peer;
1139 struct servent *sp;
6f58544d
PJ
1140
1141 /* bgp argument is absolutely required */
1142 assert (bgp);
1143 if (!bgp)
1144 return NULL;
1145
718e3744 1146 /* Allocate new peer. */
ca058a30 1147 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
718e3744 1148
1149 /* Set default value. */
eb821189 1150 peer->fd = -1;
718e3744 1151 peer->v_start = BGP_INIT_START_TIMER;
1152 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
718e3744 1153 peer->status = Idle;
1154 peer->ostatus = Idle;
6403814c 1155 peer->cur_event = peer->last_event = peer->last_major_event = 0;
6f58544d 1156 peer->bgp = bgp;
ca058a30 1157 peer = peer_lock (peer); /* initial reference */
0088b5dc 1158 bgp_lock (bgp);
1ff9a340 1159 peer->password = NULL;
718e3744 1160
1161 /* Set default flags. */
1162 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1163 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1164 {
1165 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
1166 {
1167 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
1168 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
1169 }
1170 peer->orf_plist[afi][safi] = NULL;
1171 }
1172 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
1173
1174 /* Create buffers. */
1175 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
1176 peer->obuf = stream_fifo_new ();
0a91ff55
DS
1177
1178 /* We use a larger buffer for peer->work in the event that:
1179 * - We RX a BGP_UPDATE where the attributes alone are just
1180 * under BGP_MAX_PACKET_SIZE
1181 * - The user configures an outbound route-map that does many as-path
1182 * prepends or adds many communities. At most they can have CMD_ARGC_MAX
1183 * args in a route-map so there is a finite limit on how large they can
1184 * make the attributes.
1185 *
1186 * Having a buffer with BGP_MAX_PACKET_SIZE_OVERFLOW allows us to avoid bounds
1187 * checking for every single attribute as we construct an UPDATE.
1188 */
1189 peer->work = stream_new (BGP_MAX_PACKET_SIZE + BGP_MAX_PACKET_SIZE_OVERFLOW);
8c71e481 1190 peer->scratch = stream_new (BGP_MAX_PACKET_SIZE);
718e3744 1191
1ff9a340 1192
718e3744 1193 bgp_sync_init (peer);
1194
1195 /* Get service port number. */
1196 sp = getservbyname ("bgp", "tcp");
1197 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
1198
1199 return peer;
1200}
1201
1ff9a340
DS
1202/*
1203 * This function is invoked when a duplicate peer structure associated with
1204 * a neighbor is being deleted. If this about-to-be-deleted structure is
1205 * the one with all the config, then we have to copy over the info.
1206 */
1207void
1208peer_xfer_config (struct peer *peer_dst, struct peer *peer_src)
1209{
3f9c7369 1210 struct peer_af *paf;
1ff9a340
DS
1211 afi_t afi;
1212 safi_t safi;
96885f16 1213 int afidx;
1ff9a340
DS
1214
1215 assert(peer_src);
1216 assert(peer_dst);
1217
1218 /* The following function is used by both peer group config copy to
1219 * individual peer and when we transfer config
1220 */
1221 if (peer_src->change_local_as)
1222 peer_dst->change_local_as = peer_src->change_local_as;
1223
1224 /* peer flags apply */
1225 peer_dst->flags = peer_src->flags;
1226 peer_dst->cap = peer_src->cap;
1227 peer_dst->config = peer_src->config;
1228
1229 peer_dst->local_as = peer_src->local_as;
1230 peer_dst->ifindex = peer_src->ifindex;
1231 peer_dst->port = peer_src->port;
1232 peer_sort(peer_dst);
1233 peer_dst->rmap_type = peer_src->rmap_type;
1234
1235 /* Timers */
1236 peer_dst->holdtime = peer_src->holdtime;
1237 peer_dst->keepalive = peer_src->keepalive;
1238 peer_dst->connect = peer_src->connect;
1239 peer_dst->v_holdtime = peer_src->v_holdtime;
1240 peer_dst->v_keepalive = peer_src->v_keepalive;
1ff9a340
DS
1241 peer_dst->routeadv = peer_src->routeadv;
1242 peer_dst->v_routeadv = peer_src->v_routeadv;
1243
1244 /* password apply */
1245 if (peer_src->password && !peer_dst->password)
1246 peer_dst->password = XSTRDUP (MTYPE_PEER_PASSWORD, peer_src->password);
1247
1ff9a340
DS
1248 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1249 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1250 {
1251 peer_dst->afc[afi][safi] = peer_src->afc[afi][safi];
1252 peer_dst->af_flags[afi][safi] = peer_src->af_flags[afi][safi];
1253 peer_dst->allowas_in[afi][safi] = peer_src->allowas_in[afi][safi];
d93f7ffc 1254 peer_dst->weight[afi][safi] = peer_src->weight[afi][safi];
1ff9a340
DS
1255 }
1256
96885f16 1257 for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++)
1258 {
1259 paf = peer_src->peer_af_array[afidx];
1260 if (paf != NULL)
1261 peer_af_create(peer_dst, paf->afi, paf->safi);
1262 }
3f9c7369 1263
1ff9a340
DS
1264 /* update-source apply */
1265 if (peer_src->update_source)
1266 {
1267 if (peer_dst->update_source)
1268 sockunion_free (peer_dst->update_source);
1269 if (peer_dst->update_if)
1270 {
1271 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer_dst->update_if);
1272 peer_dst->update_if = NULL;
1273 }
1274 peer_dst->update_source = sockunion_dup (peer_src->update_source);
1275 }
1276 else if (peer_src->update_if)
1277 {
1278 if (peer_dst->update_if)
1279 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer_dst->update_if);
1280 if (peer_dst->update_source)
1281 {
1282 sockunion_free (peer_dst->update_source);
1283 peer_dst->update_source = NULL;
1284 }
1285 peer_dst->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, peer_src->update_if);
1286 }
1287
1288 if (peer_src->ifname)
1289 {
1290 if (peer_dst->ifname)
6e919709 1291 XFREE(MTYPE_BGP_PEER_IFNAME, peer_dst->ifname);
1ff9a340 1292
6e919709 1293 peer_dst->ifname = XSTRDUP(MTYPE_BGP_PEER_IFNAME, peer_src->ifname);
1ff9a340
DS
1294 }
1295}
1296
89ca90fa 1297static int
1298bgp_peer_conf_if_to_su_update_v4 (struct peer *peer, struct interface *ifp)
a80beece 1299{
8ffedcea
DS
1300 struct connected *ifc;
1301 struct prefix p;
f43e655e 1302 u_int32_t addr;
8ffedcea 1303 struct listnode *node;
a80beece 1304
89ca90fa 1305 /* If our IPv4 address on the interface is /30 or /31, we can derive the
1306 * IPv4 address of the other end.
1307 */
1308 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc))
a80beece 1309 {
89ca90fa 1310 if (ifc->address && (ifc->address->family == AF_INET))
1311 {
1312 PREFIX_COPY_IPV4(&p, CONNECTED_PREFIX(ifc));
1313 if (p.prefixlen == 30)
1314 {
1315 peer->su.sa.sa_family = AF_INET;
f43e655e
RW
1316 addr = ntohl(p.u.prefix4.s_addr);
1317 if (addr % 4 == 1)
1318 peer->su.sin.sin_addr.s_addr = htonl(addr+1);
1319 else if (addr % 4 == 2)
1320 peer->su.sin.sin_addr.s_addr = htonl(addr-1);
8ffedcea 1321#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
8f500a1c 1322 peer->su.sin.sin_len = sizeof(struct sockaddr_in);
8ffedcea 1323#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
89ca90fa 1324 return 1;
1325 }
1326 else if (p.prefixlen == 31)
1327 {
1328 peer->su.sa.sa_family = AF_INET;
f43e655e
RW
1329 addr = ntohl(p.u.prefix4.s_addr);
1330 if (addr % 2 == 0)
1331 peer->su.sin.sin_addr.s_addr = htonl(addr+1);
89ca90fa 1332 else
f43e655e 1333 peer->su.sin.sin_addr.s_addr = htonl(addr-1);
8ffedcea 1334#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
8f500a1c 1335 peer->su.sin.sin_len = sizeof(struct sockaddr_in);
8ffedcea 1336#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
89ca90fa 1337 return 1;
1338 }
1339 else
7709d56b
DS
1340 if (bgp_debug_neighbor_events(peer))
1341 zlog_debug("%s: IPv4 interface address is not /30 or /31, v4 session not started",
1342 peer->conf_if);
89ca90fa 1343 }
1344 }
8ffedcea 1345
89ca90fa 1346 return 0;
1347}
1348
1349static int
1350bgp_peer_conf_if_to_su_update_v6 (struct peer *peer, struct interface *ifp)
1351{
1352 struct nbr_connected *ifc_nbr;
1353
1354 /* Have we learnt the peer's IPv6 link-local address? */
1355 if (ifp->nbr_connected &&
1356 (ifc_nbr = listnode_head(ifp->nbr_connected)))
1357 {
1358 peer->su.sa.sa_family = AF_INET6;
1359 memcpy(&peer->su.sin6.sin6_addr, &ifc_nbr->address->u.prefix,
1360 sizeof (struct in6_addr));
a80beece 1361#ifdef SIN6_LEN
89ca90fa 1362 peer->su.sin6.sin6_len = sizeof (struct sockaddr_in6);
a80beece 1363#endif
89ca90fa 1364 peer->su.sin6.sin6_scope_id = ifp->ifindex;
1365 return 1;
1366 }
8ffedcea 1367
89ca90fa 1368 return 0;
1369}
1370
1371/*
1372 * Set or reset the peer address socketunion structure based on the
1373 * learnt/derived peer address. If the address has changed, update the
1374 * password on the listen socket, if needed.
1375 */
1376void
1377bgp_peer_conf_if_to_su_update (struct peer *peer)
1378{
1379 struct interface *ifp;
1380 int prev_family;
1381 int peer_addr_updated = 0;
1382
1383 if (!peer->conf_if)
1384 return;
1385
1386 prev_family = peer->su.sa.sa_family;
8dee0396 1387 if ((ifp = if_lookup_by_name_vrf (peer->conf_if, peer->bgp->vrf_id)))
89ca90fa 1388 {
4a04e5f7 1389 peer->ifp = ifp;
89ca90fa 1390 /* If BGP unnumbered is not "v6only", we first see if we can derive the
1391 * peer's IPv4 address.
1392 */
1393 if (!CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))
1394 peer_addr_updated = bgp_peer_conf_if_to_su_update_v4 (peer, ifp);
1395
1396 /* If "v6only" or we can't derive peer's IPv4 address, see if we've
1397 * learnt the peer's IPv6 link-local address. This is from the source
1398 * IPv6 address in router advertisement.
1399 */
1400 if (!peer_addr_updated)
1401 peer_addr_updated = bgp_peer_conf_if_to_su_update_v6 (peer, ifp);
1402 }
1403 /* If we could derive the peer address, we may need to install the password
1404 * configured for the peer, if any, on the listen socket. Otherwise, mark
1405 * that peer's address is not available and uninstall the password, if
1406 * needed.
1407 */
1408 if (peer_addr_updated)
1409 {
1410 if (peer->password && prev_family == AF_UNSPEC)
1411 bgp_md5_set (peer);
1412 }
1413 else
1414 {
1415 if (peer->password && prev_family != AF_UNSPEC)
1416 bgp_md5_unset (peer);
1417 peer->su.sa.sa_family = AF_UNSPEC;
1418 memset(&peer->su.sin6.sin6_addr, 0, sizeof (struct in6_addr));
a80beece 1419 }
dd793e4a
DW
1420
1421 /* Since our su changed we need to del/add peer to the peerhash */
1422 hash_release(peer->bgp->peerhash, peer);
1423 hash_get(peer->bgp->peerhash, peer, hash_alloc_intern);
a80beece
DS
1424}
1425
06370dac
DW
1426/* Force a bestpath recalculation for all prefixes. This is used
1427 * when 'bgp bestpath' commands are entered.
1428 */
1429void
1430bgp_recalculate_all_bestpaths (struct bgp *bgp)
1431{
1432 afi_t afi;
1433 safi_t safi;
1434 struct bgp_node *rn;
1435
1436 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1437 {
1438 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1439 {
1440 for (rn = bgp_table_top (bgp->rib[afi][safi]); rn; rn = bgp_route_next (rn))
1441 {
353cd37f
DW
1442 if (rn->info != NULL)
1443 {
1444 bgp_process (bgp, rn, afi, safi);
1445 }
06370dac
DW
1446 }
1447 }
1448 }
1449}
1450
718e3744 1451/* Create new BGP peer. */
1ff9a340 1452struct peer *
a80beece 1453peer_create (union sockunion *su, const char *conf_if, struct bgp *bgp,
f813b13b 1454 as_t local_as, as_t remote_as, int as_type, afi_t afi, safi_t safi, struct peer_group *group)
718e3744 1455{
1456 int active;
1457 struct peer *peer;
1458 char buf[SU_ADDRSTRLEN];
1459
6f58544d 1460 peer = peer_new (bgp);
a80beece
DS
1461 if (conf_if)
1462 {
1463 peer->conf_if = XSTRDUP (MTYPE_PEER_CONF_IF, conf_if);
ff7c8333 1464 bgp_peer_conf_if_to_su_update(peer);
6e919709
DS
1465 if (peer->host)
1466 XFREE(MTYPE_BGP_PEER_HOST, peer->host);
a80beece
DS
1467 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, conf_if);
1468 }
1469 else if (su)
1470 {
1471 peer->su = *su;
1472 sockunion2str (su, buf, SU_ADDRSTRLEN);
6e919709
DS
1473 if (peer->host)
1474 XFREE(MTYPE_BGP_PEER_HOST, peer->host);
a80beece
DS
1475 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
1476 }
718e3744 1477 peer->local_as = local_as;
1478 peer->as = remote_as;
0299c004 1479 peer->as_type = as_type;
718e3744 1480 peer->local_id = bgp->router_id;
1481 peer->v_holdtime = bgp->default_holdtime;
1482 peer->v_keepalive = bgp->default_keepalive;
1483 if (peer_sort (peer) == BGP_PEER_IBGP)
1484 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1485 else
1486 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
28066f4b 1487
200df115 1488 peer = peer_lock (peer); /* bgp peer list reference */
f813b13b 1489 peer->group = group;
718e3744 1490 listnode_add_sort (bgp->peer, peer);
dd793e4a 1491 hash_get(bgp->peerhash, peer, hash_alloc_intern);
718e3744 1492
1493 active = peer_active (peer);
1494
65957886
SH
1495 /* Last read and reset time set */
1496 peer->readtime = peer->resettime = bgp_clock ();
848973c7 1497
718e3744 1498 /* Default TTL set. */
9b1be336 1499 peer->ttl = (peer->sort == BGP_PEER_IBGP) ? MAXTTL : 1;
718e3744 1500
1ff9a340
DS
1501 SET_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE);
1502
3f9c7369
DS
1503 if (afi && safi)
1504 {
1505 peer->afc[afi][safi] = 1;
c8560b44 1506 peer_af_create(peer, afi, safi);
3f9c7369
DS
1507 }
1508
718e3744 1509 /* Set up peer's events and timers. */
1510 if (! active && peer_active (peer))
1511 bgp_timer_set (peer);
1512
1513 return peer;
1514}
1515
dd793e4a 1516/* Make accept BGP peer. This function is only called from the test code */
eb821189 1517struct peer *
1518peer_create_accept (struct bgp *bgp)
1519{
1520 struct peer *peer;
1521
6f58544d 1522 peer = peer_new (bgp);
1ff9a340 1523
200df115 1524 peer = peer_lock (peer); /* bgp peer list reference */
eb821189 1525 listnode_add_sort (bgp->peer, peer);
1526
1527 return peer;
1528}
1529
718e3744 1530/* Change peer's AS number. */
a80beece 1531void
0299c004 1532peer_as_change (struct peer *peer, as_t as, int as_specified)
718e3744 1533{
6d85b15b 1534 bgp_peer_sort_t type;
966f821c 1535 struct peer *conf;
718e3744 1536
1537 /* Stop peer. */
1538 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1539 {
6aa136f1 1540 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 1541 {
1542 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
1543 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1544 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1545 }
718e3744 1546 else
1ff9a340 1547 bgp_session_reset(peer);
718e3744 1548 }
1549 type = peer_sort (peer);
1550 peer->as = as;
0299c004 1551 peer->as_type = as_specified;
718e3744 1552
848973c7 1553 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
1554 && ! bgp_confederation_peers_check (peer->bgp, as)
1555 && peer->bgp->as != as)
1556 peer->local_as = peer->bgp->confed_id;
1557 else
1558 peer->local_as = peer->bgp->as;
1559
718e3744 1560 /* Advertisement-interval reset */
966f821c
DS
1561 conf = NULL;
1562 if (peer->group)
1563 conf = peer->group->conf;
1564
1565 if (conf && CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
ffd0c037 1566 {
966f821c 1567 peer->v_routeadv = conf->routeadv;
ffd0c037 1568 }
d973c4f0
DS
1569 /* Only go back to the default advertisement-interval if the user had not
1570 * already configured it */
1571 else if (!CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
ffd0c037
DS
1572 {
1573 if (peer_sort (peer) == BGP_PEER_IBGP)
1574 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1575 else
1576 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1577 }
718e3744 1578 /* TTL reset */
1579 if (peer_sort (peer) == BGP_PEER_IBGP)
9b1be336 1580 peer->ttl = MAXTTL;
718e3744 1581 else if (type == BGP_PEER_IBGP)
1582 peer->ttl = 1;
1583
1584 /* reflector-client reset */
1585 if (peer_sort (peer) != BGP_PEER_IBGP)
1586 {
1587 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
1588 PEER_FLAG_REFLECTOR_CLIENT);
1589 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
1590 PEER_FLAG_REFLECTOR_CLIENT);
1591 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
1592 PEER_FLAG_REFLECTOR_CLIENT);
587ff0fd
LB
1593 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_ENCAP],
1594 PEER_FLAG_REFLECTOR_CLIENT);
718e3744 1595 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
1596 PEER_FLAG_REFLECTOR_CLIENT);
1597 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
1598 PEER_FLAG_REFLECTOR_CLIENT);
945c8fe9
LB
1599 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MPLS_VPN],
1600 PEER_FLAG_REFLECTOR_CLIENT);
587ff0fd
LB
1601 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_ENCAP],
1602 PEER_FLAG_REFLECTOR_CLIENT);
718e3744 1603 }
1604
1605 /* local-as reset */
1606 if (peer_sort (peer) != BGP_PEER_EBGP)
1607 {
1608 peer->change_local_as = 0;
1609 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
9d3f9705 1610 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
718e3744 1611 }
1612}
1613
1614/* If peer does not exist, create new one. If peer already exists,
1615 set AS number to the peer. */
1616int
0299c004
DS
1617peer_remote_as (struct bgp *bgp, union sockunion *su, const char *conf_if,
1618 as_t *as, int as_type, afi_t afi, safi_t safi)
718e3744 1619{
1620 struct peer *peer;
1621 as_t local_as;
1622
a80beece
DS
1623 if (conf_if)
1624 peer = peer_lookup_by_conf_if (bgp, conf_if);
1625 else
1626 peer = peer_lookup (bgp, su);
718e3744 1627
1628 if (peer)
1629 {
f14e6fdb
DS
1630 /* Not allowed for a dynamic peer. */
1631 if (peer_dynamic_neighbor (peer))
1632 {
1633 *as = peer->as;
1634 return BGP_ERR_INVALID_FOR_DYNAMIC_PEER;
1635 }
1636
718e3744 1637 /* When this peer is a member of peer-group. */
1638 if (peer->group)
1639 {
1640 if (peer->group->conf->as)
1641 {
1642 /* Return peer group's AS number. */
1643 *as = peer->group->conf->as;
1644 return BGP_ERR_PEER_GROUP_MEMBER;
1645 }
1646 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
1647 {
0299c004 1648 if ((as_type != AS_INTERNAL) && (bgp->as != *as))
718e3744 1649 {
1650 *as = peer->as;
1651 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1652 }
1653 }
1654 else
1655 {
0299c004 1656 if ((as_type != AS_EXTERNAL) && (bgp->as == *as))
718e3744 1657 {
1658 *as = peer->as;
1659 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1660 }
1661 }
1662 }
1663
1664 /* Existing peer's AS number change. */
9da3a1a1
DS
1665 if (((peer->as_type == AS_SPECIFIED) && peer->as != *as) ||
1666 (peer->as_type != as_type))
0299c004 1667 peer_as_change (peer, *as, as_type);
718e3744 1668 }
1669 else
1670 {
a80beece
DS
1671 if (conf_if)
1672 return BGP_ERR_NO_INTERFACE_CONFIG;
718e3744 1673
1674 /* If the peer is not part of our confederation, and its not an
1675 iBGP peer then spoof the source AS */
1676 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1677 && ! bgp_confederation_peers_check (bgp, *as)
1678 && bgp->as != *as)
1679 local_as = bgp->confed_id;
1680 else
1681 local_as = bgp->as;
1682
1683 /* If this is IPv4 unicast configuration and "no bgp default
1684 ipv4-unicast" is specified. */
1685
1686 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1687 && afi == AFI_IP && safi == SAFI_UNICAST)
4799375a 1688 peer_create (su, conf_if, bgp, local_as, *as, as_type, 0, 0, NULL);
718e3744 1689 else
4799375a 1690 peer_create (su, conf_if, bgp, local_as, *as, as_type, afi, safi, NULL);
718e3744 1691 }
1692
1693 return 0;
1694}
1695
c8560b44
DW
1696static int
1697non_peergroup_activate_af (struct peer *peer, afi_t afi, safi_t safi)
718e3744 1698{
1699 int active;
1700
718e3744 1701 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
718e3744 1702 {
c8560b44
DW
1703 zlog_err("%s was called for peer-group %s", __func__, peer->host);
1704 return 1;
1705 }
718e3744 1706
c8560b44
DW
1707 /* Nothing to do if we've already activated this peer */
1708 if (peer->afc[afi][safi])
1709 return 0;
718e3744 1710
c8560b44
DW
1711 if (peer_af_create(peer, afi, safi) == NULL)
1712 return 1;
3f9c7369 1713
c8560b44
DW
1714 active = peer_active (peer);
1715 peer->afc[afi][safi] = 1;
1716
1717 if (!active && peer_active (peer))
1718 {
1719 bgp_timer_set (peer);
718e3744 1720 }
c8560b44
DW
1721 else
1722 {
1723 if (peer->status == Established)
1724 {
1725 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1726 {
1727 peer->afc_adv[afi][safi] = 1;
1728 bgp_capability_send (peer, afi, safi,
1729 CAPABILITY_CODE_MP,
1730 CAPABILITY_ACTION_SET);
1731 if (peer->afc_recv[afi][safi])
1732 {
1733 peer->afc_nego[afi][safi] = 1;
1734 bgp_announce_route (peer, afi, safi);
1735 }
1736 }
1737 else
1738 {
1739 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1740 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1741 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1742 }
1743 }
1744 }
1745
1746 return 0;
718e3744 1747}
1748
c8560b44 1749/* Activate the peer or peer group for specified AFI and SAFI. */
718e3744 1750int
c8560b44 1751peer_activate (struct peer *peer, afi_t afi, safi_t safi)
718e3744 1752{
c8560b44 1753 int ret = 0;
718e3744 1754 struct peer_group *group;
1eb8ef25 1755 struct listnode *node, *nnode;
c8560b44 1756 struct peer *tmp_peer;
718e3744 1757
c8560b44
DW
1758 /* Nothing to do if we've already activated this peer */
1759 if (peer->afc[afi][safi])
1760 return ret;
1761
1762 /* This is a peer-group so activate all of the members of the
1763 * peer-group as well */
718e3744 1764 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1765 {
c8560b44 1766 peer->afc[afi][safi] = 1;
718e3744 1767 group = peer->group;
1768
c8560b44
DW
1769 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, tmp_peer))
1770 {
1771 ret |= non_peergroup_activate_af (tmp_peer, afi, safi);
1772 }
718e3744 1773 }
1774 else
1775 {
c8560b44
DW
1776 ret |= non_peergroup_activate_af (peer, afi, safi);
1777 }
1778
1779 return ret;
1780}
1781
1782static int
1783non_peergroup_deactivate_af (struct peer *peer, afi_t afi, safi_t safi)
1784{
1785 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1786 {
1787 zlog_err("%s was called for peer-group %s", __func__, peer->host);
1788 return 1;
718e3744 1789 }
1790
c8560b44 1791 /* Nothing to do if we've already deactivated this peer */
718e3744 1792 if (! peer->afc[afi][safi])
1793 return 0;
1794
1795 /* De-activate the address family configuration. */
1796 peer->afc[afi][safi] = 0;
400b1fad 1797
3f9c7369
DS
1798 if (peer_af_delete(peer, afi, safi) != 0)
1799 {
1800 zlog_err("couldn't delete af structure for peer %s", peer->host);
c8560b44 1801 return 1;
3f9c7369 1802 }
718e3744 1803
c8560b44
DW
1804 if (peer->status == Established)
1805 {
1806 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1807 {
1808 peer->afc_adv[afi][safi] = 0;
1809 peer->afc_nego[afi][safi] = 0;
718e3744 1810
c8560b44
DW
1811 if (peer_active_nego (peer))
1812 {
1813 bgp_capability_send (peer, afi, safi,
1814 CAPABILITY_CODE_MP,
1815 CAPABILITY_ACTION_UNSET);
1816 bgp_clear_route (peer, afi, safi);
1817 peer->pcount[afi][safi] = 0;
1818 }
1819 else
e0701b79 1820 {
1821 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1822 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1823 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1824 }
c8560b44
DW
1825 }
1826 else
1827 {
1828 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1829 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1830 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1831 }
718e3744 1832 }
c8560b44 1833
718e3744 1834 return 0;
1835}
1836
c8560b44
DW
1837int
1838peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1839{
1840 int ret = 0;
1841 struct peer_group *group;
1842 struct peer *tmp_peer;
1843 struct listnode *node, *nnode;
1844
1845 /* Nothing to do if we've already de-activated this peer */
1846 if (! peer->afc[afi][safi])
1847 return ret;
1848
1849 /* This is a peer-group so de-activate all of the members of the
1850 * peer-group as well */
1851 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1852 {
1853 peer->afc[afi][safi] = 0;
1854 group = peer->group;
1855
1856 if (peer_af_delete(peer, afi, safi) != 0)
1857 {
1858 zlog_err("couldn't delete af structure for peer %s", peer->host);
1859 }
1860
1861 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, tmp_peer))
1862 {
1863 ret |= non_peergroup_deactivate_af (tmp_peer, afi, safi);
1864 }
1865 }
1866 else
1867 {
1868 ret |= non_peergroup_deactivate_af (peer, afi, safi);
1869 }
1870
1871 return ret;
1872}
1873
4760600f
DL
1874int
1875peer_afc_set (struct peer *peer, afi_t afi, safi_t safi, int enable)
1876{
1877 if (enable)
1878 return peer_activate (peer, afi, safi);
1879 else
1880 return peer_deactivate (peer, afi, safi);
1881}
1882
da88ea82 1883static void
93406d87 1884peer_nsf_stop (struct peer *peer)
1885{
1886 afi_t afi;
1887 safi_t safi;
1888
1889 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1890 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1891
1892 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
0a28130d 1893 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
93406d87 1894 peer->nsf[afi][safi] = 0;
1895
1896 if (peer->t_gr_restart)
1897 {
1898 BGP_TIMER_OFF (peer->t_gr_restart);
16286195 1899 if (bgp_debug_neighbor_events(peer))
93406d87 1900 zlog_debug ("%s graceful restart timer stopped", peer->host);
1901 }
1902 if (peer->t_gr_stale)
1903 {
1904 BGP_TIMER_OFF (peer->t_gr_stale);
16286195 1905 if (bgp_debug_neighbor_events(peer))
93406d87 1906 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1907 }
1908 bgp_clear_route_all (peer);
1909}
1910
ca058a30
PJ
1911/* Delete peer from confguration.
1912 *
1913 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1914 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1915 *
1916 * This function /should/ take care to be idempotent, to guard against
1917 * it being called multiple times through stray events that come in
1918 * that happen to result in this function being called again. That
1919 * said, getting here for a "Deleted" peer is a bug in the neighbour
1920 * FSM.
1921 */
718e3744 1922int
1923peer_delete (struct peer *peer)
1924{
1925 int i;
1926 afi_t afi;
1927 safi_t safi;
1928 struct bgp *bgp;
1929 struct bgp_filter *filter;
228da428 1930 struct listnode *pn;
019cbf70 1931 int accept_peer;
718e3744 1932
ca058a30 1933 assert (peer->status != Deleted);
1ff9a340 1934
718e3744 1935 bgp = peer->bgp;
019cbf70 1936 accept_peer = CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER);
718e3744 1937
93406d87 1938 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1939 peer_nsf_stop (peer);
1940
1ff9a340
DS
1941 SET_FLAG(peer->flags, PEER_FLAG_DELETE);
1942
228da428 1943 /* If this peer belongs to peer group, clear up the
718e3744 1944 relationship. */
1945 if (peer->group)
1946 {
f14e6fdb
DS
1947 if (peer_dynamic_neighbor(peer))
1948 peer_drop_dynamic_neighbor(peer);
1949
ca058a30
PJ
1950 if ((pn = listnode_lookup (peer->group->peer, peer)))
1951 {
1952 peer = peer_unlock (peer); /* group->peer list reference */
1953 list_delete_node (peer->group->peer, pn);
1954 }
718e3744 1955 peer->group = NULL;
1956 }
200df115 1957
718e3744 1958 /* Withdraw all information from routing table. We can not use
200df115 1959 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1960 * executed after peer structure is deleted.
1961 */
e0701b79 1962 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
718e3744 1963 bgp_stop (peer);
1ff9a340
DS
1964 UNSET_FLAG(peer->flags, PEER_FLAG_DELETE);
1965
1966 if (peer->doppelganger)
9e08021c
DW
1967 {
1968 peer->doppelganger->doppelganger = NULL;
1969 peer->doppelganger = NULL;
1970 }
1ff9a340
DS
1971
1972 UNSET_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER);
ca058a30 1973 bgp_fsm_change_status (peer, Deleted);
0df7c91f
PJ
1974
1975 /* Password configuration */
1976 if (peer->password)
1977 {
1978 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1979 peer->password = NULL;
1980
019cbf70 1981 if (!accept_peer &&
89ca90fa 1982 ! BGP_PEER_SU_UNSPEC(peer) &&
019cbf70 1983 ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
89ca90fa 1984 bgp_md5_unset (peer);
0df7c91f
PJ
1985 }
1986
ca058a30 1987 bgp_timer_set (peer); /* stops all timers for Deleted */
1ff9a340 1988
718e3744 1989 /* Delete from all peer list. */
228da428
CC
1990 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1991 && (pn = listnode_lookup (bgp->peer, peer)))
fee0f4c6 1992 {
228da428
CC
1993 peer_unlock (peer); /* bgp peer list reference */
1994 list_delete_node (bgp->peer, pn);
dd793e4a 1995 hash_release(bgp->peerhash, peer);
228da428 1996 }
200df115 1997
200df115 1998 /* Buffers. */
718e3744 1999 if (peer->ibuf)
9e08021c
DW
2000 {
2001 stream_free (peer->ibuf);
2002 peer->ibuf = NULL;
2003 }
2004
718e3744 2005 if (peer->obuf)
9e08021c
DW
2006 {
2007 stream_fifo_free (peer->obuf);
2008 peer->obuf = NULL;
2009 }
2010
718e3744 2011 if (peer->work)
9e08021c
DW
2012 {
2013 stream_free (peer->work);
2014 peer->work = NULL;
2015 }
2016
8c71e481 2017 if (peer->scratch)
9e08021c
DW
2018 {
2019 stream_free(peer->scratch);
2020 peer->scratch = NULL;
2021 }
18937400 2022
718e3744 2023 /* Local and remote addresses. */
2024 if (peer->su_local)
9e08021c
DW
2025 {
2026 sockunion_free (peer->su_local);
2027 peer->su_local = NULL;
2028 }
2029
718e3744 2030 if (peer->su_remote)
9e08021c
DW
2031 {
2032 sockunion_free (peer->su_remote);
2033 peer->su_remote = NULL;
2034 }
200df115 2035
718e3744 2036 /* Free filter related memory. */
2037 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2038 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2039 {
2040 filter = &peer->filter[afi][safi];
2041
2042 for (i = FILTER_IN; i < FILTER_MAX; i++)
2043 {
2044 if (filter->dlist[i].name)
9e08021c
DW
2045 {
2046 XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[i].name);
2047 filter->dlist[i].name = NULL;
2048 }
2049
718e3744 2050 if (filter->plist[i].name)
9e08021c
DW
2051 {
2052 XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[i].name);
2053 filter->plist[i].name = NULL;
2054 }
2055
718e3744 2056 if (filter->aslist[i].name)
9e08021c
DW
2057 {
2058 XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[i].name);
2059 filter->aslist[i].name = NULL;
2060 }
200df115 2061 }
9e08021c 2062
200df115 2063 for (i = RMAP_IN; i < RMAP_MAX; i++)
2064 {
718e3744 2065 if (filter->map[i].name)
9e08021c
DW
2066 {
2067 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[i].name);
2068 filter->map[i].name = NULL;
2069 }
718e3744 2070 }
2071
2072 if (filter->usmap.name)
9e08021c
DW
2073 {
2074 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
2075 filter->usmap.name = NULL;
2076 }
718e3744 2077
2078 if (peer->default_rmap[afi][safi].name)
9e08021c
DW
2079 {
2080 XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name);
2081 peer->default_rmap[afi][safi].name = NULL;
2082 }
718e3744 2083 }
3f9c7369
DS
2084
2085 FOREACH_AFI_SAFI (afi, safi)
2086 peer_af_delete (peer, afi, safi);
04b6bdc0
DW
2087
2088 if (peer->hostname)
9e08021c 2089 {
4a1ab8e4 2090 XFREE(MTYPE_BGP_PEER_HOST, peer->hostname);
9e08021c
DW
2091 peer->hostname = NULL;
2092 }
2093
04b6bdc0 2094 if (peer->domainname)
9e08021c 2095 {
4a1ab8e4 2096 XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
9e08021c
DW
2097 peer->domainname = NULL;
2098 }
bb86c601 2099
200df115 2100 peer_unlock (peer); /* initial reference */
718e3744 2101
2102 return 0;
2103}
6b0655a2 2104
94f2b392 2105static int
718e3744 2106peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
2107{
2108 return strcmp (g1->name, g2->name);
2109}
2110
718e3744 2111/* Peer group cofiguration. */
2112static struct peer_group *
66e5cd87 2113peer_group_new (void)
718e3744 2114{
4a1ab8e4 2115 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
718e3744 2116 sizeof (struct peer_group));
2117}
2118
94f2b392 2119static void
718e3744 2120peer_group_free (struct peer_group *group)
2121{
4a1ab8e4 2122 XFREE (MTYPE_PEER_GROUP, group);
718e3744 2123}
2124
2125struct peer_group *
fd79ac91 2126peer_group_lookup (struct bgp *bgp, const char *name)
718e3744 2127{
2128 struct peer_group *group;
1eb8ef25 2129 struct listnode *node, *nnode;
718e3744 2130
1eb8ef25 2131 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 2132 {
2133 if (strcmp (group->name, name) == 0)
2134 return group;
2135 }
2136 return NULL;
2137}
2138
2139struct peer_group *
fd79ac91 2140peer_group_get (struct bgp *bgp, const char *name)
718e3744 2141{
2142 struct peer_group *group;
f14e6fdb 2143 afi_t afi;
718e3744 2144
2145 group = peer_group_lookup (bgp, name);
2146 if (group)
2147 return group;
2148
2149 group = peer_group_new ();
2150 group->bgp = bgp;
6e919709 2151 if (group->name)
4a1ab8e4
DL
2152 XFREE(MTYPE_PEER_GROUP_HOST, group->name);
2153 group->name = XSTRDUP(MTYPE_PEER_GROUP_HOST, name);
718e3744 2154 group->peer = list_new ();
f14e6fdb
DS
2155 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2156 group->listen_range[afi] = list_new ();
6f58544d 2157 group->conf = peer_new (bgp);
718e3744 2158 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
2159 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
6e919709
DS
2160 if (group->conf->host)
2161 XFREE(MTYPE_BGP_PEER_HOST, group->conf->host);
228da428 2162 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
718e3744 2163 group->conf->group = group;
2164 group->conf->as = 0;
2165 group->conf->ttl = 1;
fa411a21 2166 group->conf->gtsm_hops = 0;
718e3744 2167 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
2168 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
2169 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
2170 group->conf->keepalive = 0;
2171 group->conf->holdtime = 0;
2172 group->conf->connect = 0;
2173 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
2174 listnode_add_sort (bgp->group, group);
2175
2176 return 0;
2177}
2178
94f2b392 2179static void
a4ed4829 2180peer_group2peer_config_copy (struct peer_group *group, struct peer *peer)
718e3744 2181{
718e3744 2182 struct peer *conf;
8ffedcea 2183 int v6only;
718e3744 2184
2185 conf = group->conf;
718e3744 2186
2187 /* remote-as */
2188 if (conf->as)
2189 peer->as = conf->as;
2190
2191 /* remote-as */
2192 if (conf->change_local_as)
2193 peer->change_local_as = conf->change_local_as;
2194
2195 /* TTL */
2196 peer->ttl = conf->ttl;
2197
fa411a21
NH
2198 /* GTSM hops */
2199 peer->gtsm_hops = conf->gtsm_hops;
2200
8ffedcea
DS
2201 /* this flag is per-neighbor and so has to be preserved */
2202 v6only = CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
2203
718e3744 2204 /* peer flags apply */
2205 peer->flags = conf->flags;
8ffedcea
DS
2206
2207 if (v6only)
2208 SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
2209
718e3744 2210 /* peer config apply */
2211 peer->config = conf->config;
2212
2213 /* peer timers apply */
2214 peer->holdtime = conf->holdtime;
2215 peer->keepalive = conf->keepalive;
2216 peer->connect = conf->connect;
2217 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
2218 peer->v_connect = conf->connect;
2219 else
2220 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
2221
2222 /* advertisement-interval reset */
966f821c
DS
2223 if (CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
2224 peer->v_routeadv = conf->routeadv;
718e3744 2225 else
966f821c
DS
2226 if (peer_sort (peer) == BGP_PEER_IBGP)
2227 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
2228 else
2229 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
718e3744 2230
0df7c91f 2231 /* password apply */
0e4303d3 2232 if (conf->password && !peer->password)
0df7c91f 2233 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
0df7c91f 2234
89ca90fa 2235 if (! BGP_PEER_SU_UNSPEC(peer))
2236 bgp_md5_set (peer);
0df7c91f 2237
718e3744 2238 /* update-source apply */
2239 if (conf->update_source)
2240 {
2241 if (peer->update_source)
2242 sockunion_free (peer->update_source);
2243 if (peer->update_if)
2244 {
2245 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2246 peer->update_if = NULL;
2247 }
2248 peer->update_source = sockunion_dup (conf->update_source);
2249 }
2250 else if (conf->update_if)
2251 {
2252 if (peer->update_if)
6e919709 2253 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
718e3744 2254 if (peer->update_source)
2255 {
2256 sockunion_free (peer->update_source);
2257 peer->update_source = NULL;
2258 }
2259 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
2260 }
8d78d851 2261
2262 bgp_bfd_peer_group2peer_copy(conf, peer);
a4ed4829
DW
2263}
2264
2265static void
2266peer_group2peer_config_copy_af (struct peer_group *group, struct peer *peer,
2267 afi_t afi, safi_t safi)
2268{
2269 int in = FILTER_IN;
2270 int out = FILTER_OUT;
2271 struct peer *conf;
2272 struct bgp_filter *pfilter;
2273 struct bgp_filter *gfilter;
2274
2275 conf = group->conf;
2276 pfilter = &peer->filter[afi][safi];
2277 gfilter = &conf->filter[afi][safi];
2278
2279 /* peer af_flags apply */
2280 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
2281
2282 /* maximum-prefix */
2283 peer->pmax[afi][safi] = conf->pmax[afi][safi];
2284 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
2285 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
2286
2287 /* allowas-in */
2288 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
2289
d93f7ffc
DW
2290 /* weight */
2291 peer->weight[afi][safi] = conf->weight[afi][safi];
2292
a4ed4829
DW
2293 /* default-originate route-map */
2294 if (conf->default_rmap[afi][safi].name)
2295 {
2296 if (peer->default_rmap[afi][safi].name)
2297 XFREE(MTYPE_BGP_FILTER_NAME, peer->default_rmap[afi][safi].name);
2298 peer->default_rmap[afi][safi].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, conf->default_rmap[afi][safi].name);
2299 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
2300 }
718e3744 2301
2302 /* inbound filter apply */
2303 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
2304 {
2305 if (pfilter->dlist[in].name)
6e919709
DS
2306 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->dlist[in].name);
2307 pfilter->dlist[in].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->dlist[in].name);
718e3744 2308 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
2309 }
a4ed4829 2310
718e3744 2311 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
2312 {
2313 if (pfilter->plist[in].name)
6e919709
DS
2314 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->plist[in].name);
2315 pfilter->plist[in].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->plist[in].name);
718e3744 2316 pfilter->plist[in].plist = gfilter->plist[in].plist;
2317 }
a4ed4829 2318
718e3744 2319 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
2320 {
2321 if (pfilter->aslist[in].name)
6e919709
DS
2322 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->aslist[in].name);
2323 pfilter->aslist[in].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->aslist[in].name);
718e3744 2324 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
2325 }
a4ed4829 2326
fee0f4c6 2327 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
718e3744 2328 {
fee0f4c6 2329 if (pfilter->map[RMAP_IN].name)
6e919709
DS
2330 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->map[RMAP_IN].name);
2331 pfilter->map[RMAP_IN].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->map[RMAP_IN].name);
fee0f4c6 2332 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
718e3744 2333 }
2334
2335 /* outbound filter apply */
2336 if (gfilter->dlist[out].name)
2337 {
2338 if (pfilter->dlist[out].name)
6e919709
DS
2339 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->dlist[out].name);
2340 pfilter->dlist[out].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->dlist[out].name);
718e3744 2341 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
2342 }
2343 else
2344 {
2345 if (pfilter->dlist[out].name)
6e919709 2346 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->dlist[out].name);
718e3744 2347 pfilter->dlist[out].name = NULL;
2348 pfilter->dlist[out].alist = NULL;
2349 }
a4ed4829 2350
718e3744 2351 if (gfilter->plist[out].name)
2352 {
2353 if (pfilter->plist[out].name)
6e919709
DS
2354 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->plist[out].name);
2355 pfilter->plist[out].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->plist[out].name);
718e3744 2356 pfilter->plist[out].plist = gfilter->plist[out].plist;
2357 }
2358 else
2359 {
2360 if (pfilter->plist[out].name)
6e919709 2361 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->plist[out].name);
718e3744 2362 pfilter->plist[out].name = NULL;
2363 pfilter->plist[out].plist = NULL;
2364 }
a4ed4829 2365
718e3744 2366 if (gfilter->aslist[out].name)
2367 {
2368 if (pfilter->aslist[out].name)
6e919709
DS
2369 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->aslist[out].name);
2370 pfilter->aslist[out].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->aslist[out].name);
718e3744 2371 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
2372 }
2373 else
2374 {
2375 if (pfilter->aslist[out].name)
6e919709 2376 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->aslist[out].name);
718e3744 2377 pfilter->aslist[out].name = NULL;
2378 pfilter->aslist[out].aslist = NULL;
2379 }
a4ed4829 2380
fee0f4c6 2381 if (gfilter->map[RMAP_OUT].name)
2382 {
2383 if (pfilter->map[RMAP_OUT].name)
6e919709
DS
2384 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->map[RMAP_OUT].name);
2385 pfilter->map[RMAP_OUT].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->map[RMAP_OUT].name);
fee0f4c6 2386 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
2387 }
2388 else
2389 {
2390 if (pfilter->map[RMAP_OUT].name)
6e919709 2391 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->map[RMAP_OUT].name);
fee0f4c6 2392 pfilter->map[RMAP_OUT].name = NULL;
2393 pfilter->map[RMAP_OUT].map = NULL;
2394 }
2395
718e3744 2396 if (gfilter->usmap.name)
2397 {
2398 if (pfilter->usmap.name)
6e919709
DS
2399 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->usmap.name);
2400 pfilter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->usmap.name);
718e3744 2401 pfilter->usmap.map = gfilter->usmap.map;
2402 }
2403 else
2404 {
2405 if (pfilter->usmap.name)
6e919709 2406 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->usmap.name);
718e3744 2407 pfilter->usmap.name = NULL;
2408 pfilter->usmap.map = NULL;
2409 }
2410}
2411
2412/* Peer group's remote AS configuration. */
2413int
0299c004
DS
2414peer_group_remote_as (struct bgp *bgp, const char *group_name,
2415 as_t *as, int as_type)
718e3744 2416{
2417 struct peer_group *group;
2418 struct peer *peer;
1eb8ef25 2419 struct listnode *node, *nnode;
718e3744 2420
2421 group = peer_group_lookup (bgp, group_name);
2422 if (! group)
2423 return -1;
2424
0299c004 2425 if ((as_type == group->conf->as_type) && (group->conf->as == *as))
718e3744 2426 return 0;
2427
0299c004 2428
718e3744 2429 /* When we setup peer-group AS number all peer group member's AS
2430 number must be updated to same number. */
0299c004 2431 peer_as_change (group->conf, *as, as_type);
718e3744 2432
1eb8ef25 2433 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 2434 {
9da3a1a1
DS
2435 if (((peer->as_type == AS_SPECIFIED) && peer->as != *as) ||
2436 (peer->as_type != as_type))
0299c004 2437 peer_as_change (peer, *as, as_type);
718e3744 2438 }
2439
2440 return 0;
2441}
2442
2443int
2444peer_group_delete (struct peer_group *group)
2445{
2446 struct bgp *bgp;
2447 struct peer *peer;
f14e6fdb 2448 struct prefix *prefix;
1ff9a340 2449 struct peer *other;
1eb8ef25 2450 struct listnode *node, *nnode;
f14e6fdb 2451 afi_t afi;
718e3744 2452
2453 bgp = group->bgp;
2454
1eb8ef25 2455 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 2456 {
1ff9a340 2457 other = peer->doppelganger;
718e3744 2458 peer_delete (peer);
1ff9a340
DS
2459 if (other && other->status != Deleted)
2460 {
2461 other->group = NULL;
2462 peer_delete(other);
2463 }
718e3744 2464 }
2465 list_delete (group->peer);
2466
f14e6fdb
DS
2467 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2468 {
2469 for (ALL_LIST_ELEMENTS (group->listen_range[afi], node, nnode, prefix))
2470 {
2471 prefix_free(prefix);
2472 }
2473 list_delete (group->listen_range[afi]);
2474 }
2475
6e919709 2476 XFREE(MTYPE_BGP_PEER_HOST, group->name);
718e3744 2477 group->name = NULL;
2478
2479 group->conf->group = NULL;
2480 peer_delete (group->conf);
2481
2482 /* Delete from all peer_group list. */
2483 listnode_delete (bgp->group, group);
2484
7f342629 2485 bfd_info_free(&(group->conf->bfd_info));
c43ed2e4 2486
718e3744 2487 peer_group_free (group);
2488
2489 return 0;
2490}
2491
2492int
2493peer_group_remote_as_delete (struct peer_group *group)
2494{
1ff9a340 2495 struct peer *peer, *other;
1eb8ef25 2496 struct listnode *node, *nnode;
718e3744 2497
0299c004
DS
2498 if ((group->conf->as_type == AS_UNSPECIFIED) ||
2499 ((! group->conf->as) && (group->conf->as_type == AS_SPECIFIED)))
718e3744 2500 return 0;
2501
1eb8ef25 2502 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 2503 {
1ff9a340
DS
2504 other = peer->doppelganger;
2505
718e3744 2506 peer_delete (peer);
1ff9a340
DS
2507
2508 if (other && other->status != Deleted)
2509 {
2510 other->group = NULL;
2511 peer_delete(other);
2512 }
718e3744 2513 }
2514 list_delete_all_node (group->peer);
2515
2516 group->conf->as = 0;
0299c004 2517 group->conf->as_type = AS_UNSPECIFIED;
718e3744 2518
2519 return 0;
2520}
2521
f14e6fdb
DS
2522int
2523peer_group_listen_range_add (struct peer_group *group, struct prefix *range)
2524{
2525 struct prefix *prefix;
2526 struct listnode *node, *nnode;
2527 afi_t afi;
2528
2529 afi = family2afi(range->family);
2530
2531 /* Group needs remote AS configured. */
2aab8d2b 2532 if (group->conf->as_type == AS_UNSPECIFIED)
f14e6fdb
DS
2533 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
2534
2535 /* Ensure no duplicates. Currently we don't care about overlaps. */
2536 for (ALL_LIST_ELEMENTS (group->listen_range[afi], node, nnode, prefix))
2537 {
2538 if (prefix_same(range, prefix))
57e9ee0a 2539 return 0;
f14e6fdb
DS
2540 }
2541
2542 prefix = prefix_new();
2543 prefix_copy(prefix, range);
2544 listnode_add(group->listen_range[afi], prefix);
2545 return 0;
2546}
2547
2548int
2549peer_group_listen_range_del (struct peer_group *group, struct prefix *range)
2550{
40ee54a7 2551 struct prefix *prefix, prefix2;
f14e6fdb
DS
2552 struct listnode *node, *nnode;
2553 struct peer *peer;
2554 afi_t afi;
4690c7d7 2555 char buf[PREFIX2STR_BUFFER];
f14e6fdb
DS
2556
2557 afi = family2afi(range->family);
2558
2559 /* Identify the listen range. */
2560 for (ALL_LIST_ELEMENTS (group->listen_range[afi], node, nnode, prefix))
2561 {
2562 if (prefix_same(range, prefix))
2563 break;
2564 }
2565
2566 if (!prefix)
2567 return BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_NOT_FOUND;
2568
2569 prefix2str(prefix, buf, sizeof(buf));
2570
2571 /* Dispose off any dynamic neighbors that exist due to this listen range */
2572 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
2573 {
2574 if (!peer_dynamic_neighbor (peer))
2575 continue;
2576
40ee54a7
TT
2577 sockunion2hostprefix(&peer->su, &prefix2);
2578 if (prefix_match(prefix, &prefix2))
f14e6fdb
DS
2579 {
2580 if (bgp_debug_neighbor_events(peer))
2581 zlog_debug ("Deleting dynamic neighbor %s group %s upon "
2582 "delete of listen range %s",
2583 peer->host, group->name, buf);
2584 peer_delete (peer);
2585 }
2586 }
2587
2588 /* Get rid of the listen range */
2589 listnode_delete(group->listen_range[afi], prefix);
2590
2591 return 0;
2592}
2593
718e3744 2594/* Bind specified peer to peer group. */
2595int
a80beece 2596peer_group_bind (struct bgp *bgp, union sockunion *su, struct peer *peer,
c8560b44 2597 struct peer_group *group, as_t *as)
718e3744 2598{
718e3744 2599 int first_member = 0;
c8560b44
DW
2600 afi_t afi;
2601 safi_t safi;
b3a39dc5 2602 int cap_enhe_preset = 0;
718e3744 2603
2604 /* Lookup the peer. */
a80beece 2605 if (!peer)
c8560b44 2606 peer = peer_lookup (bgp, su);
718e3744 2607
c8560b44
DW
2608 /* The peer exist, bind it to the peer-group */
2609 if (peer)
718e3744 2610 {
c8560b44
DW
2611 /* When the peer already belongs to peer group, check the consistency. */
2612 if (peer_group_active (peer) && strcmp (peer->group->name, group->name) != 0)
4c48cf63 2613 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
718e3744 2614
c8560b44
DW
2615 /* The peer has not specified a remote-as, inherit it from the
2616 * peer-group */
2617 if (peer->as_type == AS_UNSPECIFIED)
2618 {
2619 peer->as_type = group->conf->as_type;
2620 peer->as = group->conf->as;
2621 }
200df115 2622
c8560b44
DW
2623 if (! group->conf->as)
2624 {
2625 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
2626 && peer_sort (group->conf) != peer_sort (peer))
2627 {
2628 if (as)
2629 *as = peer->as;
2630 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
2631 }
718e3744 2632
c8560b44
DW
2633 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
2634 first_member = 1;
2635 }
718e3744 2636
b3a39dc5
DD
2637 if (CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE))
2638 cap_enhe_preset = 1;
2639
a4ed4829
DW
2640 peer_group2peer_config_copy(group, peer);
2641
b3a39dc5
DD
2642 /*
2643 * Capability extended-nexthop is enabled for an interface neighbor by
2644 * default. So, fix that up here.
2645 */
2646 if (peer->ifp && cap_enhe_preset)
2647 peer_flag_set (peer, PEER_FLAG_CAPABILITY_ENHE);
2648
c8560b44
DW
2649 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2650 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2651 {
2652 if (group->conf->afc[afi][safi])
2653 {
2654 peer->afc[afi][safi] = 1;
718e3744 2655
c8560b44
DW
2656 if (peer_af_find(peer, afi, safi) || peer_af_create(peer, afi, safi))
2657 {
a4ed4829 2658 peer_group2peer_config_copy_af (group, peer, afi, safi);
c8560b44
DW
2659 }
2660 }
2661 }
718e3744 2662
c8560b44
DW
2663 if (peer->group)
2664 {
2665 assert (group && peer->group == group);
2666 }
2667 else
2668 {
0aaa34db
DS
2669 struct listnode *pn;
2670 pn = listnode_lookup (bgp->peer, peer);
2671 list_delete_node (bgp->peer, pn);
c8560b44 2672 peer->group = group;
0aaa34db 2673 listnode_add_sort (bgp->peer, peer);
718e3744 2674
c8560b44
DW
2675 peer = peer_lock (peer); /* group->peer list reference */
2676 listnode_add (group->peer, peer);
2677 }
0299c004 2678
c8560b44
DW
2679 if (first_member)
2680 {
2681 /* Advertisement-interval reset */
2682 if (! CHECK_FLAG (group->conf->config, PEER_CONFIG_ROUTEADV))
2683 {
2684 if (peer_sort (group->conf) == BGP_PEER_IBGP)
2685 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
2686 else
2687 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
2688 }
718e3744 2689
c8560b44
DW
2690 /* ebgp-multihop reset */
2691 if (peer_sort (group->conf) == BGP_PEER_IBGP)
9b1be336 2692 group->conf->ttl = MAXTTL;
718e3744 2693
c8560b44
DW
2694 /* local-as reset */
2695 if (peer_sort (group->conf) != BGP_PEER_EBGP)
2696 {
2697 group->conf->change_local_as = 0;
2698 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
2699 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
2700 }
2701 }
2702
2703 SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
2704
2705 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2706 {
2707 peer->last_reset = PEER_DOWN_RMAP_BIND;
2708 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2709 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2710 }
2711 else
2712 {
2713 bgp_session_reset(peer);
2714 }
3f9c7369 2715 }
c8560b44
DW
2716
2717 /* Create a new peer. */
2718 else
718e3744 2719 {
c8560b44
DW
2720 if ((group->conf->as_type == AS_SPECIFIED) && (! group->conf->as))
2721 {
2722 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
2723 }
2724
f813b13b 2725 peer = peer_create (su, NULL, bgp, bgp->as, group->conf->as, group->conf->as_type, 0, 0, group);
c8560b44 2726
ca058a30 2727 peer = peer_lock (peer); /* group->peer list reference */
718e3744 2728 listnode_add (group->peer, peer);
718e3744 2729
a4ed4829
DW
2730 peer_group2peer_config_copy(group, peer);
2731
c8560b44
DW
2732 /* If the peer-group is active for this afi/safi then activate for this peer */
2733 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2734 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2735 if (group->conf->afc[afi][safi])
2736 {
2737 peer->afc[afi][safi] = 1;
2738 peer_af_create(peer, afi, safi);
a4ed4829 2739 peer_group2peer_config_copy_af (group, peer, afi, safi);
c8560b44 2740 }
fee0f4c6 2741
c8560b44 2742 SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
718e3744 2743
c8560b44
DW
2744 /* Set up peer's events and timers. */
2745 if (peer_active (peer))
2746 bgp_timer_set (peer);
e0701b79 2747 }
718e3744 2748
2749 return 0;
2750}
2751
2752int
2753peer_group_unbind (struct bgp *bgp, struct peer *peer,
c8560b44 2754 struct peer_group *group)
718e3744 2755{
1ff9a340 2756 struct peer *other;
c8560b44
DW
2757 afi_t afi;
2758 safi_t safi;
718e3744 2759
2760 if (group != peer->group)
2761 return BGP_ERR_PEER_GROUP_MISMATCH;
2762
c8560b44
DW
2763 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2764 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2765 {
2766 if (peer->afc[afi][safi])
2767 {
2768 peer->afc[afi][safi] = 0;
2769 peer_af_flag_reset (peer, afi, safi);
718e3744 2770
c8560b44
DW
2771 if (peer_af_delete(peer, afi, safi) != 0)
2772 {
2773 zlog_err("couldn't delete af structure for peer %s", peer->host);
2774 }
2775 }
2776 }
2777
2778 assert (listnode_lookup (group->peer, peer));
2779 peer_unlock (peer); /* peer group list reference */
2780 listnode_delete (group->peer, peer);
2781 peer->group = NULL;
2782 other = peer->doppelganger;
2783
2784 if (group->conf->as)
718e3744 2785 {
c8560b44
DW
2786 peer_delete (peer);
2787 if (other && other->status != Deleted)
2788 {
2789 if (other->group)
2790 {
2791 peer_unlock(other);
2792 listnode_delete(group->peer, other);
2793 }
2794 other->group = NULL;
2795 peer_delete(other);
2796 }
2797 return 0;
718e3744 2798 }
2799
c8560b44
DW
2800 bgp_bfd_deregister_peer(peer);
2801 peer_global_config_reset (peer);
2802
6aa136f1 2803 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 2804 {
2805 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
2806 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2807 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2808 }
718e3744 2809 else
1ff9a340 2810 bgp_session_reset(peer);
718e3744 2811
2812 return 0;
2813}
6b0655a2 2814
fe7d2a48
DS
2815static int
2816bgp_startup_timer_expire (struct thread *thread)
2817{
2818 struct bgp *bgp;
2819
2820 bgp = THREAD_ARG (thread);
2821 bgp->t_startup = NULL;
2822
2823 return 0;
2824}
2825
718e3744 2826/* BGP instance creation by `router bgp' commands. */
94f2b392 2827static struct bgp *
ad4cbda1 2828bgp_create (as_t *as, const char *name, enum bgp_instance_type inst_type)
718e3744 2829{
2830 struct bgp *bgp;
2831 afi_t afi;
2832 safi_t safi;
2833
200df115 2834 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
2835 return NULL;
2836
ad4cbda1 2837 if (BGP_DEBUG (zebra, ZEBRA))
2838 {
2839 if (inst_type == BGP_INSTANCE_TYPE_DEFAULT)
2840 zlog_debug("Creating Default VRF, AS %u", *as);
2841 else
2842 zlog_debug("Creating %s %s, AS %u",
2843 (inst_type == BGP_INSTANCE_TYPE_VRF) ? "VRF" : "VIEW",
2844 name, *as);
2845 }
2846
0088b5dc 2847 bgp_lock (bgp);
ad4cbda1 2848 bgp->inst_type = inst_type;
5c81a5f3 2849 bgp->vrf_id = (inst_type == BGP_INSTANCE_TYPE_DEFAULT) ?
2850 VRF_DEFAULT : VRF_UNKNOWN;
6f58544d 2851 bgp->peer_self = peer_new (bgp);
6e919709
DS
2852 if (bgp->peer_self->host)
2853 XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->host);
2854 bgp->peer_self->host = XSTRDUP(MTYPE_BGP_PEER_HOST, "Static announcement");
718e3744 2855 bgp->peer = list_new ();
2856 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
dd793e4a 2857 bgp->peerhash = hash_create (peer_hash_key_make, peer_hash_cmp);
718e3744 2858
2859 bgp->group = list_new ();
2860 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
2861
2862 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2863 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2864 {
64e580a7
PJ
2865 bgp->route[afi][safi] = bgp_table_init (afi, safi);
2866 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
2867 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
219178b6
DW
2868
2869 /* Enable maximum-paths */
d5b77cc2
DS
2870 bgp_maximum_paths_set (bgp, afi, safi, BGP_PEER_EBGP, MULTIPATH_NUM, 0);
2871 bgp_maximum_paths_set (bgp, afi, safi, BGP_PEER_IBGP, MULTIPATH_NUM, 0);
718e3744 2872 }
2873
f188f2c4 2874 bgp->v_update_delay = BGP_UPDATE_DELAY_DEF;
718e3744 2875 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
3f9c7369 2876 bgp->default_subgroup_pkt_queue_max = BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX;
718e3744 2877 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
2878 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
538621f2 2879 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
2880 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
f14e6fdb
DS
2881 bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT;
2882 bgp->dynamic_neighbors_count = 0;
5623e905 2883 bgp_flag_set (bgp, BGP_FLAG_IMPORT_CHECK);
15f3b5c0 2884 bgp_flag_set (bgp, BGP_FLAG_SHOW_HOSTNAME);
6793fbe0 2885 bgp_flag_set (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES);
1475ac87 2886 bgp_flag_set (bgp, BGP_FLAG_DETERMINISTIC_MED);
adbac85e 2887 bgp->addpath_tx_id = BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE;
718e3744 2888
2889 bgp->as = *as;
2890
65efcfce
LB
2891#if ENABLE_BGP_VNC
2892 bgp->rfapi = bgp_rfapi_new(bgp);
2893 assert(bgp->rfapi);
2894 assert(bgp->rfapi_cfg);
2895#endif /* ENABLE_BGP_VNC */
2896
718e3744 2897 if (name)
6aeb9e78
DS
2898 {
2899 bgp->name = XSTRDUP(MTYPE_BGP, name);
2900 }
2901 else
2902 {
ad4cbda1 2903 /* TODO - The startup timer needs to be run for the whole of BGP */
6aeb9e78
DS
2904 THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire,
2905 bgp, bgp->restart_time);
2906 }
718e3744 2907
cb1faec9 2908 bgp->wpkt_quanta = BGP_WRITE_PACKET_MAX;
3f9c7369 2909 bgp->coalesce_time = BGP_DEFAULT_SUBGROUP_COALESCE_TIME;
cb1faec9 2910
6aeb9e78
DS
2911 update_bgp_group_init(bgp);
2912 return bgp;
2913}
2914
ad4cbda1 2915/* Return the "default VRF" instance of BGP. */
718e3744 2916struct bgp *
94f2b392 2917bgp_get_default (void)
718e3744 2918{
ad4cbda1 2919 struct bgp *bgp;
2920 struct listnode *node, *nnode;
2921
2922 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
2923 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
2924 return bgp;
718e3744 2925 return NULL;
2926}
2927
2928/* Lookup BGP entry. */
2929struct bgp *
fd79ac91 2930bgp_lookup (as_t as, const char *name)
718e3744 2931{
2932 struct bgp *bgp;
1eb8ef25 2933 struct listnode *node, *nnode;
718e3744 2934
1eb8ef25 2935 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
718e3744 2936 if (bgp->as == as
2937 && ((bgp->name == NULL && name == NULL)
2938 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
2939 return bgp;
2940 return NULL;
2941}
2942
2943/* Lookup BGP structure by view name. */
2944struct bgp *
fd79ac91 2945bgp_lookup_by_name (const char *name)
718e3744 2946{
2947 struct bgp *bgp;
1eb8ef25 2948 struct listnode *node, *nnode;
718e3744 2949
1eb8ef25 2950 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
718e3744 2951 if ((bgp->name == NULL && name == NULL)
2952 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2953 return bgp;
2954 return NULL;
2955}
2956
d1be1f08 2957/* Lookup BGP instance based on VRF id. */
2958/* Note: Only to be used for incoming messages from Zebra. */
6aeb9e78
DS
2959struct bgp *
2960bgp_lookup_by_vrf_id (vrf_id_t vrf_id)
ad4cbda1 2961{
2962 struct vrf *vrf;
2963
d1be1f08 2964 /* Lookup VRF (in tree) and follow link. */
2965 vrf = vrf_lookup (vrf_id);
ad4cbda1 2966 if (!vrf)
d1be1f08 2967 return NULL;
2968 return (vrf->info) ? (struct bgp *)vrf->info : NULL;
ad4cbda1 2969}
2970
718e3744 2971/* Called from VTY commands. */
2972int
ad4cbda1 2973bgp_get (struct bgp **bgp_val, as_t *as, const char *name,
2974 enum bgp_instance_type inst_type)
718e3744 2975{
2976 struct bgp *bgp;
2977
2978 /* Multiple instance check. */
2979 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2980 {
2981 if (name)
2982 bgp = bgp_lookup_by_name (name);
2983 else
2984 bgp = bgp_get_default ();
2985
2986 /* Already exists. */
2987 if (bgp)
2988 {
2989 if (bgp->as != *as)
2990 {
2991 *as = bgp->as;
2992 return BGP_ERR_INSTANCE_MISMATCH;
2993 }
ad4cbda1 2994 if (bgp->inst_type != inst_type)
2995 return BGP_ERR_INSTANCE_MISMATCH;
718e3744 2996 *bgp_val = bgp;
2997 return 0;
2998 }
2999 }
3000 else
3001 {
3002 /* BGP instance name can not be specified for single instance. */
3003 if (name)
3004 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
3005
3006 /* Get default BGP structure if exists. */
3007 bgp = bgp_get_default ();
3008
3009 if (bgp)
3010 {
3011 if (bgp->as != *as)
3012 {
3013 *as = bgp->as;
3014 return BGP_ERR_AS_MISMATCH;
3015 }
3016 *bgp_val = bgp;
3017 return 0;
3018 }
3019 }
3020
ad4cbda1 3021 bgp = bgp_create (as, name, inst_type);
6aeb9e78
DS
3022 bgp_router_id_set(bgp, &bgp->router_id_zebra);
3023 bgp_address_init (bgp);
3024 bgp_scan_init (bgp);
1758dbaa
SA
3025 *bgp_val = bgp;
3026
0de4848d 3027 bgp->t_rmap_def_originate_eval = NULL;
518f0eb1 3028
ad12dde6 3029 /* Create BGP server socket, if first instance. */
cccbc015
PJ
3030 if (list_isempty(bm->bgp)
3031 && !bgp_option_check (BGP_OPT_NO_LISTEN))
ad12dde6
PJ
3032 {
3033 if (bgp_socket (bm->port, bm->address) < 0)
3034 return BGP_ERR_INVALID_VALUE;
3035 }
3036
718e3744 3037 listnode_add (bm->bgp, bgp);
718e3744 3038
d1be1f08 3039 /* If Default instance or VRF, link to the VRF structure, if present. */
3040 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT ||
3041 bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
3042 {
3043 struct vrf *vrf;
3044
3045 vrf = bgp_vrf_lookup_by_instance_type (bgp);
3046 if (vrf)
b33adb7c 3047 {
3048 bgp_vrf_link (bgp, vrf);
3049 bgp_if_init (bgp);
3050 }
d1be1f08 3051 }
ad4cbda1 3052
3053 /* Register with Zebra, if needed */
3054 if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
3055 bgp_zebra_instance_register (bgp);
3056
6aeb9e78 3057
718e3744 3058 return 0;
3059}
3060
ad4cbda1 3061/*
3062 * Make BGP instance "up". Applies only to VRFs (non-default) and
3063 * implies the VRF has been learnt from Zebra.
3064 */
6aeb9e78 3065void
ad4cbda1 3066bgp_instance_up (struct bgp *bgp)
718e3744 3067{
3068 struct peer *peer;
ad4cbda1 3069 struct listnode *node, *next;
718e3744 3070
ad4cbda1 3071 /* Register with zebra. */
3072 bgp_zebra_instance_register (bgp);
d4a7a753 3073
ad4cbda1 3074 /* Kick off any peers that may have been configured. */
cd92e548
DS
3075 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
3076 {
ad4cbda1 3077 if (!BGP_PEER_START_SUPPRESSED (peer))
3078 BGP_EVENT_ADD (peer, BGP_Start);
cd92e548
DS
3079 }
3080
ad4cbda1 3081 /* Process any networks that have been configured. */
3082 bgp_static_add (bgp);
3083}
718e3744 3084
ad4cbda1 3085/*
3086 * Make BGP instance "down". Applies only to VRFs (non-default) and
3087 * implies the VRF has been deleted by Zebra.
3088 */
3089void
3090bgp_instance_down (struct bgp *bgp)
3091{
3092 struct peer *peer;
3093 struct listnode *node;
3094 struct listnode *next;
718e3744 3095
ad4cbda1 3096 /* Stop timers. */
ad4cbda1 3097 if (bgp->t_rmap_def_originate_eval)
6aa136f1 3098 {
ad4cbda1 3099 BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval);
3100 bgp_unlock(bgp); /* TODO - This timer is started with a lock - why? */
6aa136f1 3101 }
228da428 3102
ad4cbda1 3103 /* Bring down peers, so corresponding routes are purged. */
1ff9a340
DS
3104 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
3105 {
3106 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
ad4cbda1 3107 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
3108 else
3109 bgp_session_reset(peer);
6aeb9e78
DS
3110 }
3111
ad4cbda1 3112 /* Purge network and redistributed routes. */
3113 bgp_purge_static_redist_routes (bgp);
6aeb9e78 3114}
1ff9a340 3115
6aeb9e78
DS
3116/* Delete BGP instance. */
3117int
3118bgp_delete (struct bgp *bgp)
3119{
3120 struct peer *peer;
3121 struct peer_group *group;
3122 struct listnode *node, *next;
3123 afi_t afi;
3124 int i;
3125
7cb43556 3126 THREAD_OFF (bgp->t_startup);
3127
ad4cbda1 3128 if (BGP_DEBUG (zebra, ZEBRA))
3129 {
3130 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
3131 zlog_debug("Deleting Default VRF");
3132 else
3133 zlog_debug("Deleting %s %s",
3134 (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) ? "VRF" : "VIEW",
3135 bgp->name);
3136 }
3137
3138 /* Stop timers. */
ad4cbda1 3139 if (bgp->t_rmap_def_originate_eval)
3140 {
3141 BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval);
3142 bgp_unlock(bgp); /* TODO - This timer is started with a lock - why? */
3143 }
3144
3145 /* Inform peers we're going down. */
3146 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
3147 {
3148 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3149 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
3150 }
7cb43556 3151
ad4cbda1 3152 /* Delete static routes (networks). */
6aeb9e78
DS
3153 bgp_static_delete (bgp);
3154
3155 /* Unset redistribution. */
3156 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3157 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3158 if (i != ZEBRA_ROUTE_BGP)
3159 bgp_redistribute_unset (bgp, afi, i, 0);
3160
ad4cbda1 3161 /* Free peers and peer-groups. */
6aeb9e78 3162 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
ad4cbda1 3163 peer_group_delete (group);
6aeb9e78
DS
3164
3165 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
ad4cbda1 3166 peer_delete (peer);
1ff9a340 3167
0088b5dc
SH
3168 if (bgp->peer_self) {
3169 peer_delete(bgp->peer_self);
3170 bgp->peer_self = NULL;
3171 }
0de4848d 3172
3d68677e 3173 update_bgp_group_free (bgp);
ad4cbda1 3174
3175 /* TODO - Other memory may need to be freed - e.g., NHT */
3176
65efcfce
LB
3177#if ENABLE_BGP_VNC
3178 rfapi_delete(bgp);
3179 bgp_cleanup_routes(); /* rfapi cleanup can create route entries! */
3180#endif
3181
fd35b948
PJ
3182 /* Remove visibility via the master list - there may however still be
3183 * routes to be processed still referencing the struct bgp.
3184 */
3185 listnode_delete (bm->bgp, bgp);
d023aec4
SH
3186 if (list_isempty(bm->bgp))
3187 bgp_close ();
3188
ad4cbda1 3189 /* Deregister from Zebra, if needed */
3190 if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
3191 bgp_zebra_instance_deregister (bgp);
3192
009b18fc 3193 /* Free interfaces in this instance. */
3194 bgp_if_finish (bgp);
3195
87d4a781 3196 thread_master_free_unused(bm->master);
0088b5dc 3197 bgp_unlock(bgp); /* initial reference */
6410e93a 3198
0088b5dc
SH
3199 return 0;
3200}
3201
3202static void bgp_free (struct bgp *);
3203
3204void
3205bgp_lock (struct bgp *bgp)
3206{
3207 ++bgp->lock;
3208}
3209
3210void
3211bgp_unlock(struct bgp *bgp)
3212{
228da428 3213 assert(bgp->lock > 0);
0088b5dc
SH
3214 if (--bgp->lock == 0)
3215 bgp_free (bgp);
3216}
3217
3218static void
3219bgp_free (struct bgp *bgp)
3220{
3221 afi_t afi;
3222 safi_t safi;
d3f5a0d3 3223 struct vrf *vrf;
0088b5dc
SH
3224
3225 list_delete (bgp->group);
3226 list_delete (bgp->peer);
3ffe142a
DW
3227
3228 if (bgp->peerhash)
3229 {
3230 hash_free(bgp->peerhash);
3231 bgp->peerhash = NULL;
3232 }
fee0f4c6 3233
718e3744 3234 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3235 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3236 {
3237 if (bgp->route[afi][safi])
228da428 3238 bgp_table_finish (&bgp->route[afi][safi]);
718e3744 3239 if (bgp->aggregate[afi][safi])
228da428 3240 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
718e3744 3241 if (bgp->rib[afi][safi])
228da428 3242 bgp_table_finish (&bgp->rib[afi][safi]);
718e3744 3243 }
d3f5a0d3 3244
5e6d589c
DS
3245 bgp_address_destroy (bgp);
3246
d3f5a0d3 3247 /* If Default instance or VRF, unlink from the VRF structure. */
3248 vrf = bgp_vrf_lookup_by_instance_type (bgp);
3249 if (vrf)
3250 bgp_vrf_unlink (bgp, vrf);
3251
4ac82321 3252 if (bgp->name)
3253 XFREE(MTYPE_BGP, bgp->name);
3254
718e3744 3255 XFREE (MTYPE_BGP, bgp);
718e3744 3256}
6b0655a2 3257
a80beece
DS
3258struct peer *
3259peer_lookup_by_conf_if (struct bgp *bgp, const char *conf_if)
3260{
3261 struct peer *peer;
3262 struct listnode *node, *nnode;
3263
3264 if (!conf_if)
3265 return NULL;
3266
3267 if (bgp != NULL)
3268 {
3269 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
3270 if (peer->conf_if && !strcmp(peer->conf_if, conf_if)
3271 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
3272 return peer;
3273 }
3274 else if (bm->bgp != NULL)
3275 {
3276 struct listnode *bgpnode, *nbgpnode;
3277
3278 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
3279 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
3280 if (peer->conf_if && !strcmp(peer->conf_if, conf_if)
3281 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
3282 return peer;
3283 }
3284 return NULL;
3285}
3286
04b6bdc0
DW
3287struct peer *
3288peer_lookup_by_hostname (struct bgp *bgp, const char *hostname)
3289{
3290 struct peer *peer;
3291 struct listnode *node, *nnode;
3292
3293 if (!hostname)
3294 return NULL;
3295
3296 if (bgp != NULL)
3297 {
3298 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
3299 if (peer->hostname && !strcmp(peer->hostname, hostname)
3300 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
3301 return peer;
3302 }
3303 else if (bm->bgp != NULL)
3304 {
3305 struct listnode *bgpnode, *nbgpnode;
3306
3307 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
3308 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
3309 if (peer->hostname && !strcmp(peer->hostname, hostname)
3310 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
3311 return peer;
3312 }
3313 return NULL;
3314}
3315
718e3744 3316struct peer *
3317peer_lookup (struct bgp *bgp, union sockunion *su)
3318{
dd793e4a
DW
3319 struct peer *peer = NULL;
3320 struct peer tmp_peer;
3321
3322 memset(&tmp_peer, 0, sizeof(struct peer));
3323
3324 /*
3325 * We do not want to find the doppelganger peer so search for the peer in
3326 * the hash that has PEER_FLAG_CONFIG_NODE
3327 */
3328 SET_FLAG (tmp_peer.flags, PEER_FLAG_CONFIG_NODE);
3329
3330 tmp_peer.su = *su;
718e3744 3331
fc4dc59d 3332 if (bgp != NULL)
fc4dc59d 3333 {
dd793e4a 3334 peer = hash_lookup(bgp->peerhash, &tmp_peer);
fc4dc59d 3335 }
fc4dc59d 3336 else if (bm->bgp != NULL)
718e3744 3337 {
2158ad23
PJ
3338 struct listnode *bgpnode, *nbgpnode;
3339
3340 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
dd793e4a 3341 {
ad4cbda1 3342 /* Skip VRFs, this function will not be invoked without an instance
3343 * when examining VRFs.
6aeb9e78 3344 */
ad4cbda1 3345 if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6aeb9e78
DS
3346 continue;
3347
dd793e4a
DW
3348 peer = hash_lookup(bgp->peerhash, &tmp_peer);
3349
3350 if (peer)
3351 break;
3352 }
fc4dc59d 3353 }
dd793e4a
DW
3354
3355 return peer;
718e3744 3356}
3357
f14e6fdb
DS
3358struct peer *
3359peer_create_bind_dynamic_neighbor (struct bgp *bgp, union sockunion *su,
3360 struct peer_group *group)
3361{
3362 struct peer *peer;
3363 afi_t afi;
3364 safi_t safi;
f14e6fdb
DS
3365
3366 /* Create peer first; we've already checked group config is valid. */
f813b13b 3367 peer = peer_create (su, NULL, bgp, bgp->as, group->conf->as, group->conf->as_type, 0, 0, group);
f14e6fdb
DS
3368 if (!peer)
3369 return NULL;
3370
3371 /* Link to group */
f14e6fdb
DS
3372 peer = peer_lock (peer);
3373 listnode_add (group->peer, peer);
3374
a4ed4829
DW
3375 peer_group2peer_config_copy(group, peer);
3376
f14e6fdb
DS
3377 /*
3378 * Bind peer for all AFs configured for the group. We don't call
3379 * peer_group_bind as that is sub-optimal and does some stuff we don't want.
3380 */
3381 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3382 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3383 {
3384 if (!group->conf->afc[afi][safi])
3385 continue;
f14e6fdb 3386 peer->afc[afi][safi] = 1;
c8560b44
DW
3387
3388 if (!peer_af_find(peer, afi, safi))
3389 peer_af_create(peer, afi, safi);
3390
a4ed4829 3391 peer_group2peer_config_copy_af (group, peer, afi, safi);
f14e6fdb
DS
3392 }
3393
3394 /* Mark as dynamic, but also as a "config node" for other things to work. */
3395 SET_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR);
3396 SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
3397
3398 return peer;
3399}
3400
3401struct prefix *
3402peer_group_lookup_dynamic_neighbor_range (struct peer_group * group,
3403 struct prefix * prefix)
3404{
3405 struct listnode *node, *nnode;
3406 struct prefix *range;
3407 afi_t afi;
3408
3409 afi = family2afi(prefix->family);
3410
3411 if (group->listen_range[afi])
3412 for (ALL_LIST_ELEMENTS (group->listen_range[afi], node, nnode, range))
3413 if (prefix_match(range, prefix))
3414 return range;
3415
3416 return NULL;
3417}
3418
3419struct peer_group *
3420peer_group_lookup_dynamic_neighbor (struct bgp *bgp, struct prefix *prefix,
3421 struct prefix **listen_range)
3422{
3423 struct prefix *range = NULL;
3424 struct peer_group *group = NULL;
3425 struct listnode *node, *nnode;
3426
3427 *listen_range = NULL;
3428 if (bgp != NULL)
3429 {
3430 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
3431 if ((range = peer_group_lookup_dynamic_neighbor_range(group, prefix)))
3432 break;
3433 }
3434 else if (bm->bgp != NULL)
3435 {
3436 struct listnode *bgpnode, *nbgpnode;
3437
3438 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
3439 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
3440 if ((range = peer_group_lookup_dynamic_neighbor_range(group, prefix)))
2aab8d2b 3441 goto found_range;
f14e6fdb
DS
3442 }
3443
2aab8d2b 3444 found_range:
f14e6fdb
DS
3445 *listen_range = range;
3446 return (group && range) ? group : NULL;
3447}
3448
3449struct peer *
3450peer_lookup_dynamic_neighbor (struct bgp *bgp, union sockunion *su)
3451{
3452 struct peer_group *group;
3453 struct bgp *gbgp;
3454 struct peer *peer;
40ee54a7 3455 struct prefix prefix;
f14e6fdb
DS
3456 struct prefix *listen_range;
3457 int dncount;
4690c7d7
DS
3458 char buf[PREFIX2STR_BUFFER];
3459 char buf1[PREFIX2STR_BUFFER];
f14e6fdb 3460
40ee54a7 3461 sockunion2hostprefix(su, &prefix);
f14e6fdb
DS
3462
3463 /* See if incoming connection matches a configured listen range. */
40ee54a7 3464 group = peer_group_lookup_dynamic_neighbor (bgp, &prefix, &listen_range);
f14e6fdb
DS
3465
3466 if (! group)
3467 return NULL;
3468
0299c004 3469
f14e6fdb
DS
3470 gbgp = group->bgp;
3471
3472 if (! gbgp)
3473 return NULL;
3474
40ee54a7 3475 prefix2str(&prefix, buf, sizeof(buf));
f14e6fdb
DS
3476 prefix2str(listen_range, buf1, sizeof(buf1));
3477
3478 if (bgp_debug_neighbor_events(NULL))
3479 zlog_debug ("Dynamic Neighbor %s matches group %s listen range %s",
3480 buf, group->name, buf1);
3481
3482 /* Are we within the listen limit? */
3483 dncount = gbgp->dynamic_neighbors_count;
3484
3485 if (dncount >= gbgp->dynamic_neighbors_limit)
3486 {
3487 if (bgp_debug_neighbor_events(NULL))
3488 zlog_debug ("Dynamic Neighbor %s rejected - at limit %d",
3489 inet_sutop (su, buf), gbgp->dynamic_neighbors_limit);
3490 return NULL;
3491 }
3492
3493 /* Ensure group is not disabled. */
3494 if (CHECK_FLAG (group->conf->flags, PEER_FLAG_SHUTDOWN))
3495 {
3496 if (bgp_debug_neighbor_events(NULL))
3497 zlog_debug ("Dynamic Neighbor %s rejected - group %s disabled",
3498 buf, group->name);
3499 return NULL;
3500 }
3501
3502 /* Check that at least one AF is activated for the group. */
3503 if (!peer_group_af_configured (group))
3504 {
3505 if (bgp_debug_neighbor_events(NULL))
3506 zlog_debug ("Dynamic Neighbor %s rejected - no AF activated for group %s",
3507 buf, group->name);
3508 return NULL;
3509 }
3510
3511 /* Create dynamic peer and bind to associated group. */
3512 peer = peer_create_bind_dynamic_neighbor (gbgp, su, group);
3513 assert (peer);
3514
3515 gbgp->dynamic_neighbors_count = ++dncount;
3516
3517 if (bgp_debug_neighbor_events(peer))
3518 zlog_debug ("%s Dynamic Neighbor added, group %s count %d",
3519 peer->host, group->name, dncount);
3520
3521 return peer;
3522}
3523
3524void peer_drop_dynamic_neighbor (struct peer *peer)
3525{
3526 int dncount = -1;
3527 if (peer->group && peer->group->bgp)
3528 {
3529 dncount = peer->group->bgp->dynamic_neighbors_count;
3530 if (dncount)
3531 peer->group->bgp->dynamic_neighbors_count = --dncount;
3532 }
3533 if (bgp_debug_neighbor_events(peer))
3534 zlog_debug ("%s dropped from group %s, count %d",
3535 peer->host, peer->group->name, dncount);
3536}
3537
3538
718e3744 3539/* If peer is configured at least one address family return 1. */
3540int
3541peer_active (struct peer *peer)
3542{
a80beece
DS
3543 if (BGP_PEER_SU_UNSPEC(peer))
3544 return 0;
718e3744 3545 if (peer->afc[AFI_IP][SAFI_UNICAST]
3546 || peer->afc[AFI_IP][SAFI_MULTICAST]
3547 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
587ff0fd 3548 || peer->afc[AFI_IP][SAFI_ENCAP]
718e3744 3549 || peer->afc[AFI_IP6][SAFI_UNICAST]
945c8fe9 3550 || peer->afc[AFI_IP6][SAFI_MULTICAST]
587ff0fd
LB
3551 || peer->afc[AFI_IP6][SAFI_MPLS_VPN]
3552 || peer->afc[AFI_IP6][SAFI_ENCAP])
718e3744 3553 return 1;
3554 return 0;
3555}
3556
3557/* If peer is negotiated at least one address family return 1. */
3558int
3559peer_active_nego (struct peer *peer)
3560{
3561 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
3562 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
3563 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
587ff0fd 3564 || peer->afc_nego[AFI_IP][SAFI_ENCAP]
718e3744 3565 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
945c8fe9 3566 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
587ff0fd
LB
3567 || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
3568 || peer->afc_nego[AFI_IP6][SAFI_ENCAP])
718e3744 3569 return 1;
3570 return 0;
3571}
6b0655a2 3572
718e3744 3573/* peer_flag_change_type. */
3574enum peer_change_type
3575{
3576 peer_change_none,
3577 peer_change_reset,
3578 peer_change_reset_in,
3579 peer_change_reset_out,
3580};
3581
94f2b392 3582static void
718e3744 3583peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
3584 enum peer_change_type type)
3585{
3586 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3587 return;
3588
d9d4ae51
SH
3589 if (peer->status != Established)
3590 return;
3591
718e3744 3592 if (type == peer_change_reset)
1ff9a340
DS
3593 {
3594 /* If we're resetting session, we've to delete both peer struct */
3595 if ((peer->doppelganger) && (peer->doppelganger->status != Deleted)
3596 && (!CHECK_FLAG(peer->doppelganger->flags,
3597 PEER_FLAG_CONFIG_NODE)))
3598 peer_delete(peer->doppelganger);
3599
3600 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3601 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3602 }
718e3744 3603 else if (type == peer_change_reset_in)
3604 {
3605 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
3606 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
3607 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
3608 else
1ff9a340
DS
3609 {
3610 if ((peer->doppelganger) && (peer->doppelganger->status != Deleted)
3611 && (!CHECK_FLAG(peer->doppelganger->flags,
3612 PEER_FLAG_CONFIG_NODE)))
3613 peer_delete(peer->doppelganger);
3614
3615 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3616 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3617 }
718e3744 3618 }
3619 else if (type == peer_change_reset_out)
3f9c7369
DS
3620 {
3621 update_group_adjust_peer(peer_af_find(peer, afi, safi));
3622 bgp_announce_route (peer, afi, safi);
3623 }
718e3744 3624}
3625
3626struct peer_flag_action
3627{
3628 /* Peer's flag. */
3629 u_int32_t flag;
3630
3631 /* This flag can be set for peer-group member. */
3632 u_char not_for_member;
3633
3634 /* Action when the flag is changed. */
3635 enum peer_change_type type;
e0701b79 3636
3637 /* Peer down cause */
3638 u_char peer_down;
718e3744 3639};
3640
03621955 3641static const struct peer_flag_action peer_flag_action_list[] =
718e3744 3642 {
3643 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
3644 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
3645 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
3646 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
3647 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
718e3744 3648 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
6ffd2079 3649 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
8a92a8a0 3650 { PEER_FLAG_CAPABILITY_ENHE, 0, peer_change_reset },
718e3744 3651 { 0, 0, 0 }
3652 };
3653
03621955 3654static const struct peer_flag_action peer_af_flag_action_list[] =
718e3744 3655 {
718e3744 3656 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
3657 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
adbac85e 3658 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
718e3744 3659 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
3660 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
adbac85e 3661 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
718e3744 3662 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
3663 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
3664 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
adbac85e 3665 // PEER_FLAG_DEFAULT_ORIGINATE
718e3744 3666 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
3667 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
3668 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
3669 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
adbac85e
DW
3670 // PEER_FLAG_MAX_PREFIX
3671 // PEER_FLAG_MAX_PREFIX_WARNING
fee0f4c6 3672 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
a538debe 3673 { PEER_FLAG_FORCE_NEXTHOP_SELF, 1, peer_change_reset_out },
adbac85e
DW
3674 { PEER_FLAG_REMOVE_PRIVATE_AS_ALL, 1, peer_change_reset_out },
3675 { PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE,1, peer_change_reset_out },
c7122e14 3676 { PEER_FLAG_AS_OVERRIDE, 1, peer_change_reset_out },
88b8ed8d 3677 { PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE,1, peer_change_reset_out },
adbac85e 3678 { PEER_FLAG_ADDPATH_TX_ALL_PATHS, 1, peer_change_reset },
06370dac 3679 { PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS, 1, peer_change_reset },
d93f7ffc 3680 { PEER_FLAG_WEIGHT, 0, peer_change_reset_in },
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
d93f7ffc
DW
4516/*
4517 * Helper function that is called after the name of the policy
4518 * being used by a peer has changed (AF specific). Automatically
4519 * initiates inbound or outbound processing as needed.
4520 */
4521static void
4522peer_on_policy_change (struct peer *peer, afi_t afi, safi_t safi, int outbound)
4523{
4524 if (outbound)
4525 {
4526 update_group_adjust_peer (peer_af_find (peer, afi, safi));
4527 if (peer->status == Established)
4528 bgp_announce_route(peer, afi, safi);
4529 }
4530 else
4531 {
4532 if (peer->status != Established)
4533 return;
4534
4535 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4536 bgp_soft_reconfig_in (peer, afi, safi);
4537 else if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4538 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4539 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4540 }
4541}
4542
4543
718e3744 4544/* neighbor weight. */
1f9a9fff 4545int
d93f7ffc 4546peer_weight_set (struct peer *peer, afi_t afi, safi_t safi, u_int16_t weight)
718e3744 4547{
4548 struct peer_group *group;
1eb8ef25 4549 struct listnode *node, *nnode;
718e3744 4550
d93f7ffc
DW
4551 if (peer->weight[afi][safi] != weight)
4552 {
4553 peer->weight[afi][safi] = weight;
4554 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_WEIGHT);
4555 peer_on_policy_change (peer, afi, safi, 0);
4556 }
718e3744 4557
4558 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1f9a9fff 4559 return 0;
718e3744 4560
4561 /* peer-group member updates. */
4562 group = peer->group;
1eb8ef25 4563 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4564 {
d93f7ffc
DW
4565 if (peer->weight[afi][safi] != weight)
4566 {
4567 peer->weight[afi][safi] = weight;
4568 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_WEIGHT);
4569 peer_on_policy_change (peer, afi, safi, 0);
4570 }
718e3744 4571 }
d93f7ffc 4572 return 0;
718e3744 4573}
4574
1f9a9fff 4575int
d93f7ffc 4576peer_weight_unset (struct peer *peer, afi_t afi, safi_t safi)
718e3744 4577{
4578 struct peer_group *group;
1eb8ef25 4579 struct listnode *node, *nnode;
718e3744 4580
d93f7ffc
DW
4581 /* not the peer-group itself but a peer in a peer-group */
4582 if (peer_group_active(peer))
4583 {
4584 group = peer->group;
718e3744 4585
d93f7ffc
DW
4586 /* inherit weight from the peer-group */
4587 if (CHECK_FLAG (group->conf->af_flags[afi][safi], PEER_FLAG_WEIGHT))
4588 {
4589 peer->weight[afi][safi] = group->conf->weight[afi][safi];
4590 peer_af_flag_set (peer, afi, safi, PEER_FLAG_WEIGHT);
4591 peer_on_policy_change (peer, afi, safi, 0);
4592 }
4593 else
4594 {
4595 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_WEIGHT))
4596 {
4597 peer->weight[afi][safi] = 0;
4598 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_WEIGHT);
4599 peer_on_policy_change (peer, afi, safi, 0);
4600 }
4601 }
4602 }
718e3744 4603
d93f7ffc 4604 else
718e3744 4605 {
d93f7ffc
DW
4606 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_WEIGHT))
4607 {
4608 peer->weight[afi][safi] = 0;
4609 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_WEIGHT);
4610 peer_on_policy_change (peer, afi, safi, 0);
4611 }
4612
4613 /* peer-group member updates. */
4614 group = peer->group;
4615
4616 if (group)
4617 {
4618 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4619 {
4620 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_WEIGHT))
4621 {
4622 peer->weight[afi][safi] = 0;
4623 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_WEIGHT);
4624 peer_on_policy_change (peer, afi, safi, 0);
4625 }
4626 }
4627 }
718e3744 4628 }
d93f7ffc 4629 return 0;
718e3744 4630}
6b0655a2 4631
718e3744 4632int
4633peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
4634{
4635 struct peer_group *group;
1eb8ef25 4636 struct listnode *node, *nnode;
718e3744 4637
718e3744 4638 /* keepalive value check. */
4639 if (keepalive > 65535)
4640 return BGP_ERR_INVALID_VALUE;
4641
4642 /* Holdtime value check. */
4643 if (holdtime > 65535)
4644 return BGP_ERR_INVALID_VALUE;
4645
4646 /* Holdtime value must be either 0 or greater than 3. */
4647 if (holdtime < 3 && holdtime != 0)
4648 return BGP_ERR_INVALID_VALUE;
4649
4650 /* Set value to the configuration. */
4651 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
4652 peer->holdtime = holdtime;
4653 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
4654
4655 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4656 return 0;
4657
4658 /* peer-group member updates. */
4659 group = peer->group;
1eb8ef25 4660 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4661 {
4662 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
4663 peer->holdtime = group->conf->holdtime;
4664 peer->keepalive = group->conf->keepalive;
4665 }
4666 return 0;
4667}
4668
4669int
4670peer_timers_unset (struct peer *peer)
4671{
4672 struct peer_group *group;
1eb8ef25 4673 struct listnode *node, *nnode;
718e3744 4674
718e3744 4675 /* Clear configuration. */
4676 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
4677 peer->keepalive = 0;
4678 peer->holdtime = 0;
4679
4680 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4681 return 0;
4682
4683 /* peer-group member updates. */
4684 group = peer->group;
1eb8ef25 4685 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4686 {
4687 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
4688 peer->holdtime = 0;
4689 peer->keepalive = 0;
4690 }
4691
4692 return 0;
4693}
6b0655a2 4694
718e3744 4695int
4696peer_timers_connect_set (struct peer *peer, u_int32_t connect)
4697{
966f821c
DS
4698 struct peer_group *group;
4699 struct listnode *node, *nnode;
4700
718e3744 4701 if (connect > 65535)
4702 return BGP_ERR_INVALID_VALUE;
4703
4704 /* Set value to the configuration. */
4705 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
4706 peer->connect = connect;
4707
4708 /* Set value to timer setting. */
4709 peer->v_connect = connect;
4710
966f821c
DS
4711 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4712 return 0;
4713
4714 /* peer-group member updates. */
4715 group = peer->group;
4716 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4717 {
4718 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
4719 peer->connect = connect;
4720 peer->v_connect = connect;
4721 }
718e3744 4722 return 0;
4723}
4724
4725int
4726peer_timers_connect_unset (struct peer *peer)
4727{
966f821c
DS
4728 struct peer_group *group;
4729 struct listnode *node, *nnode;
4730
718e3744 4731 /* Clear configuration. */
4732 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
4733 peer->connect = 0;
4734
4735 /* Set timer setting to default value. */
4736 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
4737
966f821c
DS
4738 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4739 return 0;
4740
4741 /* peer-group member updates. */
4742 group = peer->group;
4743 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4744 {
4745 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
4746 peer->connect = 0;
4747 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
4748 }
718e3744 4749 return 0;
4750}
6b0655a2 4751
718e3744 4752int
4753peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
4754{
966f821c
DS
4755 struct peer_group *group;
4756 struct listnode *node, *nnode;
4757
718e3744 4758 if (routeadv > 600)
4759 return BGP_ERR_INVALID_VALUE;
4760
4761 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
4762 peer->routeadv = routeadv;
4763 peer->v_routeadv = routeadv;
4764
3f9c7369
DS
4765 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) {
4766 update_group_adjust_peer_afs (peer);
4767 if (peer->status == Established)
4768 bgp_announce_route_all (peer);
966f821c 4769 return 0;
3f9c7369 4770 }
966f821c
DS
4771
4772 /* peer-group member updates. */
4773 group = peer->group;
4774 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4775 {
4776 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
4777 peer->routeadv = routeadv;
4778 peer->v_routeadv = routeadv;
3f9c7369
DS
4779 update_group_adjust_peer_afs (peer);
4780 if (peer->status == Established)
4781 bgp_announce_route_all (peer);
966f821c
DS
4782 }
4783
718e3744 4784 return 0;
4785}
4786
4787int
4788peer_advertise_interval_unset (struct peer *peer)
4789{
966f821c
DS
4790 struct peer_group *group;
4791 struct listnode *node, *nnode;
4792
718e3744 4793 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
4794 peer->routeadv = 0;
4795
6d85b15b 4796 if (peer->sort == BGP_PEER_IBGP)
718e3744 4797 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
4798 else
4799 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
966f821c 4800
3f9c7369
DS
4801 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) {
4802 update_group_adjust_peer_afs (peer);
4803 if (peer->status == Established)
4804 bgp_announce_route_all (peer);
966f821c 4805 return 0;
3f9c7369 4806 }
966f821c
DS
4807
4808 /* peer-group member updates. */
4809 group = peer->group;
4810 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4811 {
4812 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
4813 peer->routeadv = 0;
4814
4815 if (peer->sort == BGP_PEER_IBGP)
4816 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
4817 else
4818 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3f9c7369
DS
4819
4820 update_group_adjust_peer_afs (peer);
4821 if (peer->status == Established)
4822 bgp_announce_route_all (peer);
966f821c 4823 }
718e3744 4824
4825 return 0;
4826}
6b0655a2 4827
718e3744 4828/* neighbor interface */
ffd0c037 4829void
fd79ac91 4830peer_interface_set (struct peer *peer, const char *str)
718e3744 4831{
4832 if (peer->ifname)
6e919709
DS
4833 XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
4834 peer->ifname = XSTRDUP(MTYPE_BGP_PEER_IFNAME, str);
718e3744 4835}
4836
ffd0c037 4837void
718e3744 4838peer_interface_unset (struct peer *peer)
4839{
4840 if (peer->ifname)
6e919709 4841 XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
718e3744 4842 peer->ifname = NULL;
718e3744 4843}
6b0655a2 4844
718e3744 4845/* Allow-as in. */
4846int
4847peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
4848{
4849 struct peer_group *group;
1eb8ef25 4850 struct listnode *node, *nnode;
718e3744 4851
4852 if (allow_num < 1 || allow_num > 10)
4853 return BGP_ERR_INVALID_VALUE;
4854
4855 if (peer->allowas_in[afi][safi] != allow_num)
4856 {
4857 peer->allowas_in[afi][safi] = allow_num;
4858 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
d93f7ffc 4859 peer_on_policy_change (peer, afi, safi, 0);
718e3744 4860 }
4861
4862 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4863 return 0;
4864
4865 group = peer->group;
1eb8ef25 4866 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4867 {
4868 if (peer->allowas_in[afi][safi] != allow_num)
4869 {
4870 peer->allowas_in[afi][safi] = allow_num;
4871 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
d93f7ffc 4872 peer_on_policy_change (peer, afi, safi, 0);
718e3744 4873 }
4874
4875 }
4876 return 0;
4877}
4878
4879int
4880peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
4881{
4882 struct peer_group *group;
1eb8ef25 4883 struct listnode *node, *nnode;
718e3744 4884
4885 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
4886 {
4887 peer->allowas_in[afi][safi] = 0;
4888 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
d93f7ffc 4889 peer_on_policy_change (peer, afi, safi, 0);
718e3744 4890 }
4891
4892 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4893 return 0;
4894
4895 group = peer->group;
1eb8ef25 4896 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4897 {
4898 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
4899 {
4900 peer->allowas_in[afi][safi] = 0;
4901 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
d93f7ffc 4902 peer_on_policy_change (peer, afi, safi, 0);
718e3744 4903 }
4904 }
4905 return 0;
4906}
6b0655a2 4907
718e3744 4908int
9d3f9705 4909peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
718e3744 4910{
4911 struct bgp *bgp = peer->bgp;
4912 struct peer_group *group;
1eb8ef25 4913 struct listnode *node, *nnode;
718e3744 4914
4915 if (peer_sort (peer) != BGP_PEER_EBGP
4916 && peer_sort (peer) != BGP_PEER_INTERNAL)
4917 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
4918
4919 if (bgp->as == as)
4920 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
4921
9d3f9705
AC
4922 if (peer->as == as)
4923 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
4924
718e3744 4925 if (peer->change_local_as == as &&
4926 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
9d3f9705
AC
4927 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
4928 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
4929 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
718e3744 4930 return 0;
4931
4932 peer->change_local_as = as;
4933 if (no_prepend)
4934 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4935 else
4936 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4937
9d3f9705
AC
4938 if (replace_as)
4939 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4940 else
4941 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4942
718e3744 4943 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4944 {
6aa136f1 4945 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4946 {
4947 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
4948 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4949 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4950 }
718e3744 4951 else
1ff9a340 4952 bgp_session_reset(peer);
718e3744 4953 return 0;
4954 }
4955
4956 group = peer->group;
1eb8ef25 4957 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4958 {
4959 peer->change_local_as = as;
4960 if (no_prepend)
4961 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4962 else
4963 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4964
9d3f9705
AC
4965 if (replace_as)
4966 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4967 else
4968 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4969
6aa136f1 4970 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4971 {
4972 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
4973 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4974 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4975 }
718e3744 4976 else
4977 BGP_EVENT_ADD (peer, BGP_Stop);
4978 }
4979
4980 return 0;
4981}
4982
4983int
4984peer_local_as_unset (struct peer *peer)
4985{
4986 struct peer_group *group;
1eb8ef25 4987 struct listnode *node, *nnode;
718e3744 4988
718e3744 4989 if (! peer->change_local_as)
4990 return 0;
4991
4992 peer->change_local_as = 0;
4993 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
9d3f9705 4994 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
718e3744 4995
4996 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4997 {
6aa136f1 4998 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4999 {
5000 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
5001 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5002 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5003 }
718e3744 5004 else
5005 BGP_EVENT_ADD (peer, BGP_Stop);
5006
5007 return 0;
5008 }
5009
5010 group = peer->group;
1eb8ef25 5011 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5012 {
5013 peer->change_local_as = 0;
5014 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
9d3f9705 5015 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
718e3744 5016
6aa136f1 5017 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 5018 {
5019 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
5020 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5021 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5022 }
718e3744 5023 else
1ff9a340 5024 bgp_session_reset(peer);
718e3744 5025 }
5026 return 0;
5027}
6b0655a2 5028
0df7c91f
PJ
5029/* Set password for authenticating with the peer. */
5030int
5031peer_password_set (struct peer *peer, const char *password)
5032{
5033 struct listnode *nn, *nnode;
5034 int len = password ? strlen(password) : 0;
5035 int ret = BGP_SUCCESS;
5036
5037 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
5038 return BGP_ERR_INVALID_VALUE;
5039
5040 if (peer->password && strcmp (peer->password, password) == 0
5041 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5042 return 0;
5043
5044 if (peer->password)
5045 XFREE (MTYPE_PEER_PASSWORD, peer->password);
5046
5047 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
5048
5049 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5050 {
6aa136f1
VS
5051 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
5052 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
0df7c91f 5053 else
1ff9a340 5054 bgp_session_reset(peer);
0df7c91f 5055
89ca90fa 5056 if (BGP_PEER_SU_UNSPEC(peer))
5057 return BGP_SUCCESS;
5058
0df7c91f
PJ
5059 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
5060 }
5061
5062 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
5063 {
5064 if (peer->password && strcmp (peer->password, password) == 0)
5065 continue;
5066
5067 if (peer->password)
5068 XFREE (MTYPE_PEER_PASSWORD, peer->password);
5069
5070 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
5071
6aa136f1 5072 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
0df7c91f
PJ
5073 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5074 else
1ff9a340 5075 bgp_session_reset(peer);
0df7c91f 5076
89ca90fa 5077 if (! BGP_PEER_SU_UNSPEC(peer))
5078 {
5079 if (bgp_md5_set (peer) < 0)
5080 ret = BGP_ERR_TCPSIG_FAILED;
5081 }
0df7c91f
PJ
5082 }
5083
5084 return ret;
5085}
5086
5087int
5088peer_password_unset (struct peer *peer)
5089{
5090 struct listnode *nn, *nnode;
5091
5092 if (!peer->password
5093 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5094 return 0;
5095
5096 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5097 {
6aa136f1 5098 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
0df7c91f
PJ
5099 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5100 else
1ff9a340 5101 bgp_session_reset(peer);
0df7c91f
PJ
5102
5103 if (peer->password)
5104 XFREE (MTYPE_PEER_PASSWORD, peer->password);
5105
5106 peer->password = NULL;
5107
89ca90fa 5108 if (! BGP_PEER_SU_UNSPEC(peer))
5109 bgp_md5_unset (peer);
0df7c91f
PJ
5110
5111 return 0;
5112 }
5113
5114 XFREE (MTYPE_PEER_PASSWORD, peer->password);
5115 peer->password = NULL;
5116
5117 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
5118 {
5119 if (!peer->password)
5120 continue;
5121
6aa136f1 5122 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
0df7c91f
PJ
5123 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5124 else
1ff9a340 5125 bgp_session_reset(peer);
0df7c91f
PJ
5126
5127 XFREE (MTYPE_PEER_PASSWORD, peer->password);
5128 peer->password = NULL;
5129
89ca90fa 5130 if (! BGP_PEER_SU_UNSPEC(peer))
5131 bgp_md5_unset (peer);
0df7c91f
PJ
5132 }
5133
5134 return 0;
5135}
6b0655a2 5136
3f9c7369 5137
718e3744 5138/* Set distribute list to the peer. */
5139int
5140peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
fd79ac91 5141 const char *name)
718e3744 5142{
5143 struct bgp_filter *filter;
5144 struct peer_group *group;
1eb8ef25 5145 struct listnode *node, *nnode;
718e3744 5146
718e3744 5147 if (direct != FILTER_IN && direct != FILTER_OUT)
5148 return BGP_ERR_INVALID_VALUE;
5149
718e3744 5150 filter = &peer->filter[afi][safi];
5151
5152 if (filter->plist[direct].name)
5153 return BGP_ERR_PEER_FILTER_CONFLICT;
5154
5155 if (filter->dlist[direct].name)
6e919709
DS
5156 XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name);
5157 filter->dlist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5158 filter->dlist[direct].alist = access_list_lookup (afi, name);
5159
5160 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 5161 {
94f34286
DS
5162 peer_on_policy_change(peer, afi, safi,
5163 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
5164 return 0;
5165 }
718e3744 5166
5167 group = peer->group;
1eb8ef25 5168 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5169 {
5170 filter = &peer->filter[afi][safi];
5171
718e3744 5172 if (filter->dlist[direct].name)
6e919709
DS
5173 XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name);
5174 filter->dlist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5175 filter->dlist[direct].alist = access_list_lookup (afi, name);
94f34286
DS
5176 peer_on_policy_change(peer, afi, safi,
5177 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5178 }
5179
5180 return 0;
5181}
5182
5183int
5184peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
5185{
5186 struct bgp_filter *filter;
5187 struct bgp_filter *gfilter;
5188 struct peer_group *group;
1eb8ef25 5189 struct listnode *node, *nnode;
718e3744 5190
718e3744 5191 if (direct != FILTER_IN && direct != FILTER_OUT)
5192 return BGP_ERR_INVALID_VALUE;
5193
718e3744 5194 filter = &peer->filter[afi][safi];
5195
5196 /* apply peer-group filter */
c8560b44 5197 if (peer_group_active(peer))
718e3744 5198 {
5199 gfilter = &peer->group->conf->filter[afi][safi];
5200
5201 if (gfilter->dlist[direct].name)
5202 {
5203 if (filter->dlist[direct].name)
6e919709
DS
5204 XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name);
5205 filter->dlist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->dlist[direct].name);
718e3744 5206 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
94f34286
DS
5207 peer_on_policy_change(peer, afi, safi,
5208 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5209 return 0;
5210 }
5211 }
5212
5213 if (filter->dlist[direct].name)
6e919709 5214 XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name);
718e3744 5215 filter->dlist[direct].name = NULL;
5216 filter->dlist[direct].alist = NULL;
5217
5218 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 5219 {
94f34286
DS
5220 peer_on_policy_change(peer, afi, safi,
5221 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
5222 return 0;
5223 }
718e3744 5224
94f34286
DS
5225 group = peer->group;
5226 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
5227 {
5228 filter = &peer->filter[afi][safi];
718e3744 5229
94f34286 5230 if (filter->dlist[direct].name)
6e919709 5231 XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name);
94f34286
DS
5232 filter->dlist[direct].name = NULL;
5233 filter->dlist[direct].alist = NULL;
5234 peer_on_policy_change(peer, afi, safi,
5235 (direct == FILTER_OUT) ? 1 : 0);
5236 }
718e3744 5237
5238 return 0;
5239}
5240
5241/* Update distribute list. */
94f2b392 5242static void
718e3744 5243peer_distribute_update (struct access_list *access)
5244{
5245 afi_t afi;
5246 safi_t safi;
5247 int direct;
1eb8ef25 5248 struct listnode *mnode, *mnnode;
5249 struct listnode *node, *nnode;
718e3744 5250 struct bgp *bgp;
5251 struct peer *peer;
5252 struct peer_group *group;
5253 struct bgp_filter *filter;
5254
1eb8ef25 5255 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
718e3744 5256 {
3f9c7369
DS
5257 if (access->name)
5258 update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST, access->name,
5259 0, 0);
1eb8ef25 5260 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 5261 {
5262 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5263 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
5264 {
5265 filter = &peer->filter[afi][safi];
5266
5267 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
5268 {
5269 if (filter->dlist[direct].name)
5270 filter->dlist[direct].alist =
5271 access_list_lookup (afi, filter->dlist[direct].name);
5272 else
5273 filter->dlist[direct].alist = NULL;
5274 }
5275 }
5276 }
1eb8ef25 5277 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 5278 {
5279 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5280 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
5281 {
5282 filter = &group->conf->filter[afi][safi];
5283
5284 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
5285 {
5286 if (filter->dlist[direct].name)
5287 filter->dlist[direct].alist =
5288 access_list_lookup (afi, filter->dlist[direct].name);
5289 else
5290 filter->dlist[direct].alist = NULL;
5291 }
5292 }
5293 }
65efcfce
LB
5294#if ENABLE_BGP_VNC
5295 vnc_prefix_list_update(bgp);
5296#endif
718e3744 5297 }
5298}
6b0655a2 5299
718e3744 5300/* Set prefix list to the peer. */
5301int
5302peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
fd79ac91 5303 const char *name)
718e3744 5304{
5305 struct bgp_filter *filter;
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 if (filter->dlist[direct].name)
5315 return BGP_ERR_PEER_FILTER_CONFLICT;
5316
5317 if (filter->plist[direct].name)
6e919709
DS
5318 XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name);
5319 filter->plist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5320 filter->plist[direct].plist = prefix_list_lookup (afi, name);
5321
5322 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 5323 {
94f34286
DS
5324 peer_on_policy_change(peer, afi, safi,
5325 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
5326 return 0;
5327 }
718e3744 5328
5329 group = peer->group;
1eb8ef25 5330 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5331 {
5332 filter = &peer->filter[afi][safi];
5333
718e3744 5334 if (filter->plist[direct].name)
6e919709
DS
5335 XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name);
5336 filter->plist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5337 filter->plist[direct].plist = prefix_list_lookup (afi, name);
94f34286
DS
5338 peer_on_policy_change(peer, afi, safi,
5339 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5340 }
5341 return 0;
5342}
5343
5344int
5345peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
5346{
5347 struct bgp_filter *filter;
5348 struct bgp_filter *gfilter;
5349 struct peer_group *group;
1eb8ef25 5350 struct listnode *node, *nnode;
718e3744 5351
718e3744 5352 if (direct != FILTER_IN && direct != FILTER_OUT)
5353 return BGP_ERR_INVALID_VALUE;
5354
718e3744 5355 filter = &peer->filter[afi][safi];
5356
5357 /* apply peer-group filter */
c8560b44 5358 if (peer_group_active(peer))
718e3744 5359 {
5360 gfilter = &peer->group->conf->filter[afi][safi];
5361
5362 if (gfilter->plist[direct].name)
5363 {
5364 if (filter->plist[direct].name)
6e919709
DS
5365 XSTRDUP(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name);
5366 filter->plist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->plist[direct].name);
718e3744 5367 filter->plist[direct].plist = gfilter->plist[direct].plist;
94f34286
DS
5368 peer_on_policy_change(peer, afi, safi,
5369 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5370 return 0;
5371 }
5372 }
5373
5374 if (filter->plist[direct].name)
6e919709 5375 XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name);
718e3744 5376 filter->plist[direct].name = NULL;
5377 filter->plist[direct].plist = NULL;
5378
5379 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 5380 {
94f34286
DS
5381 peer_on_policy_change(peer, afi, safi,
5382 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
5383 return 0;
5384 }
718e3744 5385
5386 group = peer->group;
1eb8ef25 5387 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5388 {
5389 filter = &peer->filter[afi][safi];
5390
718e3744 5391 if (filter->plist[direct].name)
6e919709 5392 XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name);
718e3744 5393 filter->plist[direct].name = NULL;
5394 filter->plist[direct].plist = NULL;
94f34286
DS
5395 peer_on_policy_change(peer, afi, safi,
5396 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5397 }
5398
5399 return 0;
5400}
5401
5402/* Update prefix-list list. */
94f2b392 5403static void
718e3744 5404peer_prefix_list_update (struct prefix_list *plist)
5405{
1eb8ef25 5406 struct listnode *mnode, *mnnode;
5407 struct listnode *node, *nnode;
718e3744 5408 struct bgp *bgp;
5409 struct peer *peer;
5410 struct peer_group *group;
5411 struct bgp_filter *filter;
5412 afi_t afi;
5413 safi_t safi;
5414 int direct;
5415
1eb8ef25 5416 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
718e3744 5417 {
3f9c7369
DS
5418
5419 /*
5420 * Update the prefix-list on update groups.
5421 */
5422 update_group_policy_update(bgp, BGP_POLICY_PREFIX_LIST,
a38401b6 5423 plist ? prefix_list_name(plist) : NULL, 0, 0);
3f9c7369 5424
1eb8ef25 5425 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 5426 {
5427 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5428 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
5429 {
5430 filter = &peer->filter[afi][safi];
5431
5432 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
5433 {
5434 if (filter->plist[direct].name)
5435 filter->plist[direct].plist =
5436 prefix_list_lookup (afi, filter->plist[direct].name);
5437 else
5438 filter->plist[direct].plist = NULL;
5439 }
5440 }
5441 }
1eb8ef25 5442 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 5443 {
5444 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5445 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
5446 {
5447 filter = &group->conf->filter[afi][safi];
5448
5449 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
5450 {
5451 if (filter->plist[direct].name)
5452 filter->plist[direct].plist =
5453 prefix_list_lookup (afi, filter->plist[direct].name);
5454 else
5455 filter->plist[direct].plist = NULL;
5456 }
5457 }
5458 }
5459 }
5460}
6b0655a2 5461
718e3744 5462int
5463peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
fd79ac91 5464 const char *name)
718e3744 5465{
5466 struct bgp_filter *filter;
5467 struct peer_group *group;
1eb8ef25 5468 struct listnode *node, *nnode;
718e3744 5469
718e3744 5470 if (direct != FILTER_IN && direct != FILTER_OUT)
5471 return BGP_ERR_INVALID_VALUE;
5472
718e3744 5473 filter = &peer->filter[afi][safi];
5474
5475 if (filter->aslist[direct].name)
6e919709
DS
5476 XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name);
5477 filter->aslist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5478 filter->aslist[direct].aslist = as_list_lookup (name);
5479
5480 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 5481 {
94f34286
DS
5482 peer_on_policy_change(peer, afi, safi,
5483 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
5484 return 0;
5485 }
718e3744 5486
5487 group = peer->group;
1eb8ef25 5488 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5489 {
5490 filter = &peer->filter[afi][safi];
5491
718e3744 5492 if (filter->aslist[direct].name)
6e919709
DS
5493 XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name);
5494 filter->aslist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5495 filter->aslist[direct].aslist = as_list_lookup (name);
94f34286
DS
5496 peer_on_policy_change(peer, afi, safi,
5497 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5498 }
5499 return 0;
5500}
5501
5502int
5503peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
5504{
5505 struct bgp_filter *filter;
5506 struct bgp_filter *gfilter;
5507 struct peer_group *group;
1eb8ef25 5508 struct listnode *node, *nnode;
718e3744 5509
b5f29603 5510 if (direct != FILTER_IN && direct != FILTER_OUT)
718e3744 5511 return BGP_ERR_INVALID_VALUE;
5512
718e3744 5513 filter = &peer->filter[afi][safi];
5514
5515 /* apply peer-group filter */
c8560b44 5516 if (peer_group_active(peer))
718e3744 5517 {
5518 gfilter = &peer->group->conf->filter[afi][safi];
5519
5520 if (gfilter->aslist[direct].name)
5521 {
5522 if (filter->aslist[direct].name)
6e919709
DS
5523 XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name);
5524 filter->aslist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->aslist[direct].name);
718e3744 5525 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
94f34286
DS
5526 peer_on_policy_change(peer, afi, safi,
5527 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5528 return 0;
5529 }
5530 }
5531
5532 if (filter->aslist[direct].name)
6e919709 5533 XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name);
718e3744 5534 filter->aslist[direct].name = NULL;
5535 filter->aslist[direct].aslist = NULL;
5536
5537 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 5538 {
94f34286
DS
5539 peer_on_policy_change(peer, afi, safi,
5540 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
5541 return 0;
5542 }
718e3744 5543
5544 group = peer->group;
1eb8ef25 5545 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5546 {
5547 filter = &peer->filter[afi][safi];
5548
718e3744 5549 if (filter->aslist[direct].name)
6e919709 5550 XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name);
718e3744 5551 filter->aslist[direct].name = NULL;
5552 filter->aslist[direct].aslist = NULL;
94f34286
DS
5553 peer_on_policy_change(peer, afi, safi,
5554 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5555 }
5556
5557 return 0;
5558}
5559
94f2b392 5560static void
ffd0c037 5561peer_aslist_update (const char *aslist_name)
718e3744 5562{
5563 afi_t afi;
5564 safi_t safi;
5565 int direct;
1eb8ef25 5566 struct listnode *mnode, *mnnode;
5567 struct listnode *node, *nnode;
718e3744 5568 struct bgp *bgp;
5569 struct peer *peer;
5570 struct peer_group *group;
5571 struct bgp_filter *filter;
5572
1eb8ef25 5573 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
718e3744 5574 {
3f9c7369
DS
5575 update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST, aslist_name,
5576 0, 0);
5577
1eb8ef25 5578 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 5579 {
5580 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5581 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
5582 {
5583 filter = &peer->filter[afi][safi];
5584
5585 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
5586 {
5587 if (filter->aslist[direct].name)
5588 filter->aslist[direct].aslist =
5589 as_list_lookup (filter->aslist[direct].name);
5590 else
5591 filter->aslist[direct].aslist = NULL;
5592 }
5593 }
5594 }
1eb8ef25 5595 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 5596 {
5597 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5598 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
5599 {
5600 filter = &group->conf->filter[afi][safi];
5601
5602 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
5603 {
5604 if (filter->aslist[direct].name)
5605 filter->aslist[direct].aslist =
5606 as_list_lookup (filter->aslist[direct].name);
5607 else
5608 filter->aslist[direct].aslist = NULL;
5609 }
5610 }
5611 }
5612 }
5613}
3f9c7369 5614
518f0eb1
DS
5615static void
5616peer_aslist_add (char *aslist_name)
5617{
5618 peer_aslist_update (aslist_name);
5619 route_map_notify_dependencies((char *)aslist_name, RMAP_EVENT_ASLIST_ADDED);
5620}
5621
5622static void
ffd0c037 5623peer_aslist_del (const char *aslist_name)
518f0eb1
DS
5624{
5625 peer_aslist_update (aslist_name);
ffd0c037 5626 route_map_notify_dependencies(aslist_name, RMAP_EVENT_ASLIST_DELETED);
518f0eb1
DS
5627}
5628
6b0655a2 5629
718e3744 5630int
5631peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
fd79ac91 5632 const char *name)
718e3744 5633{
5634 struct bgp_filter *filter;
5635 struct peer_group *group;
1eb8ef25 5636 struct listnode *node, *nnode;
718e3744 5637
2a3d5731 5638 if (direct != RMAP_IN && direct != RMAP_OUT)
718e3744 5639 return BGP_ERR_INVALID_VALUE;
5640
718e3744 5641 filter = &peer->filter[afi][safi];
5642
5643 if (filter->map[direct].name)
6e919709 5644 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
518f0eb1 5645
6e919709 5646 filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5647 filter->map[direct].map = route_map_lookup_by_name (name);
5648
5649 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
518f0eb1 5650 {
94f34286
DS
5651 peer_on_policy_change(peer, afi, safi,
5652 (direct == RMAP_OUT) ? 1 : 0);
518f0eb1
DS
5653 return 0;
5654 }
718e3744 5655
5656 group = peer->group;
1eb8ef25 5657 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5658 {
5659 filter = &peer->filter[afi][safi];
5660
718e3744 5661 if (filter->map[direct].name)
6e919709
DS
5662 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
5663 filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5664 filter->map[direct].map = route_map_lookup_by_name (name);
94f34286
DS
5665 peer_on_policy_change(peer, afi, safi,
5666 (direct == RMAP_OUT) ? 1 : 0);
718e3744 5667 }
5668 return 0;
5669}
5670
5671/* Unset route-map from the peer. */
5672int
5673peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
5674{
5675 struct bgp_filter *filter;
5676 struct bgp_filter *gfilter;
5677 struct peer_group *group;
1eb8ef25 5678 struct listnode *node, *nnode;
718e3744 5679
2a3d5731 5680 if (direct != RMAP_IN && direct != RMAP_OUT)
718e3744 5681 return BGP_ERR_INVALID_VALUE;
5682
718e3744 5683 filter = &peer->filter[afi][safi];
5684
5685 /* apply peer-group filter */
c8560b44 5686 if (peer_group_active(peer))
718e3744 5687 {
5688 gfilter = &peer->group->conf->filter[afi][safi];
5689
5690 if (gfilter->map[direct].name)
5691 {
5692 if (filter->map[direct].name)
6e919709
DS
5693 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
5694 filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->map[direct].name);
718e3744 5695 filter->map[direct].map = gfilter->map[direct].map;
94f34286
DS
5696 peer_on_policy_change(peer, afi, safi,
5697 (direct == RMAP_OUT) ? 1 : 0);
718e3744 5698 return 0;
5699 }
5700 }
5701
5702 if (filter->map[direct].name)
6e919709 5703 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
718e3744 5704 filter->map[direct].name = NULL;
5705 filter->map[direct].map = NULL;
5706
5707 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
518f0eb1 5708 {
94f34286
DS
5709 peer_on_policy_change(peer, afi, safi,
5710 (direct == RMAP_OUT) ? 1 : 0);
518f0eb1
DS
5711 return 0;
5712 }
718e3744 5713
5714 group = peer->group;
1eb8ef25 5715 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5716 {
5717 filter = &peer->filter[afi][safi];
5718
718e3744 5719 if (filter->map[direct].name)
6e919709 5720 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
718e3744 5721 filter->map[direct].name = NULL;
5722 filter->map[direct].map = NULL;
94f34286
DS
5723 peer_on_policy_change(peer, afi, safi,
5724 (direct == RMAP_OUT) ? 1 : 0);
718e3744 5725 }
5726 return 0;
5727}
6b0655a2 5728
718e3744 5729/* Set unsuppress-map to the peer. */
5730int
fd79ac91 5731peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
5732 const char *name)
718e3744 5733{
5734 struct bgp_filter *filter;
5735 struct peer_group *group;
1eb8ef25 5736 struct listnode *node, *nnode;
718e3744 5737
718e3744 5738 filter = &peer->filter[afi][safi];
5739
5740 if (filter->usmap.name)
6e919709 5741 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
718e3744 5742
6e919709 5743 filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5744 filter->usmap.map = route_map_lookup_by_name (name);
5745
5746 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
518f0eb1 5747 {
94f34286 5748 peer_on_policy_change(peer, afi, safi, 1);
518f0eb1
DS
5749 return 0;
5750 }
718e3744 5751
5752 group = peer->group;
1eb8ef25 5753 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5754 {
5755 filter = &peer->filter[afi][safi];
5756
718e3744 5757 if (filter->usmap.name)
6e919709
DS
5758 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
5759 filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5760 filter->usmap.map = route_map_lookup_by_name (name);
94f34286 5761 peer_on_policy_change(peer, afi, safi, 1);
718e3744 5762 }
5763 return 0;
5764}
5765
5766/* Unset route-map from the peer. */
5767int
5768peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
5769{
5770 struct bgp_filter *filter;
5771 struct peer_group *group;
1eb8ef25 5772 struct listnode *node, *nnode;
718e3744 5773
718e3744 5774 filter = &peer->filter[afi][safi];
5775
5776 if (filter->usmap.name)
6e919709 5777 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
718e3744 5778 filter->usmap.name = NULL;
5779 filter->usmap.map = NULL;
5780
5781 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
518f0eb1 5782 {
94f34286 5783 peer_on_policy_change(peer, afi, safi, 1);
518f0eb1
DS
5784 return 0;
5785 }
718e3744 5786
5787 group = peer->group;
1eb8ef25 5788 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5789 {
5790 filter = &peer->filter[afi][safi];
5791
718e3744 5792 if (filter->usmap.name)
6e919709 5793 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
718e3744 5794 filter->usmap.name = NULL;
5795 filter->usmap.map = NULL;
94f34286 5796 peer_on_policy_change(peer, afi, safi, 1);
718e3744 5797 }
5798 return 0;
5799}
6b0655a2 5800
718e3744 5801int
5802peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
0a486e5f 5803 u_int32_t max, u_char threshold,
5804 int warning, u_int16_t restart)
718e3744 5805{
5806 struct peer_group *group;
1eb8ef25 5807 struct listnode *node, *nnode;
718e3744 5808
718e3744 5809 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5810 peer->pmax[afi][safi] = max;
e0701b79 5811 peer->pmax_threshold[afi][safi] = threshold;
0a486e5f 5812 peer->pmax_restart[afi][safi] = restart;
718e3744 5813 if (warning)
5814 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5815 else
5816 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5817
fc9a856f 5818 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
718e3744 5819 {
fc9a856f
DS
5820 group = peer->group;
5821 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
5822 {
fc9a856f
DS
5823 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5824 peer->pmax[afi][safi] = max;
5825 peer->pmax_threshold[afi][safi] = threshold;
5826 peer->pmax_restart[afi][safi] = restart;
5827 if (warning)
5828 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5829 else
5830 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5831
5832 if ((peer->status == Established) && (peer->afc[afi][safi]))
5833 bgp_maximum_prefix_overflow (peer, afi, safi, 1);
5834 }
5835 }
5836 else
5837 {
5838 if ((peer->status == Established) && (peer->afc[afi][safi]))
5839 bgp_maximum_prefix_overflow (peer, afi, safi, 1);
718e3744 5840 }
fc9a856f 5841
718e3744 5842 return 0;
5843}
5844
5845int
5846peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
5847{
5848 struct peer_group *group;
1eb8ef25 5849 struct listnode *node, *nnode;
718e3744 5850
718e3744 5851 /* apply peer-group config */
c8560b44 5852 if (peer_group_active(peer))
718e3744 5853 {
5854 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
5855 PEER_FLAG_MAX_PREFIX))
5856 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5857 else
5858 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5859
5860 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
5861 PEER_FLAG_MAX_PREFIX_WARNING))
5862 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5863 else
5864 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5865
5866 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
e0701b79 5867 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
0a486e5f 5868 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
718e3744 5869 return 0;
5870 }
5871
5872 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5873 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5874 peer->pmax[afi][safi] = 0;
0a486e5f 5875 peer->pmax_threshold[afi][safi] = 0;
5876 peer->pmax_restart[afi][safi] = 0;
718e3744 5877
5878 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5879 return 0;
5880
5881 group = peer->group;
1eb8ef25 5882 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5883 {
718e3744 5884 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5885 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5886 peer->pmax[afi][safi] = 0;
0a486e5f 5887 peer->pmax_threshold[afi][safi] = 0;
5888 peer->pmax_restart[afi][safi] = 0;
718e3744 5889 }
5890 return 0;
5891}
5f9adb5d 5892
c43ed2e4 5893int is_ebgp_multihop_configured (struct peer *peer)
5f9adb5d
DL
5894{
5895 struct peer_group *group;
5896 struct listnode *node, *nnode;
5897 struct peer *peer1;
5898
5899 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5900 {
5901 group = peer->group;
5d804b43
PM
5902 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
5903 (group->conf->ttl != 1))
5f9adb5d
DL
5904 return 1;
5905
5906 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
5907 {
5d804b43
PM
5908 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
5909 (peer1->ttl != 1))
5f9adb5d
DL
5910 return 1;
5911 }
5912 }
5913 else
5914 {
5d804b43
PM
5915 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
5916 (peer->ttl != 1))
5f9adb5d
DL
5917 return 1;
5918 }
5919 return 0;
5920}
5921
fa411a21
NH
5922/* Set # of hops between us and BGP peer. */
5923int
5924peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
5925{
5926 struct peer_group *group;
5927 struct listnode *node, *nnode;
fa411a21
NH
5928 int ret;
5929
5930 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
5931
fa411a21
NH
5932 /* We cannot configure ttl-security hops when ebgp-multihop is already
5933 set. For non peer-groups, the check is simple. For peer-groups, it's
5934 slightly messy, because we need to check both the peer-group structure
5935 and all peer-group members for any trace of ebgp-multihop configuration
5936 before actually applying the ttl-security rules. Cisco really made a
5937 mess of this configuration parameter, and OpenBGPD got it right.
5938 */
e5cc509c
DS
5939
5940 if ((peer->gtsm_hops == 0) && (peer->sort != BGP_PEER_IBGP))
5f9adb5d
DL
5941 {
5942 if (is_ebgp_multihop_configured (peer))
5943 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
fa411a21 5944
e5cc509c
DS
5945 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5946 {
5947 peer->gtsm_hops = gtsm_hops;
fa411a21 5948
e5cc509c
DS
5949 /* Calling ebgp multihop also resets the session.
5950 * On restart, NHT will get setup correctly as will the
5951 * min & max ttls on the socket. The return value is
5952 * irrelevant.
5953 */
5954 ret = peer_ebgp_multihop_set (peer, MAXTTL);
5955
5956 if (ret != 0)
5957 return ret;
5958 }
5959 else
5960 {
5961 group = peer->group;
5962 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
5963 {
5964 peer->gtsm_hops = group->conf->gtsm_hops;
5965
5966 /* Calling ebgp multihop also resets the session.
5967 * On restart, NHT will get setup correctly as will the
5968 * min & max ttls on the socket. The return value is
5969 * irrelevant.
5970 */
5971 ret = peer_ebgp_multihop_set (peer, MAXTTL);
5972 }
5973 }
fa411a21
NH
5974 }
5975 else
5976 {
e5cc509c
DS
5977 /* Post the first gtsm setup or if its ibgp, maxttl setting isn't
5978 * necessary, just set the minttl.
5979 */
5980 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
fa411a21 5981 {
e5cc509c 5982 peer->gtsm_hops = gtsm_hops;
fa411a21 5983
e5cc509c
DS
5984 if (peer->fd >= 0)
5985 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
5986 MAXTTL + 1 - gtsm_hops);
5987 if ((peer->status < Established) && peer->doppelganger &&
5988 (peer->doppelganger->fd >= 0))
5989 sockopt_minttl (peer->su.sa.sa_family, peer->doppelganger->fd,
5990 MAXTTL + 1 - gtsm_hops);
5991 }
5992 else
5993 {
5994 group = peer->group;
5995 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
f5a4827d 5996 {
e5cc509c
DS
5997 peer->gtsm_hops = group->conf->gtsm_hops;
5998
5999 /* Change setting of existing peer
6000 * established then change value (may break connectivity)
6001 * not established yet (teardown session and restart)
6002 * no session then do nothing (will get handled by next connection)
6003 */
f5a4827d
SH
6004 if (peer->fd >= 0 && peer->gtsm_hops != 0)
6005 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
6006 MAXTTL + 1 - peer->gtsm_hops);
e5cc509c
DS
6007 if ((peer->status < Established) && peer->doppelganger &&
6008 (peer->doppelganger->fd >= 0))
6009 sockopt_minttl (peer->su.sa.sa_family, peer->doppelganger->fd,
6010 MAXTTL + 1 - gtsm_hops);
6011
f5a4827d 6012 }
fa411a21
NH
6013 }
6014 }
6015
6016 return 0;
6017}
6018
6019int
6020peer_ttl_security_hops_unset (struct peer *peer)
6021{
6022 struct peer_group *group;
6023 struct listnode *node, *nnode;
e5cc509c 6024 int ret = 0;
fa411a21
NH
6025
6026 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
6027
fa411a21
NH
6028 /* if a peer-group member, then reset to peer-group default rather than 0 */
6029 if (peer_group_active (peer))
6030 peer->gtsm_hops = peer->group->conf->gtsm_hops;
6031 else
6032 peer->gtsm_hops = 0;
6033
fa411a21
NH
6034 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
6035 {
e5cc509c
DS
6036 /* Invoking ebgp_multihop_set will set the TTL back to the original
6037 * value as well as restting the NHT and such. The session is reset.
6038 */
6039 if (peer->sort == BGP_PEER_EBGP)
6040 ret = peer_ebgp_multihop_unset (peer);
6041 else
6042 {
6043 if (peer->fd >= 0)
6044 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
1ff9a340 6045
e5cc509c
DS
6046 if ((peer->status < Established) && peer->doppelganger &&
6047 (peer->doppelganger->fd >= 0))
6048 sockopt_minttl (peer->su.sa.sa_family,
6049 peer->doppelganger->fd, 0);
6050 }
fa411a21
NH
6051 }
6052 else
6053 {
6054 group = peer->group;
6055 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
6056 {
fa411a21 6057 peer->gtsm_hops = 0;
e5cc509c
DS
6058 if (peer->sort == BGP_PEER_EBGP)
6059 ret = peer_ebgp_multihop_unset (peer);
6060 else
6061 {
6062 if (peer->fd >= 0)
6063 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
1ff9a340 6064
e5cc509c
DS
6065 if ((peer->status < Established) && peer->doppelganger &&
6066 (peer->doppelganger->fd >= 0))
6067 sockopt_minttl (peer->su.sa.sa_family,
6068 peer->doppelganger->fd, 0);
6069 }
fa411a21
NH
6070 }
6071 }
6072
88177fe3 6073 return ret;
fa411a21 6074}
6b0655a2 6075
1ff9a340
DS
6076/*
6077 * If peer clear is invoked in a loop for all peers on the BGP instance,
6078 * it may end up freeing the doppelganger, and if this was the next node
6079 * to the current node, we would end up accessing the freed next node.
6080 * Pass along additional parameter which can be updated if next node
6081 * is freed; only required when walking the peer list on BGP instance.
6082 */
718e3744 6083int
1ff9a340 6084peer_clear (struct peer *peer, struct listnode **nnode)
718e3744 6085{
6086 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
6087 {
0a486e5f 6088 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
6089 {
6090 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
6091 if (peer->t_pmax_restart)
6092 {
6093 BGP_TIMER_OFF (peer->t_pmax_restart);
16286195 6094 if (bgp_debug_neighbor_events(peer))
0a486e5f 6095 zlog_debug ("%s Maximum-prefix restart timer canceled",
6096 peer->host);
6097 }
6098 BGP_EVENT_ADD (peer, BGP_Start);
6099 return 0;
6100 }
6101
718e3744 6102 peer->v_start = BGP_INIT_START_TIMER;
6aa136f1 6103 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
718e3744 6104 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
6105 BGP_NOTIFY_CEASE_ADMIN_RESET);
6106 else
1ff9a340 6107 bgp_session_reset_safe(peer, nnode);
718e3744 6108 }
6109 return 0;
6110}
6111
6112int
6113peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
6114 enum bgp_clear_type stype)
6115{
6a646146
DS
6116 struct peer_af *paf;
6117
718e3744 6118 if (peer->status != Established)
6119 return 0;
6120
6121 if (! peer->afc[afi][safi])
6122 return BGP_ERR_AF_UNCONFIGURED;
6123
e9a0c656
TT
6124 peer->rtt = sockopt_tcp_rtt (peer->fd);
6125
718e3744 6126 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
6a646146
DS
6127 {
6128 /* Clear the "neighbor x.x.x.x default-originate" flag */
6129 paf = peer_af_find (peer, afi, safi);
6130 if (paf && paf->subgroup &&
6131 CHECK_FLAG (paf->subgroup->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE))
6132 UNSET_FLAG (paf->subgroup->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE);
6133
6134 bgp_announce_route (peer, afi, safi);
6135 }
718e3744 6136
6137 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
6138 {
6139 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
6140 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
6141 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
6142 {
6143 struct bgp_filter *filter = &peer->filter[afi][safi];
6144 u_char prefix_type;
6145
6146 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
6147 prefix_type = ORF_TYPE_PREFIX;
6148 else
6149 prefix_type = ORF_TYPE_PREFIX_OLD;
6150
6151 if (filter->plist[FILTER_IN].plist)
6152 {
6153 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
6154 bgp_route_refresh_send (peer, afi, safi,
6155 prefix_type, REFRESH_DEFER, 1);
6156 bgp_route_refresh_send (peer, afi, safi, prefix_type,
6157 REFRESH_IMMEDIATE, 0);
6158 }
6159 else
6160 {
6161 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
6162 bgp_route_refresh_send (peer, afi, safi,
6163 prefix_type, REFRESH_IMMEDIATE, 1);
6164 else
6165 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
6166 }
6167 return 0;
6168 }
6169 }
6170
6171 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
6172 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
6173 {
6174 /* If neighbor has soft reconfiguration inbound flag.
6175 Use Adj-RIB-In database. */
6176 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
6177 bgp_soft_reconfig_in (peer, afi, safi);
6178 else
6179 {
6180 /* If neighbor has route refresh capability, send route refresh
6181 message to the peer. */
6182 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
6183 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
6184 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
6185 else
6186 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
6187 }
6188 }
6189 return 0;
6190}
6b0655a2 6191
fd79ac91 6192/* Display peer uptime.*/
6193/* XXX: why does this function return char * when it takes buffer? */
718e3744 6194char *
856ca177 6195peer_uptime (time_t uptime2, char *buf, size_t len, u_char use_json, json_object *json)
718e3744 6196{
6197 time_t uptime1;
6198 struct tm *tm;
6199
6200 /* Check buffer length. */
6201 if (len < BGP_UPTIME_LEN)
6202 {
856ca177
MS
6203 if (!use_json)
6204 {
6205 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
6206 /* XXX: should return status instead of buf... */
6207 snprintf (buf, len, "<error> ");
6208 }
fd79ac91 6209 return buf;
718e3744 6210 }
6211
6212 /* If there is no connection has been done before print `never'. */
6213 if (uptime2 == 0)
6214 {
856ca177
MS
6215 if (use_json)
6216 json_object_string_add(json, "peerUptime", "never");
6217 else
6218 snprintf (buf, len, "never");
718e3744 6219 return buf;
6220 }
6221
6222 /* Get current time. */
65957886 6223 uptime1 = bgp_clock ();
718e3744 6224 uptime1 -= uptime2;
6225 tm = gmtime (&uptime1);
6226
6227 /* Making formatted timer strings. */
6228#define ONE_DAY_SECOND 60*60*24
3a6229da
PJ
6229#define ONE_WEEK_SECOND ONE_DAY_SECOND*7
6230#define ONE_YEAR_SECOND ONE_DAY_SECOND*365
718e3744 6231
856ca177
MS
6232 if (use_json)
6233 {
1d889348 6234 unsigned long time_store;
1d889348 6235 unsigned long sec_msec = 1000;
3a6229da
PJ
6236 unsigned long minute_msec = sec_msec * 60;
6237 unsigned long hour_msec = minute_msec * 60;
6238 unsigned long day_msec = hour_msec * 24;
6239 unsigned long year_msec = day_msec *365;
1d889348
DS
6240
6241 time_store =
3a6229da 6242 year_msec * tm->tm_year +
1d889348
DS
6243 day_msec * tm->tm_yday +
6244 hour_msec * tm->tm_hour +
6245 minute_msec * tm->tm_min +
6246 sec_msec * tm->tm_sec;
6247 json_object_int_add(json, "peerUptimeMsec", time_store);
6248 }
6249
6250 if (uptime1 < ONE_DAY_SECOND)
6251 snprintf (buf, len, "%02d:%02d:%02d",
6252 tm->tm_hour, tm->tm_min, tm->tm_sec);
6253 else if (uptime1 < ONE_WEEK_SECOND)
6254 snprintf (buf, len, "%dd%02dh%02dm",
6255 tm->tm_yday, tm->tm_hour, tm->tm_min);
3a6229da 6256 else if (uptime1 < ONE_YEAR_SECOND)
1d889348
DS
6257 snprintf (buf, len, "%02dw%dd%02dh",
6258 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
3a6229da
PJ
6259 else
6260 snprintf (buf, len, "%02dy%02dw%dd",
6261 tm->tm_year - 70, tm->tm_yday/7,
6262 tm->tm_yday - ((tm->tm_yday/7) * 7));
1d889348 6263
718e3744 6264 return buf;
6265}
6b0655a2 6266
400b1fad
DW
6267static void
6268afi_header_vty_out (struct vty *vty, afi_t afi, safi_t safi,
6269 int *write, const char *format, ...)
6270{
6271 va_list args;
6272 int len = 0;
6273 char buf[1024];
6274
6275 bgp_config_write_family_header (vty, afi, safi, write);
6276
6277 if (vty_shell (vty))
6278 {
6279 va_start (args, format);
6280 vprintf (format, args);
6281 va_end (args);
6282 }
6283 else
6284 {
6285 va_start (args, format);
6286 len = vsnprintf (buf, sizeof(buf), format, args);
6287 va_end (args);
6288
6289 buffer_put (vty->obuf, (u_char *) buf, len);
6290 }
6291}
6292
94f2b392 6293static void
718e3744 6294bgp_config_write_filter (struct vty *vty, struct peer *peer,
400b1fad 6295 afi_t afi, safi_t safi, int *write)
718e3744 6296{
6297 struct bgp_filter *filter;
6298 struct bgp_filter *gfilter = NULL;
6299 char *addr;
6300 int in = FILTER_IN;
6301 int out = FILTER_OUT;
6302
6303 addr = peer->host;
6304 filter = &peer->filter[afi][safi];
c8560b44
DW
6305
6306 if (peer_group_active(peer))
718e3744 6307 gfilter = &peer->group->conf->filter[afi][safi];
6308
6309 /* distribute-list. */
6310 if (filter->dlist[in].name)
6311 if (! gfilter || ! gfilter->dlist[in].name
6312 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
400b1fad
DW
6313 {
6314 afi_header_vty_out (vty, afi, safi, write,
6315 " neighbor %s distribute-list %s in%s",
6316 addr, filter->dlist[in].name, VTY_NEWLINE);
6317 }
6318
718e3744 6319 if (filter->dlist[out].name && ! gfilter)
400b1fad
DW
6320 {
6321 afi_header_vty_out (vty, afi, safi, write,
6322 " neighbor %s distribute-list %s out%s",
6323 addr, filter->dlist[out].name, VTY_NEWLINE);
6324 }
718e3744 6325
6326 /* prefix-list. */
6327 if (filter->plist[in].name)
6328 if (! gfilter || ! gfilter->plist[in].name
6329 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
400b1fad
DW
6330 {
6331 afi_header_vty_out (vty, afi, safi, write,
6332 " neighbor %s prefix-list %s in%s",
6333 addr, filter->plist[in].name, VTY_NEWLINE);
6334 }
6335
718e3744 6336 if (filter->plist[out].name && ! gfilter)
400b1fad
DW
6337 {
6338 afi_header_vty_out (vty, afi, safi, write,
6339 " neighbor %s prefix-list %s out%s",
6340 addr, filter->plist[out].name, VTY_NEWLINE);
6341 }
718e3744 6342
6343 /* route-map. */
fee0f4c6 6344 if (filter->map[RMAP_IN].name)
6345 if (! gfilter || ! gfilter->map[RMAP_IN].name
6346 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
400b1fad
DW
6347 {
6348 afi_header_vty_out (vty, afi, safi, write,
6349 " neighbor %s route-map %s in%s",
6350 addr, filter->map[RMAP_IN].name, VTY_NEWLINE);
6351 }
6352
2bd5af06
DS
6353 if (filter->map[RMAP_OUT].name)
6354 if (! gfilter || ! gfilter->map[RMAP_OUT].name
6355 || strcmp (filter->map[RMAP_OUT].name, gfilter->map[RMAP_OUT].name) != 0)
400b1fad
DW
6356 {
6357 afi_header_vty_out (vty, afi, safi, write,
6358 " neighbor %s route-map %s out%s",
6359 addr, filter->map[RMAP_OUT].name, VTY_NEWLINE);
6360 }
6361
718e3744 6362 /* unsuppress-map */
6363 if (filter->usmap.name && ! gfilter)
400b1fad
DW
6364 {
6365 afi_header_vty_out (vty, afi, safi, write,
6366 " neighbor %s unsuppress-map %s%s",
6367 addr, filter->usmap.name, VTY_NEWLINE);
6368 }
718e3744 6369
6370 /* filter-list. */
6371 if (filter->aslist[in].name)
6372 if (! gfilter || ! gfilter->aslist[in].name
6373 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
400b1fad
DW
6374 {
6375 afi_header_vty_out (vty, afi, safi, write,
6376 " neighbor %s filter-list %s in%s",
6377 addr, filter->aslist[in].name, VTY_NEWLINE);
6378 }
6379
718e3744 6380 if (filter->aslist[out].name && ! gfilter)
400b1fad
DW
6381 {
6382 afi_header_vty_out (vty, afi, safi, write,
6383 " neighbor %s filter-list %s out%s",
6384 addr, filter->aslist[out].name, VTY_NEWLINE);
6385 }
718e3744 6386}
6387
6388/* BGP peer configuration display function. */
94f2b392 6389static void
0b960b4d
DW
6390bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp,
6391 struct peer *peer)
718e3744 6392{
718e3744 6393 struct peer *g_peer = NULL;
6394 char buf[SU_ADDRSTRLEN];
6395 char *addr;
b3a39dc5
DD
6396 int if_pg_printed = FALSE;
6397 int if_ras_printed = FALSE;
718e3744 6398
f14e6fdb
DS
6399 /* Skip dynamic neighbors. */
6400 if (peer_dynamic_neighbor (peer))
6401 return;
6402
a80beece
DS
6403 if (peer->conf_if)
6404 addr = peer->conf_if;
6405 else
6406 addr = peer->host;
6407
718e3744 6408 /************************************
6409 ****** Global to the neighbor ******
6410 ************************************/
0b960b4d 6411 if (peer->conf_if)
718e3744 6412 {
0b960b4d 6413 if (CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))
4c48cf63 6414 vty_out (vty, " neighbor %s interface v6only", addr);
0b960b4d 6415 else
4c48cf63
DW
6416 vty_out (vty, " neighbor %s interface", addr);
6417
6418 if (peer_group_active (peer))
b3a39dc5
DD
6419 {
6420 vty_out (vty, " peer-group %s", peer->group->name);
6421 if_pg_printed = TRUE;
6422 }
6423 else if (peer->as_type == AS_SPECIFIED)
6424 {
6425 vty_out (vty, " remote-as %u", peer->as);
6426 if_ras_printed = TRUE;
6427 }
6428 else if (peer->as_type == AS_INTERNAL)
6429 {
6430 vty_out (vty, " remote-as internal");
6431 if_ras_printed = TRUE;
6432 }
6433 else if (peer->as_type == AS_EXTERNAL)
6434 {
6435 vty_out (vty, " remote-as external");
6436 if_ras_printed = TRUE;
6437 }
4c48cf63
DW
6438
6439 vty_out (vty, "%s", VTY_NEWLINE);
0b960b4d 6440 }
a80beece 6441
c8560b44
DW
6442 /* remote-as and peer-group */
6443 /* peer is a member of a peer-group */
6444 if (peer_group_active (peer))
0b960b4d 6445 {
c8560b44 6446 g_peer = peer->group->conf;
0b960b4d 6447
b3a39dc5 6448 if (g_peer->as_type == AS_UNSPECIFIED && !if_ras_printed)
0b960b4d
DW
6449 {
6450 if (peer->as_type == AS_SPECIFIED)
6451 {
6452 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
6453 VTY_NEWLINE);
6454 }
6455 else if (peer->as_type == AS_INTERNAL)
6456 {
6457 vty_out (vty, " neighbor %s remote-as internal%s", addr, VTY_NEWLINE);
6458 }
6459 else if (peer->as_type == AS_EXTERNAL)
6460 {
6461 vty_out (vty, " neighbor %s remote-as external%s", addr, VTY_NEWLINE);
6462 }
6463 }
c8560b44 6464
4c48cf63
DW
6465 /* For swpX peers we displayed the peer-group
6466 * via 'neighbor swpX interface peer-group WORD' */
b3a39dc5 6467 if (!if_pg_printed)
4c48cf63
DW
6468 vty_out (vty, " neighbor %s peer-group %s%s", addr,
6469 peer->group->name, VTY_NEWLINE);
c8560b44
DW
6470 }
6471
6472 /* peer is NOT a member of a peer-group */
6473 else
6474 {
6475 /* peer is a peer-group, declare the peer-group */
6476 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
6477 {
6478 vty_out (vty, " neighbor %s peer-group%s", addr,
6479 VTY_NEWLINE);
6480 }
6481
b3a39dc5 6482 if (!if_ras_printed)
c8560b44 6483 {
b3a39dc5
DD
6484 if (peer->as_type == AS_SPECIFIED)
6485 {
6486 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
6487 VTY_NEWLINE);
6488 }
6489 else if (peer->as_type == AS_INTERNAL)
6490 {
6491 vty_out (vty, " neighbor %s remote-as internal%s", addr, VTY_NEWLINE);
6492 }
6493 else if (peer->as_type == AS_EXTERNAL)
6494 {
6495 vty_out (vty, " neighbor %s remote-as external%s", addr, VTY_NEWLINE);
6496 }
0b960b4d
DW
6497 }
6498 }
718e3744 6499
0b960b4d
DW
6500 /* local-as */
6501 if (peer->change_local_as)
6502 {
06830cb8
DW
6503 if (! peer_group_active (peer)
6504 || peer->change_local_as != g_peer->change_local_as
6505 || (CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) !=
6506 CHECK_FLAG (g_peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
6507 || (CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) !=
6508 CHECK_FLAG (g_peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS)))
0b960b4d
DW
6509 {
6510 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
6511 peer->change_local_as,
6512 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
6513 " no-prepend" : "",
6514 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
6515 " replace-as" : "", VTY_NEWLINE);
6516 }
6517 }
718e3744 6518
0b960b4d
DW
6519 /* description */
6520 if (peer->desc)
6521 {
6522 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
6523 VTY_NEWLINE);
6524 }
718e3744 6525
0b960b4d
DW
6526 /* shutdown */
6527 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
6528 {
6529 if (! peer_group_active (peer) ||
6530 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
6531 {
6532 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
6533 }
6534 }
d5a5c8f0 6535
0b960b4d
DW
6536 /* bfd */
6537 if (peer->bfd_info)
6538 {
6539 if (! peer_group_active (peer) || ! g_peer->bfd_info)
6540 {
6541 bgp_bfd_peer_config_write(vty, peer, addr);
6542 }
6543 }
718e3744 6544
0b960b4d
DW
6545 /* password */
6546 if (peer->password)
6547 {
6548 if (!peer_group_active (peer)
6549 || ! g_peer->password
6550 || strcmp (peer->password, g_peer->password) != 0)
6551 {
6552 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
6553 VTY_NEWLINE);
6554 }
6555 }
6556
6557 /* neighbor solo */
6558 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
6559 {
6560 if (!peer_group_active (peer))
6561 {
6562 vty_out (vty, " neighbor %s solo%s", addr, VTY_NEWLINE);
6563 }
6564 }
6565
6566 /* BGP port */
6567 if (peer->port != BGP_PORT_DEFAULT)
6568 {
6569 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
6570 VTY_NEWLINE);
6571 }
6572
6573 /* Local interface name */
6574 if (peer->ifname)
6575 {
6576 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
6577 VTY_NEWLINE);
6578 }
6579
6580 /* passive */
6581 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
6582 {
6583 if (! peer_group_active (peer) ||
6584 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
6585 {
6586 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
6587 }
6588 }
6589
6590 /* ebgp-multihop */
6591 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
6592 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
6593 {
6594 if (! peer_group_active (peer) || g_peer->ttl != peer->ttl)
6595 {
6596 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
6597 VTY_NEWLINE);
6598 }
6599 }
6600
6601 /* ttl-security hops */
6602 if (peer->gtsm_hops != 0)
6603 {
6604 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
6605 {
89b6d1f8 6606 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
fa411a21 6607 peer->gtsm_hops, VTY_NEWLINE);
0b960b4d
DW
6608 }
6609 }
fa411a21 6610
0b960b4d
DW
6611 /* disable-connected-check */
6612 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
6613 {
6614 if (! peer_group_active (peer) ||
6615 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
6616 {
6617 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
6618 }
6619 }
718e3744 6620
0b960b4d
DW
6621 /* update-source */
6622 if (peer->update_if)
6623 {
6624 if (! peer_group_active (peer) || ! g_peer->update_if
6625 || strcmp (g_peer->update_if, peer->update_if) != 0)
6626 {
6627 vty_out (vty, " neighbor %s update-source %s%s", addr,
6628 peer->update_if, VTY_NEWLINE);
6629 }
6630 }
6631 if (peer->update_source)
6632 {
6633 if (! peer_group_active (peer) || ! g_peer->update_source
6634 || sockunion_cmp (g_peer->update_source,
6635 peer->update_source) != 0)
6636 {
6637 vty_out (vty, " neighbor %s update-source %s%s", addr,
6638 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
6639 VTY_NEWLINE);
6640 }
6641 }
718e3744 6642
0b960b4d 6643 /* advertisement-interval */
813d4307
DW
6644 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV)
6645 && peer->v_routeadv != BGP_DEFAULT_EBGP_ROUTEADV
6646 && ! peer_group_active (peer))
0b960b4d
DW
6647 {
6648 vty_out (vty, " neighbor %s advertisement-interval %d%s",
6649 addr, peer->v_routeadv, VTY_NEWLINE);
6650 }
8a92a8a0 6651
0b960b4d
DW
6652 /* timers */
6653 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
813d4307 6654 && (peer->keepalive != BGP_DEFAULT_KEEPALIVE || peer->holdtime != BGP_DEFAULT_HOLDTIME)
0b960b4d
DW
6655 && ! peer_group_active (peer))
6656 {
6657 vty_out (vty, " neighbor %s timers %d %d%s", addr,
6658 peer->keepalive, peer->holdtime, VTY_NEWLINE);
6659 }
718e3744 6660
0b960b4d 6661 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT) &&
400b1fad 6662 peer->connect != BGP_DEFAULT_CONNECT_RETRY &&
0b960b4d
DW
6663 ! peer_group_active (peer))
6664 {
6665 vty_out (vty, " neighbor %s timers connect %d%s", addr,
6666 peer->connect, VTY_NEWLINE);
6667 }
718e3744 6668
0b960b4d
DW
6669 /* capability dynamic */
6670 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
6671 {
6672 if (! peer_group_active (peer) ||
6673 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
6674 {
6675 vty_out (vty, " neighbor %s capability dynamic%s", addr,
6676 VTY_NEWLINE);
6677 }
6678 }
6679
6680 /* capability extended-nexthop */
b3a39dc5
DD
6681 if (peer->ifp && !CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE))
6682 {
6683 if (! peer_group_active (peer) ||
6684 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_CAPABILITY_ENHE))
6685 {
6686 vty_out (vty, " no neighbor %s capability extended-nexthop%s", addr,
6687 VTY_NEWLINE);
6688 }
6689 }
6690
6691 if (!peer->ifp && CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE))
0b960b4d
DW
6692 {
6693 if (! peer_group_active (peer) ||
6694 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_CAPABILITY_ENHE))
6695 {
6696 vty_out (vty, " neighbor %s capability extended-nexthop%s", addr,
6697 VTY_NEWLINE);
6698 }
718e3744 6699 }
6700
0b960b4d
DW
6701 /* dont-capability-negotiation */
6702 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
6703 {
6704 if (! peer_group_active (peer) ||
6705 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
6706 {
6707 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
6708 VTY_NEWLINE);
6709 }
6710 }
718e3744 6711
0b960b4d
DW
6712 /* override-capability */
6713 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
6714 {
6715 if (! peer_group_active (peer) ||
6716 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
6717 {
6718 vty_out (vty, " neighbor %s override-capability%s", addr,
6719 VTY_NEWLINE);
6720 }
6721 }
718e3744 6722
0b960b4d
DW
6723 /* strict-capability-match */
6724 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
718e3744 6725 {
0b960b4d
DW
6726 if (! peer_group_active (peer) ||
6727 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
6728 {
6729 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
6730 VTY_NEWLINE);
6731 }
718e3744 6732 }
0b960b4d
DW
6733}
6734
0b960b4d
DW
6735/* BGP peer configuration display function. */
6736static void
6737bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp,
400b1fad
DW
6738 struct peer *peer, afi_t afi, safi_t safi,
6739 int *write)
0b960b4d
DW
6740{
6741 struct peer *g_peer = NULL;
6742 char *addr;
6743
6744 /* Skip dynamic neighbors. */
6745 if (peer_dynamic_neighbor (peer))
6746 return;
6747
6748 if (peer->conf_if)
6749 addr = peer->conf_if;
6750 else
6751 addr = peer->host;
6752
0b960b4d
DW
6753 /************************************
6754 ****** Per AF to the neighbor ******
6755 ************************************/
c8560b44 6756 if (peer_group_active (peer))
400b1fad 6757 {
c8560b44
DW
6758 g_peer = peer->group->conf;
6759
6760 /* If the peer-group is active but peer is not, print a 'no activate' */
6761 if (g_peer->afc[afi][safi] && !peer->afc[afi][safi])
6762 {
6763 afi_header_vty_out (vty, afi, safi, write,
6764 " no neighbor %s activate%s",
6765 addr, VTY_NEWLINE);
6766 }
6767
6768 /* If the peer-group is not active but peer is, print an 'activate' */
6769 else if (!g_peer->afc[afi][safi] && peer->afc[afi][safi])
6770 {
6771 afi_header_vty_out (vty, afi, safi, write,
6772 " neighbor %s activate%s",
6773 addr, VTY_NEWLINE);
6774 }
400b1fad 6775 }
0b960b4d 6776 else
c8560b44
DW
6777 {
6778 if (peer->afc[afi][safi])
6779 {
655f79c9
DD
6780 if ((afi == AFI_IP) && (safi == SAFI_UNICAST))
6781 {
6782 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
6783 {
a94d98ae
DW
6784 afi_header_vty_out(vty, afi, safi, write,
6785 " neighbor %s activate%s",
6786 addr, VTY_NEWLINE);
655f79c9
DD
6787 }
6788 }
6789 else
6790 afi_header_vty_out (vty, afi, safi, write,
6791 " neighbor %s activate%s",
6792 addr, VTY_NEWLINE);
c8560b44 6793 }
7709c62d
DS
6794 else
6795 {
6796 if ((afi == AFI_IP) && (safi == SAFI_UNICAST))
6797 {
6798 if (!bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
6799 {
6800 afi_header_vty_out (vty, afi, safi, write,
6801 " no neighbor %s activate%s",
6802 addr, VTY_NEWLINE);
6803 }
6804 }
6805 }
c8560b44 6806 }
718e3744 6807
adbac85e
DW
6808 /* addpath TX knobs */
6809 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ADDPATH_TX_ALL_PATHS))
c8560b44
DW
6810 {
6811 afi_header_vty_out (vty, afi, safi, write,
6812 " neighbor %s addpath-tx-all-paths%s",
6813 addr, VTY_NEWLINE);
6814 }
06370dac
DW
6815
6816 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS))
c8560b44
DW
6817 {
6818 afi_header_vty_out (vty, afi, safi, write,
6819 " neighbor %s addpath-tx-bestpath-per-AS%s",
6820 addr, VTY_NEWLINE);
6821 }
adbac85e 6822
718e3744 6823 /* ORF capability. */
88b8ed8d
DW
6824 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM) ||
6825 peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_RM))
718e3744 6826 {
400b1fad
DW
6827 afi_header_vty_out (vty, afi, safi, write,
6828 " neighbor %s capability orf prefix-list",
6829 addr);
718e3744 6830
88b8ed8d
DW
6831 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM) &&
6832 peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_RM))
718e3744 6833 vty_out (vty, " both");
88b8ed8d 6834 else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM))
718e3744 6835 vty_out (vty, " send");
6836 else
6837 vty_out (vty, " receive");
6838 vty_out (vty, "%s", VTY_NEWLINE);
6839 }
6840
6841 /* Route reflector client. */
88b8ed8d 6842 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT))
400b1fad
DW
6843 {
6844 afi_header_vty_out (vty, afi, safi, write,
6845 " neighbor %s route-reflector-client%s",
6846 addr, VTY_NEWLINE);
6847 }
88b8ed8d
DW
6848
6849 /* next-hop-self force */
6850 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_FORCE_NEXTHOP_SELF))
400b1fad
DW
6851 {
6852 afi_header_vty_out (vty, afi, safi, write,
6853 " neighbor %s next-hop-self force%s",
6854 addr, VTY_NEWLINE);
6855 }
718e3744 6856
88b8ed8d
DW
6857 /* next-hop-self */
6858 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF))
400b1fad
DW
6859 {
6860 afi_header_vty_out (vty, afi, safi, write,
6861 " neighbor %s next-hop-self%s",
6862 addr, VTY_NEWLINE);
6863 }
718e3744 6864
5000f21c 6865 /* remove-private-AS */
88b8ed8d 6866 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
400b1fad
DW
6867 {
6868 afi_header_vty_out (vty, afi, safi, write,
6869 " neighbor %s remove-private-AS all replace-AS%s",
6870 addr, VTY_NEWLINE);
6871 }
5000f21c 6872
88b8ed8d 6873 else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
400b1fad
DW
6874 {
6875 afi_header_vty_out (vty, afi, safi, write,
6876 " neighbor %s remove-private-AS replace-AS%s",
6877 addr, VTY_NEWLINE);
6878 }
5000f21c 6879
88b8ed8d 6880 else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL))
400b1fad
DW
6881 {
6882 afi_header_vty_out (vty, afi, safi, write,
6883 " neighbor %s remove-private-AS all%s",
6884 addr, VTY_NEWLINE);
6885 }
5000f21c 6886
88b8ed8d 6887 else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS))
400b1fad
DW
6888 {
6889 afi_header_vty_out (vty, afi, safi, write,
6890 " neighbor %s remove-private-AS%s",
6891 addr, VTY_NEWLINE);
6892 }
718e3744 6893
c7122e14 6894 /* as-override */
88b8ed8d 6895 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_OVERRIDE))
400b1fad
DW
6896 {
6897 afi_header_vty_out (vty, afi, safi, write,
6898 " neighbor %s as-override%s",
6899 addr, VTY_NEWLINE);
6900 }
c7122e14 6901
718e3744 6902 /* send-community print. */
88b8ed8d 6903 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
718e3744 6904 {
88b8ed8d
DW
6905 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
6906 && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
400b1fad
DW
6907 {
6908 afi_header_vty_out (vty, afi, safi, write,
6909 " neighbor %s send-community both%s",
6910 addr, VTY_NEWLINE);
6911 }
88b8ed8d 6912 else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
400b1fad
DW
6913 {
6914 afi_header_vty_out (vty, afi, safi, write,
6915 " neighbor %s send-community extended%s",
6916 addr, VTY_NEWLINE);
6917 }
88b8ed8d 6918 else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
400b1fad
DW
6919 {
6920 afi_header_vty_out (vty, afi, safi, write,
6921 " neighbor %s send-community%s",
6922 addr, VTY_NEWLINE);
6923 }
88b8ed8d
DW
6924 }
6925 else
6926 {
6927 if (!peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY) &&
ad695d6e 6928 (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)) &&
88b8ed8d 6929 !peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY) &&
ad695d6e 6930 (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)))
400b1fad
DW
6931 {
6932 afi_header_vty_out (vty, afi, safi, write,
6933 " no neighbor %s send-community both%s",
6934 addr, VTY_NEWLINE);
6935 }
88b8ed8d 6936 else if (!peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY) &&
ad695d6e 6937 (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)))
400b1fad
DW
6938 {
6939 afi_header_vty_out (vty, afi, safi, write,
6940 " no neighbor %s send-community extended%s",
6941 addr, VTY_NEWLINE);
6942 }
88b8ed8d 6943 else if (!peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY) &&
ad695d6e 6944 (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)))
400b1fad
DW
6945 {
6946 afi_header_vty_out (vty, afi, safi, write,
6947 " no neighbor %s send-community%s",
6948 addr, VTY_NEWLINE);
6949 }
718e3744 6950 }
6951
6952 /* Default information */
88b8ed8d
DW
6953 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE) ||
6954 (g_peer &&
6955 ((peer->default_rmap[afi][safi].name && !g_peer->default_rmap[afi][safi].name) ||
6956 (!peer->default_rmap[afi][safi].name && g_peer->default_rmap[afi][safi].name) ||
6957 (peer->default_rmap[afi][safi].name &&
6958 strcmp(peer->default_rmap[afi][safi].name, g_peer->default_rmap[afi][safi].name)))))
718e3744 6959 {
400b1fad
DW
6960 afi_header_vty_out (vty, afi, safi, write,
6961 " neighbor %s default-originate", addr);
718e3744 6962 if (peer->default_rmap[afi][safi].name)
88b8ed8d 6963 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
718e3744 6964 vty_out (vty, "%s", VTY_NEWLINE);
6965 }
6966
6967 /* Soft reconfiguration inbound. */
88b8ed8d 6968 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SOFT_RECONFIG))
400b1fad
DW
6969 {
6970 afi_header_vty_out (vty, afi, safi, write,
6971 " neighbor %s soft-reconfiguration inbound%s",
6972 addr, VTY_NEWLINE);
6973 }
718e3744 6974
6975 /* maximum-prefix. */
6976 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
c8560b44 6977 if (! peer_group_active(peer)
718e3744 6978 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
e0701b79 6979 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
718e3744 6980 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
6981 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
e0701b79 6982 {
400b1fad 6983 afi_header_vty_out (vty, afi, safi, write,
85e11c23 6984 " neighbor %s maximum-prefix %lu",
400b1fad 6985 addr, peer->pmax[afi][safi]);
0a486e5f 6986 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
6987 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
6988 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
6989 vty_out (vty, " warning-only");
6990 if (peer->pmax_restart[afi][safi])
6991 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
6992 vty_out (vty, "%s", VTY_NEWLINE);
e0701b79 6993 }
718e3744 6994
6995 /* Route server client. */
88b8ed8d 6996 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_RSERVER_CLIENT))
400b1fad
DW
6997 {
6998 afi_header_vty_out (vty, afi, safi, write,
6999 " neighbor %s route-server-client%s",
7000 addr, VTY_NEWLINE);
7001 }
718e3744 7002
3cf1288b 7003 /* Nexthop-local unchanged. */
88b8ed8d 7004 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED))
400b1fad
DW
7005 {
7006 afi_header_vty_out (vty, afi, safi, write,
7007 " neighbor %s nexthop-local unchanged%s",
7008 addr, VTY_NEWLINE);
7009 }
3cf1288b 7010
718e3744 7011 /* Allow AS in. */
7012 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
7013 if (! peer_group_active (peer)
7014 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
7015 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
7016 {
7017 if (peer->allowas_in[afi][safi] == 3)
400b1fad
DW
7018 {
7019 afi_header_vty_out (vty, afi, safi, write,
7020 " neighbor %s allowas-in%s",
7021 addr, VTY_NEWLINE);
7022 }
7023 else
7024 {
7025 afi_header_vty_out (vty, afi, safi, write,
7026 " neighbor %s allowas-in %d%s",
7027 addr, peer->allowas_in[afi][safi], VTY_NEWLINE);
7028 }
718e3744 7029 }
7030
d93f7ffc
DW
7031 /* weight */
7032 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_WEIGHT))
7033 if (! peer_group_active (peer)
7034 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_WEIGHT)
7035 || peer->weight[afi][safi] != g_peer->weight[afi][safi])
7036 {
7037 if (peer->weight[afi][safi])
7038 {
7039 afi_header_vty_out (vty, afi, safi, write,
7040 " neighbor %s weight %d%s",
7041 addr, peer->weight[afi][safi], VTY_NEWLINE);
7042 }
7043 }
7044
718e3744 7045 /* Filter. */
400b1fad 7046 bgp_config_write_filter (vty, peer, afi, safi, write);
718e3744 7047
7048 /* atribute-unchanged. */
88b8ed8d 7049 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
718e3744 7050 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
7051 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
718e3744 7052 {
88b8ed8d
DW
7053 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED)
7054 && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_UNCHANGED)
7055 && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_MED_UNCHANGED))
400b1fad
DW
7056 {
7057 afi_header_vty_out (vty, afi, safi, write,
7058 " neighbor %s attribute-unchanged%s",
7059 addr, VTY_NEWLINE);
7060 }
718e3744 7061 else
400b1fad
DW
7062 {
7063 afi_header_vty_out (vty, afi, safi, write,
7064 " neighbor %s attribute-unchanged%s%s%s%s", addr,
7065 peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED) ?
7066 " as-path" : "",
7067 peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_UNCHANGED) ?
7068 " next-hop" : "",
7069 peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_MED_UNCHANGED) ?
7070 " med" : "", VTY_NEWLINE);
7071 }
718e3744 7072 }
7073}
7074
7075/* Display "address-family" configuration header. */
7076void
7077bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
7078 int *write)
7079{
7080 if (*write)
7081 return;
7082
3914b418 7083 vty_out (vty, " !%s address-family ", VTY_NEWLINE);
718e3744 7084
7085 if (afi == AFI_IP)
7086 {
0b960b4d
DW
7087 if (safi == SAFI_UNICAST)
7088 vty_out (vty, "ipv4 unicast");
7089 else if (safi == SAFI_MULTICAST)
718e3744 7090 vty_out (vty, "ipv4 multicast");
7091 else if (safi == SAFI_MPLS_VPN)
8b1fb8be
LB
7092 vty_out (vty, "vpnv4");
7093 else if (safi == SAFI_ENCAP)
7094 vty_out (vty, "encap");
718e3744 7095 }
7096 else if (afi == AFI_IP6)
37a217a5 7097 {
0b960b4d
DW
7098 if (safi == SAFI_UNICAST)
7099 vty_out (vty, "ipv6 unicast");
7100 else if (safi == SAFI_MULTICAST)
7101 vty_out (vty, "ipv6 multicast");
8ecd3266 7102 else if (safi == SAFI_MPLS_VPN)
7103 vty_out (vty, "vpnv6");
8b1fb8be
LB
7104 else if (safi == SAFI_ENCAP)
7105 vty_out (vty, "encapv6");
37a217a5 7106 }
718e3744 7107
7108 vty_out (vty, "%s", VTY_NEWLINE);
7109
7110 *write = 1;
7111}
7112
7113/* Address family based peer configuration display. */
94f2b392 7114static int
718e3744 7115bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
7116 safi_t safi)
7117{
7118 int write = 0;
7119 struct peer *peer;
7120 struct peer_group *group;
1eb8ef25 7121 struct listnode *node, *nnode;
718e3744 7122
7123 bgp_config_write_network (vty, bgp, afi, safi, &write);
7124
7125 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
7126
1eb8ef25 7127 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
400b1fad
DW
7128 bgp_config_write_peer_af (vty, bgp, group->conf, afi, safi, &write);
7129
1eb8ef25 7130 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 7131 {
f14e6fdb
DS
7132 /* Skip dynamic neighbors. */
7133 if (peer_dynamic_neighbor (peer))
7134 continue;
7135
400b1fad
DW
7136 /* Do not display doppelganger peers */
7137 if (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE))
7138 bgp_config_write_peer_af (vty, bgp, peer, afi, safi, &write);
718e3744 7139 }
165b5fff
JB
7140
7141 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
73ac8160 7142 bgp_config_write_table_map (vty, bgp, afi, safi, &write);
165b5fff 7143
718e3744 7144 if (write)
7145 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
7146
7147 return write;
7148}
7149
7150int
7151bgp_config_write (struct vty *vty)
7152{
7153 int write = 0;
7154 struct bgp *bgp;
7155 struct peer_group *group;
7156 struct peer *peer;
1eb8ef25 7157 struct listnode *node, *nnode;
7158 struct listnode *mnode, *mnnode;
718e3744 7159
7160 /* BGP Multiple instance. */
b8fd6a15 7161 if (!bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
718e3744 7162 {
b8fd6a15 7163 vty_out (vty, "no bgp multiple-instance%s", VTY_NEWLINE);
718e3744 7164 write++;
7165 }
7166
7167 /* BGP Config type. */
7168 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
7169 {
7170 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
7171 write++;
7172 }
7173
5fe9f963 7174 if (bm->rmap_update_timer != RMAP_DEFAULT_UPDATE_TIMER)
7175 vty_out (vty, "bgp route-map delay-timer %d%s", bm->rmap_update_timer,
7176 VTY_NEWLINE);
7177
718e3744 7178 /* BGP configuration. */
1eb8ef25 7179 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
718e3744 7180 {
7181 if (write)
7182 vty_out (vty, "!%s", VTY_NEWLINE);
7183
7184 /* Router bgp ASN */
aea339f7 7185 vty_out (vty, "router bgp %u", bgp->as);
718e3744 7186
7187 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
7188 {
7189 if (bgp->name)
ad4cbda1 7190 vty_out (vty, " %s %s",
7191 (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) ?
7192 "view" : "vrf", bgp->name);
718e3744 7193 }
7194 vty_out (vty, "%s", VTY_NEWLINE);
7195
7196 /* No Synchronization */
7197 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
7198 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
7199
7200 /* BGP fast-external-failover. */
7201 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
7202 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
7203
7204 /* BGP router ID. */
c2d58d6d 7205 if (bgp->router_id_static.s_addr != 0)
7206 vty_out (vty, " bgp router-id %s%s",
7207 inet_ntoa (bgp->router_id_static), VTY_NEWLINE);
718e3744 7208
848973c7 7209 /* BGP log-neighbor-changes. */
6793fbe0
DW
7210 if (!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
7211 vty_out (vty, " no bgp log-neighbor-changes%s", VTY_NEWLINE);
848973c7 7212
718e3744 7213 /* BGP configuration. */
7214 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
7215 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
7216
7217 /* BGP default ipv4-unicast. */
7218 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
7219 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
7220
7221 /* BGP default local-preference. */
7222 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
7223 vty_out (vty, " bgp default local-preference %d%s",
7224 bgp->default_local_pref, VTY_NEWLINE);
7225
04b6bdc0 7226 /* BGP default show-hostname */
15f3b5c0
DW
7227 if (!bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME))
7228 vty_out (vty, " no bgp default show-hostname%s", VTY_NEWLINE);
04b6bdc0 7229
3f9c7369
DS
7230 /* BGP default subgroup-pkt-queue-max. */
7231 if (bgp->default_subgroup_pkt_queue_max != BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX)
7232 vty_out (vty, " bgp default subgroup-pkt-queue-max %d%s",
7233 bgp->default_subgroup_pkt_queue_max, VTY_NEWLINE);
7234
718e3744 7235 /* BGP client-to-client reflection. */
7236 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
7237 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
7238
7239 /* BGP cluster ID. */
7240 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
7241 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
7242 VTY_NEWLINE);
7243
907f92c8
DS
7244 /* Disable ebgp connected nexthop check */
7245 if (bgp_flag_check (bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
7246 vty_out (vty, " bgp disable-ebgp-connected-route-check%s", VTY_NEWLINE);
7247
e0701b79 7248 /* Confederation identifier*/
718e3744 7249 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
e0701b79 7250 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
7251 VTY_NEWLINE);
7252
7253 /* Confederation peer */
7254 if (bgp->confed_peers_cnt > 0)
718e3744 7255 {
e0701b79 7256 int i;
718e3744 7257
e0701b79 7258 vty_out (vty, " bgp confederation peers");
718e3744 7259
e0701b79 7260 for (i = 0; i < bgp->confed_peers_cnt; i++)
aea339f7 7261 vty_out(vty, " %u", bgp->confed_peers[i]);
718e3744 7262
e0701b79 7263 vty_out (vty, "%s", VTY_NEWLINE);
718e3744 7264 }
7265
7266 /* BGP enforce-first-as. */
7267 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
7268 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
7269
7270 /* BGP deterministic-med. */
1475ac87
DW
7271 if (!bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
7272 vty_out (vty, " no bgp deterministic-med%s", VTY_NEWLINE);
538621f2 7273
f188f2c4
DS
7274 /* BGP update-delay. */
7275 bgp_config_write_update_delay (vty, bgp);
7276
abc920f8
DS
7277 if (bgp->v_maxmed_onstartup != BGP_MAXMED_ONSTARTUP_UNCONFIGURED)
7278 {
7279 vty_out (vty, " bgp max-med on-startup %d", bgp->v_maxmed_onstartup);
7280 if (bgp->maxmed_onstartup_value != BGP_MAXMED_VALUE_DEFAULT)
7281 vty_out (vty, " %d", bgp->maxmed_onstartup_value);
7282 vty_out (vty, "%s", VTY_NEWLINE);
7283 }
7284 if (bgp->v_maxmed_admin != BGP_MAXMED_ADMIN_UNCONFIGURED)
7285 {
7286 vty_out (vty, " bgp max-med administrative");
7287 if (bgp->maxmed_admin_value != BGP_MAXMED_VALUE_DEFAULT)
7288 vty_out (vty, " %d", bgp->maxmed_admin_value);
7289 vty_out (vty, "%s", VTY_NEWLINE);
7290 }
7291
cb1faec9
DS
7292 /* write quanta */
7293 bgp_config_write_wpkt_quanta (vty, bgp);
7294
3f9c7369
DS
7295 /* coalesce time */
7296 bgp_config_write_coalesce_time(vty, bgp);
7297
538621f2 7298 /* BGP graceful-restart. */
93406d87 7299 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
7300 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
7301 bgp->stalepath_time, VTY_NEWLINE);
eb6f1b41
PG
7302 if (bgp->restart_time != BGP_DEFAULT_RESTART_TIME)
7303 vty_out (vty, " bgp graceful-restart restart-time %d%s",
7304 bgp->restart_time, VTY_NEWLINE);
538621f2 7305 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
7306 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
7307
718e3744 7308 /* BGP bestpath method. */
7309 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
7310 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
6811845b 7311 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
7312 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
16fc1eec 7313
219178b6
DW
7314 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX))
7315 {
7316 if (bgp_flag_check (bgp, BGP_FLAG_MULTIPATH_RELAX_AS_SET))
7317 {
7318 vty_out (vty, " bgp bestpath as-path multipath-relax as-set%s", VTY_NEWLINE);
7319 }
7dc9d4e4
DW
7320 else
7321 {
7322 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
7323 }
16fc1eec 7324 }
16fc1eec 7325
8bd9d948
DS
7326 if (bgp_flag_check (bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
7327 vty_out (vty, " bgp route-reflector allow-outbound-policy%s",
7328 VTY_NEWLINE);
7329 }
718e3744 7330 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
7331 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
7332 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
7333 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
7334 {
7335 vty_out (vty, " bgp bestpath med");
7336 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
7337 vty_out (vty, " confed");
7338 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
7339 vty_out (vty, " missing-as-worst");
7340 vty_out (vty, "%s", VTY_NEWLINE);
7341 }
7342
7343 /* BGP network import check. */
5623e905
DW
7344 if (!bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
7345 vty_out (vty, " no bgp network import-check%s", VTY_NEWLINE);
718e3744 7346
718e3744 7347 /* BGP flag dampening. */
7348 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
7349 BGP_CONFIG_DAMPENING))
7350 bgp_config_write_damp (vty);
7351
718e3744 7352 /* BGP timers configuration. */
7353 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
7354 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
7355 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
7356 bgp->default_holdtime, VTY_NEWLINE);
7357
7358 /* peer-group */
1eb8ef25 7359 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 7360 {
0b960b4d 7361 bgp_config_write_peer_global (vty, bgp, group->conf);
718e3744 7362 }
7363
7364 /* Normal neighbor configuration. */
1eb8ef25 7365 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 7366 {
1ff9a340 7367 if (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE))
0b960b4d 7368 bgp_config_write_peer_global (vty, bgp, peer);
718e3744 7369 }
7370
7371 /* Distance configuration. */
7372 bgp_config_write_distance (vty, bgp);
7373
f14e6fdb
DS
7374 /* listen range and limit for dynamic BGP neighbors */
7375 bgp_config_write_listen (vty, bgp);
7376
718e3744 7377 /* No auto-summary */
7378 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
7379 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
7380
0b960b4d
DW
7381 /* IPv4 unicast configuration. */
7382 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_UNICAST);
7383
718e3744 7384 /* IPv4 multicast configuration. */
7385 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
7386
7387 /* IPv4 VPN configuration. */
7388 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
7389
8b1fb8be
LB
7390 /* ENCAPv4 configuration. */
7391 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_ENCAP);
7392
718e3744 7393 /* IPv6 unicast configuration. */
7394 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
7395
37a217a5
PJ
7396 /* IPv6 multicast configuration. */
7397 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
7398
8ecd3266 7399 /* IPv6 VPN configuration. */
7400 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MPLS_VPN);
7401
8b1fb8be
LB
7402 /* ENCAPv6 configuration. */
7403 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_ENCAP);
7404
65efcfce
LB
7405#if ENABLE_BGP_VNC
7406 write += bgp_rfapi_cfg_write(vty, bgp);
7407#endif
7408
718e3744 7409 write++;
7410 }
7411 return write;
7412}
7413
7414void
94f2b392 7415bgp_master_init (void)
718e3744 7416{
7417 memset (&bgp_master, 0, sizeof (struct bgp_master));
7418
7419 bm = &bgp_master;
7420 bm->bgp = list_new ();
0df7c91f 7421 bm->listen_sockets = list_new ();
718e3744 7422 bm->port = BGP_PORT_DEFAULT;
87d4a781 7423 bm->master = thread_master_create ();
65957886 7424 bm->start_time = bgp_clock ();
5fe9f963 7425 bm->t_rmap_update = NULL;
7426 bm->rmap_update_timer = RMAP_DEFAULT_UPDATE_TIMER;
495f0b13
DS
7427
7428 bgp_process_queue_init();
b8fd6a15 7429
7430 /* Enable multiple instances by default. */
7431 bgp_option_set (BGP_OPT_MULTIPLE_INSTANCE);
718e3744 7432}
200df115 7433
b33adb7c 7434/*
7435 * Initialize interface list for instance, if needed. Invoked upon
7436 * instance create.
7437 */
7438static void
7439bgp_if_init (struct bgp *bgp)
7440{
7441 if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
7442 return;
7443
7444 vrf_iflist_create (bgp->vrf_id);
7445}
7446
ad4cbda1 7447/*
009b18fc 7448 * Free up connected routes and interfaces for a BGP instance. Invoked upon
7449 * instance delete (non-default only) or BGP exit.
ad4cbda1 7450 */
b33adb7c 7451static void
009b18fc 7452bgp_if_finish (struct bgp *bgp)
ad4cbda1 7453{
009b18fc 7454 struct listnode *ifnode, *ifnnode;
7455 struct interface *ifp;
ad4cbda1 7456
009b18fc 7457 if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
7458 return;
ad4cbda1 7459
009b18fc 7460 for (ALL_LIST_ELEMENTS (vrf_iflist(bgp->vrf_id), ifnode, ifnnode, ifp))
7461 {
7462 struct listnode *c_node, *c_nnode;
7463 struct connected *c;
ad4cbda1 7464
009b18fc 7465 for (ALL_LIST_ELEMENTS (ifp->connected, c_node, c_nnode, c))
7466 bgp_connected_delete (bgp, c);
ad4cbda1 7467 }
7468}
6b0655a2 7469
718e3744 7470void
94f2b392 7471bgp_init (void)
718e3744 7472{
fc9a856f
DS
7473
7474 /* allocates some vital data structures used by peer commands in vty_init */
718e3744 7475
718e3744 7476 /* Init zebra. */
9229d914 7477 bgp_zebra_init(bm->master);
718e3744 7478
65efcfce
LB
7479#if ENABLE_BGP_VNC
7480 vnc_zebra_init (bm->master);
7481#endif
7482
fc9a856f
DS
7483 /* BGP VTY commands installation. */
7484 bgp_vty_init ();
7485
718e3744 7486 /* BGP inits. */
7487 bgp_attr_init ();
7488 bgp_debug_init ();
7489 bgp_dump_init ();
7490 bgp_route_init ();
7491 bgp_route_map_init ();
fc9a856f 7492 bgp_scan_vty_init();
718e3744 7493 bgp_mplsvpn_init ();
587ff0fd 7494 bgp_encap_init ();
65efcfce
LB
7495#if ENABLE_BGP_VNC
7496 rfapi_init ();
7497#endif
718e3744 7498
7499 /* Access list initialize. */
7500 access_list_init ();
7501 access_list_add_hook (peer_distribute_update);
7502 access_list_delete_hook (peer_distribute_update);
7503
7504 /* Filter list initialize. */
7505 bgp_filter_init ();
518f0eb1
DS
7506 as_list_add_hook (peer_aslist_add);
7507 as_list_delete_hook (peer_aslist_del);
718e3744 7508
7509 /* Prefix list initialize.*/
7510 prefix_list_init ();
7511 prefix_list_add_hook (peer_prefix_list_update);
7512 prefix_list_delete_hook (peer_prefix_list_update);
7513
7514 /* Community list initialize. */
7515 bgp_clist = community_list_init ();
7516
7517#ifdef HAVE_SNMP
7518 bgp_snmp_init ();
7519#endif /* HAVE_SNMP */
c43ed2e4
DS
7520
7521 /* BFD init */
7522 bgp_bfd_init();
718e3744 7523}
545acafb 7524
7525void
66e5cd87 7526bgp_terminate (void)
545acafb 7527{
545acafb 7528 struct bgp *bgp;
7529 struct peer *peer;
1eb8ef25 7530 struct listnode *node, *nnode;
7531 struct listnode *mnode, *mnnode;
545acafb 7532
1ff9a340
DS
7533 /* Close the listener sockets first as this prevents peers from attempting
7534 * to reconnect on receiving the peer unconfig message. In the presence
7535 * of a large number of peers this will ensure that no peer is left with
7536 * a dangling connection
7537 */
7538 /* reverse bgp_master_init */
7539 bgp_close();
7540 if (bm->listen_sockets)
7541 list_free(bm->listen_sockets);
7542 bm->listen_sockets = NULL;
7543
1eb8ef25 7544 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
7545 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
1ff9a340
DS
7546 if (peer->status == Established ||
7547 peer->status == OpenSent ||
7548 peer->status == OpenConfirm)
545acafb 7549 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
7550 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
1ff9a340 7551
545acafb 7552 bgp_cleanup_routes ();
acde4b86 7553
e210cf9f 7554 if (bm->process_main_queue)
acde4b86
SH
7555 {
7556 work_queue_free (bm->process_main_queue);
7557 bm->process_main_queue = NULL;
7558 }
5fe9f963 7559
7560 if (bm->t_rmap_update)
7561 BGP_TIMER_OFF(bm->t_rmap_update);
545acafb 7562}