blob: 6aeecb13dd3dcbace0f3804f1a02edb670c896a4 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* 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"
Timo Teräs5a2a1ec2015-10-22 11:35:18 +030029#include "sockopt.h"
paul718e3742002-12-13 20:15:29 +000030#include "network.h"
31#include "memory.h"
32#include "filter.h"
33#include "routemap.h"
34#include "str.h"
35#include "log.h"
36#include "plist.h"
37#include "linklist.h"
paul200df112005-06-01 11:17:05 +000038#include "workqueue.h"
Lou Berger298cc2f2016-01-12 13:42:02 -050039#include "table.h"
paul718e3742002-12-13 20:15:29 +000040
41#include "bgpd/bgpd.h"
42#include "bgpd/bgp_table.h"
43#include "bgpd/bgp_aspath.h"
44#include "bgpd/bgp_route.h"
45#include "bgpd/bgp_dump.h"
46#include "bgpd/bgp_debug.h"
47#include "bgpd/bgp_community.h"
48#include "bgpd/bgp_attr.h"
49#include "bgpd/bgp_regex.h"
50#include "bgpd/bgp_clist.h"
51#include "bgpd/bgp_fsm.h"
52#include "bgpd/bgp_packet.h"
53#include "bgpd/bgp_zebra.h"
54#include "bgpd/bgp_open.h"
55#include "bgpd/bgp_filter.h"
56#include "bgpd/bgp_nexthop.h"
57#include "bgpd/bgp_damp.h"
58#include "bgpd/bgp_mplsvpn.h"
Lou Berger298cc2f2016-01-12 13:42:02 -050059#include "bgpd/bgp_encap.h"
paul718e3742002-12-13 20:15:29 +000060#include "bgpd/bgp_advertise.h"
61#include "bgpd/bgp_network.h"
62#include "bgpd/bgp_vty.h"
Josh Bailey165b5ff2011-07-20 20:43:22 -070063#include "bgpd/bgp_mpath.h"
Dinesh Duttd9ab53a2015-05-19 17:47:21 -070064#include "bgpd/bgp_nht.h"
paul718e3742002-12-13 20:15:29 +000065#ifdef HAVE_SNMP
66#include "bgpd/bgp_snmp.h"
67#endif /* HAVE_SNMP */
David Lamparter6b0655a2014-06-04 06:53:35 +020068
paul718e3742002-12-13 20:15:29 +000069/* BGP process wide configuration. */
70static struct bgp_master bgp_master;
71
hasso18a6dce2004-10-03 18:18:34 +000072extern struct in_addr router_id_zebra;
73
paul718e3742002-12-13 20:15:29 +000074/* BGP process wide configuration pointer to export. */
75struct bgp_master *bm;
76
77/* BGP community-list. */
78struct community_list_handler *bgp_clist;
David Lamparter6b0655a2014-06-04 06:53:35 +020079
paul718e3742002-12-13 20:15:29 +000080/* BGP global flag manipulation. */
81int
82bgp_option_set (int flag)
83{
84 switch (flag)
85 {
86 case BGP_OPT_NO_FIB:
87 case BGP_OPT_MULTIPLE_INSTANCE:
88 case BGP_OPT_CONFIG_CISCO:
Paul Jakmacccbc012012-06-14 10:40:26 +010089 case BGP_OPT_NO_LISTEN:
paul718e3742002-12-13 20:15:29 +000090 SET_FLAG (bm->options, flag);
91 break;
92 default:
93 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +000094 }
95 return 0;
96}
97
98int
99bgp_option_unset (int flag)
100{
101 switch (flag)
102 {
103 case BGP_OPT_MULTIPLE_INSTANCE:
104 if (listcount (bm->bgp) > 1)
105 return BGP_ERR_MULTIPLE_INSTANCE_USED;
106 /* Fall through. */
107 case BGP_OPT_NO_FIB:
108 case BGP_OPT_CONFIG_CISCO:
109 UNSET_FLAG (bm->options, flag);
110 break;
111 default:
112 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +0000113 }
114 return 0;
115}
116
117int
118bgp_option_check (int flag)
119{
120 return CHECK_FLAG (bm->options, flag);
121}
David Lamparter6b0655a2014-06-04 06:53:35 +0200122
paul718e3742002-12-13 20:15:29 +0000123/* BGP flag manipulation. */
124int
125bgp_flag_set (struct bgp *bgp, int flag)
126{
127 SET_FLAG (bgp->flags, flag);
128 return 0;
129}
130
131int
132bgp_flag_unset (struct bgp *bgp, int flag)
133{
134 UNSET_FLAG (bgp->flags, flag);
135 return 0;
136}
137
138int
139bgp_flag_check (struct bgp *bgp, int flag)
140{
141 return CHECK_FLAG (bgp->flags, flag);
142}
David Lamparter6b0655a2014-06-04 06:53:35 +0200143
paul718e3742002-12-13 20:15:29 +0000144/* Internal function to set BGP structure configureation flag. */
145static void
146bgp_config_set (struct bgp *bgp, int config)
147{
148 SET_FLAG (bgp->config, config);
149}
150
151static void
152bgp_config_unset (struct bgp *bgp, int config)
153{
154 UNSET_FLAG (bgp->config, config);
155}
156
157static int
158bgp_config_check (struct bgp *bgp, int config)
159{
160 return CHECK_FLAG (bgp->config, config);
161}
David Lamparter6b0655a2014-06-04 06:53:35 +0200162
paul718e3742002-12-13 20:15:29 +0000163/* Set BGP router identifier. */
David Lamparter584083d2016-05-24 18:58:08 +0200164static int
paul718e3742002-12-13 20:15:29 +0000165bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
166{
167 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000168 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000169
170 if (bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID)
171 && IPV4_ADDR_SAME (&bgp->router_id, id))
172 return 0;
173
174 IPV4_ADDR_COPY (&bgp->router_id, id);
175 bgp_config_set (bgp, BGP_CONFIG_ROUTER_ID);
176
177 /* Set all peer's local identifier with this value. */
paul1eb8ef22005-04-07 07:30:20 +0000178 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000179 {
180 IPV4_ADDR_COPY (&peer->local_id, id);
181
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000182 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000183 {
184 peer->last_reset = PEER_DOWN_RID_CHANGE;
185 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
186 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
187 }
paul718e3742002-12-13 20:15:29 +0000188 }
189 return 0;
190}
191
David Lamparter584083d2016-05-24 18:58:08 +0200192void
193bgp_router_id_zebra_bump (void)
194{
195 struct listnode *node, *nnode;
196 struct bgp *bgp;
197
198 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
199 {
200 if (!bgp->router_id_static.s_addr)
201 bgp_router_id_set (bgp, &router_id_zebra);
202 }
203}
204
205int
206bgp_router_id_static_set (struct bgp *bgp, struct in_addr id)
207{
208 bgp->router_id_static = id;
209 bgp_router_id_set (bgp, id.s_addr ? &id : &router_id_zebra);
210 return 0;
211}
212
paul718e3742002-12-13 20:15:29 +0000213/* BGP's cluster-id control. */
214int
215bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
216{
217 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000218 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000219
220 if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)
221 && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id))
222 return 0;
223
224 IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id);
225 bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID);
226
227 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000228 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000229 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000230 if (peer->sort != BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +0000231 continue;
232
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000233 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000234 {
235 peer->last_reset = PEER_DOWN_CLID_CHANGE;
236 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
237 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
238 }
paul718e3742002-12-13 20:15:29 +0000239 }
240 return 0;
241}
242
243int
244bgp_cluster_id_unset (struct bgp *bgp)
245{
246 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000247 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000248
249 if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID))
250 return 0;
251
252 bgp->cluster_id.s_addr = 0;
253 bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID);
254
255 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000256 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000257 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000258 if (peer->sort != BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +0000259 continue;
260
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000261 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000262 {
263 peer->last_reset = PEER_DOWN_CLID_CHANGE;
264 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
265 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
266 }
paul718e3742002-12-13 20:15:29 +0000267 }
268 return 0;
269}
David Lamparter6b0655a2014-06-04 06:53:35 +0200270
Stephen Hemminger65957882010-01-15 16:22:10 +0300271/* time_t value that is monotonicly increasing
272 * and uneffected by adjustments to system clock
273 */
274time_t bgp_clock (void)
275{
276 struct timeval tv;
277
278 quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv);
279 return tv.tv_sec;
280}
281
paul718e3742002-12-13 20:15:29 +0000282/* BGP timer configuration. */
283int
284bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
285{
286 bgp->default_keepalive = (keepalive < holdtime / 3
287 ? keepalive : holdtime / 3);
288 bgp->default_holdtime = holdtime;
289
290 return 0;
291}
292
293int
294bgp_timers_unset (struct bgp *bgp)
295{
296 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
297 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
298
299 return 0;
300}
David Lamparter6b0655a2014-06-04 06:53:35 +0200301
paul718e3742002-12-13 20:15:29 +0000302/* BGP confederation configuration. */
303int
304bgp_confederation_id_set (struct bgp *bgp, as_t as)
305{
306 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000307 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000308 int already_confed;
309
310 if (as == 0)
311 return BGP_ERR_INVALID_AS;
312
313 /* Remember - were we doing confederation before? */
314 already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);
315 bgp->confed_id = as;
316 bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);
317
318 /* If we were doing confederation already, this is just an external
319 AS change. Just Reset EBGP sessions, not CONFED sessions. If we
320 were not doing confederation before, reset all EBGP sessions. */
paul1eb8ef22005-04-07 07:30:20 +0000321 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000322 {
323 /* We're looking for peers who's AS is not local or part of our
324 confederation. */
325 if (already_confed)
326 {
327 if (peer_sort (peer) == BGP_PEER_EBGP)
328 {
329 peer->local_as = as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000330 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000331 {
332 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
333 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
334 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
335 }
336
paul718e3742002-12-13 20:15:29 +0000337 else
338 BGP_EVENT_ADD (peer, BGP_Stop);
339 }
340 }
341 else
342 {
343 /* Not doign confederation before, so reset every non-local
344 session */
345 if (peer_sort (peer) != BGP_PEER_IBGP)
346 {
347 /* Reset the local_as to be our EBGP one */
348 if (peer_sort (peer) == BGP_PEER_EBGP)
349 peer->local_as = as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000350 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000351 {
352 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
353 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
354 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
355 }
paul718e3742002-12-13 20:15:29 +0000356 else
357 BGP_EVENT_ADD (peer, BGP_Stop);
358 }
359 }
360 }
361 return 0;
362}
363
364int
365bgp_confederation_id_unset (struct bgp *bgp)
366{
367 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000368 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000369
370 bgp->confed_id = 0;
371 bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
372
paul1eb8ef22005-04-07 07:30:20 +0000373 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000374 {
375 /* We're looking for peers who's AS is not local */
376 if (peer_sort (peer) != BGP_PEER_IBGP)
377 {
378 peer->local_as = bgp->as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000379 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000380 {
381 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
382 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
383 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
384 }
385
paul718e3742002-12-13 20:15:29 +0000386 else
387 BGP_EVENT_ADD (peer, BGP_Stop);
388 }
389 }
390 return 0;
391}
392
393/* Is an AS part of the confed or not? */
394int
395bgp_confederation_peers_check (struct bgp *bgp, as_t as)
396{
397 int i;
398
399 if (! bgp)
400 return 0;
401
402 for (i = 0; i < bgp->confed_peers_cnt; i++)
403 if (bgp->confed_peers[i] == as)
404 return 1;
405
406 return 0;
407}
408
409/* Add an AS to the confederation set. */
410int
411bgp_confederation_peers_add (struct bgp *bgp, as_t as)
412{
413 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000414 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000415
416 if (! bgp)
417 return BGP_ERR_INVALID_BGP;
418
419 if (bgp->as == as)
420 return BGP_ERR_INVALID_AS;
421
422 if (bgp_confederation_peers_check (bgp, as))
423 return -1;
424
425 if (bgp->confed_peers)
426 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
427 bgp->confed_peers,
428 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
429 else
430 bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST,
431 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
432
433 bgp->confed_peers[bgp->confed_peers_cnt] = as;
434 bgp->confed_peers_cnt++;
435
436 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
437 {
paul1eb8ef22005-04-07 07:30:20 +0000438 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000439 {
440 if (peer->as == as)
441 {
442 peer->local_as = bgp->as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000443 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000444 {
445 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
446 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
447 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
448 }
paul718e3742002-12-13 20:15:29 +0000449 else
450 BGP_EVENT_ADD (peer, BGP_Stop);
451 }
452 }
453 }
454 return 0;
455}
456
457/* Delete an AS from the confederation set. */
458int
459bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
460{
461 int i;
462 int j;
463 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000464 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000465
466 if (! bgp)
467 return -1;
468
469 if (! bgp_confederation_peers_check (bgp, as))
470 return -1;
471
472 for (i = 0; i < bgp->confed_peers_cnt; i++)
473 if (bgp->confed_peers[i] == as)
474 for(j = i + 1; j < bgp->confed_peers_cnt; j++)
475 bgp->confed_peers[j - 1] = bgp->confed_peers[j];
476
477 bgp->confed_peers_cnt--;
478
479 if (bgp->confed_peers_cnt == 0)
480 {
481 if (bgp->confed_peers)
482 XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
483 bgp->confed_peers = NULL;
484 }
485 else
486 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
487 bgp->confed_peers,
488 bgp->confed_peers_cnt * sizeof (as_t));
489
490 /* Now reset any peer who's remote AS has just been removed from the
491 CONFED */
492 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
493 {
paul1eb8ef22005-04-07 07:30:20 +0000494 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000495 {
496 if (peer->as == as)
497 {
498 peer->local_as = bgp->confed_id;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000499 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000500 {
501 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
502 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
503 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
504 }
paul718e3742002-12-13 20:15:29 +0000505 else
506 BGP_EVENT_ADD (peer, BGP_Stop);
507 }
508 }
509 }
510
511 return 0;
512}
David Lamparter6b0655a2014-06-04 06:53:35 +0200513
paul718e3742002-12-13 20:15:29 +0000514/* Local preference configuration. */
515int
516bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
517{
518 if (! bgp)
519 return -1;
520
paul718e3742002-12-13 20:15:29 +0000521 bgp->default_local_pref = local_pref;
522
523 return 0;
524}
525
526int
527bgp_default_local_preference_unset (struct bgp *bgp)
528{
529 if (! bgp)
530 return -1;
531
paul718e3742002-12-13 20:15:29 +0000532 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
533
534 return 0;
535}
David Lamparter6b0655a2014-06-04 06:53:35 +0200536
paulfee0f4c2004-09-13 05:12:46 +0000537/* If peer is RSERVER_CLIENT in at least one address family and is not member
538 of a peer_group for that family, return 1.
539 Used to check wether the peer is included in list bgp->rsclient. */
540int
541peer_rsclient_active (struct peer *peer)
542{
543 int i;
544 int j;
545
546 for (i=AFI_IP; i < AFI_MAX; i++)
547 for (j=SAFI_UNICAST; j < SAFI_MAX; j++)
548 if (CHECK_FLAG(peer->af_flags[i][j], PEER_FLAG_RSERVER_CLIENT)
549 && ! peer->af_group[i][j])
550 return 1;
551 return 0;
552}
553
pauleb821182004-05-01 08:44:08 +0000554/* Peer comparison function for sorting. */
paul718e3742002-12-13 20:15:29 +0000555static int
556peer_cmp (struct peer *p1, struct peer *p2)
557{
pauleb821182004-05-01 08:44:08 +0000558 return sockunion_cmp (&p1->su, &p2->su);
paul718e3742002-12-13 20:15:29 +0000559}
560
561int
562peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
563{
564 return CHECK_FLAG (peer->af_flags[afi][safi], flag);
565}
566
567/* Reset all address family specific configuration. */
568static void
569peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
570{
571 int i;
572 struct bgp_filter *filter;
573 char orf_name[BUFSIZ];
574
575 filter = &peer->filter[afi][safi];
576
577 /* Clear neighbor filter and route-map */
578 for (i = FILTER_IN; i < FILTER_MAX; i++)
579 {
580 if (filter->dlist[i].name)
581 {
582 free (filter->dlist[i].name);
583 filter->dlist[i].name = NULL;
584 }
585 if (filter->plist[i].name)
586 {
587 free (filter->plist[i].name);
588 filter->plist[i].name = NULL;
589 }
590 if (filter->aslist[i].name)
591 {
592 free (filter->aslist[i].name);
593 filter->aslist[i].name = NULL;
594 }
paulfee0f4c2004-09-13 05:12:46 +0000595 }
596 for (i = RMAP_IN; i < RMAP_MAX; i++)
597 {
paul718e3742002-12-13 20:15:29 +0000598 if (filter->map[i].name)
599 {
600 free (filter->map[i].name);
601 filter->map[i].name = NULL;
602 }
603 }
604
605 /* Clear unsuppress map. */
606 if (filter->usmap.name)
607 free (filter->usmap.name);
608 filter->usmap.name = NULL;
609 filter->usmap.map = NULL;
610
611 /* Clear neighbor's all address family flags. */
612 peer->af_flags[afi][safi] = 0;
613
614 /* Clear neighbor's all address family sflags. */
615 peer->af_sflags[afi][safi] = 0;
616
617 /* Clear neighbor's all address family capabilities. */
618 peer->af_cap[afi][safi] = 0;
619
620 /* Clear ORF info */
621 peer->orf_plist[afi][safi] = NULL;
622 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
David Lamparterc9c06d02015-04-13 10:21:35 +0200623 prefix_bgp_orf_remove_all (afi, orf_name);
paul718e3742002-12-13 20:15:29 +0000624
625 /* Set default neighbor send-community. */
626 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
627 {
628 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
629 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
Job Snijders3334bab2017-01-20 14:47:12 +0000630 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_LARGE_COMMUNITY);
paul718e3742002-12-13 20:15:29 +0000631 }
632
633 /* Clear neighbor default_originate_rmap */
634 if (peer->default_rmap[afi][safi].name)
635 free (peer->default_rmap[afi][safi].name);
636 peer->default_rmap[afi][safi].name = NULL;
637 peer->default_rmap[afi][safi].map = NULL;
638
639 /* Clear neighbor maximum-prefix */
640 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +0000641 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000642}
643
644/* peer global config reset */
paul94f2b392005-06-28 12:44:16 +0000645static void
paul718e3742002-12-13 20:15:29 +0000646peer_global_config_reset (struct peer *peer)
647{
648 peer->weight = 0;
649 peer->change_local_as = 0;
Timo Teräse3443a22016-10-19 16:02:34 +0300650 peer->ttl = 0;
651 peer->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +0000652 if (peer->update_source)
653 {
654 sockunion_free (peer->update_source);
655 peer->update_source = NULL;
656 }
657 if (peer->update_if)
658 {
659 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
660 peer->update_if = NULL;
661 }
662
663 if (peer_sort (peer) == BGP_PEER_IBGP)
664 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
665 else
666 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
667
668 peer->flags = 0;
669 peer->config = 0;
670 peer->holdtime = 0;
671 peer->keepalive = 0;
672 peer->connect = 0;
673 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
674}
675
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000676/* Check peer's AS number and determines if this peer is IBGP or EBGP */
677static bgp_peer_sort_t
678peer_calc_sort (struct peer *peer)
paul718e3742002-12-13 20:15:29 +0000679{
680 struct bgp *bgp;
681
682 bgp = peer->bgp;
683
684 /* Peer-group */
685 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
686 {
687 if (peer->as)
688 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
689 else
690 {
691 struct peer *peer1;
692 peer1 = listnode_head (peer->group->peer);
693 if (peer1)
694 return (peer1->local_as == peer1->as
695 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
696 }
697 return BGP_PEER_INTERNAL;
698 }
699
700 /* Normal peer */
701 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
702 {
703 if (peer->local_as == 0)
704 return BGP_PEER_INTERNAL;
705
706 if (peer->local_as == peer->as)
707 {
708 if (peer->local_as == bgp->confed_id)
709 return BGP_PEER_EBGP;
710 else
711 return BGP_PEER_IBGP;
712 }
713
714 if (bgp_confederation_peers_check (bgp, peer->as))
715 return BGP_PEER_CONFED;
716
717 return BGP_PEER_EBGP;
718 }
719 else
720 {
721 return (peer->local_as == 0
722 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
723 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
724 }
725}
726
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000727/* Calculate and cache the peer "sort" */
728bgp_peer_sort_t
729peer_sort (struct peer *peer)
730{
731 peer->sort = peer_calc_sort (peer);
732 return peer->sort;
733}
734
Paul Jakmaf63f06d2011-04-08 12:44:43 +0100735static void
paul200df112005-06-01 11:17:05 +0000736peer_free (struct peer *peer)
737{
Paul Jakmaca058a32006-09-14 02:58:49 +0000738 assert (peer->status == Deleted);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700739
Paul Jakmaca058a32006-09-14 02:58:49 +0000740 /* this /ought/ to have been done already through bgp_stop earlier,
741 * but just to be sure..
742 */
743 bgp_timer_set (peer);
744 BGP_READ_OFF (peer->t_read);
745 BGP_WRITE_OFF (peer->t_write);
Paul Jakma9fde6622006-09-14 03:02:02 +0000746 BGP_EVENT_FLUSH (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +0000747
paul200df112005-06-01 11:17:05 +0000748 if (peer->desc)
Daniel Walton363c9032015-10-21 06:42:54 -0700749 {
750 XFREE (MTYPE_PEER_DESC, peer->desc);
751 peer->desc = NULL;
752 }
paul200df112005-06-01 11:17:05 +0000753
754 /* Free allocated host character. */
755 if (peer->host)
Daniel Walton363c9032015-10-21 06:42:54 -0700756 {
757 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
758 peer->host = NULL;
759 }
760
paul200df112005-06-01 11:17:05 +0000761 /* Update source configuration. */
762 if (peer->update_source)
Daniel Walton363c9032015-10-21 06:42:54 -0700763 {
764 sockunion_free (peer->update_source);
765 peer->update_source = NULL;
766 }
paul200df112005-06-01 11:17:05 +0000767
768 if (peer->update_if)
Daniel Walton363c9032015-10-21 06:42:54 -0700769 {
770 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
771 peer->update_if = NULL;
772 }
Paul Jakmaa625ca32006-03-30 14:12:38 +0000773
774 if (peer->clear_node_queue)
Daniel Walton363c9032015-10-21 06:42:54 -0700775 {
776 work_queue_free(peer->clear_node_queue);
777 peer->clear_node_queue = NULL;
778 }
Paul Jakmaa625ca32006-03-30 14:12:38 +0000779
Lou Berger056f3762013-04-10 12:30:04 -0700780 if (peer->notify.data)
781 XFREE(MTYPE_TMP, peer->notify.data);
782
Paul Jakmaca058a32006-09-14 02:58:49 +0000783 bgp_sync_delete (peer);
Renato Westphal670f3db2016-11-28 16:47:13 -0200784
785 bgp_unlock(peer->bgp);
786
paul200df112005-06-01 11:17:05 +0000787 memset (peer, 0, sizeof (struct peer));
788
789 XFREE (MTYPE_BGP_PEER, peer);
790}
791
792/* increase reference count on a struct peer */
793struct peer *
Donald Sharp104576d2015-09-16 13:17:55 -0400794peer_lock_with_caller (const char *name, struct peer *peer)
paul200df112005-06-01 11:17:05 +0000795{
796 assert (peer && (peer->lock >= 0));
Donald Sharp104576d2015-09-16 13:17:55 -0400797
798#if 0
799 zlog_debug("%s peer_lock %p %d", name, peer, peer->lock);
800#endif
801
paul200df112005-06-01 11:17:05 +0000802 peer->lock++;
803
804 return peer;
805}
806
807/* decrease reference count on a struct peer
808 * struct peer is freed and NULL returned if last reference
809 */
810struct peer *
Donald Sharp104576d2015-09-16 13:17:55 -0400811peer_unlock_with_caller (const char *name, struct peer *peer)
paul200df112005-06-01 11:17:05 +0000812{
813 assert (peer && (peer->lock > 0));
Donald Sharp104576d2015-09-16 13:17:55 -0400814
815#if 0
816 zlog_debug("%s peer_unlock %p %d", name, peer, peer->lock);
817#endif
818
paul200df112005-06-01 11:17:05 +0000819 peer->lock--;
820
821 if (peer->lock == 0)
822 {
paul200df112005-06-01 11:17:05 +0000823 peer_free (peer);
824 return NULL;
825 }
826
paul200df112005-06-01 11:17:05 +0000827 return peer;
828}
829
830/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000831static struct peer *
Paul Jakma6f585442006-10-22 19:13:07 +0000832peer_new (struct bgp *bgp)
paul718e3742002-12-13 20:15:29 +0000833{
834 afi_t afi;
835 safi_t safi;
836 struct peer *peer;
837 struct servent *sp;
Paul Jakma6f585442006-10-22 19:13:07 +0000838
839 /* bgp argument is absolutely required */
840 assert (bgp);
841 if (!bgp)
842 return NULL;
843
paul718e3742002-12-13 20:15:29 +0000844 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000845 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000846
847 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000848 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000849 peer->v_start = BGP_INIT_START_TIMER;
850 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
paul718e3742002-12-13 20:15:29 +0000851 peer->status = Idle;
852 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000853 peer->weight = 0;
Paul Jakma0df7c912008-07-21 21:02:49 +0000854 peer->password = NULL;
Paul Jakma6f585442006-10-22 19:13:07 +0000855 peer->bgp = bgp;
Paul Jakmaca058a32006-09-14 02:58:49 +0000856 peer = peer_lock (peer); /* initial reference */
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700857 bgp_lock (bgp);
paul718e3742002-12-13 20:15:29 +0000858
859 /* Set default flags. */
860 for (afi = AFI_IP; afi < AFI_MAX; afi++)
861 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
862 {
863 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
864 {
865 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
866 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
Job Snijders3334bab2017-01-20 14:47:12 +0000867 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_LARGE_COMMUNITY);
paul718e3742002-12-13 20:15:29 +0000868 }
869 peer->orf_plist[afi][safi] = NULL;
870 }
871 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
872
873 /* Create buffers. */
874 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
875 peer->obuf = stream_fifo_new ();
Daniel Walton5bcd7542015-05-19 17:58:10 -0700876
877 /* We use a larger buffer for peer->work in the event that:
878 * - We RX a BGP_UPDATE where the attributes alone are just
879 * under BGP_MAX_PACKET_SIZE
880 * - The user configures an outbound route-map that does many as-path
881 * prepends or adds many communities. At most they can have CMD_ARGC_MAX
882 * args in a route-map so there is a finite limit on how large they can
883 * make the attributes.
884 *
885 * Having a buffer with BGP_MAX_PACKET_SIZE_OVERFLOW allows us to avoid bounds
886 * checking for every single attribute as we construct an UPDATE.
887 */
888 peer->work = stream_new (BGP_MAX_PACKET_SIZE + BGP_MAX_PACKET_SIZE_OVERFLOW);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000889 peer->scratch = stream_new (BGP_MAX_PACKET_SIZE);
paul718e3742002-12-13 20:15:29 +0000890
891 bgp_sync_init (peer);
892
893 /* Get service port number. */
894 sp = getservbyname ("bgp", "tcp");
895 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
896
897 return peer;
898}
899
900/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000901static struct peer *
paul718e3742002-12-13 20:15:29 +0000902peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
903 as_t remote_as, afi_t afi, safi_t safi)
904{
905 int active;
906 struct peer *peer;
907 char buf[SU_ADDRSTRLEN];
908
Paul Jakma6f585442006-10-22 19:13:07 +0000909 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000910 peer->su = *su;
911 peer->local_as = local_as;
912 peer->as = remote_as;
913 peer->local_id = bgp->router_id;
914 peer->v_holdtime = bgp->default_holdtime;
915 peer->v_keepalive = bgp->default_keepalive;
916 if (peer_sort (peer) == BGP_PEER_IBGP)
917 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
918 else
919 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000920
921 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000922 listnode_add_sort (bgp->peer, peer);
923
924 active = peer_active (peer);
925
926 if (afi && safi)
927 peer->afc[afi][safi] = 1;
928
Stephen Hemminger65957882010-01-15 16:22:10 +0300929 /* Last read and reset time set */
930 peer->readtime = peer->resettime = bgp_clock ();
paul848973c2003-08-13 00:32:49 +0000931
paul718e3742002-12-13 20:15:29 +0000932 /* Make peer's address string. */
933 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000934 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000935
936 /* Set up peer's events and timers. */
937 if (! active && peer_active (peer))
938 bgp_timer_set (peer);
939
940 return peer;
941}
942
pauleb821182004-05-01 08:44:08 +0000943/* Make accept BGP peer. Called from bgp_accept (). */
944struct peer *
945peer_create_accept (struct bgp *bgp)
946{
947 struct peer *peer;
948
Paul Jakma6f585442006-10-22 19:13:07 +0000949 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000950
951 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000952 listnode_add_sort (bgp->peer, peer);
953
954 return peer;
955}
956
paul718e3742002-12-13 20:15:29 +0000957/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000958static void
paul718e3742002-12-13 20:15:29 +0000959peer_as_change (struct peer *peer, as_t as)
960{
Daniel Walton0d7435f2015-10-22 11:35:20 +0300961 struct peer *conf;
paul718e3742002-12-13 20:15:29 +0000962
963 /* Stop peer. */
964 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
965 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000966 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000967 {
968 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
969 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
970 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
971 }
paul718e3742002-12-13 20:15:29 +0000972 else
973 BGP_EVENT_ADD (peer, BGP_Stop);
974 }
paul718e3742002-12-13 20:15:29 +0000975 peer->as = as;
976
paul848973c2003-08-13 00:32:49 +0000977 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
978 && ! bgp_confederation_peers_check (peer->bgp, as)
979 && peer->bgp->as != as)
980 peer->local_as = peer->bgp->confed_id;
981 else
982 peer->local_as = peer->bgp->as;
983
paul718e3742002-12-13 20:15:29 +0000984 /* Advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +0300985 conf = NULL;
986 if (peer->group)
987 conf = peer->group->conf;
988
989 if (conf && CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
990 peer->v_routeadv = conf->routeadv;
paul718e3742002-12-13 20:15:29 +0000991 else
Daniel Walton0d7435f2015-10-22 11:35:20 +0300992 if (peer_sort (peer) == BGP_PEER_IBGP)
993 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
994 else
995 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul718e3742002-12-13 20:15:29 +0000996
paul718e3742002-12-13 20:15:29 +0000997 /* reflector-client reset */
998 if (peer_sort (peer) != BGP_PEER_IBGP)
999 {
1000 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
1001 PEER_FLAG_REFLECTOR_CLIENT);
1002 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
1003 PEER_FLAG_REFLECTOR_CLIENT);
1004 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
1005 PEER_FLAG_REFLECTOR_CLIENT);
Lou Berger298cc2f2016-01-12 13:42:02 -05001006 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_ENCAP],
1007 PEER_FLAG_REFLECTOR_CLIENT);
paul718e3742002-12-13 20:15:29 +00001008 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
1009 PEER_FLAG_REFLECTOR_CLIENT);
1010 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
1011 PEER_FLAG_REFLECTOR_CLIENT);
Lou Berger9da04bc2016-01-12 13:41:55 -05001012 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MPLS_VPN],
1013 PEER_FLAG_REFLECTOR_CLIENT);
Lou Berger298cc2f2016-01-12 13:42:02 -05001014 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_ENCAP],
1015 PEER_FLAG_REFLECTOR_CLIENT);
paul718e3742002-12-13 20:15:29 +00001016 }
1017
1018 /* local-as reset */
1019 if (peer_sort (peer) != BGP_PEER_EBGP)
1020 {
1021 peer->change_local_as = 0;
1022 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001023 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001024 }
1025}
1026
1027/* If peer does not exist, create new one. If peer already exists,
1028 set AS number to the peer. */
1029int
1030peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
1031 afi_t afi, safi_t safi)
1032{
1033 struct peer *peer;
1034 as_t local_as;
1035
1036 peer = peer_lookup (bgp, su);
1037
1038 if (peer)
1039 {
1040 /* When this peer is a member of peer-group. */
1041 if (peer->group)
1042 {
1043 if (peer->group->conf->as)
1044 {
1045 /* Return peer group's AS number. */
1046 *as = peer->group->conf->as;
1047 return BGP_ERR_PEER_GROUP_MEMBER;
1048 }
1049 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
1050 {
1051 if (bgp->as != *as)
1052 {
1053 *as = peer->as;
1054 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1055 }
1056 }
1057 else
1058 {
1059 if (bgp->as == *as)
1060 {
1061 *as = peer->as;
1062 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1063 }
1064 }
1065 }
1066
1067 /* Existing peer's AS number change. */
1068 if (peer->as != *as)
1069 peer_as_change (peer, *as);
1070 }
1071 else
1072 {
1073
1074 /* If the peer is not part of our confederation, and its not an
1075 iBGP peer then spoof the source AS */
1076 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1077 && ! bgp_confederation_peers_check (bgp, *as)
1078 && bgp->as != *as)
1079 local_as = bgp->confed_id;
1080 else
1081 local_as = bgp->as;
1082
1083 /* If this is IPv4 unicast configuration and "no bgp default
1084 ipv4-unicast" is specified. */
1085
1086 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1087 && afi == AFI_IP && safi == SAFI_UNICAST)
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001088 peer_create (su, bgp, local_as, *as, 0, 0);
paul718e3742002-12-13 20:15:29 +00001089 else
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001090 peer_create (su, bgp, local_as, *as, afi, safi);
paul718e3742002-12-13 20:15:29 +00001091 }
1092
1093 return 0;
1094}
1095
1096/* Activate the peer or peer group for specified AFI and SAFI. */
1097int
1098peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1099{
1100 int active;
1101
1102 if (peer->afc[afi][safi])
1103 return 0;
1104
1105 /* Activate the address family configuration. */
1106 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1107 peer->afc[afi][safi] = 1;
1108 else
1109 {
1110 active = peer_active (peer);
1111
1112 peer->afc[afi][safi] = 1;
1113
1114 if (! active && peer_active (peer))
1115 bgp_timer_set (peer);
1116 else
1117 {
1118 if (peer->status == Established)
1119 {
1120 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1121 {
1122 peer->afc_adv[afi][safi] = 1;
1123 bgp_capability_send (peer, afi, safi,
1124 CAPABILITY_CODE_MP,
1125 CAPABILITY_ACTION_SET);
1126 if (peer->afc_recv[afi][safi])
1127 {
1128 peer->afc_nego[afi][safi] = 1;
1129 bgp_announce_route (peer, afi, safi);
1130 }
1131 }
1132 else
hassoe0701b72004-05-20 09:19:34 +00001133 {
1134 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1135 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1136 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1137 }
paul718e3742002-12-13 20:15:29 +00001138 }
1139 }
1140 }
1141 return 0;
1142}
1143
1144int
1145peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1146{
1147 struct peer_group *group;
1148 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001149 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001150
1151 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1152 {
1153 group = peer->group;
1154
paul1eb8ef22005-04-07 07:30:20 +00001155 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001156 {
1157 if (peer1->af_group[afi][safi])
1158 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1159 }
1160 }
1161 else
1162 {
1163 if (peer->af_group[afi][safi])
1164 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1165 }
1166
1167 if (! peer->afc[afi][safi])
1168 return 0;
1169
1170 /* De-activate the address family configuration. */
1171 peer->afc[afi][safi] = 0;
1172 peer_af_flag_reset (peer, afi, safi);
1173
1174 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1175 {
1176 if (peer->status == Established)
1177 {
1178 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1179 {
1180 peer->afc_adv[afi][safi] = 0;
1181 peer->afc_nego[afi][safi] = 0;
1182
1183 if (peer_active_nego (peer))
1184 {
1185 bgp_capability_send (peer, afi, safi,
1186 CAPABILITY_CODE_MP,
1187 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001188 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001189 peer->pcount[afi][safi] = 0;
1190 }
1191 else
hassoe0701b72004-05-20 09:19:34 +00001192 {
1193 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1194 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1195 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1196 }
paul718e3742002-12-13 20:15:29 +00001197 }
1198 else
hassoe0701b72004-05-20 09:19:34 +00001199 {
1200 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1201 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1202 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1203 }
paul718e3742002-12-13 20:15:29 +00001204 }
1205 }
1206 return 0;
1207}
1208
David Lamparterdfb9bd72016-05-24 18:58:07 +02001209int
1210peer_afc_set (struct peer *peer, afi_t afi, safi_t safi, int enable)
1211{
1212 if (enable)
1213 return peer_activate (peer, afi, safi);
1214 else
1215 return peer_deactivate (peer, afi, safi);
1216}
1217
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001218static void
hasso93406d82005-02-02 14:40:33 +00001219peer_nsf_stop (struct peer *peer)
1220{
1221 afi_t afi;
1222 safi_t safi;
1223
1224 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1225 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1226
1227 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +04001228 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +00001229 peer->nsf[afi][safi] = 0;
1230
1231 if (peer->t_gr_restart)
1232 {
1233 BGP_TIMER_OFF (peer->t_gr_restart);
1234 if (BGP_DEBUG (events, EVENTS))
1235 zlog_debug ("%s graceful restart timer stopped", peer->host);
1236 }
1237 if (peer->t_gr_stale)
1238 {
1239 BGP_TIMER_OFF (peer->t_gr_stale);
1240 if (BGP_DEBUG (events, EVENTS))
1241 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1242 }
1243 bgp_clear_route_all (peer);
1244}
1245
Paul Jakmaca058a32006-09-14 02:58:49 +00001246/* Delete peer from confguration.
1247 *
1248 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1249 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1250 *
1251 * This function /should/ take care to be idempotent, to guard against
1252 * it being called multiple times through stray events that come in
1253 * that happen to result in this function being called again. That
1254 * said, getting here for a "Deleted" peer is a bug in the neighbour
1255 * FSM.
1256 */
paul718e3742002-12-13 20:15:29 +00001257int
1258peer_delete (struct peer *peer)
1259{
1260 int i;
1261 afi_t afi;
1262 safi_t safi;
1263 struct bgp *bgp;
1264 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001265 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001266
Paul Jakmaca058a32006-09-14 02:58:49 +00001267 assert (peer->status != Deleted);
1268
paul718e3742002-12-13 20:15:29 +00001269 bgp = peer->bgp;
1270
hasso93406d82005-02-02 14:40:33 +00001271 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1272 peer_nsf_stop (peer);
1273
Chris Caputo228da422009-07-18 05:44:03 +00001274 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001275 relationship. */
1276 if (peer->group)
1277 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001278 if ((pn = listnode_lookup (peer->group->peer, peer)))
1279 {
1280 peer = peer_unlock (peer); /* group->peer list reference */
1281 list_delete_node (peer->group->peer, pn);
1282 }
paul718e3742002-12-13 20:15:29 +00001283 peer->group = NULL;
1284 }
paul200df112005-06-01 11:17:05 +00001285
paul718e3742002-12-13 20:15:29 +00001286 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001287 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1288 * executed after peer structure is deleted.
1289 */
hassoe0701b72004-05-20 09:19:34 +00001290 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001291 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001292 bgp_fsm_change_status (peer, Deleted);
Paul Jakma19e6c192016-09-06 17:23:48 +01001293
1294 /* Remove from NHT */
1295 bgp_unlink_nexthop_by_peer (peer);
1296
Paul Jakma0df7c912008-07-21 21:02:49 +00001297 /* Password configuration */
1298 if (peer->password)
1299 {
1300 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1301 peer->password = NULL;
1302
1303 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1304 bgp_md5_set (peer);
1305 }
1306
Paul Jakmaca058a32006-09-14 02:58:49 +00001307 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001308
paul718e3742002-12-13 20:15:29 +00001309 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001310 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1311 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001312 {
Chris Caputo228da422009-07-18 05:44:03 +00001313 peer_unlock (peer); /* bgp peer list reference */
1314 list_delete_node (bgp->peer, pn);
1315 }
paul200df112005-06-01 11:17:05 +00001316
Chris Caputo228da422009-07-18 05:44:03 +00001317 if (peer_rsclient_active (peer)
1318 && (pn = listnode_lookup (bgp->rsclient, peer)))
1319 {
1320 peer_unlock (peer); /* rsclient list reference */
1321 list_delete_node (bgp->rsclient, pn);
1322
1323 /* Clear our own rsclient ribs. */
1324 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1325 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1326 if (CHECK_FLAG(peer->af_flags[afi][safi],
1327 PEER_FLAG_RSERVER_CLIENT))
1328 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001329 }
1330
1331 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1332 member of a peer_group. */
1333 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1334 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1335 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001336 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001337
paul200df112005-06-01 11:17:05 +00001338 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001339 if (peer->ibuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001340 {
1341 stream_free (peer->ibuf);
1342 peer->ibuf = NULL;
1343 }
1344
paul718e3742002-12-13 20:15:29 +00001345 if (peer->obuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001346 {
1347 stream_fifo_free (peer->obuf);
1348 peer->obuf = NULL;
1349 }
1350
paul718e3742002-12-13 20:15:29 +00001351 if (peer->work)
Daniel Walton363c9032015-10-21 06:42:54 -07001352 {
1353 stream_free (peer->work);
1354 peer->work = NULL;
1355 }
1356
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00001357 if (peer->scratch)
Daniel Walton363c9032015-10-21 06:42:54 -07001358 {
1359 stream_free(peer->scratch);
1360 peer->scratch = NULL;
1361 }
Paul Jakma18937402006-07-27 19:05:12 +00001362
paul718e3742002-12-13 20:15:29 +00001363 /* Local and remote addresses. */
1364 if (peer->su_local)
Daniel Walton363c9032015-10-21 06:42:54 -07001365 {
1366 sockunion_free (peer->su_local);
1367 peer->su_local = NULL;
1368 }
1369
paul718e3742002-12-13 20:15:29 +00001370 if (peer->su_remote)
Daniel Walton363c9032015-10-21 06:42:54 -07001371 {
1372 sockunion_free (peer->su_remote);
1373 peer->su_remote = NULL;
1374 }
paul200df112005-06-01 11:17:05 +00001375
paul718e3742002-12-13 20:15:29 +00001376 /* Free filter related memory. */
1377 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1378 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1379 {
1380 filter = &peer->filter[afi][safi];
1381
1382 for (i = FILTER_IN; i < FILTER_MAX; i++)
1383 {
1384 if (filter->dlist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001385 {
1386 free(filter->dlist[i].name);
1387 filter->dlist[i].name = NULL;
1388 }
1389
paul718e3742002-12-13 20:15:29 +00001390 if (filter->plist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001391 {
1392 free(filter->plist[i].name);
1393 filter->plist[i].name = NULL;
1394 }
1395
paul718e3742002-12-13 20:15:29 +00001396 if (filter->aslist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001397 {
1398 free(filter->aslist[i].name);
1399 filter->aslist[i].name = NULL;
1400 }
paul200df112005-06-01 11:17:05 +00001401 }
Daniel Walton363c9032015-10-21 06:42:54 -07001402
paul200df112005-06-01 11:17:05 +00001403 for (i = RMAP_IN; i < RMAP_MAX; i++)
1404 {
paul718e3742002-12-13 20:15:29 +00001405 if (filter->map[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001406 {
1407 free (filter->map[i].name);
1408 filter->map[i].name = NULL;
1409 }
paul718e3742002-12-13 20:15:29 +00001410 }
1411
1412 if (filter->usmap.name)
Daniel Walton363c9032015-10-21 06:42:54 -07001413 {
1414 free (filter->usmap.name);
1415 filter->usmap.name = NULL;
1416 }
paul718e3742002-12-13 20:15:29 +00001417
1418 if (peer->default_rmap[afi][safi].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001419 {
1420 free (peer->default_rmap[afi][safi].name);
1421 peer->default_rmap[afi][safi].name = NULL;
1422 }
paul718e3742002-12-13 20:15:29 +00001423 }
paul200df112005-06-01 11:17:05 +00001424
Lou Berger82dd7072016-01-12 13:41:57 -05001425 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETING))
1426 bgp_peer_clear_node_queue_drain_immediate(peer);
1427
paul200df112005-06-01 11:17:05 +00001428 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001429
1430 return 0;
1431}
David Lamparter6b0655a2014-06-04 06:53:35 +02001432
paul94f2b392005-06-28 12:44:16 +00001433static int
paul718e3742002-12-13 20:15:29 +00001434peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1435{
1436 return strcmp (g1->name, g2->name);
1437}
1438
1439/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001440static int
paul718e3742002-12-13 20:15:29 +00001441peer_group_active (struct peer *peer)
1442{
1443 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1444 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1445 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05001446 || peer->af_group[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00001447 || peer->af_group[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05001448 || peer->af_group[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05001449 || peer->af_group[AFI_IP6][SAFI_MPLS_VPN]
1450 || peer->af_group[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00001451 return 1;
1452 return 0;
1453}
1454
1455/* Peer group cofiguration. */
1456static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001457peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001458{
1459 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1460 sizeof (struct peer_group));
1461}
1462
paul94f2b392005-06-28 12:44:16 +00001463static void
paul718e3742002-12-13 20:15:29 +00001464peer_group_free (struct peer_group *group)
1465{
1466 XFREE (MTYPE_PEER_GROUP, group);
1467}
1468
1469struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001470peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001471{
1472 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001473 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001474
paul1eb8ef22005-04-07 07:30:20 +00001475 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001476 {
1477 if (strcmp (group->name, name) == 0)
1478 return group;
1479 }
1480 return NULL;
1481}
1482
1483struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001484peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001485{
1486 struct peer_group *group;
1487
1488 group = peer_group_lookup (bgp, name);
1489 if (group)
1490 return group;
1491
1492 group = peer_group_new ();
1493 group->bgp = bgp;
1494 group->name = strdup (name);
1495 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001496 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001497 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1498 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001499 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001500 group->conf->group = group;
1501 group->conf->as = 0;
Timo Teräse3443a22016-10-19 16:02:34 +03001502 group->conf->ttl = 0;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001503 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001504 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1505 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1506 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1507 group->conf->keepalive = 0;
1508 group->conf->holdtime = 0;
1509 group->conf->connect = 0;
1510 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1511 listnode_add_sort (bgp->group, group);
1512
1513 return 0;
1514}
1515
paul94f2b392005-06-28 12:44:16 +00001516static void
paul718e3742002-12-13 20:15:29 +00001517peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1518 afi_t afi, safi_t safi)
1519{
1520 int in = FILTER_IN;
1521 int out = FILTER_OUT;
1522 struct peer *conf;
1523 struct bgp_filter *pfilter;
1524 struct bgp_filter *gfilter;
1525
1526 conf = group->conf;
1527 pfilter = &peer->filter[afi][safi];
1528 gfilter = &conf->filter[afi][safi];
1529
1530 /* remote-as */
1531 if (conf->as)
1532 peer->as = conf->as;
1533
1534 /* remote-as */
1535 if (conf->change_local_as)
1536 peer->change_local_as = conf->change_local_as;
1537
1538 /* TTL */
1539 peer->ttl = conf->ttl;
1540
Nick Hilliardfa411a22011-03-23 15:33:17 +00001541 /* GTSM hops */
1542 peer->gtsm_hops = conf->gtsm_hops;
1543
paul718e3742002-12-13 20:15:29 +00001544 /* Weight */
1545 peer->weight = conf->weight;
1546
1547 /* peer flags apply */
1548 peer->flags = conf->flags;
1549 /* peer af_flags apply */
1550 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1551 /* peer config apply */
1552 peer->config = conf->config;
1553
1554 /* peer timers apply */
1555 peer->holdtime = conf->holdtime;
1556 peer->keepalive = conf->keepalive;
1557 peer->connect = conf->connect;
1558 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1559 peer->v_connect = conf->connect;
1560 else
1561 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1562
1563 /* advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +03001564 if (CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
1565 peer->v_routeadv = conf->routeadv;
paul718e3742002-12-13 20:15:29 +00001566 else
Daniel Walton0d7435f2015-10-22 11:35:20 +03001567 if (peer_sort (peer) == BGP_PEER_IBGP)
1568 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1569 else
1570 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul718e3742002-12-13 20:15:29 +00001571
Paul Jakma0df7c912008-07-21 21:02:49 +00001572 /* password apply */
Roman Hoog Antink0e4303d2013-01-18 13:52:03 +01001573 if (conf->password && !peer->password)
Paul Jakma0df7c912008-07-21 21:02:49 +00001574 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
Paul Jakma0df7c912008-07-21 21:02:49 +00001575
1576 bgp_md5_set (peer);
1577
paul718e3742002-12-13 20:15:29 +00001578 /* maximum-prefix */
1579 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001580 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001581 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001582
1583 /* allowas-in */
1584 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1585
paulfee0f4c2004-09-13 05:12:46 +00001586 /* route-server-client */
1587 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1588 {
1589 /* Make peer's RIB point to group's RIB. */
1590 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1591
1592 /* Import policy. */
1593 if (pfilter->map[RMAP_IMPORT].name)
1594 free (pfilter->map[RMAP_IMPORT].name);
1595 if (gfilter->map[RMAP_IMPORT].name)
1596 {
1597 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1598 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1599 }
1600 else
1601 {
1602 pfilter->map[RMAP_IMPORT].name = NULL;
1603 pfilter->map[RMAP_IMPORT].map = NULL;
1604 }
1605
1606 /* Export policy. */
1607 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1608 {
1609 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1610 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1611 }
1612 }
1613
paul718e3742002-12-13 20:15:29 +00001614 /* default-originate route-map */
1615 if (conf->default_rmap[afi][safi].name)
1616 {
1617 if (peer->default_rmap[afi][safi].name)
1618 free (peer->default_rmap[afi][safi].name);
1619 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1620 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1621 }
1622
1623 /* update-source apply */
1624 if (conf->update_source)
1625 {
1626 if (peer->update_source)
1627 sockunion_free (peer->update_source);
1628 if (peer->update_if)
1629 {
1630 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1631 peer->update_if = NULL;
1632 }
1633 peer->update_source = sockunion_dup (conf->update_source);
1634 }
1635 else if (conf->update_if)
1636 {
1637 if (peer->update_if)
1638 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1639 if (peer->update_source)
1640 {
1641 sockunion_free (peer->update_source);
1642 peer->update_source = NULL;
1643 }
1644 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1645 }
1646
1647 /* inbound filter apply */
1648 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1649 {
1650 if (pfilter->dlist[in].name)
1651 free (pfilter->dlist[in].name);
1652 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1653 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1654 }
1655 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1656 {
1657 if (pfilter->plist[in].name)
1658 free (pfilter->plist[in].name);
1659 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1660 pfilter->plist[in].plist = gfilter->plist[in].plist;
1661 }
1662 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1663 {
1664 if (pfilter->aslist[in].name)
1665 free (pfilter->aslist[in].name);
1666 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1667 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1668 }
paulfee0f4c2004-09-13 05:12:46 +00001669 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001670 {
paulfee0f4c2004-09-13 05:12:46 +00001671 if (pfilter->map[RMAP_IN].name)
1672 free (pfilter->map[RMAP_IN].name);
1673 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1674 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001675 }
1676
1677 /* outbound filter apply */
1678 if (gfilter->dlist[out].name)
1679 {
1680 if (pfilter->dlist[out].name)
1681 free (pfilter->dlist[out].name);
1682 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1683 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1684 }
1685 else
1686 {
1687 if (pfilter->dlist[out].name)
1688 free (pfilter->dlist[out].name);
1689 pfilter->dlist[out].name = NULL;
1690 pfilter->dlist[out].alist = NULL;
1691 }
1692 if (gfilter->plist[out].name)
1693 {
1694 if (pfilter->plist[out].name)
1695 free (pfilter->plist[out].name);
1696 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1697 pfilter->plist[out].plist = gfilter->plist[out].plist;
1698 }
1699 else
1700 {
1701 if (pfilter->plist[out].name)
1702 free (pfilter->plist[out].name);
1703 pfilter->plist[out].name = NULL;
1704 pfilter->plist[out].plist = NULL;
1705 }
1706 if (gfilter->aslist[out].name)
1707 {
1708 if (pfilter->aslist[out].name)
1709 free (pfilter->aslist[out].name);
1710 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1711 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1712 }
1713 else
1714 {
1715 if (pfilter->aslist[out].name)
1716 free (pfilter->aslist[out].name);
1717 pfilter->aslist[out].name = NULL;
1718 pfilter->aslist[out].aslist = NULL;
1719 }
paulfee0f4c2004-09-13 05:12:46 +00001720 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001721 {
paulfee0f4c2004-09-13 05:12:46 +00001722 if (pfilter->map[RMAP_OUT].name)
1723 free (pfilter->map[RMAP_OUT].name);
1724 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1725 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001726 }
1727 else
1728 {
paulfee0f4c2004-09-13 05:12:46 +00001729 if (pfilter->map[RMAP_OUT].name)
1730 free (pfilter->map[RMAP_OUT].name);
1731 pfilter->map[RMAP_OUT].name = NULL;
1732 pfilter->map[RMAP_OUT].map = NULL;
1733 }
1734
1735 /* RS-client's import/export route-maps. */
1736 if (gfilter->map[RMAP_IMPORT].name)
1737 {
1738 if (pfilter->map[RMAP_IMPORT].name)
1739 free (pfilter->map[RMAP_IMPORT].name);
1740 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1741 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1742 }
1743 else
1744 {
1745 if (pfilter->map[RMAP_IMPORT].name)
1746 free (pfilter->map[RMAP_IMPORT].name);
1747 pfilter->map[RMAP_IMPORT].name = NULL;
1748 pfilter->map[RMAP_IMPORT].map = NULL;
1749 }
1750 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1751 {
1752 if (pfilter->map[RMAP_EXPORT].name)
1753 free (pfilter->map[RMAP_EXPORT].name);
1754 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1755 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001756 }
1757
1758 if (gfilter->usmap.name)
1759 {
1760 if (pfilter->usmap.name)
1761 free (pfilter->usmap.name);
1762 pfilter->usmap.name = strdup (gfilter->usmap.name);
1763 pfilter->usmap.map = gfilter->usmap.map;
1764 }
1765 else
1766 {
1767 if (pfilter->usmap.name)
1768 free (pfilter->usmap.name);
1769 pfilter->usmap.name = NULL;
1770 pfilter->usmap.map = NULL;
1771 }
1772}
1773
1774/* Peer group's remote AS configuration. */
1775int
paulfd79ac92004-10-13 05:06:08 +00001776peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001777{
1778 struct peer_group *group;
1779 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001780 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001781
1782 group = peer_group_lookup (bgp, group_name);
1783 if (! group)
1784 return -1;
1785
1786 if (group->conf->as == *as)
1787 return 0;
1788
1789 /* When we setup peer-group AS number all peer group member's AS
1790 number must be updated to same number. */
1791 peer_as_change (group->conf, *as);
1792
paul1eb8ef22005-04-07 07:30:20 +00001793 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001794 {
1795 if (peer->as != *as)
1796 peer_as_change (peer, *as);
1797 }
1798
1799 return 0;
1800}
1801
1802int
Timo Teräse3443a22016-10-19 16:02:34 +03001803peer_ttl (struct peer *peer)
1804{
1805 if (peer->ttl)
1806 return peer->ttl;
1807 if (peer->gtsm_hops || peer->sort == BGP_PEER_IBGP)
1808 return 255;
1809 return 1;
1810}
1811
1812int
paul718e3742002-12-13 20:15:29 +00001813peer_group_delete (struct peer_group *group)
1814{
1815 struct bgp *bgp;
1816 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001817 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001818
1819 bgp = group->bgp;
1820
paul1eb8ef22005-04-07 07:30:20 +00001821 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001822 {
paul718e3742002-12-13 20:15:29 +00001823 peer_delete (peer);
1824 }
1825 list_delete (group->peer);
1826
1827 free (group->name);
1828 group->name = NULL;
1829
1830 group->conf->group = NULL;
1831 peer_delete (group->conf);
1832
1833 /* Delete from all peer_group list. */
1834 listnode_delete (bgp->group, group);
1835
1836 peer_group_free (group);
1837
1838 return 0;
1839}
1840
1841int
1842peer_group_remote_as_delete (struct peer_group *group)
1843{
1844 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001845 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001846
1847 if (! group->conf->as)
1848 return 0;
1849
paul1eb8ef22005-04-07 07:30:20 +00001850 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001851 {
paul718e3742002-12-13 20:15:29 +00001852 peer_delete (peer);
1853 }
1854 list_delete_all_node (group->peer);
1855
1856 group->conf->as = 0;
1857
1858 return 0;
1859}
1860
1861/* Bind specified peer to peer group. */
1862int
1863peer_group_bind (struct bgp *bgp, union sockunion *su,
1864 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1865{
1866 struct peer *peer;
1867 int first_member = 0;
1868
1869 /* Check peer group's address family. */
1870 if (! group->conf->afc[afi][safi])
1871 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1872
1873 /* Lookup the peer. */
1874 peer = peer_lookup (bgp, su);
1875
1876 /* Create a new peer. */
1877 if (! peer)
1878 {
1879 if (! group->conf->as)
1880 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1881
1882 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1883 peer->group = group;
1884 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001885
Paul Jakmaca058a32006-09-14 02:58:49 +00001886 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001887 listnode_add (group->peer, peer);
1888 peer_group2peer_config_copy (group, peer, afi, safi);
1889
1890 return 0;
1891 }
1892
1893 /* When the peer already belongs to peer group, check the consistency. */
1894 if (peer->af_group[afi][safi])
1895 {
1896 if (strcmp (peer->group->name, group->name) != 0)
1897 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1898
1899 return 0;
1900 }
1901
1902 /* Check current peer group configuration. */
1903 if (peer_group_active (peer)
1904 && strcmp (peer->group->name, group->name) != 0)
1905 return BGP_ERR_PEER_GROUP_MISMATCH;
1906
1907 if (! group->conf->as)
1908 {
1909 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1910 && peer_sort (group->conf) != peer_sort (peer))
1911 {
1912 if (as)
1913 *as = peer->as;
1914 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1915 }
1916
1917 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1918 first_member = 1;
1919 }
1920
1921 peer->af_group[afi][safi] = 1;
1922 peer->afc[afi][safi] = 1;
1923 if (! peer->group)
1924 {
1925 peer->group = group;
paul200df112005-06-01 11:17:05 +00001926
Paul Jakmaca058a32006-09-14 02:58:49 +00001927 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001928 listnode_add (group->peer, peer);
1929 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001930 else
1931 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001932
1933 if (first_member)
1934 {
1935 /* Advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +03001936 if (! CHECK_FLAG (group->conf->config, PEER_CONFIG_ROUTEADV))
1937 {
1938 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1939 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1940 else
1941 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1942 }
paul718e3742002-12-13 20:15:29 +00001943
paul718e3742002-12-13 20:15:29 +00001944 /* local-as reset */
1945 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1946 {
1947 group->conf->change_local_as = 0;
1948 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001949 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001950 }
1951 }
paulfee0f4c2004-09-13 05:12:46 +00001952
1953 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1954 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001955 struct listnode *pn;
1956
paulfee0f4c2004-09-13 05:12:46 +00001957 /* If it's not configured as RSERVER_CLIENT in any other address
1958 family, without being member of a peer_group, remove it from
1959 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001960 if (! peer_rsclient_active (peer)
1961 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001962 {
1963 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001964 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001965
1966 /* Clear our own rsclient rib for this afi/safi. */
1967 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001968 }
paulfee0f4c2004-09-13 05:12:46 +00001969
Paul Jakmab608d5b2008-07-02 02:12:07 +00001970 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001971
1972 /* Import policy. */
1973 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1974 {
1975 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1976 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1977 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1978 }
1979
1980 /* Export policy. */
1981 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1982 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1983 {
1984 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1985 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1986 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1987 }
1988 }
1989
paul718e3742002-12-13 20:15:29 +00001990 peer_group2peer_config_copy (group, peer, afi, safi);
1991
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001992 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001993 {
1994 peer->last_reset = PEER_DOWN_RMAP_BIND;
1995 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1996 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1997 }
paul718e3742002-12-13 20:15:29 +00001998 else
1999 BGP_EVENT_ADD (peer, BGP_Stop);
2000
2001 return 0;
2002}
2003
2004int
2005peer_group_unbind (struct bgp *bgp, struct peer *peer,
2006 struct peer_group *group, afi_t afi, safi_t safi)
2007{
2008 if (! peer->af_group[afi][safi])
2009 return 0;
2010
2011 if (group != peer->group)
2012 return BGP_ERR_PEER_GROUP_MISMATCH;
2013
2014 peer->af_group[afi][safi] = 0;
2015 peer->afc[afi][safi] = 0;
2016 peer_af_flag_reset (peer, afi, safi);
2017
paulfee0f4c2004-09-13 05:12:46 +00002018 if (peer->rib[afi][safi])
2019 peer->rib[afi][safi] = NULL;
2020
paul718e3742002-12-13 20:15:29 +00002021 if (! peer_group_active (peer))
2022 {
Paul Jakmaca058a32006-09-14 02:58:49 +00002023 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00002024 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00002025 listnode_delete (group->peer, peer);
2026 peer->group = NULL;
2027 if (group->conf->as)
2028 {
2029 peer_delete (peer);
2030 return 0;
2031 }
2032 peer_global_config_reset (peer);
2033 }
2034
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002035 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002036 {
2037 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
2038 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2039 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2040 }
paul718e3742002-12-13 20:15:29 +00002041 else
2042 BGP_EVENT_ADD (peer, BGP_Stop);
2043
2044 return 0;
2045}
David Lamparter6b0655a2014-06-04 06:53:35 +02002046
Vipin Kumardd49eb12014-09-30 14:36:38 -07002047
2048static int
2049bgp_startup_timer_expire (struct thread *thread)
2050{
2051 struct bgp *bgp;
2052
2053 bgp = THREAD_ARG (thread);
2054 bgp->t_startup = NULL;
2055
2056 return 0;
2057}
2058
paul718e3742002-12-13 20:15:29 +00002059/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00002060static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002061bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002062{
2063 struct bgp *bgp;
2064 afi_t afi;
2065 safi_t safi;
2066
paul200df112005-06-01 11:17:05 +00002067 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
2068 return NULL;
2069
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002070 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00002071 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00002072 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00002073
2074 bgp->peer = list_new ();
2075 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
2076
2077 bgp->group = list_new ();
2078 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
2079
paulfee0f4c2004-09-13 05:12:46 +00002080 bgp->rsclient = list_new ();
2081 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
2082
paul718e3742002-12-13 20:15:29 +00002083 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2084 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2085 {
Paul Jakma64e580a2006-02-21 01:09:01 +00002086 bgp->route[afi][safi] = bgp_table_init (afi, safi);
2087 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
2088 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07002089 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
2090 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00002091 }
2092
2093 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
2094 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
2095 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00002096 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
2097 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07002098 bgp_flag_set (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES);
paul718e3742002-12-13 20:15:29 +00002099
2100 bgp->as = *as;
2101
2102 if (name)
2103 bgp->name = strdup (name);
2104
Donald Sharp774914f2015-10-14 08:50:39 -04002105 THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire,
Vipin Kumardd49eb12014-09-30 14:36:38 -07002106 bgp, bgp->restart_time);
2107
paul718e3742002-12-13 20:15:29 +00002108 return bgp;
2109}
2110
2111/* Return first entry of BGP. */
2112struct bgp *
paul94f2b392005-06-28 12:44:16 +00002113bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00002114{
Lou Berger056f3762013-04-10 12:30:04 -07002115 if (bm && bm->bgp && bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00002116 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00002117 return NULL;
2118}
2119
2120/* Lookup BGP entry. */
2121struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002122bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00002123{
2124 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002125 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002126
paul1eb8ef22005-04-07 07:30:20 +00002127 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002128 if (bgp->as == as
2129 && ((bgp->name == NULL && name == NULL)
2130 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
2131 return bgp;
2132 return NULL;
2133}
2134
2135/* Lookup BGP structure by view name. */
2136struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002137bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002138{
2139 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002140 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002141
paul1eb8ef22005-04-07 07:30:20 +00002142 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002143 if ((bgp->name == NULL && name == NULL)
2144 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2145 return bgp;
2146 return NULL;
2147}
2148
2149/* Called from VTY commands. */
2150int
paulfd79ac92004-10-13 05:06:08 +00002151bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002152{
2153 struct bgp *bgp;
2154
2155 /* Multiple instance check. */
2156 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2157 {
2158 if (name)
2159 bgp = bgp_lookup_by_name (name);
2160 else
2161 bgp = bgp_get_default ();
2162
2163 /* Already exists. */
2164 if (bgp)
2165 {
2166 if (bgp->as != *as)
2167 {
2168 *as = bgp->as;
2169 return BGP_ERR_INSTANCE_MISMATCH;
2170 }
2171 *bgp_val = bgp;
2172 return 0;
2173 }
2174 }
2175 else
2176 {
2177 /* BGP instance name can not be specified for single instance. */
2178 if (name)
2179 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2180
2181 /* Get default BGP structure if exists. */
2182 bgp = bgp_get_default ();
2183
2184 if (bgp)
2185 {
2186 if (bgp->as != *as)
2187 {
2188 *as = bgp->as;
2189 return BGP_ERR_AS_MISMATCH;
2190 }
2191 *bgp_val = bgp;
2192 return 0;
2193 }
2194 }
2195
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002196 bgp = bgp_create (as, name);
2197 bgp_router_id_set(bgp, &router_id_zebra);
2198 *bgp_val = bgp;
2199
Paul Jakmaad12dde2012-06-13 22:50:07 +01002200 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002201 if (list_isempty(bm->bgp)
2202 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002203 {
2204 if (bgp_socket (bm->port, bm->address) < 0)
2205 return BGP_ERR_INVALID_VALUE;
2206 }
2207
paul718e3742002-12-13 20:15:29 +00002208 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002209
2210 return 0;
2211}
2212
2213/* Delete BGP instance. */
2214int
2215bgp_delete (struct bgp *bgp)
2216{
2217 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002218 struct peer_group *group;
Denil Vira57cd5e72015-08-10 12:46:14 -07002219 struct listnode *node, *pnode;
2220 struct listnode *next, *pnext;
paul718e3742002-12-13 20:15:29 +00002221 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002222 int i;
2223
Lou Berger82dd7072016-01-12 13:41:57 -05002224 SET_FLAG(bgp->flags, BGP_FLAG_DELETING);
2225
David Lampartercffe7802014-12-07 03:27:13 +01002226 THREAD_OFF (bgp->t_startup);
2227
Daniel Walton9e518dd2015-05-19 17:47:26 -07002228 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2229 {
2230 if (peer->status == Established ||
2231 peer->status == OpenSent ||
2232 peer->status == OpenConfirm)
2233 {
2234 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2235 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
2236 }
2237 }
2238
paul718e3742002-12-13 20:15:29 +00002239 /* Delete static route. */
2240 bgp_static_delete (bgp);
2241
2242 /* Unset redistribution. */
2243 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2244 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2245 if (i != ZEBRA_ROUTE_BGP)
2246 bgp_redistribute_unset (bgp, afi, i);
2247
paul1eb8ef22005-04-07 07:30:20 +00002248 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002249 {
2250 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2251 {
2252 /* Send notify to remote peer. */
2253 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2254 }
2255
2256 peer_delete (peer);
2257 }
paul718e3742002-12-13 20:15:29 +00002258
Chris Caputo228da422009-07-18 05:44:03 +00002259 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002260 {
Denil Vira57cd5e72015-08-10 12:46:14 -07002261 for (ALL_LIST_ELEMENTS (group->peer, pnode, pnext, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002262 {
2263 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2264 {
2265 /* Send notify to remote peer. */
2266 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2267 }
2268 }
2269 peer_group_delete (group);
2270 }
Chris Caputo228da422009-07-18 05:44:03 +00002271
2272 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002273
2274 if (bgp->peer_self) {
2275 peer_delete(bgp->peer_self);
2276 bgp->peer_self = NULL;
2277 }
Lou Berger82dd7072016-01-12 13:41:57 -05002278
2279 /*
2280 * Free pending deleted routes. Unfortunately, it also has to process
2281 * all the pending activity for other instances of struct bgp.
2282 *
2283 * This call was added to achieve clean memory allocation at exit,
2284 * for the sake of valgrind.
2285 */
2286 bgp_process_queues_drain_immediate();
2287
Paul Jakmafd35b942009-07-16 19:27:32 +01002288 /* Remove visibility via the master list - there may however still be
2289 * routes to be processed still referencing the struct bgp.
2290 */
2291 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002292 if (list_isempty(bm->bgp))
2293 bgp_close ();
2294
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002295 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002296
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002297 return 0;
2298}
2299
2300static void bgp_free (struct bgp *);
2301
2302void
2303bgp_lock (struct bgp *bgp)
2304{
2305 ++bgp->lock;
2306}
2307
2308void
2309bgp_unlock(struct bgp *bgp)
2310{
Chris Caputo228da422009-07-18 05:44:03 +00002311 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002312 if (--bgp->lock == 0)
2313 bgp_free (bgp);
2314}
2315
2316static void
2317bgp_free (struct bgp *bgp)
2318{
2319 afi_t afi;
2320 safi_t safi;
2321
2322 list_delete (bgp->group);
2323 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002324 list_delete (bgp->rsclient);
2325
paul718e3742002-12-13 20:15:29 +00002326 if (bgp->name)
2327 free (bgp->name);
2328
2329 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2330 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2331 {
2332 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002333 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002334 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002335 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002336 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002337 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002338 }
2339 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002340}
David Lamparter6b0655a2014-06-04 06:53:35 +02002341
paul718e3742002-12-13 20:15:29 +00002342struct peer *
2343peer_lookup (struct bgp *bgp, union sockunion *su)
2344{
2345 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002346 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002347
Steve Hillfc4dc592009-07-28 17:54:35 +01002348 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002349 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002350 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2351 if (sockunion_same (&peer->su, su)
2352 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2353 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002354 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002355 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002356 {
2357 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002358
Paul Jakma2158ad22009-07-28 18:10:55 +01002359 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2360 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2361 if (sockunion_same (&peer->su, su)
2362 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2363 return peer;
paul718e3742002-12-13 20:15:29 +00002364 }
2365 return NULL;
2366}
2367
2368struct peer *
2369peer_lookup_with_open (union sockunion *su, as_t remote_as,
2370 struct in_addr *remote_id, int *as)
2371{
2372 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002373 struct listnode *node;
2374 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002375 struct bgp *bgp;
2376
Steve Hillfc4dc592009-07-28 17:54:35 +01002377 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002378 return NULL;
2379
Paul Jakma9d878772009-08-05 16:25:16 +01002380 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002381 {
Paul Jakma9d878772009-08-05 16:25:16 +01002382 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2383 {
2384 if (sockunion_same (&peer->su, su)
2385 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2386 {
2387 if (peer->as == remote_as
2388 && peer->remote_id.s_addr == remote_id->s_addr)
2389 return peer;
2390 if (peer->as == remote_as)
2391 *as = 1;
2392 }
2393 }
2394
2395 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2396 {
2397 if (sockunion_same (&peer->su, su)
2398 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2399 {
2400 if (peer->as == remote_as
2401 && peer->remote_id.s_addr == 0)
2402 return peer;
2403 if (peer->as == remote_as)
2404 *as = 1;
2405 }
2406 }
paul718e3742002-12-13 20:15:29 +00002407 }
2408 return NULL;
2409}
David Lamparter6b0655a2014-06-04 06:53:35 +02002410
paul718e3742002-12-13 20:15:29 +00002411/* If peer is configured at least one address family return 1. */
2412int
2413peer_active (struct peer *peer)
2414{
2415 if (peer->afc[AFI_IP][SAFI_UNICAST]
2416 || peer->afc[AFI_IP][SAFI_MULTICAST]
2417 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05002418 || peer->afc[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00002419 || peer->afc[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05002420 || peer->afc[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05002421 || peer->afc[AFI_IP6][SAFI_MPLS_VPN]
2422 || peer->afc[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00002423 return 1;
2424 return 0;
2425}
2426
2427/* If peer is negotiated at least one address family return 1. */
2428int
2429peer_active_nego (struct peer *peer)
2430{
2431 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2432 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2433 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05002434 || peer->afc_nego[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00002435 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05002436 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05002437 || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
2438 || peer->afc_nego[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00002439 return 1;
2440 return 0;
2441}
David Lamparter6b0655a2014-06-04 06:53:35 +02002442
paul718e3742002-12-13 20:15:29 +00002443/* peer_flag_change_type. */
2444enum peer_change_type
2445{
2446 peer_change_none,
2447 peer_change_reset,
2448 peer_change_reset_in,
2449 peer_change_reset_out,
2450};
2451
paul94f2b392005-06-28 12:44:16 +00002452static void
paul718e3742002-12-13 20:15:29 +00002453peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2454 enum peer_change_type type)
2455{
2456 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2457 return;
2458
Stephen Hemmingerd9d4ae52010-01-13 00:32:39 +00002459 if (peer->status != Established)
2460 return;
2461
paul718e3742002-12-13 20:15:29 +00002462 if (type == peer_change_reset)
2463 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2464 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2465 else if (type == peer_change_reset_in)
2466 {
2467 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2468 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2469 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2470 else
2471 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2472 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2473 }
2474 else if (type == peer_change_reset_out)
2475 bgp_announce_route (peer, afi, safi);
2476}
2477
2478struct peer_flag_action
2479{
2480 /* Peer's flag. */
2481 u_int32_t flag;
2482
2483 /* This flag can be set for peer-group member. */
2484 u_char not_for_member;
2485
2486 /* Action when the flag is changed. */
2487 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002488
2489 /* Peer down cause */
2490 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002491};
2492
Stephen Hemminger03621952009-07-21 16:27:20 -07002493static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002494 {
2495 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2496 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2497 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2498 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2499 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002500 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002501 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002502 { 0, 0, 0 }
2503 };
2504
Stephen Hemminger03621952009-07-21 16:27:20 -07002505static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002506 {
2507 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2508 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2509 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
Job Snijders3334bab2017-01-20 14:47:12 +00002510 { PEER_FLAG_SEND_LARGE_COMMUNITY, 1, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002511 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2512 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2513 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2514 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2515 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2516 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2517 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2518 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2519 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2520 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002521 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
Timo Teräs9e7a53c2014-04-24 10:22:37 +03002522 { PEER_FLAG_NEXTHOP_SELF_ALL, 1, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002523 { 0, 0, 0 }
2524 };
2525
2526/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002527static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002528peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002529 struct peer_flag_action *action, u_int32_t flag)
2530{
2531 int i;
2532 int found = 0;
2533 int reset_in = 0;
2534 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002535 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002536
2537 /* Check peer's frag action. */
2538 for (i = 0; i < size; i++)
2539 {
2540 match = &action_list[i];
2541
2542 if (match->flag == 0)
2543 break;
2544
2545 if (match->flag & flag)
2546 {
2547 found = 1;
2548
2549 if (match->type == peer_change_reset_in)
2550 reset_in = 1;
2551 if (match->type == peer_change_reset_out)
2552 reset_out = 1;
2553 if (match->type == peer_change_reset)
2554 {
2555 reset_in = 1;
2556 reset_out = 1;
2557 }
2558 if (match->not_for_member)
2559 action->not_for_member = 1;
2560 }
2561 }
2562
2563 /* Set peer clear type. */
2564 if (reset_in && reset_out)
2565 action->type = peer_change_reset;
2566 else if (reset_in)
2567 action->type = peer_change_reset_in;
2568 else if (reset_out)
2569 action->type = peer_change_reset_out;
2570 else
2571 action->type = peer_change_none;
2572
2573 return found;
2574}
2575
paul94f2b392005-06-28 12:44:16 +00002576static void
paul718e3742002-12-13 20:15:29 +00002577peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2578{
2579 if (flag == PEER_FLAG_SHUTDOWN)
2580 {
2581 if (CHECK_FLAG (peer->flags, flag))
2582 {
hasso93406d82005-02-02 14:40:33 +00002583 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2584 peer_nsf_stop (peer);
2585
hasso0a486e52005-02-01 20:57:17 +00002586 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2587 if (peer->t_pmax_restart)
2588 {
2589 BGP_TIMER_OFF (peer->t_pmax_restart);
2590 if (BGP_DEBUG (events, EVENTS))
2591 zlog_debug ("%s Maximum-prefix restart timer canceled",
2592 peer->host);
2593 }
2594
hasso93406d82005-02-02 14:40:33 +00002595 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2596 peer_nsf_stop (peer);
2597
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002598 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002599 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2600 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2601 else
2602 BGP_EVENT_ADD (peer, BGP_Stop);
2603 }
2604 else
2605 {
2606 peer->v_start = BGP_INIT_START_TIMER;
2607 BGP_EVENT_ADD (peer, BGP_Stop);
2608 }
2609 }
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002610 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002611 {
hassoc9502432005-02-01 22:01:48 +00002612 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2613 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2614 else if (flag == PEER_FLAG_PASSIVE)
2615 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002616 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002617 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002618
hassoc9502432005-02-01 22:01:48 +00002619 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2620 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002621 }
2622 else
2623 BGP_EVENT_ADD (peer, BGP_Stop);
2624}
2625
2626/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002627static int
paul718e3742002-12-13 20:15:29 +00002628peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2629{
2630 int found;
2631 int size;
2632 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002633 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002634 struct peer_flag_action action;
2635
2636 memset (&action, 0, sizeof (struct peer_flag_action));
2637 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2638
2639 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2640
2641 /* No flag action is found. */
2642 if (! found)
2643 return BGP_ERR_INVALID_FLAG;
2644
2645 /* Not for peer-group member. */
2646 if (action.not_for_member && peer_group_active (peer))
2647 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2648
2649 /* When unset the peer-group member's flag we have to check
2650 peer-group configuration. */
2651 if (! set && peer_group_active (peer))
2652 if (CHECK_FLAG (peer->group->conf->flags, flag))
2653 {
2654 if (flag == PEER_FLAG_SHUTDOWN)
2655 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2656 else
2657 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2658 }
2659
2660 /* Flag conflict check. */
2661 if (set
2662 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2663 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2664 return BGP_ERR_PEER_FLAG_CONFLICT;
2665
2666 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2667 {
2668 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2669 return 0;
2670 if (! set && ! CHECK_FLAG (peer->flags, flag))
2671 return 0;
2672 }
2673
2674 if (set)
2675 SET_FLAG (peer->flags, flag);
2676 else
2677 UNSET_FLAG (peer->flags, flag);
2678
2679 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2680 {
2681 if (action.type == peer_change_reset)
2682 peer_flag_modify_action (peer, flag);
2683
2684 return 0;
2685 }
2686
2687 /* peer-group member updates. */
2688 group = peer->group;
2689
paul1eb8ef22005-04-07 07:30:20 +00002690 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002691 {
2692 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2693 continue;
2694
2695 if (! set && ! CHECK_FLAG (peer->flags, flag))
2696 continue;
2697
2698 if (set)
2699 SET_FLAG (peer->flags, flag);
2700 else
2701 UNSET_FLAG (peer->flags, flag);
2702
2703 if (action.type == peer_change_reset)
2704 peer_flag_modify_action (peer, flag);
2705 }
2706 return 0;
2707}
2708
2709int
2710peer_flag_set (struct peer *peer, u_int32_t flag)
2711{
2712 return peer_flag_modify (peer, flag, 1);
2713}
2714
2715int
2716peer_flag_unset (struct peer *peer, u_int32_t flag)
2717{
2718 return peer_flag_modify (peer, flag, 0);
2719}
2720
paul94f2b392005-06-28 12:44:16 +00002721static int
paul718e3742002-12-13 20:15:29 +00002722peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2723{
2724 if (peer->af_group[afi][safi])
2725 return 1;
2726 return 0;
2727}
2728
paul94f2b392005-06-28 12:44:16 +00002729static int
paul718e3742002-12-13 20:15:29 +00002730peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2731 int set)
2732{
2733 int found;
2734 int size;
paul1eb8ef22005-04-07 07:30:20 +00002735 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002736 struct peer_group *group;
2737 struct peer_flag_action action;
2738
2739 memset (&action, 0, sizeof (struct peer_flag_action));
2740 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2741
2742 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2743
2744 /* No flag action is found. */
2745 if (! found)
2746 return BGP_ERR_INVALID_FLAG;
2747
2748 /* Adress family must be activated. */
2749 if (! peer->afc[afi][safi])
2750 return BGP_ERR_PEER_INACTIVE;
2751
2752 /* Not for peer-group member. */
2753 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2754 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2755
2756 /* Spcecial check for reflector client. */
2757 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2758 && peer_sort (peer) != BGP_PEER_IBGP)
2759 return BGP_ERR_NOT_INTERNAL_PEER;
2760
2761 /* Spcecial check for remove-private-AS. */
2762 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2763 && peer_sort (peer) == BGP_PEER_IBGP)
2764 return BGP_ERR_REMOVE_PRIVATE_AS;
2765
2766 /* When unset the peer-group member's flag we have to check
2767 peer-group configuration. */
2768 if (! set && peer->af_group[afi][safi])
2769 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2770 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2771
2772 /* When current flag configuration is same as requested one. */
2773 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2774 {
2775 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2776 return 0;
2777 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2778 return 0;
2779 }
2780
2781 if (set)
2782 SET_FLAG (peer->af_flags[afi][safi], flag);
2783 else
2784 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2785
2786 /* Execute action when peer is established. */
2787 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2788 && peer->status == Established)
2789 {
2790 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2791 bgp_clear_adj_in (peer, afi, safi);
2792 else
hassoe0701b72004-05-20 09:19:34 +00002793 {
2794 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2795 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2796 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2797 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2798 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2799 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2800 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2801 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2802
2803 peer_change_action (peer, afi, safi, action.type);
2804 }
2805
paul718e3742002-12-13 20:15:29 +00002806 }
2807
2808 /* Peer group member updates. */
2809 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2810 {
2811 group = peer->group;
2812
paul1eb8ef22005-04-07 07:30:20 +00002813 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002814 {
2815 if (! peer->af_group[afi][safi])
2816 continue;
2817
2818 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2819 continue;
2820
2821 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2822 continue;
2823
2824 if (set)
2825 SET_FLAG (peer->af_flags[afi][safi], flag);
2826 else
2827 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2828
2829 if (peer->status == Established)
2830 {
2831 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2832 bgp_clear_adj_in (peer, afi, safi);
2833 else
hassoe0701b72004-05-20 09:19:34 +00002834 {
2835 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2836 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2837 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2838 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2839 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2840 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2841 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2842 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2843
2844 peer_change_action (peer, afi, safi, action.type);
2845 }
paul718e3742002-12-13 20:15:29 +00002846 }
2847 }
2848 }
2849 return 0;
2850}
2851
2852int
2853peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2854{
2855 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2856}
2857
2858int
2859peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2860{
2861 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2862}
David Lamparter6b0655a2014-06-04 06:53:35 +02002863
paul718e3742002-12-13 20:15:29 +00002864/* EBGP multihop configuration. */
2865int
2866peer_ebgp_multihop_set (struct peer *peer, int ttl)
2867{
2868 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002869 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002870 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002871
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002872 if (peer->sort == BGP_PEER_IBGP)
Timo Teräse3443a22016-10-19 16:02:34 +03002873 return BGP_ERR_NO_IBGP_WITH_TTLHACK;
paul718e3742002-12-13 20:15:29 +00002874
Timo Teräse3443a22016-10-19 16:02:34 +03002875 if (peer->gtsm_hops != 0)
2876 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2877
2878 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
Nick Hilliardfa411a22011-03-23 15:33:17 +00002879 {
Timo Teräse3443a22016-10-19 16:02:34 +03002880 group = peer->group;
2881 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
Nick Hilliardfa411a22011-03-23 15:33:17 +00002882 {
Timo Teräse3443a22016-10-19 16:02:34 +03002883 if (peer1->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002884 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2885 }
2886 }
2887
paul718e3742002-12-13 20:15:29 +00002888 peer->ttl = ttl;
2889
2890 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2891 {
Timo Teräse3443a22016-10-19 16:02:34 +03002892 bgp_set_socket_ttl (peer, peer->fd);
paul718e3742002-12-13 20:15:29 +00002893 }
2894 else
2895 {
2896 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002897 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
Timo Teräse3443a22016-10-19 16:02:34 +03002898 {
2899 peer->ttl = ttl;
2900 bgp_set_socket_ttl (peer, peer->fd);
2901 }
paul718e3742002-12-13 20:15:29 +00002902 }
paul718e3742002-12-13 20:15:29 +00002903
paul718e3742002-12-13 20:15:29 +00002904 return 0;
2905}
David Lamparter6b0655a2014-06-04 06:53:35 +02002906
paul718e3742002-12-13 20:15:29 +00002907/* Neighbor description. */
2908int
David Lamparterdfb9bd72016-05-24 18:58:07 +02002909peer_description_set (struct peer *peer, const char *desc)
paul718e3742002-12-13 20:15:29 +00002910{
2911 if (peer->desc)
2912 XFREE (MTYPE_PEER_DESC, peer->desc);
2913
2914 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2915
2916 return 0;
2917}
2918
2919int
2920peer_description_unset (struct peer *peer)
2921{
2922 if (peer->desc)
2923 XFREE (MTYPE_PEER_DESC, peer->desc);
2924
2925 peer->desc = NULL;
2926
2927 return 0;
2928}
David Lamparter6b0655a2014-06-04 06:53:35 +02002929
paul718e3742002-12-13 20:15:29 +00002930/* Neighbor update-source. */
2931int
paulfd79ac92004-10-13 05:06:08 +00002932peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002933{
2934 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002935 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002936
2937 if (peer->update_if)
2938 {
2939 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2940 && strcmp (peer->update_if, ifname) == 0)
2941 return 0;
2942
2943 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2944 peer->update_if = NULL;
2945 }
2946
2947 if (peer->update_source)
2948 {
2949 sockunion_free (peer->update_source);
2950 peer->update_source = NULL;
2951 }
2952
2953 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2954
2955 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2956 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002957 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002958 {
2959 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2960 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2961 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2962 }
paul718e3742002-12-13 20:15:29 +00002963 else
2964 BGP_EVENT_ADD (peer, BGP_Stop);
2965 return 0;
2966 }
2967
2968 /* peer-group member updates. */
2969 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002970 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002971 {
2972 if (peer->update_if)
2973 {
2974 if (strcmp (peer->update_if, ifname) == 0)
2975 continue;
2976
2977 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2978 peer->update_if = NULL;
2979 }
2980
2981 if (peer->update_source)
2982 {
2983 sockunion_free (peer->update_source);
2984 peer->update_source = NULL;
2985 }
2986
2987 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2988
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002989 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002990 {
2991 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2992 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2993 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2994 }
paul718e3742002-12-13 20:15:29 +00002995 else
2996 BGP_EVENT_ADD (peer, BGP_Stop);
2997 }
2998 return 0;
2999}
3000
3001int
David Lamparterdfb9bd72016-05-24 18:58:07 +02003002peer_update_source_addr_set (struct peer *peer, const union sockunion *su)
paul718e3742002-12-13 20:15:29 +00003003{
3004 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003005 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003006
3007 if (peer->update_source)
3008 {
3009 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3010 && sockunion_cmp (peer->update_source, su) == 0)
3011 return 0;
3012 sockunion_free (peer->update_source);
3013 peer->update_source = NULL;
3014 }
3015
3016 if (peer->update_if)
3017 {
3018 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3019 peer->update_if = NULL;
3020 }
3021
3022 peer->update_source = sockunion_dup (su);
3023
3024 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3025 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003026 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003027 {
3028 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3029 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3030 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3031 }
paul718e3742002-12-13 20:15:29 +00003032 else
3033 BGP_EVENT_ADD (peer, BGP_Stop);
3034 return 0;
3035 }
3036
3037 /* peer-group member updates. */
3038 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003039 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003040 {
3041 if (peer->update_source)
3042 {
3043 if (sockunion_cmp (peer->update_source, su) == 0)
3044 continue;
3045 sockunion_free (peer->update_source);
3046 peer->update_source = NULL;
3047 }
3048
3049 if (peer->update_if)
3050 {
3051 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3052 peer->update_if = NULL;
3053 }
3054
3055 peer->update_source = sockunion_dup (su);
3056
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003057 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003058 {
3059 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3060 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3061 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3062 }
paul718e3742002-12-13 20:15:29 +00003063 else
3064 BGP_EVENT_ADD (peer, BGP_Stop);
3065 }
3066 return 0;
3067}
3068
3069int
3070peer_update_source_unset (struct peer *peer)
3071{
3072 union sockunion *su;
3073 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003074 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003075
3076 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3077 && ! peer->update_source
3078 && ! peer->update_if)
3079 return 0;
3080
3081 if (peer->update_source)
3082 {
3083 sockunion_free (peer->update_source);
3084 peer->update_source = NULL;
3085 }
3086 if (peer->update_if)
3087 {
3088 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3089 peer->update_if = NULL;
3090 }
3091
3092 if (peer_group_active (peer))
3093 {
3094 group = peer->group;
3095
3096 if (group->conf->update_source)
3097 {
3098 su = sockunion_dup (group->conf->update_source);
3099 peer->update_source = su;
3100 }
3101 else if (group->conf->update_if)
3102 peer->update_if =
3103 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
3104 }
3105
3106 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3107 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003108 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003109 {
3110 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3111 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3112 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3113 }
paul718e3742002-12-13 20:15:29 +00003114 else
3115 BGP_EVENT_ADD (peer, BGP_Stop);
3116 return 0;
3117 }
3118
3119 /* peer-group member updates. */
3120 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003121 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003122 {
3123 if (! peer->update_source && ! peer->update_if)
3124 continue;
3125
3126 if (peer->update_source)
3127 {
3128 sockunion_free (peer->update_source);
3129 peer->update_source = NULL;
3130 }
3131
3132 if (peer->update_if)
3133 {
3134 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3135 peer->update_if = NULL;
3136 }
3137
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003138 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003139 {
3140 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3141 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3142 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3143 }
paul718e3742002-12-13 20:15:29 +00003144 else
3145 BGP_EVENT_ADD (peer, BGP_Stop);
3146 }
3147 return 0;
3148}
David Lamparter6b0655a2014-06-04 06:53:35 +02003149
paul718e3742002-12-13 20:15:29 +00003150int
3151peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003152 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003153{
3154 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003155 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003156
3157 /* Adress family must be activated. */
3158 if (! peer->afc[afi][safi])
3159 return BGP_ERR_PEER_INACTIVE;
3160
3161 /* Default originate can't be used for peer group memeber. */
3162 if (peer_is_group_member (peer, afi, safi))
3163 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3164
3165 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3166 || (rmap && ! peer->default_rmap[afi][safi].name)
3167 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3168 {
3169 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3170
3171 if (rmap)
3172 {
3173 if (peer->default_rmap[afi][safi].name)
3174 free (peer->default_rmap[afi][safi].name);
3175 peer->default_rmap[afi][safi].name = strdup (rmap);
3176 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3177 }
3178 }
3179
3180 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3181 {
3182 if (peer->status == Established && peer->afc_nego[afi][safi])
3183 bgp_default_originate (peer, afi, safi, 0);
3184 return 0;
3185 }
3186
3187 /* peer-group member updates. */
3188 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003189 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003190 {
3191 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3192
3193 if (rmap)
3194 {
3195 if (peer->default_rmap[afi][safi].name)
3196 free (peer->default_rmap[afi][safi].name);
3197 peer->default_rmap[afi][safi].name = strdup (rmap);
3198 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3199 }
3200
3201 if (peer->status == Established && peer->afc_nego[afi][safi])
3202 bgp_default_originate (peer, afi, safi, 0);
3203 }
3204 return 0;
3205}
3206
3207int
3208peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3209{
3210 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003211 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003212
3213 /* Adress family must be activated. */
3214 if (! peer->afc[afi][safi])
3215 return BGP_ERR_PEER_INACTIVE;
3216
3217 /* Default originate can't be used for peer group memeber. */
3218 if (peer_is_group_member (peer, afi, safi))
3219 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3220
3221 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3222 {
3223 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3224
3225 if (peer->default_rmap[afi][safi].name)
3226 free (peer->default_rmap[afi][safi].name);
3227 peer->default_rmap[afi][safi].name = NULL;
3228 peer->default_rmap[afi][safi].map = NULL;
3229 }
3230
3231 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3232 {
3233 if (peer->status == Established && peer->afc_nego[afi][safi])
3234 bgp_default_originate (peer, afi, safi, 1);
3235 return 0;
3236 }
3237
3238 /* peer-group member updates. */
3239 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003240 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003241 {
3242 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3243
3244 if (peer->default_rmap[afi][safi].name)
3245 free (peer->default_rmap[afi][safi].name);
3246 peer->default_rmap[afi][safi].name = NULL;
3247 peer->default_rmap[afi][safi].map = NULL;
3248
3249 if (peer->status == Established && peer->afc_nego[afi][safi])
3250 bgp_default_originate (peer, afi, safi, 1);
3251 }
3252 return 0;
3253}
David Lamparter6b0655a2014-06-04 06:53:35 +02003254
paul718e3742002-12-13 20:15:29 +00003255int
3256peer_port_set (struct peer *peer, u_int16_t port)
3257{
3258 peer->port = port;
3259 return 0;
3260}
3261
3262int
3263peer_port_unset (struct peer *peer)
3264{
3265 peer->port = BGP_PORT_DEFAULT;
3266 return 0;
3267}
David Lamparter6b0655a2014-06-04 06:53:35 +02003268
paul718e3742002-12-13 20:15:29 +00003269/* neighbor weight. */
3270int
3271peer_weight_set (struct peer *peer, u_int16_t weight)
3272{
3273 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003274 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003275
3276 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3277 peer->weight = weight;
3278
3279 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3280 return 0;
3281
3282 /* peer-group member updates. */
3283 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003284 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003285 {
3286 peer->weight = group->conf->weight;
3287 }
3288 return 0;
3289}
3290
3291int
3292peer_weight_unset (struct peer *peer)
3293{
3294 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003295 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003296
3297 /* Set default weight. */
3298 if (peer_group_active (peer))
3299 peer->weight = peer->group->conf->weight;
3300 else
3301 peer->weight = 0;
3302
3303 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3304
3305 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3306 return 0;
3307
3308 /* peer-group member updates. */
3309 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003310 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003311 {
3312 peer->weight = 0;
3313 }
3314 return 0;
3315}
David Lamparter6b0655a2014-06-04 06:53:35 +02003316
paul718e3742002-12-13 20:15:29 +00003317int
3318peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3319{
3320 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003321 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003322
3323 /* Not for peer group memeber. */
3324 if (peer_group_active (peer))
3325 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3326
3327 /* keepalive value check. */
3328 if (keepalive > 65535)
3329 return BGP_ERR_INVALID_VALUE;
3330
3331 /* Holdtime value check. */
3332 if (holdtime > 65535)
3333 return BGP_ERR_INVALID_VALUE;
3334
3335 /* Holdtime value must be either 0 or greater than 3. */
3336 if (holdtime < 3 && holdtime != 0)
3337 return BGP_ERR_INVALID_VALUE;
3338
3339 /* Set value to the configuration. */
3340 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3341 peer->holdtime = holdtime;
3342 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3343
3344 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3345 return 0;
3346
3347 /* peer-group member updates. */
3348 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003349 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003350 {
3351 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3352 peer->holdtime = group->conf->holdtime;
3353 peer->keepalive = group->conf->keepalive;
3354 }
3355 return 0;
3356}
3357
3358int
3359peer_timers_unset (struct peer *peer)
3360{
3361 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003362 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003363
3364 if (peer_group_active (peer))
3365 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3366
3367 /* Clear configuration. */
3368 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3369 peer->keepalive = 0;
3370 peer->holdtime = 0;
3371
3372 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3373 return 0;
3374
3375 /* peer-group member updates. */
3376 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003377 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003378 {
3379 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3380 peer->holdtime = 0;
3381 peer->keepalive = 0;
3382 }
3383
3384 return 0;
3385}
David Lamparter6b0655a2014-06-04 06:53:35 +02003386
paul718e3742002-12-13 20:15:29 +00003387int
3388peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3389{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003390 struct peer_group *group;
3391 struct listnode *node, *nnode;
3392
paul718e3742002-12-13 20:15:29 +00003393 if (peer_group_active (peer))
3394 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3395
3396 if (connect > 65535)
3397 return BGP_ERR_INVALID_VALUE;
3398
3399 /* Set value to the configuration. */
3400 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3401 peer->connect = connect;
3402
3403 /* Set value to timer setting. */
3404 peer->v_connect = connect;
3405
Daniel Walton0d7435f2015-10-22 11:35:20 +03003406 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3407 return 0;
3408
3409 /* peer-group member updates. */
3410 group = peer->group;
3411 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3412 {
3413 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3414 peer->connect = connect;
3415 peer->v_connect = connect;
3416 }
paul718e3742002-12-13 20:15:29 +00003417 return 0;
3418}
3419
3420int
3421peer_timers_connect_unset (struct peer *peer)
3422{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003423 struct peer_group *group;
3424 struct listnode *node, *nnode;
3425
paul718e3742002-12-13 20:15:29 +00003426 if (peer_group_active (peer))
3427 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3428
3429 /* Clear configuration. */
3430 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3431 peer->connect = 0;
3432
3433 /* Set timer setting to default value. */
3434 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3435
Daniel Walton0d7435f2015-10-22 11:35:20 +03003436 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3437 return 0;
3438
3439 /* peer-group member updates. */
3440 group = peer->group;
3441 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3442 {
3443 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3444 peer->connect = 0;
3445 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3446 }
3447 return 0;
paul718e3742002-12-13 20:15:29 +00003448}
David Lamparter6b0655a2014-06-04 06:53:35 +02003449
paul718e3742002-12-13 20:15:29 +00003450int
3451peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3452{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003453 struct peer_group *group;
3454 struct listnode *node, *nnode;
3455
paul718e3742002-12-13 20:15:29 +00003456 if (peer_group_active (peer))
3457 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3458
3459 if (routeadv > 600)
3460 return BGP_ERR_INVALID_VALUE;
3461
3462 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3463 peer->routeadv = routeadv;
3464 peer->v_routeadv = routeadv;
3465
Daniel Walton0d7435f2015-10-22 11:35:20 +03003466 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3467 return 0;
3468
3469 /* peer-group member updates. */
3470 group = peer->group;
3471 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3472 {
3473 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3474 peer->routeadv = routeadv;
3475 peer->v_routeadv = routeadv;
3476 }
3477
paul718e3742002-12-13 20:15:29 +00003478 return 0;
3479}
3480
3481int
3482peer_advertise_interval_unset (struct peer *peer)
3483{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003484 struct peer_group *group;
3485 struct listnode *node, *nnode;
3486
paul718e3742002-12-13 20:15:29 +00003487 if (peer_group_active (peer))
3488 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3489
3490 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3491 peer->routeadv = 0;
3492
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003493 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003494 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3495 else
3496 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
Daniel Walton0d7435f2015-10-22 11:35:20 +03003497
3498 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3499 return 0;
3500
3501 /* peer-group member updates. */
3502 group = peer->group;
3503 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3504 {
3505 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3506 peer->routeadv = 0;
3507
3508 if (peer->sort == BGP_PEER_IBGP)
3509 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3510 else
3511 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3512 }
paul718e3742002-12-13 20:15:29 +00003513
3514 return 0;
3515}
David Lamparter6b0655a2014-06-04 06:53:35 +02003516
paul718e3742002-12-13 20:15:29 +00003517/* neighbor interface */
3518int
paulfd79ac92004-10-13 05:06:08 +00003519peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003520{
3521 if (peer->ifname)
3522 free (peer->ifname);
3523 peer->ifname = strdup (str);
3524
3525 return 0;
3526}
3527
3528int
3529peer_interface_unset (struct peer *peer)
3530{
3531 if (peer->ifname)
3532 free (peer->ifname);
3533 peer->ifname = NULL;
3534
3535 return 0;
3536}
David Lamparter6b0655a2014-06-04 06:53:35 +02003537
paul718e3742002-12-13 20:15:29 +00003538/* Allow-as in. */
3539int
3540peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3541{
3542 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003543 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003544
3545 if (allow_num < 1 || allow_num > 10)
3546 return BGP_ERR_INVALID_VALUE;
3547
3548 if (peer->allowas_in[afi][safi] != allow_num)
3549 {
3550 peer->allowas_in[afi][safi] = allow_num;
3551 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3552 peer_change_action (peer, afi, safi, peer_change_reset_in);
3553 }
3554
3555 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3556 return 0;
3557
3558 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003559 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003560 {
3561 if (peer->allowas_in[afi][safi] != allow_num)
3562 {
3563 peer->allowas_in[afi][safi] = allow_num;
3564 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3565 peer_change_action (peer, afi, safi, peer_change_reset_in);
3566 }
3567
3568 }
3569 return 0;
3570}
3571
3572int
3573peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3574{
3575 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003576 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003577
3578 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3579 {
3580 peer->allowas_in[afi][safi] = 0;
3581 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3582 }
3583
3584 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3585 return 0;
3586
3587 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003588 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003589 {
3590 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3591 {
3592 peer->allowas_in[afi][safi] = 0;
3593 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3594 }
3595 }
3596 return 0;
3597}
David Lamparter6b0655a2014-06-04 06:53:35 +02003598
paul718e3742002-12-13 20:15:29 +00003599int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003600peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003601{
3602 struct bgp *bgp = peer->bgp;
3603 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003604 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003605
3606 if (peer_sort (peer) != BGP_PEER_EBGP
3607 && peer_sort (peer) != BGP_PEER_INTERNAL)
3608 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3609
3610 if (bgp->as == as)
3611 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3612
3613 if (peer_group_active (peer))
3614 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3615
Andrew Certain9d3f9702012-11-07 23:50:07 +00003616 if (peer->as == as)
3617 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3618
paul718e3742002-12-13 20:15:29 +00003619 if (peer->change_local_as == as &&
3620 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003621 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3622 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3623 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003624 return 0;
3625
3626 peer->change_local_as = as;
3627 if (no_prepend)
3628 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3629 else
3630 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3631
Andrew Certain9d3f9702012-11-07 23:50:07 +00003632 if (replace_as)
3633 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3634 else
3635 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3636
paul718e3742002-12-13 20:15:29 +00003637 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3638 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003639 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003640 {
3641 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3642 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3643 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3644 }
paul718e3742002-12-13 20:15:29 +00003645 else
3646 BGP_EVENT_ADD (peer, BGP_Stop);
3647
3648 return 0;
3649 }
3650
3651 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003652 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003653 {
3654 peer->change_local_as = as;
3655 if (no_prepend)
3656 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3657 else
3658 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3659
Andrew Certain9d3f9702012-11-07 23:50:07 +00003660 if (replace_as)
3661 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3662 else
3663 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3664
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003665 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003666 {
3667 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3668 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3669 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3670 }
paul718e3742002-12-13 20:15:29 +00003671 else
3672 BGP_EVENT_ADD (peer, BGP_Stop);
3673 }
3674
3675 return 0;
3676}
3677
3678int
3679peer_local_as_unset (struct peer *peer)
3680{
3681 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003682 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003683
3684 if (peer_group_active (peer))
3685 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3686
3687 if (! peer->change_local_as)
3688 return 0;
3689
3690 peer->change_local_as = 0;
3691 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003692 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003693
3694 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3695 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003696 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003697 {
3698 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3699 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3700 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3701 }
paul718e3742002-12-13 20:15:29 +00003702 else
3703 BGP_EVENT_ADD (peer, BGP_Stop);
3704
3705 return 0;
3706 }
3707
3708 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003709 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003710 {
3711 peer->change_local_as = 0;
3712 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003713 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003714
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003715 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003716 {
3717 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3718 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3719 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3720 }
paul718e3742002-12-13 20:15:29 +00003721 else
3722 BGP_EVENT_ADD (peer, BGP_Stop);
3723 }
3724 return 0;
3725}
David Lamparter6b0655a2014-06-04 06:53:35 +02003726
Paul Jakma0df7c912008-07-21 21:02:49 +00003727/* Set password for authenticating with the peer. */
3728int
3729peer_password_set (struct peer *peer, const char *password)
3730{
3731 struct listnode *nn, *nnode;
3732 int len = password ? strlen(password) : 0;
3733 int ret = BGP_SUCCESS;
3734
3735 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3736 return BGP_ERR_INVALID_VALUE;
3737
3738 if (peer->password && strcmp (peer->password, password) == 0
3739 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3740 return 0;
3741
3742 if (peer->password)
3743 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3744
3745 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3746
3747 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3748 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003749 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3750 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
Paul Jakma0df7c912008-07-21 21:02:49 +00003751 else
3752 BGP_EVENT_ADD (peer, BGP_Stop);
3753
3754 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3755 }
3756
3757 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3758 {
3759 if (peer->password && strcmp (peer->password, password) == 0)
3760 continue;
3761
3762 if (peer->password)
3763 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3764
3765 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3766
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003767 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003768 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3769 else
3770 BGP_EVENT_ADD (peer, BGP_Stop);
3771
3772 if (bgp_md5_set (peer) < 0)
3773 ret = BGP_ERR_TCPSIG_FAILED;
3774 }
3775
3776 return ret;
3777}
3778
3779int
3780peer_password_unset (struct peer *peer)
3781{
3782 struct listnode *nn, *nnode;
3783
3784 if (!peer->password
3785 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3786 return 0;
3787
3788 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3789 {
3790 if (peer_group_active (peer)
3791 && peer->group->conf->password
3792 && strcmp (peer->group->conf->password, peer->password) == 0)
3793 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3794
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003795 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003796 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3797 else
3798 BGP_EVENT_ADD (peer, BGP_Stop);
3799
3800 if (peer->password)
3801 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3802
3803 peer->password = NULL;
3804
3805 bgp_md5_set (peer);
3806
3807 return 0;
3808 }
3809
3810 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3811 peer->password = NULL;
3812
3813 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3814 {
3815 if (!peer->password)
3816 continue;
3817
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003818 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003819 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3820 else
3821 BGP_EVENT_ADD (peer, BGP_Stop);
3822
3823 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3824 peer->password = NULL;
3825
3826 bgp_md5_set (peer);
3827 }
3828
3829 return 0;
3830}
David Lamparter6b0655a2014-06-04 06:53:35 +02003831
paul718e3742002-12-13 20:15:29 +00003832/* Set distribute list to the peer. */
3833int
3834peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003835 const char *name)
paul718e3742002-12-13 20:15:29 +00003836{
3837 struct bgp_filter *filter;
3838 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003839 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003840
3841 if (! peer->afc[afi][safi])
3842 return BGP_ERR_PEER_INACTIVE;
3843
3844 if (direct != FILTER_IN && direct != FILTER_OUT)
3845 return BGP_ERR_INVALID_VALUE;
3846
3847 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3848 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3849
3850 filter = &peer->filter[afi][safi];
3851
3852 if (filter->plist[direct].name)
3853 return BGP_ERR_PEER_FILTER_CONFLICT;
3854
3855 if (filter->dlist[direct].name)
3856 free (filter->dlist[direct].name);
3857 filter->dlist[direct].name = strdup (name);
3858 filter->dlist[direct].alist = access_list_lookup (afi, name);
3859
3860 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3861 return 0;
3862
3863 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003864 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003865 {
3866 filter = &peer->filter[afi][safi];
3867
3868 if (! peer->af_group[afi][safi])
3869 continue;
3870
3871 if (filter->dlist[direct].name)
3872 free (filter->dlist[direct].name);
3873 filter->dlist[direct].name = strdup (name);
3874 filter->dlist[direct].alist = access_list_lookup (afi, name);
3875 }
3876
3877 return 0;
3878}
3879
3880int
3881peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3882{
3883 struct bgp_filter *filter;
3884 struct bgp_filter *gfilter;
3885 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003886 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003887
3888 if (! peer->afc[afi][safi])
3889 return BGP_ERR_PEER_INACTIVE;
3890
3891 if (direct != FILTER_IN && direct != FILTER_OUT)
3892 return BGP_ERR_INVALID_VALUE;
3893
3894 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3895 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3896
3897 filter = &peer->filter[afi][safi];
3898
3899 /* apply peer-group filter */
3900 if (peer->af_group[afi][safi])
3901 {
3902 gfilter = &peer->group->conf->filter[afi][safi];
3903
3904 if (gfilter->dlist[direct].name)
3905 {
3906 if (filter->dlist[direct].name)
3907 free (filter->dlist[direct].name);
3908 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3909 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3910 return 0;
3911 }
3912 }
3913
3914 if (filter->dlist[direct].name)
3915 free (filter->dlist[direct].name);
3916 filter->dlist[direct].name = NULL;
3917 filter->dlist[direct].alist = NULL;
3918
3919 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3920 return 0;
3921
Paul Jakma5bc62ca2016-07-11 16:21:23 +01003922 group = peer->group;
3923 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3924 {
3925 filter = &peer->filter[afi][safi];
paul718e3742002-12-13 20:15:29 +00003926
Paul Jakma5bc62ca2016-07-11 16:21:23 +01003927 if (! peer->af_group[afi][safi])
3928 continue;
paul718e3742002-12-13 20:15:29 +00003929
Paul Jakma5bc62ca2016-07-11 16:21:23 +01003930 if (filter->dlist[direct].name)
3931 free (filter->dlist[direct].name);
3932 filter->dlist[direct].name = NULL;
3933 filter->dlist[direct].alist = NULL;
3934 }
paul718e3742002-12-13 20:15:29 +00003935
3936 return 0;
3937}
3938
3939/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003940static void
paul718e3742002-12-13 20:15:29 +00003941peer_distribute_update (struct access_list *access)
3942{
3943 afi_t afi;
3944 safi_t safi;
3945 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003946 struct listnode *mnode, *mnnode;
3947 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003948 struct bgp *bgp;
3949 struct peer *peer;
3950 struct peer_group *group;
3951 struct bgp_filter *filter;
3952
paul1eb8ef22005-04-07 07:30:20 +00003953 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003954 {
paul1eb8ef22005-04-07 07:30:20 +00003955 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003956 {
3957 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3958 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3959 {
3960 filter = &peer->filter[afi][safi];
3961
3962 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3963 {
3964 if (filter->dlist[direct].name)
3965 filter->dlist[direct].alist =
3966 access_list_lookup (afi, filter->dlist[direct].name);
3967 else
3968 filter->dlist[direct].alist = NULL;
3969 }
3970 }
3971 }
paul1eb8ef22005-04-07 07:30:20 +00003972 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003973 {
3974 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3975 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3976 {
3977 filter = &group->conf->filter[afi][safi];
3978
3979 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3980 {
3981 if (filter->dlist[direct].name)
3982 filter->dlist[direct].alist =
3983 access_list_lookup (afi, filter->dlist[direct].name);
3984 else
3985 filter->dlist[direct].alist = NULL;
3986 }
3987 }
3988 }
3989 }
3990}
David Lamparter6b0655a2014-06-04 06:53:35 +02003991
paul718e3742002-12-13 20:15:29 +00003992/* Set prefix list to the peer. */
3993int
3994peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003995 const char *name)
paul718e3742002-12-13 20:15:29 +00003996{
3997 struct bgp_filter *filter;
3998 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003999 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004000
4001 if (! peer->afc[afi][safi])
4002 return BGP_ERR_PEER_INACTIVE;
4003
4004 if (direct != FILTER_IN && direct != FILTER_OUT)
4005 return BGP_ERR_INVALID_VALUE;
4006
4007 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4008 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4009
4010 filter = &peer->filter[afi][safi];
4011
4012 if (filter->dlist[direct].name)
4013 return BGP_ERR_PEER_FILTER_CONFLICT;
4014
4015 if (filter->plist[direct].name)
4016 free (filter->plist[direct].name);
4017 filter->plist[direct].name = strdup (name);
4018 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4019
4020 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4021 return 0;
4022
4023 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004024 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004025 {
4026 filter = &peer->filter[afi][safi];
4027
4028 if (! peer->af_group[afi][safi])
4029 continue;
4030
4031 if (filter->plist[direct].name)
4032 free (filter->plist[direct].name);
4033 filter->plist[direct].name = strdup (name);
4034 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4035 }
4036 return 0;
4037}
4038
4039int
4040peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4041{
4042 struct bgp_filter *filter;
4043 struct bgp_filter *gfilter;
4044 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004045 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004046
4047 if (! peer->afc[afi][safi])
4048 return BGP_ERR_PEER_INACTIVE;
4049
4050 if (direct != FILTER_IN && direct != FILTER_OUT)
4051 return BGP_ERR_INVALID_VALUE;
4052
4053 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4054 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4055
4056 filter = &peer->filter[afi][safi];
4057
4058 /* apply peer-group filter */
4059 if (peer->af_group[afi][safi])
4060 {
4061 gfilter = &peer->group->conf->filter[afi][safi];
4062
4063 if (gfilter->plist[direct].name)
4064 {
4065 if (filter->plist[direct].name)
4066 free (filter->plist[direct].name);
4067 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
4068 filter->plist[direct].plist = gfilter->plist[direct].plist;
4069 return 0;
4070 }
4071 }
4072
4073 if (filter->plist[direct].name)
4074 free (filter->plist[direct].name);
4075 filter->plist[direct].name = NULL;
4076 filter->plist[direct].plist = NULL;
4077
4078 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4079 return 0;
4080
4081 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004082 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004083 {
4084 filter = &peer->filter[afi][safi];
4085
4086 if (! peer->af_group[afi][safi])
4087 continue;
4088
4089 if (filter->plist[direct].name)
4090 free (filter->plist[direct].name);
4091 filter->plist[direct].name = NULL;
4092 filter->plist[direct].plist = NULL;
4093 }
4094
4095 return 0;
4096}
4097
4098/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00004099static void
paul718e3742002-12-13 20:15:29 +00004100peer_prefix_list_update (struct prefix_list *plist)
4101{
paul1eb8ef22005-04-07 07:30:20 +00004102 struct listnode *mnode, *mnnode;
4103 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004104 struct bgp *bgp;
4105 struct peer *peer;
4106 struct peer_group *group;
4107 struct bgp_filter *filter;
4108 afi_t afi;
4109 safi_t safi;
4110 int direct;
4111
paul1eb8ef22005-04-07 07:30:20 +00004112 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004113 {
paul1eb8ef22005-04-07 07:30:20 +00004114 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004115 {
4116 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4117 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4118 {
4119 filter = &peer->filter[afi][safi];
4120
4121 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4122 {
4123 if (filter->plist[direct].name)
4124 filter->plist[direct].plist =
4125 prefix_list_lookup (afi, filter->plist[direct].name);
4126 else
4127 filter->plist[direct].plist = NULL;
4128 }
4129 }
4130 }
paul1eb8ef22005-04-07 07:30:20 +00004131 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004132 {
4133 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4134 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4135 {
4136 filter = &group->conf->filter[afi][safi];
4137
4138 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4139 {
4140 if (filter->plist[direct].name)
4141 filter->plist[direct].plist =
4142 prefix_list_lookup (afi, filter->plist[direct].name);
4143 else
4144 filter->plist[direct].plist = NULL;
4145 }
4146 }
4147 }
4148 }
4149}
David Lamparter6b0655a2014-06-04 06:53:35 +02004150
paul718e3742002-12-13 20:15:29 +00004151int
4152peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004153 const char *name)
paul718e3742002-12-13 20:15:29 +00004154{
4155 struct bgp_filter *filter;
4156 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004157 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004158
4159 if (! peer->afc[afi][safi])
4160 return BGP_ERR_PEER_INACTIVE;
4161
4162 if (direct != FILTER_IN && direct != FILTER_OUT)
4163 return BGP_ERR_INVALID_VALUE;
4164
4165 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4166 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4167
4168 filter = &peer->filter[afi][safi];
4169
4170 if (filter->aslist[direct].name)
4171 free (filter->aslist[direct].name);
4172 filter->aslist[direct].name = strdup (name);
4173 filter->aslist[direct].aslist = as_list_lookup (name);
4174
4175 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4176 return 0;
4177
4178 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004179 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004180 {
4181 filter = &peer->filter[afi][safi];
4182
4183 if (! peer->af_group[afi][safi])
4184 continue;
4185
4186 if (filter->aslist[direct].name)
4187 free (filter->aslist[direct].name);
4188 filter->aslist[direct].name = strdup (name);
4189 filter->aslist[direct].aslist = as_list_lookup (name);
4190 }
4191 return 0;
4192}
4193
4194int
4195peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4196{
4197 struct bgp_filter *filter;
4198 struct bgp_filter *gfilter;
4199 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004200 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004201
4202 if (! peer->afc[afi][safi])
4203 return BGP_ERR_PEER_INACTIVE;
4204
hassob5f29602005-05-25 21:00:28 +00004205 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004206 return BGP_ERR_INVALID_VALUE;
4207
hassob5f29602005-05-25 21:00:28 +00004208 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004209 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4210
4211 filter = &peer->filter[afi][safi];
4212
4213 /* apply peer-group filter */
4214 if (peer->af_group[afi][safi])
4215 {
4216 gfilter = &peer->group->conf->filter[afi][safi];
4217
4218 if (gfilter->aslist[direct].name)
4219 {
4220 if (filter->aslist[direct].name)
4221 free (filter->aslist[direct].name);
4222 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4223 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4224 return 0;
4225 }
4226 }
4227
4228 if (filter->aslist[direct].name)
4229 free (filter->aslist[direct].name);
4230 filter->aslist[direct].name = NULL;
4231 filter->aslist[direct].aslist = NULL;
4232
4233 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4234 return 0;
4235
4236 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004237 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004238 {
4239 filter = &peer->filter[afi][safi];
4240
4241 if (! peer->af_group[afi][safi])
4242 continue;
4243
4244 if (filter->aslist[direct].name)
4245 free (filter->aslist[direct].name);
4246 filter->aslist[direct].name = NULL;
4247 filter->aslist[direct].aslist = NULL;
4248 }
4249
4250 return 0;
4251}
4252
paul94f2b392005-06-28 12:44:16 +00004253static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004254peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004255{
4256 afi_t afi;
4257 safi_t safi;
4258 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004259 struct listnode *mnode, *mnnode;
4260 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004261 struct bgp *bgp;
4262 struct peer *peer;
4263 struct peer_group *group;
4264 struct bgp_filter *filter;
4265
paul1eb8ef22005-04-07 07:30:20 +00004266 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004267 {
paul1eb8ef22005-04-07 07:30:20 +00004268 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004269 {
4270 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4271 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4272 {
4273 filter = &peer->filter[afi][safi];
4274
4275 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4276 {
4277 if (filter->aslist[direct].name)
4278 filter->aslist[direct].aslist =
4279 as_list_lookup (filter->aslist[direct].name);
4280 else
4281 filter->aslist[direct].aslist = NULL;
4282 }
4283 }
4284 }
paul1eb8ef22005-04-07 07:30:20 +00004285 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004286 {
4287 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4288 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4289 {
4290 filter = &group->conf->filter[afi][safi];
4291
4292 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4293 {
4294 if (filter->aslist[direct].name)
4295 filter->aslist[direct].aslist =
4296 as_list_lookup (filter->aslist[direct].name);
4297 else
4298 filter->aslist[direct].aslist = NULL;
4299 }
4300 }
4301 }
4302 }
4303}
David Lamparter6b0655a2014-06-04 06:53:35 +02004304
paul718e3742002-12-13 20:15:29 +00004305/* Set route-map to the peer. */
4306int
4307peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004308 const char *name)
paul718e3742002-12-13 20:15:29 +00004309{
4310 struct bgp_filter *filter;
4311 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004312 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004313
4314 if (! peer->afc[afi][safi])
4315 return BGP_ERR_PEER_INACTIVE;
4316
paulfee0f4c2004-09-13 05:12:46 +00004317 if (direct != RMAP_IN && direct != RMAP_OUT &&
4318 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004319 return BGP_ERR_INVALID_VALUE;
4320
paulfee0f4c2004-09-13 05:12:46 +00004321 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4322 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004323 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4324
4325 filter = &peer->filter[afi][safi];
4326
4327 if (filter->map[direct].name)
4328 free (filter->map[direct].name);
4329
4330 filter->map[direct].name = strdup (name);
4331 filter->map[direct].map = route_map_lookup_by_name (name);
4332
4333 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4334 return 0;
4335
4336 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004337 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004338 {
4339 filter = &peer->filter[afi][safi];
4340
4341 if (! peer->af_group[afi][safi])
4342 continue;
4343
4344 if (filter->map[direct].name)
4345 free (filter->map[direct].name);
4346 filter->map[direct].name = strdup (name);
4347 filter->map[direct].map = route_map_lookup_by_name (name);
4348 }
4349 return 0;
4350}
4351
4352/* Unset route-map from the peer. */
4353int
4354peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4355{
4356 struct bgp_filter *filter;
4357 struct bgp_filter *gfilter;
4358 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004359 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004360
4361 if (! peer->afc[afi][safi])
4362 return BGP_ERR_PEER_INACTIVE;
4363
hassob5f29602005-05-25 21:00:28 +00004364 if (direct != RMAP_IN && direct != RMAP_OUT &&
4365 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004366 return BGP_ERR_INVALID_VALUE;
4367
hassob5f29602005-05-25 21:00:28 +00004368 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4369 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004370 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4371
4372 filter = &peer->filter[afi][safi];
4373
4374 /* apply peer-group filter */
4375 if (peer->af_group[afi][safi])
4376 {
4377 gfilter = &peer->group->conf->filter[afi][safi];
4378
4379 if (gfilter->map[direct].name)
4380 {
4381 if (filter->map[direct].name)
4382 free (filter->map[direct].name);
4383 filter->map[direct].name = strdup (gfilter->map[direct].name);
4384 filter->map[direct].map = gfilter->map[direct].map;
4385 return 0;
4386 }
4387 }
4388
4389 if (filter->map[direct].name)
4390 free (filter->map[direct].name);
4391 filter->map[direct].name = NULL;
4392 filter->map[direct].map = NULL;
4393
4394 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4395 return 0;
4396
4397 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004398 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004399 {
4400 filter = &peer->filter[afi][safi];
4401
4402 if (! peer->af_group[afi][safi])
4403 continue;
4404
4405 if (filter->map[direct].name)
4406 free (filter->map[direct].name);
4407 filter->map[direct].name = NULL;
4408 filter->map[direct].map = NULL;
4409 }
4410 return 0;
4411}
David Lamparter6b0655a2014-06-04 06:53:35 +02004412
paul718e3742002-12-13 20:15:29 +00004413/* Set unsuppress-map to the peer. */
4414int
paulfd79ac92004-10-13 05:06:08 +00004415peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4416 const char *name)
paul718e3742002-12-13 20:15:29 +00004417{
4418 struct bgp_filter *filter;
4419 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004420 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004421
4422 if (! peer->afc[afi][safi])
4423 return BGP_ERR_PEER_INACTIVE;
4424
4425 if (peer_is_group_member (peer, afi, safi))
4426 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4427
4428 filter = &peer->filter[afi][safi];
4429
4430 if (filter->usmap.name)
4431 free (filter->usmap.name);
4432
4433 filter->usmap.name = strdup (name);
4434 filter->usmap.map = route_map_lookup_by_name (name);
4435
4436 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4437 return 0;
4438
4439 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004440 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004441 {
4442 filter = &peer->filter[afi][safi];
4443
4444 if (! peer->af_group[afi][safi])
4445 continue;
4446
4447 if (filter->usmap.name)
4448 free (filter->usmap.name);
4449 filter->usmap.name = strdup (name);
4450 filter->usmap.map = route_map_lookup_by_name (name);
4451 }
4452 return 0;
4453}
4454
4455/* Unset route-map from the peer. */
4456int
4457peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4458{
4459 struct bgp_filter *filter;
4460 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004461 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004462
4463 if (! peer->afc[afi][safi])
4464 return BGP_ERR_PEER_INACTIVE;
4465
4466 if (peer_is_group_member (peer, afi, safi))
4467 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4468
4469 filter = &peer->filter[afi][safi];
4470
4471 if (filter->usmap.name)
4472 free (filter->usmap.name);
4473 filter->usmap.name = NULL;
4474 filter->usmap.map = NULL;
4475
4476 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4477 return 0;
4478
4479 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004480 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004481 {
4482 filter = &peer->filter[afi][safi];
4483
4484 if (! peer->af_group[afi][safi])
4485 continue;
4486
4487 if (filter->usmap.name)
4488 free (filter->usmap.name);
4489 filter->usmap.name = NULL;
4490 filter->usmap.map = NULL;
4491 }
4492 return 0;
4493}
David Lamparter6b0655a2014-06-04 06:53:35 +02004494
paul718e3742002-12-13 20:15:29 +00004495int
4496peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004497 u_int32_t max, u_char threshold,
4498 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004499{
4500 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004501 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004502
4503 if (! peer->afc[afi][safi])
4504 return BGP_ERR_PEER_INACTIVE;
4505
4506 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4507 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004508 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004509 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004510 if (warning)
4511 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4512 else
4513 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4514
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07004515 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
paul718e3742002-12-13 20:15:29 +00004516 {
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07004517 group = peer->group;
4518 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4519 {
4520 if (! peer->af_group[afi][safi])
4521 continue;
paul718e3742002-12-13 20:15:29 +00004522
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07004523 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4524 peer->pmax[afi][safi] = max;
4525 peer->pmax_threshold[afi][safi] = threshold;
4526 peer->pmax_restart[afi][safi] = restart;
4527 if (warning)
4528 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4529 else
4530 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4531
4532 if ((peer->status == Established) && (peer->afc[afi][safi]))
4533 bgp_maximum_prefix_overflow (peer, afi, safi, 1);
4534 }
paul718e3742002-12-13 20:15:29 +00004535 }
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07004536 else
4537 {
4538 if ((peer->status == Established) && (peer->afc[afi][safi]))
4539 bgp_maximum_prefix_overflow (peer, afi, safi, 1);
4540 }
4541
paul718e3742002-12-13 20:15:29 +00004542 return 0;
4543}
4544
4545int
4546peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4547{
4548 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004549 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004550
4551 if (! peer->afc[afi][safi])
4552 return BGP_ERR_PEER_INACTIVE;
4553
4554 /* apply peer-group config */
4555 if (peer->af_group[afi][safi])
4556 {
4557 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4558 PEER_FLAG_MAX_PREFIX))
4559 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4560 else
4561 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4562
4563 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4564 PEER_FLAG_MAX_PREFIX_WARNING))
4565 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4566 else
4567 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4568
4569 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004570 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004571 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004572 return 0;
4573 }
4574
4575 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4576 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4577 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004578 peer->pmax_threshold[afi][safi] = 0;
4579 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004580
4581 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4582 return 0;
4583
4584 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004585 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004586 {
4587 if (! peer->af_group[afi][safi])
4588 continue;
4589
4590 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4591 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4592 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004593 peer->pmax_threshold[afi][safi] = 0;
4594 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004595 }
4596 return 0;
4597}
David Lamparter5f9adb52014-05-19 23:15:02 +02004598
Nick Hilliardfa411a22011-03-23 15:33:17 +00004599/* Set # of hops between us and BGP peer. */
4600int
4601peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4602{
4603 struct peer_group *group;
4604 struct listnode *node, *nnode;
Timo Teräse3443a22016-10-19 16:02:34 +03004605 struct peer *peer1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004606
4607 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4608
Timo Teräse3443a22016-10-19 16:02:34 +03004609 if (peer->ttl != 0)
4610 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004611
Timo Teräse3443a22016-10-19 16:02:34 +03004612 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4613 {
4614 group = peer->group;
4615 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4616 {
4617 if (peer1->ttl != 0)
4618 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4619 }
David Lamparter5f9adb52014-05-19 23:15:02 +02004620 }
Timo Teräse3443a22016-10-19 16:02:34 +03004621
Nick Hilliardfa411a22011-03-23 15:33:17 +00004622 peer->gtsm_hops = gtsm_hops;
4623
Nick Hilliardfa411a22011-03-23 15:33:17 +00004624 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4625 {
Timo Teräse3443a22016-10-19 16:02:34 +03004626 bgp_set_socket_ttl (peer, peer->fd);
Nick Hilliardfa411a22011-03-23 15:33:17 +00004627 }
4628 else
4629 {
4630 group = peer->group;
4631 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4632 {
Timo Teräse3443a22016-10-19 16:02:34 +03004633 peer->gtsm_hops = gtsm_hops;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004634
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004635 /* Change setting of existing peer
4636 * established then change value (may break connectivity)
4637 * not established yet (teardown session and restart)
4638 * no session then do nothing (will get handled by next connection)
4639 */
4640 if (peer->status == Established)
4641 {
Timo Teräse3443a22016-10-19 16:02:34 +03004642 bgp_set_socket_ttl (peer, peer->fd);
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004643 }
4644 else if (peer->status < Established)
4645 {
4646 if (BGP_DEBUG (events, EVENTS))
4647 zlog_debug ("%s Min-ttl changed", peer->host);
4648 BGP_EVENT_ADD (peer, BGP_Stop);
4649 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004650 }
4651 }
4652
4653 return 0;
4654}
4655
4656int
paul718e3742002-12-13 20:15:29 +00004657peer_clear (struct peer *peer)
4658{
4659 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4660 {
hasso0a486e52005-02-01 20:57:17 +00004661 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4662 {
4663 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4664 if (peer->t_pmax_restart)
4665 {
4666 BGP_TIMER_OFF (peer->t_pmax_restart);
4667 if (BGP_DEBUG (events, EVENTS))
4668 zlog_debug ("%s Maximum-prefix restart timer canceled",
4669 peer->host);
4670 }
4671 BGP_EVENT_ADD (peer, BGP_Start);
4672 return 0;
4673 }
4674
paul718e3742002-12-13 20:15:29 +00004675 peer->v_start = BGP_INIT_START_TIMER;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00004676 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00004677 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4678 BGP_NOTIFY_CEASE_ADMIN_RESET);
4679 else
4680 BGP_EVENT_ADD (peer, BGP_Stop);
4681 }
4682 return 0;
4683}
4684
4685int
4686peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4687 enum bgp_clear_type stype)
4688{
4689 if (peer->status != Established)
4690 return 0;
4691
4692 if (! peer->afc[afi][safi])
4693 return BGP_ERR_AF_UNCONFIGURED;
4694
Timo Teräs5a2a1ec2015-10-22 11:35:18 +03004695 peer->rtt = sockopt_tcp_rtt (peer->fd);
4696
paulfee0f4c2004-09-13 05:12:46 +00004697 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4698 {
4699 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4700 return 0;
4701 bgp_check_local_routes_rsclient (peer, afi, safi);
4702 bgp_soft_reconfig_rsclient (peer, afi, safi);
4703 }
4704
paul718e3742002-12-13 20:15:29 +00004705 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4706 bgp_announce_route (peer, afi, safi);
4707
4708 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4709 {
4710 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4711 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4712 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4713 {
4714 struct bgp_filter *filter = &peer->filter[afi][safi];
4715 u_char prefix_type;
4716
4717 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4718 prefix_type = ORF_TYPE_PREFIX;
4719 else
4720 prefix_type = ORF_TYPE_PREFIX_OLD;
4721
4722 if (filter->plist[FILTER_IN].plist)
4723 {
4724 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4725 bgp_route_refresh_send (peer, afi, safi,
4726 prefix_type, REFRESH_DEFER, 1);
4727 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4728 REFRESH_IMMEDIATE, 0);
4729 }
4730 else
4731 {
4732 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4733 bgp_route_refresh_send (peer, afi, safi,
4734 prefix_type, REFRESH_IMMEDIATE, 1);
4735 else
4736 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4737 }
4738 return 0;
4739 }
4740 }
4741
4742 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4743 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4744 {
4745 /* If neighbor has soft reconfiguration inbound flag.
4746 Use Adj-RIB-In database. */
4747 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4748 bgp_soft_reconfig_in (peer, afi, safi);
4749 else
4750 {
4751 /* If neighbor has route refresh capability, send route refresh
4752 message to the peer. */
4753 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4754 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4755 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4756 else
4757 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4758 }
4759 }
4760 return 0;
4761}
David Lamparter6b0655a2014-06-04 06:53:35 +02004762
paulfd79ac92004-10-13 05:06:08 +00004763/* Display peer uptime.*/
4764/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004765char *
4766peer_uptime (time_t uptime2, char *buf, size_t len)
4767{
4768 time_t uptime1;
4769 struct tm *tm;
4770
4771 /* Check buffer length. */
4772 if (len < BGP_UPTIME_LEN)
4773 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004774 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004775 /* XXX: should return status instead of buf... */
4776 snprintf (buf, len, "<error> ");
4777 return buf;
paul718e3742002-12-13 20:15:29 +00004778 }
4779
4780 /* If there is no connection has been done before print `never'. */
4781 if (uptime2 == 0)
4782 {
4783 snprintf (buf, len, "never ");
4784 return buf;
4785 }
4786
4787 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004788 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004789 uptime1 -= uptime2;
4790 tm = gmtime (&uptime1);
Paul Jakma84c38402015-05-26 15:19:38 +01004791
paul718e3742002-12-13 20:15:29 +00004792 /* Making formatted timer strings. */
4793#define ONE_DAY_SECOND 60*60*24
Paul Jakma84c38402015-05-26 15:19:38 +01004794#define ONE_WEEK_SECOND ONE_DAY_SECOND*7
4795#define ONE_YEAR_SECOND ONE_DAY_SECOND*365
paul718e3742002-12-13 20:15:29 +00004796
4797 if (uptime1 < ONE_DAY_SECOND)
4798 snprintf (buf, len, "%02d:%02d:%02d",
4799 tm->tm_hour, tm->tm_min, tm->tm_sec);
4800 else if (uptime1 < ONE_WEEK_SECOND)
4801 snprintf (buf, len, "%dd%02dh%02dm",
4802 tm->tm_yday, tm->tm_hour, tm->tm_min);
Paul Jakma84c38402015-05-26 15:19:38 +01004803 else if (uptime1 < ONE_YEAR_SECOND)
paul718e3742002-12-13 20:15:29 +00004804 snprintf (buf, len, "%02dw%dd%02dh",
4805 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
Paul Jakma84c38402015-05-26 15:19:38 +01004806 else
4807 snprintf (buf, len, "%02dy%02dw%dd",
4808 tm->tm_year - 70, tm->tm_yday/7,
4809 tm->tm_yday - ((tm->tm_yday/7) * 7));
paul718e3742002-12-13 20:15:29 +00004810 return buf;
4811}
David Lamparter6b0655a2014-06-04 06:53:35 +02004812
paul94f2b392005-06-28 12:44:16 +00004813static void
paul718e3742002-12-13 20:15:29 +00004814bgp_config_write_filter (struct vty *vty, struct peer *peer,
4815 afi_t afi, safi_t safi)
4816{
4817 struct bgp_filter *filter;
4818 struct bgp_filter *gfilter = NULL;
4819 char *addr;
4820 int in = FILTER_IN;
4821 int out = FILTER_OUT;
4822
4823 addr = peer->host;
4824 filter = &peer->filter[afi][safi];
4825 if (peer->af_group[afi][safi])
4826 gfilter = &peer->group->conf->filter[afi][safi];
4827
4828 /* distribute-list. */
4829 if (filter->dlist[in].name)
4830 if (! gfilter || ! gfilter->dlist[in].name
4831 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4832 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4833 filter->dlist[in].name, VTY_NEWLINE);
4834 if (filter->dlist[out].name && ! gfilter)
4835 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4836 filter->dlist[out].name, VTY_NEWLINE);
4837
4838 /* prefix-list. */
4839 if (filter->plist[in].name)
4840 if (! gfilter || ! gfilter->plist[in].name
4841 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4842 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4843 filter->plist[in].name, VTY_NEWLINE);
4844 if (filter->plist[out].name && ! gfilter)
4845 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4846 filter->plist[out].name, VTY_NEWLINE);
4847
4848 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004849 if (filter->map[RMAP_IN].name)
4850 if (! gfilter || ! gfilter->map[RMAP_IN].name
4851 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004852 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004853 filter->map[RMAP_IN].name, VTY_NEWLINE);
4854 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004855 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004856 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4857 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4858 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4859 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4860 if (filter->map[RMAP_EXPORT].name)
4861 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4862 || strcmp (filter->map[RMAP_EXPORT].name,
4863 gfilter->map[RMAP_EXPORT].name) != 0)
4864 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4865 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004866
4867 /* unsuppress-map */
4868 if (filter->usmap.name && ! gfilter)
4869 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4870 filter->usmap.name, VTY_NEWLINE);
4871
4872 /* filter-list. */
4873 if (filter->aslist[in].name)
4874 if (! gfilter || ! gfilter->aslist[in].name
4875 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4876 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4877 filter->aslist[in].name, VTY_NEWLINE);
4878 if (filter->aslist[out].name && ! gfilter)
4879 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4880 filter->aslist[out].name, VTY_NEWLINE);
4881}
4882
4883/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004884static void
paul718e3742002-12-13 20:15:29 +00004885bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4886 struct peer *peer, afi_t afi, safi_t safi)
4887{
paul718e3742002-12-13 20:15:29 +00004888 struct peer *g_peer = NULL;
4889 char buf[SU_ADDRSTRLEN];
4890 char *addr;
4891
paul718e3742002-12-13 20:15:29 +00004892 addr = peer->host;
4893 if (peer_group_active (peer))
4894 g_peer = peer->group->conf;
4895
4896 /************************************
4897 ****** Global to the neighbor ******
4898 ************************************/
4899 if (afi == AFI_IP && safi == SAFI_UNICAST)
4900 {
4901 /* remote-as. */
4902 if (! peer_group_active (peer))
4903 {
4904 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4905 vty_out (vty, " neighbor %s peer-group%s", addr,
4906 VTY_NEWLINE);
4907 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004908 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004909 VTY_NEWLINE);
4910 }
4911 else
4912 {
4913 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004914 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004915 VTY_NEWLINE);
4916 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4917 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4918 peer->group->name, VTY_NEWLINE);
4919 }
4920
4921 /* local-as. */
4922 if (peer->change_local_as)
4923 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00004924 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004925 peer->change_local_as,
4926 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00004927 " no-prepend" : "",
4928 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
4929 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004930
4931 /* Description. */
4932 if (peer->desc)
4933 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4934 VTY_NEWLINE);
4935
4936 /* Shutdown. */
4937 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4938 if (! peer_group_active (peer) ||
4939 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4940 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4941
Paul Jakma0df7c912008-07-21 21:02:49 +00004942 /* Password. */
4943 if (peer->password)
4944 if (!peer_group_active (peer)
4945 || ! g_peer->password
4946 || strcmp (peer->password, g_peer->password) != 0)
4947 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4948 VTY_NEWLINE);
4949
paul718e3742002-12-13 20:15:29 +00004950 /* BGP port. */
4951 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004952 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004953 VTY_NEWLINE);
4954
4955 /* Local interface name. */
4956 if (peer->ifname)
4957 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4958 VTY_NEWLINE);
4959
4960 /* Passive. */
4961 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4962 if (! peer_group_active (peer) ||
4963 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4964 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4965
Timo Teräse3443a22016-10-19 16:02:34 +03004966 /* TTL option */
4967 if (peer->gtsm_hops && ! peer_group_active (peer))
4968 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
4969 peer->gtsm_hops, VTY_NEWLINE);
4970 else if (peer->ttl && ! peer_group_active (peer))
4971 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4972 VTY_NEWLINE);
Nick Hilliardfa411a22011-03-23 15:33:17 +00004973
hasso6ffd2072005-02-02 14:50:11 +00004974 /* disable-connected-check. */
4975 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004976 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004977 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4978 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004979
4980 /* Update-source. */
4981 if (peer->update_if)
4982 if (! peer_group_active (peer) || ! g_peer->update_if
4983 || strcmp (g_peer->update_if, peer->update_if) != 0)
4984 vty_out (vty, " neighbor %s update-source %s%s", addr,
4985 peer->update_if, VTY_NEWLINE);
4986 if (peer->update_source)
4987 if (! peer_group_active (peer) || ! g_peer->update_source
4988 || sockunion_cmp (g_peer->update_source,
4989 peer->update_source) != 0)
4990 vty_out (vty, " neighbor %s update-source %s%s", addr,
4991 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4992 VTY_NEWLINE);
4993
paul718e3742002-12-13 20:15:29 +00004994 /* advertisement-interval */
Daniel Walton0d7435f2015-10-22 11:35:20 +03004995 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV) &&
4996 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00004997 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4998 addr, peer->v_routeadv, VTY_NEWLINE);
4999
5000 /* timers. */
5001 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
5002 && ! peer_group_active (peer))
5003 vty_out (vty, " neighbor %s timers %d %d%s", addr,
5004 peer->keepalive, peer->holdtime, VTY_NEWLINE);
5005
Daniel Walton0d7435f2015-10-22 11:35:20 +03005006 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT) &&
5007 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00005008 vty_out (vty, " neighbor %s timers connect %d%s", addr,
5009 peer->connect, VTY_NEWLINE);
5010
5011 /* Default weight. */
5012 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
5013 if (! peer_group_active (peer) ||
5014 g_peer->weight != peer->weight)
5015 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
5016 VTY_NEWLINE);
5017
paul718e3742002-12-13 20:15:29 +00005018 /* Dynamic capability. */
5019 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5020 if (! peer_group_active (peer) ||
5021 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5022 vty_out (vty, " neighbor %s capability dynamic%s", addr,
5023 VTY_NEWLINE);
5024
5025 /* dont capability negotiation. */
5026 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
5027 if (! peer_group_active (peer) ||
5028 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
5029 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
5030 VTY_NEWLINE);
5031
5032 /* override capability negotiation. */
5033 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5034 if (! peer_group_active (peer) ||
5035 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5036 vty_out (vty, " neighbor %s override-capability%s", addr,
5037 VTY_NEWLINE);
5038
5039 /* strict capability negotiation. */
5040 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5041 if (! peer_group_active (peer) ||
5042 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5043 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
5044 VTY_NEWLINE);
5045
Christian Franke15c71342012-11-19 11:17:31 +00005046 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
paul718e3742002-12-13 20:15:29 +00005047 {
5048 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5049 {
5050 if (peer->afc[AFI_IP][SAFI_UNICAST])
5051 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5052 }
5053 else
5054 {
5055 if (! peer->afc[AFI_IP][SAFI_UNICAST])
5056 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
5057 }
5058 }
5059 }
5060
5061
5062 /************************************
5063 ****** Per AF to the neighbor ******
5064 ************************************/
5065
5066 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
5067 {
5068 if (peer->af_group[afi][safi])
5069 vty_out (vty, " neighbor %s peer-group %s%s", addr,
5070 peer->group->name, VTY_NEWLINE);
5071 else
5072 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5073 }
5074
5075 /* ORF capability. */
5076 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5077 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5078 if (! peer->af_group[afi][safi])
5079 {
5080 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
5081
5082 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5083 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5084 vty_out (vty, " both");
5085 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
5086 vty_out (vty, " send");
5087 else
5088 vty_out (vty, " receive");
5089 vty_out (vty, "%s", VTY_NEWLINE);
5090 }
5091
5092 /* Route reflector client. */
5093 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
5094 && ! peer->af_group[afi][safi])
5095 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
5096 VTY_NEWLINE);
5097
5098 /* Nexthop self. */
5099 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
5100 && ! peer->af_group[afi][safi])
Timo Teräs9e7a53c2014-04-24 10:22:37 +03005101 vty_out (vty, " neighbor %s next-hop-self%s%s", addr,
5102 peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ?
5103 " all" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005104
5105 /* Remove private AS. */
5106 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
5107 && ! peer->af_group[afi][safi])
5108 vty_out (vty, " neighbor %s remove-private-AS%s",
5109 addr, VTY_NEWLINE);
5110
5111 /* send-community print. */
5112 if (! peer->af_group[afi][safi])
5113 {
5114 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5115 {
5116 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
Job Snijders3334bab2017-01-20 14:47:12 +00005117 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)
5118 && peer_af_flag_check(peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY))
5119 vty_out (vty, " neighbor %s send-community all%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005120 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5121 vty_out (vty, " neighbor %s send-community extended%s",
5122 addr, VTY_NEWLINE);
Job Snijders3334bab2017-01-20 14:47:12 +00005123 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY))
5124 vty_out (vty, " neighbor %s send-community large%s",
5125 addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005126 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5127 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
5128 }
5129 else
5130 {
5131 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
Job Snijders3334bab2017-01-20 14:47:12 +00005132 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY)
5133 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY))
5134 vty_out (vty, " no neighbor %s send-community all%s",
paul718e3742002-12-13 20:15:29 +00005135 addr, VTY_NEWLINE);
5136 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5137 vty_out (vty, " no neighbor %s send-community extended%s",
5138 addr, VTY_NEWLINE);
Job Snijders3334bab2017-01-20 14:47:12 +00005139 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_LARGE_COMMUNITY))
5140 vty_out (vty, " no neighbor %s send-community large%s",
5141 addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005142 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5143 vty_out (vty, " no neighbor %s send-community%s",
5144 addr, VTY_NEWLINE);
5145 }
5146 }
5147
5148 /* Default information */
5149 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5150 && ! peer->af_group[afi][safi])
5151 {
5152 vty_out (vty, " neighbor %s default-originate", addr);
5153 if (peer->default_rmap[afi][safi].name)
5154 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5155 vty_out (vty, "%s", VTY_NEWLINE);
5156 }
5157
5158 /* Soft reconfiguration inbound. */
5159 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5160 if (! peer->af_group[afi][safi] ||
5161 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5162 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5163 VTY_NEWLINE);
5164
5165 /* maximum-prefix. */
5166 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5167 if (! peer->af_group[afi][safi]
5168 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005169 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005170 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5171 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005172 {
hasso0a486e52005-02-01 20:57:17 +00005173 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5174 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5175 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5176 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5177 vty_out (vty, " warning-only");
5178 if (peer->pmax_restart[afi][safi])
5179 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5180 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005181 }
paul718e3742002-12-13 20:15:29 +00005182
5183 /* Route server client. */
5184 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5185 && ! peer->af_group[afi][safi])
5186 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5187
Dylan Hall3cf12882011-10-27 15:28:17 +04005188 /* Nexthop-local unchanged. */
5189 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5190 && ! peer->af_group[afi][safi])
5191 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5192
paul718e3742002-12-13 20:15:29 +00005193 /* Allow AS in. */
5194 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5195 if (! peer_group_active (peer)
5196 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5197 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5198 {
5199 if (peer->allowas_in[afi][safi] == 3)
5200 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5201 else
5202 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5203 peer->allowas_in[afi][safi], VTY_NEWLINE);
5204 }
5205
5206 /* Filter. */
5207 bgp_config_write_filter (vty, peer, afi, safi);
5208
5209 /* atribute-unchanged. */
5210 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5211 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5212 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5213 && ! peer->af_group[afi][safi])
5214 {
5215 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5216 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5217 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5218 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5219 else
5220 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5221 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5222 " as-path" : "",
5223 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5224 " next-hop" : "",
5225 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5226 " med" : "", VTY_NEWLINE);
5227 }
5228}
5229
5230/* Display "address-family" configuration header. */
5231void
5232bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5233 int *write)
5234{
5235 if (*write)
5236 return;
5237
5238 if (afi == AFI_IP && safi == SAFI_UNICAST)
5239 return;
5240
5241 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5242
5243 if (afi == AFI_IP)
5244 {
5245 if (safi == SAFI_MULTICAST)
5246 vty_out (vty, "ipv4 multicast");
5247 else if (safi == SAFI_MPLS_VPN)
Lou Bergera3fda882016-01-12 13:42:04 -05005248 vty_out (vty, "vpnv4");
5249 else if (safi == SAFI_ENCAP)
5250 vty_out (vty, "encap");
paul718e3742002-12-13 20:15:29 +00005251 }
5252 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005253 {
Lou Berger13c378d2016-01-12 13:41:56 -05005254 if (safi == SAFI_MPLS_VPN)
5255 vty_out (vty, "vpnv6");
Lou Bergera3fda882016-01-12 13:42:04 -05005256 else if (safi == SAFI_ENCAP)
5257 vty_out (vty, "encapv6");
Lou Berger13c378d2016-01-12 13:41:56 -05005258 else
5259 {
5260 vty_out (vty, "ipv6");
5261 if (safi == SAFI_MULTICAST)
5262 vty_out (vty, " multicast");
5263 }
Paul Jakma37a217a2007-04-10 19:20:29 +00005264 }
paul718e3742002-12-13 20:15:29 +00005265
5266 vty_out (vty, "%s", VTY_NEWLINE);
5267
5268 *write = 1;
5269}
5270
5271/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005272static int
paul718e3742002-12-13 20:15:29 +00005273bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5274 safi_t safi)
5275{
5276 int write = 0;
5277 struct peer *peer;
5278 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005279 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005280
5281 bgp_config_write_network (vty, bgp, afi, safi, &write);
5282
5283 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5284
paul1eb8ef22005-04-07 07:30:20 +00005285 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005286 {
5287 if (group->conf->afc[afi][safi])
5288 {
5289 bgp_config_write_family_header (vty, afi, safi, &write);
5290 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5291 }
5292 }
paul1eb8ef22005-04-07 07:30:20 +00005293 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005294 {
5295 if (peer->afc[afi][safi])
5296 {
5297 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5298 {
5299 bgp_config_write_family_header (vty, afi, safi, &write);
5300 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5301 }
5302 }
5303 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005304
5305 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5306
Roman Hoog Antink6184c392014-03-17 14:01:42 +01005307 bgp_config_write_distance (vty, bgp, afi, safi, &write);
5308
paul718e3742002-12-13 20:15:29 +00005309 if (write)
5310 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5311
5312 return write;
5313}
5314
5315int
5316bgp_config_write (struct vty *vty)
5317{
5318 int write = 0;
5319 struct bgp *bgp;
5320 struct peer_group *group;
5321 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005322 struct listnode *node, *nnode;
5323 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005324
5325 /* BGP Multiple instance. */
5326 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5327 {
5328 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5329 write++;
5330 }
5331
5332 /* BGP Config type. */
5333 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5334 {
5335 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5336 write++;
5337 }
5338
5339 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005340 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005341 {
5342 if (write)
5343 vty_out (vty, "!%s", VTY_NEWLINE);
5344
5345 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005346 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005347
5348 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5349 {
5350 if (bgp->name)
5351 vty_out (vty, " view %s", bgp->name);
5352 }
5353 vty_out (vty, "%s", VTY_NEWLINE);
5354
5355 /* No Synchronization */
5356 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5357 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5358
5359 /* BGP fast-external-failover. */
5360 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5361 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5362
5363 /* BGP router ID. */
5364 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5365 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5366 VTY_NEWLINE);
5367
paul848973c2003-08-13 00:32:49 +00005368 /* BGP log-neighbor-changes. */
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07005369 if (!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5370 vty_out (vty, " no bgp log-neighbor-changes%s", VTY_NEWLINE);
paul848973c2003-08-13 00:32:49 +00005371
paul718e3742002-12-13 20:15:29 +00005372 /* BGP configuration. */
5373 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5374 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5375
5376 /* BGP default ipv4-unicast. */
5377 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5378 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5379
5380 /* BGP default local-preference. */
5381 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5382 vty_out (vty, " bgp default local-preference %d%s",
5383 bgp->default_local_pref, VTY_NEWLINE);
5384
5385 /* BGP client-to-client reflection. */
5386 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5387 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5388
5389 /* BGP cluster ID. */
5390 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5391 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5392 VTY_NEWLINE);
5393
hassoe0701b72004-05-20 09:19:34 +00005394 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005395 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005396 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5397 VTY_NEWLINE);
5398
5399 /* Confederation peer */
5400 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005401 {
hassoe0701b72004-05-20 09:19:34 +00005402 int i;
paul718e3742002-12-13 20:15:29 +00005403
hassoe0701b72004-05-20 09:19:34 +00005404 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005405
hassoe0701b72004-05-20 09:19:34 +00005406 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005407 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005408
hassoe0701b72004-05-20 09:19:34 +00005409 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005410 }
5411
5412 /* BGP enforce-first-as. */
5413 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5414 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5415
5416 /* BGP deterministic-med. */
5417 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5418 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005419
5420 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005421 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5422 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5423 bgp->stalepath_time, VTY_NEWLINE);
Philippe Guibert4afa3dd2016-05-24 16:52:02 +02005424 if (bgp->restart_time != BGP_DEFAULT_RESTART_TIME)
5425 vty_out (vty, " bgp graceful-restart restart-time %d%s",
5426 bgp->restart_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005427 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5428 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5429
paul718e3742002-12-13 20:15:29 +00005430 /* BGP bestpath method. */
5431 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5432 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005433 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5434 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
Pradosh Mohapatra2fdd4552013-09-07 07:02:36 +00005435 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
5436 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
5437 }
Dinesh Dutt083e5e22015-11-09 20:21:54 -05005438 if (bgp_flag_check (bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
5439 vty_out (vty, " bgp route-reflector allow-outbound-policy%s",
5440 VTY_NEWLINE);
5441 }
paul718e3742002-12-13 20:15:29 +00005442 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5443 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5444 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5445 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5446 {
5447 vty_out (vty, " bgp bestpath med");
5448 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5449 vty_out (vty, " confed");
5450 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5451 vty_out (vty, " missing-as-worst");
5452 vty_out (vty, "%s", VTY_NEWLINE);
5453 }
5454
5455 /* BGP network import check. */
5456 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5457 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5458
paul718e3742002-12-13 20:15:29 +00005459 /* BGP flag dampening. */
5460 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5461 BGP_CONFIG_DAMPENING))
5462 bgp_config_write_damp (vty);
5463
5464 /* BGP static route configuration. */
5465 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5466
5467 /* BGP redistribute configuration. */
5468 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5469
5470 /* BGP timers configuration. */
5471 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5472 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5473 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5474 bgp->default_holdtime, VTY_NEWLINE);
5475
5476 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005477 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005478 {
5479 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5480 }
5481
5482 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005483 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005484 {
5485 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5486 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5487 }
5488
Josh Bailey165b5ff2011-07-20 20:43:22 -07005489 /* maximum-paths */
5490 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5491
paul718e3742002-12-13 20:15:29 +00005492 /* Distance configuration. */
Roman Hoog Antink6184c392014-03-17 14:01:42 +01005493 bgp_config_write_distance (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
paul718e3742002-12-13 20:15:29 +00005494
5495 /* No auto-summary */
5496 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5497 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5498
5499 /* IPv4 multicast configuration. */
5500 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5501
5502 /* IPv4 VPN configuration. */
5503 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5504
Lou Bergera3fda882016-01-12 13:42:04 -05005505 /* ENCAPv4 configuration. */
5506 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_ENCAP);
5507
paul718e3742002-12-13 20:15:29 +00005508 /* IPv6 unicast configuration. */
5509 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5510
Paul Jakma37a217a2007-04-10 19:20:29 +00005511 /* IPv6 multicast configuration. */
5512 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5513
Lou Berger13c378d2016-01-12 13:41:56 -05005514 /* IPv6 VPN configuration. */
5515 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MPLS_VPN);
5516
Lou Bergera3fda882016-01-12 13:42:04 -05005517 /* ENCAPv6 configuration. */
5518 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_ENCAP);
5519
5520 vty_out (vty, " exit%s", VTY_NEWLINE);
5521
paul718e3742002-12-13 20:15:29 +00005522 write++;
5523 }
5524 return write;
5525}
5526
5527void
paul94f2b392005-06-28 12:44:16 +00005528bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005529{
5530 memset (&bgp_master, 0, sizeof (struct bgp_master));
5531
5532 bm = &bgp_master;
5533 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005534 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005535 bm->port = BGP_PORT_DEFAULT;
5536 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005537 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005538}
paul200df112005-06-01 11:17:05 +00005539
David Lamparter6b0655a2014-06-04 06:53:35 +02005540
paul718e3742002-12-13 20:15:29 +00005541void
paul94f2b392005-06-28 12:44:16 +00005542bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005543{
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07005544
5545 /* allocates some vital data structures used by peer commands in vty_init */
5546 bgp_scan_init ();
paul718e3742002-12-13 20:15:29 +00005547
paul718e3742002-12-13 20:15:29 +00005548 /* Init zebra. */
Donald Sharp774914f2015-10-14 08:50:39 -04005549 bgp_zebra_init (bm->master);
paul718e3742002-12-13 20:15:29 +00005550
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07005551 /* BGP VTY commands installation. */
5552 bgp_vty_init ();
5553
paul718e3742002-12-13 20:15:29 +00005554 /* BGP inits. */
5555 bgp_attr_init ();
5556 bgp_debug_init ();
5557 bgp_dump_init ();
5558 bgp_route_init ();
5559 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005560 bgp_address_init ();
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07005561 bgp_scan_vty_init();
paul718e3742002-12-13 20:15:29 +00005562 bgp_mplsvpn_init ();
Lou Berger298cc2f2016-01-12 13:42:02 -05005563 bgp_encap_init ();
paul718e3742002-12-13 20:15:29 +00005564
5565 /* Access list initialize. */
5566 access_list_init ();
5567 access_list_add_hook (peer_distribute_update);
5568 access_list_delete_hook (peer_distribute_update);
5569
5570 /* Filter list initialize. */
5571 bgp_filter_init ();
5572 as_list_add_hook (peer_aslist_update);
5573 as_list_delete_hook (peer_aslist_update);
5574
5575 /* Prefix list initialize.*/
5576 prefix_list_init ();
5577 prefix_list_add_hook (peer_prefix_list_update);
5578 prefix_list_delete_hook (peer_prefix_list_update);
5579
5580 /* Community list initialize. */
5581 bgp_clist = community_list_init ();
5582
5583#ifdef HAVE_SNMP
5584 bgp_snmp_init ();
5585#endif /* HAVE_SNMP */
5586}
paul545acaf2004-04-20 15:13:15 +00005587
5588void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005589bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005590{
paul545acaf2004-04-20 15:13:15 +00005591 struct bgp *bgp;
5592 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005593 struct listnode *node, *nnode;
5594 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005595
paul1eb8ef22005-04-07 07:30:20 +00005596 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5597 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005598 if (peer->status == Established)
5599 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5600 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005601
paul545acaf2004-04-20 15:13:15 +00005602 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005603
paule210cf92005-06-15 19:15:35 +00005604 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005605 {
5606 work_queue_free (bm->process_main_queue);
5607 bm->process_main_queue = NULL;
5608 }
paule210cf92005-06-15 19:15:35 +00005609 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005610 {
5611 work_queue_free (bm->process_rsclient_queue);
5612 bm->process_rsclient_queue = NULL;
5613 }
paul545acaf2004-04-20 15:13:15 +00005614}