blob: 56e4322b9fc06f791775d5b06eae9f4ef4b2dda1 [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);
630 }
631
632 /* Clear neighbor default_originate_rmap */
633 if (peer->default_rmap[afi][safi].name)
634 free (peer->default_rmap[afi][safi].name);
635 peer->default_rmap[afi][safi].name = NULL;
636 peer->default_rmap[afi][safi].map = NULL;
637
638 /* Clear neighbor maximum-prefix */
639 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +0000640 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000641}
642
643/* peer global config reset */
paul94f2b392005-06-28 12:44:16 +0000644static void
paul718e3742002-12-13 20:15:29 +0000645peer_global_config_reset (struct peer *peer)
646{
647 peer->weight = 0;
648 peer->change_local_as = 0;
Timo Teräse3443a22016-10-19 16:02:34 +0300649 peer->ttl = 0;
650 peer->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +0000651 if (peer->update_source)
652 {
653 sockunion_free (peer->update_source);
654 peer->update_source = NULL;
655 }
656 if (peer->update_if)
657 {
658 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
659 peer->update_if = NULL;
660 }
661
662 if (peer_sort (peer) == BGP_PEER_IBGP)
663 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
664 else
665 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
666
667 peer->flags = 0;
668 peer->config = 0;
669 peer->holdtime = 0;
670 peer->keepalive = 0;
671 peer->connect = 0;
672 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
673}
674
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000675/* Check peer's AS number and determines if this peer is IBGP or EBGP */
676static bgp_peer_sort_t
677peer_calc_sort (struct peer *peer)
paul718e3742002-12-13 20:15:29 +0000678{
679 struct bgp *bgp;
680
681 bgp = peer->bgp;
682
683 /* Peer-group */
684 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
685 {
686 if (peer->as)
687 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
688 else
689 {
690 struct peer *peer1;
691 peer1 = listnode_head (peer->group->peer);
692 if (peer1)
693 return (peer1->local_as == peer1->as
694 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
695 }
696 return BGP_PEER_INTERNAL;
697 }
698
699 /* Normal peer */
700 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
701 {
702 if (peer->local_as == 0)
703 return BGP_PEER_INTERNAL;
704
705 if (peer->local_as == peer->as)
706 {
707 if (peer->local_as == bgp->confed_id)
708 return BGP_PEER_EBGP;
709 else
710 return BGP_PEER_IBGP;
711 }
712
713 if (bgp_confederation_peers_check (bgp, peer->as))
714 return BGP_PEER_CONFED;
715
716 return BGP_PEER_EBGP;
717 }
718 else
719 {
720 return (peer->local_as == 0
721 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
722 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
723 }
724}
725
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000726/* Calculate and cache the peer "sort" */
727bgp_peer_sort_t
728peer_sort (struct peer *peer)
729{
730 peer->sort = peer_calc_sort (peer);
731 return peer->sort;
732}
733
Paul Jakmaf63f06d2011-04-08 12:44:43 +0100734static void
paul200df112005-06-01 11:17:05 +0000735peer_free (struct peer *peer)
736{
Paul Jakmaca058a32006-09-14 02:58:49 +0000737 assert (peer->status == Deleted);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700738
739 bgp_unlock(peer->bgp);
740
Paul Jakmaca058a32006-09-14 02:58:49 +0000741 /* this /ought/ to have been done already through bgp_stop earlier,
742 * but just to be sure..
743 */
744 bgp_timer_set (peer);
745 BGP_READ_OFF (peer->t_read);
746 BGP_WRITE_OFF (peer->t_write);
Paul Jakma9fde6622006-09-14 03:02:02 +0000747 BGP_EVENT_FLUSH (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +0000748
paul200df112005-06-01 11:17:05 +0000749 if (peer->desc)
Daniel Walton363c9032015-10-21 06:42:54 -0700750 {
751 XFREE (MTYPE_PEER_DESC, peer->desc);
752 peer->desc = NULL;
753 }
paul200df112005-06-01 11:17:05 +0000754
755 /* Free allocated host character. */
756 if (peer->host)
Daniel Walton363c9032015-10-21 06:42:54 -0700757 {
758 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
759 peer->host = NULL;
760 }
761
paul200df112005-06-01 11:17:05 +0000762 /* Update source configuration. */
763 if (peer->update_source)
Daniel Walton363c9032015-10-21 06:42:54 -0700764 {
765 sockunion_free (peer->update_source);
766 peer->update_source = NULL;
767 }
paul200df112005-06-01 11:17:05 +0000768
769 if (peer->update_if)
Daniel Walton363c9032015-10-21 06:42:54 -0700770 {
771 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
772 peer->update_if = NULL;
773 }
Paul Jakmaa625ca32006-03-30 14:12:38 +0000774
775 if (peer->clear_node_queue)
Daniel Walton363c9032015-10-21 06:42:54 -0700776 {
777 work_queue_free(peer->clear_node_queue);
778 peer->clear_node_queue = NULL;
779 }
Paul Jakmaa625ca32006-03-30 14:12:38 +0000780
Lou Berger056f3762013-04-10 12:30:04 -0700781 if (peer->notify.data)
782 XFREE(MTYPE_TMP, peer->notify.data);
783
Paul Jakmaca058a32006-09-14 02:58:49 +0000784 bgp_sync_delete (peer);
paul200df112005-06-01 11:17:05 +0000785 memset (peer, 0, sizeof (struct peer));
786
787 XFREE (MTYPE_BGP_PEER, peer);
788}
789
790/* increase reference count on a struct peer */
791struct peer *
Donald Sharp104576d2015-09-16 13:17:55 -0400792peer_lock_with_caller (const char *name, struct peer *peer)
paul200df112005-06-01 11:17:05 +0000793{
794 assert (peer && (peer->lock >= 0));
Donald Sharp104576d2015-09-16 13:17:55 -0400795
796#if 0
797 zlog_debug("%s peer_lock %p %d", name, peer, peer->lock);
798#endif
799
paul200df112005-06-01 11:17:05 +0000800 peer->lock++;
801
802 return peer;
803}
804
805/* decrease reference count on a struct peer
806 * struct peer is freed and NULL returned if last reference
807 */
808struct peer *
Donald Sharp104576d2015-09-16 13:17:55 -0400809peer_unlock_with_caller (const char *name, struct peer *peer)
paul200df112005-06-01 11:17:05 +0000810{
811 assert (peer && (peer->lock > 0));
Donald Sharp104576d2015-09-16 13:17:55 -0400812
813#if 0
814 zlog_debug("%s peer_unlock %p %d", name, peer, peer->lock);
815#endif
816
paul200df112005-06-01 11:17:05 +0000817 peer->lock--;
818
819 if (peer->lock == 0)
820 {
paul200df112005-06-01 11:17:05 +0000821 peer_free (peer);
822 return NULL;
823 }
824
paul200df112005-06-01 11:17:05 +0000825 return peer;
826}
827
828/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000829static struct peer *
Paul Jakma6f585442006-10-22 19:13:07 +0000830peer_new (struct bgp *bgp)
paul718e3742002-12-13 20:15:29 +0000831{
832 afi_t afi;
833 safi_t safi;
834 struct peer *peer;
835 struct servent *sp;
Paul Jakma6f585442006-10-22 19:13:07 +0000836
837 /* bgp argument is absolutely required */
838 assert (bgp);
839 if (!bgp)
840 return NULL;
841
paul718e3742002-12-13 20:15:29 +0000842 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000843 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000844
845 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000846 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000847 peer->v_start = BGP_INIT_START_TIMER;
848 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
paul718e3742002-12-13 20:15:29 +0000849 peer->status = Idle;
850 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000851 peer->weight = 0;
Paul Jakma0df7c912008-07-21 21:02:49 +0000852 peer->password = NULL;
Paul Jakma6f585442006-10-22 19:13:07 +0000853 peer->bgp = bgp;
Paul Jakmaca058a32006-09-14 02:58:49 +0000854 peer = peer_lock (peer); /* initial reference */
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700855 bgp_lock (bgp);
paul718e3742002-12-13 20:15:29 +0000856
857 /* Set default flags. */
858 for (afi = AFI_IP; afi < AFI_MAX; afi++)
859 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
860 {
861 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
862 {
863 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
864 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
865 }
866 peer->orf_plist[afi][safi] = NULL;
867 }
868 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
869
870 /* Create buffers. */
871 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
872 peer->obuf = stream_fifo_new ();
Daniel Walton5bcd7542015-05-19 17:58:10 -0700873
874 /* We use a larger buffer for peer->work in the event that:
875 * - We RX a BGP_UPDATE where the attributes alone are just
876 * under BGP_MAX_PACKET_SIZE
877 * - The user configures an outbound route-map that does many as-path
878 * prepends or adds many communities. At most they can have CMD_ARGC_MAX
879 * args in a route-map so there is a finite limit on how large they can
880 * make the attributes.
881 *
882 * Having a buffer with BGP_MAX_PACKET_SIZE_OVERFLOW allows us to avoid bounds
883 * checking for every single attribute as we construct an UPDATE.
884 */
885 peer->work = stream_new (BGP_MAX_PACKET_SIZE + BGP_MAX_PACKET_SIZE_OVERFLOW);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000886 peer->scratch = stream_new (BGP_MAX_PACKET_SIZE);
paul718e3742002-12-13 20:15:29 +0000887
888 bgp_sync_init (peer);
889
890 /* Get service port number. */
891 sp = getservbyname ("bgp", "tcp");
892 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
893
894 return peer;
895}
896
897/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000898static struct peer *
paul718e3742002-12-13 20:15:29 +0000899peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
900 as_t remote_as, afi_t afi, safi_t safi)
901{
902 int active;
903 struct peer *peer;
904 char buf[SU_ADDRSTRLEN];
905
Paul Jakma6f585442006-10-22 19:13:07 +0000906 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000907 peer->su = *su;
908 peer->local_as = local_as;
909 peer->as = remote_as;
910 peer->local_id = bgp->router_id;
911 peer->v_holdtime = bgp->default_holdtime;
912 peer->v_keepalive = bgp->default_keepalive;
913 if (peer_sort (peer) == BGP_PEER_IBGP)
914 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
915 else
916 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000917
918 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000919 listnode_add_sort (bgp->peer, peer);
920
921 active = peer_active (peer);
922
923 if (afi && safi)
924 peer->afc[afi][safi] = 1;
925
Stephen Hemminger65957882010-01-15 16:22:10 +0300926 /* Last read and reset time set */
927 peer->readtime = peer->resettime = bgp_clock ();
paul848973c2003-08-13 00:32:49 +0000928
paul718e3742002-12-13 20:15:29 +0000929 /* Make peer's address string. */
930 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000931 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000932
933 /* Set up peer's events and timers. */
934 if (! active && peer_active (peer))
935 bgp_timer_set (peer);
936
937 return peer;
938}
939
pauleb821182004-05-01 08:44:08 +0000940/* Make accept BGP peer. Called from bgp_accept (). */
941struct peer *
942peer_create_accept (struct bgp *bgp)
943{
944 struct peer *peer;
945
Paul Jakma6f585442006-10-22 19:13:07 +0000946 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000947
948 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000949 listnode_add_sort (bgp->peer, peer);
950
951 return peer;
952}
953
paul718e3742002-12-13 20:15:29 +0000954/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000955static void
paul718e3742002-12-13 20:15:29 +0000956peer_as_change (struct peer *peer, as_t as)
957{
Daniel Walton0d7435f2015-10-22 11:35:20 +0300958 struct peer *conf;
paul718e3742002-12-13 20:15:29 +0000959
960 /* Stop peer. */
961 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
962 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000963 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000964 {
965 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
966 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
967 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
968 }
paul718e3742002-12-13 20:15:29 +0000969 else
970 BGP_EVENT_ADD (peer, BGP_Stop);
971 }
paul718e3742002-12-13 20:15:29 +0000972 peer->as = as;
973
paul848973c2003-08-13 00:32:49 +0000974 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
975 && ! bgp_confederation_peers_check (peer->bgp, as)
976 && peer->bgp->as != as)
977 peer->local_as = peer->bgp->confed_id;
978 else
979 peer->local_as = peer->bgp->as;
980
paul718e3742002-12-13 20:15:29 +0000981 /* Advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +0300982 conf = NULL;
983 if (peer->group)
984 conf = peer->group->conf;
985
986 if (conf && CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
987 peer->v_routeadv = conf->routeadv;
paul718e3742002-12-13 20:15:29 +0000988 else
Daniel Walton0d7435f2015-10-22 11:35:20 +0300989 if (peer_sort (peer) == BGP_PEER_IBGP)
990 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
991 else
992 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul718e3742002-12-13 20:15:29 +0000993
paul718e3742002-12-13 20:15:29 +0000994 /* reflector-client reset */
995 if (peer_sort (peer) != BGP_PEER_IBGP)
996 {
997 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
998 PEER_FLAG_REFLECTOR_CLIENT);
999 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
1000 PEER_FLAG_REFLECTOR_CLIENT);
1001 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
1002 PEER_FLAG_REFLECTOR_CLIENT);
Lou Berger298cc2f2016-01-12 13:42:02 -05001003 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_ENCAP],
1004 PEER_FLAG_REFLECTOR_CLIENT);
paul718e3742002-12-13 20:15:29 +00001005 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
1006 PEER_FLAG_REFLECTOR_CLIENT);
1007 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
1008 PEER_FLAG_REFLECTOR_CLIENT);
Lou Berger9da04bc2016-01-12 13:41:55 -05001009 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MPLS_VPN],
1010 PEER_FLAG_REFLECTOR_CLIENT);
Lou Berger298cc2f2016-01-12 13:42:02 -05001011 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_ENCAP],
1012 PEER_FLAG_REFLECTOR_CLIENT);
paul718e3742002-12-13 20:15:29 +00001013 }
1014
1015 /* local-as reset */
1016 if (peer_sort (peer) != BGP_PEER_EBGP)
1017 {
1018 peer->change_local_as = 0;
1019 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001020 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001021 }
1022}
1023
1024/* If peer does not exist, create new one. If peer already exists,
1025 set AS number to the peer. */
1026int
1027peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
1028 afi_t afi, safi_t safi)
1029{
1030 struct peer *peer;
1031 as_t local_as;
1032
1033 peer = peer_lookup (bgp, su);
1034
1035 if (peer)
1036 {
1037 /* When this peer is a member of peer-group. */
1038 if (peer->group)
1039 {
1040 if (peer->group->conf->as)
1041 {
1042 /* Return peer group's AS number. */
1043 *as = peer->group->conf->as;
1044 return BGP_ERR_PEER_GROUP_MEMBER;
1045 }
1046 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
1047 {
1048 if (bgp->as != *as)
1049 {
1050 *as = peer->as;
1051 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1052 }
1053 }
1054 else
1055 {
1056 if (bgp->as == *as)
1057 {
1058 *as = peer->as;
1059 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1060 }
1061 }
1062 }
1063
1064 /* Existing peer's AS number change. */
1065 if (peer->as != *as)
1066 peer_as_change (peer, *as);
1067 }
1068 else
1069 {
1070
1071 /* If the peer is not part of our confederation, and its not an
1072 iBGP peer then spoof the source AS */
1073 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1074 && ! bgp_confederation_peers_check (bgp, *as)
1075 && bgp->as != *as)
1076 local_as = bgp->confed_id;
1077 else
1078 local_as = bgp->as;
1079
1080 /* If this is IPv4 unicast configuration and "no bgp default
1081 ipv4-unicast" is specified. */
1082
1083 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1084 && afi == AFI_IP && safi == SAFI_UNICAST)
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001085 peer_create (su, bgp, local_as, *as, 0, 0);
paul718e3742002-12-13 20:15:29 +00001086 else
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001087 peer_create (su, bgp, local_as, *as, afi, safi);
paul718e3742002-12-13 20:15:29 +00001088 }
1089
1090 return 0;
1091}
1092
1093/* Activate the peer or peer group for specified AFI and SAFI. */
1094int
1095peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1096{
1097 int active;
1098
1099 if (peer->afc[afi][safi])
1100 return 0;
1101
1102 /* Activate the address family configuration. */
1103 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1104 peer->afc[afi][safi] = 1;
1105 else
1106 {
1107 active = peer_active (peer);
1108
1109 peer->afc[afi][safi] = 1;
1110
1111 if (! active && peer_active (peer))
1112 bgp_timer_set (peer);
1113 else
1114 {
1115 if (peer->status == Established)
1116 {
1117 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1118 {
1119 peer->afc_adv[afi][safi] = 1;
1120 bgp_capability_send (peer, afi, safi,
1121 CAPABILITY_CODE_MP,
1122 CAPABILITY_ACTION_SET);
1123 if (peer->afc_recv[afi][safi])
1124 {
1125 peer->afc_nego[afi][safi] = 1;
1126 bgp_announce_route (peer, afi, safi);
1127 }
1128 }
1129 else
hassoe0701b72004-05-20 09:19:34 +00001130 {
1131 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1132 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1133 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1134 }
paul718e3742002-12-13 20:15:29 +00001135 }
1136 }
1137 }
1138 return 0;
1139}
1140
1141int
1142peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1143{
1144 struct peer_group *group;
1145 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001146 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001147
1148 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1149 {
1150 group = peer->group;
1151
paul1eb8ef22005-04-07 07:30:20 +00001152 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001153 {
1154 if (peer1->af_group[afi][safi])
1155 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1156 }
1157 }
1158 else
1159 {
1160 if (peer->af_group[afi][safi])
1161 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1162 }
1163
1164 if (! peer->afc[afi][safi])
1165 return 0;
1166
1167 /* De-activate the address family configuration. */
1168 peer->afc[afi][safi] = 0;
1169 peer_af_flag_reset (peer, afi, safi);
1170
1171 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1172 {
1173 if (peer->status == Established)
1174 {
1175 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1176 {
1177 peer->afc_adv[afi][safi] = 0;
1178 peer->afc_nego[afi][safi] = 0;
1179
1180 if (peer_active_nego (peer))
1181 {
1182 bgp_capability_send (peer, afi, safi,
1183 CAPABILITY_CODE_MP,
1184 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001185 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001186 peer->pcount[afi][safi] = 0;
1187 }
1188 else
hassoe0701b72004-05-20 09:19:34 +00001189 {
1190 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1191 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1192 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1193 }
paul718e3742002-12-13 20:15:29 +00001194 }
1195 else
hassoe0701b72004-05-20 09:19:34 +00001196 {
1197 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1198 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1199 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1200 }
paul718e3742002-12-13 20:15:29 +00001201 }
1202 }
1203 return 0;
1204}
1205
David Lamparterdfb9bd72016-05-24 18:58:07 +02001206int
1207peer_afc_set (struct peer *peer, afi_t afi, safi_t safi, int enable)
1208{
1209 if (enable)
1210 return peer_activate (peer, afi, safi);
1211 else
1212 return peer_deactivate (peer, afi, safi);
1213}
1214
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001215static void
hasso93406d82005-02-02 14:40:33 +00001216peer_nsf_stop (struct peer *peer)
1217{
1218 afi_t afi;
1219 safi_t safi;
1220
1221 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1222 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1223
1224 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +04001225 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +00001226 peer->nsf[afi][safi] = 0;
1227
1228 if (peer->t_gr_restart)
1229 {
1230 BGP_TIMER_OFF (peer->t_gr_restart);
1231 if (BGP_DEBUG (events, EVENTS))
1232 zlog_debug ("%s graceful restart timer stopped", peer->host);
1233 }
1234 if (peer->t_gr_stale)
1235 {
1236 BGP_TIMER_OFF (peer->t_gr_stale);
1237 if (BGP_DEBUG (events, EVENTS))
1238 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1239 }
1240 bgp_clear_route_all (peer);
1241}
1242
Paul Jakmaca058a32006-09-14 02:58:49 +00001243/* Delete peer from confguration.
1244 *
1245 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1246 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1247 *
1248 * This function /should/ take care to be idempotent, to guard against
1249 * it being called multiple times through stray events that come in
1250 * that happen to result in this function being called again. That
1251 * said, getting here for a "Deleted" peer is a bug in the neighbour
1252 * FSM.
1253 */
paul718e3742002-12-13 20:15:29 +00001254int
1255peer_delete (struct peer *peer)
1256{
1257 int i;
1258 afi_t afi;
1259 safi_t safi;
1260 struct bgp *bgp;
1261 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001262 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001263
Paul Jakmaca058a32006-09-14 02:58:49 +00001264 assert (peer->status != Deleted);
1265
paul718e3742002-12-13 20:15:29 +00001266 bgp = peer->bgp;
1267
hasso93406d82005-02-02 14:40:33 +00001268 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1269 peer_nsf_stop (peer);
1270
Chris Caputo228da422009-07-18 05:44:03 +00001271 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001272 relationship. */
1273 if (peer->group)
1274 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001275 if ((pn = listnode_lookup (peer->group->peer, peer)))
1276 {
1277 peer = peer_unlock (peer); /* group->peer list reference */
1278 list_delete_node (peer->group->peer, pn);
1279 }
paul718e3742002-12-13 20:15:29 +00001280 peer->group = NULL;
1281 }
paul200df112005-06-01 11:17:05 +00001282
paul718e3742002-12-13 20:15:29 +00001283 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001284 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1285 * executed after peer structure is deleted.
1286 */
hassoe0701b72004-05-20 09:19:34 +00001287 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001288 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001289 bgp_fsm_change_status (peer, Deleted);
Paul Jakma19e6c192016-09-06 17:23:48 +01001290
1291 /* Remove from NHT */
1292 bgp_unlink_nexthop_by_peer (peer);
1293
Paul Jakma0df7c912008-07-21 21:02:49 +00001294 /* Password configuration */
1295 if (peer->password)
1296 {
1297 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1298 peer->password = NULL;
1299
1300 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1301 bgp_md5_set (peer);
1302 }
1303
Paul Jakmaca058a32006-09-14 02:58:49 +00001304 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001305
paul718e3742002-12-13 20:15:29 +00001306 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001307 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1308 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001309 {
Chris Caputo228da422009-07-18 05:44:03 +00001310 peer_unlock (peer); /* bgp peer list reference */
1311 list_delete_node (bgp->peer, pn);
1312 }
paul200df112005-06-01 11:17:05 +00001313
Chris Caputo228da422009-07-18 05:44:03 +00001314 if (peer_rsclient_active (peer)
1315 && (pn = listnode_lookup (bgp->rsclient, peer)))
1316 {
1317 peer_unlock (peer); /* rsclient list reference */
1318 list_delete_node (bgp->rsclient, pn);
1319
1320 /* Clear our own rsclient ribs. */
1321 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1322 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1323 if (CHECK_FLAG(peer->af_flags[afi][safi],
1324 PEER_FLAG_RSERVER_CLIENT))
1325 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001326 }
1327
1328 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1329 member of a peer_group. */
1330 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1331 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1332 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001333 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001334
paul200df112005-06-01 11:17:05 +00001335 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001336 if (peer->ibuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001337 {
1338 stream_free (peer->ibuf);
1339 peer->ibuf = NULL;
1340 }
1341
paul718e3742002-12-13 20:15:29 +00001342 if (peer->obuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001343 {
1344 stream_fifo_free (peer->obuf);
1345 peer->obuf = NULL;
1346 }
1347
paul718e3742002-12-13 20:15:29 +00001348 if (peer->work)
Daniel Walton363c9032015-10-21 06:42:54 -07001349 {
1350 stream_free (peer->work);
1351 peer->work = NULL;
1352 }
1353
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00001354 if (peer->scratch)
Daniel Walton363c9032015-10-21 06:42:54 -07001355 {
1356 stream_free(peer->scratch);
1357 peer->scratch = NULL;
1358 }
Paul Jakma18937402006-07-27 19:05:12 +00001359
paul718e3742002-12-13 20:15:29 +00001360 /* Local and remote addresses. */
1361 if (peer->su_local)
Daniel Walton363c9032015-10-21 06:42:54 -07001362 {
1363 sockunion_free (peer->su_local);
1364 peer->su_local = NULL;
1365 }
1366
paul718e3742002-12-13 20:15:29 +00001367 if (peer->su_remote)
Daniel Walton363c9032015-10-21 06:42:54 -07001368 {
1369 sockunion_free (peer->su_remote);
1370 peer->su_remote = NULL;
1371 }
paul200df112005-06-01 11:17:05 +00001372
paul718e3742002-12-13 20:15:29 +00001373 /* Free filter related memory. */
1374 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1375 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1376 {
1377 filter = &peer->filter[afi][safi];
1378
1379 for (i = FILTER_IN; i < FILTER_MAX; i++)
1380 {
1381 if (filter->dlist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001382 {
1383 free(filter->dlist[i].name);
1384 filter->dlist[i].name = NULL;
1385 }
1386
paul718e3742002-12-13 20:15:29 +00001387 if (filter->plist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001388 {
1389 free(filter->plist[i].name);
1390 filter->plist[i].name = NULL;
1391 }
1392
paul718e3742002-12-13 20:15:29 +00001393 if (filter->aslist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001394 {
1395 free(filter->aslist[i].name);
1396 filter->aslist[i].name = NULL;
1397 }
paul200df112005-06-01 11:17:05 +00001398 }
Daniel Walton363c9032015-10-21 06:42:54 -07001399
paul200df112005-06-01 11:17:05 +00001400 for (i = RMAP_IN; i < RMAP_MAX; i++)
1401 {
paul718e3742002-12-13 20:15:29 +00001402 if (filter->map[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001403 {
1404 free (filter->map[i].name);
1405 filter->map[i].name = NULL;
1406 }
paul718e3742002-12-13 20:15:29 +00001407 }
1408
1409 if (filter->usmap.name)
Daniel Walton363c9032015-10-21 06:42:54 -07001410 {
1411 free (filter->usmap.name);
1412 filter->usmap.name = NULL;
1413 }
paul718e3742002-12-13 20:15:29 +00001414
1415 if (peer->default_rmap[afi][safi].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001416 {
1417 free (peer->default_rmap[afi][safi].name);
1418 peer->default_rmap[afi][safi].name = NULL;
1419 }
paul718e3742002-12-13 20:15:29 +00001420 }
paul200df112005-06-01 11:17:05 +00001421
Lou Berger82dd7072016-01-12 13:41:57 -05001422 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETING))
1423 bgp_peer_clear_node_queue_drain_immediate(peer);
1424
paul200df112005-06-01 11:17:05 +00001425 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001426
1427 return 0;
1428}
David Lamparter6b0655a2014-06-04 06:53:35 +02001429
paul94f2b392005-06-28 12:44:16 +00001430static int
paul718e3742002-12-13 20:15:29 +00001431peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1432{
1433 return strcmp (g1->name, g2->name);
1434}
1435
1436/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001437static int
paul718e3742002-12-13 20:15:29 +00001438peer_group_active (struct peer *peer)
1439{
1440 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1441 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1442 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05001443 || peer->af_group[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00001444 || peer->af_group[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05001445 || peer->af_group[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05001446 || peer->af_group[AFI_IP6][SAFI_MPLS_VPN]
1447 || peer->af_group[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00001448 return 1;
1449 return 0;
1450}
1451
1452/* Peer group cofiguration. */
1453static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001454peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001455{
1456 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1457 sizeof (struct peer_group));
1458}
1459
paul94f2b392005-06-28 12:44:16 +00001460static void
paul718e3742002-12-13 20:15:29 +00001461peer_group_free (struct peer_group *group)
1462{
1463 XFREE (MTYPE_PEER_GROUP, group);
1464}
1465
1466struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001467peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001468{
1469 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001470 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001471
paul1eb8ef22005-04-07 07:30:20 +00001472 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001473 {
1474 if (strcmp (group->name, name) == 0)
1475 return group;
1476 }
1477 return NULL;
1478}
1479
1480struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001481peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001482{
1483 struct peer_group *group;
1484
1485 group = peer_group_lookup (bgp, name);
1486 if (group)
1487 return group;
1488
1489 group = peer_group_new ();
1490 group->bgp = bgp;
1491 group->name = strdup (name);
1492 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001493 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001494 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1495 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001496 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001497 group->conf->group = group;
1498 group->conf->as = 0;
Timo Teräse3443a22016-10-19 16:02:34 +03001499 group->conf->ttl = 0;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001500 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001501 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1502 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1503 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1504 group->conf->keepalive = 0;
1505 group->conf->holdtime = 0;
1506 group->conf->connect = 0;
1507 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1508 listnode_add_sort (bgp->group, group);
1509
1510 return 0;
1511}
1512
paul94f2b392005-06-28 12:44:16 +00001513static void
paul718e3742002-12-13 20:15:29 +00001514peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1515 afi_t afi, safi_t safi)
1516{
1517 int in = FILTER_IN;
1518 int out = FILTER_OUT;
1519 struct peer *conf;
1520 struct bgp_filter *pfilter;
1521 struct bgp_filter *gfilter;
1522
1523 conf = group->conf;
1524 pfilter = &peer->filter[afi][safi];
1525 gfilter = &conf->filter[afi][safi];
1526
1527 /* remote-as */
1528 if (conf->as)
1529 peer->as = conf->as;
1530
1531 /* remote-as */
1532 if (conf->change_local_as)
1533 peer->change_local_as = conf->change_local_as;
1534
1535 /* TTL */
1536 peer->ttl = conf->ttl;
1537
Nick Hilliardfa411a22011-03-23 15:33:17 +00001538 /* GTSM hops */
1539 peer->gtsm_hops = conf->gtsm_hops;
1540
paul718e3742002-12-13 20:15:29 +00001541 /* Weight */
1542 peer->weight = conf->weight;
1543
1544 /* peer flags apply */
1545 peer->flags = conf->flags;
1546 /* peer af_flags apply */
1547 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1548 /* peer config apply */
1549 peer->config = conf->config;
1550
1551 /* peer timers apply */
1552 peer->holdtime = conf->holdtime;
1553 peer->keepalive = conf->keepalive;
1554 peer->connect = conf->connect;
1555 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1556 peer->v_connect = conf->connect;
1557 else
1558 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1559
1560 /* advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +03001561 if (CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
1562 peer->v_routeadv = conf->routeadv;
paul718e3742002-12-13 20:15:29 +00001563 else
Daniel Walton0d7435f2015-10-22 11:35:20 +03001564 if (peer_sort (peer) == BGP_PEER_IBGP)
1565 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1566 else
1567 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul718e3742002-12-13 20:15:29 +00001568
Paul Jakma0df7c912008-07-21 21:02:49 +00001569 /* password apply */
Roman Hoog Antink0e4303d2013-01-18 13:52:03 +01001570 if (conf->password && !peer->password)
Paul Jakma0df7c912008-07-21 21:02:49 +00001571 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
Paul Jakma0df7c912008-07-21 21:02:49 +00001572
1573 bgp_md5_set (peer);
1574
paul718e3742002-12-13 20:15:29 +00001575 /* maximum-prefix */
1576 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001577 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001578 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001579
1580 /* allowas-in */
1581 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1582
paulfee0f4c2004-09-13 05:12:46 +00001583 /* route-server-client */
1584 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1585 {
1586 /* Make peer's RIB point to group's RIB. */
1587 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1588
1589 /* Import policy. */
1590 if (pfilter->map[RMAP_IMPORT].name)
1591 free (pfilter->map[RMAP_IMPORT].name);
1592 if (gfilter->map[RMAP_IMPORT].name)
1593 {
1594 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1595 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1596 }
1597 else
1598 {
1599 pfilter->map[RMAP_IMPORT].name = NULL;
1600 pfilter->map[RMAP_IMPORT].map = NULL;
1601 }
1602
1603 /* Export policy. */
1604 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1605 {
1606 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1607 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1608 }
1609 }
1610
paul718e3742002-12-13 20:15:29 +00001611 /* default-originate route-map */
1612 if (conf->default_rmap[afi][safi].name)
1613 {
1614 if (peer->default_rmap[afi][safi].name)
1615 free (peer->default_rmap[afi][safi].name);
1616 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1617 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1618 }
1619
1620 /* update-source apply */
1621 if (conf->update_source)
1622 {
1623 if (peer->update_source)
1624 sockunion_free (peer->update_source);
1625 if (peer->update_if)
1626 {
1627 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1628 peer->update_if = NULL;
1629 }
1630 peer->update_source = sockunion_dup (conf->update_source);
1631 }
1632 else if (conf->update_if)
1633 {
1634 if (peer->update_if)
1635 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1636 if (peer->update_source)
1637 {
1638 sockunion_free (peer->update_source);
1639 peer->update_source = NULL;
1640 }
1641 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1642 }
1643
1644 /* inbound filter apply */
1645 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1646 {
1647 if (pfilter->dlist[in].name)
1648 free (pfilter->dlist[in].name);
1649 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1650 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1651 }
1652 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1653 {
1654 if (pfilter->plist[in].name)
1655 free (pfilter->plist[in].name);
1656 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1657 pfilter->plist[in].plist = gfilter->plist[in].plist;
1658 }
1659 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1660 {
1661 if (pfilter->aslist[in].name)
1662 free (pfilter->aslist[in].name);
1663 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1664 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1665 }
paulfee0f4c2004-09-13 05:12:46 +00001666 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001667 {
paulfee0f4c2004-09-13 05:12:46 +00001668 if (pfilter->map[RMAP_IN].name)
1669 free (pfilter->map[RMAP_IN].name);
1670 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1671 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001672 }
1673
1674 /* outbound filter apply */
1675 if (gfilter->dlist[out].name)
1676 {
1677 if (pfilter->dlist[out].name)
1678 free (pfilter->dlist[out].name);
1679 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1680 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1681 }
1682 else
1683 {
1684 if (pfilter->dlist[out].name)
1685 free (pfilter->dlist[out].name);
1686 pfilter->dlist[out].name = NULL;
1687 pfilter->dlist[out].alist = NULL;
1688 }
1689 if (gfilter->plist[out].name)
1690 {
1691 if (pfilter->plist[out].name)
1692 free (pfilter->plist[out].name);
1693 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1694 pfilter->plist[out].plist = gfilter->plist[out].plist;
1695 }
1696 else
1697 {
1698 if (pfilter->plist[out].name)
1699 free (pfilter->plist[out].name);
1700 pfilter->plist[out].name = NULL;
1701 pfilter->plist[out].plist = NULL;
1702 }
1703 if (gfilter->aslist[out].name)
1704 {
1705 if (pfilter->aslist[out].name)
1706 free (pfilter->aslist[out].name);
1707 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1708 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1709 }
1710 else
1711 {
1712 if (pfilter->aslist[out].name)
1713 free (pfilter->aslist[out].name);
1714 pfilter->aslist[out].name = NULL;
1715 pfilter->aslist[out].aslist = NULL;
1716 }
paulfee0f4c2004-09-13 05:12:46 +00001717 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001718 {
paulfee0f4c2004-09-13 05:12:46 +00001719 if (pfilter->map[RMAP_OUT].name)
1720 free (pfilter->map[RMAP_OUT].name);
1721 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1722 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001723 }
1724 else
1725 {
paulfee0f4c2004-09-13 05:12:46 +00001726 if (pfilter->map[RMAP_OUT].name)
1727 free (pfilter->map[RMAP_OUT].name);
1728 pfilter->map[RMAP_OUT].name = NULL;
1729 pfilter->map[RMAP_OUT].map = NULL;
1730 }
1731
1732 /* RS-client's import/export route-maps. */
1733 if (gfilter->map[RMAP_IMPORT].name)
1734 {
1735 if (pfilter->map[RMAP_IMPORT].name)
1736 free (pfilter->map[RMAP_IMPORT].name);
1737 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1738 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1739 }
1740 else
1741 {
1742 if (pfilter->map[RMAP_IMPORT].name)
1743 free (pfilter->map[RMAP_IMPORT].name);
1744 pfilter->map[RMAP_IMPORT].name = NULL;
1745 pfilter->map[RMAP_IMPORT].map = NULL;
1746 }
1747 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1748 {
1749 if (pfilter->map[RMAP_EXPORT].name)
1750 free (pfilter->map[RMAP_EXPORT].name);
1751 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1752 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001753 }
1754
1755 if (gfilter->usmap.name)
1756 {
1757 if (pfilter->usmap.name)
1758 free (pfilter->usmap.name);
1759 pfilter->usmap.name = strdup (gfilter->usmap.name);
1760 pfilter->usmap.map = gfilter->usmap.map;
1761 }
1762 else
1763 {
1764 if (pfilter->usmap.name)
1765 free (pfilter->usmap.name);
1766 pfilter->usmap.name = NULL;
1767 pfilter->usmap.map = NULL;
1768 }
1769}
1770
1771/* Peer group's remote AS configuration. */
1772int
paulfd79ac92004-10-13 05:06:08 +00001773peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001774{
1775 struct peer_group *group;
1776 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001777 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001778
1779 group = peer_group_lookup (bgp, group_name);
1780 if (! group)
1781 return -1;
1782
1783 if (group->conf->as == *as)
1784 return 0;
1785
1786 /* When we setup peer-group AS number all peer group member's AS
1787 number must be updated to same number. */
1788 peer_as_change (group->conf, *as);
1789
paul1eb8ef22005-04-07 07:30:20 +00001790 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001791 {
1792 if (peer->as != *as)
1793 peer_as_change (peer, *as);
1794 }
1795
1796 return 0;
1797}
1798
1799int
Timo Teräse3443a22016-10-19 16:02:34 +03001800peer_ttl (struct peer *peer)
1801{
1802 if (peer->ttl)
1803 return peer->ttl;
1804 if (peer->gtsm_hops || peer->sort == BGP_PEER_IBGP)
1805 return 255;
1806 return 1;
1807}
1808
1809int
paul718e3742002-12-13 20:15:29 +00001810peer_group_delete (struct peer_group *group)
1811{
1812 struct bgp *bgp;
1813 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001814 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001815
1816 bgp = group->bgp;
1817
paul1eb8ef22005-04-07 07:30:20 +00001818 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001819 {
paul718e3742002-12-13 20:15:29 +00001820 peer_delete (peer);
1821 }
1822 list_delete (group->peer);
1823
1824 free (group->name);
1825 group->name = NULL;
1826
1827 group->conf->group = NULL;
1828 peer_delete (group->conf);
1829
1830 /* Delete from all peer_group list. */
1831 listnode_delete (bgp->group, group);
1832
1833 peer_group_free (group);
1834
1835 return 0;
1836}
1837
1838int
1839peer_group_remote_as_delete (struct peer_group *group)
1840{
1841 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001842 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001843
1844 if (! group->conf->as)
1845 return 0;
1846
paul1eb8ef22005-04-07 07:30:20 +00001847 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001848 {
paul718e3742002-12-13 20:15:29 +00001849 peer_delete (peer);
1850 }
1851 list_delete_all_node (group->peer);
1852
1853 group->conf->as = 0;
1854
1855 return 0;
1856}
1857
1858/* Bind specified peer to peer group. */
1859int
1860peer_group_bind (struct bgp *bgp, union sockunion *su,
1861 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1862{
1863 struct peer *peer;
1864 int first_member = 0;
1865
1866 /* Check peer group's address family. */
1867 if (! group->conf->afc[afi][safi])
1868 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1869
1870 /* Lookup the peer. */
1871 peer = peer_lookup (bgp, su);
1872
1873 /* Create a new peer. */
1874 if (! peer)
1875 {
1876 if (! group->conf->as)
1877 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1878
1879 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1880 peer->group = group;
1881 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001882
Paul Jakmaca058a32006-09-14 02:58:49 +00001883 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001884 listnode_add (group->peer, peer);
1885 peer_group2peer_config_copy (group, peer, afi, safi);
1886
1887 return 0;
1888 }
1889
1890 /* When the peer already belongs to peer group, check the consistency. */
1891 if (peer->af_group[afi][safi])
1892 {
1893 if (strcmp (peer->group->name, group->name) != 0)
1894 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1895
1896 return 0;
1897 }
1898
1899 /* Check current peer group configuration. */
1900 if (peer_group_active (peer)
1901 && strcmp (peer->group->name, group->name) != 0)
1902 return BGP_ERR_PEER_GROUP_MISMATCH;
1903
1904 if (! group->conf->as)
1905 {
1906 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1907 && peer_sort (group->conf) != peer_sort (peer))
1908 {
1909 if (as)
1910 *as = peer->as;
1911 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1912 }
1913
1914 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1915 first_member = 1;
1916 }
1917
1918 peer->af_group[afi][safi] = 1;
1919 peer->afc[afi][safi] = 1;
1920 if (! peer->group)
1921 {
1922 peer->group = group;
paul200df112005-06-01 11:17:05 +00001923
Paul Jakmaca058a32006-09-14 02:58:49 +00001924 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001925 listnode_add (group->peer, peer);
1926 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001927 else
1928 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001929
1930 if (first_member)
1931 {
1932 /* Advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +03001933 if (! CHECK_FLAG (group->conf->config, PEER_CONFIG_ROUTEADV))
1934 {
1935 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1936 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1937 else
1938 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1939 }
paul718e3742002-12-13 20:15:29 +00001940
paul718e3742002-12-13 20:15:29 +00001941 /* local-as reset */
1942 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1943 {
1944 group->conf->change_local_as = 0;
1945 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001946 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001947 }
1948 }
paulfee0f4c2004-09-13 05:12:46 +00001949
1950 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1951 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001952 struct listnode *pn;
1953
paulfee0f4c2004-09-13 05:12:46 +00001954 /* If it's not configured as RSERVER_CLIENT in any other address
1955 family, without being member of a peer_group, remove it from
1956 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001957 if (! peer_rsclient_active (peer)
1958 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001959 {
1960 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001961 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001962
1963 /* Clear our own rsclient rib for this afi/safi. */
1964 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001965 }
paulfee0f4c2004-09-13 05:12:46 +00001966
Paul Jakmab608d5b2008-07-02 02:12:07 +00001967 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001968
1969 /* Import policy. */
1970 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1971 {
1972 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1973 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1974 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1975 }
1976
1977 /* Export policy. */
1978 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1979 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1980 {
1981 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1982 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1983 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1984 }
1985 }
1986
paul718e3742002-12-13 20:15:29 +00001987 peer_group2peer_config_copy (group, peer, afi, safi);
1988
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001989 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001990 {
1991 peer->last_reset = PEER_DOWN_RMAP_BIND;
1992 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1993 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1994 }
paul718e3742002-12-13 20:15:29 +00001995 else
1996 BGP_EVENT_ADD (peer, BGP_Stop);
1997
1998 return 0;
1999}
2000
2001int
2002peer_group_unbind (struct bgp *bgp, struct peer *peer,
2003 struct peer_group *group, afi_t afi, safi_t safi)
2004{
2005 if (! peer->af_group[afi][safi])
2006 return 0;
2007
2008 if (group != peer->group)
2009 return BGP_ERR_PEER_GROUP_MISMATCH;
2010
2011 peer->af_group[afi][safi] = 0;
2012 peer->afc[afi][safi] = 0;
2013 peer_af_flag_reset (peer, afi, safi);
2014
paulfee0f4c2004-09-13 05:12:46 +00002015 if (peer->rib[afi][safi])
2016 peer->rib[afi][safi] = NULL;
2017
paul718e3742002-12-13 20:15:29 +00002018 if (! peer_group_active (peer))
2019 {
Paul Jakmaca058a32006-09-14 02:58:49 +00002020 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00002021 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00002022 listnode_delete (group->peer, peer);
2023 peer->group = NULL;
2024 if (group->conf->as)
2025 {
2026 peer_delete (peer);
2027 return 0;
2028 }
2029 peer_global_config_reset (peer);
2030 }
2031
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002032 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002033 {
2034 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
2035 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2036 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2037 }
paul718e3742002-12-13 20:15:29 +00002038 else
2039 BGP_EVENT_ADD (peer, BGP_Stop);
2040
2041 return 0;
2042}
David Lamparter6b0655a2014-06-04 06:53:35 +02002043
Vipin Kumardd49eb12014-09-30 14:36:38 -07002044
2045static int
2046bgp_startup_timer_expire (struct thread *thread)
2047{
2048 struct bgp *bgp;
2049
2050 bgp = THREAD_ARG (thread);
2051 bgp->t_startup = NULL;
2052
2053 return 0;
2054}
2055
paul718e3742002-12-13 20:15:29 +00002056/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00002057static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002058bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002059{
2060 struct bgp *bgp;
2061 afi_t afi;
2062 safi_t safi;
2063
paul200df112005-06-01 11:17:05 +00002064 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
2065 return NULL;
2066
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002067 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00002068 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00002069 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00002070
2071 bgp->peer = list_new ();
2072 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
2073
2074 bgp->group = list_new ();
2075 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
2076
paulfee0f4c2004-09-13 05:12:46 +00002077 bgp->rsclient = list_new ();
2078 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
2079
paul718e3742002-12-13 20:15:29 +00002080 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2081 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2082 {
Paul Jakma64e580a2006-02-21 01:09:01 +00002083 bgp->route[afi][safi] = bgp_table_init (afi, safi);
2084 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
2085 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07002086 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
2087 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00002088 }
2089
2090 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
2091 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
2092 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00002093 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
2094 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07002095 bgp_flag_set (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES);
paul718e3742002-12-13 20:15:29 +00002096
2097 bgp->as = *as;
2098
2099 if (name)
2100 bgp->name = strdup (name);
2101
Donald Sharp774914f2015-10-14 08:50:39 -04002102 THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire,
Vipin Kumardd49eb12014-09-30 14:36:38 -07002103 bgp, bgp->restart_time);
2104
paul718e3742002-12-13 20:15:29 +00002105 return bgp;
2106}
2107
2108/* Return first entry of BGP. */
2109struct bgp *
paul94f2b392005-06-28 12:44:16 +00002110bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00002111{
Lou Berger056f3762013-04-10 12:30:04 -07002112 if (bm && bm->bgp && bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00002113 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00002114 return NULL;
2115}
2116
2117/* Lookup BGP entry. */
2118struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002119bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00002120{
2121 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002122 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002123
paul1eb8ef22005-04-07 07:30:20 +00002124 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002125 if (bgp->as == as
2126 && ((bgp->name == NULL && name == NULL)
2127 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
2128 return bgp;
2129 return NULL;
2130}
2131
2132/* Lookup BGP structure by view name. */
2133struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002134bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002135{
2136 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002137 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002138
paul1eb8ef22005-04-07 07:30:20 +00002139 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002140 if ((bgp->name == NULL && name == NULL)
2141 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2142 return bgp;
2143 return NULL;
2144}
2145
2146/* Called from VTY commands. */
2147int
paulfd79ac92004-10-13 05:06:08 +00002148bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002149{
2150 struct bgp *bgp;
2151
2152 /* Multiple instance check. */
2153 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2154 {
2155 if (name)
2156 bgp = bgp_lookup_by_name (name);
2157 else
2158 bgp = bgp_get_default ();
2159
2160 /* Already exists. */
2161 if (bgp)
2162 {
2163 if (bgp->as != *as)
2164 {
2165 *as = bgp->as;
2166 return BGP_ERR_INSTANCE_MISMATCH;
2167 }
2168 *bgp_val = bgp;
2169 return 0;
2170 }
2171 }
2172 else
2173 {
2174 /* BGP instance name can not be specified for single instance. */
2175 if (name)
2176 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2177
2178 /* Get default BGP structure if exists. */
2179 bgp = bgp_get_default ();
2180
2181 if (bgp)
2182 {
2183 if (bgp->as != *as)
2184 {
2185 *as = bgp->as;
2186 return BGP_ERR_AS_MISMATCH;
2187 }
2188 *bgp_val = bgp;
2189 return 0;
2190 }
2191 }
2192
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002193 bgp = bgp_create (as, name);
2194 bgp_router_id_set(bgp, &router_id_zebra);
2195 *bgp_val = bgp;
2196
Paul Jakmaad12dde2012-06-13 22:50:07 +01002197 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002198 if (list_isempty(bm->bgp)
2199 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002200 {
2201 if (bgp_socket (bm->port, bm->address) < 0)
2202 return BGP_ERR_INVALID_VALUE;
2203 }
2204
paul718e3742002-12-13 20:15:29 +00002205 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002206
2207 return 0;
2208}
2209
2210/* Delete BGP instance. */
2211int
2212bgp_delete (struct bgp *bgp)
2213{
2214 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002215 struct peer_group *group;
Denil Vira57cd5e72015-08-10 12:46:14 -07002216 struct listnode *node, *pnode;
2217 struct listnode *next, *pnext;
paul718e3742002-12-13 20:15:29 +00002218 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002219 int i;
2220
Lou Berger82dd7072016-01-12 13:41:57 -05002221 SET_FLAG(bgp->flags, BGP_FLAG_DELETING);
2222
David Lampartercffe7802014-12-07 03:27:13 +01002223 THREAD_OFF (bgp->t_startup);
2224
Daniel Walton9e518dd2015-05-19 17:47:26 -07002225 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2226 {
2227 if (peer->status == Established ||
2228 peer->status == OpenSent ||
2229 peer->status == OpenConfirm)
2230 {
2231 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2232 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
2233 }
2234 }
2235
paul718e3742002-12-13 20:15:29 +00002236 /* Delete static route. */
2237 bgp_static_delete (bgp);
2238
2239 /* Unset redistribution. */
2240 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2241 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2242 if (i != ZEBRA_ROUTE_BGP)
2243 bgp_redistribute_unset (bgp, afi, i);
2244
paul1eb8ef22005-04-07 07:30:20 +00002245 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002246 {
2247 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2248 {
2249 /* Send notify to remote peer. */
2250 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2251 }
2252
2253 peer_delete (peer);
2254 }
paul718e3742002-12-13 20:15:29 +00002255
Chris Caputo228da422009-07-18 05:44:03 +00002256 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002257 {
Denil Vira57cd5e72015-08-10 12:46:14 -07002258 for (ALL_LIST_ELEMENTS (group->peer, pnode, pnext, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002259 {
2260 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2261 {
2262 /* Send notify to remote peer. */
2263 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2264 }
2265 }
2266 peer_group_delete (group);
2267 }
Chris Caputo228da422009-07-18 05:44:03 +00002268
2269 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002270
2271 if (bgp->peer_self) {
2272 peer_delete(bgp->peer_self);
2273 bgp->peer_self = NULL;
2274 }
Lou Berger82dd7072016-01-12 13:41:57 -05002275
2276 /*
2277 * Free pending deleted routes. Unfortunately, it also has to process
2278 * all the pending activity for other instances of struct bgp.
2279 *
2280 * This call was added to achieve clean memory allocation at exit,
2281 * for the sake of valgrind.
2282 */
2283 bgp_process_queues_drain_immediate();
2284
Paul Jakmafd35b942009-07-16 19:27:32 +01002285 /* Remove visibility via the master list - there may however still be
2286 * routes to be processed still referencing the struct bgp.
2287 */
2288 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002289 if (list_isempty(bm->bgp))
2290 bgp_close ();
2291
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002292 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002293
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002294 return 0;
2295}
2296
2297static void bgp_free (struct bgp *);
2298
2299void
2300bgp_lock (struct bgp *bgp)
2301{
2302 ++bgp->lock;
2303}
2304
2305void
2306bgp_unlock(struct bgp *bgp)
2307{
Chris Caputo228da422009-07-18 05:44:03 +00002308 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002309 if (--bgp->lock == 0)
2310 bgp_free (bgp);
2311}
2312
2313static void
2314bgp_free (struct bgp *bgp)
2315{
2316 afi_t afi;
2317 safi_t safi;
2318
2319 list_delete (bgp->group);
2320 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002321 list_delete (bgp->rsclient);
2322
paul718e3742002-12-13 20:15:29 +00002323 if (bgp->name)
2324 free (bgp->name);
2325
2326 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2327 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2328 {
2329 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002330 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002331 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002332 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002333 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002334 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002335 }
2336 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002337}
David Lamparter6b0655a2014-06-04 06:53:35 +02002338
paul718e3742002-12-13 20:15:29 +00002339struct peer *
2340peer_lookup (struct bgp *bgp, union sockunion *su)
2341{
2342 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002343 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002344
Steve Hillfc4dc592009-07-28 17:54:35 +01002345 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002346 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002347 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2348 if (sockunion_same (&peer->su, su)
2349 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2350 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002351 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002352 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002353 {
2354 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002355
Paul Jakma2158ad22009-07-28 18:10:55 +01002356 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2357 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2358 if (sockunion_same (&peer->su, su)
2359 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2360 return peer;
paul718e3742002-12-13 20:15:29 +00002361 }
2362 return NULL;
2363}
2364
2365struct peer *
2366peer_lookup_with_open (union sockunion *su, as_t remote_as,
2367 struct in_addr *remote_id, int *as)
2368{
2369 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002370 struct listnode *node;
2371 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002372 struct bgp *bgp;
2373
Steve Hillfc4dc592009-07-28 17:54:35 +01002374 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002375 return NULL;
2376
Paul Jakma9d878772009-08-05 16:25:16 +01002377 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002378 {
Paul Jakma9d878772009-08-05 16:25:16 +01002379 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2380 {
2381 if (sockunion_same (&peer->su, su)
2382 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2383 {
2384 if (peer->as == remote_as
2385 && peer->remote_id.s_addr == remote_id->s_addr)
2386 return peer;
2387 if (peer->as == remote_as)
2388 *as = 1;
2389 }
2390 }
2391
2392 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2393 {
2394 if (sockunion_same (&peer->su, su)
2395 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2396 {
2397 if (peer->as == remote_as
2398 && peer->remote_id.s_addr == 0)
2399 return peer;
2400 if (peer->as == remote_as)
2401 *as = 1;
2402 }
2403 }
paul718e3742002-12-13 20:15:29 +00002404 }
2405 return NULL;
2406}
David Lamparter6b0655a2014-06-04 06:53:35 +02002407
paul718e3742002-12-13 20:15:29 +00002408/* If peer is configured at least one address family return 1. */
2409int
2410peer_active (struct peer *peer)
2411{
2412 if (peer->afc[AFI_IP][SAFI_UNICAST]
2413 || peer->afc[AFI_IP][SAFI_MULTICAST]
2414 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05002415 || peer->afc[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00002416 || peer->afc[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05002417 || peer->afc[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05002418 || peer->afc[AFI_IP6][SAFI_MPLS_VPN]
2419 || peer->afc[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00002420 return 1;
2421 return 0;
2422}
2423
2424/* If peer is negotiated at least one address family return 1. */
2425int
2426peer_active_nego (struct peer *peer)
2427{
2428 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2429 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2430 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05002431 || peer->afc_nego[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00002432 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05002433 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05002434 || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
2435 || peer->afc_nego[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00002436 return 1;
2437 return 0;
2438}
David Lamparter6b0655a2014-06-04 06:53:35 +02002439
paul718e3742002-12-13 20:15:29 +00002440/* peer_flag_change_type. */
2441enum peer_change_type
2442{
2443 peer_change_none,
2444 peer_change_reset,
2445 peer_change_reset_in,
2446 peer_change_reset_out,
2447};
2448
paul94f2b392005-06-28 12:44:16 +00002449static void
paul718e3742002-12-13 20:15:29 +00002450peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2451 enum peer_change_type type)
2452{
2453 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2454 return;
2455
Stephen Hemmingerd9d4ae52010-01-13 00:32:39 +00002456 if (peer->status != Established)
2457 return;
2458
paul718e3742002-12-13 20:15:29 +00002459 if (type == peer_change_reset)
2460 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2461 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2462 else if (type == peer_change_reset_in)
2463 {
2464 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2465 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2466 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2467 else
2468 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2469 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2470 }
2471 else if (type == peer_change_reset_out)
2472 bgp_announce_route (peer, afi, safi);
2473}
2474
2475struct peer_flag_action
2476{
2477 /* Peer's flag. */
2478 u_int32_t flag;
2479
2480 /* This flag can be set for peer-group member. */
2481 u_char not_for_member;
2482
2483 /* Action when the flag is changed. */
2484 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002485
2486 /* Peer down cause */
2487 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002488};
2489
Stephen Hemminger03621952009-07-21 16:27:20 -07002490static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002491 {
2492 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2493 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2494 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2495 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2496 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002497 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002498 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002499 { 0, 0, 0 }
2500 };
2501
Stephen Hemminger03621952009-07-21 16:27:20 -07002502static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002503 {
2504 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2505 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2506 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2507 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2508 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2509 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2510 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2511 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2512 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2513 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2514 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2515 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2516 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002517 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
Timo Teräs9e7a53c2014-04-24 10:22:37 +03002518 { PEER_FLAG_NEXTHOP_SELF_ALL, 1, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002519 { 0, 0, 0 }
2520 };
2521
2522/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002523static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002524peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002525 struct peer_flag_action *action, u_int32_t flag)
2526{
2527 int i;
2528 int found = 0;
2529 int reset_in = 0;
2530 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002531 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002532
2533 /* Check peer's frag action. */
2534 for (i = 0; i < size; i++)
2535 {
2536 match = &action_list[i];
2537
2538 if (match->flag == 0)
2539 break;
2540
2541 if (match->flag & flag)
2542 {
2543 found = 1;
2544
2545 if (match->type == peer_change_reset_in)
2546 reset_in = 1;
2547 if (match->type == peer_change_reset_out)
2548 reset_out = 1;
2549 if (match->type == peer_change_reset)
2550 {
2551 reset_in = 1;
2552 reset_out = 1;
2553 }
2554 if (match->not_for_member)
2555 action->not_for_member = 1;
2556 }
2557 }
2558
2559 /* Set peer clear type. */
2560 if (reset_in && reset_out)
2561 action->type = peer_change_reset;
2562 else if (reset_in)
2563 action->type = peer_change_reset_in;
2564 else if (reset_out)
2565 action->type = peer_change_reset_out;
2566 else
2567 action->type = peer_change_none;
2568
2569 return found;
2570}
2571
paul94f2b392005-06-28 12:44:16 +00002572static void
paul718e3742002-12-13 20:15:29 +00002573peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2574{
2575 if (flag == PEER_FLAG_SHUTDOWN)
2576 {
2577 if (CHECK_FLAG (peer->flags, flag))
2578 {
hasso93406d82005-02-02 14:40:33 +00002579 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2580 peer_nsf_stop (peer);
2581
hasso0a486e52005-02-01 20:57:17 +00002582 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2583 if (peer->t_pmax_restart)
2584 {
2585 BGP_TIMER_OFF (peer->t_pmax_restart);
2586 if (BGP_DEBUG (events, EVENTS))
2587 zlog_debug ("%s Maximum-prefix restart timer canceled",
2588 peer->host);
2589 }
2590
hasso93406d82005-02-02 14:40:33 +00002591 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2592 peer_nsf_stop (peer);
2593
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002594 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002595 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2596 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2597 else
2598 BGP_EVENT_ADD (peer, BGP_Stop);
2599 }
2600 else
2601 {
2602 peer->v_start = BGP_INIT_START_TIMER;
2603 BGP_EVENT_ADD (peer, BGP_Stop);
2604 }
2605 }
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002606 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002607 {
hassoc9502432005-02-01 22:01:48 +00002608 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2609 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2610 else if (flag == PEER_FLAG_PASSIVE)
2611 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002612 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002613 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002614
hassoc9502432005-02-01 22:01:48 +00002615 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2616 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002617 }
2618 else
2619 BGP_EVENT_ADD (peer, BGP_Stop);
2620}
2621
2622/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002623static int
paul718e3742002-12-13 20:15:29 +00002624peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2625{
2626 int found;
2627 int size;
2628 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002629 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002630 struct peer_flag_action action;
2631
2632 memset (&action, 0, sizeof (struct peer_flag_action));
2633 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2634
2635 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2636
2637 /* No flag action is found. */
2638 if (! found)
2639 return BGP_ERR_INVALID_FLAG;
2640
2641 /* Not for peer-group member. */
2642 if (action.not_for_member && peer_group_active (peer))
2643 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2644
2645 /* When unset the peer-group member's flag we have to check
2646 peer-group configuration. */
2647 if (! set && peer_group_active (peer))
2648 if (CHECK_FLAG (peer->group->conf->flags, flag))
2649 {
2650 if (flag == PEER_FLAG_SHUTDOWN)
2651 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2652 else
2653 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2654 }
2655
2656 /* Flag conflict check. */
2657 if (set
2658 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2659 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2660 return BGP_ERR_PEER_FLAG_CONFLICT;
2661
2662 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2663 {
2664 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2665 return 0;
2666 if (! set && ! CHECK_FLAG (peer->flags, flag))
2667 return 0;
2668 }
2669
2670 if (set)
2671 SET_FLAG (peer->flags, flag);
2672 else
2673 UNSET_FLAG (peer->flags, flag);
2674
2675 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2676 {
2677 if (action.type == peer_change_reset)
2678 peer_flag_modify_action (peer, flag);
2679
2680 return 0;
2681 }
2682
2683 /* peer-group member updates. */
2684 group = peer->group;
2685
paul1eb8ef22005-04-07 07:30:20 +00002686 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002687 {
2688 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2689 continue;
2690
2691 if (! set && ! CHECK_FLAG (peer->flags, flag))
2692 continue;
2693
2694 if (set)
2695 SET_FLAG (peer->flags, flag);
2696 else
2697 UNSET_FLAG (peer->flags, flag);
2698
2699 if (action.type == peer_change_reset)
2700 peer_flag_modify_action (peer, flag);
2701 }
2702 return 0;
2703}
2704
2705int
2706peer_flag_set (struct peer *peer, u_int32_t flag)
2707{
2708 return peer_flag_modify (peer, flag, 1);
2709}
2710
2711int
2712peer_flag_unset (struct peer *peer, u_int32_t flag)
2713{
2714 return peer_flag_modify (peer, flag, 0);
2715}
2716
paul94f2b392005-06-28 12:44:16 +00002717static int
paul718e3742002-12-13 20:15:29 +00002718peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2719{
2720 if (peer->af_group[afi][safi])
2721 return 1;
2722 return 0;
2723}
2724
paul94f2b392005-06-28 12:44:16 +00002725static int
paul718e3742002-12-13 20:15:29 +00002726peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2727 int set)
2728{
2729 int found;
2730 int size;
paul1eb8ef22005-04-07 07:30:20 +00002731 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002732 struct peer_group *group;
2733 struct peer_flag_action action;
2734
2735 memset (&action, 0, sizeof (struct peer_flag_action));
2736 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2737
2738 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2739
2740 /* No flag action is found. */
2741 if (! found)
2742 return BGP_ERR_INVALID_FLAG;
2743
2744 /* Adress family must be activated. */
2745 if (! peer->afc[afi][safi])
2746 return BGP_ERR_PEER_INACTIVE;
2747
2748 /* Not for peer-group member. */
2749 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2750 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2751
2752 /* Spcecial check for reflector client. */
2753 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2754 && peer_sort (peer) != BGP_PEER_IBGP)
2755 return BGP_ERR_NOT_INTERNAL_PEER;
2756
2757 /* Spcecial check for remove-private-AS. */
2758 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2759 && peer_sort (peer) == BGP_PEER_IBGP)
2760 return BGP_ERR_REMOVE_PRIVATE_AS;
2761
2762 /* When unset the peer-group member's flag we have to check
2763 peer-group configuration. */
2764 if (! set && peer->af_group[afi][safi])
2765 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2766 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2767
2768 /* When current flag configuration is same as requested one. */
2769 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2770 {
2771 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2772 return 0;
2773 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2774 return 0;
2775 }
2776
2777 if (set)
2778 SET_FLAG (peer->af_flags[afi][safi], flag);
2779 else
2780 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2781
2782 /* Execute action when peer is established. */
2783 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2784 && peer->status == Established)
2785 {
2786 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2787 bgp_clear_adj_in (peer, afi, safi);
2788 else
hassoe0701b72004-05-20 09:19:34 +00002789 {
2790 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2791 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2792 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2793 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2794 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2795 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2796 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2797 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2798
2799 peer_change_action (peer, afi, safi, action.type);
2800 }
2801
paul718e3742002-12-13 20:15:29 +00002802 }
2803
2804 /* Peer group member updates. */
2805 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2806 {
2807 group = peer->group;
2808
paul1eb8ef22005-04-07 07:30:20 +00002809 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002810 {
2811 if (! peer->af_group[afi][safi])
2812 continue;
2813
2814 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2815 continue;
2816
2817 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2818 continue;
2819
2820 if (set)
2821 SET_FLAG (peer->af_flags[afi][safi], flag);
2822 else
2823 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2824
2825 if (peer->status == Established)
2826 {
2827 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2828 bgp_clear_adj_in (peer, afi, safi);
2829 else
hassoe0701b72004-05-20 09:19:34 +00002830 {
2831 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2832 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2833 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2834 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2835 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2836 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2837 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2838 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2839
2840 peer_change_action (peer, afi, safi, action.type);
2841 }
paul718e3742002-12-13 20:15:29 +00002842 }
2843 }
2844 }
2845 return 0;
2846}
2847
2848int
2849peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2850{
2851 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2852}
2853
2854int
2855peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2856{
2857 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2858}
David Lamparter6b0655a2014-06-04 06:53:35 +02002859
paul718e3742002-12-13 20:15:29 +00002860/* EBGP multihop configuration. */
2861int
2862peer_ebgp_multihop_set (struct peer *peer, int ttl)
2863{
2864 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002865 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002866 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002867
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002868 if (peer->sort == BGP_PEER_IBGP)
Timo Teräse3443a22016-10-19 16:02:34 +03002869 return BGP_ERR_NO_IBGP_WITH_TTLHACK;
paul718e3742002-12-13 20:15:29 +00002870
Timo Teräse3443a22016-10-19 16:02:34 +03002871 if (peer->gtsm_hops != 0)
2872 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2873
2874 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
Nick Hilliardfa411a22011-03-23 15:33:17 +00002875 {
Timo Teräse3443a22016-10-19 16:02:34 +03002876 group = peer->group;
2877 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
Nick Hilliardfa411a22011-03-23 15:33:17 +00002878 {
Timo Teräse3443a22016-10-19 16:02:34 +03002879 if (peer1->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002880 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2881 }
2882 }
2883
paul718e3742002-12-13 20:15:29 +00002884 peer->ttl = ttl;
2885
2886 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2887 {
Timo Teräse3443a22016-10-19 16:02:34 +03002888 bgp_set_socket_ttl (peer, peer->fd);
paul718e3742002-12-13 20:15:29 +00002889 }
2890 else
2891 {
2892 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002893 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
Timo Teräse3443a22016-10-19 16:02:34 +03002894 {
2895 peer->ttl = ttl;
2896 bgp_set_socket_ttl (peer, peer->fd);
2897 }
paul718e3742002-12-13 20:15:29 +00002898 }
paul718e3742002-12-13 20:15:29 +00002899
paul718e3742002-12-13 20:15:29 +00002900 return 0;
2901}
David Lamparter6b0655a2014-06-04 06:53:35 +02002902
paul718e3742002-12-13 20:15:29 +00002903/* Neighbor description. */
2904int
David Lamparterdfb9bd72016-05-24 18:58:07 +02002905peer_description_set (struct peer *peer, const char *desc)
paul718e3742002-12-13 20:15:29 +00002906{
2907 if (peer->desc)
2908 XFREE (MTYPE_PEER_DESC, peer->desc);
2909
2910 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2911
2912 return 0;
2913}
2914
2915int
2916peer_description_unset (struct peer *peer)
2917{
2918 if (peer->desc)
2919 XFREE (MTYPE_PEER_DESC, peer->desc);
2920
2921 peer->desc = NULL;
2922
2923 return 0;
2924}
David Lamparter6b0655a2014-06-04 06:53:35 +02002925
paul718e3742002-12-13 20:15:29 +00002926/* Neighbor update-source. */
2927int
paulfd79ac92004-10-13 05:06:08 +00002928peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002929{
2930 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002931 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002932
2933 if (peer->update_if)
2934 {
2935 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2936 && strcmp (peer->update_if, ifname) == 0)
2937 return 0;
2938
2939 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2940 peer->update_if = NULL;
2941 }
2942
2943 if (peer->update_source)
2944 {
2945 sockunion_free (peer->update_source);
2946 peer->update_source = NULL;
2947 }
2948
2949 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2950
2951 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2952 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002953 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002954 {
2955 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2956 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2957 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2958 }
paul718e3742002-12-13 20:15:29 +00002959 else
2960 BGP_EVENT_ADD (peer, BGP_Stop);
2961 return 0;
2962 }
2963
2964 /* peer-group member updates. */
2965 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002966 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002967 {
2968 if (peer->update_if)
2969 {
2970 if (strcmp (peer->update_if, ifname) == 0)
2971 continue;
2972
2973 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2974 peer->update_if = NULL;
2975 }
2976
2977 if (peer->update_source)
2978 {
2979 sockunion_free (peer->update_source);
2980 peer->update_source = NULL;
2981 }
2982
2983 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2984
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002985 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002986 {
2987 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2988 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2989 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2990 }
paul718e3742002-12-13 20:15:29 +00002991 else
2992 BGP_EVENT_ADD (peer, BGP_Stop);
2993 }
2994 return 0;
2995}
2996
2997int
David Lamparterdfb9bd72016-05-24 18:58:07 +02002998peer_update_source_addr_set (struct peer *peer, const union sockunion *su)
paul718e3742002-12-13 20:15:29 +00002999{
3000 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003001 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003002
3003 if (peer->update_source)
3004 {
3005 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3006 && sockunion_cmp (peer->update_source, su) == 0)
3007 return 0;
3008 sockunion_free (peer->update_source);
3009 peer->update_source = NULL;
3010 }
3011
3012 if (peer->update_if)
3013 {
3014 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3015 peer->update_if = NULL;
3016 }
3017
3018 peer->update_source = sockunion_dup (su);
3019
3020 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3021 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003022 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003023 {
3024 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3025 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3026 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3027 }
paul718e3742002-12-13 20:15:29 +00003028 else
3029 BGP_EVENT_ADD (peer, BGP_Stop);
3030 return 0;
3031 }
3032
3033 /* peer-group member updates. */
3034 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003035 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003036 {
3037 if (peer->update_source)
3038 {
3039 if (sockunion_cmp (peer->update_source, su) == 0)
3040 continue;
3041 sockunion_free (peer->update_source);
3042 peer->update_source = NULL;
3043 }
3044
3045 if (peer->update_if)
3046 {
3047 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3048 peer->update_if = NULL;
3049 }
3050
3051 peer->update_source = sockunion_dup (su);
3052
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003053 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003054 {
3055 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3056 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3057 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3058 }
paul718e3742002-12-13 20:15:29 +00003059 else
3060 BGP_EVENT_ADD (peer, BGP_Stop);
3061 }
3062 return 0;
3063}
3064
3065int
3066peer_update_source_unset (struct peer *peer)
3067{
3068 union sockunion *su;
3069 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003070 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003071
3072 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3073 && ! peer->update_source
3074 && ! peer->update_if)
3075 return 0;
3076
3077 if (peer->update_source)
3078 {
3079 sockunion_free (peer->update_source);
3080 peer->update_source = NULL;
3081 }
3082 if (peer->update_if)
3083 {
3084 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3085 peer->update_if = NULL;
3086 }
3087
3088 if (peer_group_active (peer))
3089 {
3090 group = peer->group;
3091
3092 if (group->conf->update_source)
3093 {
3094 su = sockunion_dup (group->conf->update_source);
3095 peer->update_source = su;
3096 }
3097 else if (group->conf->update_if)
3098 peer->update_if =
3099 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
3100 }
3101
3102 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3103 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003104 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003105 {
3106 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3107 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3108 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3109 }
paul718e3742002-12-13 20:15:29 +00003110 else
3111 BGP_EVENT_ADD (peer, BGP_Stop);
3112 return 0;
3113 }
3114
3115 /* peer-group member updates. */
3116 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003117 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003118 {
3119 if (! peer->update_source && ! peer->update_if)
3120 continue;
3121
3122 if (peer->update_source)
3123 {
3124 sockunion_free (peer->update_source);
3125 peer->update_source = NULL;
3126 }
3127
3128 if (peer->update_if)
3129 {
3130 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3131 peer->update_if = NULL;
3132 }
3133
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003134 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003135 {
3136 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3137 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3138 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3139 }
paul718e3742002-12-13 20:15:29 +00003140 else
3141 BGP_EVENT_ADD (peer, BGP_Stop);
3142 }
3143 return 0;
3144}
David Lamparter6b0655a2014-06-04 06:53:35 +02003145
paul718e3742002-12-13 20:15:29 +00003146int
3147peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003148 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003149{
3150 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003151 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003152
3153 /* Adress family must be activated. */
3154 if (! peer->afc[afi][safi])
3155 return BGP_ERR_PEER_INACTIVE;
3156
3157 /* Default originate can't be used for peer group memeber. */
3158 if (peer_is_group_member (peer, afi, safi))
3159 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3160
3161 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3162 || (rmap && ! peer->default_rmap[afi][safi].name)
3163 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3164 {
3165 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3166
3167 if (rmap)
3168 {
3169 if (peer->default_rmap[afi][safi].name)
3170 free (peer->default_rmap[afi][safi].name);
3171 peer->default_rmap[afi][safi].name = strdup (rmap);
3172 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3173 }
3174 }
3175
3176 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3177 {
3178 if (peer->status == Established && peer->afc_nego[afi][safi])
3179 bgp_default_originate (peer, afi, safi, 0);
3180 return 0;
3181 }
3182
3183 /* peer-group member updates. */
3184 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003185 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003186 {
3187 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3188
3189 if (rmap)
3190 {
3191 if (peer->default_rmap[afi][safi].name)
3192 free (peer->default_rmap[afi][safi].name);
3193 peer->default_rmap[afi][safi].name = strdup (rmap);
3194 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3195 }
3196
3197 if (peer->status == Established && peer->afc_nego[afi][safi])
3198 bgp_default_originate (peer, afi, safi, 0);
3199 }
3200 return 0;
3201}
3202
3203int
3204peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3205{
3206 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003207 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003208
3209 /* Adress family must be activated. */
3210 if (! peer->afc[afi][safi])
3211 return BGP_ERR_PEER_INACTIVE;
3212
3213 /* Default originate can't be used for peer group memeber. */
3214 if (peer_is_group_member (peer, afi, safi))
3215 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3216
3217 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3218 {
3219 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3220
3221 if (peer->default_rmap[afi][safi].name)
3222 free (peer->default_rmap[afi][safi].name);
3223 peer->default_rmap[afi][safi].name = NULL;
3224 peer->default_rmap[afi][safi].map = NULL;
3225 }
3226
3227 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3228 {
3229 if (peer->status == Established && peer->afc_nego[afi][safi])
3230 bgp_default_originate (peer, afi, safi, 1);
3231 return 0;
3232 }
3233
3234 /* peer-group member updates. */
3235 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003236 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003237 {
3238 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3239
3240 if (peer->default_rmap[afi][safi].name)
3241 free (peer->default_rmap[afi][safi].name);
3242 peer->default_rmap[afi][safi].name = NULL;
3243 peer->default_rmap[afi][safi].map = NULL;
3244
3245 if (peer->status == Established && peer->afc_nego[afi][safi])
3246 bgp_default_originate (peer, afi, safi, 1);
3247 }
3248 return 0;
3249}
David Lamparter6b0655a2014-06-04 06:53:35 +02003250
paul718e3742002-12-13 20:15:29 +00003251int
3252peer_port_set (struct peer *peer, u_int16_t port)
3253{
3254 peer->port = port;
3255 return 0;
3256}
3257
3258int
3259peer_port_unset (struct peer *peer)
3260{
3261 peer->port = BGP_PORT_DEFAULT;
3262 return 0;
3263}
David Lamparter6b0655a2014-06-04 06:53:35 +02003264
paul718e3742002-12-13 20:15:29 +00003265/* neighbor weight. */
3266int
3267peer_weight_set (struct peer *peer, u_int16_t weight)
3268{
3269 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003270 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003271
3272 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3273 peer->weight = weight;
3274
3275 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3276 return 0;
3277
3278 /* peer-group member updates. */
3279 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003280 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003281 {
3282 peer->weight = group->conf->weight;
3283 }
3284 return 0;
3285}
3286
3287int
3288peer_weight_unset (struct peer *peer)
3289{
3290 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003291 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003292
3293 /* Set default weight. */
3294 if (peer_group_active (peer))
3295 peer->weight = peer->group->conf->weight;
3296 else
3297 peer->weight = 0;
3298
3299 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3300
3301 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3302 return 0;
3303
3304 /* peer-group member updates. */
3305 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003306 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003307 {
3308 peer->weight = 0;
3309 }
3310 return 0;
3311}
David Lamparter6b0655a2014-06-04 06:53:35 +02003312
paul718e3742002-12-13 20:15:29 +00003313int
3314peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3315{
3316 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003317 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003318
3319 /* Not for peer group memeber. */
3320 if (peer_group_active (peer))
3321 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3322
3323 /* keepalive value check. */
3324 if (keepalive > 65535)
3325 return BGP_ERR_INVALID_VALUE;
3326
3327 /* Holdtime value check. */
3328 if (holdtime > 65535)
3329 return BGP_ERR_INVALID_VALUE;
3330
3331 /* Holdtime value must be either 0 or greater than 3. */
3332 if (holdtime < 3 && holdtime != 0)
3333 return BGP_ERR_INVALID_VALUE;
3334
3335 /* Set value to the configuration. */
3336 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3337 peer->holdtime = holdtime;
3338 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3339
3340 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3341 return 0;
3342
3343 /* peer-group member updates. */
3344 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003345 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003346 {
3347 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3348 peer->holdtime = group->conf->holdtime;
3349 peer->keepalive = group->conf->keepalive;
3350 }
3351 return 0;
3352}
3353
3354int
3355peer_timers_unset (struct peer *peer)
3356{
3357 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003358 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003359
3360 if (peer_group_active (peer))
3361 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3362
3363 /* Clear configuration. */
3364 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3365 peer->keepalive = 0;
3366 peer->holdtime = 0;
3367
3368 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3369 return 0;
3370
3371 /* peer-group member updates. */
3372 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003373 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003374 {
3375 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3376 peer->holdtime = 0;
3377 peer->keepalive = 0;
3378 }
3379
3380 return 0;
3381}
David Lamparter6b0655a2014-06-04 06:53:35 +02003382
paul718e3742002-12-13 20:15:29 +00003383int
3384peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3385{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003386 struct peer_group *group;
3387 struct listnode *node, *nnode;
3388
paul718e3742002-12-13 20:15:29 +00003389 if (peer_group_active (peer))
3390 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3391
3392 if (connect > 65535)
3393 return BGP_ERR_INVALID_VALUE;
3394
3395 /* Set value to the configuration. */
3396 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3397 peer->connect = connect;
3398
3399 /* Set value to timer setting. */
3400 peer->v_connect = connect;
3401
Daniel Walton0d7435f2015-10-22 11:35:20 +03003402 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3403 return 0;
3404
3405 /* peer-group member updates. */
3406 group = peer->group;
3407 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3408 {
3409 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3410 peer->connect = connect;
3411 peer->v_connect = connect;
3412 }
paul718e3742002-12-13 20:15:29 +00003413 return 0;
3414}
3415
3416int
3417peer_timers_connect_unset (struct peer *peer)
3418{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003419 struct peer_group *group;
3420 struct listnode *node, *nnode;
3421
paul718e3742002-12-13 20:15:29 +00003422 if (peer_group_active (peer))
3423 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3424
3425 /* Clear configuration. */
3426 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3427 peer->connect = 0;
3428
3429 /* Set timer setting to default value. */
3430 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3431
Daniel Walton0d7435f2015-10-22 11:35:20 +03003432 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3433 return 0;
3434
3435 /* peer-group member updates. */
3436 group = peer->group;
3437 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3438 {
3439 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3440 peer->connect = 0;
3441 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3442 }
3443 return 0;
paul718e3742002-12-13 20:15:29 +00003444}
David Lamparter6b0655a2014-06-04 06:53:35 +02003445
paul718e3742002-12-13 20:15:29 +00003446int
3447peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3448{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003449 struct peer_group *group;
3450 struct listnode *node, *nnode;
3451
paul718e3742002-12-13 20:15:29 +00003452 if (peer_group_active (peer))
3453 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3454
3455 if (routeadv > 600)
3456 return BGP_ERR_INVALID_VALUE;
3457
3458 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3459 peer->routeadv = routeadv;
3460 peer->v_routeadv = routeadv;
3461
Daniel Walton0d7435f2015-10-22 11:35:20 +03003462 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3463 return 0;
3464
3465 /* peer-group member updates. */
3466 group = peer->group;
3467 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3468 {
3469 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3470 peer->routeadv = routeadv;
3471 peer->v_routeadv = routeadv;
3472 }
3473
paul718e3742002-12-13 20:15:29 +00003474 return 0;
3475}
3476
3477int
3478peer_advertise_interval_unset (struct peer *peer)
3479{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003480 struct peer_group *group;
3481 struct listnode *node, *nnode;
3482
paul718e3742002-12-13 20:15:29 +00003483 if (peer_group_active (peer))
3484 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3485
3486 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3487 peer->routeadv = 0;
3488
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003489 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003490 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3491 else
3492 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
Daniel Walton0d7435f2015-10-22 11:35:20 +03003493
3494 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3495 return 0;
3496
3497 /* peer-group member updates. */
3498 group = peer->group;
3499 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3500 {
3501 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3502 peer->routeadv = 0;
3503
3504 if (peer->sort == BGP_PEER_IBGP)
3505 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3506 else
3507 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3508 }
paul718e3742002-12-13 20:15:29 +00003509
3510 return 0;
3511}
David Lamparter6b0655a2014-06-04 06:53:35 +02003512
paul718e3742002-12-13 20:15:29 +00003513/* neighbor interface */
3514int
paulfd79ac92004-10-13 05:06:08 +00003515peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003516{
3517 if (peer->ifname)
3518 free (peer->ifname);
3519 peer->ifname = strdup (str);
3520
3521 return 0;
3522}
3523
3524int
3525peer_interface_unset (struct peer *peer)
3526{
3527 if (peer->ifname)
3528 free (peer->ifname);
3529 peer->ifname = NULL;
3530
3531 return 0;
3532}
David Lamparter6b0655a2014-06-04 06:53:35 +02003533
paul718e3742002-12-13 20:15:29 +00003534/* Allow-as in. */
3535int
3536peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3537{
3538 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003539 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003540
3541 if (allow_num < 1 || allow_num > 10)
3542 return BGP_ERR_INVALID_VALUE;
3543
3544 if (peer->allowas_in[afi][safi] != allow_num)
3545 {
3546 peer->allowas_in[afi][safi] = allow_num;
3547 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3548 peer_change_action (peer, afi, safi, peer_change_reset_in);
3549 }
3550
3551 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3552 return 0;
3553
3554 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003555 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003556 {
3557 if (peer->allowas_in[afi][safi] != allow_num)
3558 {
3559 peer->allowas_in[afi][safi] = allow_num;
3560 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3561 peer_change_action (peer, afi, safi, peer_change_reset_in);
3562 }
3563
3564 }
3565 return 0;
3566}
3567
3568int
3569peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3570{
3571 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003572 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003573
3574 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3575 {
3576 peer->allowas_in[afi][safi] = 0;
3577 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3578 }
3579
3580 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3581 return 0;
3582
3583 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003584 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003585 {
3586 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3587 {
3588 peer->allowas_in[afi][safi] = 0;
3589 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3590 }
3591 }
3592 return 0;
3593}
David Lamparter6b0655a2014-06-04 06:53:35 +02003594
paul718e3742002-12-13 20:15:29 +00003595int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003596peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003597{
3598 struct bgp *bgp = peer->bgp;
3599 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003600 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003601
3602 if (peer_sort (peer) != BGP_PEER_EBGP
3603 && peer_sort (peer) != BGP_PEER_INTERNAL)
3604 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3605
3606 if (bgp->as == as)
3607 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3608
3609 if (peer_group_active (peer))
3610 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3611
Andrew Certain9d3f9702012-11-07 23:50:07 +00003612 if (peer->as == as)
3613 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3614
paul718e3742002-12-13 20:15:29 +00003615 if (peer->change_local_as == as &&
3616 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003617 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3618 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3619 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003620 return 0;
3621
3622 peer->change_local_as = as;
3623 if (no_prepend)
3624 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3625 else
3626 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3627
Andrew Certain9d3f9702012-11-07 23:50:07 +00003628 if (replace_as)
3629 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3630 else
3631 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3632
paul718e3742002-12-13 20:15:29 +00003633 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3634 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003635 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003636 {
3637 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3638 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3639 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3640 }
paul718e3742002-12-13 20:15:29 +00003641 else
3642 BGP_EVENT_ADD (peer, BGP_Stop);
3643
3644 return 0;
3645 }
3646
3647 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003648 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003649 {
3650 peer->change_local_as = as;
3651 if (no_prepend)
3652 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3653 else
3654 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3655
Andrew Certain9d3f9702012-11-07 23:50:07 +00003656 if (replace_as)
3657 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3658 else
3659 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3660
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003661 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003662 {
3663 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3664 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3665 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3666 }
paul718e3742002-12-13 20:15:29 +00003667 else
3668 BGP_EVENT_ADD (peer, BGP_Stop);
3669 }
3670
3671 return 0;
3672}
3673
3674int
3675peer_local_as_unset (struct peer *peer)
3676{
3677 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003678 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003679
3680 if (peer_group_active (peer))
3681 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3682
3683 if (! peer->change_local_as)
3684 return 0;
3685
3686 peer->change_local_as = 0;
3687 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003688 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003689
3690 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3691 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003692 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003693 {
3694 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3695 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3696 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3697 }
paul718e3742002-12-13 20:15:29 +00003698 else
3699 BGP_EVENT_ADD (peer, BGP_Stop);
3700
3701 return 0;
3702 }
3703
3704 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003705 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003706 {
3707 peer->change_local_as = 0;
3708 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003709 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003710
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003711 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003712 {
3713 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3714 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3715 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3716 }
paul718e3742002-12-13 20:15:29 +00003717 else
3718 BGP_EVENT_ADD (peer, BGP_Stop);
3719 }
3720 return 0;
3721}
David Lamparter6b0655a2014-06-04 06:53:35 +02003722
Paul Jakma0df7c912008-07-21 21:02:49 +00003723/* Set password for authenticating with the peer. */
3724int
3725peer_password_set (struct peer *peer, const char *password)
3726{
3727 struct listnode *nn, *nnode;
3728 int len = password ? strlen(password) : 0;
3729 int ret = BGP_SUCCESS;
3730
3731 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3732 return BGP_ERR_INVALID_VALUE;
3733
3734 if (peer->password && strcmp (peer->password, password) == 0
3735 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3736 return 0;
3737
3738 if (peer->password)
3739 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3740
3741 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3742
3743 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3744 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003745 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3746 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
Paul Jakma0df7c912008-07-21 21:02:49 +00003747 else
3748 BGP_EVENT_ADD (peer, BGP_Stop);
3749
3750 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3751 }
3752
3753 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3754 {
3755 if (peer->password && strcmp (peer->password, password) == 0)
3756 continue;
3757
3758 if (peer->password)
3759 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3760
3761 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3762
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003763 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003764 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3765 else
3766 BGP_EVENT_ADD (peer, BGP_Stop);
3767
3768 if (bgp_md5_set (peer) < 0)
3769 ret = BGP_ERR_TCPSIG_FAILED;
3770 }
3771
3772 return ret;
3773}
3774
3775int
3776peer_password_unset (struct peer *peer)
3777{
3778 struct listnode *nn, *nnode;
3779
3780 if (!peer->password
3781 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3782 return 0;
3783
3784 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3785 {
3786 if (peer_group_active (peer)
3787 && peer->group->conf->password
3788 && strcmp (peer->group->conf->password, peer->password) == 0)
3789 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3790
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003791 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003792 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3793 else
3794 BGP_EVENT_ADD (peer, BGP_Stop);
3795
3796 if (peer->password)
3797 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3798
3799 peer->password = NULL;
3800
3801 bgp_md5_set (peer);
3802
3803 return 0;
3804 }
3805
3806 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3807 peer->password = NULL;
3808
3809 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3810 {
3811 if (!peer->password)
3812 continue;
3813
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003814 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003815 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3816 else
3817 BGP_EVENT_ADD (peer, BGP_Stop);
3818
3819 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3820 peer->password = NULL;
3821
3822 bgp_md5_set (peer);
3823 }
3824
3825 return 0;
3826}
David Lamparter6b0655a2014-06-04 06:53:35 +02003827
paul718e3742002-12-13 20:15:29 +00003828/* Set distribute list to the peer. */
3829int
3830peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003831 const char *name)
paul718e3742002-12-13 20:15:29 +00003832{
3833 struct bgp_filter *filter;
3834 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003835 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003836
3837 if (! peer->afc[afi][safi])
3838 return BGP_ERR_PEER_INACTIVE;
3839
3840 if (direct != FILTER_IN && direct != FILTER_OUT)
3841 return BGP_ERR_INVALID_VALUE;
3842
3843 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3844 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3845
3846 filter = &peer->filter[afi][safi];
3847
3848 if (filter->plist[direct].name)
3849 return BGP_ERR_PEER_FILTER_CONFLICT;
3850
3851 if (filter->dlist[direct].name)
3852 free (filter->dlist[direct].name);
3853 filter->dlist[direct].name = strdup (name);
3854 filter->dlist[direct].alist = access_list_lookup (afi, name);
3855
3856 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3857 return 0;
3858
3859 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003860 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003861 {
3862 filter = &peer->filter[afi][safi];
3863
3864 if (! peer->af_group[afi][safi])
3865 continue;
3866
3867 if (filter->dlist[direct].name)
3868 free (filter->dlist[direct].name);
3869 filter->dlist[direct].name = strdup (name);
3870 filter->dlist[direct].alist = access_list_lookup (afi, name);
3871 }
3872
3873 return 0;
3874}
3875
3876int
3877peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3878{
3879 struct bgp_filter *filter;
3880 struct bgp_filter *gfilter;
3881 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003882 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003883
3884 if (! peer->afc[afi][safi])
3885 return BGP_ERR_PEER_INACTIVE;
3886
3887 if (direct != FILTER_IN && direct != FILTER_OUT)
3888 return BGP_ERR_INVALID_VALUE;
3889
3890 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3891 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3892
3893 filter = &peer->filter[afi][safi];
3894
3895 /* apply peer-group filter */
3896 if (peer->af_group[afi][safi])
3897 {
3898 gfilter = &peer->group->conf->filter[afi][safi];
3899
3900 if (gfilter->dlist[direct].name)
3901 {
3902 if (filter->dlist[direct].name)
3903 free (filter->dlist[direct].name);
3904 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3905 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3906 return 0;
3907 }
3908 }
3909
3910 if (filter->dlist[direct].name)
3911 free (filter->dlist[direct].name);
3912 filter->dlist[direct].name = NULL;
3913 filter->dlist[direct].alist = NULL;
3914
3915 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3916 return 0;
3917
3918 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003919 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003920 {
3921 filter = &peer->filter[afi][safi];
3922
3923 if (! peer->af_group[afi][safi])
3924 continue;
3925
3926 if (filter->dlist[direct].name)
3927 free (filter->dlist[direct].name);
3928 filter->dlist[direct].name = NULL;
3929 filter->dlist[direct].alist = NULL;
3930 }
3931
3932 return 0;
3933}
3934
3935/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003936static void
paul718e3742002-12-13 20:15:29 +00003937peer_distribute_update (struct access_list *access)
3938{
3939 afi_t afi;
3940 safi_t safi;
3941 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003942 struct listnode *mnode, *mnnode;
3943 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003944 struct bgp *bgp;
3945 struct peer *peer;
3946 struct peer_group *group;
3947 struct bgp_filter *filter;
3948
paul1eb8ef22005-04-07 07:30:20 +00003949 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003950 {
paul1eb8ef22005-04-07 07:30:20 +00003951 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003952 {
3953 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3954 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3955 {
3956 filter = &peer->filter[afi][safi];
3957
3958 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3959 {
3960 if (filter->dlist[direct].name)
3961 filter->dlist[direct].alist =
3962 access_list_lookup (afi, filter->dlist[direct].name);
3963 else
3964 filter->dlist[direct].alist = NULL;
3965 }
3966 }
3967 }
paul1eb8ef22005-04-07 07:30:20 +00003968 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003969 {
3970 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3971 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3972 {
3973 filter = &group->conf->filter[afi][safi];
3974
3975 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3976 {
3977 if (filter->dlist[direct].name)
3978 filter->dlist[direct].alist =
3979 access_list_lookup (afi, filter->dlist[direct].name);
3980 else
3981 filter->dlist[direct].alist = NULL;
3982 }
3983 }
3984 }
3985 }
3986}
David Lamparter6b0655a2014-06-04 06:53:35 +02003987
paul718e3742002-12-13 20:15:29 +00003988/* Set prefix list to the peer. */
3989int
3990peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003991 const char *name)
paul718e3742002-12-13 20:15:29 +00003992{
3993 struct bgp_filter *filter;
3994 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003995 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003996
3997 if (! peer->afc[afi][safi])
3998 return BGP_ERR_PEER_INACTIVE;
3999
4000 if (direct != FILTER_IN && direct != FILTER_OUT)
4001 return BGP_ERR_INVALID_VALUE;
4002
4003 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4004 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4005
4006 filter = &peer->filter[afi][safi];
4007
4008 if (filter->dlist[direct].name)
4009 return BGP_ERR_PEER_FILTER_CONFLICT;
4010
4011 if (filter->plist[direct].name)
4012 free (filter->plist[direct].name);
4013 filter->plist[direct].name = strdup (name);
4014 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4015
4016 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4017 return 0;
4018
4019 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004020 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004021 {
4022 filter = &peer->filter[afi][safi];
4023
4024 if (! peer->af_group[afi][safi])
4025 continue;
4026
4027 if (filter->plist[direct].name)
4028 free (filter->plist[direct].name);
4029 filter->plist[direct].name = strdup (name);
4030 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4031 }
4032 return 0;
4033}
4034
4035int
4036peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4037{
4038 struct bgp_filter *filter;
4039 struct bgp_filter *gfilter;
4040 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004041 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004042
4043 if (! peer->afc[afi][safi])
4044 return BGP_ERR_PEER_INACTIVE;
4045
4046 if (direct != FILTER_IN && direct != FILTER_OUT)
4047 return BGP_ERR_INVALID_VALUE;
4048
4049 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4050 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4051
4052 filter = &peer->filter[afi][safi];
4053
4054 /* apply peer-group filter */
4055 if (peer->af_group[afi][safi])
4056 {
4057 gfilter = &peer->group->conf->filter[afi][safi];
4058
4059 if (gfilter->plist[direct].name)
4060 {
4061 if (filter->plist[direct].name)
4062 free (filter->plist[direct].name);
4063 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
4064 filter->plist[direct].plist = gfilter->plist[direct].plist;
4065 return 0;
4066 }
4067 }
4068
4069 if (filter->plist[direct].name)
4070 free (filter->plist[direct].name);
4071 filter->plist[direct].name = NULL;
4072 filter->plist[direct].plist = NULL;
4073
4074 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4075 return 0;
4076
4077 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004078 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004079 {
4080 filter = &peer->filter[afi][safi];
4081
4082 if (! peer->af_group[afi][safi])
4083 continue;
4084
4085 if (filter->plist[direct].name)
4086 free (filter->plist[direct].name);
4087 filter->plist[direct].name = NULL;
4088 filter->plist[direct].plist = NULL;
4089 }
4090
4091 return 0;
4092}
4093
4094/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00004095static void
paul718e3742002-12-13 20:15:29 +00004096peer_prefix_list_update (struct prefix_list *plist)
4097{
paul1eb8ef22005-04-07 07:30:20 +00004098 struct listnode *mnode, *mnnode;
4099 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004100 struct bgp *bgp;
4101 struct peer *peer;
4102 struct peer_group *group;
4103 struct bgp_filter *filter;
4104 afi_t afi;
4105 safi_t safi;
4106 int direct;
4107
paul1eb8ef22005-04-07 07:30:20 +00004108 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004109 {
paul1eb8ef22005-04-07 07:30:20 +00004110 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004111 {
4112 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4113 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4114 {
4115 filter = &peer->filter[afi][safi];
4116
4117 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4118 {
4119 if (filter->plist[direct].name)
4120 filter->plist[direct].plist =
4121 prefix_list_lookup (afi, filter->plist[direct].name);
4122 else
4123 filter->plist[direct].plist = NULL;
4124 }
4125 }
4126 }
paul1eb8ef22005-04-07 07:30:20 +00004127 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004128 {
4129 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4130 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4131 {
4132 filter = &group->conf->filter[afi][safi];
4133
4134 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4135 {
4136 if (filter->plist[direct].name)
4137 filter->plist[direct].plist =
4138 prefix_list_lookup (afi, filter->plist[direct].name);
4139 else
4140 filter->plist[direct].plist = NULL;
4141 }
4142 }
4143 }
4144 }
4145}
David Lamparter6b0655a2014-06-04 06:53:35 +02004146
paul718e3742002-12-13 20:15:29 +00004147int
4148peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004149 const char *name)
paul718e3742002-12-13 20:15:29 +00004150{
4151 struct bgp_filter *filter;
4152 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004153 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004154
4155 if (! peer->afc[afi][safi])
4156 return BGP_ERR_PEER_INACTIVE;
4157
4158 if (direct != FILTER_IN && direct != FILTER_OUT)
4159 return BGP_ERR_INVALID_VALUE;
4160
4161 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4162 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4163
4164 filter = &peer->filter[afi][safi];
4165
4166 if (filter->aslist[direct].name)
4167 free (filter->aslist[direct].name);
4168 filter->aslist[direct].name = strdup (name);
4169 filter->aslist[direct].aslist = as_list_lookup (name);
4170
4171 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4172 return 0;
4173
4174 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004175 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004176 {
4177 filter = &peer->filter[afi][safi];
4178
4179 if (! peer->af_group[afi][safi])
4180 continue;
4181
4182 if (filter->aslist[direct].name)
4183 free (filter->aslist[direct].name);
4184 filter->aslist[direct].name = strdup (name);
4185 filter->aslist[direct].aslist = as_list_lookup (name);
4186 }
4187 return 0;
4188}
4189
4190int
4191peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4192{
4193 struct bgp_filter *filter;
4194 struct bgp_filter *gfilter;
4195 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004196 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004197
4198 if (! peer->afc[afi][safi])
4199 return BGP_ERR_PEER_INACTIVE;
4200
hassob5f29602005-05-25 21:00:28 +00004201 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004202 return BGP_ERR_INVALID_VALUE;
4203
hassob5f29602005-05-25 21:00:28 +00004204 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004205 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4206
4207 filter = &peer->filter[afi][safi];
4208
4209 /* apply peer-group filter */
4210 if (peer->af_group[afi][safi])
4211 {
4212 gfilter = &peer->group->conf->filter[afi][safi];
4213
4214 if (gfilter->aslist[direct].name)
4215 {
4216 if (filter->aslist[direct].name)
4217 free (filter->aslist[direct].name);
4218 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4219 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4220 return 0;
4221 }
4222 }
4223
4224 if (filter->aslist[direct].name)
4225 free (filter->aslist[direct].name);
4226 filter->aslist[direct].name = NULL;
4227 filter->aslist[direct].aslist = NULL;
4228
4229 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4230 return 0;
4231
4232 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004233 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004234 {
4235 filter = &peer->filter[afi][safi];
4236
4237 if (! peer->af_group[afi][safi])
4238 continue;
4239
4240 if (filter->aslist[direct].name)
4241 free (filter->aslist[direct].name);
4242 filter->aslist[direct].name = NULL;
4243 filter->aslist[direct].aslist = NULL;
4244 }
4245
4246 return 0;
4247}
4248
paul94f2b392005-06-28 12:44:16 +00004249static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004250peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004251{
4252 afi_t afi;
4253 safi_t safi;
4254 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004255 struct listnode *mnode, *mnnode;
4256 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004257 struct bgp *bgp;
4258 struct peer *peer;
4259 struct peer_group *group;
4260 struct bgp_filter *filter;
4261
paul1eb8ef22005-04-07 07:30:20 +00004262 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004263 {
paul1eb8ef22005-04-07 07:30:20 +00004264 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004265 {
4266 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4267 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4268 {
4269 filter = &peer->filter[afi][safi];
4270
4271 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4272 {
4273 if (filter->aslist[direct].name)
4274 filter->aslist[direct].aslist =
4275 as_list_lookup (filter->aslist[direct].name);
4276 else
4277 filter->aslist[direct].aslist = NULL;
4278 }
4279 }
4280 }
paul1eb8ef22005-04-07 07:30:20 +00004281 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004282 {
4283 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4284 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4285 {
4286 filter = &group->conf->filter[afi][safi];
4287
4288 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4289 {
4290 if (filter->aslist[direct].name)
4291 filter->aslist[direct].aslist =
4292 as_list_lookup (filter->aslist[direct].name);
4293 else
4294 filter->aslist[direct].aslist = NULL;
4295 }
4296 }
4297 }
4298 }
4299}
David Lamparter6b0655a2014-06-04 06:53:35 +02004300
paul718e3742002-12-13 20:15:29 +00004301/* Set route-map to the peer. */
4302int
4303peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004304 const char *name)
paul718e3742002-12-13 20:15:29 +00004305{
4306 struct bgp_filter *filter;
4307 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004308 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004309
4310 if (! peer->afc[afi][safi])
4311 return BGP_ERR_PEER_INACTIVE;
4312
paulfee0f4c2004-09-13 05:12:46 +00004313 if (direct != RMAP_IN && direct != RMAP_OUT &&
4314 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004315 return BGP_ERR_INVALID_VALUE;
4316
paulfee0f4c2004-09-13 05:12:46 +00004317 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4318 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004319 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4320
4321 filter = &peer->filter[afi][safi];
4322
4323 if (filter->map[direct].name)
4324 free (filter->map[direct].name);
4325
4326 filter->map[direct].name = strdup (name);
4327 filter->map[direct].map = route_map_lookup_by_name (name);
4328
4329 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4330 return 0;
4331
4332 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004333 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004334 {
4335 filter = &peer->filter[afi][safi];
4336
4337 if (! peer->af_group[afi][safi])
4338 continue;
4339
4340 if (filter->map[direct].name)
4341 free (filter->map[direct].name);
4342 filter->map[direct].name = strdup (name);
4343 filter->map[direct].map = route_map_lookup_by_name (name);
4344 }
4345 return 0;
4346}
4347
4348/* Unset route-map from the peer. */
4349int
4350peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4351{
4352 struct bgp_filter *filter;
4353 struct bgp_filter *gfilter;
4354 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004355 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004356
4357 if (! peer->afc[afi][safi])
4358 return BGP_ERR_PEER_INACTIVE;
4359
hassob5f29602005-05-25 21:00:28 +00004360 if (direct != RMAP_IN && direct != RMAP_OUT &&
4361 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004362 return BGP_ERR_INVALID_VALUE;
4363
hassob5f29602005-05-25 21:00:28 +00004364 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4365 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004366 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4367
4368 filter = &peer->filter[afi][safi];
4369
4370 /* apply peer-group filter */
4371 if (peer->af_group[afi][safi])
4372 {
4373 gfilter = &peer->group->conf->filter[afi][safi];
4374
4375 if (gfilter->map[direct].name)
4376 {
4377 if (filter->map[direct].name)
4378 free (filter->map[direct].name);
4379 filter->map[direct].name = strdup (gfilter->map[direct].name);
4380 filter->map[direct].map = gfilter->map[direct].map;
4381 return 0;
4382 }
4383 }
4384
4385 if (filter->map[direct].name)
4386 free (filter->map[direct].name);
4387 filter->map[direct].name = NULL;
4388 filter->map[direct].map = NULL;
4389
4390 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4391 return 0;
4392
4393 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004394 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004395 {
4396 filter = &peer->filter[afi][safi];
4397
4398 if (! peer->af_group[afi][safi])
4399 continue;
4400
4401 if (filter->map[direct].name)
4402 free (filter->map[direct].name);
4403 filter->map[direct].name = NULL;
4404 filter->map[direct].map = NULL;
4405 }
4406 return 0;
4407}
David Lamparter6b0655a2014-06-04 06:53:35 +02004408
paul718e3742002-12-13 20:15:29 +00004409/* Set unsuppress-map to the peer. */
4410int
paulfd79ac92004-10-13 05:06:08 +00004411peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4412 const char *name)
paul718e3742002-12-13 20:15:29 +00004413{
4414 struct bgp_filter *filter;
4415 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004416 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004417
4418 if (! peer->afc[afi][safi])
4419 return BGP_ERR_PEER_INACTIVE;
4420
4421 if (peer_is_group_member (peer, afi, safi))
4422 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4423
4424 filter = &peer->filter[afi][safi];
4425
4426 if (filter->usmap.name)
4427 free (filter->usmap.name);
4428
4429 filter->usmap.name = strdup (name);
4430 filter->usmap.map = route_map_lookup_by_name (name);
4431
4432 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4433 return 0;
4434
4435 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004436 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004437 {
4438 filter = &peer->filter[afi][safi];
4439
4440 if (! peer->af_group[afi][safi])
4441 continue;
4442
4443 if (filter->usmap.name)
4444 free (filter->usmap.name);
4445 filter->usmap.name = strdup (name);
4446 filter->usmap.map = route_map_lookup_by_name (name);
4447 }
4448 return 0;
4449}
4450
4451/* Unset route-map from the peer. */
4452int
4453peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4454{
4455 struct bgp_filter *filter;
4456 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004457 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004458
4459 if (! peer->afc[afi][safi])
4460 return BGP_ERR_PEER_INACTIVE;
4461
4462 if (peer_is_group_member (peer, afi, safi))
4463 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4464
4465 filter = &peer->filter[afi][safi];
4466
4467 if (filter->usmap.name)
4468 free (filter->usmap.name);
4469 filter->usmap.name = NULL;
4470 filter->usmap.map = NULL;
4471
4472 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4473 return 0;
4474
4475 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004476 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004477 {
4478 filter = &peer->filter[afi][safi];
4479
4480 if (! peer->af_group[afi][safi])
4481 continue;
4482
4483 if (filter->usmap.name)
4484 free (filter->usmap.name);
4485 filter->usmap.name = NULL;
4486 filter->usmap.map = NULL;
4487 }
4488 return 0;
4489}
David Lamparter6b0655a2014-06-04 06:53:35 +02004490
paul718e3742002-12-13 20:15:29 +00004491int
4492peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004493 u_int32_t max, u_char threshold,
4494 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004495{
4496 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004497 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004498
4499 if (! peer->afc[afi][safi])
4500 return BGP_ERR_PEER_INACTIVE;
4501
4502 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4503 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004504 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004505 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004506 if (warning)
4507 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4508 else
4509 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4510
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07004511 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
paul718e3742002-12-13 20:15:29 +00004512 {
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07004513 group = peer->group;
4514 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4515 {
4516 if (! peer->af_group[afi][safi])
4517 continue;
paul718e3742002-12-13 20:15:29 +00004518
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07004519 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4520 peer->pmax[afi][safi] = max;
4521 peer->pmax_threshold[afi][safi] = threshold;
4522 peer->pmax_restart[afi][safi] = restart;
4523 if (warning)
4524 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4525 else
4526 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4527
4528 if ((peer->status == Established) && (peer->afc[afi][safi]))
4529 bgp_maximum_prefix_overflow (peer, afi, safi, 1);
4530 }
paul718e3742002-12-13 20:15:29 +00004531 }
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07004532 else
4533 {
4534 if ((peer->status == Established) && (peer->afc[afi][safi]))
4535 bgp_maximum_prefix_overflow (peer, afi, safi, 1);
4536 }
4537
paul718e3742002-12-13 20:15:29 +00004538 return 0;
4539}
4540
4541int
4542peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4543{
4544 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004545 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004546
4547 if (! peer->afc[afi][safi])
4548 return BGP_ERR_PEER_INACTIVE;
4549
4550 /* apply peer-group config */
4551 if (peer->af_group[afi][safi])
4552 {
4553 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4554 PEER_FLAG_MAX_PREFIX))
4555 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4556 else
4557 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4558
4559 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4560 PEER_FLAG_MAX_PREFIX_WARNING))
4561 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4562 else
4563 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4564
4565 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004566 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004567 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004568 return 0;
4569 }
4570
4571 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4572 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4573 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004574 peer->pmax_threshold[afi][safi] = 0;
4575 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004576
4577 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4578 return 0;
4579
4580 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004581 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004582 {
4583 if (! peer->af_group[afi][safi])
4584 continue;
4585
4586 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4587 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4588 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004589 peer->pmax_threshold[afi][safi] = 0;
4590 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004591 }
4592 return 0;
4593}
David Lamparter5f9adb52014-05-19 23:15:02 +02004594
Nick Hilliardfa411a22011-03-23 15:33:17 +00004595/* Set # of hops between us and BGP peer. */
4596int
4597peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4598{
4599 struct peer_group *group;
4600 struct listnode *node, *nnode;
Timo Teräse3443a22016-10-19 16:02:34 +03004601 struct peer *peer1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004602
4603 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4604
Timo Teräse3443a22016-10-19 16:02:34 +03004605 if (peer->ttl != 0)
4606 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004607
Timo Teräse3443a22016-10-19 16:02:34 +03004608 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4609 {
4610 group = peer->group;
4611 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4612 {
4613 if (peer1->ttl != 0)
4614 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4615 }
David Lamparter5f9adb52014-05-19 23:15:02 +02004616 }
Timo Teräse3443a22016-10-19 16:02:34 +03004617
Nick Hilliardfa411a22011-03-23 15:33:17 +00004618 peer->gtsm_hops = gtsm_hops;
4619
Nick Hilliardfa411a22011-03-23 15:33:17 +00004620 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4621 {
Timo Teräse3443a22016-10-19 16:02:34 +03004622 bgp_set_socket_ttl (peer, peer->fd);
Nick Hilliardfa411a22011-03-23 15:33:17 +00004623 }
4624 else
4625 {
4626 group = peer->group;
4627 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4628 {
Timo Teräse3443a22016-10-19 16:02:34 +03004629 peer->gtsm_hops = gtsm_hops;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004630
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004631 /* Change setting of existing peer
4632 * established then change value (may break connectivity)
4633 * not established yet (teardown session and restart)
4634 * no session then do nothing (will get handled by next connection)
4635 */
4636 if (peer->status == Established)
4637 {
Timo Teräse3443a22016-10-19 16:02:34 +03004638 bgp_set_socket_ttl (peer, peer->fd);
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004639 }
4640 else if (peer->status < Established)
4641 {
4642 if (BGP_DEBUG (events, EVENTS))
4643 zlog_debug ("%s Min-ttl changed", peer->host);
4644 BGP_EVENT_ADD (peer, BGP_Stop);
4645 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004646 }
4647 }
4648
4649 return 0;
4650}
4651
4652int
paul718e3742002-12-13 20:15:29 +00004653peer_clear (struct peer *peer)
4654{
4655 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4656 {
hasso0a486e52005-02-01 20:57:17 +00004657 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4658 {
4659 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4660 if (peer->t_pmax_restart)
4661 {
4662 BGP_TIMER_OFF (peer->t_pmax_restart);
4663 if (BGP_DEBUG (events, EVENTS))
4664 zlog_debug ("%s Maximum-prefix restart timer canceled",
4665 peer->host);
4666 }
4667 BGP_EVENT_ADD (peer, BGP_Start);
4668 return 0;
4669 }
4670
paul718e3742002-12-13 20:15:29 +00004671 peer->v_start = BGP_INIT_START_TIMER;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00004672 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00004673 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4674 BGP_NOTIFY_CEASE_ADMIN_RESET);
4675 else
4676 BGP_EVENT_ADD (peer, BGP_Stop);
4677 }
4678 return 0;
4679}
4680
4681int
4682peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4683 enum bgp_clear_type stype)
4684{
4685 if (peer->status != Established)
4686 return 0;
4687
4688 if (! peer->afc[afi][safi])
4689 return BGP_ERR_AF_UNCONFIGURED;
4690
Timo Teräs5a2a1ec2015-10-22 11:35:18 +03004691 peer->rtt = sockopt_tcp_rtt (peer->fd);
4692
paulfee0f4c2004-09-13 05:12:46 +00004693 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4694 {
4695 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4696 return 0;
4697 bgp_check_local_routes_rsclient (peer, afi, safi);
4698 bgp_soft_reconfig_rsclient (peer, afi, safi);
4699 }
4700
paul718e3742002-12-13 20:15:29 +00004701 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4702 bgp_announce_route (peer, afi, safi);
4703
4704 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4705 {
4706 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4707 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4708 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4709 {
4710 struct bgp_filter *filter = &peer->filter[afi][safi];
4711 u_char prefix_type;
4712
4713 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4714 prefix_type = ORF_TYPE_PREFIX;
4715 else
4716 prefix_type = ORF_TYPE_PREFIX_OLD;
4717
4718 if (filter->plist[FILTER_IN].plist)
4719 {
4720 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4721 bgp_route_refresh_send (peer, afi, safi,
4722 prefix_type, REFRESH_DEFER, 1);
4723 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4724 REFRESH_IMMEDIATE, 0);
4725 }
4726 else
4727 {
4728 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4729 bgp_route_refresh_send (peer, afi, safi,
4730 prefix_type, REFRESH_IMMEDIATE, 1);
4731 else
4732 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4733 }
4734 return 0;
4735 }
4736 }
4737
4738 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4739 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4740 {
4741 /* If neighbor has soft reconfiguration inbound flag.
4742 Use Adj-RIB-In database. */
4743 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4744 bgp_soft_reconfig_in (peer, afi, safi);
4745 else
4746 {
4747 /* If neighbor has route refresh capability, send route refresh
4748 message to the peer. */
4749 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4750 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4751 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4752 else
4753 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4754 }
4755 }
4756 return 0;
4757}
David Lamparter6b0655a2014-06-04 06:53:35 +02004758
paulfd79ac92004-10-13 05:06:08 +00004759/* Display peer uptime.*/
4760/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004761char *
4762peer_uptime (time_t uptime2, char *buf, size_t len)
4763{
4764 time_t uptime1;
4765 struct tm *tm;
4766
4767 /* Check buffer length. */
4768 if (len < BGP_UPTIME_LEN)
4769 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004770 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004771 /* XXX: should return status instead of buf... */
4772 snprintf (buf, len, "<error> ");
4773 return buf;
paul718e3742002-12-13 20:15:29 +00004774 }
4775
4776 /* If there is no connection has been done before print `never'. */
4777 if (uptime2 == 0)
4778 {
4779 snprintf (buf, len, "never ");
4780 return buf;
4781 }
4782
4783 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004784 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004785 uptime1 -= uptime2;
4786 tm = gmtime (&uptime1);
Paul Jakma84c38402015-05-26 15:19:38 +01004787
paul718e3742002-12-13 20:15:29 +00004788 /* Making formatted timer strings. */
4789#define ONE_DAY_SECOND 60*60*24
Paul Jakma84c38402015-05-26 15:19:38 +01004790#define ONE_WEEK_SECOND ONE_DAY_SECOND*7
4791#define ONE_YEAR_SECOND ONE_DAY_SECOND*365
paul718e3742002-12-13 20:15:29 +00004792
4793 if (uptime1 < ONE_DAY_SECOND)
4794 snprintf (buf, len, "%02d:%02d:%02d",
4795 tm->tm_hour, tm->tm_min, tm->tm_sec);
4796 else if (uptime1 < ONE_WEEK_SECOND)
4797 snprintf (buf, len, "%dd%02dh%02dm",
4798 tm->tm_yday, tm->tm_hour, tm->tm_min);
Paul Jakma84c38402015-05-26 15:19:38 +01004799 else if (uptime1 < ONE_YEAR_SECOND)
paul718e3742002-12-13 20:15:29 +00004800 snprintf (buf, len, "%02dw%dd%02dh",
4801 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
Paul Jakma84c38402015-05-26 15:19:38 +01004802 else
4803 snprintf (buf, len, "%02dy%02dw%dd",
4804 tm->tm_year - 70, tm->tm_yday/7,
4805 tm->tm_yday - ((tm->tm_yday/7) * 7));
paul718e3742002-12-13 20:15:29 +00004806 return buf;
4807}
David Lamparter6b0655a2014-06-04 06:53:35 +02004808
paul94f2b392005-06-28 12:44:16 +00004809static void
paul718e3742002-12-13 20:15:29 +00004810bgp_config_write_filter (struct vty *vty, struct peer *peer,
4811 afi_t afi, safi_t safi)
4812{
4813 struct bgp_filter *filter;
4814 struct bgp_filter *gfilter = NULL;
4815 char *addr;
4816 int in = FILTER_IN;
4817 int out = FILTER_OUT;
4818
4819 addr = peer->host;
4820 filter = &peer->filter[afi][safi];
4821 if (peer->af_group[afi][safi])
4822 gfilter = &peer->group->conf->filter[afi][safi];
4823
4824 /* distribute-list. */
4825 if (filter->dlist[in].name)
4826 if (! gfilter || ! gfilter->dlist[in].name
4827 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4828 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4829 filter->dlist[in].name, VTY_NEWLINE);
4830 if (filter->dlist[out].name && ! gfilter)
4831 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4832 filter->dlist[out].name, VTY_NEWLINE);
4833
4834 /* prefix-list. */
4835 if (filter->plist[in].name)
4836 if (! gfilter || ! gfilter->plist[in].name
4837 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4838 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4839 filter->plist[in].name, VTY_NEWLINE);
4840 if (filter->plist[out].name && ! gfilter)
4841 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4842 filter->plist[out].name, VTY_NEWLINE);
4843
4844 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004845 if (filter->map[RMAP_IN].name)
4846 if (! gfilter || ! gfilter->map[RMAP_IN].name
4847 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004848 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004849 filter->map[RMAP_IN].name, VTY_NEWLINE);
4850 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004851 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004852 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4853 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4854 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4855 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4856 if (filter->map[RMAP_EXPORT].name)
4857 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4858 || strcmp (filter->map[RMAP_EXPORT].name,
4859 gfilter->map[RMAP_EXPORT].name) != 0)
4860 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4861 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004862
4863 /* unsuppress-map */
4864 if (filter->usmap.name && ! gfilter)
4865 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4866 filter->usmap.name, VTY_NEWLINE);
4867
4868 /* filter-list. */
4869 if (filter->aslist[in].name)
4870 if (! gfilter || ! gfilter->aslist[in].name
4871 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4872 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4873 filter->aslist[in].name, VTY_NEWLINE);
4874 if (filter->aslist[out].name && ! gfilter)
4875 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4876 filter->aslist[out].name, VTY_NEWLINE);
4877}
4878
4879/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004880static void
paul718e3742002-12-13 20:15:29 +00004881bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4882 struct peer *peer, afi_t afi, safi_t safi)
4883{
paul718e3742002-12-13 20:15:29 +00004884 struct peer *g_peer = NULL;
4885 char buf[SU_ADDRSTRLEN];
4886 char *addr;
4887
paul718e3742002-12-13 20:15:29 +00004888 addr = peer->host;
4889 if (peer_group_active (peer))
4890 g_peer = peer->group->conf;
4891
4892 /************************************
4893 ****** Global to the neighbor ******
4894 ************************************/
4895 if (afi == AFI_IP && safi == SAFI_UNICAST)
4896 {
4897 /* remote-as. */
4898 if (! peer_group_active (peer))
4899 {
4900 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4901 vty_out (vty, " neighbor %s peer-group%s", addr,
4902 VTY_NEWLINE);
4903 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004904 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004905 VTY_NEWLINE);
4906 }
4907 else
4908 {
4909 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004910 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004911 VTY_NEWLINE);
4912 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4913 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4914 peer->group->name, VTY_NEWLINE);
4915 }
4916
4917 /* local-as. */
4918 if (peer->change_local_as)
4919 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00004920 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004921 peer->change_local_as,
4922 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00004923 " no-prepend" : "",
4924 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
4925 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004926
4927 /* Description. */
4928 if (peer->desc)
4929 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4930 VTY_NEWLINE);
4931
4932 /* Shutdown. */
4933 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4934 if (! peer_group_active (peer) ||
4935 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4936 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4937
Paul Jakma0df7c912008-07-21 21:02:49 +00004938 /* Password. */
4939 if (peer->password)
4940 if (!peer_group_active (peer)
4941 || ! g_peer->password
4942 || strcmp (peer->password, g_peer->password) != 0)
4943 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4944 VTY_NEWLINE);
4945
paul718e3742002-12-13 20:15:29 +00004946 /* BGP port. */
4947 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004948 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004949 VTY_NEWLINE);
4950
4951 /* Local interface name. */
4952 if (peer->ifname)
4953 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4954 VTY_NEWLINE);
4955
4956 /* Passive. */
4957 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4958 if (! peer_group_active (peer) ||
4959 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4960 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4961
Timo Teräse3443a22016-10-19 16:02:34 +03004962 /* TTL option */
4963 if (peer->gtsm_hops && ! peer_group_active (peer))
4964 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
4965 peer->gtsm_hops, VTY_NEWLINE);
4966 else if (peer->ttl && ! peer_group_active (peer))
4967 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4968 VTY_NEWLINE);
Nick Hilliardfa411a22011-03-23 15:33:17 +00004969
hasso6ffd2072005-02-02 14:50:11 +00004970 /* disable-connected-check. */
4971 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004972 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004973 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4974 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004975
4976 /* Update-source. */
4977 if (peer->update_if)
4978 if (! peer_group_active (peer) || ! g_peer->update_if
4979 || strcmp (g_peer->update_if, peer->update_if) != 0)
4980 vty_out (vty, " neighbor %s update-source %s%s", addr,
4981 peer->update_if, VTY_NEWLINE);
4982 if (peer->update_source)
4983 if (! peer_group_active (peer) || ! g_peer->update_source
4984 || sockunion_cmp (g_peer->update_source,
4985 peer->update_source) != 0)
4986 vty_out (vty, " neighbor %s update-source %s%s", addr,
4987 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4988 VTY_NEWLINE);
4989
paul718e3742002-12-13 20:15:29 +00004990 /* advertisement-interval */
Daniel Walton0d7435f2015-10-22 11:35:20 +03004991 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV) &&
4992 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00004993 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4994 addr, peer->v_routeadv, VTY_NEWLINE);
4995
4996 /* timers. */
4997 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4998 && ! peer_group_active (peer))
4999 vty_out (vty, " neighbor %s timers %d %d%s", addr,
5000 peer->keepalive, peer->holdtime, VTY_NEWLINE);
5001
Daniel Walton0d7435f2015-10-22 11:35:20 +03005002 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT) &&
5003 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00005004 vty_out (vty, " neighbor %s timers connect %d%s", addr,
5005 peer->connect, VTY_NEWLINE);
5006
5007 /* Default weight. */
5008 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
5009 if (! peer_group_active (peer) ||
5010 g_peer->weight != peer->weight)
5011 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
5012 VTY_NEWLINE);
5013
paul718e3742002-12-13 20:15:29 +00005014 /* Dynamic capability. */
5015 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5016 if (! peer_group_active (peer) ||
5017 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5018 vty_out (vty, " neighbor %s capability dynamic%s", addr,
5019 VTY_NEWLINE);
5020
5021 /* dont capability negotiation. */
5022 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
5023 if (! peer_group_active (peer) ||
5024 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
5025 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
5026 VTY_NEWLINE);
5027
5028 /* override capability negotiation. */
5029 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5030 if (! peer_group_active (peer) ||
5031 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5032 vty_out (vty, " neighbor %s override-capability%s", addr,
5033 VTY_NEWLINE);
5034
5035 /* strict capability negotiation. */
5036 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5037 if (! peer_group_active (peer) ||
5038 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5039 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
5040 VTY_NEWLINE);
5041
Christian Franke15c71342012-11-19 11:17:31 +00005042 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
paul718e3742002-12-13 20:15:29 +00005043 {
5044 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5045 {
5046 if (peer->afc[AFI_IP][SAFI_UNICAST])
5047 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5048 }
5049 else
5050 {
5051 if (! peer->afc[AFI_IP][SAFI_UNICAST])
5052 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
5053 }
5054 }
5055 }
5056
5057
5058 /************************************
5059 ****** Per AF to the neighbor ******
5060 ************************************/
5061
5062 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
5063 {
5064 if (peer->af_group[afi][safi])
5065 vty_out (vty, " neighbor %s peer-group %s%s", addr,
5066 peer->group->name, VTY_NEWLINE);
5067 else
5068 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5069 }
5070
5071 /* ORF capability. */
5072 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5073 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5074 if (! peer->af_group[afi][safi])
5075 {
5076 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
5077
5078 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5079 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5080 vty_out (vty, " both");
5081 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
5082 vty_out (vty, " send");
5083 else
5084 vty_out (vty, " receive");
5085 vty_out (vty, "%s", VTY_NEWLINE);
5086 }
5087
5088 /* Route reflector client. */
5089 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
5090 && ! peer->af_group[afi][safi])
5091 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
5092 VTY_NEWLINE);
5093
5094 /* Nexthop self. */
5095 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
5096 && ! peer->af_group[afi][safi])
Timo Teräs9e7a53c2014-04-24 10:22:37 +03005097 vty_out (vty, " neighbor %s next-hop-self%s%s", addr,
5098 peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ?
5099 " all" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005100
5101 /* Remove private AS. */
5102 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
5103 && ! peer->af_group[afi][safi])
5104 vty_out (vty, " neighbor %s remove-private-AS%s",
5105 addr, VTY_NEWLINE);
5106
5107 /* send-community print. */
5108 if (! peer->af_group[afi][safi])
5109 {
5110 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5111 {
5112 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5113 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5114 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
5115 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5116 vty_out (vty, " neighbor %s send-community extended%s",
5117 addr, VTY_NEWLINE);
5118 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5119 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
5120 }
5121 else
5122 {
5123 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5124 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5125 vty_out (vty, " no neighbor %s send-community both%s",
5126 addr, VTY_NEWLINE);
5127 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5128 vty_out (vty, " no neighbor %s send-community extended%s",
5129 addr, VTY_NEWLINE);
5130 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5131 vty_out (vty, " no neighbor %s send-community%s",
5132 addr, VTY_NEWLINE);
5133 }
5134 }
5135
5136 /* Default information */
5137 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5138 && ! peer->af_group[afi][safi])
5139 {
5140 vty_out (vty, " neighbor %s default-originate", addr);
5141 if (peer->default_rmap[afi][safi].name)
5142 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5143 vty_out (vty, "%s", VTY_NEWLINE);
5144 }
5145
5146 /* Soft reconfiguration inbound. */
5147 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5148 if (! peer->af_group[afi][safi] ||
5149 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5150 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5151 VTY_NEWLINE);
5152
5153 /* maximum-prefix. */
5154 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5155 if (! peer->af_group[afi][safi]
5156 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005157 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005158 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5159 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005160 {
hasso0a486e52005-02-01 20:57:17 +00005161 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5162 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5163 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5164 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5165 vty_out (vty, " warning-only");
5166 if (peer->pmax_restart[afi][safi])
5167 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5168 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005169 }
paul718e3742002-12-13 20:15:29 +00005170
5171 /* Route server client. */
5172 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5173 && ! peer->af_group[afi][safi])
5174 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5175
Dylan Hall3cf12882011-10-27 15:28:17 +04005176 /* Nexthop-local unchanged. */
5177 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5178 && ! peer->af_group[afi][safi])
5179 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5180
paul718e3742002-12-13 20:15:29 +00005181 /* Allow AS in. */
5182 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5183 if (! peer_group_active (peer)
5184 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5185 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5186 {
5187 if (peer->allowas_in[afi][safi] == 3)
5188 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5189 else
5190 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5191 peer->allowas_in[afi][safi], VTY_NEWLINE);
5192 }
5193
5194 /* Filter. */
5195 bgp_config_write_filter (vty, peer, afi, safi);
5196
5197 /* atribute-unchanged. */
5198 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5199 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5200 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5201 && ! peer->af_group[afi][safi])
5202 {
5203 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5204 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5205 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5206 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5207 else
5208 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5209 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5210 " as-path" : "",
5211 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5212 " next-hop" : "",
5213 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5214 " med" : "", VTY_NEWLINE);
5215 }
5216}
5217
5218/* Display "address-family" configuration header. */
5219void
5220bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5221 int *write)
5222{
5223 if (*write)
5224 return;
5225
5226 if (afi == AFI_IP && safi == SAFI_UNICAST)
5227 return;
5228
5229 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5230
5231 if (afi == AFI_IP)
5232 {
5233 if (safi == SAFI_MULTICAST)
5234 vty_out (vty, "ipv4 multicast");
5235 else if (safi == SAFI_MPLS_VPN)
Lou Bergera3fda882016-01-12 13:42:04 -05005236 vty_out (vty, "vpnv4");
5237 else if (safi == SAFI_ENCAP)
5238 vty_out (vty, "encap");
paul718e3742002-12-13 20:15:29 +00005239 }
5240 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005241 {
Lou Berger13c378d2016-01-12 13:41:56 -05005242 if (safi == SAFI_MPLS_VPN)
5243 vty_out (vty, "vpnv6");
Lou Bergera3fda882016-01-12 13:42:04 -05005244 else if (safi == SAFI_ENCAP)
5245 vty_out (vty, "encapv6");
Lou Berger13c378d2016-01-12 13:41:56 -05005246 else
5247 {
5248 vty_out (vty, "ipv6");
5249 if (safi == SAFI_MULTICAST)
5250 vty_out (vty, " multicast");
5251 }
Paul Jakma37a217a2007-04-10 19:20:29 +00005252 }
paul718e3742002-12-13 20:15:29 +00005253
5254 vty_out (vty, "%s", VTY_NEWLINE);
5255
5256 *write = 1;
5257}
5258
5259/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005260static int
paul718e3742002-12-13 20:15:29 +00005261bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5262 safi_t safi)
5263{
5264 int write = 0;
5265 struct peer *peer;
5266 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005267 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005268
5269 bgp_config_write_network (vty, bgp, afi, safi, &write);
5270
5271 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5272
paul1eb8ef22005-04-07 07:30:20 +00005273 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005274 {
5275 if (group->conf->afc[afi][safi])
5276 {
5277 bgp_config_write_family_header (vty, afi, safi, &write);
5278 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5279 }
5280 }
paul1eb8ef22005-04-07 07:30:20 +00005281 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005282 {
5283 if (peer->afc[afi][safi])
5284 {
5285 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5286 {
5287 bgp_config_write_family_header (vty, afi, safi, &write);
5288 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5289 }
5290 }
5291 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005292
5293 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5294
Roman Hoog Antink6184c392014-03-17 14:01:42 +01005295 bgp_config_write_distance (vty, bgp, afi, safi, &write);
5296
paul718e3742002-12-13 20:15:29 +00005297 if (write)
5298 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5299
5300 return write;
5301}
5302
5303int
5304bgp_config_write (struct vty *vty)
5305{
5306 int write = 0;
5307 struct bgp *bgp;
5308 struct peer_group *group;
5309 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005310 struct listnode *node, *nnode;
5311 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005312
5313 /* BGP Multiple instance. */
5314 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5315 {
5316 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5317 write++;
5318 }
5319
5320 /* BGP Config type. */
5321 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5322 {
5323 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5324 write++;
5325 }
5326
5327 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005328 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005329 {
5330 if (write)
5331 vty_out (vty, "!%s", VTY_NEWLINE);
5332
5333 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005334 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005335
5336 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5337 {
5338 if (bgp->name)
5339 vty_out (vty, " view %s", bgp->name);
5340 }
5341 vty_out (vty, "%s", VTY_NEWLINE);
5342
5343 /* No Synchronization */
5344 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5345 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5346
5347 /* BGP fast-external-failover. */
5348 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5349 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5350
5351 /* BGP router ID. */
5352 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5353 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5354 VTY_NEWLINE);
5355
paul848973c2003-08-13 00:32:49 +00005356 /* BGP log-neighbor-changes. */
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07005357 if (!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5358 vty_out (vty, " no bgp log-neighbor-changes%s", VTY_NEWLINE);
paul848973c2003-08-13 00:32:49 +00005359
paul718e3742002-12-13 20:15:29 +00005360 /* BGP configuration. */
5361 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5362 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5363
5364 /* BGP default ipv4-unicast. */
5365 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5366 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5367
5368 /* BGP default local-preference. */
5369 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5370 vty_out (vty, " bgp default local-preference %d%s",
5371 bgp->default_local_pref, VTY_NEWLINE);
5372
5373 /* BGP client-to-client reflection. */
5374 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5375 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5376
5377 /* BGP cluster ID. */
5378 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5379 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5380 VTY_NEWLINE);
5381
hassoe0701b72004-05-20 09:19:34 +00005382 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005383 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005384 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5385 VTY_NEWLINE);
5386
5387 /* Confederation peer */
5388 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005389 {
hassoe0701b72004-05-20 09:19:34 +00005390 int i;
paul718e3742002-12-13 20:15:29 +00005391
hassoe0701b72004-05-20 09:19:34 +00005392 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005393
hassoe0701b72004-05-20 09:19:34 +00005394 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005395 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005396
hassoe0701b72004-05-20 09:19:34 +00005397 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005398 }
5399
5400 /* BGP enforce-first-as. */
5401 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5402 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5403
5404 /* BGP deterministic-med. */
5405 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5406 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005407
5408 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005409 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5410 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5411 bgp->stalepath_time, VTY_NEWLINE);
Philippe Guibert4afa3dd2016-05-24 16:52:02 +02005412 if (bgp->restart_time != BGP_DEFAULT_RESTART_TIME)
5413 vty_out (vty, " bgp graceful-restart restart-time %d%s",
5414 bgp->restart_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005415 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5416 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5417
paul718e3742002-12-13 20:15:29 +00005418 /* BGP bestpath method. */
5419 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5420 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005421 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5422 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
Pradosh Mohapatra2fdd4552013-09-07 07:02:36 +00005423 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
5424 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
5425 }
Dinesh Dutt083e5e22015-11-09 20:21:54 -05005426 if (bgp_flag_check (bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
5427 vty_out (vty, " bgp route-reflector allow-outbound-policy%s",
5428 VTY_NEWLINE);
5429 }
paul718e3742002-12-13 20:15:29 +00005430 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5431 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5432 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5433 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5434 {
5435 vty_out (vty, " bgp bestpath med");
5436 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5437 vty_out (vty, " confed");
5438 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5439 vty_out (vty, " missing-as-worst");
5440 vty_out (vty, "%s", VTY_NEWLINE);
5441 }
5442
5443 /* BGP network import check. */
5444 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5445 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5446
paul718e3742002-12-13 20:15:29 +00005447 /* BGP flag dampening. */
5448 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5449 BGP_CONFIG_DAMPENING))
5450 bgp_config_write_damp (vty);
5451
5452 /* BGP static route configuration. */
5453 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5454
5455 /* BGP redistribute configuration. */
5456 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5457
5458 /* BGP timers configuration. */
5459 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5460 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5461 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5462 bgp->default_holdtime, VTY_NEWLINE);
5463
5464 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005465 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005466 {
5467 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5468 }
5469
5470 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005471 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005472 {
5473 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5474 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5475 }
5476
Josh Bailey165b5ff2011-07-20 20:43:22 -07005477 /* maximum-paths */
5478 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5479
paul718e3742002-12-13 20:15:29 +00005480 /* Distance configuration. */
Roman Hoog Antink6184c392014-03-17 14:01:42 +01005481 bgp_config_write_distance (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
paul718e3742002-12-13 20:15:29 +00005482
5483 /* No auto-summary */
5484 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5485 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5486
5487 /* IPv4 multicast configuration. */
5488 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5489
5490 /* IPv4 VPN configuration. */
5491 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5492
Lou Bergera3fda882016-01-12 13:42:04 -05005493 /* ENCAPv4 configuration. */
5494 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_ENCAP);
5495
paul718e3742002-12-13 20:15:29 +00005496 /* IPv6 unicast configuration. */
5497 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5498
Paul Jakma37a217a2007-04-10 19:20:29 +00005499 /* IPv6 multicast configuration. */
5500 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5501
Lou Berger13c378d2016-01-12 13:41:56 -05005502 /* IPv6 VPN configuration. */
5503 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MPLS_VPN);
5504
Lou Bergera3fda882016-01-12 13:42:04 -05005505 /* ENCAPv6 configuration. */
5506 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_ENCAP);
5507
5508 vty_out (vty, " exit%s", VTY_NEWLINE);
5509
paul718e3742002-12-13 20:15:29 +00005510 write++;
5511 }
5512 return write;
5513}
5514
5515void
paul94f2b392005-06-28 12:44:16 +00005516bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005517{
5518 memset (&bgp_master, 0, sizeof (struct bgp_master));
5519
5520 bm = &bgp_master;
5521 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005522 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005523 bm->port = BGP_PORT_DEFAULT;
5524 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005525 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005526}
paul200df112005-06-01 11:17:05 +00005527
David Lamparter6b0655a2014-06-04 06:53:35 +02005528
paul718e3742002-12-13 20:15:29 +00005529void
paul94f2b392005-06-28 12:44:16 +00005530bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005531{
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07005532
5533 /* allocates some vital data structures used by peer commands in vty_init */
5534 bgp_scan_init ();
paul718e3742002-12-13 20:15:29 +00005535
paul718e3742002-12-13 20:15:29 +00005536 /* Init zebra. */
Donald Sharp774914f2015-10-14 08:50:39 -04005537 bgp_zebra_init (bm->master);
paul718e3742002-12-13 20:15:29 +00005538
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07005539 /* BGP VTY commands installation. */
5540 bgp_vty_init ();
5541
paul718e3742002-12-13 20:15:29 +00005542 /* BGP inits. */
5543 bgp_attr_init ();
5544 bgp_debug_init ();
5545 bgp_dump_init ();
5546 bgp_route_init ();
5547 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005548 bgp_address_init ();
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07005549 bgp_scan_vty_init();
paul718e3742002-12-13 20:15:29 +00005550 bgp_mplsvpn_init ();
Lou Berger298cc2f2016-01-12 13:42:02 -05005551 bgp_encap_init ();
paul718e3742002-12-13 20:15:29 +00005552
5553 /* Access list initialize. */
5554 access_list_init ();
5555 access_list_add_hook (peer_distribute_update);
5556 access_list_delete_hook (peer_distribute_update);
5557
5558 /* Filter list initialize. */
5559 bgp_filter_init ();
5560 as_list_add_hook (peer_aslist_update);
5561 as_list_delete_hook (peer_aslist_update);
5562
5563 /* Prefix list initialize.*/
5564 prefix_list_init ();
5565 prefix_list_add_hook (peer_prefix_list_update);
5566 prefix_list_delete_hook (peer_prefix_list_update);
5567
5568 /* Community list initialize. */
5569 bgp_clist = community_list_init ();
5570
5571#ifdef HAVE_SNMP
5572 bgp_snmp_init ();
5573#endif /* HAVE_SNMP */
5574}
paul545acaf2004-04-20 15:13:15 +00005575
5576void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005577bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005578{
paul545acaf2004-04-20 15:13:15 +00005579 struct bgp *bgp;
5580 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005581 struct listnode *node, *nnode;
5582 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005583
paul1eb8ef22005-04-07 07:30:20 +00005584 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5585 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005586 if (peer->status == Established)
5587 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5588 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005589
paul545acaf2004-04-20 15:13:15 +00005590 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005591
paule210cf92005-06-15 19:15:35 +00005592 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005593 {
5594 work_queue_free (bm->process_main_queue);
5595 bm->process_main_queue = NULL;
5596 }
paule210cf92005-06-15 19:15:35 +00005597 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005598 {
5599 work_queue_free (bm->process_rsclient_queue);
5600 bm->process_rsclient_queue = NULL;
5601 }
paul545acaf2004-04-20 15:13:15 +00005602}