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