]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgpd.c
bgpd: Fix rfapi qobj use.
[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);
f9164b1d
PJ
1974
1975 /* Remove from NHT */
1976 bgp_unlink_nexthop_by_peer (peer);
1977
0df7c91f
PJ
1978 /* Password configuration */
1979 if (peer->password)
1980 {
1981 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1982 peer->password = NULL;
1983
019cbf70 1984 if (!accept_peer &&
89ca90fa 1985 ! BGP_PEER_SU_UNSPEC(peer) &&
019cbf70 1986 ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
89ca90fa 1987 bgp_md5_unset (peer);
0df7c91f
PJ
1988 }
1989
ca058a30 1990 bgp_timer_set (peer); /* stops all timers for Deleted */
1ff9a340 1991
718e3744 1992 /* Delete from all peer list. */
228da428
CC
1993 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1994 && (pn = listnode_lookup (bgp->peer, peer)))
fee0f4c6 1995 {
228da428
CC
1996 peer_unlock (peer); /* bgp peer list reference */
1997 list_delete_node (bgp->peer, pn);
dd793e4a 1998 hash_release(bgp->peerhash, peer);
228da428 1999 }
200df115 2000
200df115 2001 /* Buffers. */
718e3744 2002 if (peer->ibuf)
9e08021c
DW
2003 {
2004 stream_free (peer->ibuf);
2005 peer->ibuf = NULL;
2006 }
2007
718e3744 2008 if (peer->obuf)
9e08021c
DW
2009 {
2010 stream_fifo_free (peer->obuf);
2011 peer->obuf = NULL;
2012 }
2013
718e3744 2014 if (peer->work)
9e08021c
DW
2015 {
2016 stream_free (peer->work);
2017 peer->work = NULL;
2018 }
2019
8c71e481 2020 if (peer->scratch)
9e08021c
DW
2021 {
2022 stream_free(peer->scratch);
2023 peer->scratch = NULL;
2024 }
18937400 2025
718e3744 2026 /* Local and remote addresses. */
2027 if (peer->su_local)
9e08021c
DW
2028 {
2029 sockunion_free (peer->su_local);
2030 peer->su_local = NULL;
2031 }
2032
718e3744 2033 if (peer->su_remote)
9e08021c
DW
2034 {
2035 sockunion_free (peer->su_remote);
2036 peer->su_remote = NULL;
2037 }
200df115 2038
718e3744 2039 /* Free filter related memory. */
2040 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2041 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2042 {
2043 filter = &peer->filter[afi][safi];
2044
2045 for (i = FILTER_IN; i < FILTER_MAX; i++)
2046 {
2047 if (filter->dlist[i].name)
9e08021c
DW
2048 {
2049 XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[i].name);
2050 filter->dlist[i].name = NULL;
2051 }
2052
718e3744 2053 if (filter->plist[i].name)
9e08021c
DW
2054 {
2055 XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[i].name);
2056 filter->plist[i].name = NULL;
2057 }
2058
718e3744 2059 if (filter->aslist[i].name)
9e08021c
DW
2060 {
2061 XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[i].name);
2062 filter->aslist[i].name = NULL;
2063 }
200df115 2064 }
9e08021c 2065
200df115 2066 for (i = RMAP_IN; i < RMAP_MAX; i++)
2067 {
718e3744 2068 if (filter->map[i].name)
9e08021c
DW
2069 {
2070 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[i].name);
2071 filter->map[i].name = NULL;
2072 }
718e3744 2073 }
2074
2075 if (filter->usmap.name)
9e08021c
DW
2076 {
2077 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
2078 filter->usmap.name = NULL;
2079 }
718e3744 2080
2081 if (peer->default_rmap[afi][safi].name)
9e08021c
DW
2082 {
2083 XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name);
2084 peer->default_rmap[afi][safi].name = NULL;
2085 }
718e3744 2086 }
3f9c7369
DS
2087
2088 FOREACH_AFI_SAFI (afi, safi)
2089 peer_af_delete (peer, afi, safi);
04b6bdc0
DW
2090
2091 if (peer->hostname)
9e08021c 2092 {
4a1ab8e4 2093 XFREE(MTYPE_BGP_PEER_HOST, peer->hostname);
9e08021c
DW
2094 peer->hostname = NULL;
2095 }
2096
04b6bdc0 2097 if (peer->domainname)
9e08021c 2098 {
4a1ab8e4 2099 XFREE(MTYPE_BGP_PEER_HOST, peer->domainname);
9e08021c
DW
2100 peer->domainname = NULL;
2101 }
bb86c601 2102
200df115 2103 peer_unlock (peer); /* initial reference */
718e3744 2104
2105 return 0;
2106}
6b0655a2 2107
94f2b392 2108static int
718e3744 2109peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
2110{
2111 return strcmp (g1->name, g2->name);
2112}
2113
718e3744 2114/* Peer group cofiguration. */
2115static struct peer_group *
66e5cd87 2116peer_group_new (void)
718e3744 2117{
4a1ab8e4 2118 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
718e3744 2119 sizeof (struct peer_group));
2120}
2121
94f2b392 2122static void
718e3744 2123peer_group_free (struct peer_group *group)
2124{
4a1ab8e4 2125 XFREE (MTYPE_PEER_GROUP, group);
718e3744 2126}
2127
2128struct peer_group *
fd79ac91 2129peer_group_lookup (struct bgp *bgp, const char *name)
718e3744 2130{
2131 struct peer_group *group;
1eb8ef25 2132 struct listnode *node, *nnode;
718e3744 2133
1eb8ef25 2134 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 2135 {
2136 if (strcmp (group->name, name) == 0)
2137 return group;
2138 }
2139 return NULL;
2140}
2141
2142struct peer_group *
fd79ac91 2143peer_group_get (struct bgp *bgp, const char *name)
718e3744 2144{
2145 struct peer_group *group;
f14e6fdb 2146 afi_t afi;
718e3744 2147
2148 group = peer_group_lookup (bgp, name);
2149 if (group)
2150 return group;
2151
2152 group = peer_group_new ();
2153 group->bgp = bgp;
6e919709 2154 if (group->name)
4a1ab8e4
DL
2155 XFREE(MTYPE_PEER_GROUP_HOST, group->name);
2156 group->name = XSTRDUP(MTYPE_PEER_GROUP_HOST, name);
718e3744 2157 group->peer = list_new ();
f14e6fdb
DS
2158 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2159 group->listen_range[afi] = list_new ();
6f58544d 2160 group->conf = peer_new (bgp);
718e3744 2161 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
2162 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
6e919709
DS
2163 if (group->conf->host)
2164 XFREE(MTYPE_BGP_PEER_HOST, group->conf->host);
228da428 2165 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
718e3744 2166 group->conf->group = group;
2167 group->conf->as = 0;
2168 group->conf->ttl = 1;
fa411a21 2169 group->conf->gtsm_hops = 0;
718e3744 2170 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
2171 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
2172 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
2173 group->conf->keepalive = 0;
2174 group->conf->holdtime = 0;
2175 group->conf->connect = 0;
2176 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
2177 listnode_add_sort (bgp->group, group);
2178
2179 return 0;
2180}
2181
94f2b392 2182static void
a4ed4829 2183peer_group2peer_config_copy (struct peer_group *group, struct peer *peer)
718e3744 2184{
718e3744 2185 struct peer *conf;
8ffedcea 2186 int v6only;
718e3744 2187
2188 conf = group->conf;
718e3744 2189
2190 /* remote-as */
2191 if (conf->as)
2192 peer->as = conf->as;
2193
2194 /* remote-as */
2195 if (conf->change_local_as)
2196 peer->change_local_as = conf->change_local_as;
2197
2198 /* TTL */
2199 peer->ttl = conf->ttl;
2200
fa411a21
NH
2201 /* GTSM hops */
2202 peer->gtsm_hops = conf->gtsm_hops;
2203
8ffedcea
DS
2204 /* this flag is per-neighbor and so has to be preserved */
2205 v6only = CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
2206
718e3744 2207 /* peer flags apply */
2208 peer->flags = conf->flags;
8ffedcea
DS
2209
2210 if (v6only)
2211 SET_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY);
2212
718e3744 2213 /* peer config apply */
2214 peer->config = conf->config;
2215
2216 /* peer timers apply */
2217 peer->holdtime = conf->holdtime;
2218 peer->keepalive = conf->keepalive;
2219 peer->connect = conf->connect;
2220 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
2221 peer->v_connect = conf->connect;
2222 else
2223 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
2224
2225 /* advertisement-interval reset */
966f821c
DS
2226 if (CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
2227 peer->v_routeadv = conf->routeadv;
718e3744 2228 else
966f821c
DS
2229 if (peer_sort (peer) == BGP_PEER_IBGP)
2230 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
2231 else
2232 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
718e3744 2233
0df7c91f 2234 /* password apply */
0e4303d3 2235 if (conf->password && !peer->password)
0df7c91f 2236 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
0df7c91f 2237
89ca90fa 2238 if (! BGP_PEER_SU_UNSPEC(peer))
2239 bgp_md5_set (peer);
0df7c91f 2240
718e3744 2241 /* update-source apply */
2242 if (conf->update_source)
2243 {
2244 if (peer->update_source)
2245 sockunion_free (peer->update_source);
2246 if (peer->update_if)
2247 {
2248 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2249 peer->update_if = NULL;
2250 }
2251 peer->update_source = sockunion_dup (conf->update_source);
2252 }
2253 else if (conf->update_if)
2254 {
2255 if (peer->update_if)
6e919709 2256 XFREE(MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
718e3744 2257 if (peer->update_source)
2258 {
2259 sockunion_free (peer->update_source);
2260 peer->update_source = NULL;
2261 }
2262 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
2263 }
8d78d851 2264
2265 bgp_bfd_peer_group2peer_copy(conf, peer);
a4ed4829
DW
2266}
2267
2268static void
2269peer_group2peer_config_copy_af (struct peer_group *group, struct peer *peer,
2270 afi_t afi, safi_t safi)
2271{
2272 int in = FILTER_IN;
2273 int out = FILTER_OUT;
2274 struct peer *conf;
2275 struct bgp_filter *pfilter;
2276 struct bgp_filter *gfilter;
2277
2278 conf = group->conf;
2279 pfilter = &peer->filter[afi][safi];
2280 gfilter = &conf->filter[afi][safi];
2281
2282 /* peer af_flags apply */
2283 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
2284
2285 /* maximum-prefix */
2286 peer->pmax[afi][safi] = conf->pmax[afi][safi];
2287 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
2288 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
2289
2290 /* allowas-in */
2291 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
2292
d93f7ffc
DW
2293 /* weight */
2294 peer->weight[afi][safi] = conf->weight[afi][safi];
2295
a4ed4829
DW
2296 /* default-originate route-map */
2297 if (conf->default_rmap[afi][safi].name)
2298 {
2299 if (peer->default_rmap[afi][safi].name)
2300 XFREE(MTYPE_BGP_FILTER_NAME, peer->default_rmap[afi][safi].name);
2301 peer->default_rmap[afi][safi].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, conf->default_rmap[afi][safi].name);
2302 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
2303 }
718e3744 2304
2305 /* inbound filter apply */
2306 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
2307 {
2308 if (pfilter->dlist[in].name)
6e919709
DS
2309 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->dlist[in].name);
2310 pfilter->dlist[in].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->dlist[in].name);
718e3744 2311 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
2312 }
a4ed4829 2313
718e3744 2314 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
2315 {
2316 if (pfilter->plist[in].name)
6e919709
DS
2317 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->plist[in].name);
2318 pfilter->plist[in].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->plist[in].name);
718e3744 2319 pfilter->plist[in].plist = gfilter->plist[in].plist;
2320 }
a4ed4829 2321
718e3744 2322 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
2323 {
2324 if (pfilter->aslist[in].name)
6e919709
DS
2325 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->aslist[in].name);
2326 pfilter->aslist[in].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->aslist[in].name);
718e3744 2327 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
2328 }
a4ed4829 2329
fee0f4c6 2330 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
718e3744 2331 {
fee0f4c6 2332 if (pfilter->map[RMAP_IN].name)
6e919709
DS
2333 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->map[RMAP_IN].name);
2334 pfilter->map[RMAP_IN].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->map[RMAP_IN].name);
fee0f4c6 2335 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
718e3744 2336 }
2337
2338 /* outbound filter apply */
2339 if (gfilter->dlist[out].name)
2340 {
2341 if (pfilter->dlist[out].name)
6e919709
DS
2342 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->dlist[out].name);
2343 pfilter->dlist[out].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->dlist[out].name);
718e3744 2344 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
2345 }
2346 else
2347 {
2348 if (pfilter->dlist[out].name)
6e919709 2349 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->dlist[out].name);
718e3744 2350 pfilter->dlist[out].name = NULL;
2351 pfilter->dlist[out].alist = NULL;
2352 }
a4ed4829 2353
718e3744 2354 if (gfilter->plist[out].name)
2355 {
2356 if (pfilter->plist[out].name)
6e919709
DS
2357 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->plist[out].name);
2358 pfilter->plist[out].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->plist[out].name);
718e3744 2359 pfilter->plist[out].plist = gfilter->plist[out].plist;
2360 }
2361 else
2362 {
2363 if (pfilter->plist[out].name)
6e919709 2364 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->plist[out].name);
718e3744 2365 pfilter->plist[out].name = NULL;
2366 pfilter->plist[out].plist = NULL;
2367 }
a4ed4829 2368
718e3744 2369 if (gfilter->aslist[out].name)
2370 {
2371 if (pfilter->aslist[out].name)
6e919709
DS
2372 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->aslist[out].name);
2373 pfilter->aslist[out].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->aslist[out].name);
718e3744 2374 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
2375 }
2376 else
2377 {
2378 if (pfilter->aslist[out].name)
6e919709 2379 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->aslist[out].name);
718e3744 2380 pfilter->aslist[out].name = NULL;
2381 pfilter->aslist[out].aslist = NULL;
2382 }
a4ed4829 2383
fee0f4c6 2384 if (gfilter->map[RMAP_OUT].name)
2385 {
2386 if (pfilter->map[RMAP_OUT].name)
6e919709
DS
2387 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->map[RMAP_OUT].name);
2388 pfilter->map[RMAP_OUT].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->map[RMAP_OUT].name);
fee0f4c6 2389 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
2390 }
2391 else
2392 {
2393 if (pfilter->map[RMAP_OUT].name)
6e919709 2394 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->map[RMAP_OUT].name);
fee0f4c6 2395 pfilter->map[RMAP_OUT].name = NULL;
2396 pfilter->map[RMAP_OUT].map = NULL;
2397 }
2398
718e3744 2399 if (gfilter->usmap.name)
2400 {
2401 if (pfilter->usmap.name)
6e919709
DS
2402 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->usmap.name);
2403 pfilter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->usmap.name);
718e3744 2404 pfilter->usmap.map = gfilter->usmap.map;
2405 }
2406 else
2407 {
2408 if (pfilter->usmap.name)
6e919709 2409 XFREE(MTYPE_BGP_FILTER_NAME, pfilter->usmap.name);
718e3744 2410 pfilter->usmap.name = NULL;
2411 pfilter->usmap.map = NULL;
2412 }
2413}
2414
2415/* Peer group's remote AS configuration. */
2416int
0299c004
DS
2417peer_group_remote_as (struct bgp *bgp, const char *group_name,
2418 as_t *as, int as_type)
718e3744 2419{
2420 struct peer_group *group;
2421 struct peer *peer;
1eb8ef25 2422 struct listnode *node, *nnode;
718e3744 2423
2424 group = peer_group_lookup (bgp, group_name);
2425 if (! group)
2426 return -1;
2427
0299c004 2428 if ((as_type == group->conf->as_type) && (group->conf->as == *as))
718e3744 2429 return 0;
2430
0299c004 2431
718e3744 2432 /* When we setup peer-group AS number all peer group member's AS
2433 number must be updated to same number. */
0299c004 2434 peer_as_change (group->conf, *as, as_type);
718e3744 2435
1eb8ef25 2436 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 2437 {
9da3a1a1
DS
2438 if (((peer->as_type == AS_SPECIFIED) && peer->as != *as) ||
2439 (peer->as_type != as_type))
0299c004 2440 peer_as_change (peer, *as, as_type);
718e3744 2441 }
2442
2443 return 0;
2444}
2445
2446int
2447peer_group_delete (struct peer_group *group)
2448{
2449 struct bgp *bgp;
2450 struct peer *peer;
f14e6fdb 2451 struct prefix *prefix;
1ff9a340 2452 struct peer *other;
1eb8ef25 2453 struct listnode *node, *nnode;
f14e6fdb 2454 afi_t afi;
718e3744 2455
2456 bgp = group->bgp;
2457
1eb8ef25 2458 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 2459 {
1ff9a340 2460 other = peer->doppelganger;
718e3744 2461 peer_delete (peer);
1ff9a340
DS
2462 if (other && other->status != Deleted)
2463 {
2464 other->group = NULL;
2465 peer_delete(other);
2466 }
718e3744 2467 }
2468 list_delete (group->peer);
2469
f14e6fdb
DS
2470 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2471 {
2472 for (ALL_LIST_ELEMENTS (group->listen_range[afi], node, nnode, prefix))
2473 {
2474 prefix_free(prefix);
2475 }
2476 list_delete (group->listen_range[afi]);
2477 }
2478
6e919709 2479 XFREE(MTYPE_BGP_PEER_HOST, group->name);
718e3744 2480 group->name = NULL;
2481
2482 group->conf->group = NULL;
2483 peer_delete (group->conf);
2484
2485 /* Delete from all peer_group list. */
2486 listnode_delete (bgp->group, group);
2487
7f342629 2488 bfd_info_free(&(group->conf->bfd_info));
c43ed2e4 2489
718e3744 2490 peer_group_free (group);
2491
2492 return 0;
2493}
2494
2495int
2496peer_group_remote_as_delete (struct peer_group *group)
2497{
1ff9a340 2498 struct peer *peer, *other;
1eb8ef25 2499 struct listnode *node, *nnode;
718e3744 2500
0299c004
DS
2501 if ((group->conf->as_type == AS_UNSPECIFIED) ||
2502 ((! group->conf->as) && (group->conf->as_type == AS_SPECIFIED)))
718e3744 2503 return 0;
2504
1eb8ef25 2505 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 2506 {
1ff9a340
DS
2507 other = peer->doppelganger;
2508
718e3744 2509 peer_delete (peer);
1ff9a340
DS
2510
2511 if (other && other->status != Deleted)
2512 {
2513 other->group = NULL;
2514 peer_delete(other);
2515 }
718e3744 2516 }
2517 list_delete_all_node (group->peer);
2518
2519 group->conf->as = 0;
0299c004 2520 group->conf->as_type = AS_UNSPECIFIED;
718e3744 2521
2522 return 0;
2523}
2524
f14e6fdb
DS
2525int
2526peer_group_listen_range_add (struct peer_group *group, struct prefix *range)
2527{
2528 struct prefix *prefix;
2529 struct listnode *node, *nnode;
2530 afi_t afi;
2531
2532 afi = family2afi(range->family);
2533
2534 /* Group needs remote AS configured. */
2aab8d2b 2535 if (group->conf->as_type == AS_UNSPECIFIED)
f14e6fdb
DS
2536 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
2537
2538 /* Ensure no duplicates. Currently we don't care about overlaps. */
2539 for (ALL_LIST_ELEMENTS (group->listen_range[afi], node, nnode, prefix))
2540 {
2541 if (prefix_same(range, prefix))
57e9ee0a 2542 return 0;
f14e6fdb
DS
2543 }
2544
2545 prefix = prefix_new();
2546 prefix_copy(prefix, range);
2547 listnode_add(group->listen_range[afi], prefix);
2548 return 0;
2549}
2550
2551int
2552peer_group_listen_range_del (struct peer_group *group, struct prefix *range)
2553{
40ee54a7 2554 struct prefix *prefix, prefix2;
f14e6fdb
DS
2555 struct listnode *node, *nnode;
2556 struct peer *peer;
2557 afi_t afi;
4690c7d7 2558 char buf[PREFIX2STR_BUFFER];
f14e6fdb
DS
2559
2560 afi = family2afi(range->family);
2561
2562 /* Identify the listen range. */
2563 for (ALL_LIST_ELEMENTS (group->listen_range[afi], node, nnode, prefix))
2564 {
2565 if (prefix_same(range, prefix))
2566 break;
2567 }
2568
2569 if (!prefix)
2570 return BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_NOT_FOUND;
2571
2572 prefix2str(prefix, buf, sizeof(buf));
2573
2574 /* Dispose off any dynamic neighbors that exist due to this listen range */
2575 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
2576 {
2577 if (!peer_dynamic_neighbor (peer))
2578 continue;
2579
40ee54a7
TT
2580 sockunion2hostprefix(&peer->su, &prefix2);
2581 if (prefix_match(prefix, &prefix2))
f14e6fdb
DS
2582 {
2583 if (bgp_debug_neighbor_events(peer))
2584 zlog_debug ("Deleting dynamic neighbor %s group %s upon "
2585 "delete of listen range %s",
2586 peer->host, group->name, buf);
2587 peer_delete (peer);
2588 }
2589 }
2590
2591 /* Get rid of the listen range */
2592 listnode_delete(group->listen_range[afi], prefix);
2593
2594 return 0;
2595}
2596
718e3744 2597/* Bind specified peer to peer group. */
2598int
a80beece 2599peer_group_bind (struct bgp *bgp, union sockunion *su, struct peer *peer,
c8560b44 2600 struct peer_group *group, as_t *as)
718e3744 2601{
718e3744 2602 int first_member = 0;
c8560b44
DW
2603 afi_t afi;
2604 safi_t safi;
b3a39dc5 2605 int cap_enhe_preset = 0;
718e3744 2606
2607 /* Lookup the peer. */
a80beece 2608 if (!peer)
c8560b44 2609 peer = peer_lookup (bgp, su);
718e3744 2610
c8560b44
DW
2611 /* The peer exist, bind it to the peer-group */
2612 if (peer)
718e3744 2613 {
c8560b44
DW
2614 /* When the peer already belongs to peer group, check the consistency. */
2615 if (peer_group_active (peer) && strcmp (peer->group->name, group->name) != 0)
4c48cf63 2616 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
718e3744 2617
c8560b44
DW
2618 /* The peer has not specified a remote-as, inherit it from the
2619 * peer-group */
2620 if (peer->as_type == AS_UNSPECIFIED)
2621 {
2622 peer->as_type = group->conf->as_type;
2623 peer->as = group->conf->as;
2624 }
200df115 2625
c8560b44
DW
2626 if (! group->conf->as)
2627 {
2628 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
2629 && peer_sort (group->conf) != peer_sort (peer))
2630 {
2631 if (as)
2632 *as = peer->as;
2633 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
2634 }
718e3744 2635
c8560b44
DW
2636 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
2637 first_member = 1;
2638 }
718e3744 2639
b3a39dc5
DD
2640 if (CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE))
2641 cap_enhe_preset = 1;
2642
a4ed4829
DW
2643 peer_group2peer_config_copy(group, peer);
2644
b3a39dc5
DD
2645 /*
2646 * Capability extended-nexthop is enabled for an interface neighbor by
2647 * default. So, fix that up here.
2648 */
2649 if (peer->ifp && cap_enhe_preset)
2650 peer_flag_set (peer, PEER_FLAG_CAPABILITY_ENHE);
2651
c8560b44
DW
2652 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2653 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2654 {
2655 if (group->conf->afc[afi][safi])
2656 {
2657 peer->afc[afi][safi] = 1;
718e3744 2658
c8560b44
DW
2659 if (peer_af_find(peer, afi, safi) || peer_af_create(peer, afi, safi))
2660 {
a4ed4829 2661 peer_group2peer_config_copy_af (group, peer, afi, safi);
c8560b44
DW
2662 }
2663 }
2664 }
718e3744 2665
c8560b44
DW
2666 if (peer->group)
2667 {
2668 assert (group && peer->group == group);
2669 }
2670 else
2671 {
0aaa34db
DS
2672 struct listnode *pn;
2673 pn = listnode_lookup (bgp->peer, peer);
2674 list_delete_node (bgp->peer, pn);
c8560b44 2675 peer->group = group;
0aaa34db 2676 listnode_add_sort (bgp->peer, peer);
718e3744 2677
c8560b44
DW
2678 peer = peer_lock (peer); /* group->peer list reference */
2679 listnode_add (group->peer, peer);
2680 }
0299c004 2681
c8560b44
DW
2682 if (first_member)
2683 {
2684 /* Advertisement-interval reset */
2685 if (! CHECK_FLAG (group->conf->config, PEER_CONFIG_ROUTEADV))
2686 {
2687 if (peer_sort (group->conf) == BGP_PEER_IBGP)
2688 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
2689 else
2690 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
2691 }
718e3744 2692
c8560b44
DW
2693 /* ebgp-multihop reset */
2694 if (peer_sort (group->conf) == BGP_PEER_IBGP)
9b1be336 2695 group->conf->ttl = MAXTTL;
718e3744 2696
c8560b44
DW
2697 /* local-as reset */
2698 if (peer_sort (group->conf) != BGP_PEER_EBGP)
2699 {
2700 group->conf->change_local_as = 0;
2701 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
2702 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
2703 }
2704 }
2705
2706 SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
2707
2708 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2709 {
2710 peer->last_reset = PEER_DOWN_RMAP_BIND;
2711 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2712 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2713 }
2714 else
2715 {
2716 bgp_session_reset(peer);
2717 }
3f9c7369 2718 }
c8560b44
DW
2719
2720 /* Create a new peer. */
2721 else
718e3744 2722 {
c8560b44
DW
2723 if ((group->conf->as_type == AS_SPECIFIED) && (! group->conf->as))
2724 {
2725 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
2726 }
2727
f813b13b 2728 peer = peer_create (su, NULL, bgp, bgp->as, group->conf->as, group->conf->as_type, 0, 0, group);
c8560b44 2729
ca058a30 2730 peer = peer_lock (peer); /* group->peer list reference */
718e3744 2731 listnode_add (group->peer, peer);
718e3744 2732
a4ed4829
DW
2733 peer_group2peer_config_copy(group, peer);
2734
c8560b44
DW
2735 /* If the peer-group is active for this afi/safi then activate for this peer */
2736 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2737 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2738 if (group->conf->afc[afi][safi])
2739 {
2740 peer->afc[afi][safi] = 1;
2741 peer_af_create(peer, afi, safi);
a4ed4829 2742 peer_group2peer_config_copy_af (group, peer, afi, safi);
c8560b44 2743 }
fee0f4c6 2744
c8560b44 2745 SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
718e3744 2746
c8560b44
DW
2747 /* Set up peer's events and timers. */
2748 if (peer_active (peer))
2749 bgp_timer_set (peer);
e0701b79 2750 }
718e3744 2751
2752 return 0;
2753}
2754
2755int
2756peer_group_unbind (struct bgp *bgp, struct peer *peer,
c8560b44 2757 struct peer_group *group)
718e3744 2758{
1ff9a340 2759 struct peer *other;
c8560b44
DW
2760 afi_t afi;
2761 safi_t safi;
718e3744 2762
2763 if (group != peer->group)
2764 return BGP_ERR_PEER_GROUP_MISMATCH;
2765
c8560b44
DW
2766 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2767 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2768 {
2769 if (peer->afc[afi][safi])
2770 {
2771 peer->afc[afi][safi] = 0;
2772 peer_af_flag_reset (peer, afi, safi);
718e3744 2773
c8560b44
DW
2774 if (peer_af_delete(peer, afi, safi) != 0)
2775 {
2776 zlog_err("couldn't delete af structure for peer %s", peer->host);
2777 }
2778 }
2779 }
2780
2781 assert (listnode_lookup (group->peer, peer));
2782 peer_unlock (peer); /* peer group list reference */
2783 listnode_delete (group->peer, peer);
2784 peer->group = NULL;
2785 other = peer->doppelganger;
2786
2787 if (group->conf->as)
718e3744 2788 {
c8560b44
DW
2789 peer_delete (peer);
2790 if (other && other->status != Deleted)
2791 {
2792 if (other->group)
2793 {
2794 peer_unlock(other);
2795 listnode_delete(group->peer, other);
2796 }
2797 other->group = NULL;
2798 peer_delete(other);
2799 }
2800 return 0;
718e3744 2801 }
2802
c8560b44
DW
2803 bgp_bfd_deregister_peer(peer);
2804 peer_global_config_reset (peer);
2805
6aa136f1 2806 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 2807 {
2808 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
2809 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2810 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2811 }
718e3744 2812 else
1ff9a340 2813 bgp_session_reset(peer);
718e3744 2814
2815 return 0;
2816}
6b0655a2 2817
fe7d2a48
DS
2818static int
2819bgp_startup_timer_expire (struct thread *thread)
2820{
2821 struct bgp *bgp;
2822
2823 bgp = THREAD_ARG (thread);
2824 bgp->t_startup = NULL;
2825
2826 return 0;
2827}
2828
718e3744 2829/* BGP instance creation by `router bgp' commands. */
94f2b392 2830static struct bgp *
ad4cbda1 2831bgp_create (as_t *as, const char *name, enum bgp_instance_type inst_type)
718e3744 2832{
2833 struct bgp *bgp;
2834 afi_t afi;
2835 safi_t safi;
2836
200df115 2837 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
2838 return NULL;
2839
ad4cbda1 2840 if (BGP_DEBUG (zebra, ZEBRA))
2841 {
2842 if (inst_type == BGP_INSTANCE_TYPE_DEFAULT)
2843 zlog_debug("Creating Default VRF, AS %u", *as);
2844 else
2845 zlog_debug("Creating %s %s, AS %u",
2846 (inst_type == BGP_INSTANCE_TYPE_VRF) ? "VRF" : "VIEW",
2847 name, *as);
2848 }
2849
0088b5dc 2850 bgp_lock (bgp);
ad4cbda1 2851 bgp->inst_type = inst_type;
5c81a5f3 2852 bgp->vrf_id = (inst_type == BGP_INSTANCE_TYPE_DEFAULT) ?
2853 VRF_DEFAULT : VRF_UNKNOWN;
6f58544d 2854 bgp->peer_self = peer_new (bgp);
6e919709
DS
2855 if (bgp->peer_self->host)
2856 XFREE(MTYPE_BGP_PEER_HOST, bgp->peer_self->host);
2857 bgp->peer_self->host = XSTRDUP(MTYPE_BGP_PEER_HOST, "Static announcement");
718e3744 2858 bgp->peer = list_new ();
2859 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
dd793e4a 2860 bgp->peerhash = hash_create (peer_hash_key_make, peer_hash_cmp);
718e3744 2861
2862 bgp->group = list_new ();
2863 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
2864
2865 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2866 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2867 {
64e580a7
PJ
2868 bgp->route[afi][safi] = bgp_table_init (afi, safi);
2869 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
2870 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
219178b6
DW
2871
2872 /* Enable maximum-paths */
d5b77cc2
DS
2873 bgp_maximum_paths_set (bgp, afi, safi, BGP_PEER_EBGP, MULTIPATH_NUM, 0);
2874 bgp_maximum_paths_set (bgp, afi, safi, BGP_PEER_IBGP, MULTIPATH_NUM, 0);
718e3744 2875 }
2876
f188f2c4 2877 bgp->v_update_delay = BGP_UPDATE_DELAY_DEF;
718e3744 2878 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
3f9c7369 2879 bgp->default_subgroup_pkt_queue_max = BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX;
718e3744 2880 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
2881 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
538621f2 2882 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
2883 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
f14e6fdb
DS
2884 bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT;
2885 bgp->dynamic_neighbors_count = 0;
5623e905 2886 bgp_flag_set (bgp, BGP_FLAG_IMPORT_CHECK);
15f3b5c0 2887 bgp_flag_set (bgp, BGP_FLAG_SHOW_HOSTNAME);
6793fbe0 2888 bgp_flag_set (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES);
1475ac87 2889 bgp_flag_set (bgp, BGP_FLAG_DETERMINISTIC_MED);
adbac85e 2890 bgp->addpath_tx_id = BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE;
718e3744 2891
2892 bgp->as = *as;
2893
65efcfce
LB
2894#if ENABLE_BGP_VNC
2895 bgp->rfapi = bgp_rfapi_new(bgp);
2896 assert(bgp->rfapi);
2897 assert(bgp->rfapi_cfg);
2898#endif /* ENABLE_BGP_VNC */
2899
718e3744 2900 if (name)
6aeb9e78
DS
2901 {
2902 bgp->name = XSTRDUP(MTYPE_BGP, name);
2903 }
2904 else
2905 {
ad4cbda1 2906 /* TODO - The startup timer needs to be run for the whole of BGP */
6aeb9e78
DS
2907 THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire,
2908 bgp, bgp->restart_time);
2909 }
718e3744 2910
cb1faec9 2911 bgp->wpkt_quanta = BGP_WRITE_PACKET_MAX;
3f9c7369 2912 bgp->coalesce_time = BGP_DEFAULT_SUBGROUP_COALESCE_TIME;
cb1faec9 2913
6aeb9e78
DS
2914 update_bgp_group_init(bgp);
2915 return bgp;
2916}
2917
ad4cbda1 2918/* Return the "default VRF" instance of BGP. */
718e3744 2919struct bgp *
94f2b392 2920bgp_get_default (void)
718e3744 2921{
ad4cbda1 2922 struct bgp *bgp;
2923 struct listnode *node, *nnode;
2924
2925 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
2926 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
2927 return bgp;
718e3744 2928 return NULL;
2929}
2930
2931/* Lookup BGP entry. */
2932struct bgp *
fd79ac91 2933bgp_lookup (as_t as, const char *name)
718e3744 2934{
2935 struct bgp *bgp;
1eb8ef25 2936 struct listnode *node, *nnode;
718e3744 2937
1eb8ef25 2938 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
718e3744 2939 if (bgp->as == as
2940 && ((bgp->name == NULL && name == NULL)
2941 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
2942 return bgp;
2943 return NULL;
2944}
2945
2946/* Lookup BGP structure by view name. */
2947struct bgp *
fd79ac91 2948bgp_lookup_by_name (const char *name)
718e3744 2949{
2950 struct bgp *bgp;
1eb8ef25 2951 struct listnode *node, *nnode;
718e3744 2952
1eb8ef25 2953 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
718e3744 2954 if ((bgp->name == NULL && name == NULL)
2955 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2956 return bgp;
2957 return NULL;
2958}
2959
d1be1f08 2960/* Lookup BGP instance based on VRF id. */
2961/* Note: Only to be used for incoming messages from Zebra. */
6aeb9e78
DS
2962struct bgp *
2963bgp_lookup_by_vrf_id (vrf_id_t vrf_id)
ad4cbda1 2964{
2965 struct vrf *vrf;
2966
d1be1f08 2967 /* Lookup VRF (in tree) and follow link. */
2968 vrf = vrf_lookup (vrf_id);
ad4cbda1 2969 if (!vrf)
d1be1f08 2970 return NULL;
2971 return (vrf->info) ? (struct bgp *)vrf->info : NULL;
ad4cbda1 2972}
2973
718e3744 2974/* Called from VTY commands. */
2975int
ad4cbda1 2976bgp_get (struct bgp **bgp_val, as_t *as, const char *name,
2977 enum bgp_instance_type inst_type)
718e3744 2978{
2979 struct bgp *bgp;
2980
2981 /* Multiple instance check. */
2982 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2983 {
2984 if (name)
2985 bgp = bgp_lookup_by_name (name);
2986 else
2987 bgp = bgp_get_default ();
2988
2989 /* Already exists. */
2990 if (bgp)
2991 {
2992 if (bgp->as != *as)
2993 {
2994 *as = bgp->as;
2995 return BGP_ERR_INSTANCE_MISMATCH;
2996 }
ad4cbda1 2997 if (bgp->inst_type != inst_type)
2998 return BGP_ERR_INSTANCE_MISMATCH;
718e3744 2999 *bgp_val = bgp;
3000 return 0;
3001 }
3002 }
3003 else
3004 {
3005 /* BGP instance name can not be specified for single instance. */
3006 if (name)
3007 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
3008
3009 /* Get default BGP structure if exists. */
3010 bgp = bgp_get_default ();
3011
3012 if (bgp)
3013 {
3014 if (bgp->as != *as)
3015 {
3016 *as = bgp->as;
3017 return BGP_ERR_AS_MISMATCH;
3018 }
3019 *bgp_val = bgp;
3020 return 0;
3021 }
3022 }
3023
ad4cbda1 3024 bgp = bgp_create (as, name, inst_type);
6aeb9e78
DS
3025 bgp_router_id_set(bgp, &bgp->router_id_zebra);
3026 bgp_address_init (bgp);
3027 bgp_scan_init (bgp);
1758dbaa
SA
3028 *bgp_val = bgp;
3029
0de4848d 3030 bgp->t_rmap_def_originate_eval = NULL;
518f0eb1 3031
ad12dde6 3032 /* Create BGP server socket, if first instance. */
cccbc015
PJ
3033 if (list_isempty(bm->bgp)
3034 && !bgp_option_check (BGP_OPT_NO_LISTEN))
ad12dde6
PJ
3035 {
3036 if (bgp_socket (bm->port, bm->address) < 0)
3037 return BGP_ERR_INVALID_VALUE;
3038 }
3039
718e3744 3040 listnode_add (bm->bgp, bgp);
718e3744 3041
d1be1f08 3042 /* If Default instance or VRF, link to the VRF structure, if present. */
3043 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT ||
3044 bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
3045 {
3046 struct vrf *vrf;
3047
3048 vrf = bgp_vrf_lookup_by_instance_type (bgp);
3049 if (vrf)
b33adb7c 3050 {
3051 bgp_vrf_link (bgp, vrf);
3052 bgp_if_init (bgp);
3053 }
d1be1f08 3054 }
ad4cbda1 3055
3056 /* Register with Zebra, if needed */
3057 if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
3058 bgp_zebra_instance_register (bgp);
3059
6aeb9e78 3060
718e3744 3061 return 0;
3062}
3063
ad4cbda1 3064/*
3065 * Make BGP instance "up". Applies only to VRFs (non-default) and
3066 * implies the VRF has been learnt from Zebra.
3067 */
6aeb9e78 3068void
ad4cbda1 3069bgp_instance_up (struct bgp *bgp)
718e3744 3070{
3071 struct peer *peer;
ad4cbda1 3072 struct listnode *node, *next;
718e3744 3073
ad4cbda1 3074 /* Register with zebra. */
3075 bgp_zebra_instance_register (bgp);
d4a7a753 3076
ad4cbda1 3077 /* Kick off any peers that may have been configured. */
cd92e548
DS
3078 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
3079 {
ad4cbda1 3080 if (!BGP_PEER_START_SUPPRESSED (peer))
3081 BGP_EVENT_ADD (peer, BGP_Start);
cd92e548
DS
3082 }
3083
ad4cbda1 3084 /* Process any networks that have been configured. */
3085 bgp_static_add (bgp);
3086}
718e3744 3087
ad4cbda1 3088/*
3089 * Make BGP instance "down". Applies only to VRFs (non-default) and
3090 * implies the VRF has been deleted by Zebra.
3091 */
3092void
3093bgp_instance_down (struct bgp *bgp)
3094{
3095 struct peer *peer;
3096 struct listnode *node;
3097 struct listnode *next;
718e3744 3098
ad4cbda1 3099 /* Stop timers. */
ad4cbda1 3100 if (bgp->t_rmap_def_originate_eval)
6aa136f1 3101 {
ad4cbda1 3102 BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval);
3103 bgp_unlock(bgp); /* TODO - This timer is started with a lock - why? */
6aa136f1 3104 }
228da428 3105
ad4cbda1 3106 /* Bring down peers, so corresponding routes are purged. */
1ff9a340
DS
3107 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
3108 {
3109 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
ad4cbda1 3110 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
3111 else
3112 bgp_session_reset(peer);
6aeb9e78
DS
3113 }
3114
ad4cbda1 3115 /* Purge network and redistributed routes. */
3116 bgp_purge_static_redist_routes (bgp);
6aeb9e78 3117}
1ff9a340 3118
6aeb9e78
DS
3119/* Delete BGP instance. */
3120int
3121bgp_delete (struct bgp *bgp)
3122{
3123 struct peer *peer;
3124 struct peer_group *group;
3125 struct listnode *node, *next;
3126 afi_t afi;
3127 int i;
3128
7cb43556 3129 THREAD_OFF (bgp->t_startup);
3130
ad4cbda1 3131 if (BGP_DEBUG (zebra, ZEBRA))
3132 {
3133 if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
3134 zlog_debug("Deleting Default VRF");
3135 else
3136 zlog_debug("Deleting %s %s",
3137 (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) ? "VRF" : "VIEW",
3138 bgp->name);
3139 }
3140
3141 /* Stop timers. */
ad4cbda1 3142 if (bgp->t_rmap_def_originate_eval)
3143 {
3144 BGP_TIMER_OFF(bgp->t_rmap_def_originate_eval);
3145 bgp_unlock(bgp); /* TODO - This timer is started with a lock - why? */
3146 }
3147
3148 /* Inform peers we're going down. */
3149 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
3150 {
3151 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3152 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
3153 }
7cb43556 3154
ad4cbda1 3155 /* Delete static routes (networks). */
6aeb9e78
DS
3156 bgp_static_delete (bgp);
3157
3158 /* Unset redistribution. */
3159 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3160 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
3161 if (i != ZEBRA_ROUTE_BGP)
3162 bgp_redistribute_unset (bgp, afi, i, 0);
3163
ad4cbda1 3164 /* Free peers and peer-groups. */
6aeb9e78 3165 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
ad4cbda1 3166 peer_group_delete (group);
6aeb9e78
DS
3167
3168 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
ad4cbda1 3169 peer_delete (peer);
1ff9a340 3170
0088b5dc
SH
3171 if (bgp->peer_self) {
3172 peer_delete(bgp->peer_self);
3173 bgp->peer_self = NULL;
3174 }
0de4848d 3175
3d68677e 3176 update_bgp_group_free (bgp);
ad4cbda1 3177
3178 /* TODO - Other memory may need to be freed - e.g., NHT */
3179
65efcfce
LB
3180#if ENABLE_BGP_VNC
3181 rfapi_delete(bgp);
3182 bgp_cleanup_routes(); /* rfapi cleanup can create route entries! */
3183#endif
3184
fd35b948
PJ
3185 /* Remove visibility via the master list - there may however still be
3186 * routes to be processed still referencing the struct bgp.
3187 */
3188 listnode_delete (bm->bgp, bgp);
d023aec4
SH
3189 if (list_isempty(bm->bgp))
3190 bgp_close ();
3191
ad4cbda1 3192 /* Deregister from Zebra, if needed */
3193 if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp))
3194 bgp_zebra_instance_deregister (bgp);
3195
009b18fc 3196 /* Free interfaces in this instance. */
3197 bgp_if_finish (bgp);
3198
87d4a781 3199 thread_master_free_unused(bm->master);
0088b5dc 3200 bgp_unlock(bgp); /* initial reference */
6410e93a 3201
0088b5dc
SH
3202 return 0;
3203}
3204
3205static void bgp_free (struct bgp *);
3206
3207void
3208bgp_lock (struct bgp *bgp)
3209{
3210 ++bgp->lock;
3211}
3212
3213void
3214bgp_unlock(struct bgp *bgp)
3215{
228da428 3216 assert(bgp->lock > 0);
0088b5dc
SH
3217 if (--bgp->lock == 0)
3218 bgp_free (bgp);
3219}
3220
3221static void
3222bgp_free (struct bgp *bgp)
3223{
3224 afi_t afi;
3225 safi_t safi;
d3f5a0d3 3226 struct vrf *vrf;
0088b5dc
SH
3227
3228 list_delete (bgp->group);
3229 list_delete (bgp->peer);
3ffe142a
DW
3230
3231 if (bgp->peerhash)
3232 {
3233 hash_free(bgp->peerhash);
3234 bgp->peerhash = NULL;
3235 }
fee0f4c6 3236
718e3744 3237 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3238 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3239 {
3240 if (bgp->route[afi][safi])
228da428 3241 bgp_table_finish (&bgp->route[afi][safi]);
718e3744 3242 if (bgp->aggregate[afi][safi])
228da428 3243 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
718e3744 3244 if (bgp->rib[afi][safi])
228da428 3245 bgp_table_finish (&bgp->rib[afi][safi]);
718e3744 3246 }
d3f5a0d3 3247
5e6d589c
DS
3248 bgp_address_destroy (bgp);
3249
d3f5a0d3 3250 /* If Default instance or VRF, unlink from the VRF structure. */
3251 vrf = bgp_vrf_lookup_by_instance_type (bgp);
3252 if (vrf)
3253 bgp_vrf_unlink (bgp, vrf);
3254
4ac82321 3255 if (bgp->name)
3256 XFREE(MTYPE_BGP, bgp->name);
3257
718e3744 3258 XFREE (MTYPE_BGP, bgp);
718e3744 3259}
6b0655a2 3260
a80beece
DS
3261struct peer *
3262peer_lookup_by_conf_if (struct bgp *bgp, const char *conf_if)
3263{
3264 struct peer *peer;
3265 struct listnode *node, *nnode;
3266
3267 if (!conf_if)
3268 return NULL;
3269
3270 if (bgp != NULL)
3271 {
3272 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
3273 if (peer->conf_if && !strcmp(peer->conf_if, conf_if)
3274 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
3275 return peer;
3276 }
3277 else if (bm->bgp != NULL)
3278 {
3279 struct listnode *bgpnode, *nbgpnode;
3280
3281 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
3282 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
3283 if (peer->conf_if && !strcmp(peer->conf_if, conf_if)
3284 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
3285 return peer;
3286 }
3287 return NULL;
3288}
3289
04b6bdc0
DW
3290struct peer *
3291peer_lookup_by_hostname (struct bgp *bgp, const char *hostname)
3292{
3293 struct peer *peer;
3294 struct listnode *node, *nnode;
3295
3296 if (!hostname)
3297 return NULL;
3298
3299 if (bgp != NULL)
3300 {
3301 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
3302 if (peer->hostname && !strcmp(peer->hostname, hostname)
3303 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
3304 return peer;
3305 }
3306 else if (bm->bgp != NULL)
3307 {
3308 struct listnode *bgpnode, *nbgpnode;
3309
3310 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
3311 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
3312 if (peer->hostname && !strcmp(peer->hostname, hostname)
3313 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
3314 return peer;
3315 }
3316 return NULL;
3317}
3318
718e3744 3319struct peer *
3320peer_lookup (struct bgp *bgp, union sockunion *su)
3321{
dd793e4a
DW
3322 struct peer *peer = NULL;
3323 struct peer tmp_peer;
3324
3325 memset(&tmp_peer, 0, sizeof(struct peer));
3326
3327 /*
3328 * We do not want to find the doppelganger peer so search for the peer in
3329 * the hash that has PEER_FLAG_CONFIG_NODE
3330 */
3331 SET_FLAG (tmp_peer.flags, PEER_FLAG_CONFIG_NODE);
3332
3333 tmp_peer.su = *su;
718e3744 3334
fc4dc59d 3335 if (bgp != NULL)
fc4dc59d 3336 {
dd793e4a 3337 peer = hash_lookup(bgp->peerhash, &tmp_peer);
fc4dc59d 3338 }
fc4dc59d 3339 else if (bm->bgp != NULL)
718e3744 3340 {
2158ad23
PJ
3341 struct listnode *bgpnode, *nbgpnode;
3342
3343 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
dd793e4a 3344 {
ad4cbda1 3345 /* Skip VRFs, this function will not be invoked without an instance
3346 * when examining VRFs.
6aeb9e78 3347 */
ad4cbda1 3348 if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
6aeb9e78
DS
3349 continue;
3350
dd793e4a
DW
3351 peer = hash_lookup(bgp->peerhash, &tmp_peer);
3352
3353 if (peer)
3354 break;
3355 }
fc4dc59d 3356 }
dd793e4a
DW
3357
3358 return peer;
718e3744 3359}
3360
f14e6fdb
DS
3361struct peer *
3362peer_create_bind_dynamic_neighbor (struct bgp *bgp, union sockunion *su,
3363 struct peer_group *group)
3364{
3365 struct peer *peer;
3366 afi_t afi;
3367 safi_t safi;
f14e6fdb
DS
3368
3369 /* Create peer first; we've already checked group config is valid. */
f813b13b 3370 peer = peer_create (su, NULL, bgp, bgp->as, group->conf->as, group->conf->as_type, 0, 0, group);
f14e6fdb
DS
3371 if (!peer)
3372 return NULL;
3373
3374 /* Link to group */
f14e6fdb
DS
3375 peer = peer_lock (peer);
3376 listnode_add (group->peer, peer);
3377
a4ed4829
DW
3378 peer_group2peer_config_copy(group, peer);
3379
f14e6fdb
DS
3380 /*
3381 * Bind peer for all AFs configured for the group. We don't call
3382 * peer_group_bind as that is sub-optimal and does some stuff we don't want.
3383 */
3384 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3385 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3386 {
3387 if (!group->conf->afc[afi][safi])
3388 continue;
f14e6fdb 3389 peer->afc[afi][safi] = 1;
c8560b44
DW
3390
3391 if (!peer_af_find(peer, afi, safi))
3392 peer_af_create(peer, afi, safi);
3393
a4ed4829 3394 peer_group2peer_config_copy_af (group, peer, afi, safi);
f14e6fdb
DS
3395 }
3396
3397 /* Mark as dynamic, but also as a "config node" for other things to work. */
3398 SET_FLAG(peer->flags, PEER_FLAG_DYNAMIC_NEIGHBOR);
3399 SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
3400
3401 return peer;
3402}
3403
3404struct prefix *
3405peer_group_lookup_dynamic_neighbor_range (struct peer_group * group,
3406 struct prefix * prefix)
3407{
3408 struct listnode *node, *nnode;
3409 struct prefix *range;
3410 afi_t afi;
3411
3412 afi = family2afi(prefix->family);
3413
3414 if (group->listen_range[afi])
3415 for (ALL_LIST_ELEMENTS (group->listen_range[afi], node, nnode, range))
3416 if (prefix_match(range, prefix))
3417 return range;
3418
3419 return NULL;
3420}
3421
3422struct peer_group *
3423peer_group_lookup_dynamic_neighbor (struct bgp *bgp, struct prefix *prefix,
3424 struct prefix **listen_range)
3425{
3426 struct prefix *range = NULL;
3427 struct peer_group *group = NULL;
3428 struct listnode *node, *nnode;
3429
3430 *listen_range = NULL;
3431 if (bgp != NULL)
3432 {
3433 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
3434 if ((range = peer_group_lookup_dynamic_neighbor_range(group, prefix)))
3435 break;
3436 }
3437 else if (bm->bgp != NULL)
3438 {
3439 struct listnode *bgpnode, *nbgpnode;
3440
3441 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
3442 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
3443 if ((range = peer_group_lookup_dynamic_neighbor_range(group, prefix)))
2aab8d2b 3444 goto found_range;
f14e6fdb
DS
3445 }
3446
2aab8d2b 3447 found_range:
f14e6fdb
DS
3448 *listen_range = range;
3449 return (group && range) ? group : NULL;
3450}
3451
3452struct peer *
3453peer_lookup_dynamic_neighbor (struct bgp *bgp, union sockunion *su)
3454{
3455 struct peer_group *group;
3456 struct bgp *gbgp;
3457 struct peer *peer;
40ee54a7 3458 struct prefix prefix;
f14e6fdb
DS
3459 struct prefix *listen_range;
3460 int dncount;
4690c7d7
DS
3461 char buf[PREFIX2STR_BUFFER];
3462 char buf1[PREFIX2STR_BUFFER];
f14e6fdb 3463
40ee54a7 3464 sockunion2hostprefix(su, &prefix);
f14e6fdb
DS
3465
3466 /* See if incoming connection matches a configured listen range. */
40ee54a7 3467 group = peer_group_lookup_dynamic_neighbor (bgp, &prefix, &listen_range);
f14e6fdb
DS
3468
3469 if (! group)
3470 return NULL;
3471
0299c004 3472
f14e6fdb
DS
3473 gbgp = group->bgp;
3474
3475 if (! gbgp)
3476 return NULL;
3477
40ee54a7 3478 prefix2str(&prefix, buf, sizeof(buf));
f14e6fdb
DS
3479 prefix2str(listen_range, buf1, sizeof(buf1));
3480
3481 if (bgp_debug_neighbor_events(NULL))
3482 zlog_debug ("Dynamic Neighbor %s matches group %s listen range %s",
3483 buf, group->name, buf1);
3484
3485 /* Are we within the listen limit? */
3486 dncount = gbgp->dynamic_neighbors_count;
3487
3488 if (dncount >= gbgp->dynamic_neighbors_limit)
3489 {
3490 if (bgp_debug_neighbor_events(NULL))
3491 zlog_debug ("Dynamic Neighbor %s rejected - at limit %d",
3492 inet_sutop (su, buf), gbgp->dynamic_neighbors_limit);
3493 return NULL;
3494 }
3495
3496 /* Ensure group is not disabled. */
3497 if (CHECK_FLAG (group->conf->flags, PEER_FLAG_SHUTDOWN))
3498 {
3499 if (bgp_debug_neighbor_events(NULL))
3500 zlog_debug ("Dynamic Neighbor %s rejected - group %s disabled",
3501 buf, group->name);
3502 return NULL;
3503 }
3504
3505 /* Check that at least one AF is activated for the group. */
3506 if (!peer_group_af_configured (group))
3507 {
3508 if (bgp_debug_neighbor_events(NULL))
3509 zlog_debug ("Dynamic Neighbor %s rejected - no AF activated for group %s",
3510 buf, group->name);
3511 return NULL;
3512 }
3513
3514 /* Create dynamic peer and bind to associated group. */
3515 peer = peer_create_bind_dynamic_neighbor (gbgp, su, group);
3516 assert (peer);
3517
3518 gbgp->dynamic_neighbors_count = ++dncount;
3519
3520 if (bgp_debug_neighbor_events(peer))
3521 zlog_debug ("%s Dynamic Neighbor added, group %s count %d",
3522 peer->host, group->name, dncount);
3523
3524 return peer;
3525}
3526
3527void peer_drop_dynamic_neighbor (struct peer *peer)
3528{
3529 int dncount = -1;
3530 if (peer->group && peer->group->bgp)
3531 {
3532 dncount = peer->group->bgp->dynamic_neighbors_count;
3533 if (dncount)
3534 peer->group->bgp->dynamic_neighbors_count = --dncount;
3535 }
3536 if (bgp_debug_neighbor_events(peer))
3537 zlog_debug ("%s dropped from group %s, count %d",
3538 peer->host, peer->group->name, dncount);
3539}
3540
3541
718e3744 3542/* If peer is configured at least one address family return 1. */
3543int
3544peer_active (struct peer *peer)
3545{
a80beece
DS
3546 if (BGP_PEER_SU_UNSPEC(peer))
3547 return 0;
718e3744 3548 if (peer->afc[AFI_IP][SAFI_UNICAST]
3549 || peer->afc[AFI_IP][SAFI_MULTICAST]
3550 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
587ff0fd 3551 || peer->afc[AFI_IP][SAFI_ENCAP]
718e3744 3552 || peer->afc[AFI_IP6][SAFI_UNICAST]
945c8fe9 3553 || peer->afc[AFI_IP6][SAFI_MULTICAST]
587ff0fd
LB
3554 || peer->afc[AFI_IP6][SAFI_MPLS_VPN]
3555 || peer->afc[AFI_IP6][SAFI_ENCAP])
718e3744 3556 return 1;
3557 return 0;
3558}
3559
3560/* If peer is negotiated at least one address family return 1. */
3561int
3562peer_active_nego (struct peer *peer)
3563{
3564 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
3565 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
3566 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
587ff0fd 3567 || peer->afc_nego[AFI_IP][SAFI_ENCAP]
718e3744 3568 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
945c8fe9 3569 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
587ff0fd
LB
3570 || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
3571 || peer->afc_nego[AFI_IP6][SAFI_ENCAP])
718e3744 3572 return 1;
3573 return 0;
3574}
6b0655a2 3575
718e3744 3576/* peer_flag_change_type. */
3577enum peer_change_type
3578{
3579 peer_change_none,
3580 peer_change_reset,
3581 peer_change_reset_in,
3582 peer_change_reset_out,
3583};
3584
94f2b392 3585static void
718e3744 3586peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
3587 enum peer_change_type type)
3588{
3589 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3590 return;
3591
d9d4ae51
SH
3592 if (peer->status != Established)
3593 return;
3594
718e3744 3595 if (type == peer_change_reset)
1ff9a340
DS
3596 {
3597 /* If we're resetting session, we've to delete both peer struct */
3598 if ((peer->doppelganger) && (peer->doppelganger->status != Deleted)
3599 && (!CHECK_FLAG(peer->doppelganger->flags,
3600 PEER_FLAG_CONFIG_NODE)))
3601 peer_delete(peer->doppelganger);
3602
3603 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3604 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3605 }
718e3744 3606 else if (type == peer_change_reset_in)
3607 {
3608 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
3609 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
3610 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
3611 else
1ff9a340
DS
3612 {
3613 if ((peer->doppelganger) && (peer->doppelganger->status != Deleted)
3614 && (!CHECK_FLAG(peer->doppelganger->flags,
3615 PEER_FLAG_CONFIG_NODE)))
3616 peer_delete(peer->doppelganger);
3617
3618 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3619 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3620 }
718e3744 3621 }
3622 else if (type == peer_change_reset_out)
3f9c7369
DS
3623 {
3624 update_group_adjust_peer(peer_af_find(peer, afi, safi));
3625 bgp_announce_route (peer, afi, safi);
3626 }
718e3744 3627}
3628
3629struct peer_flag_action
3630{
3631 /* Peer's flag. */
3632 u_int32_t flag;
3633
3634 /* This flag can be set for peer-group member. */
3635 u_char not_for_member;
3636
3637 /* Action when the flag is changed. */
3638 enum peer_change_type type;
e0701b79 3639
3640 /* Peer down cause */
3641 u_char peer_down;
718e3744 3642};
3643
03621955 3644static const struct peer_flag_action peer_flag_action_list[] =
718e3744 3645 {
3646 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
3647 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
3648 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
3649 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
3650 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
718e3744 3651 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
6ffd2079 3652 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
8a92a8a0 3653 { PEER_FLAG_CAPABILITY_ENHE, 0, peer_change_reset },
718e3744 3654 { 0, 0, 0 }
3655 };
3656
03621955 3657static const struct peer_flag_action peer_af_flag_action_list[] =
718e3744 3658 {
718e3744 3659 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
3660 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
adbac85e 3661 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
718e3744 3662 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
3663 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
adbac85e 3664 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
718e3744 3665 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
3666 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
3667 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
adbac85e 3668 // PEER_FLAG_DEFAULT_ORIGINATE
718e3744 3669 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
3670 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
3671 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
3672 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
adbac85e
DW
3673 // PEER_FLAG_MAX_PREFIX
3674 // PEER_FLAG_MAX_PREFIX_WARNING
fee0f4c6 3675 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
a538debe 3676 { PEER_FLAG_FORCE_NEXTHOP_SELF, 1, peer_change_reset_out },
adbac85e
DW
3677 { PEER_FLAG_REMOVE_PRIVATE_AS_ALL, 1, peer_change_reset_out },
3678 { PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE,1, peer_change_reset_out },
c7122e14 3679 { PEER_FLAG_AS_OVERRIDE, 1, peer_change_reset_out },
88b8ed8d 3680 { PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE,1, peer_change_reset_out },
adbac85e 3681 { PEER_FLAG_ADDPATH_TX_ALL_PATHS, 1, peer_change_reset },
06370dac 3682 { PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS, 1, peer_change_reset },
d93f7ffc 3683 { PEER_FLAG_WEIGHT, 0, peer_change_reset_in },
718e3744 3684 { 0, 0, 0 }
3685 };
3686
3687/* Proper action set. */
94f2b392 3688static int
03621955 3689peer_flag_action_set (const struct peer_flag_action *action_list, int size,
718e3744 3690 struct peer_flag_action *action, u_int32_t flag)
3691{
3692 int i;
3693 int found = 0;
3694 int reset_in = 0;
3695 int reset_out = 0;
03621955 3696 const struct peer_flag_action *match = NULL;
718e3744 3697
3698 /* Check peer's frag action. */
3699 for (i = 0; i < size; i++)
3700 {
3701 match = &action_list[i];
3702
3703 if (match->flag == 0)
3704 break;
3705
3706 if (match->flag & flag)
3707 {
3708 found = 1;
3709
3710 if (match->type == peer_change_reset_in)
3711 reset_in = 1;
3712 if (match->type == peer_change_reset_out)
3713 reset_out = 1;
3714 if (match->type == peer_change_reset)
3715 {
3716 reset_in = 1;
3717 reset_out = 1;
3718 }
3719 if (match->not_for_member)
3720 action->not_for_member = 1;
3721 }
3722 }
3723
3724 /* Set peer clear type. */
3725 if (reset_in && reset_out)
3726 action->type = peer_change_reset;
3727 else if (reset_in)
3728 action->type = peer_change_reset_in;
3729 else if (reset_out)
3730 action->type = peer_change_reset_out;
3731 else
3732 action->type = peer_change_none;
3733
3734 return found;
3735}
3736
94f2b392 3737static void
718e3744 3738peer_flag_modify_action (struct peer *peer, u_int32_t flag)
3739{
3740 if (flag == PEER_FLAG_SHUTDOWN)
3741 {
3742 if (CHECK_FLAG (peer->flags, flag))
3743 {
93406d87 3744 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
3745 peer_nsf_stop (peer);
3746
0a486e5f 3747 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3748 if (peer->t_pmax_restart)
3749 {
3750 BGP_TIMER_OFF (peer->t_pmax_restart);
16286195 3751 if (bgp_debug_neighbor_events(peer))
0a486e5f 3752 zlog_debug ("%s Maximum-prefix restart timer canceled",
3753 peer->host);
3754 }
3755
1ff9a340
DS
3756 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
3757 peer_nsf_stop (peer);
93406d87 3758
6aa136f1 3759 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
718e3744 3760 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3761 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
3762 else
1ff9a340 3763 bgp_session_reset(peer);
718e3744 3764 }
3765 else
3766 {
3767 peer->v_start = BGP_INIT_START_TIMER;
3768 BGP_EVENT_ADD (peer, BGP_Stop);
3769 }
3770 }
6aa136f1 3771 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
718e3744 3772 {
c9502438 3773 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
3774 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
3775 else if (flag == PEER_FLAG_PASSIVE)
3776 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
6ffd2079 3777 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
c9502438 3778 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
e0701b79 3779
c9502438 3780 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3781 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
718e3744 3782 }
3783 else
1ff9a340 3784 bgp_session_reset(peer);
718e3744 3785}
3786
3787/* Change specified peer flag. */
94f2b392 3788static int
718e3744 3789peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
3790{
3791 int found;
3792 int size;
3793 struct peer_group *group;
a4ed4829 3794 struct peer *tmp_peer;
1eb8ef25 3795 struct listnode *node, *nnode;
718e3744 3796 struct peer_flag_action action;
3797
3798 memset (&action, 0, sizeof (struct peer_flag_action));
3799 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
3800
3801 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
3802
3803 /* No flag action is found. */
3804 if (! found)
3805 return BGP_ERR_INVALID_FLAG;
3806
718e3744 3807 /* When unset the peer-group member's flag we have to check
3808 peer-group configuration. */
3809 if (! set && peer_group_active (peer))
3810 if (CHECK_FLAG (peer->group->conf->flags, flag))
3811 {
3812 if (flag == PEER_FLAG_SHUTDOWN)
3813 return BGP_ERR_PEER_GROUP_SHUTDOWN;
718e3744 3814 }
3815
3816 /* Flag conflict check. */
3817 if (set
3818 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
3819 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
3820 return BGP_ERR_PEER_FLAG_CONFLICT;
3821
3822 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3823 {
3824 if (set && CHECK_FLAG (peer->flags, flag) == flag)
3825 return 0;
3826 if (! set && ! CHECK_FLAG (peer->flags, flag))
3827 return 0;
3828 }
3829
3830 if (set)
3831 SET_FLAG (peer->flags, flag);
3832 else
3833 UNSET_FLAG (peer->flags, flag);
3834
3835 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3836 {
3837 if (action.type == peer_change_reset)
3838 peer_flag_modify_action (peer, flag);
3839
3840 return 0;
3841 }
3842
3843 /* peer-group member updates. */
3844 group = peer->group;
3845
a4ed4829 3846 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, tmp_peer))
718e3744 3847 {
a4ed4829 3848
1a79ce38 3849 if (set && CHECK_FLAG (tmp_peer->flags, flag) == flag)
718e3744 3850 continue;
3851
1a79ce38 3852 if (! set && ! CHECK_FLAG (tmp_peer->flags, flag))
718e3744 3853 continue;
3854
3855 if (set)
a4ed4829 3856 SET_FLAG (tmp_peer->flags, flag);
718e3744 3857 else
a4ed4829 3858 UNSET_FLAG (tmp_peer->flags, flag);
718e3744 3859
3860 if (action.type == peer_change_reset)
a4ed4829 3861 peer_flag_modify_action (tmp_peer, flag);
718e3744 3862 }
3863 return 0;
3864}
3865
3866int
3867peer_flag_set (struct peer *peer, u_int32_t flag)
3868{
3869 return peer_flag_modify (peer, flag, 1);
3870}
3871
3872int
3873peer_flag_unset (struct peer *peer, u_int32_t flag)
3874{
3875 return peer_flag_modify (peer, flag, 0);
3876}
3877
94f2b392 3878static int
718e3744 3879peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
3880 int set)
3881{
3882 int found;
3883 int size;
1eb8ef25 3884 struct listnode *node, *nnode;
718e3744 3885 struct peer_group *group;
3886 struct peer_flag_action action;
adbac85e
DW
3887 struct peer *tmp_peer;
3888 struct bgp *bgp;
3889 int addpath_tx_used;
718e3744 3890
3891 memset (&action, 0, sizeof (struct peer_flag_action));
3892 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
3893
3894 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
3895
3896 /* No flag action is found. */
3897 if (! found)
3898 return BGP_ERR_INVALID_FLAG;
3899
400b1fad 3900 /* Special check for reflector client. */
718e3744 3901 if (flag & PEER_FLAG_REFLECTOR_CLIENT
3902 && peer_sort (peer) != BGP_PEER_IBGP)
3903 return BGP_ERR_NOT_INTERNAL_PEER;
3904
400b1fad 3905 /* Special check for remove-private-AS. */
718e3744 3906 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
3907 && peer_sort (peer) == BGP_PEER_IBGP)
3908 return BGP_ERR_REMOVE_PRIVATE_AS;
3909
c7122e14
DS
3910 /* as-override is not allowed for IBGP peers */
3911 if (flag & PEER_FLAG_AS_OVERRIDE
3912 && peer_sort (peer) == BGP_PEER_IBGP)
3913 return BGP_ERR_AS_OVERRIDE;
3914
718e3744 3915 /* When current flag configuration is same as requested one. */
3916 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3917 {
3918 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
3919 return 0;
3920 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
3921 return 0;
3922 }
3923
3924 if (set)
3925 SET_FLAG (peer->af_flags[afi][safi], flag);
3926 else
3927 UNSET_FLAG (peer->af_flags[afi][safi], flag);
3928
3929 /* Execute action when peer is established. */
3930 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3931 && peer->status == Established)
3932 {
3933 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
3934 bgp_clear_adj_in (peer, afi, safi);
3935 else
e0701b79 3936 {
3937 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
3938 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
3939 else if (flag == PEER_FLAG_RSERVER_CLIENT)
3940 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
3941 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
3942 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
3943 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
3944 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
3945
3946 peer_change_action (peer, afi, safi, action.type);
3947 }
3948
718e3744 3949 }
3950
3951 /* Peer group member updates. */
3952 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3953 {
3954 group = peer->group;
3955
adbac85e 3956 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, tmp_peer))
718e3744 3957 {
adbac85e 3958 if (set && CHECK_FLAG (tmp_peer->af_flags[afi][safi], flag) == flag)
718e3744 3959 continue;
3960
adbac85e 3961 if (! set && ! CHECK_FLAG (tmp_peer->af_flags[afi][safi], flag))
718e3744 3962 continue;
3963
3964 if (set)
adbac85e 3965 SET_FLAG (tmp_peer->af_flags[afi][safi], flag);
718e3744 3966 else
adbac85e 3967 UNSET_FLAG (tmp_peer->af_flags[afi][safi], flag);
718e3744 3968
adbac85e 3969 if (tmp_peer->status == Established)
718e3744 3970 {
3971 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
adbac85e 3972 bgp_clear_adj_in (tmp_peer, afi, safi);
718e3744 3973 else
e0701b79 3974 {
3975 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
adbac85e 3976 tmp_peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
e0701b79 3977 else if (flag == PEER_FLAG_RSERVER_CLIENT)
adbac85e 3978 tmp_peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
e0701b79 3979 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
adbac85e 3980 tmp_peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
e0701b79 3981 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
adbac85e 3982 tmp_peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
e0701b79 3983
adbac85e 3984 peer_change_action (tmp_peer, afi, safi, action.type);
e0701b79 3985 }
718e3744 3986 }
3987 }
3988 }
adbac85e
DW
3989
3990 /* Track if addpath TX is in use */
06370dac 3991 if (flag & (PEER_FLAG_ADDPATH_TX_ALL_PATHS|PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS))
adbac85e
DW
3992 {
3993 bgp = peer->bgp;
3994 addpath_tx_used = 0;
3995
3996 if (set)
3997 {
3998 addpath_tx_used = 1;
06370dac
DW
3999
4000 if (flag & PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS)
4001 {
4002 if (!bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
4003 {
4004 zlog_warn("%s: enabling bgp deterministic-med, this is required"\
4005 " for addpath-tx-bestpath-per-AS",
4006 peer->host);
4007 bgp_flag_set (bgp, BGP_FLAG_DETERMINISTIC_MED);
4008 bgp_recalculate_all_bestpaths (bgp);
4009 }
4010 }
adbac85e
DW
4011 }
4012 else
4013 {
4014 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, tmp_peer))
4015 {
06370dac
DW
4016 if (CHECK_FLAG (tmp_peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_ALL_PATHS) ||
4017 CHECK_FLAG (tmp_peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS))
adbac85e
DW
4018 {
4019 addpath_tx_used = 1;
4020 break;
4021 }
4022 }
4023 }
4024
4025 bgp->addpath_tx_used[afi][safi] = addpath_tx_used;
4026 }
4027
718e3744 4028 return 0;
4029}
4030
4031int
4032peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
4033{
4034 return peer_af_flag_modify (peer, afi, safi, flag, 1);
4035}
4036
4037int
4038peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
4039{
4040 return peer_af_flag_modify (peer, afi, safi, flag, 0);
4041}
6b0655a2 4042
718e3744 4043/* EBGP multihop configuration. */
4044int
4045peer_ebgp_multihop_set (struct peer *peer, int ttl)
4046{
4047 struct peer_group *group;
1eb8ef25 4048 struct listnode *node, *nnode;
fa411a21 4049 struct peer *peer1;
718e3744 4050
a80beece 4051 if (peer->sort == BGP_PEER_IBGP || peer->conf_if)
718e3744 4052 return 0;
4053
fa411a21
NH
4054 /* see comment in peer_ttl_security_hops_set() */
4055 if (ttl != MAXTTL)
4056 {
4057 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4058 {
4059 group = peer->group;
4060 if (group->conf->gtsm_hops != 0)
4061 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4062
4063 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4064 {
6d85b15b 4065 if (peer1->sort == BGP_PEER_IBGP)
fa411a21
NH
4066 continue;
4067
4068 if (peer1->gtsm_hops != 0)
4069 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4070 }
4071 }
4072 else
4073 {
4074 if (peer->gtsm_hops != 0)
4075 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4076 }
4077 }
4078
718e3744 4079 peer->ttl = ttl;
4080
4081 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4082 {
6d85b15b 4083 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
e5cc509c
DS
4084 {
4085 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4086 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4087 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4088 else
4089 bgp_session_reset(peer);
4090 }
718e3744 4091 }
4092 else
4093 {
4094 group = peer->group;
1eb8ef25 4095 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
eb821189 4096 {
6d85b15b 4097 if (peer->sort == BGP_PEER_IBGP)
eb821189 4098 continue;
718e3744 4099
eb821189 4100 peer->ttl = group->conf->ttl;
718e3744 4101
e5cc509c
DS
4102 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4103 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4104 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4105 else
4106 bgp_session_reset(peer);
eb821189 4107 }
718e3744 4108 }
4109 return 0;
4110}
4111
4112int
4113peer_ebgp_multihop_unset (struct peer *peer)
4114{
4115 struct peer_group *group;
1eb8ef25 4116 struct listnode *node, *nnode;
718e3744 4117
6d85b15b 4118 if (peer->sort == BGP_PEER_IBGP)
718e3744 4119 return 0;
4120
fa411a21
NH
4121 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
4122 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4123
718e3744 4124 if (peer_group_active (peer))
4125 peer->ttl = peer->group->conf->ttl;
4126 else
4127 peer->ttl = 1;
4128
4129 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4130 {
e5cc509c
DS
4131 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4132 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4133 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4134 else
4135 bgp_session_reset(peer);
718e3744 4136 }
4137 else
4138 {
4139 group = peer->group;
1eb8ef25 4140 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
eb821189 4141 {
6d85b15b 4142 if (peer->sort == BGP_PEER_IBGP)
eb821189 4143 continue;
4144
4145 peer->ttl = 1;
e5cc509c 4146
eb821189 4147 if (peer->fd >= 0)
e5cc509c
DS
4148 {
4149 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
4150 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4151 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4152 else
4153 bgp_session_reset(peer);
4154 }
eb821189 4155 }
718e3744 4156 }
4157 return 0;
4158}
6b0655a2 4159
718e3744 4160/* Neighbor description. */
4161int
4760600f 4162peer_description_set (struct peer *peer, const char *desc)
718e3744 4163{
4164 if (peer->desc)
4165 XFREE (MTYPE_PEER_DESC, peer->desc);
4166
4167 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
4168
4169 return 0;
4170}
4171
4172int
4173peer_description_unset (struct peer *peer)
4174{
4175 if (peer->desc)
4176 XFREE (MTYPE_PEER_DESC, peer->desc);
4177
4178 peer->desc = NULL;
4179
4180 return 0;
4181}
6b0655a2 4182
718e3744 4183/* Neighbor update-source. */
4184int
fd79ac91 4185peer_update_source_if_set (struct peer *peer, const char *ifname)
718e3744 4186{
4187 struct peer_group *group;
1eb8ef25 4188 struct listnode *node, *nnode;
718e3744 4189
4190 if (peer->update_if)
4191 {
4192 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
4193 && strcmp (peer->update_if, ifname) == 0)
4194 return 0;
4195
4196 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
4197 peer->update_if = NULL;
4198 }
4199
4200 if (peer->update_source)
4201 {
4202 sockunion_free (peer->update_source);
4203 peer->update_source = NULL;
4204 }
4205
4206 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
4207
4208 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4209 {
6aa136f1 4210 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4211 {
4212 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4213 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4214 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4215 }
718e3744 4216 else
1ff9a340 4217 bgp_session_reset(peer);
718e3744 4218 return 0;
4219 }
4220
4221 /* peer-group member updates. */
4222 group = peer->group;
1eb8ef25 4223 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4224 {
4225 if (peer->update_if)
4226 {
4227 if (strcmp (peer->update_if, ifname) == 0)
4228 continue;
4229
4230 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
4231 peer->update_if = NULL;
4232 }
4233
4234 if (peer->update_source)
4235 {
4236 sockunion_free (peer->update_source);
4237 peer->update_source = NULL;
4238 }
4239
4240 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
4241
6aa136f1 4242 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4243 {
4244 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4245 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4246 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4247 }
718e3744 4248 else
1ff9a340 4249 bgp_session_reset(peer);
718e3744 4250 }
4251 return 0;
4252}
4253
4254int
4760600f 4255peer_update_source_addr_set (struct peer *peer, const union sockunion *su)
718e3744 4256{
4257 struct peer_group *group;
1eb8ef25 4258 struct listnode *node, *nnode;
718e3744 4259
4260 if (peer->update_source)
4261 {
4262 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
4263 && sockunion_cmp (peer->update_source, su) == 0)
4264 return 0;
4265 sockunion_free (peer->update_source);
4266 peer->update_source = NULL;
4267 }
4268
4269 if (peer->update_if)
4270 {
4271 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
4272 peer->update_if = NULL;
1ff9a340 4273
718e3744 4274 }
4275
4276 peer->update_source = sockunion_dup (su);
4277
4278 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4279 {
6aa136f1 4280 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4281 {
4282 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4283 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4284 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4285 }
718e3744 4286 else
1ff9a340 4287 bgp_session_reset(peer);
718e3744 4288 return 0;
4289 }
4290
4291 /* peer-group member updates. */
4292 group = peer->group;
1eb8ef25 4293 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4294 {
4295 if (peer->update_source)
4296 {
4297 if (sockunion_cmp (peer->update_source, su) == 0)
4298 continue;
4299 sockunion_free (peer->update_source);
4300 peer->update_source = NULL;
4301 }
4302
4303 if (peer->update_if)
4304 {
4305 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
4306 peer->update_if = NULL;
4307 }
4308
4309 peer->update_source = sockunion_dup (su);
4310
6aa136f1 4311 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4312 {
4313 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4314 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4315 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4316 }
718e3744 4317 else
1ff9a340 4318 bgp_session_reset(peer);
718e3744 4319 }
4320 return 0;
4321}
4322
4323int
4324peer_update_source_unset (struct peer *peer)
4325{
4326 union sockunion *su;
4327 struct peer_group *group;
1eb8ef25 4328 struct listnode *node, *nnode;
718e3744 4329
4330 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
4331 && ! peer->update_source
4332 && ! peer->update_if)
4333 return 0;
4334
4335 if (peer->update_source)
4336 {
4337 sockunion_free (peer->update_source);
4338 peer->update_source = NULL;
4339 }
4340 if (peer->update_if)
4341 {
4342 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
4343 peer->update_if = NULL;
4344 }
4345
4346 if (peer_group_active (peer))
4347 {
4348 group = peer->group;
4349
4350 if (group->conf->update_source)
4351 {
4352 su = sockunion_dup (group->conf->update_source);
4353 peer->update_source = su;
4354 }
4355 else if (group->conf->update_if)
4356 peer->update_if =
4357 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
4358 }
4359
4360 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4361 {
6aa136f1 4362 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4363 {
4364 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4365 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4366 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4367 }
718e3744 4368 else
1ff9a340 4369 bgp_session_reset(peer);
718e3744 4370 return 0;
4371 }
4372
4373 /* peer-group member updates. */
4374 group = peer->group;
1eb8ef25 4375 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4376 {
4377 if (! peer->update_source && ! peer->update_if)
4378 continue;
4379
4380 if (peer->update_source)
4381 {
4382 sockunion_free (peer->update_source);
4383 peer->update_source = NULL;
4384 }
4385
4386 if (peer->update_if)
4387 {
4388 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
4389 peer->update_if = NULL;
4390 }
4391
6aa136f1 4392 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4393 {
4394 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
4395 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4396 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4397 }
718e3744 4398 else
1ff9a340 4399 bgp_session_reset(peer);
718e3744 4400 }
4401 return 0;
4402}
6b0655a2 4403
718e3744 4404int
4405peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
fd79ac91 4406 const char *rmap)
718e3744 4407{
4408 struct peer_group *group;
1eb8ef25 4409 struct listnode *node, *nnode;
718e3744 4410
718e3744 4411 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
4412 || (rmap && ! peer->default_rmap[afi][safi].name)
4413 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
4414 {
4415 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
4416
4417 if (rmap)
4418 {
4419 if (peer->default_rmap[afi][safi].name)
6e919709
DS
4420 XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name);
4421 peer->default_rmap[afi][safi].name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
718e3744 4422 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
4423 }
4424 }
4425
4426 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4427 {
3f9c7369
DS
4428 if (peer->status == Established && peer->afc_nego[afi][safi]) {
4429 update_group_adjust_peer(peer_af_find(peer, afi, safi));
718e3744 4430 bgp_default_originate (peer, afi, safi, 0);
3f9c7369
DS
4431 bgp_announce_route (peer, afi, safi);
4432 }
718e3744 4433 return 0;
4434 }
4435
4436 /* peer-group member updates. */
4437 group = peer->group;
1eb8ef25 4438 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4439 {
4440 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
4441
4442 if (rmap)
4443 {
4444 if (peer->default_rmap[afi][safi].name)
6e919709
DS
4445 XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name);
4446 peer->default_rmap[afi][safi].name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
718e3744 4447 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
4448 }
4449
3f9c7369
DS
4450 if (peer->status == Established && peer->afc_nego[afi][safi]) {
4451 update_group_adjust_peer(peer_af_find(peer, afi, safi));
718e3744 4452 bgp_default_originate (peer, afi, safi, 0);
3f9c7369
DS
4453 bgp_announce_route (peer, afi, safi);
4454 }
718e3744 4455 }
4456 return 0;
4457}
4458
4459int
4460peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
4461{
4462 struct peer_group *group;
1eb8ef25 4463 struct listnode *node, *nnode;
718e3744 4464
718e3744 4465 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
4466 {
4467 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
4468
4469 if (peer->default_rmap[afi][safi].name)
6e919709 4470 XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name);
718e3744 4471 peer->default_rmap[afi][safi].name = NULL;
4472 peer->default_rmap[afi][safi].map = NULL;
4473 }
4474
4475 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4476 {
3f9c7369
DS
4477 if (peer->status == Established && peer->afc_nego[afi][safi]) {
4478 update_group_adjust_peer(peer_af_find(peer, afi, safi));
718e3744 4479 bgp_default_originate (peer, afi, safi, 1);
3f9c7369
DS
4480 bgp_announce_route (peer, afi, safi);
4481 }
718e3744 4482 return 0;
4483 }
4484
4485 /* peer-group member updates. */
4486 group = peer->group;
1eb8ef25 4487 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4488 {
4489 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
4490
4491 if (peer->default_rmap[afi][safi].name)
6e919709 4492 XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name);
718e3744 4493 peer->default_rmap[afi][safi].name = NULL;
4494 peer->default_rmap[afi][safi].map = NULL;
4495
3f9c7369
DS
4496 if (peer->status == Established && peer->afc_nego[afi][safi]) {
4497 update_group_adjust_peer(peer_af_find(peer, afi, safi));
718e3744 4498 bgp_default_originate (peer, afi, safi, 1);
3f9c7369
DS
4499 bgp_announce_route (peer, afi, safi);
4500 }
718e3744 4501 }
4502 return 0;
4503}
6b0655a2 4504
718e3744 4505int
4506peer_port_set (struct peer *peer, u_int16_t port)
4507{
4508 peer->port = port;
4509 return 0;
4510}
4511
4512int
4513peer_port_unset (struct peer *peer)
4514{
4515 peer->port = BGP_PORT_DEFAULT;
4516 return 0;
4517}
6b0655a2 4518
d93f7ffc
DW
4519/*
4520 * Helper function that is called after the name of the policy
4521 * being used by a peer has changed (AF specific). Automatically
4522 * initiates inbound or outbound processing as needed.
4523 */
4524static void
4525peer_on_policy_change (struct peer *peer, afi_t afi, safi_t safi, int outbound)
4526{
4527 if (outbound)
4528 {
4529 update_group_adjust_peer (peer_af_find (peer, afi, safi));
4530 if (peer->status == Established)
4531 bgp_announce_route(peer, afi, safi);
4532 }
4533 else
4534 {
4535 if (peer->status != Established)
4536 return;
4537
4538 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4539 bgp_soft_reconfig_in (peer, afi, safi);
4540 else if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4541 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4542 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4543 }
4544}
4545
4546
718e3744 4547/* neighbor weight. */
1f9a9fff 4548int
d93f7ffc 4549peer_weight_set (struct peer *peer, afi_t afi, safi_t safi, u_int16_t weight)
718e3744 4550{
4551 struct peer_group *group;
1eb8ef25 4552 struct listnode *node, *nnode;
718e3744 4553
d93f7ffc
DW
4554 if (peer->weight[afi][safi] != weight)
4555 {
4556 peer->weight[afi][safi] = weight;
4557 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_WEIGHT);
4558 peer_on_policy_change (peer, afi, safi, 0);
4559 }
718e3744 4560
4561 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1f9a9fff 4562 return 0;
718e3744 4563
4564 /* peer-group member updates. */
4565 group = peer->group;
1eb8ef25 4566 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4567 {
d93f7ffc
DW
4568 if (peer->weight[afi][safi] != weight)
4569 {
4570 peer->weight[afi][safi] = weight;
4571 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_WEIGHT);
4572 peer_on_policy_change (peer, afi, safi, 0);
4573 }
718e3744 4574 }
d93f7ffc 4575 return 0;
718e3744 4576}
4577
1f9a9fff 4578int
d93f7ffc 4579peer_weight_unset (struct peer *peer, afi_t afi, safi_t safi)
718e3744 4580{
4581 struct peer_group *group;
1eb8ef25 4582 struct listnode *node, *nnode;
718e3744 4583
d93f7ffc
DW
4584 /* not the peer-group itself but a peer in a peer-group */
4585 if (peer_group_active(peer))
4586 {
4587 group = peer->group;
718e3744 4588
d93f7ffc
DW
4589 /* inherit weight from the peer-group */
4590 if (CHECK_FLAG (group->conf->af_flags[afi][safi], PEER_FLAG_WEIGHT))
4591 {
4592 peer->weight[afi][safi] = group->conf->weight[afi][safi];
4593 peer_af_flag_set (peer, afi, safi, PEER_FLAG_WEIGHT);
4594 peer_on_policy_change (peer, afi, safi, 0);
4595 }
4596 else
4597 {
4598 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_WEIGHT))
4599 {
4600 peer->weight[afi][safi] = 0;
4601 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_WEIGHT);
4602 peer_on_policy_change (peer, afi, safi, 0);
4603 }
4604 }
4605 }
718e3744 4606
d93f7ffc 4607 else
718e3744 4608 {
d93f7ffc
DW
4609 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_WEIGHT))
4610 {
4611 peer->weight[afi][safi] = 0;
4612 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_WEIGHT);
4613 peer_on_policy_change (peer, afi, safi, 0);
4614 }
4615
4616 /* peer-group member updates. */
4617 group = peer->group;
4618
4619 if (group)
4620 {
4621 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4622 {
4623 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_WEIGHT))
4624 {
4625 peer->weight[afi][safi] = 0;
4626 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_WEIGHT);
4627 peer_on_policy_change (peer, afi, safi, 0);
4628 }
4629 }
4630 }
718e3744 4631 }
d93f7ffc 4632 return 0;
718e3744 4633}
6b0655a2 4634
718e3744 4635int
4636peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
4637{
4638 struct peer_group *group;
1eb8ef25 4639 struct listnode *node, *nnode;
718e3744 4640
718e3744 4641 /* keepalive value check. */
4642 if (keepalive > 65535)
4643 return BGP_ERR_INVALID_VALUE;
4644
4645 /* Holdtime value check. */
4646 if (holdtime > 65535)
4647 return BGP_ERR_INVALID_VALUE;
4648
4649 /* Holdtime value must be either 0 or greater than 3. */
4650 if (holdtime < 3 && holdtime != 0)
4651 return BGP_ERR_INVALID_VALUE;
4652
4653 /* Set value to the configuration. */
4654 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
4655 peer->holdtime = holdtime;
4656 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
4657
4658 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4659 return 0;
4660
4661 /* peer-group member updates. */
4662 group = peer->group;
1eb8ef25 4663 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4664 {
4665 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
4666 peer->holdtime = group->conf->holdtime;
4667 peer->keepalive = group->conf->keepalive;
4668 }
4669 return 0;
4670}
4671
4672int
4673peer_timers_unset (struct peer *peer)
4674{
4675 struct peer_group *group;
1eb8ef25 4676 struct listnode *node, *nnode;
718e3744 4677
718e3744 4678 /* Clear configuration. */
4679 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
4680 peer->keepalive = 0;
4681 peer->holdtime = 0;
4682
4683 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4684 return 0;
4685
4686 /* peer-group member updates. */
4687 group = peer->group;
1eb8ef25 4688 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4689 {
4690 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
4691 peer->holdtime = 0;
4692 peer->keepalive = 0;
4693 }
4694
4695 return 0;
4696}
6b0655a2 4697
718e3744 4698int
4699peer_timers_connect_set (struct peer *peer, u_int32_t connect)
4700{
966f821c
DS
4701 struct peer_group *group;
4702 struct listnode *node, *nnode;
4703
718e3744 4704 if (connect > 65535)
4705 return BGP_ERR_INVALID_VALUE;
4706
4707 /* Set value to the configuration. */
4708 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
4709 peer->connect = connect;
4710
4711 /* Set value to timer setting. */
4712 peer->v_connect = connect;
4713
966f821c
DS
4714 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4715 return 0;
4716
4717 /* peer-group member updates. */
4718 group = peer->group;
4719 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4720 {
4721 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
4722 peer->connect = connect;
4723 peer->v_connect = connect;
4724 }
718e3744 4725 return 0;
4726}
4727
4728int
4729peer_timers_connect_unset (struct peer *peer)
4730{
966f821c
DS
4731 struct peer_group *group;
4732 struct listnode *node, *nnode;
4733
718e3744 4734 /* Clear configuration. */
4735 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
4736 peer->connect = 0;
4737
4738 /* Set timer setting to default value. */
4739 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
4740
966f821c
DS
4741 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4742 return 0;
4743
4744 /* peer-group member updates. */
4745 group = peer->group;
4746 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4747 {
4748 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
4749 peer->connect = 0;
4750 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
4751 }
718e3744 4752 return 0;
4753}
6b0655a2 4754
718e3744 4755int
4756peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
4757{
966f821c
DS
4758 struct peer_group *group;
4759 struct listnode *node, *nnode;
4760
718e3744 4761 if (routeadv > 600)
4762 return BGP_ERR_INVALID_VALUE;
4763
4764 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
4765 peer->routeadv = routeadv;
4766 peer->v_routeadv = routeadv;
4767
3f9c7369
DS
4768 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) {
4769 update_group_adjust_peer_afs (peer);
4770 if (peer->status == Established)
4771 bgp_announce_route_all (peer);
966f821c 4772 return 0;
3f9c7369 4773 }
966f821c
DS
4774
4775 /* peer-group member updates. */
4776 group = peer->group;
4777 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4778 {
4779 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
4780 peer->routeadv = routeadv;
4781 peer->v_routeadv = routeadv;
3f9c7369
DS
4782 update_group_adjust_peer_afs (peer);
4783 if (peer->status == Established)
4784 bgp_announce_route_all (peer);
966f821c
DS
4785 }
4786
718e3744 4787 return 0;
4788}
4789
4790int
4791peer_advertise_interval_unset (struct peer *peer)
4792{
966f821c
DS
4793 struct peer_group *group;
4794 struct listnode *node, *nnode;
4795
718e3744 4796 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
4797 peer->routeadv = 0;
4798
6d85b15b 4799 if (peer->sort == BGP_PEER_IBGP)
718e3744 4800 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
4801 else
4802 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
966f821c 4803
3f9c7369
DS
4804 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) {
4805 update_group_adjust_peer_afs (peer);
4806 if (peer->status == Established)
4807 bgp_announce_route_all (peer);
966f821c 4808 return 0;
3f9c7369 4809 }
966f821c
DS
4810
4811 /* peer-group member updates. */
4812 group = peer->group;
4813 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4814 {
4815 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
4816 peer->routeadv = 0;
4817
4818 if (peer->sort == BGP_PEER_IBGP)
4819 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
4820 else
4821 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3f9c7369
DS
4822
4823 update_group_adjust_peer_afs (peer);
4824 if (peer->status == Established)
4825 bgp_announce_route_all (peer);
966f821c 4826 }
718e3744 4827
4828 return 0;
4829}
6b0655a2 4830
718e3744 4831/* neighbor interface */
ffd0c037 4832void
fd79ac91 4833peer_interface_set (struct peer *peer, const char *str)
718e3744 4834{
4835 if (peer->ifname)
6e919709
DS
4836 XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
4837 peer->ifname = XSTRDUP(MTYPE_BGP_PEER_IFNAME, str);
718e3744 4838}
4839
ffd0c037 4840void
718e3744 4841peer_interface_unset (struct peer *peer)
4842{
4843 if (peer->ifname)
6e919709 4844 XFREE(MTYPE_BGP_PEER_IFNAME, peer->ifname);
718e3744 4845 peer->ifname = NULL;
718e3744 4846}
6b0655a2 4847
718e3744 4848/* Allow-as in. */
4849int
4850peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
4851{
4852 struct peer_group *group;
1eb8ef25 4853 struct listnode *node, *nnode;
718e3744 4854
4855 if (allow_num < 1 || allow_num > 10)
4856 return BGP_ERR_INVALID_VALUE;
4857
4858 if (peer->allowas_in[afi][safi] != allow_num)
4859 {
4860 peer->allowas_in[afi][safi] = allow_num;
4861 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
d93f7ffc 4862 peer_on_policy_change (peer, afi, safi, 0);
718e3744 4863 }
4864
4865 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4866 return 0;
4867
4868 group = peer->group;
1eb8ef25 4869 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4870 {
4871 if (peer->allowas_in[afi][safi] != allow_num)
4872 {
4873 peer->allowas_in[afi][safi] = allow_num;
4874 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
d93f7ffc 4875 peer_on_policy_change (peer, afi, safi, 0);
718e3744 4876 }
4877
4878 }
4879 return 0;
4880}
4881
4882int
4883peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
4884{
4885 struct peer_group *group;
1eb8ef25 4886 struct listnode *node, *nnode;
718e3744 4887
4888 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
4889 {
4890 peer->allowas_in[afi][safi] = 0;
4891 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
d93f7ffc 4892 peer_on_policy_change (peer, afi, safi, 0);
718e3744 4893 }
4894
4895 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4896 return 0;
4897
4898 group = peer->group;
1eb8ef25 4899 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4900 {
4901 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
4902 {
4903 peer->allowas_in[afi][safi] = 0;
4904 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
d93f7ffc 4905 peer_on_policy_change (peer, afi, safi, 0);
718e3744 4906 }
4907 }
4908 return 0;
4909}
6b0655a2 4910
718e3744 4911int
9d3f9705 4912peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
718e3744 4913{
4914 struct bgp *bgp = peer->bgp;
4915 struct peer_group *group;
1eb8ef25 4916 struct listnode *node, *nnode;
718e3744 4917
4918 if (peer_sort (peer) != BGP_PEER_EBGP
4919 && peer_sort (peer) != BGP_PEER_INTERNAL)
4920 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
4921
4922 if (bgp->as == as)
4923 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
4924
9d3f9705
AC
4925 if (peer->as == as)
4926 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
4927
718e3744 4928 if (peer->change_local_as == as &&
4929 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
9d3f9705
AC
4930 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
4931 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
4932 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
718e3744 4933 return 0;
4934
4935 peer->change_local_as = as;
4936 if (no_prepend)
4937 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4938 else
4939 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4940
9d3f9705
AC
4941 if (replace_as)
4942 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4943 else
4944 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4945
718e3744 4946 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4947 {
6aa136f1 4948 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4949 {
4950 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
4951 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4952 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4953 }
718e3744 4954 else
1ff9a340 4955 bgp_session_reset(peer);
718e3744 4956 return 0;
4957 }
4958
4959 group = peer->group;
1eb8ef25 4960 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 4961 {
4962 peer->change_local_as = as;
4963 if (no_prepend)
4964 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4965 else
4966 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
4967
9d3f9705
AC
4968 if (replace_as)
4969 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4970 else
4971 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
4972
6aa136f1 4973 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 4974 {
4975 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
4976 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4977 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
4978 }
718e3744 4979 else
4980 BGP_EVENT_ADD (peer, BGP_Stop);
4981 }
4982
4983 return 0;
4984}
4985
4986int
4987peer_local_as_unset (struct peer *peer)
4988{
4989 struct peer_group *group;
1eb8ef25 4990 struct listnode *node, *nnode;
718e3744 4991
718e3744 4992 if (! peer->change_local_as)
4993 return 0;
4994
4995 peer->change_local_as = 0;
4996 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
9d3f9705 4997 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
718e3744 4998
4999 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5000 {
6aa136f1 5001 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 5002 {
5003 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
5004 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5005 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5006 }
718e3744 5007 else
5008 BGP_EVENT_ADD (peer, BGP_Stop);
5009
5010 return 0;
5011 }
5012
5013 group = peer->group;
1eb8ef25 5014 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5015 {
5016 peer->change_local_as = 0;
5017 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
9d3f9705 5018 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
718e3744 5019
6aa136f1 5020 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
e0701b79 5021 {
5022 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
5023 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5024 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5025 }
718e3744 5026 else
1ff9a340 5027 bgp_session_reset(peer);
718e3744 5028 }
5029 return 0;
5030}
6b0655a2 5031
0df7c91f
PJ
5032/* Set password for authenticating with the peer. */
5033int
5034peer_password_set (struct peer *peer, const char *password)
5035{
5036 struct listnode *nn, *nnode;
5037 int len = password ? strlen(password) : 0;
5038 int ret = BGP_SUCCESS;
5039
5040 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
5041 return BGP_ERR_INVALID_VALUE;
5042
5043 if (peer->password && strcmp (peer->password, password) == 0
5044 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5045 return 0;
5046
5047 if (peer->password)
5048 XFREE (MTYPE_PEER_PASSWORD, peer->password);
5049
5050 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
5051
5052 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5053 {
6aa136f1
VS
5054 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
5055 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
0df7c91f 5056 else
1ff9a340 5057 bgp_session_reset(peer);
0df7c91f 5058
89ca90fa 5059 if (BGP_PEER_SU_UNSPEC(peer))
5060 return BGP_SUCCESS;
5061
0df7c91f
PJ
5062 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
5063 }
5064
5065 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
5066 {
5067 if (peer->password && strcmp (peer->password, password) == 0)
5068 continue;
5069
5070 if (peer->password)
5071 XFREE (MTYPE_PEER_PASSWORD, peer->password);
5072
5073 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
5074
6aa136f1 5075 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
0df7c91f
PJ
5076 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5077 else
1ff9a340 5078 bgp_session_reset(peer);
0df7c91f 5079
89ca90fa 5080 if (! BGP_PEER_SU_UNSPEC(peer))
5081 {
5082 if (bgp_md5_set (peer) < 0)
5083 ret = BGP_ERR_TCPSIG_FAILED;
5084 }
0df7c91f
PJ
5085 }
5086
5087 return ret;
5088}
5089
5090int
5091peer_password_unset (struct peer *peer)
5092{
5093 struct listnode *nn, *nnode;
5094
5095 if (!peer->password
5096 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5097 return 0;
5098
5099 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5100 {
6aa136f1 5101 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
0df7c91f
PJ
5102 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5103 else
1ff9a340 5104 bgp_session_reset(peer);
0df7c91f
PJ
5105
5106 if (peer->password)
5107 XFREE (MTYPE_PEER_PASSWORD, peer->password);
5108
5109 peer->password = NULL;
5110
89ca90fa 5111 if (! BGP_PEER_SU_UNSPEC(peer))
5112 bgp_md5_unset (peer);
0df7c91f
PJ
5113
5114 return 0;
5115 }
5116
5117 XFREE (MTYPE_PEER_PASSWORD, peer->password);
5118 peer->password = NULL;
5119
5120 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
5121 {
5122 if (!peer->password)
5123 continue;
5124
6aa136f1 5125 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
0df7c91f
PJ
5126 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
5127 else
1ff9a340 5128 bgp_session_reset(peer);
0df7c91f
PJ
5129
5130 XFREE (MTYPE_PEER_PASSWORD, peer->password);
5131 peer->password = NULL;
5132
89ca90fa 5133 if (! BGP_PEER_SU_UNSPEC(peer))
5134 bgp_md5_unset (peer);
0df7c91f
PJ
5135 }
5136
5137 return 0;
5138}
6b0655a2 5139
3f9c7369 5140
718e3744 5141/* Set distribute list to the peer. */
5142int
5143peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
fd79ac91 5144 const char *name)
718e3744 5145{
5146 struct bgp_filter *filter;
5147 struct peer_group *group;
1eb8ef25 5148 struct listnode *node, *nnode;
718e3744 5149
718e3744 5150 if (direct != FILTER_IN && direct != FILTER_OUT)
5151 return BGP_ERR_INVALID_VALUE;
5152
718e3744 5153 filter = &peer->filter[afi][safi];
5154
5155 if (filter->plist[direct].name)
5156 return BGP_ERR_PEER_FILTER_CONFLICT;
5157
5158 if (filter->dlist[direct].name)
6e919709
DS
5159 XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name);
5160 filter->dlist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5161 filter->dlist[direct].alist = access_list_lookup (afi, name);
5162
5163 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 5164 {
94f34286
DS
5165 peer_on_policy_change(peer, afi, safi,
5166 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
5167 return 0;
5168 }
718e3744 5169
5170 group = peer->group;
1eb8ef25 5171 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5172 {
5173 filter = &peer->filter[afi][safi];
5174
718e3744 5175 if (filter->dlist[direct].name)
6e919709
DS
5176 XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name);
5177 filter->dlist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5178 filter->dlist[direct].alist = access_list_lookup (afi, name);
94f34286
DS
5179 peer_on_policy_change(peer, afi, safi,
5180 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5181 }
5182
5183 return 0;
5184}
5185
5186int
5187peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
5188{
5189 struct bgp_filter *filter;
5190 struct bgp_filter *gfilter;
5191 struct peer_group *group;
1eb8ef25 5192 struct listnode *node, *nnode;
718e3744 5193
718e3744 5194 if (direct != FILTER_IN && direct != FILTER_OUT)
5195 return BGP_ERR_INVALID_VALUE;
5196
718e3744 5197 filter = &peer->filter[afi][safi];
5198
5199 /* apply peer-group filter */
c8560b44 5200 if (peer_group_active(peer))
718e3744 5201 {
5202 gfilter = &peer->group->conf->filter[afi][safi];
5203
5204 if (gfilter->dlist[direct].name)
5205 {
5206 if (filter->dlist[direct].name)
6e919709
DS
5207 XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name);
5208 filter->dlist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->dlist[direct].name);
718e3744 5209 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
94f34286
DS
5210 peer_on_policy_change(peer, afi, safi,
5211 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5212 return 0;
5213 }
5214 }
5215
5216 if (filter->dlist[direct].name)
6e919709 5217 XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name);
718e3744 5218 filter->dlist[direct].name = NULL;
5219 filter->dlist[direct].alist = NULL;
5220
5221 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 5222 {
94f34286
DS
5223 peer_on_policy_change(peer, afi, safi,
5224 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
5225 return 0;
5226 }
718e3744 5227
94f34286
DS
5228 group = peer->group;
5229 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
5230 {
5231 filter = &peer->filter[afi][safi];
718e3744 5232
94f34286 5233 if (filter->dlist[direct].name)
6e919709 5234 XFREE(MTYPE_BGP_FILTER_NAME, filter->dlist[direct].name);
94f34286
DS
5235 filter->dlist[direct].name = NULL;
5236 filter->dlist[direct].alist = NULL;
5237 peer_on_policy_change(peer, afi, safi,
5238 (direct == FILTER_OUT) ? 1 : 0);
5239 }
718e3744 5240
5241 return 0;
5242}
5243
5244/* Update distribute list. */
94f2b392 5245static void
718e3744 5246peer_distribute_update (struct access_list *access)
5247{
5248 afi_t afi;
5249 safi_t safi;
5250 int direct;
1eb8ef25 5251 struct listnode *mnode, *mnnode;
5252 struct listnode *node, *nnode;
718e3744 5253 struct bgp *bgp;
5254 struct peer *peer;
5255 struct peer_group *group;
5256 struct bgp_filter *filter;
5257
1eb8ef25 5258 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
718e3744 5259 {
3f9c7369
DS
5260 if (access->name)
5261 update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST, access->name,
5262 0, 0);
1eb8ef25 5263 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 5264 {
5265 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5266 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
5267 {
5268 filter = &peer->filter[afi][safi];
5269
5270 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
5271 {
5272 if (filter->dlist[direct].name)
5273 filter->dlist[direct].alist =
5274 access_list_lookup (afi, filter->dlist[direct].name);
5275 else
5276 filter->dlist[direct].alist = NULL;
5277 }
5278 }
5279 }
1eb8ef25 5280 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 5281 {
5282 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5283 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
5284 {
5285 filter = &group->conf->filter[afi][safi];
5286
5287 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
5288 {
5289 if (filter->dlist[direct].name)
5290 filter->dlist[direct].alist =
5291 access_list_lookup (afi, filter->dlist[direct].name);
5292 else
5293 filter->dlist[direct].alist = NULL;
5294 }
5295 }
5296 }
65efcfce
LB
5297#if ENABLE_BGP_VNC
5298 vnc_prefix_list_update(bgp);
5299#endif
718e3744 5300 }
5301}
6b0655a2 5302
718e3744 5303/* Set prefix list to the peer. */
5304int
5305peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
fd79ac91 5306 const char *name)
718e3744 5307{
5308 struct bgp_filter *filter;
5309 struct peer_group *group;
1eb8ef25 5310 struct listnode *node, *nnode;
718e3744 5311
718e3744 5312 if (direct != FILTER_IN && direct != FILTER_OUT)
5313 return BGP_ERR_INVALID_VALUE;
5314
718e3744 5315 filter = &peer->filter[afi][safi];
5316
5317 if (filter->dlist[direct].name)
5318 return BGP_ERR_PEER_FILTER_CONFLICT;
5319
5320 if (filter->plist[direct].name)
6e919709
DS
5321 XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name);
5322 filter->plist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5323 filter->plist[direct].plist = prefix_list_lookup (afi, name);
5324
5325 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 5326 {
94f34286
DS
5327 peer_on_policy_change(peer, afi, safi,
5328 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
5329 return 0;
5330 }
718e3744 5331
5332 group = peer->group;
1eb8ef25 5333 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5334 {
5335 filter = &peer->filter[afi][safi];
5336
718e3744 5337 if (filter->plist[direct].name)
6e919709
DS
5338 XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name);
5339 filter->plist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5340 filter->plist[direct].plist = prefix_list_lookup (afi, name);
94f34286
DS
5341 peer_on_policy_change(peer, afi, safi,
5342 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5343 }
5344 return 0;
5345}
5346
5347int
5348peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
5349{
5350 struct bgp_filter *filter;
5351 struct bgp_filter *gfilter;
5352 struct peer_group *group;
1eb8ef25 5353 struct listnode *node, *nnode;
718e3744 5354
718e3744 5355 if (direct != FILTER_IN && direct != FILTER_OUT)
5356 return BGP_ERR_INVALID_VALUE;
5357
718e3744 5358 filter = &peer->filter[afi][safi];
5359
5360 /* apply peer-group filter */
c8560b44 5361 if (peer_group_active(peer))
718e3744 5362 {
5363 gfilter = &peer->group->conf->filter[afi][safi];
5364
5365 if (gfilter->plist[direct].name)
5366 {
5367 if (filter->plist[direct].name)
6e919709
DS
5368 XSTRDUP(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name);
5369 filter->plist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->plist[direct].name);
718e3744 5370 filter->plist[direct].plist = gfilter->plist[direct].plist;
94f34286
DS
5371 peer_on_policy_change(peer, afi, safi,
5372 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5373 return 0;
5374 }
5375 }
5376
5377 if (filter->plist[direct].name)
6e919709 5378 XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name);
718e3744 5379 filter->plist[direct].name = NULL;
5380 filter->plist[direct].plist = NULL;
5381
5382 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 5383 {
94f34286
DS
5384 peer_on_policy_change(peer, afi, safi,
5385 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
5386 return 0;
5387 }
718e3744 5388
5389 group = peer->group;
1eb8ef25 5390 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5391 {
5392 filter = &peer->filter[afi][safi];
5393
718e3744 5394 if (filter->plist[direct].name)
6e919709 5395 XFREE(MTYPE_BGP_FILTER_NAME, filter->plist[direct].name);
718e3744 5396 filter->plist[direct].name = NULL;
5397 filter->plist[direct].plist = NULL;
94f34286
DS
5398 peer_on_policy_change(peer, afi, safi,
5399 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5400 }
5401
5402 return 0;
5403}
5404
5405/* Update prefix-list list. */
94f2b392 5406static void
718e3744 5407peer_prefix_list_update (struct prefix_list *plist)
5408{
1eb8ef25 5409 struct listnode *mnode, *mnnode;
5410 struct listnode *node, *nnode;
718e3744 5411 struct bgp *bgp;
5412 struct peer *peer;
5413 struct peer_group *group;
5414 struct bgp_filter *filter;
5415 afi_t afi;
5416 safi_t safi;
5417 int direct;
5418
1eb8ef25 5419 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
718e3744 5420 {
3f9c7369
DS
5421
5422 /*
5423 * Update the prefix-list on update groups.
5424 */
5425 update_group_policy_update(bgp, BGP_POLICY_PREFIX_LIST,
a38401b6 5426 plist ? prefix_list_name(plist) : NULL, 0, 0);
3f9c7369 5427
1eb8ef25 5428 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 5429 {
5430 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5431 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
5432 {
5433 filter = &peer->filter[afi][safi];
5434
5435 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
5436 {
5437 if (filter->plist[direct].name)
5438 filter->plist[direct].plist =
5439 prefix_list_lookup (afi, filter->plist[direct].name);
5440 else
5441 filter->plist[direct].plist = NULL;
5442 }
5443 }
5444 }
1eb8ef25 5445 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 5446 {
5447 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5448 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
5449 {
5450 filter = &group->conf->filter[afi][safi];
5451
5452 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
5453 {
5454 if (filter->plist[direct].name)
5455 filter->plist[direct].plist =
5456 prefix_list_lookup (afi, filter->plist[direct].name);
5457 else
5458 filter->plist[direct].plist = NULL;
5459 }
5460 }
5461 }
5462 }
5463}
6b0655a2 5464
718e3744 5465int
5466peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
fd79ac91 5467 const char *name)
718e3744 5468{
5469 struct bgp_filter *filter;
5470 struct peer_group *group;
1eb8ef25 5471 struct listnode *node, *nnode;
718e3744 5472
718e3744 5473 if (direct != FILTER_IN && direct != FILTER_OUT)
5474 return BGP_ERR_INVALID_VALUE;
5475
718e3744 5476 filter = &peer->filter[afi][safi];
5477
5478 if (filter->aslist[direct].name)
6e919709
DS
5479 XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name);
5480 filter->aslist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5481 filter->aslist[direct].aslist = as_list_lookup (name);
5482
5483 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 5484 {
94f34286
DS
5485 peer_on_policy_change(peer, afi, safi,
5486 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
5487 return 0;
5488 }
718e3744 5489
5490 group = peer->group;
1eb8ef25 5491 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5492 {
5493 filter = &peer->filter[afi][safi];
5494
718e3744 5495 if (filter->aslist[direct].name)
6e919709
DS
5496 XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name);
5497 filter->aslist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5498 filter->aslist[direct].aslist = as_list_lookup (name);
94f34286
DS
5499 peer_on_policy_change(peer, afi, safi,
5500 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5501 }
5502 return 0;
5503}
5504
5505int
5506peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
5507{
5508 struct bgp_filter *filter;
5509 struct bgp_filter *gfilter;
5510 struct peer_group *group;
1eb8ef25 5511 struct listnode *node, *nnode;
718e3744 5512
b5f29603 5513 if (direct != FILTER_IN && direct != FILTER_OUT)
718e3744 5514 return BGP_ERR_INVALID_VALUE;
5515
718e3744 5516 filter = &peer->filter[afi][safi];
5517
5518 /* apply peer-group filter */
c8560b44 5519 if (peer_group_active(peer))
718e3744 5520 {
5521 gfilter = &peer->group->conf->filter[afi][safi];
5522
5523 if (gfilter->aslist[direct].name)
5524 {
5525 if (filter->aslist[direct].name)
6e919709
DS
5526 XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name);
5527 filter->aslist[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->aslist[direct].name);
718e3744 5528 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
94f34286
DS
5529 peer_on_policy_change(peer, afi, safi,
5530 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5531 return 0;
5532 }
5533 }
5534
5535 if (filter->aslist[direct].name)
6e919709 5536 XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name);
718e3744 5537 filter->aslist[direct].name = NULL;
5538 filter->aslist[direct].aslist = NULL;
5539
5540 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3f9c7369 5541 {
94f34286
DS
5542 peer_on_policy_change(peer, afi, safi,
5543 (direct == FILTER_OUT) ? 1 : 0);
3f9c7369
DS
5544 return 0;
5545 }
718e3744 5546
5547 group = peer->group;
1eb8ef25 5548 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5549 {
5550 filter = &peer->filter[afi][safi];
5551
718e3744 5552 if (filter->aslist[direct].name)
6e919709 5553 XFREE(MTYPE_BGP_FILTER_NAME, filter->aslist[direct].name);
718e3744 5554 filter->aslist[direct].name = NULL;
5555 filter->aslist[direct].aslist = NULL;
94f34286
DS
5556 peer_on_policy_change(peer, afi, safi,
5557 (direct == FILTER_OUT) ? 1 : 0);
718e3744 5558 }
5559
5560 return 0;
5561}
5562
94f2b392 5563static void
ffd0c037 5564peer_aslist_update (const char *aslist_name)
718e3744 5565{
5566 afi_t afi;
5567 safi_t safi;
5568 int direct;
1eb8ef25 5569 struct listnode *mnode, *mnnode;
5570 struct listnode *node, *nnode;
718e3744 5571 struct bgp *bgp;
5572 struct peer *peer;
5573 struct peer_group *group;
5574 struct bgp_filter *filter;
5575
1eb8ef25 5576 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
718e3744 5577 {
3f9c7369
DS
5578 update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST, aslist_name,
5579 0, 0);
5580
1eb8ef25 5581 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 5582 {
5583 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5584 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
5585 {
5586 filter = &peer->filter[afi][safi];
5587
5588 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
5589 {
5590 if (filter->aslist[direct].name)
5591 filter->aslist[direct].aslist =
5592 as_list_lookup (filter->aslist[direct].name);
5593 else
5594 filter->aslist[direct].aslist = NULL;
5595 }
5596 }
5597 }
1eb8ef25 5598 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 5599 {
5600 for (afi = AFI_IP; afi < AFI_MAX; afi++)
5601 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
5602 {
5603 filter = &group->conf->filter[afi][safi];
5604
5605 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
5606 {
5607 if (filter->aslist[direct].name)
5608 filter->aslist[direct].aslist =
5609 as_list_lookup (filter->aslist[direct].name);
5610 else
5611 filter->aslist[direct].aslist = NULL;
5612 }
5613 }
5614 }
5615 }
5616}
3f9c7369 5617
518f0eb1
DS
5618static void
5619peer_aslist_add (char *aslist_name)
5620{
5621 peer_aslist_update (aslist_name);
5622 route_map_notify_dependencies((char *)aslist_name, RMAP_EVENT_ASLIST_ADDED);
5623}
5624
5625static void
ffd0c037 5626peer_aslist_del (const char *aslist_name)
518f0eb1
DS
5627{
5628 peer_aslist_update (aslist_name);
ffd0c037 5629 route_map_notify_dependencies(aslist_name, RMAP_EVENT_ASLIST_DELETED);
518f0eb1
DS
5630}
5631
6b0655a2 5632
718e3744 5633int
5634peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
fd79ac91 5635 const char *name)
718e3744 5636{
5637 struct bgp_filter *filter;
5638 struct peer_group *group;
1eb8ef25 5639 struct listnode *node, *nnode;
718e3744 5640
2a3d5731 5641 if (direct != RMAP_IN && direct != RMAP_OUT)
718e3744 5642 return BGP_ERR_INVALID_VALUE;
5643
718e3744 5644 filter = &peer->filter[afi][safi];
5645
5646 if (filter->map[direct].name)
6e919709 5647 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
518f0eb1 5648
6e919709 5649 filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5650 filter->map[direct].map = route_map_lookup_by_name (name);
5651
5652 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
518f0eb1 5653 {
94f34286
DS
5654 peer_on_policy_change(peer, afi, safi,
5655 (direct == RMAP_OUT) ? 1 : 0);
518f0eb1
DS
5656 return 0;
5657 }
718e3744 5658
5659 group = peer->group;
1eb8ef25 5660 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5661 {
5662 filter = &peer->filter[afi][safi];
5663
718e3744 5664 if (filter->map[direct].name)
6e919709
DS
5665 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
5666 filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5667 filter->map[direct].map = route_map_lookup_by_name (name);
94f34286
DS
5668 peer_on_policy_change(peer, afi, safi,
5669 (direct == RMAP_OUT) ? 1 : 0);
718e3744 5670 }
5671 return 0;
5672}
5673
5674/* Unset route-map from the peer. */
5675int
5676peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
5677{
5678 struct bgp_filter *filter;
5679 struct bgp_filter *gfilter;
5680 struct peer_group *group;
1eb8ef25 5681 struct listnode *node, *nnode;
718e3744 5682
2a3d5731 5683 if (direct != RMAP_IN && direct != RMAP_OUT)
718e3744 5684 return BGP_ERR_INVALID_VALUE;
5685
718e3744 5686 filter = &peer->filter[afi][safi];
5687
5688 /* apply peer-group filter */
c8560b44 5689 if (peer_group_active(peer))
718e3744 5690 {
5691 gfilter = &peer->group->conf->filter[afi][safi];
5692
5693 if (gfilter->map[direct].name)
5694 {
5695 if (filter->map[direct].name)
6e919709
DS
5696 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
5697 filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, gfilter->map[direct].name);
718e3744 5698 filter->map[direct].map = gfilter->map[direct].map;
94f34286
DS
5699 peer_on_policy_change(peer, afi, safi,
5700 (direct == RMAP_OUT) ? 1 : 0);
718e3744 5701 return 0;
5702 }
5703 }
5704
5705 if (filter->map[direct].name)
6e919709 5706 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
718e3744 5707 filter->map[direct].name = NULL;
5708 filter->map[direct].map = NULL;
5709
5710 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
518f0eb1 5711 {
94f34286
DS
5712 peer_on_policy_change(peer, afi, safi,
5713 (direct == RMAP_OUT) ? 1 : 0);
518f0eb1
DS
5714 return 0;
5715 }
718e3744 5716
5717 group = peer->group;
1eb8ef25 5718 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5719 {
5720 filter = &peer->filter[afi][safi];
5721
718e3744 5722 if (filter->map[direct].name)
6e919709 5723 XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name);
718e3744 5724 filter->map[direct].name = NULL;
5725 filter->map[direct].map = NULL;
94f34286
DS
5726 peer_on_policy_change(peer, afi, safi,
5727 (direct == RMAP_OUT) ? 1 : 0);
718e3744 5728 }
5729 return 0;
5730}
6b0655a2 5731
718e3744 5732/* Set unsuppress-map to the peer. */
5733int
fd79ac91 5734peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
5735 const char *name)
718e3744 5736{
5737 struct bgp_filter *filter;
5738 struct peer_group *group;
1eb8ef25 5739 struct listnode *node, *nnode;
718e3744 5740
718e3744 5741 filter = &peer->filter[afi][safi];
5742
5743 if (filter->usmap.name)
6e919709 5744 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
718e3744 5745
6e919709 5746 filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5747 filter->usmap.map = route_map_lookup_by_name (name);
5748
5749 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
518f0eb1 5750 {
94f34286 5751 peer_on_policy_change(peer, afi, safi, 1);
518f0eb1
DS
5752 return 0;
5753 }
718e3744 5754
5755 group = peer->group;
1eb8ef25 5756 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5757 {
5758 filter = &peer->filter[afi][safi];
5759
718e3744 5760 if (filter->usmap.name)
6e919709
DS
5761 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
5762 filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name);
718e3744 5763 filter->usmap.map = route_map_lookup_by_name (name);
94f34286 5764 peer_on_policy_change(peer, afi, safi, 1);
718e3744 5765 }
5766 return 0;
5767}
5768
5769/* Unset route-map from the peer. */
5770int
5771peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
5772{
5773 struct bgp_filter *filter;
5774 struct peer_group *group;
1eb8ef25 5775 struct listnode *node, *nnode;
718e3744 5776
718e3744 5777 filter = &peer->filter[afi][safi];
5778
5779 if (filter->usmap.name)
6e919709 5780 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
718e3744 5781 filter->usmap.name = NULL;
5782 filter->usmap.map = NULL;
5783
5784 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
518f0eb1 5785 {
94f34286 5786 peer_on_policy_change(peer, afi, safi, 1);
518f0eb1
DS
5787 return 0;
5788 }
718e3744 5789
5790 group = peer->group;
1eb8ef25 5791 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5792 {
5793 filter = &peer->filter[afi][safi];
5794
718e3744 5795 if (filter->usmap.name)
6e919709 5796 XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
718e3744 5797 filter->usmap.name = NULL;
5798 filter->usmap.map = NULL;
94f34286 5799 peer_on_policy_change(peer, afi, safi, 1);
718e3744 5800 }
5801 return 0;
5802}
6b0655a2 5803
718e3744 5804int
5805peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
0a486e5f 5806 u_int32_t max, u_char threshold,
5807 int warning, u_int16_t restart)
718e3744 5808{
5809 struct peer_group *group;
1eb8ef25 5810 struct listnode *node, *nnode;
718e3744 5811
718e3744 5812 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5813 peer->pmax[afi][safi] = max;
e0701b79 5814 peer->pmax_threshold[afi][safi] = threshold;
0a486e5f 5815 peer->pmax_restart[afi][safi] = restart;
718e3744 5816 if (warning)
5817 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5818 else
5819 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5820
fc9a856f 5821 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
718e3744 5822 {
fc9a856f
DS
5823 group = peer->group;
5824 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
5825 {
fc9a856f
DS
5826 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5827 peer->pmax[afi][safi] = max;
5828 peer->pmax_threshold[afi][safi] = threshold;
5829 peer->pmax_restart[afi][safi] = restart;
5830 if (warning)
5831 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5832 else
5833 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5834
5835 if ((peer->status == Established) && (peer->afc[afi][safi]))
5836 bgp_maximum_prefix_overflow (peer, afi, safi, 1);
5837 }
5838 }
5839 else
5840 {
5841 if ((peer->status == Established) && (peer->afc[afi][safi]))
5842 bgp_maximum_prefix_overflow (peer, afi, safi, 1);
718e3744 5843 }
fc9a856f 5844
718e3744 5845 return 0;
5846}
5847
5848int
5849peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
5850{
5851 struct peer_group *group;
1eb8ef25 5852 struct listnode *node, *nnode;
718e3744 5853
718e3744 5854 /* apply peer-group config */
c8560b44 5855 if (peer_group_active(peer))
718e3744 5856 {
5857 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
5858 PEER_FLAG_MAX_PREFIX))
5859 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5860 else
5861 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5862
5863 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
5864 PEER_FLAG_MAX_PREFIX_WARNING))
5865 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5866 else
5867 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5868
5869 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
e0701b79 5870 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
0a486e5f 5871 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
718e3744 5872 return 0;
5873 }
5874
5875 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5876 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5877 peer->pmax[afi][safi] = 0;
0a486e5f 5878 peer->pmax_threshold[afi][safi] = 0;
5879 peer->pmax_restart[afi][safi] = 0;
718e3744 5880
5881 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5882 return 0;
5883
5884 group = peer->group;
1eb8ef25 5885 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
718e3744 5886 {
718e3744 5887 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
5888 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
5889 peer->pmax[afi][safi] = 0;
0a486e5f 5890 peer->pmax_threshold[afi][safi] = 0;
5891 peer->pmax_restart[afi][safi] = 0;
718e3744 5892 }
5893 return 0;
5894}
5f9adb5d 5895
c43ed2e4 5896int is_ebgp_multihop_configured (struct peer *peer)
5f9adb5d
DL
5897{
5898 struct peer_group *group;
5899 struct listnode *node, *nnode;
5900 struct peer *peer1;
5901
5902 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5903 {
5904 group = peer->group;
5d804b43
PM
5905 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
5906 (group->conf->ttl != 1))
5f9adb5d
DL
5907 return 1;
5908
5909 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
5910 {
5d804b43
PM
5911 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
5912 (peer1->ttl != 1))
5f9adb5d
DL
5913 return 1;
5914 }
5915 }
5916 else
5917 {
5d804b43
PM
5918 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
5919 (peer->ttl != 1))
5f9adb5d
DL
5920 return 1;
5921 }
5922 return 0;
5923}
5924
fa411a21
NH
5925/* Set # of hops between us and BGP peer. */
5926int
5927peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
5928{
5929 struct peer_group *group;
5930 struct listnode *node, *nnode;
fa411a21
NH
5931 int ret;
5932
5933 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
5934
fa411a21
NH
5935 /* We cannot configure ttl-security hops when ebgp-multihop is already
5936 set. For non peer-groups, the check is simple. For peer-groups, it's
5937 slightly messy, because we need to check both the peer-group structure
5938 and all peer-group members for any trace of ebgp-multihop configuration
5939 before actually applying the ttl-security rules. Cisco really made a
5940 mess of this configuration parameter, and OpenBGPD got it right.
5941 */
e5cc509c
DS
5942
5943 if ((peer->gtsm_hops == 0) && (peer->sort != BGP_PEER_IBGP))
5f9adb5d
DL
5944 {
5945 if (is_ebgp_multihop_configured (peer))
5946 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
fa411a21 5947
e5cc509c
DS
5948 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5949 {
5950 peer->gtsm_hops = gtsm_hops;
fa411a21 5951
e5cc509c
DS
5952 /* Calling ebgp multihop also resets the session.
5953 * On restart, NHT will get setup correctly as will the
5954 * min & max ttls on the socket. The return value is
5955 * irrelevant.
5956 */
5957 ret = peer_ebgp_multihop_set (peer, MAXTTL);
5958
5959 if (ret != 0)
5960 return ret;
5961 }
5962 else
5963 {
5964 group = peer->group;
5965 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
5966 {
5967 peer->gtsm_hops = group->conf->gtsm_hops;
5968
5969 /* Calling ebgp multihop also resets the session.
5970 * On restart, NHT will get setup correctly as will the
5971 * min & max ttls on the socket. The return value is
5972 * irrelevant.
5973 */
5974 ret = peer_ebgp_multihop_set (peer, MAXTTL);
5975 }
5976 }
fa411a21
NH
5977 }
5978 else
5979 {
e5cc509c
DS
5980 /* Post the first gtsm setup or if its ibgp, maxttl setting isn't
5981 * necessary, just set the minttl.
5982 */
5983 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
fa411a21 5984 {
e5cc509c 5985 peer->gtsm_hops = gtsm_hops;
fa411a21 5986
e5cc509c
DS
5987 if (peer->fd >= 0)
5988 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
5989 MAXTTL + 1 - gtsm_hops);
5990 if ((peer->status < Established) && peer->doppelganger &&
5991 (peer->doppelganger->fd >= 0))
5992 sockopt_minttl (peer->su.sa.sa_family, peer->doppelganger->fd,
5993 MAXTTL + 1 - gtsm_hops);
5994 }
5995 else
5996 {
5997 group = peer->group;
5998 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
f5a4827d 5999 {
e5cc509c
DS
6000 peer->gtsm_hops = group->conf->gtsm_hops;
6001
6002 /* Change setting of existing peer
6003 * established then change value (may break connectivity)
6004 * not established yet (teardown session and restart)
6005 * no session then do nothing (will get handled by next connection)
6006 */
f5a4827d
SH
6007 if (peer->fd >= 0 && peer->gtsm_hops != 0)
6008 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
6009 MAXTTL + 1 - peer->gtsm_hops);
e5cc509c
DS
6010 if ((peer->status < Established) && peer->doppelganger &&
6011 (peer->doppelganger->fd >= 0))
6012 sockopt_minttl (peer->su.sa.sa_family, peer->doppelganger->fd,
6013 MAXTTL + 1 - gtsm_hops);
6014
f5a4827d 6015 }
fa411a21
NH
6016 }
6017 }
6018
6019 return 0;
6020}
6021
6022int
6023peer_ttl_security_hops_unset (struct peer *peer)
6024{
6025 struct peer_group *group;
6026 struct listnode *node, *nnode;
e5cc509c 6027 int ret = 0;
fa411a21
NH
6028
6029 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
6030
fa411a21
NH
6031 /* if a peer-group member, then reset to peer-group default rather than 0 */
6032 if (peer_group_active (peer))
6033 peer->gtsm_hops = peer->group->conf->gtsm_hops;
6034 else
6035 peer->gtsm_hops = 0;
6036
fa411a21
NH
6037 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
6038 {
e5cc509c
DS
6039 /* Invoking ebgp_multihop_set will set the TTL back to the original
6040 * value as well as restting the NHT and such. The session is reset.
6041 */
6042 if (peer->sort == BGP_PEER_EBGP)
6043 ret = peer_ebgp_multihop_unset (peer);
6044 else
6045 {
6046 if (peer->fd >= 0)
6047 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
1ff9a340 6048
e5cc509c
DS
6049 if ((peer->status < Established) && peer->doppelganger &&
6050 (peer->doppelganger->fd >= 0))
6051 sockopt_minttl (peer->su.sa.sa_family,
6052 peer->doppelganger->fd, 0);
6053 }
fa411a21
NH
6054 }
6055 else
6056 {
6057 group = peer->group;
6058 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
6059 {
fa411a21 6060 peer->gtsm_hops = 0;
e5cc509c
DS
6061 if (peer->sort == BGP_PEER_EBGP)
6062 ret = peer_ebgp_multihop_unset (peer);
6063 else
6064 {
6065 if (peer->fd >= 0)
6066 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
1ff9a340 6067
e5cc509c
DS
6068 if ((peer->status < Established) && peer->doppelganger &&
6069 (peer->doppelganger->fd >= 0))
6070 sockopt_minttl (peer->su.sa.sa_family,
6071 peer->doppelganger->fd, 0);
6072 }
fa411a21
NH
6073 }
6074 }
6075
88177fe3 6076 return ret;
fa411a21 6077}
6b0655a2 6078
1ff9a340
DS
6079/*
6080 * If peer clear is invoked in a loop for all peers on the BGP instance,
6081 * it may end up freeing the doppelganger, and if this was the next node
6082 * to the current node, we would end up accessing the freed next node.
6083 * Pass along additional parameter which can be updated if next node
6084 * is freed; only required when walking the peer list on BGP instance.
6085 */
718e3744 6086int
1ff9a340 6087peer_clear (struct peer *peer, struct listnode **nnode)
718e3744 6088{
6089 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
6090 {
0a486e5f 6091 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
6092 {
6093 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
6094 if (peer->t_pmax_restart)
6095 {
6096 BGP_TIMER_OFF (peer->t_pmax_restart);
16286195 6097 if (bgp_debug_neighbor_events(peer))
0a486e5f 6098 zlog_debug ("%s Maximum-prefix restart timer canceled",
6099 peer->host);
6100 }
6101 BGP_EVENT_ADD (peer, BGP_Start);
6102 return 0;
6103 }
6104
718e3744 6105 peer->v_start = BGP_INIT_START_TIMER;
6aa136f1 6106 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
718e3744 6107 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
6108 BGP_NOTIFY_CEASE_ADMIN_RESET);
6109 else
1ff9a340 6110 bgp_session_reset_safe(peer, nnode);
718e3744 6111 }
6112 return 0;
6113}
6114
6115int
6116peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
6117 enum bgp_clear_type stype)
6118{
6a646146
DS
6119 struct peer_af *paf;
6120
718e3744 6121 if (peer->status != Established)
6122 return 0;
6123
6124 if (! peer->afc[afi][safi])
6125 return BGP_ERR_AF_UNCONFIGURED;
6126
e9a0c656
TT
6127 peer->rtt = sockopt_tcp_rtt (peer->fd);
6128
718e3744 6129 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
6a646146
DS
6130 {
6131 /* Clear the "neighbor x.x.x.x default-originate" flag */
6132 paf = peer_af_find (peer, afi, safi);
6133 if (paf && paf->subgroup &&
6134 CHECK_FLAG (paf->subgroup->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE))
6135 UNSET_FLAG (paf->subgroup->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE);
6136
6137 bgp_announce_route (peer, afi, safi);
6138 }
718e3744 6139
6140 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
6141 {
6142 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
6143 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
6144 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
6145 {
6146 struct bgp_filter *filter = &peer->filter[afi][safi];
6147 u_char prefix_type;
6148
6149 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
6150 prefix_type = ORF_TYPE_PREFIX;
6151 else
6152 prefix_type = ORF_TYPE_PREFIX_OLD;
6153
6154 if (filter->plist[FILTER_IN].plist)
6155 {
6156 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
6157 bgp_route_refresh_send (peer, afi, safi,
6158 prefix_type, REFRESH_DEFER, 1);
6159 bgp_route_refresh_send (peer, afi, safi, prefix_type,
6160 REFRESH_IMMEDIATE, 0);
6161 }
6162 else
6163 {
6164 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
6165 bgp_route_refresh_send (peer, afi, safi,
6166 prefix_type, REFRESH_IMMEDIATE, 1);
6167 else
6168 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
6169 }
6170 return 0;
6171 }
6172 }
6173
6174 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
6175 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
6176 {
6177 /* If neighbor has soft reconfiguration inbound flag.
6178 Use Adj-RIB-In database. */
6179 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
6180 bgp_soft_reconfig_in (peer, afi, safi);
6181 else
6182 {
6183 /* If neighbor has route refresh capability, send route refresh
6184 message to the peer. */
6185 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
6186 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
6187 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
6188 else
6189 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
6190 }
6191 }
6192 return 0;
6193}
6b0655a2 6194
fd79ac91 6195/* Display peer uptime.*/
718e3744 6196char *
856ca177 6197peer_uptime (time_t uptime2, char *buf, size_t len, u_char use_json, json_object *json)
718e3744 6198{
6199 time_t uptime1;
6200 struct tm *tm;
6201
6202 /* Check buffer length. */
6203 if (len < BGP_UPTIME_LEN)
6204 {
856ca177
MS
6205 if (!use_json)
6206 {
6207 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
6208 /* XXX: should return status instead of buf... */
6209 snprintf (buf, len, "<error> ");
6210 }
fd79ac91 6211 return buf;
718e3744 6212 }
6213
6214 /* If there is no connection has been done before print `never'. */
6215 if (uptime2 == 0)
6216 {
856ca177 6217 if (use_json)
c6a7d59c
DW
6218 {
6219 json_object_string_add(json, "peerUptime", "never");
6220 json_object_int_add(json, "peerUptimeMsec", 0);
6221 }
856ca177
MS
6222 else
6223 snprintf (buf, len, "never");
718e3744 6224 return buf;
6225 }
6226
6227 /* Get current time. */
65957886 6228 uptime1 = bgp_clock ();
718e3744 6229 uptime1 -= uptime2;
6230 tm = gmtime (&uptime1);
6231
6232 /* Making formatted timer strings. */
6233#define ONE_DAY_SECOND 60*60*24
3a6229da
PJ
6234#define ONE_WEEK_SECOND ONE_DAY_SECOND*7
6235#define ONE_YEAR_SECOND ONE_DAY_SECOND*365
718e3744 6236
1d889348
DS
6237 if (uptime1 < ONE_DAY_SECOND)
6238 snprintf (buf, len, "%02d:%02d:%02d",
6239 tm->tm_hour, tm->tm_min, tm->tm_sec);
6240 else if (uptime1 < ONE_WEEK_SECOND)
6241 snprintf (buf, len, "%dd%02dh%02dm",
6242 tm->tm_yday, tm->tm_hour, tm->tm_min);
3a6229da 6243 else if (uptime1 < ONE_YEAR_SECOND)
1d889348
DS
6244 snprintf (buf, len, "%02dw%dd%02dh",
6245 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
3a6229da
PJ
6246 else
6247 snprintf (buf, len, "%02dy%02dw%dd",
6248 tm->tm_year - 70, tm->tm_yday/7,
6249 tm->tm_yday - ((tm->tm_yday/7) * 7));
1d889348 6250
c6a7d59c
DW
6251 if (use_json)
6252 {
6253 json_object_string_add(json, "peerUptime", buf);
6254 json_object_long_add(json, "peerUptimeMsec", uptime1 * 1000);
6255 }
6256
718e3744 6257 return buf;
6258}
6b0655a2 6259
400b1fad
DW
6260static void
6261afi_header_vty_out (struct vty *vty, afi_t afi, safi_t safi,
6262 int *write, const char *format, ...)
6263{
6264 va_list args;
6265 int len = 0;
6266 char buf[1024];
6267
6268 bgp_config_write_family_header (vty, afi, safi, write);
6269
6270 if (vty_shell (vty))
6271 {
6272 va_start (args, format);
6273 vprintf (format, args);
6274 va_end (args);
6275 }
6276 else
6277 {
6278 va_start (args, format);
6279 len = vsnprintf (buf, sizeof(buf), format, args);
6280 va_end (args);
6281
6282 buffer_put (vty->obuf, (u_char *) buf, len);
6283 }
6284}
6285
94f2b392 6286static void
718e3744 6287bgp_config_write_filter (struct vty *vty, struct peer *peer,
400b1fad 6288 afi_t afi, safi_t safi, int *write)
718e3744 6289{
6290 struct bgp_filter *filter;
6291 struct bgp_filter *gfilter = NULL;
6292 char *addr;
6293 int in = FILTER_IN;
6294 int out = FILTER_OUT;
6295
6296 addr = peer->host;
6297 filter = &peer->filter[afi][safi];
c8560b44
DW
6298
6299 if (peer_group_active(peer))
718e3744 6300 gfilter = &peer->group->conf->filter[afi][safi];
6301
6302 /* distribute-list. */
6303 if (filter->dlist[in].name)
6304 if (! gfilter || ! gfilter->dlist[in].name
6305 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
400b1fad
DW
6306 {
6307 afi_header_vty_out (vty, afi, safi, write,
6308 " neighbor %s distribute-list %s in%s",
6309 addr, filter->dlist[in].name, VTY_NEWLINE);
6310 }
6311
718e3744 6312 if (filter->dlist[out].name && ! gfilter)
400b1fad
DW
6313 {
6314 afi_header_vty_out (vty, afi, safi, write,
6315 " neighbor %s distribute-list %s out%s",
6316 addr, filter->dlist[out].name, VTY_NEWLINE);
6317 }
718e3744 6318
6319 /* prefix-list. */
6320 if (filter->plist[in].name)
6321 if (! gfilter || ! gfilter->plist[in].name
6322 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
400b1fad
DW
6323 {
6324 afi_header_vty_out (vty, afi, safi, write,
6325 " neighbor %s prefix-list %s in%s",
6326 addr, filter->plist[in].name, VTY_NEWLINE);
6327 }
6328
718e3744 6329 if (filter->plist[out].name && ! gfilter)
400b1fad
DW
6330 {
6331 afi_header_vty_out (vty, afi, safi, write,
6332 " neighbor %s prefix-list %s out%s",
6333 addr, filter->plist[out].name, VTY_NEWLINE);
6334 }
718e3744 6335
6336 /* route-map. */
fee0f4c6 6337 if (filter->map[RMAP_IN].name)
6338 if (! gfilter || ! gfilter->map[RMAP_IN].name
6339 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
400b1fad
DW
6340 {
6341 afi_header_vty_out (vty, afi, safi, write,
6342 " neighbor %s route-map %s in%s",
6343 addr, filter->map[RMAP_IN].name, VTY_NEWLINE);
6344 }
6345
2bd5af06
DS
6346 if (filter->map[RMAP_OUT].name)
6347 if (! gfilter || ! gfilter->map[RMAP_OUT].name
6348 || strcmp (filter->map[RMAP_OUT].name, gfilter->map[RMAP_OUT].name) != 0)
400b1fad
DW
6349 {
6350 afi_header_vty_out (vty, afi, safi, write,
6351 " neighbor %s route-map %s out%s",
6352 addr, filter->map[RMAP_OUT].name, VTY_NEWLINE);
6353 }
6354
718e3744 6355 /* unsuppress-map */
6356 if (filter->usmap.name && ! gfilter)
400b1fad
DW
6357 {
6358 afi_header_vty_out (vty, afi, safi, write,
6359 " neighbor %s unsuppress-map %s%s",
6360 addr, filter->usmap.name, VTY_NEWLINE);
6361 }
718e3744 6362
6363 /* filter-list. */
6364 if (filter->aslist[in].name)
6365 if (! gfilter || ! gfilter->aslist[in].name
6366 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
400b1fad
DW
6367 {
6368 afi_header_vty_out (vty, afi, safi, write,
6369 " neighbor %s filter-list %s in%s",
6370 addr, filter->aslist[in].name, VTY_NEWLINE);
6371 }
6372
718e3744 6373 if (filter->aslist[out].name && ! gfilter)
400b1fad
DW
6374 {
6375 afi_header_vty_out (vty, afi, safi, write,
6376 " neighbor %s filter-list %s out%s",
6377 addr, filter->aslist[out].name, VTY_NEWLINE);
6378 }
718e3744 6379}
6380
6381/* BGP peer configuration display function. */
94f2b392 6382static void
0b960b4d
DW
6383bgp_config_write_peer_global (struct vty *vty, struct bgp *bgp,
6384 struct peer *peer)
718e3744 6385{
718e3744 6386 struct peer *g_peer = NULL;
6387 char buf[SU_ADDRSTRLEN];
6388 char *addr;
b3a39dc5
DD
6389 int if_pg_printed = FALSE;
6390 int if_ras_printed = FALSE;
718e3744 6391
f14e6fdb
DS
6392 /* Skip dynamic neighbors. */
6393 if (peer_dynamic_neighbor (peer))
6394 return;
6395
a80beece
DS
6396 if (peer->conf_if)
6397 addr = peer->conf_if;
6398 else
6399 addr = peer->host;
6400
718e3744 6401 /************************************
6402 ****** Global to the neighbor ******
6403 ************************************/
0b960b4d 6404 if (peer->conf_if)
718e3744 6405 {
0b960b4d 6406 if (CHECK_FLAG(peer->flags, PEER_FLAG_IFPEER_V6ONLY))
4c48cf63 6407 vty_out (vty, " neighbor %s interface v6only", addr);
0b960b4d 6408 else
4c48cf63
DW
6409 vty_out (vty, " neighbor %s interface", addr);
6410
6411 if (peer_group_active (peer))
b3a39dc5
DD
6412 {
6413 vty_out (vty, " peer-group %s", peer->group->name);
6414 if_pg_printed = TRUE;
6415 }
6416 else if (peer->as_type == AS_SPECIFIED)
6417 {
6418 vty_out (vty, " remote-as %u", peer->as);
6419 if_ras_printed = TRUE;
6420 }
6421 else if (peer->as_type == AS_INTERNAL)
6422 {
6423 vty_out (vty, " remote-as internal");
6424 if_ras_printed = TRUE;
6425 }
6426 else if (peer->as_type == AS_EXTERNAL)
6427 {
6428 vty_out (vty, " remote-as external");
6429 if_ras_printed = TRUE;
6430 }
4c48cf63
DW
6431
6432 vty_out (vty, "%s", VTY_NEWLINE);
0b960b4d 6433 }
a80beece 6434
c8560b44
DW
6435 /* remote-as and peer-group */
6436 /* peer is a member of a peer-group */
6437 if (peer_group_active (peer))
0b960b4d 6438 {
c8560b44 6439 g_peer = peer->group->conf;
0b960b4d 6440
b3a39dc5 6441 if (g_peer->as_type == AS_UNSPECIFIED && !if_ras_printed)
0b960b4d
DW
6442 {
6443 if (peer->as_type == AS_SPECIFIED)
6444 {
6445 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
6446 VTY_NEWLINE);
6447 }
6448 else if (peer->as_type == AS_INTERNAL)
6449 {
6450 vty_out (vty, " neighbor %s remote-as internal%s", addr, VTY_NEWLINE);
6451 }
6452 else if (peer->as_type == AS_EXTERNAL)
6453 {
6454 vty_out (vty, " neighbor %s remote-as external%s", addr, VTY_NEWLINE);
6455 }
6456 }
c8560b44 6457
4c48cf63
DW
6458 /* For swpX peers we displayed the peer-group
6459 * via 'neighbor swpX interface peer-group WORD' */
b3a39dc5 6460 if (!if_pg_printed)
4c48cf63
DW
6461 vty_out (vty, " neighbor %s peer-group %s%s", addr,
6462 peer->group->name, VTY_NEWLINE);
c8560b44
DW
6463 }
6464
6465 /* peer is NOT a member of a peer-group */
6466 else
6467 {
6468 /* peer is a peer-group, declare the peer-group */
6469 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
6470 {
6471 vty_out (vty, " neighbor %s peer-group%s", addr,
6472 VTY_NEWLINE);
6473 }
6474
b3a39dc5 6475 if (!if_ras_printed)
c8560b44 6476 {
b3a39dc5
DD
6477 if (peer->as_type == AS_SPECIFIED)
6478 {
6479 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
6480 VTY_NEWLINE);
6481 }
6482 else if (peer->as_type == AS_INTERNAL)
6483 {
6484 vty_out (vty, " neighbor %s remote-as internal%s", addr, VTY_NEWLINE);
6485 }
6486 else if (peer->as_type == AS_EXTERNAL)
6487 {
6488 vty_out (vty, " neighbor %s remote-as external%s", addr, VTY_NEWLINE);
6489 }
0b960b4d
DW
6490 }
6491 }
718e3744 6492
0b960b4d
DW
6493 /* local-as */
6494 if (peer->change_local_as)
6495 {
06830cb8
DW
6496 if (! peer_group_active (peer)
6497 || peer->change_local_as != g_peer->change_local_as
6498 || (CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) !=
6499 CHECK_FLAG (g_peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND))
6500 || (CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) !=
6501 CHECK_FLAG (g_peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS)))
0b960b4d
DW
6502 {
6503 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
6504 peer->change_local_as,
6505 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
6506 " no-prepend" : "",
6507 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
6508 " replace-as" : "", VTY_NEWLINE);
6509 }
6510 }
718e3744 6511
0b960b4d
DW
6512 /* description */
6513 if (peer->desc)
6514 {
6515 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
6516 VTY_NEWLINE);
6517 }
718e3744 6518
0b960b4d
DW
6519 /* shutdown */
6520 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
6521 {
6522 if (! peer_group_active (peer) ||
6523 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
6524 {
6525 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
6526 }
6527 }
d5a5c8f0 6528
0b960b4d
DW
6529 /* bfd */
6530 if (peer->bfd_info)
6531 {
6532 if (! peer_group_active (peer) || ! g_peer->bfd_info)
6533 {
6534 bgp_bfd_peer_config_write(vty, peer, addr);
6535 }
6536 }
718e3744 6537
0b960b4d
DW
6538 /* password */
6539 if (peer->password)
6540 {
6541 if (!peer_group_active (peer)
6542 || ! g_peer->password
6543 || strcmp (peer->password, g_peer->password) != 0)
6544 {
6545 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
6546 VTY_NEWLINE);
6547 }
6548 }
6549
6550 /* neighbor solo */
6551 if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL))
6552 {
6553 if (!peer_group_active (peer))
6554 {
6555 vty_out (vty, " neighbor %s solo%s", addr, VTY_NEWLINE);
6556 }
6557 }
6558
6559 /* BGP port */
6560 if (peer->port != BGP_PORT_DEFAULT)
6561 {
6562 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
6563 VTY_NEWLINE);
6564 }
6565
6566 /* Local interface name */
6567 if (peer->ifname)
6568 {
6569 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
6570 VTY_NEWLINE);
6571 }
6572
6573 /* passive */
6574 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
6575 {
6576 if (! peer_group_active (peer) ||
6577 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
6578 {
6579 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
6580 }
6581 }
6582
6583 /* ebgp-multihop */
6584 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
6585 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
6586 {
6587 if (! peer_group_active (peer) || g_peer->ttl != peer->ttl)
6588 {
6589 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
6590 VTY_NEWLINE);
6591 }
6592 }
6593
6594 /* ttl-security hops */
6595 if (peer->gtsm_hops != 0)
6596 {
6597 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
6598 {
89b6d1f8 6599 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
fa411a21 6600 peer->gtsm_hops, VTY_NEWLINE);
0b960b4d
DW
6601 }
6602 }
fa411a21 6603
0b960b4d
DW
6604 /* disable-connected-check */
6605 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
6606 {
6607 if (! peer_group_active (peer) ||
6608 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
6609 {
6610 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
6611 }
6612 }
718e3744 6613
0b960b4d
DW
6614 /* update-source */
6615 if (peer->update_if)
6616 {
6617 if (! peer_group_active (peer) || ! g_peer->update_if
6618 || strcmp (g_peer->update_if, peer->update_if) != 0)
6619 {
6620 vty_out (vty, " neighbor %s update-source %s%s", addr,
6621 peer->update_if, VTY_NEWLINE);
6622 }
6623 }
6624 if (peer->update_source)
6625 {
6626 if (! peer_group_active (peer) || ! g_peer->update_source
6627 || sockunion_cmp (g_peer->update_source,
6628 peer->update_source) != 0)
6629 {
6630 vty_out (vty, " neighbor %s update-source %s%s", addr,
6631 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
6632 VTY_NEWLINE);
6633 }
6634 }
718e3744 6635
0b960b4d 6636 /* advertisement-interval */
813d4307
DW
6637 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV)
6638 && peer->v_routeadv != BGP_DEFAULT_EBGP_ROUTEADV
6639 && ! peer_group_active (peer))
0b960b4d
DW
6640 {
6641 vty_out (vty, " neighbor %s advertisement-interval %d%s",
6642 addr, peer->v_routeadv, VTY_NEWLINE);
6643 }
8a92a8a0 6644
0b960b4d
DW
6645 /* timers */
6646 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
813d4307 6647 && (peer->keepalive != BGP_DEFAULT_KEEPALIVE || peer->holdtime != BGP_DEFAULT_HOLDTIME)
0b960b4d
DW
6648 && ! peer_group_active (peer))
6649 {
6650 vty_out (vty, " neighbor %s timers %d %d%s", addr,
6651 peer->keepalive, peer->holdtime, VTY_NEWLINE);
6652 }
718e3744 6653
0b960b4d 6654 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT) &&
400b1fad 6655 peer->connect != BGP_DEFAULT_CONNECT_RETRY &&
0b960b4d
DW
6656 ! peer_group_active (peer))
6657 {
6658 vty_out (vty, " neighbor %s timers connect %d%s", addr,
6659 peer->connect, VTY_NEWLINE);
6660 }
718e3744 6661
0b960b4d
DW
6662 /* capability dynamic */
6663 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
6664 {
6665 if (! peer_group_active (peer) ||
6666 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
6667 {
6668 vty_out (vty, " neighbor %s capability dynamic%s", addr,
6669 VTY_NEWLINE);
6670 }
6671 }
6672
6673 /* capability extended-nexthop */
b3a39dc5
DD
6674 if (peer->ifp && !CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE))
6675 {
6676 if (! peer_group_active (peer) ||
6677 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_CAPABILITY_ENHE))
6678 {
6679 vty_out (vty, " no neighbor %s capability extended-nexthop%s", addr,
6680 VTY_NEWLINE);
6681 }
6682 }
6683
6684 if (!peer->ifp && CHECK_FLAG (peer->flags, PEER_FLAG_CAPABILITY_ENHE))
0b960b4d
DW
6685 {
6686 if (! peer_group_active (peer) ||
6687 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_CAPABILITY_ENHE))
6688 {
6689 vty_out (vty, " neighbor %s capability extended-nexthop%s", addr,
6690 VTY_NEWLINE);
6691 }
718e3744 6692 }
6693
0b960b4d
DW
6694 /* dont-capability-negotiation */
6695 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
6696 {
6697 if (! peer_group_active (peer) ||
6698 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
6699 {
6700 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
6701 VTY_NEWLINE);
6702 }
6703 }
718e3744 6704
0b960b4d
DW
6705 /* override-capability */
6706 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
6707 {
6708 if (! peer_group_active (peer) ||
6709 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
6710 {
6711 vty_out (vty, " neighbor %s override-capability%s", addr,
6712 VTY_NEWLINE);
6713 }
6714 }
718e3744 6715
0b960b4d
DW
6716 /* strict-capability-match */
6717 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
718e3744 6718 {
0b960b4d
DW
6719 if (! peer_group_active (peer) ||
6720 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
6721 {
6722 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
6723 VTY_NEWLINE);
6724 }
718e3744 6725 }
0b960b4d
DW
6726}
6727
0b960b4d
DW
6728/* BGP peer configuration display function. */
6729static void
6730bgp_config_write_peer_af (struct vty *vty, struct bgp *bgp,
400b1fad
DW
6731 struct peer *peer, afi_t afi, safi_t safi,
6732 int *write)
0b960b4d
DW
6733{
6734 struct peer *g_peer = NULL;
6735 char *addr;
6736
6737 /* Skip dynamic neighbors. */
6738 if (peer_dynamic_neighbor (peer))
6739 return;
6740
6741 if (peer->conf_if)
6742 addr = peer->conf_if;
6743 else
6744 addr = peer->host;
6745
0b960b4d
DW
6746 /************************************
6747 ****** Per AF to the neighbor ******
6748 ************************************/
c8560b44 6749 if (peer_group_active (peer))
400b1fad 6750 {
c8560b44
DW
6751 g_peer = peer->group->conf;
6752
6753 /* If the peer-group is active but peer is not, print a 'no activate' */
6754 if (g_peer->afc[afi][safi] && !peer->afc[afi][safi])
6755 {
6756 afi_header_vty_out (vty, afi, safi, write,
6757 " no neighbor %s activate%s",
6758 addr, VTY_NEWLINE);
6759 }
6760
6761 /* If the peer-group is not active but peer is, print an 'activate' */
6762 else if (!g_peer->afc[afi][safi] && peer->afc[afi][safi])
6763 {
6764 afi_header_vty_out (vty, afi, safi, write,
6765 " neighbor %s activate%s",
6766 addr, VTY_NEWLINE);
6767 }
400b1fad 6768 }
0b960b4d 6769 else
c8560b44
DW
6770 {
6771 if (peer->afc[afi][safi])
6772 {
655f79c9
DD
6773 if ((afi == AFI_IP) && (safi == SAFI_UNICAST))
6774 {
6775 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
6776 {
a94d98ae
DW
6777 afi_header_vty_out(vty, afi, safi, write,
6778 " neighbor %s activate%s",
6779 addr, VTY_NEWLINE);
655f79c9
DD
6780 }
6781 }
6782 else
6783 afi_header_vty_out (vty, afi, safi, write,
6784 " neighbor %s activate%s",
6785 addr, VTY_NEWLINE);
c8560b44 6786 }
7709c62d
DS
6787 else
6788 {
6789 if ((afi == AFI_IP) && (safi == SAFI_UNICAST))
6790 {
6791 if (!bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
6792 {
6793 afi_header_vty_out (vty, afi, safi, write,
6794 " no neighbor %s activate%s",
6795 addr, VTY_NEWLINE);
6796 }
6797 }
6798 }
c8560b44 6799 }
718e3744 6800
adbac85e
DW
6801 /* addpath TX knobs */
6802 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ADDPATH_TX_ALL_PATHS))
c8560b44
DW
6803 {
6804 afi_header_vty_out (vty, afi, safi, write,
6805 " neighbor %s addpath-tx-all-paths%s",
6806 addr, VTY_NEWLINE);
6807 }
06370dac
DW
6808
6809 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS))
c8560b44
DW
6810 {
6811 afi_header_vty_out (vty, afi, safi, write,
6812 " neighbor %s addpath-tx-bestpath-per-AS%s",
6813 addr, VTY_NEWLINE);
6814 }
adbac85e 6815
718e3744 6816 /* ORF capability. */
88b8ed8d
DW
6817 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM) ||
6818 peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_RM))
718e3744 6819 {
400b1fad
DW
6820 afi_header_vty_out (vty, afi, safi, write,
6821 " neighbor %s capability orf prefix-list",
6822 addr);
718e3744 6823
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 vty_out (vty, " both");
88b8ed8d 6827 else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM))
718e3744 6828 vty_out (vty, " send");
6829 else
6830 vty_out (vty, " receive");
6831 vty_out (vty, "%s", VTY_NEWLINE);
6832 }
6833
6834 /* Route reflector client. */
88b8ed8d 6835 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT))
400b1fad
DW
6836 {
6837 afi_header_vty_out (vty, afi, safi, write,
6838 " neighbor %s route-reflector-client%s",
6839 addr, VTY_NEWLINE);
6840 }
88b8ed8d
DW
6841
6842 /* next-hop-self force */
6843 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_FORCE_NEXTHOP_SELF))
400b1fad
DW
6844 {
6845 afi_header_vty_out (vty, afi, safi, write,
6846 " neighbor %s next-hop-self force%s",
6847 addr, VTY_NEWLINE);
6848 }
718e3744 6849
88b8ed8d
DW
6850 /* next-hop-self */
6851 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF))
400b1fad
DW
6852 {
6853 afi_header_vty_out (vty, afi, safi, write,
6854 " neighbor %s next-hop-self%s",
6855 addr, VTY_NEWLINE);
6856 }
718e3744 6857
5000f21c 6858 /* remove-private-AS */
88b8ed8d 6859 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE))
400b1fad
DW
6860 {
6861 afi_header_vty_out (vty, afi, safi, write,
6862 " neighbor %s remove-private-AS all replace-AS%s",
6863 addr, VTY_NEWLINE);
6864 }
5000f21c 6865
88b8ed8d 6866 else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE))
400b1fad
DW
6867 {
6868 afi_header_vty_out (vty, afi, safi, write,
6869 " neighbor %s remove-private-AS 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_ALL))
400b1fad
DW
6874 {
6875 afi_header_vty_out (vty, afi, safi, write,
6876 " neighbor %s remove-private-AS all%s",
6877 addr, VTY_NEWLINE);
6878 }
5000f21c 6879
88b8ed8d 6880 else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS))
400b1fad
DW
6881 {
6882 afi_header_vty_out (vty, afi, safi, write,
6883 " neighbor %s remove-private-AS%s",
6884 addr, VTY_NEWLINE);
6885 }
718e3744 6886
c7122e14 6887 /* as-override */
88b8ed8d 6888 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_OVERRIDE))
400b1fad
DW
6889 {
6890 afi_header_vty_out (vty, afi, safi, write,
6891 " neighbor %s as-override%s",
6892 addr, VTY_NEWLINE);
6893 }
c7122e14 6894
718e3744 6895 /* send-community print. */
88b8ed8d 6896 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
718e3744 6897 {
88b8ed8d
DW
6898 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
6899 && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
400b1fad
DW
6900 {
6901 afi_header_vty_out (vty, afi, safi, write,
6902 " neighbor %s send-community both%s",
6903 addr, VTY_NEWLINE);
6904 }
88b8ed8d 6905 else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
400b1fad
DW
6906 {
6907 afi_header_vty_out (vty, afi, safi, write,
6908 " neighbor %s send-community extended%s",
6909 addr, VTY_NEWLINE);
6910 }
88b8ed8d 6911 else if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
400b1fad
DW
6912 {
6913 afi_header_vty_out (vty, afi, safi, write,
6914 " neighbor %s send-community%s",
6915 addr, VTY_NEWLINE);
6916 }
88b8ed8d
DW
6917 }
6918 else
6919 {
6920 if (!peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY) &&
ad695d6e 6921 (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)) &&
88b8ed8d 6922 !peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY) &&
ad695d6e 6923 (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)))
400b1fad
DW
6924 {
6925 afi_header_vty_out (vty, afi, safi, write,
6926 " no neighbor %s send-community both%s",
6927 addr, VTY_NEWLINE);
6928 }
88b8ed8d 6929 else if (!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 extended%s",
6934 addr, VTY_NEWLINE);
6935 }
88b8ed8d 6936 else if (!peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY) &&
ad695d6e 6937 (!g_peer || peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)))
400b1fad
DW
6938 {
6939 afi_header_vty_out (vty, afi, safi, write,
6940 " no neighbor %s send-community%s",
6941 addr, VTY_NEWLINE);
6942 }
718e3744 6943 }
6944
6945 /* Default information */
88b8ed8d
DW
6946 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE) ||
6947 (g_peer &&
6948 ((peer->default_rmap[afi][safi].name && !g_peer->default_rmap[afi][safi].name) ||
6949 (!peer->default_rmap[afi][safi].name && g_peer->default_rmap[afi][safi].name) ||
6950 (peer->default_rmap[afi][safi].name &&
6951 strcmp(peer->default_rmap[afi][safi].name, g_peer->default_rmap[afi][safi].name)))))
718e3744 6952 {
400b1fad
DW
6953 afi_header_vty_out (vty, afi, safi, write,
6954 " neighbor %s default-originate", addr);
718e3744 6955 if (peer->default_rmap[afi][safi].name)
88b8ed8d 6956 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
718e3744 6957 vty_out (vty, "%s", VTY_NEWLINE);
6958 }
6959
6960 /* Soft reconfiguration inbound. */
88b8ed8d 6961 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_SOFT_RECONFIG))
400b1fad
DW
6962 {
6963 afi_header_vty_out (vty, afi, safi, write,
6964 " neighbor %s soft-reconfiguration inbound%s",
6965 addr, VTY_NEWLINE);
6966 }
718e3744 6967
6968 /* maximum-prefix. */
6969 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
c8560b44 6970 if (! peer_group_active(peer)
718e3744 6971 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
e0701b79 6972 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
718e3744 6973 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
6974 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
e0701b79 6975 {
400b1fad 6976 afi_header_vty_out (vty, afi, safi, write,
85e11c23 6977 " neighbor %s maximum-prefix %lu",
400b1fad 6978 addr, peer->pmax[afi][safi]);
0a486e5f 6979 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
6980 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
6981 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
6982 vty_out (vty, " warning-only");
6983 if (peer->pmax_restart[afi][safi])
6984 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
6985 vty_out (vty, "%s", VTY_NEWLINE);
e0701b79 6986 }
718e3744 6987
6988 /* Route server client. */
88b8ed8d 6989 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_RSERVER_CLIENT))
400b1fad
DW
6990 {
6991 afi_header_vty_out (vty, afi, safi, write,
6992 " neighbor %s route-server-client%s",
6993 addr, VTY_NEWLINE);
6994 }
718e3744 6995
3cf1288b 6996 /* Nexthop-local unchanged. */
88b8ed8d 6997 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED))
400b1fad
DW
6998 {
6999 afi_header_vty_out (vty, afi, safi, write,
7000 " neighbor %s nexthop-local unchanged%s",
7001 addr, VTY_NEWLINE);
7002 }
3cf1288b 7003
718e3744 7004 /* Allow AS in. */
7005 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
7006 if (! peer_group_active (peer)
7007 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
7008 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
7009 {
7010 if (peer->allowas_in[afi][safi] == 3)
400b1fad
DW
7011 {
7012 afi_header_vty_out (vty, afi, safi, write,
7013 " neighbor %s allowas-in%s",
7014 addr, VTY_NEWLINE);
7015 }
7016 else
7017 {
7018 afi_header_vty_out (vty, afi, safi, write,
7019 " neighbor %s allowas-in %d%s",
7020 addr, peer->allowas_in[afi][safi], VTY_NEWLINE);
7021 }
718e3744 7022 }
7023
d93f7ffc
DW
7024 /* weight */
7025 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_WEIGHT))
7026 if (! peer_group_active (peer)
7027 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_WEIGHT)
7028 || peer->weight[afi][safi] != g_peer->weight[afi][safi])
7029 {
7030 if (peer->weight[afi][safi])
7031 {
7032 afi_header_vty_out (vty, afi, safi, write,
7033 " neighbor %s weight %d%s",
7034 addr, peer->weight[afi][safi], VTY_NEWLINE);
7035 }
7036 }
7037
718e3744 7038 /* Filter. */
400b1fad 7039 bgp_config_write_filter (vty, peer, afi, safi, write);
718e3744 7040
7041 /* atribute-unchanged. */
88b8ed8d 7042 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
718e3744 7043 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
7044 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
718e3744 7045 {
88b8ed8d
DW
7046 if (peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED)
7047 && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_UNCHANGED)
7048 && peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_MED_UNCHANGED))
400b1fad
DW
7049 {
7050 afi_header_vty_out (vty, afi, safi, write,
7051 " neighbor %s attribute-unchanged%s",
7052 addr, VTY_NEWLINE);
7053 }
718e3744 7054 else
400b1fad
DW
7055 {
7056 afi_header_vty_out (vty, afi, safi, write,
7057 " neighbor %s attribute-unchanged%s%s%s%s", addr,
7058 peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_AS_PATH_UNCHANGED) ?
7059 " as-path" : "",
7060 peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_UNCHANGED) ?
7061 " next-hop" : "",
7062 peergroup_af_flag_check (peer, afi, safi, PEER_FLAG_MED_UNCHANGED) ?
7063 " med" : "", VTY_NEWLINE);
7064 }
718e3744 7065 }
7066}
7067
7068/* Display "address-family" configuration header. */
7069void
7070bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
7071 int *write)
7072{
7073 if (*write)
7074 return;
7075
3914b418 7076 vty_out (vty, " !%s address-family ", VTY_NEWLINE);
718e3744 7077
7078 if (afi == AFI_IP)
7079 {
0b960b4d
DW
7080 if (safi == SAFI_UNICAST)
7081 vty_out (vty, "ipv4 unicast");
7082 else if (safi == SAFI_MULTICAST)
718e3744 7083 vty_out (vty, "ipv4 multicast");
7084 else if (safi == SAFI_MPLS_VPN)
8b1fb8be
LB
7085 vty_out (vty, "vpnv4");
7086 else if (safi == SAFI_ENCAP)
7087 vty_out (vty, "encap");
718e3744 7088 }
7089 else if (afi == AFI_IP6)
37a217a5 7090 {
0b960b4d
DW
7091 if (safi == SAFI_UNICAST)
7092 vty_out (vty, "ipv6 unicast");
7093 else if (safi == SAFI_MULTICAST)
7094 vty_out (vty, "ipv6 multicast");
8ecd3266 7095 else if (safi == SAFI_MPLS_VPN)
7096 vty_out (vty, "vpnv6");
8b1fb8be
LB
7097 else if (safi == SAFI_ENCAP)
7098 vty_out (vty, "encapv6");
37a217a5 7099 }
718e3744 7100
7101 vty_out (vty, "%s", VTY_NEWLINE);
7102
7103 *write = 1;
7104}
7105
7106/* Address family based peer configuration display. */
94f2b392 7107static int
718e3744 7108bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
7109 safi_t safi)
7110{
7111 int write = 0;
7112 struct peer *peer;
7113 struct peer_group *group;
1eb8ef25 7114 struct listnode *node, *nnode;
718e3744 7115
734b349e
MZ
7116 bgp_config_write_distance (vty, bgp, afi, safi, &write);
7117
718e3744 7118 bgp_config_write_network (vty, bgp, afi, safi, &write);
7119
7120 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
7121
1eb8ef25 7122 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
400b1fad
DW
7123 bgp_config_write_peer_af (vty, bgp, group->conf, afi, safi, &write);
7124
1eb8ef25 7125 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 7126 {
f14e6fdb
DS
7127 /* Skip dynamic neighbors. */
7128 if (peer_dynamic_neighbor (peer))
7129 continue;
7130
400b1fad
DW
7131 /* Do not display doppelganger peers */
7132 if (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE))
7133 bgp_config_write_peer_af (vty, bgp, peer, afi, safi, &write);
718e3744 7134 }
165b5fff
JB
7135
7136 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
73ac8160 7137 bgp_config_write_table_map (vty, bgp, afi, safi, &write);
165b5fff 7138
718e3744 7139 if (write)
7140 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
7141
7142 return write;
7143}
7144
7145int
7146bgp_config_write (struct vty *vty)
7147{
7148 int write = 0;
7149 struct bgp *bgp;
7150 struct peer_group *group;
7151 struct peer *peer;
1eb8ef25 7152 struct listnode *node, *nnode;
7153 struct listnode *mnode, *mnnode;
718e3744 7154
7155 /* BGP Multiple instance. */
b8fd6a15 7156 if (!bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
718e3744 7157 {
b8fd6a15 7158 vty_out (vty, "no bgp multiple-instance%s", VTY_NEWLINE);
718e3744 7159 write++;
7160 }
7161
7162 /* BGP Config type. */
7163 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
7164 {
7165 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
7166 write++;
7167 }
7168
5fe9f963 7169 if (bm->rmap_update_timer != RMAP_DEFAULT_UPDATE_TIMER)
7170 vty_out (vty, "bgp route-map delay-timer %d%s", bm->rmap_update_timer,
7171 VTY_NEWLINE);
7172
718e3744 7173 /* BGP configuration. */
1eb8ef25 7174 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
718e3744 7175 {
7176 if (write)
7177 vty_out (vty, "!%s", VTY_NEWLINE);
7178
7179 /* Router bgp ASN */
aea339f7 7180 vty_out (vty, "router bgp %u", bgp->as);
718e3744 7181
7182 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
7183 {
7184 if (bgp->name)
ad4cbda1 7185 vty_out (vty, " %s %s",
7186 (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW) ?
7187 "view" : "vrf", bgp->name);
718e3744 7188 }
7189 vty_out (vty, "%s", VTY_NEWLINE);
7190
7191 /* No Synchronization */
7192 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
7193 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
7194
7195 /* BGP fast-external-failover. */
7196 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
7197 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
7198
7199 /* BGP router ID. */
c2d58d6d 7200 if (bgp->router_id_static.s_addr != 0)
7201 vty_out (vty, " bgp router-id %s%s",
7202 inet_ntoa (bgp->router_id_static), VTY_NEWLINE);
718e3744 7203
848973c7 7204 /* BGP log-neighbor-changes. */
6793fbe0
DW
7205 if (!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
7206 vty_out (vty, " no bgp log-neighbor-changes%s", VTY_NEWLINE);
848973c7 7207
718e3744 7208 /* BGP configuration. */
7209 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
7210 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
7211
7212 /* BGP default ipv4-unicast. */
7213 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
7214 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
7215
7216 /* BGP default local-preference. */
7217 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
7218 vty_out (vty, " bgp default local-preference %d%s",
7219 bgp->default_local_pref, VTY_NEWLINE);
7220
04b6bdc0 7221 /* BGP default show-hostname */
15f3b5c0
DW
7222 if (!bgp_flag_check(bgp, BGP_FLAG_SHOW_HOSTNAME))
7223 vty_out (vty, " no bgp default show-hostname%s", VTY_NEWLINE);
04b6bdc0 7224
3f9c7369
DS
7225 /* BGP default subgroup-pkt-queue-max. */
7226 if (bgp->default_subgroup_pkt_queue_max != BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX)
7227 vty_out (vty, " bgp default subgroup-pkt-queue-max %d%s",
7228 bgp->default_subgroup_pkt_queue_max, VTY_NEWLINE);
7229
718e3744 7230 /* BGP client-to-client reflection. */
7231 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
7232 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
7233
7234 /* BGP cluster ID. */
7235 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
7236 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
7237 VTY_NEWLINE);
7238
907f92c8
DS
7239 /* Disable ebgp connected nexthop check */
7240 if (bgp_flag_check (bgp, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
7241 vty_out (vty, " bgp disable-ebgp-connected-route-check%s", VTY_NEWLINE);
7242
e0701b79 7243 /* Confederation identifier*/
718e3744 7244 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
e0701b79 7245 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
7246 VTY_NEWLINE);
7247
7248 /* Confederation peer */
7249 if (bgp->confed_peers_cnt > 0)
718e3744 7250 {
e0701b79 7251 int i;
718e3744 7252
e0701b79 7253 vty_out (vty, " bgp confederation peers");
718e3744 7254
e0701b79 7255 for (i = 0; i < bgp->confed_peers_cnt; i++)
aea339f7 7256 vty_out(vty, " %u", bgp->confed_peers[i]);
718e3744 7257
e0701b79 7258 vty_out (vty, "%s", VTY_NEWLINE);
718e3744 7259 }
7260
7261 /* BGP enforce-first-as. */
7262 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
7263 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
7264
7265 /* BGP deterministic-med. */
1475ac87
DW
7266 if (!bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
7267 vty_out (vty, " no bgp deterministic-med%s", VTY_NEWLINE);
538621f2 7268
f188f2c4
DS
7269 /* BGP update-delay. */
7270 bgp_config_write_update_delay (vty, bgp);
7271
abc920f8
DS
7272 if (bgp->v_maxmed_onstartup != BGP_MAXMED_ONSTARTUP_UNCONFIGURED)
7273 {
7274 vty_out (vty, " bgp max-med on-startup %d", bgp->v_maxmed_onstartup);
7275 if (bgp->maxmed_onstartup_value != BGP_MAXMED_VALUE_DEFAULT)
7276 vty_out (vty, " %d", bgp->maxmed_onstartup_value);
7277 vty_out (vty, "%s", VTY_NEWLINE);
7278 }
7279 if (bgp->v_maxmed_admin != BGP_MAXMED_ADMIN_UNCONFIGURED)
7280 {
7281 vty_out (vty, " bgp max-med administrative");
7282 if (bgp->maxmed_admin_value != BGP_MAXMED_VALUE_DEFAULT)
7283 vty_out (vty, " %d", bgp->maxmed_admin_value);
7284 vty_out (vty, "%s", VTY_NEWLINE);
7285 }
7286
cb1faec9
DS
7287 /* write quanta */
7288 bgp_config_write_wpkt_quanta (vty, bgp);
7289
3f9c7369
DS
7290 /* coalesce time */
7291 bgp_config_write_coalesce_time(vty, bgp);
7292
538621f2 7293 /* BGP graceful-restart. */
93406d87 7294 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
7295 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
7296 bgp->stalepath_time, VTY_NEWLINE);
eb6f1b41
PG
7297 if (bgp->restart_time != BGP_DEFAULT_RESTART_TIME)
7298 vty_out (vty, " bgp graceful-restart restart-time %d%s",
7299 bgp->restart_time, VTY_NEWLINE);
538621f2 7300 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
7301 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
7302
718e3744 7303 /* BGP bestpath method. */
7304 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
7305 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
6811845b 7306 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
7307 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
16fc1eec 7308
219178b6
DW
7309 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX))
7310 {
7311 if (bgp_flag_check (bgp, BGP_FLAG_MULTIPATH_RELAX_AS_SET))
7312 {
7313 vty_out (vty, " bgp bestpath as-path multipath-relax as-set%s", VTY_NEWLINE);
7314 }
7dc9d4e4
DW
7315 else
7316 {
7317 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
7318 }
16fc1eec 7319 }
16fc1eec 7320
8bd9d948
DS
7321 if (bgp_flag_check (bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
7322 vty_out (vty, " bgp route-reflector allow-outbound-policy%s",
7323 VTY_NEWLINE);
7324 }
718e3744 7325 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
7326 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
7327 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
7328 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
7329 {
7330 vty_out (vty, " bgp bestpath med");
7331 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
7332 vty_out (vty, " confed");
7333 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
7334 vty_out (vty, " missing-as-worst");
7335 vty_out (vty, "%s", VTY_NEWLINE);
7336 }
7337
7338 /* BGP network import check. */
5623e905
DW
7339 if (!bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
7340 vty_out (vty, " no bgp network import-check%s", VTY_NEWLINE);
718e3744 7341
718e3744 7342 /* BGP flag dampening. */
7343 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
7344 BGP_CONFIG_DAMPENING))
7345 bgp_config_write_damp (vty);
7346
718e3744 7347 /* BGP timers configuration. */
7348 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
7349 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
7350 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
7351 bgp->default_holdtime, VTY_NEWLINE);
7352
7353 /* peer-group */
1eb8ef25 7354 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
718e3744 7355 {
0b960b4d 7356 bgp_config_write_peer_global (vty, bgp, group->conf);
718e3744 7357 }
7358
7359 /* Normal neighbor configuration. */
1eb8ef25 7360 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
718e3744 7361 {
1ff9a340 7362 if (CHECK_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE))
0b960b4d 7363 bgp_config_write_peer_global (vty, bgp, peer);
718e3744 7364 }
7365
f14e6fdb
DS
7366 /* listen range and limit for dynamic BGP neighbors */
7367 bgp_config_write_listen (vty, bgp);
7368
718e3744 7369 /* No auto-summary */
7370 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
7371 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
7372
0b960b4d
DW
7373 /* IPv4 unicast configuration. */
7374 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_UNICAST);
7375
718e3744 7376 /* IPv4 multicast configuration. */
7377 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
7378
7379 /* IPv4 VPN configuration. */
7380 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
7381
8b1fb8be
LB
7382 /* ENCAPv4 configuration. */
7383 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_ENCAP);
7384
718e3744 7385 /* IPv6 unicast configuration. */
7386 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
7387
37a217a5
PJ
7388 /* IPv6 multicast configuration. */
7389 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
7390
8ecd3266 7391 /* IPv6 VPN configuration. */
7392 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MPLS_VPN);
7393
8b1fb8be
LB
7394 /* ENCAPv6 configuration. */
7395 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_ENCAP);
7396
65efcfce
LB
7397#if ENABLE_BGP_VNC
7398 write += bgp_rfapi_cfg_write(vty, bgp);
7399#endif
7400
718e3744 7401 write++;
7402 }
7403 return write;
7404}
7405
7406void
94f2b392 7407bgp_master_init (void)
718e3744 7408{
7409 memset (&bgp_master, 0, sizeof (struct bgp_master));
7410
7411 bm = &bgp_master;
7412 bm->bgp = list_new ();
0df7c91f 7413 bm->listen_sockets = list_new ();
718e3744 7414 bm->port = BGP_PORT_DEFAULT;
87d4a781 7415 bm->master = thread_master_create ();
65957886 7416 bm->start_time = bgp_clock ();
5fe9f963 7417 bm->t_rmap_update = NULL;
7418 bm->rmap_update_timer = RMAP_DEFAULT_UPDATE_TIMER;
495f0b13
DS
7419
7420 bgp_process_queue_init();
b8fd6a15 7421
7422 /* Enable multiple instances by default. */
7423 bgp_option_set (BGP_OPT_MULTIPLE_INSTANCE);
718e3744 7424}
200df115 7425
b33adb7c 7426/*
7427 * Initialize interface list for instance, if needed. Invoked upon
7428 * instance create.
7429 */
7430static void
7431bgp_if_init (struct bgp *bgp)
7432{
7433 if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
7434 return;
7435
7436 vrf_iflist_create (bgp->vrf_id);
7437}
7438
ad4cbda1 7439/*
009b18fc 7440 * Free up connected routes and interfaces for a BGP instance. Invoked upon
7441 * instance delete (non-default only) or BGP exit.
ad4cbda1 7442 */
b33adb7c 7443static void
009b18fc 7444bgp_if_finish (struct bgp *bgp)
ad4cbda1 7445{
009b18fc 7446 struct listnode *ifnode, *ifnnode;
7447 struct interface *ifp;
ad4cbda1 7448
009b18fc 7449 if (bgp->inst_type == BGP_INSTANCE_TYPE_VIEW)
7450 return;
ad4cbda1 7451
009b18fc 7452 for (ALL_LIST_ELEMENTS (vrf_iflist(bgp->vrf_id), ifnode, ifnnode, ifp))
7453 {
7454 struct listnode *c_node, *c_nnode;
7455 struct connected *c;
ad4cbda1 7456
009b18fc 7457 for (ALL_LIST_ELEMENTS (ifp->connected, c_node, c_nnode, c))
7458 bgp_connected_delete (bgp, c);
ad4cbda1 7459 }
7460}
6b0655a2 7461
718e3744 7462void
94f2b392 7463bgp_init (void)
718e3744 7464{
fc9a856f
DS
7465
7466 /* allocates some vital data structures used by peer commands in vty_init */
718e3744 7467
718e3744 7468 /* Init zebra. */
9229d914 7469 bgp_zebra_init(bm->master);
718e3744 7470
65efcfce
LB
7471#if ENABLE_BGP_VNC
7472 vnc_zebra_init (bm->master);
7473#endif
7474
fc9a856f
DS
7475 /* BGP VTY commands installation. */
7476 bgp_vty_init ();
7477
718e3744 7478 /* BGP inits. */
7479 bgp_attr_init ();
7480 bgp_debug_init ();
7481 bgp_dump_init ();
7482 bgp_route_init ();
7483 bgp_route_map_init ();
fc9a856f 7484 bgp_scan_vty_init();
718e3744 7485 bgp_mplsvpn_init ();
587ff0fd 7486 bgp_encap_init ();
65efcfce
LB
7487#if ENABLE_BGP_VNC
7488 rfapi_init ();
7489#endif
718e3744 7490
7491 /* Access list initialize. */
7492 access_list_init ();
7493 access_list_add_hook (peer_distribute_update);
7494 access_list_delete_hook (peer_distribute_update);
7495
7496 /* Filter list initialize. */
7497 bgp_filter_init ();
518f0eb1
DS
7498 as_list_add_hook (peer_aslist_add);
7499 as_list_delete_hook (peer_aslist_del);
718e3744 7500
7501 /* Prefix list initialize.*/
7502 prefix_list_init ();
7503 prefix_list_add_hook (peer_prefix_list_update);
7504 prefix_list_delete_hook (peer_prefix_list_update);
7505
7506 /* Community list initialize. */
7507 bgp_clist = community_list_init ();
7508
7509#ifdef HAVE_SNMP
7510 bgp_snmp_init ();
7511#endif /* HAVE_SNMP */
c43ed2e4
DS
7512
7513 /* BFD init */
7514 bgp_bfd_init();
718e3744 7515}
545acafb 7516
7517void
66e5cd87 7518bgp_terminate (void)
545acafb 7519{
545acafb 7520 struct bgp *bgp;
7521 struct peer *peer;
1eb8ef25 7522 struct listnode *node, *nnode;
7523 struct listnode *mnode, *mnnode;
545acafb 7524
1ff9a340
DS
7525 /* Close the listener sockets first as this prevents peers from attempting
7526 * to reconnect on receiving the peer unconfig message. In the presence
7527 * of a large number of peers this will ensure that no peer is left with
7528 * a dangling connection
7529 */
7530 /* reverse bgp_master_init */
7531 bgp_close();
7532 if (bm->listen_sockets)
7533 list_free(bm->listen_sockets);
7534 bm->listen_sockets = NULL;
7535
1eb8ef25 7536 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
7537 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
1ff9a340
DS
7538 if (peer->status == Established ||
7539 peer->status == OpenSent ||
7540 peer->status == OpenConfirm)
545acafb 7541 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
7542 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
1ff9a340 7543
545acafb 7544 bgp_cleanup_routes ();
acde4b86 7545
e210cf9f 7546 if (bm->process_main_queue)
acde4b86
SH
7547 {
7548 work_queue_free (bm->process_main_queue);
7549 bm->process_main_queue = NULL;
7550 }
5fe9f963 7551
7552 if (bm->t_rmap_update)
7553 BGP_TIMER_OFF(bm->t_rmap_update);
545acafb 7554}