blob: 69ab7da637d711b5d5059879198016a4b061ca02 [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
Paul Jakmaca058a32006-09-14 02:58:49 +0000739 /* this /ought/ to have been done already through bgp_stop earlier,
740 * but just to be sure..
741 */
742 bgp_timer_set (peer);
743 BGP_READ_OFF (peer->t_read);
744 BGP_WRITE_OFF (peer->t_write);
Paul Jakma9fde6622006-09-14 03:02:02 +0000745 BGP_EVENT_FLUSH (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +0000746
paul200df112005-06-01 11:17:05 +0000747 if (peer->desc)
Daniel Walton363c9032015-10-21 06:42:54 -0700748 {
749 XFREE (MTYPE_PEER_DESC, peer->desc);
750 peer->desc = NULL;
751 }
paul200df112005-06-01 11:17:05 +0000752
753 /* Free allocated host character. */
754 if (peer->host)
Daniel Walton363c9032015-10-21 06:42:54 -0700755 {
756 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
757 peer->host = NULL;
758 }
759
paul200df112005-06-01 11:17:05 +0000760 /* Update source configuration. */
761 if (peer->update_source)
Daniel Walton363c9032015-10-21 06:42:54 -0700762 {
763 sockunion_free (peer->update_source);
764 peer->update_source = NULL;
765 }
paul200df112005-06-01 11:17:05 +0000766
767 if (peer->update_if)
Daniel Walton363c9032015-10-21 06:42:54 -0700768 {
769 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
770 peer->update_if = NULL;
771 }
Paul Jakmaa625ca32006-03-30 14:12:38 +0000772
773 if (peer->clear_node_queue)
Daniel Walton363c9032015-10-21 06:42:54 -0700774 {
775 work_queue_free(peer->clear_node_queue);
776 peer->clear_node_queue = NULL;
777 }
Paul Jakmaa625ca32006-03-30 14:12:38 +0000778
Lou Berger056f3762013-04-10 12:30:04 -0700779 if (peer->notify.data)
780 XFREE(MTYPE_TMP, peer->notify.data);
781
Paul Jakmaca058a32006-09-14 02:58:49 +0000782 bgp_sync_delete (peer);
Renato Westphal670f3db2016-11-28 16:47:13 -0200783
784 bgp_unlock(peer->bgp);
785
paul200df112005-06-01 11:17:05 +0000786 memset (peer, 0, sizeof (struct peer));
787
788 XFREE (MTYPE_BGP_PEER, peer);
789}
790
791/* increase reference count on a struct peer */
792struct peer *
Donald Sharp104576d2015-09-16 13:17:55 -0400793peer_lock_with_caller (const char *name, struct peer *peer)
paul200df112005-06-01 11:17:05 +0000794{
795 assert (peer && (peer->lock >= 0));
Donald Sharp104576d2015-09-16 13:17:55 -0400796
797#if 0
798 zlog_debug("%s peer_lock %p %d", name, peer, peer->lock);
799#endif
800
paul200df112005-06-01 11:17:05 +0000801 peer->lock++;
802
803 return peer;
804}
805
806/* decrease reference count on a struct peer
807 * struct peer is freed and NULL returned if last reference
808 */
809struct peer *
Donald Sharp104576d2015-09-16 13:17:55 -0400810peer_unlock_with_caller (const char *name, struct peer *peer)
paul200df112005-06-01 11:17:05 +0000811{
812 assert (peer && (peer->lock > 0));
Donald Sharp104576d2015-09-16 13:17:55 -0400813
814#if 0
815 zlog_debug("%s peer_unlock %p %d", name, peer, peer->lock);
816#endif
817
paul200df112005-06-01 11:17:05 +0000818 peer->lock--;
819
820 if (peer->lock == 0)
821 {
paul200df112005-06-01 11:17:05 +0000822 peer_free (peer);
823 return NULL;
824 }
825
paul200df112005-06-01 11:17:05 +0000826 return peer;
827}
828
829/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000830static struct peer *
Paul Jakma6f585442006-10-22 19:13:07 +0000831peer_new (struct bgp *bgp)
paul718e3742002-12-13 20:15:29 +0000832{
833 afi_t afi;
834 safi_t safi;
835 struct peer *peer;
836 struct servent *sp;
Paul Jakma6f585442006-10-22 19:13:07 +0000837
838 /* bgp argument is absolutely required */
839 assert (bgp);
840 if (!bgp)
841 return NULL;
842
paul718e3742002-12-13 20:15:29 +0000843 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000844 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000845
846 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000847 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000848 peer->v_start = BGP_INIT_START_TIMER;
849 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
paul718e3742002-12-13 20:15:29 +0000850 peer->status = Idle;
851 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000852 peer->weight = 0;
Paul Jakma0df7c912008-07-21 21:02:49 +0000853 peer->password = NULL;
Paul Jakma6f585442006-10-22 19:13:07 +0000854 peer->bgp = bgp;
Paul Jakmaca058a32006-09-14 02:58:49 +0000855 peer = peer_lock (peer); /* initial reference */
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700856 bgp_lock (bgp);
paul718e3742002-12-13 20:15:29 +0000857
858 /* Set default flags. */
859 for (afi = AFI_IP; afi < AFI_MAX; afi++)
860 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
861 {
862 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
863 {
864 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
865 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
866 }
867 peer->orf_plist[afi][safi] = NULL;
868 }
869 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
870
871 /* Create buffers. */
872 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
873 peer->obuf = stream_fifo_new ();
Daniel Walton5bcd7542015-05-19 17:58:10 -0700874
875 /* We use a larger buffer for peer->work in the event that:
876 * - We RX a BGP_UPDATE where the attributes alone are just
877 * under BGP_MAX_PACKET_SIZE
878 * - The user configures an outbound route-map that does many as-path
879 * prepends or adds many communities. At most they can have CMD_ARGC_MAX
880 * args in a route-map so there is a finite limit on how large they can
881 * make the attributes.
882 *
883 * Having a buffer with BGP_MAX_PACKET_SIZE_OVERFLOW allows us to avoid bounds
884 * checking for every single attribute as we construct an UPDATE.
885 */
886 peer->work = stream_new (BGP_MAX_PACKET_SIZE + BGP_MAX_PACKET_SIZE_OVERFLOW);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000887 peer->scratch = stream_new (BGP_MAX_PACKET_SIZE);
paul718e3742002-12-13 20:15:29 +0000888
889 bgp_sync_init (peer);
890
891 /* Get service port number. */
892 sp = getservbyname ("bgp", "tcp");
893 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
894
895 return peer;
896}
897
898/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000899static struct peer *
paul718e3742002-12-13 20:15:29 +0000900peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
901 as_t remote_as, afi_t afi, safi_t safi)
902{
903 int active;
904 struct peer *peer;
905 char buf[SU_ADDRSTRLEN];
906
Paul Jakma6f585442006-10-22 19:13:07 +0000907 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000908 peer->su = *su;
909 peer->local_as = local_as;
910 peer->as = remote_as;
911 peer->local_id = bgp->router_id;
912 peer->v_holdtime = bgp->default_holdtime;
913 peer->v_keepalive = bgp->default_keepalive;
914 if (peer_sort (peer) == BGP_PEER_IBGP)
915 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
916 else
917 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000918
919 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000920 listnode_add_sort (bgp->peer, peer);
921
922 active = peer_active (peer);
923
924 if (afi && safi)
925 peer->afc[afi][safi] = 1;
926
Stephen Hemminger65957882010-01-15 16:22:10 +0300927 /* Last read and reset time set */
928 peer->readtime = peer->resettime = bgp_clock ();
paul848973c2003-08-13 00:32:49 +0000929
paul718e3742002-12-13 20:15:29 +0000930 /* Make peer's address string. */
931 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000932 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000933
934 /* Set up peer's events and timers. */
935 if (! active && peer_active (peer))
936 bgp_timer_set (peer);
937
938 return peer;
939}
940
pauleb821182004-05-01 08:44:08 +0000941/* Make accept BGP peer. Called from bgp_accept (). */
942struct peer *
943peer_create_accept (struct bgp *bgp)
944{
945 struct peer *peer;
946
Paul Jakma6f585442006-10-22 19:13:07 +0000947 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000948
949 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000950 listnode_add_sort (bgp->peer, peer);
951
952 return peer;
953}
954
paul718e3742002-12-13 20:15:29 +0000955/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000956static void
paul718e3742002-12-13 20:15:29 +0000957peer_as_change (struct peer *peer, as_t as)
958{
Daniel Walton0d7435f2015-10-22 11:35:20 +0300959 struct peer *conf;
paul718e3742002-12-13 20:15:29 +0000960
961 /* Stop peer. */
962 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
963 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000964 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000965 {
966 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
967 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
968 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
969 }
paul718e3742002-12-13 20:15:29 +0000970 else
971 BGP_EVENT_ADD (peer, BGP_Stop);
972 }
paul718e3742002-12-13 20:15:29 +0000973 peer->as = as;
974
paul848973c2003-08-13 00:32:49 +0000975 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
976 && ! bgp_confederation_peers_check (peer->bgp, as)
977 && peer->bgp->as != as)
978 peer->local_as = peer->bgp->confed_id;
979 else
980 peer->local_as = peer->bgp->as;
981
paul718e3742002-12-13 20:15:29 +0000982 /* Advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +0300983 conf = NULL;
984 if (peer->group)
985 conf = peer->group->conf;
986
987 if (conf && CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
988 peer->v_routeadv = conf->routeadv;
paul718e3742002-12-13 20:15:29 +0000989 else
Daniel Walton0d7435f2015-10-22 11:35:20 +0300990 if (peer_sort (peer) == BGP_PEER_IBGP)
991 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
992 else
993 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul718e3742002-12-13 20:15:29 +0000994
paul718e3742002-12-13 20:15:29 +0000995 /* reflector-client reset */
996 if (peer_sort (peer) != BGP_PEER_IBGP)
997 {
998 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
999 PEER_FLAG_REFLECTOR_CLIENT);
1000 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
1001 PEER_FLAG_REFLECTOR_CLIENT);
1002 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
1003 PEER_FLAG_REFLECTOR_CLIENT);
Lou Berger298cc2f2016-01-12 13:42:02 -05001004 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_ENCAP],
1005 PEER_FLAG_REFLECTOR_CLIENT);
paul718e3742002-12-13 20:15:29 +00001006 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
1007 PEER_FLAG_REFLECTOR_CLIENT);
1008 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
1009 PEER_FLAG_REFLECTOR_CLIENT);
Lou Berger9da04bc2016-01-12 13:41:55 -05001010 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MPLS_VPN],
1011 PEER_FLAG_REFLECTOR_CLIENT);
Lou Berger298cc2f2016-01-12 13:42:02 -05001012 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_ENCAP],
1013 PEER_FLAG_REFLECTOR_CLIENT);
paul718e3742002-12-13 20:15:29 +00001014 }
1015
1016 /* local-as reset */
1017 if (peer_sort (peer) != BGP_PEER_EBGP)
1018 {
1019 peer->change_local_as = 0;
1020 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001021 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001022 }
1023}
1024
1025/* If peer does not exist, create new one. If peer already exists,
1026 set AS number to the peer. */
1027int
1028peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
1029 afi_t afi, safi_t safi)
1030{
1031 struct peer *peer;
1032 as_t local_as;
1033
1034 peer = peer_lookup (bgp, su);
1035
1036 if (peer)
1037 {
1038 /* When this peer is a member of peer-group. */
1039 if (peer->group)
1040 {
1041 if (peer->group->conf->as)
1042 {
1043 /* Return peer group's AS number. */
1044 *as = peer->group->conf->as;
1045 return BGP_ERR_PEER_GROUP_MEMBER;
1046 }
1047 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
1048 {
1049 if (bgp->as != *as)
1050 {
1051 *as = peer->as;
1052 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1053 }
1054 }
1055 else
1056 {
1057 if (bgp->as == *as)
1058 {
1059 *as = peer->as;
1060 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1061 }
1062 }
1063 }
1064
1065 /* Existing peer's AS number change. */
1066 if (peer->as != *as)
1067 peer_as_change (peer, *as);
1068 }
1069 else
1070 {
1071
1072 /* If the peer is not part of our confederation, and its not an
1073 iBGP peer then spoof the source AS */
1074 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1075 && ! bgp_confederation_peers_check (bgp, *as)
1076 && bgp->as != *as)
1077 local_as = bgp->confed_id;
1078 else
1079 local_as = bgp->as;
1080
1081 /* If this is IPv4 unicast configuration and "no bgp default
1082 ipv4-unicast" is specified. */
1083
1084 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1085 && afi == AFI_IP && safi == SAFI_UNICAST)
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001086 peer_create (su, bgp, local_as, *as, 0, 0);
paul718e3742002-12-13 20:15:29 +00001087 else
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001088 peer_create (su, bgp, local_as, *as, afi, safi);
paul718e3742002-12-13 20:15:29 +00001089 }
1090
1091 return 0;
1092}
1093
1094/* Activate the peer or peer group for specified AFI and SAFI. */
1095int
1096peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1097{
1098 int active;
1099
1100 if (peer->afc[afi][safi])
1101 return 0;
1102
1103 /* Activate the address family configuration. */
1104 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1105 peer->afc[afi][safi] = 1;
1106 else
1107 {
1108 active = peer_active (peer);
1109
1110 peer->afc[afi][safi] = 1;
1111
1112 if (! active && peer_active (peer))
1113 bgp_timer_set (peer);
1114 else
1115 {
1116 if (peer->status == Established)
1117 {
1118 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1119 {
1120 peer->afc_adv[afi][safi] = 1;
1121 bgp_capability_send (peer, afi, safi,
1122 CAPABILITY_CODE_MP,
1123 CAPABILITY_ACTION_SET);
1124 if (peer->afc_recv[afi][safi])
1125 {
1126 peer->afc_nego[afi][safi] = 1;
1127 bgp_announce_route (peer, afi, safi);
1128 }
1129 }
1130 else
hassoe0701b72004-05-20 09:19:34 +00001131 {
1132 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1133 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1134 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1135 }
paul718e3742002-12-13 20:15:29 +00001136 }
1137 }
1138 }
1139 return 0;
1140}
1141
1142int
1143peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1144{
1145 struct peer_group *group;
1146 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001147 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001148
1149 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1150 {
1151 group = peer->group;
1152
paul1eb8ef22005-04-07 07:30:20 +00001153 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001154 {
1155 if (peer1->af_group[afi][safi])
1156 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1157 }
1158 }
1159 else
1160 {
1161 if (peer->af_group[afi][safi])
1162 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1163 }
1164
1165 if (! peer->afc[afi][safi])
1166 return 0;
1167
1168 /* De-activate the address family configuration. */
1169 peer->afc[afi][safi] = 0;
1170 peer_af_flag_reset (peer, afi, safi);
1171
1172 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1173 {
1174 if (peer->status == Established)
1175 {
1176 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1177 {
1178 peer->afc_adv[afi][safi] = 0;
1179 peer->afc_nego[afi][safi] = 0;
1180
1181 if (peer_active_nego (peer))
1182 {
1183 bgp_capability_send (peer, afi, safi,
1184 CAPABILITY_CODE_MP,
1185 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001186 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001187 peer->pcount[afi][safi] = 0;
1188 }
1189 else
hassoe0701b72004-05-20 09:19:34 +00001190 {
1191 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1192 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1193 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1194 }
paul718e3742002-12-13 20:15:29 +00001195 }
1196 else
hassoe0701b72004-05-20 09:19:34 +00001197 {
1198 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1199 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1200 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1201 }
paul718e3742002-12-13 20:15:29 +00001202 }
1203 }
1204 return 0;
1205}
1206
David Lamparterdfb9bd72016-05-24 18:58:07 +02001207int
1208peer_afc_set (struct peer *peer, afi_t afi, safi_t safi, int enable)
1209{
1210 if (enable)
1211 return peer_activate (peer, afi, safi);
1212 else
1213 return peer_deactivate (peer, afi, safi);
1214}
1215
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001216static void
hasso93406d82005-02-02 14:40:33 +00001217peer_nsf_stop (struct peer *peer)
1218{
1219 afi_t afi;
1220 safi_t safi;
1221
1222 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1223 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1224
1225 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +04001226 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +00001227 peer->nsf[afi][safi] = 0;
1228
1229 if (peer->t_gr_restart)
1230 {
1231 BGP_TIMER_OFF (peer->t_gr_restart);
1232 if (BGP_DEBUG (events, EVENTS))
1233 zlog_debug ("%s graceful restart timer stopped", peer->host);
1234 }
1235 if (peer->t_gr_stale)
1236 {
1237 BGP_TIMER_OFF (peer->t_gr_stale);
1238 if (BGP_DEBUG (events, EVENTS))
1239 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1240 }
1241 bgp_clear_route_all (peer);
1242}
1243
Paul Jakmaca058a32006-09-14 02:58:49 +00001244/* Delete peer from confguration.
1245 *
1246 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1247 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1248 *
1249 * This function /should/ take care to be idempotent, to guard against
1250 * it being called multiple times through stray events that come in
1251 * that happen to result in this function being called again. That
1252 * said, getting here for a "Deleted" peer is a bug in the neighbour
1253 * FSM.
1254 */
paul718e3742002-12-13 20:15:29 +00001255int
1256peer_delete (struct peer *peer)
1257{
1258 int i;
1259 afi_t afi;
1260 safi_t safi;
1261 struct bgp *bgp;
1262 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001263 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001264
Paul Jakmaca058a32006-09-14 02:58:49 +00001265 assert (peer->status != Deleted);
1266
paul718e3742002-12-13 20:15:29 +00001267 bgp = peer->bgp;
1268
hasso93406d82005-02-02 14:40:33 +00001269 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1270 peer_nsf_stop (peer);
1271
Chris Caputo228da422009-07-18 05:44:03 +00001272 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001273 relationship. */
1274 if (peer->group)
1275 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001276 if ((pn = listnode_lookup (peer->group->peer, peer)))
1277 {
1278 peer = peer_unlock (peer); /* group->peer list reference */
1279 list_delete_node (peer->group->peer, pn);
1280 }
paul718e3742002-12-13 20:15:29 +00001281 peer->group = NULL;
1282 }
paul200df112005-06-01 11:17:05 +00001283
paul718e3742002-12-13 20:15:29 +00001284 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001285 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1286 * executed after peer structure is deleted.
1287 */
hassoe0701b72004-05-20 09:19:34 +00001288 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001289 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001290 bgp_fsm_change_status (peer, Deleted);
Paul Jakma19e6c192016-09-06 17:23:48 +01001291
1292 /* Remove from NHT */
1293 bgp_unlink_nexthop_by_peer (peer);
1294
Paul Jakma0df7c912008-07-21 21:02:49 +00001295 /* Password configuration */
1296 if (peer->password)
1297 {
1298 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1299 peer->password = NULL;
1300
1301 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1302 bgp_md5_set (peer);
1303 }
1304
Paul Jakmaca058a32006-09-14 02:58:49 +00001305 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001306
paul718e3742002-12-13 20:15:29 +00001307 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001308 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1309 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001310 {
Chris Caputo228da422009-07-18 05:44:03 +00001311 peer_unlock (peer); /* bgp peer list reference */
1312 list_delete_node (bgp->peer, pn);
1313 }
paul200df112005-06-01 11:17:05 +00001314
Chris Caputo228da422009-07-18 05:44:03 +00001315 if (peer_rsclient_active (peer)
1316 && (pn = listnode_lookup (bgp->rsclient, peer)))
1317 {
1318 peer_unlock (peer); /* rsclient list reference */
1319 list_delete_node (bgp->rsclient, pn);
1320
1321 /* Clear our own rsclient ribs. */
1322 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1323 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1324 if (CHECK_FLAG(peer->af_flags[afi][safi],
1325 PEER_FLAG_RSERVER_CLIENT))
1326 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001327 }
1328
1329 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1330 member of a peer_group. */
1331 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1332 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1333 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001334 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001335
paul200df112005-06-01 11:17:05 +00001336 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001337 if (peer->ibuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001338 {
1339 stream_free (peer->ibuf);
1340 peer->ibuf = NULL;
1341 }
1342
paul718e3742002-12-13 20:15:29 +00001343 if (peer->obuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001344 {
1345 stream_fifo_free (peer->obuf);
1346 peer->obuf = NULL;
1347 }
1348
paul718e3742002-12-13 20:15:29 +00001349 if (peer->work)
Daniel Walton363c9032015-10-21 06:42:54 -07001350 {
1351 stream_free (peer->work);
1352 peer->work = NULL;
1353 }
1354
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00001355 if (peer->scratch)
Daniel Walton363c9032015-10-21 06:42:54 -07001356 {
1357 stream_free(peer->scratch);
1358 peer->scratch = NULL;
1359 }
Paul Jakma18937402006-07-27 19:05:12 +00001360
paul718e3742002-12-13 20:15:29 +00001361 /* Local and remote addresses. */
1362 if (peer->su_local)
Daniel Walton363c9032015-10-21 06:42:54 -07001363 {
1364 sockunion_free (peer->su_local);
1365 peer->su_local = NULL;
1366 }
1367
paul718e3742002-12-13 20:15:29 +00001368 if (peer->su_remote)
Daniel Walton363c9032015-10-21 06:42:54 -07001369 {
1370 sockunion_free (peer->su_remote);
1371 peer->su_remote = NULL;
1372 }
paul200df112005-06-01 11:17:05 +00001373
paul718e3742002-12-13 20:15:29 +00001374 /* Free filter related memory. */
1375 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1376 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1377 {
1378 filter = &peer->filter[afi][safi];
1379
1380 for (i = FILTER_IN; i < FILTER_MAX; i++)
1381 {
1382 if (filter->dlist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001383 {
1384 free(filter->dlist[i].name);
1385 filter->dlist[i].name = NULL;
1386 }
1387
paul718e3742002-12-13 20:15:29 +00001388 if (filter->plist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001389 {
1390 free(filter->plist[i].name);
1391 filter->plist[i].name = NULL;
1392 }
1393
paul718e3742002-12-13 20:15:29 +00001394 if (filter->aslist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001395 {
1396 free(filter->aslist[i].name);
1397 filter->aslist[i].name = NULL;
1398 }
paul200df112005-06-01 11:17:05 +00001399 }
Daniel Walton363c9032015-10-21 06:42:54 -07001400
paul200df112005-06-01 11:17:05 +00001401 for (i = RMAP_IN; i < RMAP_MAX; i++)
1402 {
paul718e3742002-12-13 20:15:29 +00001403 if (filter->map[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001404 {
1405 free (filter->map[i].name);
1406 filter->map[i].name = NULL;
1407 }
paul718e3742002-12-13 20:15:29 +00001408 }
1409
1410 if (filter->usmap.name)
Daniel Walton363c9032015-10-21 06:42:54 -07001411 {
1412 free (filter->usmap.name);
1413 filter->usmap.name = NULL;
1414 }
paul718e3742002-12-13 20:15:29 +00001415
1416 if (peer->default_rmap[afi][safi].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001417 {
1418 free (peer->default_rmap[afi][safi].name);
1419 peer->default_rmap[afi][safi].name = NULL;
1420 }
paul718e3742002-12-13 20:15:29 +00001421 }
paul200df112005-06-01 11:17:05 +00001422
Lou Berger82dd7072016-01-12 13:41:57 -05001423 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETING))
1424 bgp_peer_clear_node_queue_drain_immediate(peer);
1425
paul200df112005-06-01 11:17:05 +00001426 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001427
1428 return 0;
1429}
David Lamparter6b0655a2014-06-04 06:53:35 +02001430
paul94f2b392005-06-28 12:44:16 +00001431static int
paul718e3742002-12-13 20:15:29 +00001432peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1433{
1434 return strcmp (g1->name, g2->name);
1435}
1436
1437/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001438static int
paul718e3742002-12-13 20:15:29 +00001439peer_group_active (struct peer *peer)
1440{
1441 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1442 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1443 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05001444 || peer->af_group[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00001445 || peer->af_group[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05001446 || peer->af_group[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05001447 || peer->af_group[AFI_IP6][SAFI_MPLS_VPN]
1448 || peer->af_group[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00001449 return 1;
1450 return 0;
1451}
1452
1453/* Peer group cofiguration. */
1454static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001455peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001456{
1457 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1458 sizeof (struct peer_group));
1459}
1460
paul94f2b392005-06-28 12:44:16 +00001461static void
paul718e3742002-12-13 20:15:29 +00001462peer_group_free (struct peer_group *group)
1463{
1464 XFREE (MTYPE_PEER_GROUP, group);
1465}
1466
1467struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001468peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001469{
1470 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001471 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001472
paul1eb8ef22005-04-07 07:30:20 +00001473 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001474 {
1475 if (strcmp (group->name, name) == 0)
1476 return group;
1477 }
1478 return NULL;
1479}
1480
1481struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001482peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001483{
1484 struct peer_group *group;
1485
1486 group = peer_group_lookup (bgp, name);
1487 if (group)
1488 return group;
1489
1490 group = peer_group_new ();
1491 group->bgp = bgp;
1492 group->name = strdup (name);
1493 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001494 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001495 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1496 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001497 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001498 group->conf->group = group;
1499 group->conf->as = 0;
Timo Teräse3443a22016-10-19 16:02:34 +03001500 group->conf->ttl = 0;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001501 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001502 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1503 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1504 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1505 group->conf->keepalive = 0;
1506 group->conf->holdtime = 0;
1507 group->conf->connect = 0;
1508 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1509 listnode_add_sort (bgp->group, group);
1510
1511 return 0;
1512}
1513
paul94f2b392005-06-28 12:44:16 +00001514static void
paul718e3742002-12-13 20:15:29 +00001515peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1516 afi_t afi, safi_t safi)
1517{
1518 int in = FILTER_IN;
1519 int out = FILTER_OUT;
1520 struct peer *conf;
1521 struct bgp_filter *pfilter;
1522 struct bgp_filter *gfilter;
1523
1524 conf = group->conf;
1525 pfilter = &peer->filter[afi][safi];
1526 gfilter = &conf->filter[afi][safi];
1527
1528 /* remote-as */
1529 if (conf->as)
1530 peer->as = conf->as;
1531
1532 /* remote-as */
1533 if (conf->change_local_as)
1534 peer->change_local_as = conf->change_local_as;
1535
1536 /* TTL */
1537 peer->ttl = conf->ttl;
1538
Nick Hilliardfa411a22011-03-23 15:33:17 +00001539 /* GTSM hops */
1540 peer->gtsm_hops = conf->gtsm_hops;
1541
paul718e3742002-12-13 20:15:29 +00001542 /* Weight */
1543 peer->weight = conf->weight;
1544
1545 /* peer flags apply */
1546 peer->flags = conf->flags;
1547 /* peer af_flags apply */
1548 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1549 /* peer config apply */
1550 peer->config = conf->config;
1551
1552 /* peer timers apply */
1553 peer->holdtime = conf->holdtime;
1554 peer->keepalive = conf->keepalive;
1555 peer->connect = conf->connect;
1556 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1557 peer->v_connect = conf->connect;
1558 else
1559 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1560
1561 /* advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +03001562 if (CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
1563 peer->v_routeadv = conf->routeadv;
paul718e3742002-12-13 20:15:29 +00001564 else
Daniel Walton0d7435f2015-10-22 11:35:20 +03001565 if (peer_sort (peer) == BGP_PEER_IBGP)
1566 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1567 else
1568 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul718e3742002-12-13 20:15:29 +00001569
Paul Jakma0df7c912008-07-21 21:02:49 +00001570 /* password apply */
Roman Hoog Antink0e4303d2013-01-18 13:52:03 +01001571 if (conf->password && !peer->password)
Paul Jakma0df7c912008-07-21 21:02:49 +00001572 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
Paul Jakma0df7c912008-07-21 21:02:49 +00001573
1574 bgp_md5_set (peer);
1575
paul718e3742002-12-13 20:15:29 +00001576 /* maximum-prefix */
1577 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001578 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001579 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001580
1581 /* allowas-in */
1582 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1583
paulfee0f4c2004-09-13 05:12:46 +00001584 /* route-server-client */
1585 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1586 {
1587 /* Make peer's RIB point to group's RIB. */
1588 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1589
1590 /* Import policy. */
1591 if (pfilter->map[RMAP_IMPORT].name)
1592 free (pfilter->map[RMAP_IMPORT].name);
1593 if (gfilter->map[RMAP_IMPORT].name)
1594 {
1595 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1596 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1597 }
1598 else
1599 {
1600 pfilter->map[RMAP_IMPORT].name = NULL;
1601 pfilter->map[RMAP_IMPORT].map = NULL;
1602 }
1603
1604 /* Export policy. */
1605 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1606 {
1607 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1608 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1609 }
1610 }
1611
paul718e3742002-12-13 20:15:29 +00001612 /* default-originate route-map */
1613 if (conf->default_rmap[afi][safi].name)
1614 {
1615 if (peer->default_rmap[afi][safi].name)
1616 free (peer->default_rmap[afi][safi].name);
1617 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1618 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1619 }
1620
1621 /* update-source apply */
1622 if (conf->update_source)
1623 {
1624 if (peer->update_source)
1625 sockunion_free (peer->update_source);
1626 if (peer->update_if)
1627 {
1628 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1629 peer->update_if = NULL;
1630 }
1631 peer->update_source = sockunion_dup (conf->update_source);
1632 }
1633 else if (conf->update_if)
1634 {
1635 if (peer->update_if)
1636 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1637 if (peer->update_source)
1638 {
1639 sockunion_free (peer->update_source);
1640 peer->update_source = NULL;
1641 }
1642 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1643 }
1644
1645 /* inbound filter apply */
1646 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1647 {
1648 if (pfilter->dlist[in].name)
1649 free (pfilter->dlist[in].name);
1650 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1651 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1652 }
1653 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1654 {
1655 if (pfilter->plist[in].name)
1656 free (pfilter->plist[in].name);
1657 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1658 pfilter->plist[in].plist = gfilter->plist[in].plist;
1659 }
1660 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1661 {
1662 if (pfilter->aslist[in].name)
1663 free (pfilter->aslist[in].name);
1664 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1665 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1666 }
paulfee0f4c2004-09-13 05:12:46 +00001667 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001668 {
paulfee0f4c2004-09-13 05:12:46 +00001669 if (pfilter->map[RMAP_IN].name)
1670 free (pfilter->map[RMAP_IN].name);
1671 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1672 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001673 }
1674
1675 /* outbound filter apply */
1676 if (gfilter->dlist[out].name)
1677 {
1678 if (pfilter->dlist[out].name)
1679 free (pfilter->dlist[out].name);
1680 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1681 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1682 }
1683 else
1684 {
1685 if (pfilter->dlist[out].name)
1686 free (pfilter->dlist[out].name);
1687 pfilter->dlist[out].name = NULL;
1688 pfilter->dlist[out].alist = NULL;
1689 }
1690 if (gfilter->plist[out].name)
1691 {
1692 if (pfilter->plist[out].name)
1693 free (pfilter->plist[out].name);
1694 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1695 pfilter->plist[out].plist = gfilter->plist[out].plist;
1696 }
1697 else
1698 {
1699 if (pfilter->plist[out].name)
1700 free (pfilter->plist[out].name);
1701 pfilter->plist[out].name = NULL;
1702 pfilter->plist[out].plist = NULL;
1703 }
1704 if (gfilter->aslist[out].name)
1705 {
1706 if (pfilter->aslist[out].name)
1707 free (pfilter->aslist[out].name);
1708 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1709 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1710 }
1711 else
1712 {
1713 if (pfilter->aslist[out].name)
1714 free (pfilter->aslist[out].name);
1715 pfilter->aslist[out].name = NULL;
1716 pfilter->aslist[out].aslist = NULL;
1717 }
paulfee0f4c2004-09-13 05:12:46 +00001718 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001719 {
paulfee0f4c2004-09-13 05:12:46 +00001720 if (pfilter->map[RMAP_OUT].name)
1721 free (pfilter->map[RMAP_OUT].name);
1722 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1723 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001724 }
1725 else
1726 {
paulfee0f4c2004-09-13 05:12:46 +00001727 if (pfilter->map[RMAP_OUT].name)
1728 free (pfilter->map[RMAP_OUT].name);
1729 pfilter->map[RMAP_OUT].name = NULL;
1730 pfilter->map[RMAP_OUT].map = NULL;
1731 }
1732
1733 /* RS-client's import/export route-maps. */
1734 if (gfilter->map[RMAP_IMPORT].name)
1735 {
1736 if (pfilter->map[RMAP_IMPORT].name)
1737 free (pfilter->map[RMAP_IMPORT].name);
1738 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1739 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1740 }
1741 else
1742 {
1743 if (pfilter->map[RMAP_IMPORT].name)
1744 free (pfilter->map[RMAP_IMPORT].name);
1745 pfilter->map[RMAP_IMPORT].name = NULL;
1746 pfilter->map[RMAP_IMPORT].map = NULL;
1747 }
1748 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1749 {
1750 if (pfilter->map[RMAP_EXPORT].name)
1751 free (pfilter->map[RMAP_EXPORT].name);
1752 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1753 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001754 }
1755
1756 if (gfilter->usmap.name)
1757 {
1758 if (pfilter->usmap.name)
1759 free (pfilter->usmap.name);
1760 pfilter->usmap.name = strdup (gfilter->usmap.name);
1761 pfilter->usmap.map = gfilter->usmap.map;
1762 }
1763 else
1764 {
1765 if (pfilter->usmap.name)
1766 free (pfilter->usmap.name);
1767 pfilter->usmap.name = NULL;
1768 pfilter->usmap.map = NULL;
1769 }
1770}
1771
1772/* Peer group's remote AS configuration. */
1773int
paulfd79ac92004-10-13 05:06:08 +00001774peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001775{
1776 struct peer_group *group;
1777 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001778 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001779
1780 group = peer_group_lookup (bgp, group_name);
1781 if (! group)
1782 return -1;
1783
1784 if (group->conf->as == *as)
1785 return 0;
1786
1787 /* When we setup peer-group AS number all peer group member's AS
1788 number must be updated to same number. */
1789 peer_as_change (group->conf, *as);
1790
paul1eb8ef22005-04-07 07:30:20 +00001791 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001792 {
1793 if (peer->as != *as)
1794 peer_as_change (peer, *as);
1795 }
1796
1797 return 0;
1798}
1799
1800int
Timo Teräse3443a22016-10-19 16:02:34 +03001801peer_ttl (struct peer *peer)
1802{
1803 if (peer->ttl)
1804 return peer->ttl;
1805 if (peer->gtsm_hops || peer->sort == BGP_PEER_IBGP)
1806 return 255;
1807 return 1;
1808}
1809
1810int
paul718e3742002-12-13 20:15:29 +00001811peer_group_delete (struct peer_group *group)
1812{
1813 struct bgp *bgp;
1814 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001815 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001816
1817 bgp = group->bgp;
1818
paul1eb8ef22005-04-07 07:30:20 +00001819 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001820 {
paul718e3742002-12-13 20:15:29 +00001821 peer_delete (peer);
1822 }
1823 list_delete (group->peer);
1824
1825 free (group->name);
1826 group->name = NULL;
1827
1828 group->conf->group = NULL;
1829 peer_delete (group->conf);
1830
1831 /* Delete from all peer_group list. */
1832 listnode_delete (bgp->group, group);
1833
1834 peer_group_free (group);
1835
1836 return 0;
1837}
1838
1839int
1840peer_group_remote_as_delete (struct peer_group *group)
1841{
1842 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001843 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001844
1845 if (! group->conf->as)
1846 return 0;
1847
paul1eb8ef22005-04-07 07:30:20 +00001848 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001849 {
paul718e3742002-12-13 20:15:29 +00001850 peer_delete (peer);
1851 }
1852 list_delete_all_node (group->peer);
1853
1854 group->conf->as = 0;
1855
1856 return 0;
1857}
1858
1859/* Bind specified peer to peer group. */
1860int
1861peer_group_bind (struct bgp *bgp, union sockunion *su,
1862 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1863{
1864 struct peer *peer;
1865 int first_member = 0;
1866
1867 /* Check peer group's address family. */
1868 if (! group->conf->afc[afi][safi])
1869 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1870
1871 /* Lookup the peer. */
1872 peer = peer_lookup (bgp, su);
1873
1874 /* Create a new peer. */
1875 if (! peer)
1876 {
1877 if (! group->conf->as)
1878 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1879
1880 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1881 peer->group = group;
1882 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001883
Paul Jakmaca058a32006-09-14 02:58:49 +00001884 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001885 listnode_add (group->peer, peer);
1886 peer_group2peer_config_copy (group, peer, afi, safi);
1887
1888 return 0;
1889 }
1890
1891 /* When the peer already belongs to peer group, check the consistency. */
1892 if (peer->af_group[afi][safi])
1893 {
1894 if (strcmp (peer->group->name, group->name) != 0)
1895 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1896
1897 return 0;
1898 }
1899
1900 /* Check current peer group configuration. */
1901 if (peer_group_active (peer)
1902 && strcmp (peer->group->name, group->name) != 0)
1903 return BGP_ERR_PEER_GROUP_MISMATCH;
1904
1905 if (! group->conf->as)
1906 {
1907 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1908 && peer_sort (group->conf) != peer_sort (peer))
1909 {
1910 if (as)
1911 *as = peer->as;
1912 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1913 }
1914
1915 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1916 first_member = 1;
1917 }
1918
1919 peer->af_group[afi][safi] = 1;
1920 peer->afc[afi][safi] = 1;
1921 if (! peer->group)
1922 {
1923 peer->group = group;
paul200df112005-06-01 11:17:05 +00001924
Paul Jakmaca058a32006-09-14 02:58:49 +00001925 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001926 listnode_add (group->peer, peer);
1927 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001928 else
1929 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001930
1931 if (first_member)
1932 {
1933 /* Advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +03001934 if (! CHECK_FLAG (group->conf->config, PEER_CONFIG_ROUTEADV))
1935 {
1936 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1937 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1938 else
1939 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1940 }
paul718e3742002-12-13 20:15:29 +00001941
paul718e3742002-12-13 20:15:29 +00001942 /* local-as reset */
1943 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1944 {
1945 group->conf->change_local_as = 0;
1946 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001947 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001948 }
1949 }
paulfee0f4c2004-09-13 05:12:46 +00001950
1951 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1952 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001953 struct listnode *pn;
1954
paulfee0f4c2004-09-13 05:12:46 +00001955 /* If it's not configured as RSERVER_CLIENT in any other address
1956 family, without being member of a peer_group, remove it from
1957 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001958 if (! peer_rsclient_active (peer)
1959 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001960 {
1961 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001962 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001963
1964 /* Clear our own rsclient rib for this afi/safi. */
1965 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001966 }
paulfee0f4c2004-09-13 05:12:46 +00001967
Paul Jakmab608d5b2008-07-02 02:12:07 +00001968 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001969
1970 /* Import policy. */
1971 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1972 {
1973 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1974 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1975 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1976 }
1977
1978 /* Export policy. */
1979 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1980 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1981 {
1982 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1983 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1984 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1985 }
1986 }
1987
paul718e3742002-12-13 20:15:29 +00001988 peer_group2peer_config_copy (group, peer, afi, safi);
1989
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001990 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001991 {
1992 peer->last_reset = PEER_DOWN_RMAP_BIND;
1993 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1994 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1995 }
paul718e3742002-12-13 20:15:29 +00001996 else
1997 BGP_EVENT_ADD (peer, BGP_Stop);
1998
1999 return 0;
2000}
2001
2002int
2003peer_group_unbind (struct bgp *bgp, struct peer *peer,
2004 struct peer_group *group, afi_t afi, safi_t safi)
2005{
2006 if (! peer->af_group[afi][safi])
2007 return 0;
2008
2009 if (group != peer->group)
2010 return BGP_ERR_PEER_GROUP_MISMATCH;
2011
2012 peer->af_group[afi][safi] = 0;
2013 peer->afc[afi][safi] = 0;
2014 peer_af_flag_reset (peer, afi, safi);
2015
paulfee0f4c2004-09-13 05:12:46 +00002016 if (peer->rib[afi][safi])
2017 peer->rib[afi][safi] = NULL;
2018
paul718e3742002-12-13 20:15:29 +00002019 if (! peer_group_active (peer))
2020 {
Paul Jakmaca058a32006-09-14 02:58:49 +00002021 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00002022 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00002023 listnode_delete (group->peer, peer);
2024 peer->group = NULL;
2025 if (group->conf->as)
2026 {
2027 peer_delete (peer);
2028 return 0;
2029 }
2030 peer_global_config_reset (peer);
2031 }
2032
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002033 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002034 {
2035 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
2036 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2037 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2038 }
paul718e3742002-12-13 20:15:29 +00002039 else
2040 BGP_EVENT_ADD (peer, BGP_Stop);
2041
2042 return 0;
2043}
David Lamparter6b0655a2014-06-04 06:53:35 +02002044
Vipin Kumardd49eb12014-09-30 14:36:38 -07002045
2046static int
2047bgp_startup_timer_expire (struct thread *thread)
2048{
2049 struct bgp *bgp;
2050
2051 bgp = THREAD_ARG (thread);
2052 bgp->t_startup = NULL;
2053
2054 return 0;
2055}
2056
paul718e3742002-12-13 20:15:29 +00002057/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00002058static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002059bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002060{
2061 struct bgp *bgp;
2062 afi_t afi;
2063 safi_t safi;
2064
paul200df112005-06-01 11:17:05 +00002065 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
2066 return NULL;
2067
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002068 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00002069 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00002070 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00002071
2072 bgp->peer = list_new ();
2073 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
2074
2075 bgp->group = list_new ();
2076 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
2077
paulfee0f4c2004-09-13 05:12:46 +00002078 bgp->rsclient = list_new ();
2079 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
2080
paul718e3742002-12-13 20:15:29 +00002081 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2082 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2083 {
Paul Jakma64e580a2006-02-21 01:09:01 +00002084 bgp->route[afi][safi] = bgp_table_init (afi, safi);
2085 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
2086 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07002087 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
2088 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00002089 }
2090
2091 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
2092 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
2093 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00002094 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
2095 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07002096 bgp_flag_set (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES);
paul718e3742002-12-13 20:15:29 +00002097
2098 bgp->as = *as;
2099
2100 if (name)
2101 bgp->name = strdup (name);
2102
Donald Sharp774914f2015-10-14 08:50:39 -04002103 THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire,
Vipin Kumardd49eb12014-09-30 14:36:38 -07002104 bgp, bgp->restart_time);
2105
paul718e3742002-12-13 20:15:29 +00002106 return bgp;
2107}
2108
2109/* Return first entry of BGP. */
2110struct bgp *
paul94f2b392005-06-28 12:44:16 +00002111bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00002112{
Lou Berger056f3762013-04-10 12:30:04 -07002113 if (bm && bm->bgp && bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00002114 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00002115 return NULL;
2116}
2117
2118/* Lookup BGP entry. */
2119struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002120bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00002121{
2122 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002123 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002124
paul1eb8ef22005-04-07 07:30:20 +00002125 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002126 if (bgp->as == as
2127 && ((bgp->name == NULL && name == NULL)
2128 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
2129 return bgp;
2130 return NULL;
2131}
2132
2133/* Lookup BGP structure by view name. */
2134struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002135bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002136{
2137 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002138 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002139
paul1eb8ef22005-04-07 07:30:20 +00002140 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002141 if ((bgp->name == NULL && name == NULL)
2142 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2143 return bgp;
2144 return NULL;
2145}
2146
2147/* Called from VTY commands. */
2148int
paulfd79ac92004-10-13 05:06:08 +00002149bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002150{
2151 struct bgp *bgp;
2152
2153 /* Multiple instance check. */
2154 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2155 {
2156 if (name)
2157 bgp = bgp_lookup_by_name (name);
2158 else
2159 bgp = bgp_get_default ();
2160
2161 /* Already exists. */
2162 if (bgp)
2163 {
2164 if (bgp->as != *as)
2165 {
2166 *as = bgp->as;
2167 return BGP_ERR_INSTANCE_MISMATCH;
2168 }
2169 *bgp_val = bgp;
2170 return 0;
2171 }
2172 }
2173 else
2174 {
2175 /* BGP instance name can not be specified for single instance. */
2176 if (name)
2177 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2178
2179 /* Get default BGP structure if exists. */
2180 bgp = bgp_get_default ();
2181
2182 if (bgp)
2183 {
2184 if (bgp->as != *as)
2185 {
2186 *as = bgp->as;
2187 return BGP_ERR_AS_MISMATCH;
2188 }
2189 *bgp_val = bgp;
2190 return 0;
2191 }
2192 }
2193
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002194 bgp = bgp_create (as, name);
2195 bgp_router_id_set(bgp, &router_id_zebra);
2196 *bgp_val = bgp;
2197
Paul Jakmaad12dde2012-06-13 22:50:07 +01002198 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002199 if (list_isempty(bm->bgp)
2200 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002201 {
2202 if (bgp_socket (bm->port, bm->address) < 0)
2203 return BGP_ERR_INVALID_VALUE;
2204 }
2205
paul718e3742002-12-13 20:15:29 +00002206 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002207
2208 return 0;
2209}
2210
2211/* Delete BGP instance. */
2212int
2213bgp_delete (struct bgp *bgp)
2214{
2215 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002216 struct peer_group *group;
Denil Vira57cd5e72015-08-10 12:46:14 -07002217 struct listnode *node, *pnode;
2218 struct listnode *next, *pnext;
paul718e3742002-12-13 20:15:29 +00002219 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002220 int i;
2221
Lou Berger82dd7072016-01-12 13:41:57 -05002222 SET_FLAG(bgp->flags, BGP_FLAG_DELETING);
2223
David Lampartercffe7802014-12-07 03:27:13 +01002224 THREAD_OFF (bgp->t_startup);
2225
Daniel Walton9e518dd2015-05-19 17:47:26 -07002226 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2227 {
2228 if (peer->status == Established ||
2229 peer->status == OpenSent ||
2230 peer->status == OpenConfirm)
2231 {
2232 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2233 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
2234 }
2235 }
2236
paul718e3742002-12-13 20:15:29 +00002237 /* Delete static route. */
2238 bgp_static_delete (bgp);
2239
2240 /* Unset redistribution. */
2241 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2242 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2243 if (i != ZEBRA_ROUTE_BGP)
2244 bgp_redistribute_unset (bgp, afi, i);
2245
paul1eb8ef22005-04-07 07:30:20 +00002246 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002247 {
2248 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2249 {
2250 /* Send notify to remote peer. */
2251 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2252 }
2253
2254 peer_delete (peer);
2255 }
paul718e3742002-12-13 20:15:29 +00002256
Chris Caputo228da422009-07-18 05:44:03 +00002257 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002258 {
Denil Vira57cd5e72015-08-10 12:46:14 -07002259 for (ALL_LIST_ELEMENTS (group->peer, pnode, pnext, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002260 {
2261 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2262 {
2263 /* Send notify to remote peer. */
2264 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2265 }
2266 }
2267 peer_group_delete (group);
2268 }
Chris Caputo228da422009-07-18 05:44:03 +00002269
2270 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002271
2272 if (bgp->peer_self) {
2273 peer_delete(bgp->peer_self);
2274 bgp->peer_self = NULL;
2275 }
Lou Berger82dd7072016-01-12 13:41:57 -05002276
2277 /*
2278 * Free pending deleted routes. Unfortunately, it also has to process
2279 * all the pending activity for other instances of struct bgp.
2280 *
2281 * This call was added to achieve clean memory allocation at exit,
2282 * for the sake of valgrind.
2283 */
2284 bgp_process_queues_drain_immediate();
2285
Paul Jakmafd35b942009-07-16 19:27:32 +01002286 /* Remove visibility via the master list - there may however still be
2287 * routes to be processed still referencing the struct bgp.
2288 */
2289 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002290 if (list_isempty(bm->bgp))
2291 bgp_close ();
2292
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002293 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002294
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002295 return 0;
2296}
2297
2298static void bgp_free (struct bgp *);
2299
2300void
2301bgp_lock (struct bgp *bgp)
2302{
2303 ++bgp->lock;
2304}
2305
2306void
2307bgp_unlock(struct bgp *bgp)
2308{
Chris Caputo228da422009-07-18 05:44:03 +00002309 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002310 if (--bgp->lock == 0)
2311 bgp_free (bgp);
2312}
2313
2314static void
2315bgp_free (struct bgp *bgp)
2316{
2317 afi_t afi;
2318 safi_t safi;
2319
2320 list_delete (bgp->group);
2321 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002322 list_delete (bgp->rsclient);
2323
paul718e3742002-12-13 20:15:29 +00002324 if (bgp->name)
2325 free (bgp->name);
2326
2327 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2328 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2329 {
2330 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002331 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002332 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002333 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002334 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002335 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002336 }
2337 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002338}
David Lamparter6b0655a2014-06-04 06:53:35 +02002339
paul718e3742002-12-13 20:15:29 +00002340struct peer *
2341peer_lookup (struct bgp *bgp, union sockunion *su)
2342{
2343 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002344 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002345
Steve Hillfc4dc592009-07-28 17:54:35 +01002346 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002347 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002348 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2349 if (sockunion_same (&peer->su, su)
2350 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2351 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002352 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002353 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002354 {
2355 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002356
Paul Jakma2158ad22009-07-28 18:10:55 +01002357 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2358 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2359 if (sockunion_same (&peer->su, su)
2360 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2361 return peer;
paul718e3742002-12-13 20:15:29 +00002362 }
2363 return NULL;
2364}
2365
2366struct peer *
2367peer_lookup_with_open (union sockunion *su, as_t remote_as,
2368 struct in_addr *remote_id, int *as)
2369{
2370 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002371 struct listnode *node;
2372 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002373 struct bgp *bgp;
2374
Steve Hillfc4dc592009-07-28 17:54:35 +01002375 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002376 return NULL;
2377
Paul Jakma9d878772009-08-05 16:25:16 +01002378 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002379 {
Paul Jakma9d878772009-08-05 16:25:16 +01002380 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2381 {
2382 if (sockunion_same (&peer->su, su)
2383 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2384 {
2385 if (peer->as == remote_as
2386 && peer->remote_id.s_addr == remote_id->s_addr)
2387 return peer;
2388 if (peer->as == remote_as)
2389 *as = 1;
2390 }
2391 }
2392
2393 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2394 {
2395 if (sockunion_same (&peer->su, su)
2396 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2397 {
2398 if (peer->as == remote_as
2399 && peer->remote_id.s_addr == 0)
2400 return peer;
2401 if (peer->as == remote_as)
2402 *as = 1;
2403 }
2404 }
paul718e3742002-12-13 20:15:29 +00002405 }
2406 return NULL;
2407}
David Lamparter6b0655a2014-06-04 06:53:35 +02002408
paul718e3742002-12-13 20:15:29 +00002409/* If peer is configured at least one address family return 1. */
2410int
2411peer_active (struct peer *peer)
2412{
2413 if (peer->afc[AFI_IP][SAFI_UNICAST]
2414 || peer->afc[AFI_IP][SAFI_MULTICAST]
2415 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05002416 || peer->afc[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00002417 || peer->afc[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05002418 || peer->afc[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05002419 || peer->afc[AFI_IP6][SAFI_MPLS_VPN]
2420 || peer->afc[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00002421 return 1;
2422 return 0;
2423}
2424
2425/* If peer is negotiated at least one address family return 1. */
2426int
2427peer_active_nego (struct peer *peer)
2428{
2429 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2430 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2431 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05002432 || peer->afc_nego[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00002433 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05002434 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05002435 || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
2436 || peer->afc_nego[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00002437 return 1;
2438 return 0;
2439}
David Lamparter6b0655a2014-06-04 06:53:35 +02002440
paul718e3742002-12-13 20:15:29 +00002441/* peer_flag_change_type. */
2442enum peer_change_type
2443{
2444 peer_change_none,
2445 peer_change_reset,
2446 peer_change_reset_in,
2447 peer_change_reset_out,
2448};
2449
paul94f2b392005-06-28 12:44:16 +00002450static void
paul718e3742002-12-13 20:15:29 +00002451peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2452 enum peer_change_type type)
2453{
2454 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2455 return;
2456
Stephen Hemmingerd9d4ae52010-01-13 00:32:39 +00002457 if (peer->status != Established)
2458 return;
2459
paul718e3742002-12-13 20:15:29 +00002460 if (type == peer_change_reset)
2461 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2462 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2463 else if (type == peer_change_reset_in)
2464 {
2465 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2466 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2467 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2468 else
2469 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2470 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2471 }
2472 else if (type == peer_change_reset_out)
2473 bgp_announce_route (peer, afi, safi);
2474}
2475
2476struct peer_flag_action
2477{
2478 /* Peer's flag. */
2479 u_int32_t flag;
2480
2481 /* This flag can be set for peer-group member. */
2482 u_char not_for_member;
2483
2484 /* Action when the flag is changed. */
2485 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002486
2487 /* Peer down cause */
2488 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002489};
2490
Stephen Hemminger03621952009-07-21 16:27:20 -07002491static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002492 {
2493 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2494 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2495 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2496 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2497 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002498 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002499 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002500 { 0, 0, 0 }
2501 };
2502
Stephen Hemminger03621952009-07-21 16:27:20 -07002503static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002504 {
2505 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2506 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2507 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2508 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2509 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2510 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2511 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2512 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2513 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2514 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2515 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2516 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2517 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002518 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
Timo Teräs9e7a53c2014-04-24 10:22:37 +03002519 { PEER_FLAG_NEXTHOP_SELF_ALL, 1, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002520 { 0, 0, 0 }
2521 };
2522
2523/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002524static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002525peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002526 struct peer_flag_action *action, u_int32_t flag)
2527{
2528 int i;
2529 int found = 0;
2530 int reset_in = 0;
2531 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002532 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002533
2534 /* Check peer's frag action. */
2535 for (i = 0; i < size; i++)
2536 {
2537 match = &action_list[i];
2538
2539 if (match->flag == 0)
2540 break;
2541
2542 if (match->flag & flag)
2543 {
2544 found = 1;
2545
2546 if (match->type == peer_change_reset_in)
2547 reset_in = 1;
2548 if (match->type == peer_change_reset_out)
2549 reset_out = 1;
2550 if (match->type == peer_change_reset)
2551 {
2552 reset_in = 1;
2553 reset_out = 1;
2554 }
2555 if (match->not_for_member)
2556 action->not_for_member = 1;
2557 }
2558 }
2559
2560 /* Set peer clear type. */
2561 if (reset_in && reset_out)
2562 action->type = peer_change_reset;
2563 else if (reset_in)
2564 action->type = peer_change_reset_in;
2565 else if (reset_out)
2566 action->type = peer_change_reset_out;
2567 else
2568 action->type = peer_change_none;
2569
2570 return found;
2571}
2572
paul94f2b392005-06-28 12:44:16 +00002573static void
paul718e3742002-12-13 20:15:29 +00002574peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2575{
2576 if (flag == PEER_FLAG_SHUTDOWN)
2577 {
2578 if (CHECK_FLAG (peer->flags, flag))
2579 {
hasso93406d82005-02-02 14:40:33 +00002580 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2581 peer_nsf_stop (peer);
2582
hasso0a486e52005-02-01 20:57:17 +00002583 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2584 if (peer->t_pmax_restart)
2585 {
2586 BGP_TIMER_OFF (peer->t_pmax_restart);
2587 if (BGP_DEBUG (events, EVENTS))
2588 zlog_debug ("%s Maximum-prefix restart timer canceled",
2589 peer->host);
2590 }
2591
hasso93406d82005-02-02 14:40:33 +00002592 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2593 peer_nsf_stop (peer);
2594
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002595 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002596 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2597 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2598 else
2599 BGP_EVENT_ADD (peer, BGP_Stop);
2600 }
2601 else
2602 {
2603 peer->v_start = BGP_INIT_START_TIMER;
2604 BGP_EVENT_ADD (peer, BGP_Stop);
2605 }
2606 }
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002607 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002608 {
hassoc9502432005-02-01 22:01:48 +00002609 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2610 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2611 else if (flag == PEER_FLAG_PASSIVE)
2612 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002613 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002614 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002615
hassoc9502432005-02-01 22:01:48 +00002616 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2617 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002618 }
2619 else
2620 BGP_EVENT_ADD (peer, BGP_Stop);
2621}
2622
2623/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002624static int
paul718e3742002-12-13 20:15:29 +00002625peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2626{
2627 int found;
2628 int size;
2629 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002630 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002631 struct peer_flag_action action;
2632
2633 memset (&action, 0, sizeof (struct peer_flag_action));
2634 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2635
2636 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2637
2638 /* No flag action is found. */
2639 if (! found)
2640 return BGP_ERR_INVALID_FLAG;
2641
2642 /* Not for peer-group member. */
2643 if (action.not_for_member && peer_group_active (peer))
2644 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2645
2646 /* When unset the peer-group member's flag we have to check
2647 peer-group configuration. */
2648 if (! set && peer_group_active (peer))
2649 if (CHECK_FLAG (peer->group->conf->flags, flag))
2650 {
2651 if (flag == PEER_FLAG_SHUTDOWN)
2652 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2653 else
2654 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2655 }
2656
2657 /* Flag conflict check. */
2658 if (set
2659 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2660 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2661 return BGP_ERR_PEER_FLAG_CONFLICT;
2662
2663 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2664 {
2665 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2666 return 0;
2667 if (! set && ! CHECK_FLAG (peer->flags, flag))
2668 return 0;
2669 }
2670
2671 if (set)
2672 SET_FLAG (peer->flags, flag);
2673 else
2674 UNSET_FLAG (peer->flags, flag);
2675
2676 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2677 {
2678 if (action.type == peer_change_reset)
2679 peer_flag_modify_action (peer, flag);
2680
2681 return 0;
2682 }
2683
2684 /* peer-group member updates. */
2685 group = peer->group;
2686
paul1eb8ef22005-04-07 07:30:20 +00002687 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002688 {
2689 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2690 continue;
2691
2692 if (! set && ! CHECK_FLAG (peer->flags, flag))
2693 continue;
2694
2695 if (set)
2696 SET_FLAG (peer->flags, flag);
2697 else
2698 UNSET_FLAG (peer->flags, flag);
2699
2700 if (action.type == peer_change_reset)
2701 peer_flag_modify_action (peer, flag);
2702 }
2703 return 0;
2704}
2705
2706int
2707peer_flag_set (struct peer *peer, u_int32_t flag)
2708{
2709 return peer_flag_modify (peer, flag, 1);
2710}
2711
2712int
2713peer_flag_unset (struct peer *peer, u_int32_t flag)
2714{
2715 return peer_flag_modify (peer, flag, 0);
2716}
2717
paul94f2b392005-06-28 12:44:16 +00002718static int
paul718e3742002-12-13 20:15:29 +00002719peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2720{
2721 if (peer->af_group[afi][safi])
2722 return 1;
2723 return 0;
2724}
2725
paul94f2b392005-06-28 12:44:16 +00002726static int
paul718e3742002-12-13 20:15:29 +00002727peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2728 int set)
2729{
2730 int found;
2731 int size;
paul1eb8ef22005-04-07 07:30:20 +00002732 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002733 struct peer_group *group;
2734 struct peer_flag_action action;
2735
2736 memset (&action, 0, sizeof (struct peer_flag_action));
2737 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2738
2739 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2740
2741 /* No flag action is found. */
2742 if (! found)
2743 return BGP_ERR_INVALID_FLAG;
2744
2745 /* Adress family must be activated. */
2746 if (! peer->afc[afi][safi])
2747 return BGP_ERR_PEER_INACTIVE;
2748
2749 /* Not for peer-group member. */
2750 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2751 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2752
2753 /* Spcecial check for reflector client. */
2754 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2755 && peer_sort (peer) != BGP_PEER_IBGP)
2756 return BGP_ERR_NOT_INTERNAL_PEER;
2757
2758 /* Spcecial check for remove-private-AS. */
2759 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2760 && peer_sort (peer) == BGP_PEER_IBGP)
2761 return BGP_ERR_REMOVE_PRIVATE_AS;
2762
2763 /* When unset the peer-group member's flag we have to check
2764 peer-group configuration. */
2765 if (! set && peer->af_group[afi][safi])
2766 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2767 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2768
2769 /* When current flag configuration is same as requested one. */
2770 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2771 {
2772 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2773 return 0;
2774 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2775 return 0;
2776 }
2777
2778 if (set)
2779 SET_FLAG (peer->af_flags[afi][safi], flag);
2780 else
2781 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2782
2783 /* Execute action when peer is established. */
2784 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2785 && peer->status == Established)
2786 {
2787 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2788 bgp_clear_adj_in (peer, afi, safi);
2789 else
hassoe0701b72004-05-20 09:19:34 +00002790 {
2791 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2792 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2793 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2794 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2795 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2796 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2797 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2798 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2799
2800 peer_change_action (peer, afi, safi, action.type);
2801 }
2802
paul718e3742002-12-13 20:15:29 +00002803 }
2804
2805 /* Peer group member updates. */
2806 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2807 {
2808 group = peer->group;
2809
paul1eb8ef22005-04-07 07:30:20 +00002810 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002811 {
2812 if (! peer->af_group[afi][safi])
2813 continue;
2814
2815 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2816 continue;
2817
2818 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2819 continue;
2820
2821 if (set)
2822 SET_FLAG (peer->af_flags[afi][safi], flag);
2823 else
2824 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2825
2826 if (peer->status == Established)
2827 {
2828 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2829 bgp_clear_adj_in (peer, afi, safi);
2830 else
hassoe0701b72004-05-20 09:19:34 +00002831 {
2832 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2833 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2834 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2835 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2836 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2837 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2838 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2839 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2840
2841 peer_change_action (peer, afi, safi, action.type);
2842 }
paul718e3742002-12-13 20:15:29 +00002843 }
2844 }
2845 }
2846 return 0;
2847}
2848
2849int
2850peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2851{
2852 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2853}
2854
2855int
2856peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2857{
2858 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2859}
David Lamparter6b0655a2014-06-04 06:53:35 +02002860
paul718e3742002-12-13 20:15:29 +00002861/* EBGP multihop configuration. */
2862int
2863peer_ebgp_multihop_set (struct peer *peer, int ttl)
2864{
2865 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002866 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002867 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002868
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002869 if (peer->sort == BGP_PEER_IBGP)
Timo Teräse3443a22016-10-19 16:02:34 +03002870 return BGP_ERR_NO_IBGP_WITH_TTLHACK;
paul718e3742002-12-13 20:15:29 +00002871
Timo Teräse3443a22016-10-19 16:02:34 +03002872 if (peer->gtsm_hops != 0)
2873 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2874
2875 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
Nick Hilliardfa411a22011-03-23 15:33:17 +00002876 {
Timo Teräse3443a22016-10-19 16:02:34 +03002877 group = peer->group;
2878 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
Nick Hilliardfa411a22011-03-23 15:33:17 +00002879 {
Timo Teräse3443a22016-10-19 16:02:34 +03002880 if (peer1->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002881 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2882 }
2883 }
2884
paul718e3742002-12-13 20:15:29 +00002885 peer->ttl = ttl;
2886
2887 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2888 {
Timo Teräse3443a22016-10-19 16:02:34 +03002889 bgp_set_socket_ttl (peer, peer->fd);
paul718e3742002-12-13 20:15:29 +00002890 }
2891 else
2892 {
2893 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002894 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
Timo Teräse3443a22016-10-19 16:02:34 +03002895 {
2896 peer->ttl = ttl;
2897 bgp_set_socket_ttl (peer, peer->fd);
2898 }
paul718e3742002-12-13 20:15:29 +00002899 }
paul718e3742002-12-13 20:15:29 +00002900
paul718e3742002-12-13 20:15:29 +00002901 return 0;
2902}
David Lamparter6b0655a2014-06-04 06:53:35 +02002903
paul718e3742002-12-13 20:15:29 +00002904/* Neighbor description. */
2905int
David Lamparterdfb9bd72016-05-24 18:58:07 +02002906peer_description_set (struct peer *peer, const char *desc)
paul718e3742002-12-13 20:15:29 +00002907{
2908 if (peer->desc)
2909 XFREE (MTYPE_PEER_DESC, peer->desc);
2910
2911 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2912
2913 return 0;
2914}
2915
2916int
2917peer_description_unset (struct peer *peer)
2918{
2919 if (peer->desc)
2920 XFREE (MTYPE_PEER_DESC, peer->desc);
2921
2922 peer->desc = NULL;
2923
2924 return 0;
2925}
David Lamparter6b0655a2014-06-04 06:53:35 +02002926
paul718e3742002-12-13 20:15:29 +00002927/* Neighbor update-source. */
2928int
paulfd79ac92004-10-13 05:06:08 +00002929peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002930{
2931 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002932 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002933
2934 if (peer->update_if)
2935 {
2936 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2937 && strcmp (peer->update_if, ifname) == 0)
2938 return 0;
2939
2940 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2941 peer->update_if = NULL;
2942 }
2943
2944 if (peer->update_source)
2945 {
2946 sockunion_free (peer->update_source);
2947 peer->update_source = NULL;
2948 }
2949
2950 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2951
2952 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2953 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002954 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002955 {
2956 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2957 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2958 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2959 }
paul718e3742002-12-13 20:15:29 +00002960 else
2961 BGP_EVENT_ADD (peer, BGP_Stop);
2962 return 0;
2963 }
2964
2965 /* peer-group member updates. */
2966 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002967 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002968 {
2969 if (peer->update_if)
2970 {
2971 if (strcmp (peer->update_if, ifname) == 0)
2972 continue;
2973
2974 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2975 peer->update_if = NULL;
2976 }
2977
2978 if (peer->update_source)
2979 {
2980 sockunion_free (peer->update_source);
2981 peer->update_source = NULL;
2982 }
2983
2984 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2985
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002986 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002987 {
2988 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2989 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2990 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2991 }
paul718e3742002-12-13 20:15:29 +00002992 else
2993 BGP_EVENT_ADD (peer, BGP_Stop);
2994 }
2995 return 0;
2996}
2997
2998int
David Lamparterdfb9bd72016-05-24 18:58:07 +02002999peer_update_source_addr_set (struct peer *peer, const union sockunion *su)
paul718e3742002-12-13 20:15:29 +00003000{
3001 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003002 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003003
3004 if (peer->update_source)
3005 {
3006 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3007 && sockunion_cmp (peer->update_source, su) == 0)
3008 return 0;
3009 sockunion_free (peer->update_source);
3010 peer->update_source = NULL;
3011 }
3012
3013 if (peer->update_if)
3014 {
3015 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3016 peer->update_if = NULL;
3017 }
3018
3019 peer->update_source = sockunion_dup (su);
3020
3021 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3022 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003023 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003024 {
3025 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3026 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3027 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3028 }
paul718e3742002-12-13 20:15:29 +00003029 else
3030 BGP_EVENT_ADD (peer, BGP_Stop);
3031 return 0;
3032 }
3033
3034 /* peer-group member updates. */
3035 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003036 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003037 {
3038 if (peer->update_source)
3039 {
3040 if (sockunion_cmp (peer->update_source, su) == 0)
3041 continue;
3042 sockunion_free (peer->update_source);
3043 peer->update_source = NULL;
3044 }
3045
3046 if (peer->update_if)
3047 {
3048 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3049 peer->update_if = NULL;
3050 }
3051
3052 peer->update_source = sockunion_dup (su);
3053
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003054 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003055 {
3056 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3057 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3058 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3059 }
paul718e3742002-12-13 20:15:29 +00003060 else
3061 BGP_EVENT_ADD (peer, BGP_Stop);
3062 }
3063 return 0;
3064}
3065
3066int
3067peer_update_source_unset (struct peer *peer)
3068{
3069 union sockunion *su;
3070 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003071 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003072
3073 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3074 && ! peer->update_source
3075 && ! peer->update_if)
3076 return 0;
3077
3078 if (peer->update_source)
3079 {
3080 sockunion_free (peer->update_source);
3081 peer->update_source = NULL;
3082 }
3083 if (peer->update_if)
3084 {
3085 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3086 peer->update_if = NULL;
3087 }
3088
3089 if (peer_group_active (peer))
3090 {
3091 group = peer->group;
3092
3093 if (group->conf->update_source)
3094 {
3095 su = sockunion_dup (group->conf->update_source);
3096 peer->update_source = su;
3097 }
3098 else if (group->conf->update_if)
3099 peer->update_if =
3100 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
3101 }
3102
3103 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3104 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003105 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003106 {
3107 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3108 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3109 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3110 }
paul718e3742002-12-13 20:15:29 +00003111 else
3112 BGP_EVENT_ADD (peer, BGP_Stop);
3113 return 0;
3114 }
3115
3116 /* peer-group member updates. */
3117 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003118 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003119 {
3120 if (! peer->update_source && ! peer->update_if)
3121 continue;
3122
3123 if (peer->update_source)
3124 {
3125 sockunion_free (peer->update_source);
3126 peer->update_source = NULL;
3127 }
3128
3129 if (peer->update_if)
3130 {
3131 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3132 peer->update_if = NULL;
3133 }
3134
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003135 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003136 {
3137 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3138 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3139 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3140 }
paul718e3742002-12-13 20:15:29 +00003141 else
3142 BGP_EVENT_ADD (peer, BGP_Stop);
3143 }
3144 return 0;
3145}
David Lamparter6b0655a2014-06-04 06:53:35 +02003146
paul718e3742002-12-13 20:15:29 +00003147int
3148peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003149 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003150{
3151 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003152 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003153
3154 /* Adress family must be activated. */
3155 if (! peer->afc[afi][safi])
3156 return BGP_ERR_PEER_INACTIVE;
3157
3158 /* Default originate can't be used for peer group memeber. */
3159 if (peer_is_group_member (peer, afi, safi))
3160 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3161
3162 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3163 || (rmap && ! peer->default_rmap[afi][safi].name)
3164 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3165 {
3166 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3167
3168 if (rmap)
3169 {
3170 if (peer->default_rmap[afi][safi].name)
3171 free (peer->default_rmap[afi][safi].name);
3172 peer->default_rmap[afi][safi].name = strdup (rmap);
3173 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3174 }
3175 }
3176
3177 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3178 {
3179 if (peer->status == Established && peer->afc_nego[afi][safi])
3180 bgp_default_originate (peer, afi, safi, 0);
3181 return 0;
3182 }
3183
3184 /* peer-group member updates. */
3185 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003186 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003187 {
3188 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3189
3190 if (rmap)
3191 {
3192 if (peer->default_rmap[afi][safi].name)
3193 free (peer->default_rmap[afi][safi].name);
3194 peer->default_rmap[afi][safi].name = strdup (rmap);
3195 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3196 }
3197
3198 if (peer->status == Established && peer->afc_nego[afi][safi])
3199 bgp_default_originate (peer, afi, safi, 0);
3200 }
3201 return 0;
3202}
3203
3204int
3205peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3206{
3207 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003208 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003209
3210 /* Adress family must be activated. */
3211 if (! peer->afc[afi][safi])
3212 return BGP_ERR_PEER_INACTIVE;
3213
3214 /* Default originate can't be used for peer group memeber. */
3215 if (peer_is_group_member (peer, afi, safi))
3216 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3217
3218 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3219 {
3220 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3221
3222 if (peer->default_rmap[afi][safi].name)
3223 free (peer->default_rmap[afi][safi].name);
3224 peer->default_rmap[afi][safi].name = NULL;
3225 peer->default_rmap[afi][safi].map = NULL;
3226 }
3227
3228 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3229 {
3230 if (peer->status == Established && peer->afc_nego[afi][safi])
3231 bgp_default_originate (peer, afi, safi, 1);
3232 return 0;
3233 }
3234
3235 /* peer-group member updates. */
3236 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003237 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003238 {
3239 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3240
3241 if (peer->default_rmap[afi][safi].name)
3242 free (peer->default_rmap[afi][safi].name);
3243 peer->default_rmap[afi][safi].name = NULL;
3244 peer->default_rmap[afi][safi].map = NULL;
3245
3246 if (peer->status == Established && peer->afc_nego[afi][safi])
3247 bgp_default_originate (peer, afi, safi, 1);
3248 }
3249 return 0;
3250}
David Lamparter6b0655a2014-06-04 06:53:35 +02003251
paul718e3742002-12-13 20:15:29 +00003252int
3253peer_port_set (struct peer *peer, u_int16_t port)
3254{
3255 peer->port = port;
3256 return 0;
3257}
3258
3259int
3260peer_port_unset (struct peer *peer)
3261{
3262 peer->port = BGP_PORT_DEFAULT;
3263 return 0;
3264}
David Lamparter6b0655a2014-06-04 06:53:35 +02003265
paul718e3742002-12-13 20:15:29 +00003266/* neighbor weight. */
3267int
3268peer_weight_set (struct peer *peer, u_int16_t weight)
3269{
3270 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003271 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003272
3273 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3274 peer->weight = weight;
3275
3276 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3277 return 0;
3278
3279 /* peer-group member updates. */
3280 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003281 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003282 {
3283 peer->weight = group->conf->weight;
3284 }
3285 return 0;
3286}
3287
3288int
3289peer_weight_unset (struct peer *peer)
3290{
3291 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003292 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003293
3294 /* Set default weight. */
3295 if (peer_group_active (peer))
3296 peer->weight = peer->group->conf->weight;
3297 else
3298 peer->weight = 0;
3299
3300 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3301
3302 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3303 return 0;
3304
3305 /* peer-group member updates. */
3306 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003307 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003308 {
3309 peer->weight = 0;
3310 }
3311 return 0;
3312}
David Lamparter6b0655a2014-06-04 06:53:35 +02003313
paul718e3742002-12-13 20:15:29 +00003314int
3315peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3316{
3317 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003318 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003319
3320 /* Not for peer group memeber. */
3321 if (peer_group_active (peer))
3322 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3323
3324 /* keepalive value check. */
3325 if (keepalive > 65535)
3326 return BGP_ERR_INVALID_VALUE;
3327
3328 /* Holdtime value check. */
3329 if (holdtime > 65535)
3330 return BGP_ERR_INVALID_VALUE;
3331
3332 /* Holdtime value must be either 0 or greater than 3. */
3333 if (holdtime < 3 && holdtime != 0)
3334 return BGP_ERR_INVALID_VALUE;
3335
3336 /* Set value to the configuration. */
3337 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3338 peer->holdtime = holdtime;
3339 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3340
3341 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3342 return 0;
3343
3344 /* peer-group member updates. */
3345 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003346 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003347 {
3348 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3349 peer->holdtime = group->conf->holdtime;
3350 peer->keepalive = group->conf->keepalive;
3351 }
3352 return 0;
3353}
3354
3355int
3356peer_timers_unset (struct peer *peer)
3357{
3358 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003359 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003360
3361 if (peer_group_active (peer))
3362 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3363
3364 /* Clear configuration. */
3365 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3366 peer->keepalive = 0;
3367 peer->holdtime = 0;
3368
3369 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3370 return 0;
3371
3372 /* peer-group member updates. */
3373 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003374 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003375 {
3376 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3377 peer->holdtime = 0;
3378 peer->keepalive = 0;
3379 }
3380
3381 return 0;
3382}
David Lamparter6b0655a2014-06-04 06:53:35 +02003383
paul718e3742002-12-13 20:15:29 +00003384int
3385peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3386{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003387 struct peer_group *group;
3388 struct listnode *node, *nnode;
3389
paul718e3742002-12-13 20:15:29 +00003390 if (peer_group_active (peer))
3391 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3392
3393 if (connect > 65535)
3394 return BGP_ERR_INVALID_VALUE;
3395
3396 /* Set value to the configuration. */
3397 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3398 peer->connect = connect;
3399
3400 /* Set value to timer setting. */
3401 peer->v_connect = connect;
3402
Daniel Walton0d7435f2015-10-22 11:35:20 +03003403 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3404 return 0;
3405
3406 /* peer-group member updates. */
3407 group = peer->group;
3408 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3409 {
3410 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3411 peer->connect = connect;
3412 peer->v_connect = connect;
3413 }
paul718e3742002-12-13 20:15:29 +00003414 return 0;
3415}
3416
3417int
3418peer_timers_connect_unset (struct peer *peer)
3419{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003420 struct peer_group *group;
3421 struct listnode *node, *nnode;
3422
paul718e3742002-12-13 20:15:29 +00003423 if (peer_group_active (peer))
3424 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3425
3426 /* Clear configuration. */
3427 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3428 peer->connect = 0;
3429
3430 /* Set timer setting to default value. */
3431 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3432
Daniel Walton0d7435f2015-10-22 11:35:20 +03003433 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3434 return 0;
3435
3436 /* peer-group member updates. */
3437 group = peer->group;
3438 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3439 {
3440 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3441 peer->connect = 0;
3442 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3443 }
3444 return 0;
paul718e3742002-12-13 20:15:29 +00003445}
David Lamparter6b0655a2014-06-04 06:53:35 +02003446
paul718e3742002-12-13 20:15:29 +00003447int
3448peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3449{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003450 struct peer_group *group;
3451 struct listnode *node, *nnode;
3452
paul718e3742002-12-13 20:15:29 +00003453 if (peer_group_active (peer))
3454 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3455
3456 if (routeadv > 600)
3457 return BGP_ERR_INVALID_VALUE;
3458
3459 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3460 peer->routeadv = routeadv;
3461 peer->v_routeadv = routeadv;
3462
Daniel Walton0d7435f2015-10-22 11:35:20 +03003463 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3464 return 0;
3465
3466 /* peer-group member updates. */
3467 group = peer->group;
3468 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3469 {
3470 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3471 peer->routeadv = routeadv;
3472 peer->v_routeadv = routeadv;
3473 }
3474
paul718e3742002-12-13 20:15:29 +00003475 return 0;
3476}
3477
3478int
3479peer_advertise_interval_unset (struct peer *peer)
3480{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003481 struct peer_group *group;
3482 struct listnode *node, *nnode;
3483
paul718e3742002-12-13 20:15:29 +00003484 if (peer_group_active (peer))
3485 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3486
3487 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3488 peer->routeadv = 0;
3489
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003490 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003491 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3492 else
3493 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
Daniel Walton0d7435f2015-10-22 11:35:20 +03003494
3495 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3496 return 0;
3497
3498 /* peer-group member updates. */
3499 group = peer->group;
3500 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3501 {
3502 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3503 peer->routeadv = 0;
3504
3505 if (peer->sort == BGP_PEER_IBGP)
3506 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3507 else
3508 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3509 }
paul718e3742002-12-13 20:15:29 +00003510
3511 return 0;
3512}
David Lamparter6b0655a2014-06-04 06:53:35 +02003513
paul718e3742002-12-13 20:15:29 +00003514/* neighbor interface */
3515int
paulfd79ac92004-10-13 05:06:08 +00003516peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003517{
3518 if (peer->ifname)
3519 free (peer->ifname);
3520 peer->ifname = strdup (str);
3521
3522 return 0;
3523}
3524
3525int
3526peer_interface_unset (struct peer *peer)
3527{
3528 if (peer->ifname)
3529 free (peer->ifname);
3530 peer->ifname = NULL;
3531
3532 return 0;
3533}
David Lamparter6b0655a2014-06-04 06:53:35 +02003534
paul718e3742002-12-13 20:15:29 +00003535/* Allow-as in. */
3536int
3537peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3538{
3539 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003540 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003541
3542 if (allow_num < 1 || allow_num > 10)
3543 return BGP_ERR_INVALID_VALUE;
3544
3545 if (peer->allowas_in[afi][safi] != allow_num)
3546 {
3547 peer->allowas_in[afi][safi] = allow_num;
3548 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3549 peer_change_action (peer, afi, safi, peer_change_reset_in);
3550 }
3551
3552 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3553 return 0;
3554
3555 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003556 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003557 {
3558 if (peer->allowas_in[afi][safi] != allow_num)
3559 {
3560 peer->allowas_in[afi][safi] = allow_num;
3561 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3562 peer_change_action (peer, afi, safi, peer_change_reset_in);
3563 }
3564
3565 }
3566 return 0;
3567}
3568
3569int
3570peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3571{
3572 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003573 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003574
3575 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3576 {
3577 peer->allowas_in[afi][safi] = 0;
3578 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3579 }
3580
3581 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3582 return 0;
3583
3584 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003585 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003586 {
3587 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3588 {
3589 peer->allowas_in[afi][safi] = 0;
3590 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3591 }
3592 }
3593 return 0;
3594}
David Lamparter6b0655a2014-06-04 06:53:35 +02003595
paul718e3742002-12-13 20:15:29 +00003596int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003597peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003598{
3599 struct bgp *bgp = peer->bgp;
3600 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003601 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003602
3603 if (peer_sort (peer) != BGP_PEER_EBGP
3604 && peer_sort (peer) != BGP_PEER_INTERNAL)
3605 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3606
3607 if (bgp->as == as)
3608 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3609
3610 if (peer_group_active (peer))
3611 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3612
Andrew Certain9d3f9702012-11-07 23:50:07 +00003613 if (peer->as == as)
3614 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3615
paul718e3742002-12-13 20:15:29 +00003616 if (peer->change_local_as == as &&
3617 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003618 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3619 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3620 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003621 return 0;
3622
3623 peer->change_local_as = as;
3624 if (no_prepend)
3625 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3626 else
3627 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3628
Andrew Certain9d3f9702012-11-07 23:50:07 +00003629 if (replace_as)
3630 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3631 else
3632 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3633
paul718e3742002-12-13 20:15:29 +00003634 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3635 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003636 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003637 {
3638 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3639 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3640 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3641 }
paul718e3742002-12-13 20:15:29 +00003642 else
3643 BGP_EVENT_ADD (peer, BGP_Stop);
3644
3645 return 0;
3646 }
3647
3648 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003649 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003650 {
3651 peer->change_local_as = as;
3652 if (no_prepend)
3653 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3654 else
3655 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3656
Andrew Certain9d3f9702012-11-07 23:50:07 +00003657 if (replace_as)
3658 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3659 else
3660 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3661
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003662 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003663 {
3664 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3665 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3666 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3667 }
paul718e3742002-12-13 20:15:29 +00003668 else
3669 BGP_EVENT_ADD (peer, BGP_Stop);
3670 }
3671
3672 return 0;
3673}
3674
3675int
3676peer_local_as_unset (struct peer *peer)
3677{
3678 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003679 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003680
3681 if (peer_group_active (peer))
3682 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3683
3684 if (! peer->change_local_as)
3685 return 0;
3686
3687 peer->change_local_as = 0;
3688 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003689 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003690
3691 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3692 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003693 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003694 {
3695 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3696 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3697 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3698 }
paul718e3742002-12-13 20:15:29 +00003699 else
3700 BGP_EVENT_ADD (peer, BGP_Stop);
3701
3702 return 0;
3703 }
3704
3705 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003706 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003707 {
3708 peer->change_local_as = 0;
3709 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003710 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003711
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003712 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003713 {
3714 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3715 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3716 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3717 }
paul718e3742002-12-13 20:15:29 +00003718 else
3719 BGP_EVENT_ADD (peer, BGP_Stop);
3720 }
3721 return 0;
3722}
David Lamparter6b0655a2014-06-04 06:53:35 +02003723
Paul Jakma0df7c912008-07-21 21:02:49 +00003724/* Set password for authenticating with the peer. */
3725int
3726peer_password_set (struct peer *peer, const char *password)
3727{
3728 struct listnode *nn, *nnode;
3729 int len = password ? strlen(password) : 0;
3730 int ret = BGP_SUCCESS;
3731
3732 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3733 return BGP_ERR_INVALID_VALUE;
3734
3735 if (peer->password && strcmp (peer->password, password) == 0
3736 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3737 return 0;
3738
3739 if (peer->password)
3740 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3741
3742 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3743
3744 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3745 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003746 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3747 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
Paul Jakma0df7c912008-07-21 21:02:49 +00003748 else
3749 BGP_EVENT_ADD (peer, BGP_Stop);
3750
3751 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3752 }
3753
3754 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3755 {
3756 if (peer->password && strcmp (peer->password, password) == 0)
3757 continue;
3758
3759 if (peer->password)
3760 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3761
3762 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3763
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003764 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003765 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3766 else
3767 BGP_EVENT_ADD (peer, BGP_Stop);
3768
3769 if (bgp_md5_set (peer) < 0)
3770 ret = BGP_ERR_TCPSIG_FAILED;
3771 }
3772
3773 return ret;
3774}
3775
3776int
3777peer_password_unset (struct peer *peer)
3778{
3779 struct listnode *nn, *nnode;
3780
3781 if (!peer->password
3782 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3783 return 0;
3784
3785 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3786 {
3787 if (peer_group_active (peer)
3788 && peer->group->conf->password
3789 && strcmp (peer->group->conf->password, peer->password) == 0)
3790 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3791
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003792 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003793 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3794 else
3795 BGP_EVENT_ADD (peer, BGP_Stop);
3796
3797 if (peer->password)
3798 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3799
3800 peer->password = NULL;
3801
3802 bgp_md5_set (peer);
3803
3804 return 0;
3805 }
3806
3807 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3808 peer->password = NULL;
3809
3810 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3811 {
3812 if (!peer->password)
3813 continue;
3814
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003815 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003816 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3817 else
3818 BGP_EVENT_ADD (peer, BGP_Stop);
3819
3820 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3821 peer->password = NULL;
3822
3823 bgp_md5_set (peer);
3824 }
3825
3826 return 0;
3827}
David Lamparter6b0655a2014-06-04 06:53:35 +02003828
paul718e3742002-12-13 20:15:29 +00003829/* Set distribute list to the peer. */
3830int
3831peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003832 const char *name)
paul718e3742002-12-13 20:15:29 +00003833{
3834 struct bgp_filter *filter;
3835 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003836 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003837
3838 if (! peer->afc[afi][safi])
3839 return BGP_ERR_PEER_INACTIVE;
3840
3841 if (direct != FILTER_IN && direct != FILTER_OUT)
3842 return BGP_ERR_INVALID_VALUE;
3843
3844 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3845 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3846
3847 filter = &peer->filter[afi][safi];
3848
3849 if (filter->plist[direct].name)
3850 return BGP_ERR_PEER_FILTER_CONFLICT;
3851
3852 if (filter->dlist[direct].name)
3853 free (filter->dlist[direct].name);
3854 filter->dlist[direct].name = strdup (name);
3855 filter->dlist[direct].alist = access_list_lookup (afi, name);
3856
3857 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3858 return 0;
3859
3860 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003861 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003862 {
3863 filter = &peer->filter[afi][safi];
3864
3865 if (! peer->af_group[afi][safi])
3866 continue;
3867
3868 if (filter->dlist[direct].name)
3869 free (filter->dlist[direct].name);
3870 filter->dlist[direct].name = strdup (name);
3871 filter->dlist[direct].alist = access_list_lookup (afi, name);
3872 }
3873
3874 return 0;
3875}
3876
3877int
3878peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3879{
3880 struct bgp_filter *filter;
3881 struct bgp_filter *gfilter;
3882 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003883 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003884
3885 if (! peer->afc[afi][safi])
3886 return BGP_ERR_PEER_INACTIVE;
3887
3888 if (direct != FILTER_IN && direct != FILTER_OUT)
3889 return BGP_ERR_INVALID_VALUE;
3890
3891 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3892 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3893
3894 filter = &peer->filter[afi][safi];
3895
3896 /* apply peer-group filter */
3897 if (peer->af_group[afi][safi])
3898 {
3899 gfilter = &peer->group->conf->filter[afi][safi];
3900
3901 if (gfilter->dlist[direct].name)
3902 {
3903 if (filter->dlist[direct].name)
3904 free (filter->dlist[direct].name);
3905 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3906 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3907 return 0;
3908 }
3909 }
3910
3911 if (filter->dlist[direct].name)
3912 free (filter->dlist[direct].name);
3913 filter->dlist[direct].name = NULL;
3914 filter->dlist[direct].alist = NULL;
3915
3916 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3917 return 0;
3918
3919 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003920 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003921 {
3922 filter = &peer->filter[afi][safi];
3923
3924 if (! peer->af_group[afi][safi])
3925 continue;
3926
3927 if (filter->dlist[direct].name)
3928 free (filter->dlist[direct].name);
3929 filter->dlist[direct].name = NULL;
3930 filter->dlist[direct].alist = NULL;
3931 }
3932
3933 return 0;
3934}
3935
3936/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003937static void
paul718e3742002-12-13 20:15:29 +00003938peer_distribute_update (struct access_list *access)
3939{
3940 afi_t afi;
3941 safi_t safi;
3942 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003943 struct listnode *mnode, *mnnode;
3944 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003945 struct bgp *bgp;
3946 struct peer *peer;
3947 struct peer_group *group;
3948 struct bgp_filter *filter;
3949
paul1eb8ef22005-04-07 07:30:20 +00003950 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003951 {
paul1eb8ef22005-04-07 07:30:20 +00003952 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003953 {
3954 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3955 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3956 {
3957 filter = &peer->filter[afi][safi];
3958
3959 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3960 {
3961 if (filter->dlist[direct].name)
3962 filter->dlist[direct].alist =
3963 access_list_lookup (afi, filter->dlist[direct].name);
3964 else
3965 filter->dlist[direct].alist = NULL;
3966 }
3967 }
3968 }
paul1eb8ef22005-04-07 07:30:20 +00003969 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003970 {
3971 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3972 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3973 {
3974 filter = &group->conf->filter[afi][safi];
3975
3976 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3977 {
3978 if (filter->dlist[direct].name)
3979 filter->dlist[direct].alist =
3980 access_list_lookup (afi, filter->dlist[direct].name);
3981 else
3982 filter->dlist[direct].alist = NULL;
3983 }
3984 }
3985 }
3986 }
3987}
David Lamparter6b0655a2014-06-04 06:53:35 +02003988
paul718e3742002-12-13 20:15:29 +00003989/* Set prefix list to the peer. */
3990int
3991peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003992 const char *name)
paul718e3742002-12-13 20:15:29 +00003993{
3994 struct bgp_filter *filter;
3995 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003996 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003997
3998 if (! peer->afc[afi][safi])
3999 return BGP_ERR_PEER_INACTIVE;
4000
4001 if (direct != FILTER_IN && direct != FILTER_OUT)
4002 return BGP_ERR_INVALID_VALUE;
4003
4004 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4005 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4006
4007 filter = &peer->filter[afi][safi];
4008
4009 if (filter->dlist[direct].name)
4010 return BGP_ERR_PEER_FILTER_CONFLICT;
4011
4012 if (filter->plist[direct].name)
4013 free (filter->plist[direct].name);
4014 filter->plist[direct].name = strdup (name);
4015 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4016
4017 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4018 return 0;
4019
4020 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004021 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004022 {
4023 filter = &peer->filter[afi][safi];
4024
4025 if (! peer->af_group[afi][safi])
4026 continue;
4027
4028 if (filter->plist[direct].name)
4029 free (filter->plist[direct].name);
4030 filter->plist[direct].name = strdup (name);
4031 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4032 }
4033 return 0;
4034}
4035
4036int
4037peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4038{
4039 struct bgp_filter *filter;
4040 struct bgp_filter *gfilter;
4041 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004042 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004043
4044 if (! peer->afc[afi][safi])
4045 return BGP_ERR_PEER_INACTIVE;
4046
4047 if (direct != FILTER_IN && direct != FILTER_OUT)
4048 return BGP_ERR_INVALID_VALUE;
4049
4050 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4051 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4052
4053 filter = &peer->filter[afi][safi];
4054
4055 /* apply peer-group filter */
4056 if (peer->af_group[afi][safi])
4057 {
4058 gfilter = &peer->group->conf->filter[afi][safi];
4059
4060 if (gfilter->plist[direct].name)
4061 {
4062 if (filter->plist[direct].name)
4063 free (filter->plist[direct].name);
4064 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
4065 filter->plist[direct].plist = gfilter->plist[direct].plist;
4066 return 0;
4067 }
4068 }
4069
4070 if (filter->plist[direct].name)
4071 free (filter->plist[direct].name);
4072 filter->plist[direct].name = NULL;
4073 filter->plist[direct].plist = NULL;
4074
4075 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4076 return 0;
4077
4078 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004079 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004080 {
4081 filter = &peer->filter[afi][safi];
4082
4083 if (! peer->af_group[afi][safi])
4084 continue;
4085
4086 if (filter->plist[direct].name)
4087 free (filter->plist[direct].name);
4088 filter->plist[direct].name = NULL;
4089 filter->plist[direct].plist = NULL;
4090 }
4091
4092 return 0;
4093}
4094
4095/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00004096static void
paul718e3742002-12-13 20:15:29 +00004097peer_prefix_list_update (struct prefix_list *plist)
4098{
paul1eb8ef22005-04-07 07:30:20 +00004099 struct listnode *mnode, *mnnode;
4100 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004101 struct bgp *bgp;
4102 struct peer *peer;
4103 struct peer_group *group;
4104 struct bgp_filter *filter;
4105 afi_t afi;
4106 safi_t safi;
4107 int direct;
4108
paul1eb8ef22005-04-07 07:30:20 +00004109 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004110 {
paul1eb8ef22005-04-07 07:30:20 +00004111 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004112 {
4113 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4114 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4115 {
4116 filter = &peer->filter[afi][safi];
4117
4118 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4119 {
4120 if (filter->plist[direct].name)
4121 filter->plist[direct].plist =
4122 prefix_list_lookup (afi, filter->plist[direct].name);
4123 else
4124 filter->plist[direct].plist = NULL;
4125 }
4126 }
4127 }
paul1eb8ef22005-04-07 07:30:20 +00004128 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004129 {
4130 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4131 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4132 {
4133 filter = &group->conf->filter[afi][safi];
4134
4135 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4136 {
4137 if (filter->plist[direct].name)
4138 filter->plist[direct].plist =
4139 prefix_list_lookup (afi, filter->plist[direct].name);
4140 else
4141 filter->plist[direct].plist = NULL;
4142 }
4143 }
4144 }
4145 }
4146}
David Lamparter6b0655a2014-06-04 06:53:35 +02004147
paul718e3742002-12-13 20:15:29 +00004148int
4149peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004150 const char *name)
paul718e3742002-12-13 20:15:29 +00004151{
4152 struct bgp_filter *filter;
4153 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004154 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004155
4156 if (! peer->afc[afi][safi])
4157 return BGP_ERR_PEER_INACTIVE;
4158
4159 if (direct != FILTER_IN && direct != FILTER_OUT)
4160 return BGP_ERR_INVALID_VALUE;
4161
4162 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4163 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4164
4165 filter = &peer->filter[afi][safi];
4166
4167 if (filter->aslist[direct].name)
4168 free (filter->aslist[direct].name);
4169 filter->aslist[direct].name = strdup (name);
4170 filter->aslist[direct].aslist = as_list_lookup (name);
4171
4172 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4173 return 0;
4174
4175 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004176 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004177 {
4178 filter = &peer->filter[afi][safi];
4179
4180 if (! peer->af_group[afi][safi])
4181 continue;
4182
4183 if (filter->aslist[direct].name)
4184 free (filter->aslist[direct].name);
4185 filter->aslist[direct].name = strdup (name);
4186 filter->aslist[direct].aslist = as_list_lookup (name);
4187 }
4188 return 0;
4189}
4190
4191int
4192peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4193{
4194 struct bgp_filter *filter;
4195 struct bgp_filter *gfilter;
4196 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004197 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004198
4199 if (! peer->afc[afi][safi])
4200 return BGP_ERR_PEER_INACTIVE;
4201
hassob5f29602005-05-25 21:00:28 +00004202 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004203 return BGP_ERR_INVALID_VALUE;
4204
hassob5f29602005-05-25 21:00:28 +00004205 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004206 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4207
4208 filter = &peer->filter[afi][safi];
4209
4210 /* apply peer-group filter */
4211 if (peer->af_group[afi][safi])
4212 {
4213 gfilter = &peer->group->conf->filter[afi][safi];
4214
4215 if (gfilter->aslist[direct].name)
4216 {
4217 if (filter->aslist[direct].name)
4218 free (filter->aslist[direct].name);
4219 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4220 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4221 return 0;
4222 }
4223 }
4224
4225 if (filter->aslist[direct].name)
4226 free (filter->aslist[direct].name);
4227 filter->aslist[direct].name = NULL;
4228 filter->aslist[direct].aslist = NULL;
4229
4230 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4231 return 0;
4232
4233 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004234 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004235 {
4236 filter = &peer->filter[afi][safi];
4237
4238 if (! peer->af_group[afi][safi])
4239 continue;
4240
4241 if (filter->aslist[direct].name)
4242 free (filter->aslist[direct].name);
4243 filter->aslist[direct].name = NULL;
4244 filter->aslist[direct].aslist = NULL;
4245 }
4246
4247 return 0;
4248}
4249
paul94f2b392005-06-28 12:44:16 +00004250static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004251peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004252{
4253 afi_t afi;
4254 safi_t safi;
4255 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004256 struct listnode *mnode, *mnnode;
4257 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004258 struct bgp *bgp;
4259 struct peer *peer;
4260 struct peer_group *group;
4261 struct bgp_filter *filter;
4262
paul1eb8ef22005-04-07 07:30:20 +00004263 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004264 {
paul1eb8ef22005-04-07 07:30:20 +00004265 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004266 {
4267 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4268 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4269 {
4270 filter = &peer->filter[afi][safi];
4271
4272 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4273 {
4274 if (filter->aslist[direct].name)
4275 filter->aslist[direct].aslist =
4276 as_list_lookup (filter->aslist[direct].name);
4277 else
4278 filter->aslist[direct].aslist = NULL;
4279 }
4280 }
4281 }
paul1eb8ef22005-04-07 07:30:20 +00004282 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004283 {
4284 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4285 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4286 {
4287 filter = &group->conf->filter[afi][safi];
4288
4289 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4290 {
4291 if (filter->aslist[direct].name)
4292 filter->aslist[direct].aslist =
4293 as_list_lookup (filter->aslist[direct].name);
4294 else
4295 filter->aslist[direct].aslist = NULL;
4296 }
4297 }
4298 }
4299 }
4300}
David Lamparter6b0655a2014-06-04 06:53:35 +02004301
paul718e3742002-12-13 20:15:29 +00004302/* Set route-map to the peer. */
4303int
4304peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004305 const char *name)
paul718e3742002-12-13 20:15:29 +00004306{
4307 struct bgp_filter *filter;
4308 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004309 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004310
4311 if (! peer->afc[afi][safi])
4312 return BGP_ERR_PEER_INACTIVE;
4313
paulfee0f4c2004-09-13 05:12:46 +00004314 if (direct != RMAP_IN && direct != RMAP_OUT &&
4315 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004316 return BGP_ERR_INVALID_VALUE;
4317
paulfee0f4c2004-09-13 05:12:46 +00004318 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4319 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004320 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4321
4322 filter = &peer->filter[afi][safi];
4323
4324 if (filter->map[direct].name)
4325 free (filter->map[direct].name);
4326
4327 filter->map[direct].name = strdup (name);
4328 filter->map[direct].map = route_map_lookup_by_name (name);
4329
4330 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4331 return 0;
4332
4333 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004334 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004335 {
4336 filter = &peer->filter[afi][safi];
4337
4338 if (! peer->af_group[afi][safi])
4339 continue;
4340
4341 if (filter->map[direct].name)
4342 free (filter->map[direct].name);
4343 filter->map[direct].name = strdup (name);
4344 filter->map[direct].map = route_map_lookup_by_name (name);
4345 }
4346 return 0;
4347}
4348
4349/* Unset route-map from the peer. */
4350int
4351peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4352{
4353 struct bgp_filter *filter;
4354 struct bgp_filter *gfilter;
4355 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004356 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004357
4358 if (! peer->afc[afi][safi])
4359 return BGP_ERR_PEER_INACTIVE;
4360
hassob5f29602005-05-25 21:00:28 +00004361 if (direct != RMAP_IN && direct != RMAP_OUT &&
4362 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004363 return BGP_ERR_INVALID_VALUE;
4364
hassob5f29602005-05-25 21:00:28 +00004365 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4366 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004367 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4368
4369 filter = &peer->filter[afi][safi];
4370
4371 /* apply peer-group filter */
4372 if (peer->af_group[afi][safi])
4373 {
4374 gfilter = &peer->group->conf->filter[afi][safi];
4375
4376 if (gfilter->map[direct].name)
4377 {
4378 if (filter->map[direct].name)
4379 free (filter->map[direct].name);
4380 filter->map[direct].name = strdup (gfilter->map[direct].name);
4381 filter->map[direct].map = gfilter->map[direct].map;
4382 return 0;
4383 }
4384 }
4385
4386 if (filter->map[direct].name)
4387 free (filter->map[direct].name);
4388 filter->map[direct].name = NULL;
4389 filter->map[direct].map = NULL;
4390
4391 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4392 return 0;
4393
4394 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004395 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004396 {
4397 filter = &peer->filter[afi][safi];
4398
4399 if (! peer->af_group[afi][safi])
4400 continue;
4401
4402 if (filter->map[direct].name)
4403 free (filter->map[direct].name);
4404 filter->map[direct].name = NULL;
4405 filter->map[direct].map = NULL;
4406 }
4407 return 0;
4408}
David Lamparter6b0655a2014-06-04 06:53:35 +02004409
paul718e3742002-12-13 20:15:29 +00004410/* Set unsuppress-map to the peer. */
4411int
paulfd79ac92004-10-13 05:06:08 +00004412peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4413 const char *name)
paul718e3742002-12-13 20:15:29 +00004414{
4415 struct bgp_filter *filter;
4416 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004417 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004418
4419 if (! peer->afc[afi][safi])
4420 return BGP_ERR_PEER_INACTIVE;
4421
4422 if (peer_is_group_member (peer, afi, safi))
4423 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4424
4425 filter = &peer->filter[afi][safi];
4426
4427 if (filter->usmap.name)
4428 free (filter->usmap.name);
4429
4430 filter->usmap.name = strdup (name);
4431 filter->usmap.map = route_map_lookup_by_name (name);
4432
4433 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4434 return 0;
4435
4436 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004437 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004438 {
4439 filter = &peer->filter[afi][safi];
4440
4441 if (! peer->af_group[afi][safi])
4442 continue;
4443
4444 if (filter->usmap.name)
4445 free (filter->usmap.name);
4446 filter->usmap.name = strdup (name);
4447 filter->usmap.map = route_map_lookup_by_name (name);
4448 }
4449 return 0;
4450}
4451
4452/* Unset route-map from the peer. */
4453int
4454peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4455{
4456 struct bgp_filter *filter;
4457 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004458 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004459
4460 if (! peer->afc[afi][safi])
4461 return BGP_ERR_PEER_INACTIVE;
4462
4463 if (peer_is_group_member (peer, afi, safi))
4464 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4465
4466 filter = &peer->filter[afi][safi];
4467
4468 if (filter->usmap.name)
4469 free (filter->usmap.name);
4470 filter->usmap.name = NULL;
4471 filter->usmap.map = NULL;
4472
4473 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4474 return 0;
4475
4476 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004477 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004478 {
4479 filter = &peer->filter[afi][safi];
4480
4481 if (! peer->af_group[afi][safi])
4482 continue;
4483
4484 if (filter->usmap.name)
4485 free (filter->usmap.name);
4486 filter->usmap.name = NULL;
4487 filter->usmap.map = NULL;
4488 }
4489 return 0;
4490}
David Lamparter6b0655a2014-06-04 06:53:35 +02004491
paul718e3742002-12-13 20:15:29 +00004492int
4493peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004494 u_int32_t max, u_char threshold,
4495 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004496{
4497 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004498 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004499
4500 if (! peer->afc[afi][safi])
4501 return BGP_ERR_PEER_INACTIVE;
4502
4503 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4504 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004505 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004506 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004507 if (warning)
4508 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4509 else
4510 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4511
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07004512 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
paul718e3742002-12-13 20:15:29 +00004513 {
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07004514 group = peer->group;
4515 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4516 {
4517 if (! peer->af_group[afi][safi])
4518 continue;
paul718e3742002-12-13 20:15:29 +00004519
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07004520 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4521 peer->pmax[afi][safi] = max;
4522 peer->pmax_threshold[afi][safi] = threshold;
4523 peer->pmax_restart[afi][safi] = restart;
4524 if (warning)
4525 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4526 else
4527 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4528
4529 if ((peer->status == Established) && (peer->afc[afi][safi]))
4530 bgp_maximum_prefix_overflow (peer, afi, safi, 1);
4531 }
paul718e3742002-12-13 20:15:29 +00004532 }
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07004533 else
4534 {
4535 if ((peer->status == Established) && (peer->afc[afi][safi]))
4536 bgp_maximum_prefix_overflow (peer, afi, safi, 1);
4537 }
4538
paul718e3742002-12-13 20:15:29 +00004539 return 0;
4540}
4541
4542int
4543peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4544{
4545 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004546 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004547
4548 if (! peer->afc[afi][safi])
4549 return BGP_ERR_PEER_INACTIVE;
4550
4551 /* apply peer-group config */
4552 if (peer->af_group[afi][safi])
4553 {
4554 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4555 PEER_FLAG_MAX_PREFIX))
4556 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4557 else
4558 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4559
4560 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4561 PEER_FLAG_MAX_PREFIX_WARNING))
4562 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4563 else
4564 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4565
4566 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004567 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004568 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004569 return 0;
4570 }
4571
4572 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4573 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4574 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004575 peer->pmax_threshold[afi][safi] = 0;
4576 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004577
4578 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4579 return 0;
4580
4581 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004582 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004583 {
4584 if (! peer->af_group[afi][safi])
4585 continue;
4586
4587 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4588 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4589 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004590 peer->pmax_threshold[afi][safi] = 0;
4591 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004592 }
4593 return 0;
4594}
David Lamparter5f9adb52014-05-19 23:15:02 +02004595
Nick Hilliardfa411a22011-03-23 15:33:17 +00004596/* Set # of hops between us and BGP peer. */
4597int
4598peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4599{
4600 struct peer_group *group;
4601 struct listnode *node, *nnode;
Timo Teräse3443a22016-10-19 16:02:34 +03004602 struct peer *peer1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004603
4604 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4605
Timo Teräse3443a22016-10-19 16:02:34 +03004606 if (peer->ttl != 0)
4607 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004608
Timo Teräse3443a22016-10-19 16:02:34 +03004609 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4610 {
4611 group = peer->group;
4612 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4613 {
4614 if (peer1->ttl != 0)
4615 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4616 }
David Lamparter5f9adb52014-05-19 23:15:02 +02004617 }
Timo Teräse3443a22016-10-19 16:02:34 +03004618
Nick Hilliardfa411a22011-03-23 15:33:17 +00004619 peer->gtsm_hops = gtsm_hops;
4620
Nick Hilliardfa411a22011-03-23 15:33:17 +00004621 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4622 {
Timo Teräse3443a22016-10-19 16:02:34 +03004623 bgp_set_socket_ttl (peer, peer->fd);
Nick Hilliardfa411a22011-03-23 15:33:17 +00004624 }
4625 else
4626 {
4627 group = peer->group;
4628 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4629 {
Timo Teräse3443a22016-10-19 16:02:34 +03004630 peer->gtsm_hops = gtsm_hops;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004631
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004632 /* Change setting of existing peer
4633 * established then change value (may break connectivity)
4634 * not established yet (teardown session and restart)
4635 * no session then do nothing (will get handled by next connection)
4636 */
4637 if (peer->status == Established)
4638 {
Timo Teräse3443a22016-10-19 16:02:34 +03004639 bgp_set_socket_ttl (peer, peer->fd);
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004640 }
4641 else if (peer->status < Established)
4642 {
4643 if (BGP_DEBUG (events, EVENTS))
4644 zlog_debug ("%s Min-ttl changed", peer->host);
4645 BGP_EVENT_ADD (peer, BGP_Stop);
4646 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004647 }
4648 }
4649
4650 return 0;
4651}
4652
4653int
paul718e3742002-12-13 20:15:29 +00004654peer_clear (struct peer *peer)
4655{
4656 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4657 {
hasso0a486e52005-02-01 20:57:17 +00004658 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4659 {
4660 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4661 if (peer->t_pmax_restart)
4662 {
4663 BGP_TIMER_OFF (peer->t_pmax_restart);
4664 if (BGP_DEBUG (events, EVENTS))
4665 zlog_debug ("%s Maximum-prefix restart timer canceled",
4666 peer->host);
4667 }
4668 BGP_EVENT_ADD (peer, BGP_Start);
4669 return 0;
4670 }
4671
paul718e3742002-12-13 20:15:29 +00004672 peer->v_start = BGP_INIT_START_TIMER;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00004673 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00004674 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4675 BGP_NOTIFY_CEASE_ADMIN_RESET);
4676 else
4677 BGP_EVENT_ADD (peer, BGP_Stop);
4678 }
4679 return 0;
4680}
4681
4682int
4683peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4684 enum bgp_clear_type stype)
4685{
4686 if (peer->status != Established)
4687 return 0;
4688
4689 if (! peer->afc[afi][safi])
4690 return BGP_ERR_AF_UNCONFIGURED;
4691
Timo Teräs5a2a1ec2015-10-22 11:35:18 +03004692 peer->rtt = sockopt_tcp_rtt (peer->fd);
4693
paulfee0f4c2004-09-13 05:12:46 +00004694 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4695 {
4696 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4697 return 0;
4698 bgp_check_local_routes_rsclient (peer, afi, safi);
4699 bgp_soft_reconfig_rsclient (peer, afi, safi);
4700 }
4701
paul718e3742002-12-13 20:15:29 +00004702 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4703 bgp_announce_route (peer, afi, safi);
4704
4705 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4706 {
4707 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4708 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4709 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4710 {
4711 struct bgp_filter *filter = &peer->filter[afi][safi];
4712 u_char prefix_type;
4713
4714 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4715 prefix_type = ORF_TYPE_PREFIX;
4716 else
4717 prefix_type = ORF_TYPE_PREFIX_OLD;
4718
4719 if (filter->plist[FILTER_IN].plist)
4720 {
4721 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4722 bgp_route_refresh_send (peer, afi, safi,
4723 prefix_type, REFRESH_DEFER, 1);
4724 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4725 REFRESH_IMMEDIATE, 0);
4726 }
4727 else
4728 {
4729 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4730 bgp_route_refresh_send (peer, afi, safi,
4731 prefix_type, REFRESH_IMMEDIATE, 1);
4732 else
4733 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4734 }
4735 return 0;
4736 }
4737 }
4738
4739 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4740 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4741 {
4742 /* If neighbor has soft reconfiguration inbound flag.
4743 Use Adj-RIB-In database. */
4744 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4745 bgp_soft_reconfig_in (peer, afi, safi);
4746 else
4747 {
4748 /* If neighbor has route refresh capability, send route refresh
4749 message to the peer. */
4750 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4751 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4752 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4753 else
4754 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4755 }
4756 }
4757 return 0;
4758}
David Lamparter6b0655a2014-06-04 06:53:35 +02004759
paulfd79ac92004-10-13 05:06:08 +00004760/* Display peer uptime.*/
4761/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004762char *
4763peer_uptime (time_t uptime2, char *buf, size_t len)
4764{
4765 time_t uptime1;
4766 struct tm *tm;
4767
4768 /* Check buffer length. */
4769 if (len < BGP_UPTIME_LEN)
4770 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004771 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004772 /* XXX: should return status instead of buf... */
4773 snprintf (buf, len, "<error> ");
4774 return buf;
paul718e3742002-12-13 20:15:29 +00004775 }
4776
4777 /* If there is no connection has been done before print `never'. */
4778 if (uptime2 == 0)
4779 {
4780 snprintf (buf, len, "never ");
4781 return buf;
4782 }
4783
4784 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004785 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004786 uptime1 -= uptime2;
4787 tm = gmtime (&uptime1);
Paul Jakma84c38402015-05-26 15:19:38 +01004788
paul718e3742002-12-13 20:15:29 +00004789 /* Making formatted timer strings. */
4790#define ONE_DAY_SECOND 60*60*24
Paul Jakma84c38402015-05-26 15:19:38 +01004791#define ONE_WEEK_SECOND ONE_DAY_SECOND*7
4792#define ONE_YEAR_SECOND ONE_DAY_SECOND*365
paul718e3742002-12-13 20:15:29 +00004793
4794 if (uptime1 < ONE_DAY_SECOND)
4795 snprintf (buf, len, "%02d:%02d:%02d",
4796 tm->tm_hour, tm->tm_min, tm->tm_sec);
4797 else if (uptime1 < ONE_WEEK_SECOND)
4798 snprintf (buf, len, "%dd%02dh%02dm",
4799 tm->tm_yday, tm->tm_hour, tm->tm_min);
Paul Jakma84c38402015-05-26 15:19:38 +01004800 else if (uptime1 < ONE_YEAR_SECOND)
paul718e3742002-12-13 20:15:29 +00004801 snprintf (buf, len, "%02dw%dd%02dh",
4802 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
Paul Jakma84c38402015-05-26 15:19:38 +01004803 else
4804 snprintf (buf, len, "%02dy%02dw%dd",
4805 tm->tm_year - 70, tm->tm_yday/7,
4806 tm->tm_yday - ((tm->tm_yday/7) * 7));
paul718e3742002-12-13 20:15:29 +00004807 return buf;
4808}
David Lamparter6b0655a2014-06-04 06:53:35 +02004809
paul94f2b392005-06-28 12:44:16 +00004810static void
paul718e3742002-12-13 20:15:29 +00004811bgp_config_write_filter (struct vty *vty, struct peer *peer,
4812 afi_t afi, safi_t safi)
4813{
4814 struct bgp_filter *filter;
4815 struct bgp_filter *gfilter = NULL;
4816 char *addr;
4817 int in = FILTER_IN;
4818 int out = FILTER_OUT;
4819
4820 addr = peer->host;
4821 filter = &peer->filter[afi][safi];
4822 if (peer->af_group[afi][safi])
4823 gfilter = &peer->group->conf->filter[afi][safi];
4824
4825 /* distribute-list. */
4826 if (filter->dlist[in].name)
4827 if (! gfilter || ! gfilter->dlist[in].name
4828 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4829 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4830 filter->dlist[in].name, VTY_NEWLINE);
4831 if (filter->dlist[out].name && ! gfilter)
4832 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4833 filter->dlist[out].name, VTY_NEWLINE);
4834
4835 /* prefix-list. */
4836 if (filter->plist[in].name)
4837 if (! gfilter || ! gfilter->plist[in].name
4838 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4839 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4840 filter->plist[in].name, VTY_NEWLINE);
4841 if (filter->plist[out].name && ! gfilter)
4842 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4843 filter->plist[out].name, VTY_NEWLINE);
4844
4845 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004846 if (filter->map[RMAP_IN].name)
4847 if (! gfilter || ! gfilter->map[RMAP_IN].name
4848 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004849 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004850 filter->map[RMAP_IN].name, VTY_NEWLINE);
4851 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004852 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004853 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4854 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4855 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4856 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4857 if (filter->map[RMAP_EXPORT].name)
4858 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4859 || strcmp (filter->map[RMAP_EXPORT].name,
4860 gfilter->map[RMAP_EXPORT].name) != 0)
4861 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4862 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004863
4864 /* unsuppress-map */
4865 if (filter->usmap.name && ! gfilter)
4866 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4867 filter->usmap.name, VTY_NEWLINE);
4868
4869 /* filter-list. */
4870 if (filter->aslist[in].name)
4871 if (! gfilter || ! gfilter->aslist[in].name
4872 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4873 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4874 filter->aslist[in].name, VTY_NEWLINE);
4875 if (filter->aslist[out].name && ! gfilter)
4876 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4877 filter->aslist[out].name, VTY_NEWLINE);
4878}
4879
4880/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004881static void
paul718e3742002-12-13 20:15:29 +00004882bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4883 struct peer *peer, afi_t afi, safi_t safi)
4884{
paul718e3742002-12-13 20:15:29 +00004885 struct peer *g_peer = NULL;
4886 char buf[SU_ADDRSTRLEN];
4887 char *addr;
4888
paul718e3742002-12-13 20:15:29 +00004889 addr = peer->host;
4890 if (peer_group_active (peer))
4891 g_peer = peer->group->conf;
4892
4893 /************************************
4894 ****** Global to the neighbor ******
4895 ************************************/
4896 if (afi == AFI_IP && safi == SAFI_UNICAST)
4897 {
4898 /* remote-as. */
4899 if (! peer_group_active (peer))
4900 {
4901 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4902 vty_out (vty, " neighbor %s peer-group%s", addr,
4903 VTY_NEWLINE);
4904 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004905 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004906 VTY_NEWLINE);
4907 }
4908 else
4909 {
4910 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004911 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004912 VTY_NEWLINE);
4913 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4914 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4915 peer->group->name, VTY_NEWLINE);
4916 }
4917
4918 /* local-as. */
4919 if (peer->change_local_as)
4920 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00004921 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004922 peer->change_local_as,
4923 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00004924 " no-prepend" : "",
4925 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
4926 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004927
4928 /* Description. */
4929 if (peer->desc)
4930 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4931 VTY_NEWLINE);
4932
4933 /* Shutdown. */
4934 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4935 if (! peer_group_active (peer) ||
4936 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4937 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4938
Paul Jakma0df7c912008-07-21 21:02:49 +00004939 /* Password. */
4940 if (peer->password)
4941 if (!peer_group_active (peer)
4942 || ! g_peer->password
4943 || strcmp (peer->password, g_peer->password) != 0)
4944 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4945 VTY_NEWLINE);
4946
paul718e3742002-12-13 20:15:29 +00004947 /* BGP port. */
4948 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004949 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004950 VTY_NEWLINE);
4951
4952 /* Local interface name. */
4953 if (peer->ifname)
4954 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4955 VTY_NEWLINE);
4956
4957 /* Passive. */
4958 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4959 if (! peer_group_active (peer) ||
4960 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4961 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4962
Timo Teräse3443a22016-10-19 16:02:34 +03004963 /* TTL option */
4964 if (peer->gtsm_hops && ! peer_group_active (peer))
4965 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
4966 peer->gtsm_hops, VTY_NEWLINE);
4967 else if (peer->ttl && ! peer_group_active (peer))
4968 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4969 VTY_NEWLINE);
Nick Hilliardfa411a22011-03-23 15:33:17 +00004970
hasso6ffd2072005-02-02 14:50:11 +00004971 /* disable-connected-check. */
4972 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004973 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004974 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4975 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004976
4977 /* Update-source. */
4978 if (peer->update_if)
4979 if (! peer_group_active (peer) || ! g_peer->update_if
4980 || strcmp (g_peer->update_if, peer->update_if) != 0)
4981 vty_out (vty, " neighbor %s update-source %s%s", addr,
4982 peer->update_if, VTY_NEWLINE);
4983 if (peer->update_source)
4984 if (! peer_group_active (peer) || ! g_peer->update_source
4985 || sockunion_cmp (g_peer->update_source,
4986 peer->update_source) != 0)
4987 vty_out (vty, " neighbor %s update-source %s%s", addr,
4988 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4989 VTY_NEWLINE);
4990
paul718e3742002-12-13 20:15:29 +00004991 /* advertisement-interval */
Daniel Walton0d7435f2015-10-22 11:35:20 +03004992 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV) &&
4993 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00004994 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4995 addr, peer->v_routeadv, VTY_NEWLINE);
4996
4997 /* timers. */
4998 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4999 && ! peer_group_active (peer))
5000 vty_out (vty, " neighbor %s timers %d %d%s", addr,
5001 peer->keepalive, peer->holdtime, VTY_NEWLINE);
5002
Daniel Walton0d7435f2015-10-22 11:35:20 +03005003 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT) &&
5004 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00005005 vty_out (vty, " neighbor %s timers connect %d%s", addr,
5006 peer->connect, VTY_NEWLINE);
5007
5008 /* Default weight. */
5009 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
5010 if (! peer_group_active (peer) ||
5011 g_peer->weight != peer->weight)
5012 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
5013 VTY_NEWLINE);
5014
paul718e3742002-12-13 20:15:29 +00005015 /* Dynamic capability. */
5016 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5017 if (! peer_group_active (peer) ||
5018 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5019 vty_out (vty, " neighbor %s capability dynamic%s", addr,
5020 VTY_NEWLINE);
5021
5022 /* dont capability negotiation. */
5023 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
5024 if (! peer_group_active (peer) ||
5025 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
5026 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
5027 VTY_NEWLINE);
5028
5029 /* override capability negotiation. */
5030 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5031 if (! peer_group_active (peer) ||
5032 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5033 vty_out (vty, " neighbor %s override-capability%s", addr,
5034 VTY_NEWLINE);
5035
5036 /* strict capability negotiation. */
5037 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5038 if (! peer_group_active (peer) ||
5039 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5040 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
5041 VTY_NEWLINE);
5042
Christian Franke15c71342012-11-19 11:17:31 +00005043 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
paul718e3742002-12-13 20:15:29 +00005044 {
5045 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5046 {
5047 if (peer->afc[AFI_IP][SAFI_UNICAST])
5048 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5049 }
5050 else
5051 {
5052 if (! peer->afc[AFI_IP][SAFI_UNICAST])
5053 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
5054 }
5055 }
5056 }
5057
5058
5059 /************************************
5060 ****** Per AF to the neighbor ******
5061 ************************************/
5062
5063 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
5064 {
5065 if (peer->af_group[afi][safi])
5066 vty_out (vty, " neighbor %s peer-group %s%s", addr,
5067 peer->group->name, VTY_NEWLINE);
5068 else
5069 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5070 }
5071
5072 /* ORF capability. */
5073 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5074 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5075 if (! peer->af_group[afi][safi])
5076 {
5077 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
5078
5079 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5080 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5081 vty_out (vty, " both");
5082 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
5083 vty_out (vty, " send");
5084 else
5085 vty_out (vty, " receive");
5086 vty_out (vty, "%s", VTY_NEWLINE);
5087 }
5088
5089 /* Route reflector client. */
5090 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
5091 && ! peer->af_group[afi][safi])
5092 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
5093 VTY_NEWLINE);
5094
5095 /* Nexthop self. */
5096 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
5097 && ! peer->af_group[afi][safi])
Timo Teräs9e7a53c2014-04-24 10:22:37 +03005098 vty_out (vty, " neighbor %s next-hop-self%s%s", addr,
5099 peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ?
5100 " all" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005101
5102 /* Remove private AS. */
5103 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
5104 && ! peer->af_group[afi][safi])
5105 vty_out (vty, " neighbor %s remove-private-AS%s",
5106 addr, VTY_NEWLINE);
5107
5108 /* send-community print. */
5109 if (! peer->af_group[afi][safi])
5110 {
5111 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5112 {
5113 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5114 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5115 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
5116 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5117 vty_out (vty, " neighbor %s send-community extended%s",
5118 addr, VTY_NEWLINE);
5119 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5120 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
5121 }
5122 else
5123 {
5124 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5125 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5126 vty_out (vty, " no neighbor %s send-community both%s",
5127 addr, VTY_NEWLINE);
5128 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5129 vty_out (vty, " no neighbor %s send-community extended%s",
5130 addr, VTY_NEWLINE);
5131 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5132 vty_out (vty, " no neighbor %s send-community%s",
5133 addr, VTY_NEWLINE);
5134 }
5135 }
5136
5137 /* Default information */
5138 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5139 && ! peer->af_group[afi][safi])
5140 {
5141 vty_out (vty, " neighbor %s default-originate", addr);
5142 if (peer->default_rmap[afi][safi].name)
5143 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5144 vty_out (vty, "%s", VTY_NEWLINE);
5145 }
5146
5147 /* Soft reconfiguration inbound. */
5148 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5149 if (! peer->af_group[afi][safi] ||
5150 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5151 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5152 VTY_NEWLINE);
5153
5154 /* maximum-prefix. */
5155 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5156 if (! peer->af_group[afi][safi]
5157 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005158 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005159 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5160 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005161 {
hasso0a486e52005-02-01 20:57:17 +00005162 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5163 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5164 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5165 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5166 vty_out (vty, " warning-only");
5167 if (peer->pmax_restart[afi][safi])
5168 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5169 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005170 }
paul718e3742002-12-13 20:15:29 +00005171
5172 /* Route server client. */
5173 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5174 && ! peer->af_group[afi][safi])
5175 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5176
Dylan Hall3cf12882011-10-27 15:28:17 +04005177 /* Nexthop-local unchanged. */
5178 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5179 && ! peer->af_group[afi][safi])
5180 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5181
paul718e3742002-12-13 20:15:29 +00005182 /* Allow AS in. */
5183 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5184 if (! peer_group_active (peer)
5185 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5186 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5187 {
5188 if (peer->allowas_in[afi][safi] == 3)
5189 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5190 else
5191 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5192 peer->allowas_in[afi][safi], VTY_NEWLINE);
5193 }
5194
5195 /* Filter. */
5196 bgp_config_write_filter (vty, peer, afi, safi);
5197
5198 /* atribute-unchanged. */
5199 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5200 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5201 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5202 && ! peer->af_group[afi][safi])
5203 {
5204 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5205 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5206 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5207 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5208 else
5209 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5210 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5211 " as-path" : "",
5212 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5213 " next-hop" : "",
5214 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5215 " med" : "", VTY_NEWLINE);
5216 }
5217}
5218
5219/* Display "address-family" configuration header. */
5220void
5221bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5222 int *write)
5223{
5224 if (*write)
5225 return;
5226
5227 if (afi == AFI_IP && safi == SAFI_UNICAST)
5228 return;
5229
5230 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5231
5232 if (afi == AFI_IP)
5233 {
5234 if (safi == SAFI_MULTICAST)
5235 vty_out (vty, "ipv4 multicast");
5236 else if (safi == SAFI_MPLS_VPN)
Lou Bergera3fda882016-01-12 13:42:04 -05005237 vty_out (vty, "vpnv4");
5238 else if (safi == SAFI_ENCAP)
5239 vty_out (vty, "encap");
paul718e3742002-12-13 20:15:29 +00005240 }
5241 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005242 {
Lou Berger13c378d2016-01-12 13:41:56 -05005243 if (safi == SAFI_MPLS_VPN)
5244 vty_out (vty, "vpnv6");
Lou Bergera3fda882016-01-12 13:42:04 -05005245 else if (safi == SAFI_ENCAP)
5246 vty_out (vty, "encapv6");
Lou Berger13c378d2016-01-12 13:41:56 -05005247 else
5248 {
5249 vty_out (vty, "ipv6");
5250 if (safi == SAFI_MULTICAST)
5251 vty_out (vty, " multicast");
5252 }
Paul Jakma37a217a2007-04-10 19:20:29 +00005253 }
paul718e3742002-12-13 20:15:29 +00005254
5255 vty_out (vty, "%s", VTY_NEWLINE);
5256
5257 *write = 1;
5258}
5259
5260/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005261static int
paul718e3742002-12-13 20:15:29 +00005262bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5263 safi_t safi)
5264{
5265 int write = 0;
5266 struct peer *peer;
5267 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005268 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005269
5270 bgp_config_write_network (vty, bgp, afi, safi, &write);
5271
5272 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5273
paul1eb8ef22005-04-07 07:30:20 +00005274 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005275 {
5276 if (group->conf->afc[afi][safi])
5277 {
5278 bgp_config_write_family_header (vty, afi, safi, &write);
5279 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5280 }
5281 }
paul1eb8ef22005-04-07 07:30:20 +00005282 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005283 {
5284 if (peer->afc[afi][safi])
5285 {
5286 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5287 {
5288 bgp_config_write_family_header (vty, afi, safi, &write);
5289 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5290 }
5291 }
5292 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005293
5294 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5295
Roman Hoog Antink6184c392014-03-17 14:01:42 +01005296 bgp_config_write_distance (vty, bgp, afi, safi, &write);
5297
paul718e3742002-12-13 20:15:29 +00005298 if (write)
5299 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5300
5301 return write;
5302}
5303
5304int
5305bgp_config_write (struct vty *vty)
5306{
5307 int write = 0;
5308 struct bgp *bgp;
5309 struct peer_group *group;
5310 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005311 struct listnode *node, *nnode;
5312 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005313
5314 /* BGP Multiple instance. */
5315 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5316 {
5317 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5318 write++;
5319 }
5320
5321 /* BGP Config type. */
5322 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5323 {
5324 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5325 write++;
5326 }
5327
5328 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005329 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005330 {
5331 if (write)
5332 vty_out (vty, "!%s", VTY_NEWLINE);
5333
5334 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005335 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005336
5337 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5338 {
5339 if (bgp->name)
5340 vty_out (vty, " view %s", bgp->name);
5341 }
5342 vty_out (vty, "%s", VTY_NEWLINE);
5343
5344 /* No Synchronization */
5345 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5346 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5347
5348 /* BGP fast-external-failover. */
5349 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5350 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5351
5352 /* BGP router ID. */
5353 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5354 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5355 VTY_NEWLINE);
5356
paul848973c2003-08-13 00:32:49 +00005357 /* BGP log-neighbor-changes. */
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07005358 if (!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5359 vty_out (vty, " no bgp log-neighbor-changes%s", VTY_NEWLINE);
paul848973c2003-08-13 00:32:49 +00005360
paul718e3742002-12-13 20:15:29 +00005361 /* BGP configuration. */
5362 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5363 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5364
5365 /* BGP default ipv4-unicast. */
5366 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5367 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5368
5369 /* BGP default local-preference. */
5370 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5371 vty_out (vty, " bgp default local-preference %d%s",
5372 bgp->default_local_pref, VTY_NEWLINE);
5373
5374 /* BGP client-to-client reflection. */
5375 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5376 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5377
5378 /* BGP cluster ID. */
5379 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5380 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5381 VTY_NEWLINE);
5382
hassoe0701b72004-05-20 09:19:34 +00005383 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005384 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005385 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5386 VTY_NEWLINE);
5387
5388 /* Confederation peer */
5389 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005390 {
hassoe0701b72004-05-20 09:19:34 +00005391 int i;
paul718e3742002-12-13 20:15:29 +00005392
hassoe0701b72004-05-20 09:19:34 +00005393 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005394
hassoe0701b72004-05-20 09:19:34 +00005395 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005396 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005397
hassoe0701b72004-05-20 09:19:34 +00005398 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005399 }
5400
5401 /* BGP enforce-first-as. */
5402 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5403 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5404
5405 /* BGP deterministic-med. */
5406 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5407 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005408
5409 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005410 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5411 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5412 bgp->stalepath_time, VTY_NEWLINE);
Philippe Guibert4afa3dd2016-05-24 16:52:02 +02005413 if (bgp->restart_time != BGP_DEFAULT_RESTART_TIME)
5414 vty_out (vty, " bgp graceful-restart restart-time %d%s",
5415 bgp->restart_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005416 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5417 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5418
paul718e3742002-12-13 20:15:29 +00005419 /* BGP bestpath method. */
5420 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5421 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005422 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5423 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
Pradosh Mohapatra2fdd4552013-09-07 07:02:36 +00005424 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
5425 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
5426 }
Dinesh Dutt083e5e22015-11-09 20:21:54 -05005427 if (bgp_flag_check (bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
5428 vty_out (vty, " bgp route-reflector allow-outbound-policy%s",
5429 VTY_NEWLINE);
5430 }
paul718e3742002-12-13 20:15:29 +00005431 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5432 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5433 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5434 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5435 {
5436 vty_out (vty, " bgp bestpath med");
5437 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5438 vty_out (vty, " confed");
5439 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5440 vty_out (vty, " missing-as-worst");
5441 vty_out (vty, "%s", VTY_NEWLINE);
5442 }
5443
5444 /* BGP network import check. */
5445 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5446 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5447
paul718e3742002-12-13 20:15:29 +00005448 /* BGP flag dampening. */
5449 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5450 BGP_CONFIG_DAMPENING))
5451 bgp_config_write_damp (vty);
5452
5453 /* BGP static route configuration. */
5454 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5455
5456 /* BGP redistribute configuration. */
5457 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5458
5459 /* BGP timers configuration. */
5460 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5461 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5462 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5463 bgp->default_holdtime, VTY_NEWLINE);
5464
5465 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005466 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005467 {
5468 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5469 }
5470
5471 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005472 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005473 {
5474 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5475 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5476 }
5477
Josh Bailey165b5ff2011-07-20 20:43:22 -07005478 /* maximum-paths */
5479 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5480
paul718e3742002-12-13 20:15:29 +00005481 /* Distance configuration. */
Roman Hoog Antink6184c392014-03-17 14:01:42 +01005482 bgp_config_write_distance (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
paul718e3742002-12-13 20:15:29 +00005483
5484 /* No auto-summary */
5485 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5486 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5487
5488 /* IPv4 multicast configuration. */
5489 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5490
5491 /* IPv4 VPN configuration. */
5492 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5493
Lou Bergera3fda882016-01-12 13:42:04 -05005494 /* ENCAPv4 configuration. */
5495 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_ENCAP);
5496
paul718e3742002-12-13 20:15:29 +00005497 /* IPv6 unicast configuration. */
5498 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5499
Paul Jakma37a217a2007-04-10 19:20:29 +00005500 /* IPv6 multicast configuration. */
5501 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5502
Lou Berger13c378d2016-01-12 13:41:56 -05005503 /* IPv6 VPN configuration. */
5504 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MPLS_VPN);
5505
Lou Bergera3fda882016-01-12 13:42:04 -05005506 /* ENCAPv6 configuration. */
5507 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_ENCAP);
5508
5509 vty_out (vty, " exit%s", VTY_NEWLINE);
5510
paul718e3742002-12-13 20:15:29 +00005511 write++;
5512 }
5513 return write;
5514}
5515
5516void
paul94f2b392005-06-28 12:44:16 +00005517bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005518{
5519 memset (&bgp_master, 0, sizeof (struct bgp_master));
5520
5521 bm = &bgp_master;
5522 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005523 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005524 bm->port = BGP_PORT_DEFAULT;
5525 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005526 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005527}
paul200df112005-06-01 11:17:05 +00005528
David Lamparter6b0655a2014-06-04 06:53:35 +02005529
paul718e3742002-12-13 20:15:29 +00005530void
paul94f2b392005-06-28 12:44:16 +00005531bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005532{
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07005533
5534 /* allocates some vital data structures used by peer commands in vty_init */
5535 bgp_scan_init ();
paul718e3742002-12-13 20:15:29 +00005536
paul718e3742002-12-13 20:15:29 +00005537 /* Init zebra. */
Donald Sharp774914f2015-10-14 08:50:39 -04005538 bgp_zebra_init (bm->master);
paul718e3742002-12-13 20:15:29 +00005539
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07005540 /* BGP VTY commands installation. */
5541 bgp_vty_init ();
5542
paul718e3742002-12-13 20:15:29 +00005543 /* BGP inits. */
5544 bgp_attr_init ();
5545 bgp_debug_init ();
5546 bgp_dump_init ();
5547 bgp_route_init ();
5548 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005549 bgp_address_init ();
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07005550 bgp_scan_vty_init();
paul718e3742002-12-13 20:15:29 +00005551 bgp_mplsvpn_init ();
Lou Berger298cc2f2016-01-12 13:42:02 -05005552 bgp_encap_init ();
paul718e3742002-12-13 20:15:29 +00005553
5554 /* Access list initialize. */
5555 access_list_init ();
5556 access_list_add_hook (peer_distribute_update);
5557 access_list_delete_hook (peer_distribute_update);
5558
5559 /* Filter list initialize. */
5560 bgp_filter_init ();
5561 as_list_add_hook (peer_aslist_update);
5562 as_list_delete_hook (peer_aslist_update);
5563
5564 /* Prefix list initialize.*/
5565 prefix_list_init ();
5566 prefix_list_add_hook (peer_prefix_list_update);
5567 prefix_list_delete_hook (peer_prefix_list_update);
5568
5569 /* Community list initialize. */
5570 bgp_clist = community_list_init ();
5571
5572#ifdef HAVE_SNMP
5573 bgp_snmp_init ();
5574#endif /* HAVE_SNMP */
5575}
paul545acaf2004-04-20 15:13:15 +00005576
5577void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005578bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005579{
paul545acaf2004-04-20 15:13:15 +00005580 struct bgp *bgp;
5581 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005582 struct listnode *node, *nnode;
5583 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005584
paul1eb8ef22005-04-07 07:30:20 +00005585 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5586 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005587 if (peer->status == Established)
5588 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5589 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005590
paul545acaf2004-04-20 15:13:15 +00005591 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005592
paule210cf92005-06-15 19:15:35 +00005593 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005594 {
5595 work_queue_free (bm->process_main_queue);
5596 bm->process_main_queue = NULL;
5597 }
paule210cf92005-06-15 19:15:35 +00005598 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005599 {
5600 work_queue_free (bm->process_rsclient_queue);
5601 bm->process_rsclient_queue = NULL;
5602 }
paul545acaf2004-04-20 15:13:15 +00005603}