blob: 018a599411019866157a97e8b653366668c4d650 [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;
649 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
650 if (peer->update_source)
651 {
652 sockunion_free (peer->update_source);
653 peer->update_source = NULL;
654 }
655 if (peer->update_if)
656 {
657 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
658 peer->update_if = NULL;
659 }
660
661 if (peer_sort (peer) == BGP_PEER_IBGP)
662 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
663 else
664 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
665
666 peer->flags = 0;
667 peer->config = 0;
668 peer->holdtime = 0;
669 peer->keepalive = 0;
670 peer->connect = 0;
671 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
672}
673
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000674/* Check peer's AS number and determines if this peer is IBGP or EBGP */
675static bgp_peer_sort_t
676peer_calc_sort (struct peer *peer)
paul718e3742002-12-13 20:15:29 +0000677{
678 struct bgp *bgp;
679
680 bgp = peer->bgp;
681
682 /* Peer-group */
683 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
684 {
685 if (peer->as)
686 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
687 else
688 {
689 struct peer *peer1;
690 peer1 = listnode_head (peer->group->peer);
691 if (peer1)
692 return (peer1->local_as == peer1->as
693 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
694 }
695 return BGP_PEER_INTERNAL;
696 }
697
698 /* Normal peer */
699 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
700 {
701 if (peer->local_as == 0)
702 return BGP_PEER_INTERNAL;
703
704 if (peer->local_as == peer->as)
705 {
706 if (peer->local_as == bgp->confed_id)
707 return BGP_PEER_EBGP;
708 else
709 return BGP_PEER_IBGP;
710 }
711
712 if (bgp_confederation_peers_check (bgp, peer->as))
713 return BGP_PEER_CONFED;
714
715 return BGP_PEER_EBGP;
716 }
717 else
718 {
719 return (peer->local_as == 0
720 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
721 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
722 }
723}
724
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000725/* Calculate and cache the peer "sort" */
726bgp_peer_sort_t
727peer_sort (struct peer *peer)
728{
729 peer->sort = peer_calc_sort (peer);
730 return peer->sort;
731}
732
Paul Jakmaf63f06d2011-04-08 12:44:43 +0100733static void
paul200df112005-06-01 11:17:05 +0000734peer_free (struct peer *peer)
735{
Paul Jakmaca058a32006-09-14 02:58:49 +0000736 assert (peer->status == Deleted);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700737
738 bgp_unlock(peer->bgp);
739
Paul Jakmaca058a32006-09-14 02:58:49 +0000740 /* this /ought/ to have been done already through bgp_stop earlier,
741 * but just to be sure..
742 */
743 bgp_timer_set (peer);
744 BGP_READ_OFF (peer->t_read);
745 BGP_WRITE_OFF (peer->t_write);
Paul Jakma9fde6622006-09-14 03:02:02 +0000746 BGP_EVENT_FLUSH (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +0000747
paul200df112005-06-01 11:17:05 +0000748 if (peer->desc)
Daniel Walton363c9032015-10-21 06:42:54 -0700749 {
750 XFREE (MTYPE_PEER_DESC, peer->desc);
751 peer->desc = NULL;
752 }
paul200df112005-06-01 11:17:05 +0000753
754 /* Free allocated host character. */
755 if (peer->host)
Daniel Walton363c9032015-10-21 06:42:54 -0700756 {
757 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
758 peer->host = NULL;
759 }
760
paul200df112005-06-01 11:17:05 +0000761 /* Update source configuration. */
762 if (peer->update_source)
Daniel Walton363c9032015-10-21 06:42:54 -0700763 {
764 sockunion_free (peer->update_source);
765 peer->update_source = NULL;
766 }
paul200df112005-06-01 11:17:05 +0000767
768 if (peer->update_if)
Daniel Walton363c9032015-10-21 06:42:54 -0700769 {
770 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
771 peer->update_if = NULL;
772 }
Paul Jakmaa625ca32006-03-30 14:12:38 +0000773
774 if (peer->clear_node_queue)
Daniel Walton363c9032015-10-21 06:42:54 -0700775 {
776 work_queue_free(peer->clear_node_queue);
777 peer->clear_node_queue = NULL;
778 }
Paul Jakmaa625ca32006-03-30 14:12:38 +0000779
Lou Berger056f3762013-04-10 12:30:04 -0700780 if (peer->notify.data)
781 XFREE(MTYPE_TMP, peer->notify.data);
782
Paul Jakmaca058a32006-09-14 02:58:49 +0000783 bgp_sync_delete (peer);
paul200df112005-06-01 11:17:05 +0000784 memset (peer, 0, sizeof (struct peer));
785
786 XFREE (MTYPE_BGP_PEER, peer);
787}
788
789/* increase reference count on a struct peer */
790struct peer *
Donald Sharp104576d2015-09-16 13:17:55 -0400791peer_lock_with_caller (const char *name, struct peer *peer)
paul200df112005-06-01 11:17:05 +0000792{
793 assert (peer && (peer->lock >= 0));
Donald Sharp104576d2015-09-16 13:17:55 -0400794
795#if 0
796 zlog_debug("%s peer_lock %p %d", name, peer, peer->lock);
797#endif
798
paul200df112005-06-01 11:17:05 +0000799 peer->lock++;
800
801 return peer;
802}
803
804/* decrease reference count on a struct peer
805 * struct peer is freed and NULL returned if last reference
806 */
807struct peer *
Donald Sharp104576d2015-09-16 13:17:55 -0400808peer_unlock_with_caller (const char *name, struct peer *peer)
paul200df112005-06-01 11:17:05 +0000809{
810 assert (peer && (peer->lock > 0));
Donald Sharp104576d2015-09-16 13:17:55 -0400811
812#if 0
813 zlog_debug("%s peer_unlock %p %d", name, peer, peer->lock);
814#endif
815
paul200df112005-06-01 11:17:05 +0000816 peer->lock--;
817
818 if (peer->lock == 0)
819 {
paul200df112005-06-01 11:17:05 +0000820 peer_free (peer);
821 return NULL;
822 }
823
paul200df112005-06-01 11:17:05 +0000824 return peer;
825}
826
827/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000828static struct peer *
Paul Jakma6f585442006-10-22 19:13:07 +0000829peer_new (struct bgp *bgp)
paul718e3742002-12-13 20:15:29 +0000830{
831 afi_t afi;
832 safi_t safi;
833 struct peer *peer;
834 struct servent *sp;
Paul Jakma6f585442006-10-22 19:13:07 +0000835
836 /* bgp argument is absolutely required */
837 assert (bgp);
838 if (!bgp)
839 return NULL;
840
paul718e3742002-12-13 20:15:29 +0000841 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000842 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000843
844 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000845 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000846 peer->v_start = BGP_INIT_START_TIMER;
847 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
paul718e3742002-12-13 20:15:29 +0000848 peer->status = Idle;
849 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000850 peer->weight = 0;
Paul Jakma0df7c912008-07-21 21:02:49 +0000851 peer->password = NULL;
Paul Jakma6f585442006-10-22 19:13:07 +0000852 peer->bgp = bgp;
Paul Jakmaca058a32006-09-14 02:58:49 +0000853 peer = peer_lock (peer); /* initial reference */
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700854 bgp_lock (bgp);
paul718e3742002-12-13 20:15:29 +0000855
856 /* Set default flags. */
857 for (afi = AFI_IP; afi < AFI_MAX; afi++)
858 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
859 {
860 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
861 {
862 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
863 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
864 }
865 peer->orf_plist[afi][safi] = NULL;
866 }
867 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
868
869 /* Create buffers. */
870 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
871 peer->obuf = stream_fifo_new ();
Daniel Walton5bcd7542015-05-19 17:58:10 -0700872
873 /* We use a larger buffer for peer->work in the event that:
874 * - We RX a BGP_UPDATE where the attributes alone are just
875 * under BGP_MAX_PACKET_SIZE
876 * - The user configures an outbound route-map that does many as-path
877 * prepends or adds many communities. At most they can have CMD_ARGC_MAX
878 * args in a route-map so there is a finite limit on how large they can
879 * make the attributes.
880 *
881 * Having a buffer with BGP_MAX_PACKET_SIZE_OVERFLOW allows us to avoid bounds
882 * checking for every single attribute as we construct an UPDATE.
883 */
884 peer->work = stream_new (BGP_MAX_PACKET_SIZE + BGP_MAX_PACKET_SIZE_OVERFLOW);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000885 peer->scratch = stream_new (BGP_MAX_PACKET_SIZE);
paul718e3742002-12-13 20:15:29 +0000886
887 bgp_sync_init (peer);
888
889 /* Get service port number. */
890 sp = getservbyname ("bgp", "tcp");
891 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
892
893 return peer;
894}
895
896/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000897static struct peer *
paul718e3742002-12-13 20:15:29 +0000898peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
899 as_t remote_as, afi_t afi, safi_t safi)
900{
901 int active;
902 struct peer *peer;
903 char buf[SU_ADDRSTRLEN];
904
Paul Jakma6f585442006-10-22 19:13:07 +0000905 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000906 peer->su = *su;
907 peer->local_as = local_as;
908 peer->as = remote_as;
909 peer->local_id = bgp->router_id;
910 peer->v_holdtime = bgp->default_holdtime;
911 peer->v_keepalive = bgp->default_keepalive;
912 if (peer_sort (peer) == BGP_PEER_IBGP)
913 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
914 else
915 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000916
917 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000918 listnode_add_sort (bgp->peer, peer);
919
920 active = peer_active (peer);
921
922 if (afi && safi)
923 peer->afc[afi][safi] = 1;
924
Stephen Hemminger65957882010-01-15 16:22:10 +0300925 /* Last read and reset time set */
926 peer->readtime = peer->resettime = bgp_clock ();
paul848973c2003-08-13 00:32:49 +0000927
paul718e3742002-12-13 20:15:29 +0000928 /* Default TTL set. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000929 peer->ttl = (peer->sort == BGP_PEER_IBGP) ? 255 : 1;
paul718e3742002-12-13 20:15:29 +0000930
931 /* Make peer's address string. */
932 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000933 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000934
935 /* Set up peer's events and timers. */
936 if (! active && peer_active (peer))
937 bgp_timer_set (peer);
938
939 return peer;
940}
941
pauleb821182004-05-01 08:44:08 +0000942/* Make accept BGP peer. Called from bgp_accept (). */
943struct peer *
944peer_create_accept (struct bgp *bgp)
945{
946 struct peer *peer;
947
Paul Jakma6f585442006-10-22 19:13:07 +0000948 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000949
950 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000951 listnode_add_sort (bgp->peer, peer);
952
953 return peer;
954}
955
paul718e3742002-12-13 20:15:29 +0000956/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000957static void
paul718e3742002-12-13 20:15:29 +0000958peer_as_change (struct peer *peer, as_t as)
959{
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000960 bgp_peer_sort_t type;
Daniel Walton0d7435f2015-10-22 11:35:20 +0300961 struct peer *conf;
paul718e3742002-12-13 20:15:29 +0000962
963 /* Stop peer. */
964 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
965 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000966 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000967 {
968 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
969 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
970 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
971 }
paul718e3742002-12-13 20:15:29 +0000972 else
973 BGP_EVENT_ADD (peer, BGP_Stop);
974 }
975 type = peer_sort (peer);
976 peer->as = as;
977
paul848973c2003-08-13 00:32:49 +0000978 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
979 && ! bgp_confederation_peers_check (peer->bgp, as)
980 && peer->bgp->as != as)
981 peer->local_as = peer->bgp->confed_id;
982 else
983 peer->local_as = peer->bgp->as;
984
paul718e3742002-12-13 20:15:29 +0000985 /* Advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +0300986 conf = NULL;
987 if (peer->group)
988 conf = peer->group->conf;
989
990 if (conf && CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
991 peer->v_routeadv = conf->routeadv;
paul718e3742002-12-13 20:15:29 +0000992 else
Daniel Walton0d7435f2015-10-22 11:35:20 +0300993 if (peer_sort (peer) == BGP_PEER_IBGP)
994 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
995 else
996 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul718e3742002-12-13 20:15:29 +0000997
998 /* TTL reset */
999 if (peer_sort (peer) == BGP_PEER_IBGP)
1000 peer->ttl = 255;
1001 else if (type == BGP_PEER_IBGP)
1002 peer->ttl = 1;
1003
1004 /* reflector-client reset */
1005 if (peer_sort (peer) != BGP_PEER_IBGP)
1006 {
1007 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
1008 PEER_FLAG_REFLECTOR_CLIENT);
1009 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
1010 PEER_FLAG_REFLECTOR_CLIENT);
1011 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
1012 PEER_FLAG_REFLECTOR_CLIENT);
Lou Berger298cc2f2016-01-12 13:42:02 -05001013 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_ENCAP],
1014 PEER_FLAG_REFLECTOR_CLIENT);
paul718e3742002-12-13 20:15:29 +00001015 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
1016 PEER_FLAG_REFLECTOR_CLIENT);
1017 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
1018 PEER_FLAG_REFLECTOR_CLIENT);
Lou Berger9da04bc2016-01-12 13:41:55 -05001019 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MPLS_VPN],
1020 PEER_FLAG_REFLECTOR_CLIENT);
Lou Berger298cc2f2016-01-12 13:42:02 -05001021 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_ENCAP],
1022 PEER_FLAG_REFLECTOR_CLIENT);
paul718e3742002-12-13 20:15:29 +00001023 }
1024
1025 /* local-as reset */
1026 if (peer_sort (peer) != BGP_PEER_EBGP)
1027 {
1028 peer->change_local_as = 0;
1029 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001030 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001031 }
1032}
1033
1034/* If peer does not exist, create new one. If peer already exists,
1035 set AS number to the peer. */
1036int
1037peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
1038 afi_t afi, safi_t safi)
1039{
1040 struct peer *peer;
1041 as_t local_as;
1042
1043 peer = peer_lookup (bgp, su);
1044
1045 if (peer)
1046 {
1047 /* When this peer is a member of peer-group. */
1048 if (peer->group)
1049 {
1050 if (peer->group->conf->as)
1051 {
1052 /* Return peer group's AS number. */
1053 *as = peer->group->conf->as;
1054 return BGP_ERR_PEER_GROUP_MEMBER;
1055 }
1056 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
1057 {
1058 if (bgp->as != *as)
1059 {
1060 *as = peer->as;
1061 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1062 }
1063 }
1064 else
1065 {
1066 if (bgp->as == *as)
1067 {
1068 *as = peer->as;
1069 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1070 }
1071 }
1072 }
1073
1074 /* Existing peer's AS number change. */
1075 if (peer->as != *as)
1076 peer_as_change (peer, *as);
1077 }
1078 else
1079 {
1080
1081 /* If the peer is not part of our confederation, and its not an
1082 iBGP peer then spoof the source AS */
1083 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1084 && ! bgp_confederation_peers_check (bgp, *as)
1085 && bgp->as != *as)
1086 local_as = bgp->confed_id;
1087 else
1088 local_as = bgp->as;
1089
1090 /* If this is IPv4 unicast configuration and "no bgp default
1091 ipv4-unicast" is specified. */
1092
1093 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1094 && afi == AFI_IP && safi == SAFI_UNICAST)
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001095 peer_create (su, bgp, local_as, *as, 0, 0);
paul718e3742002-12-13 20:15:29 +00001096 else
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001097 peer_create (su, bgp, local_as, *as, afi, safi);
paul718e3742002-12-13 20:15:29 +00001098 }
1099
1100 return 0;
1101}
1102
1103/* Activate the peer or peer group for specified AFI and SAFI. */
1104int
1105peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1106{
1107 int active;
1108
1109 if (peer->afc[afi][safi])
1110 return 0;
1111
1112 /* Activate the address family configuration. */
1113 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1114 peer->afc[afi][safi] = 1;
1115 else
1116 {
1117 active = peer_active (peer);
1118
1119 peer->afc[afi][safi] = 1;
1120
1121 if (! active && peer_active (peer))
1122 bgp_timer_set (peer);
1123 else
1124 {
1125 if (peer->status == Established)
1126 {
1127 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1128 {
1129 peer->afc_adv[afi][safi] = 1;
1130 bgp_capability_send (peer, afi, safi,
1131 CAPABILITY_CODE_MP,
1132 CAPABILITY_ACTION_SET);
1133 if (peer->afc_recv[afi][safi])
1134 {
1135 peer->afc_nego[afi][safi] = 1;
1136 bgp_announce_route (peer, afi, safi);
1137 }
1138 }
1139 else
hassoe0701b72004-05-20 09:19:34 +00001140 {
1141 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1142 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1143 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1144 }
paul718e3742002-12-13 20:15:29 +00001145 }
1146 }
1147 }
1148 return 0;
1149}
1150
1151int
1152peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1153{
1154 struct peer_group *group;
1155 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001156 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001157
1158 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1159 {
1160 group = peer->group;
1161
paul1eb8ef22005-04-07 07:30:20 +00001162 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001163 {
1164 if (peer1->af_group[afi][safi])
1165 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1166 }
1167 }
1168 else
1169 {
1170 if (peer->af_group[afi][safi])
1171 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1172 }
1173
1174 if (! peer->afc[afi][safi])
1175 return 0;
1176
1177 /* De-activate the address family configuration. */
1178 peer->afc[afi][safi] = 0;
1179 peer_af_flag_reset (peer, afi, safi);
1180
1181 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1182 {
1183 if (peer->status == Established)
1184 {
1185 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1186 {
1187 peer->afc_adv[afi][safi] = 0;
1188 peer->afc_nego[afi][safi] = 0;
1189
1190 if (peer_active_nego (peer))
1191 {
1192 bgp_capability_send (peer, afi, safi,
1193 CAPABILITY_CODE_MP,
1194 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001195 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001196 peer->pcount[afi][safi] = 0;
1197 }
1198 else
hassoe0701b72004-05-20 09:19:34 +00001199 {
1200 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1201 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1202 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1203 }
paul718e3742002-12-13 20:15:29 +00001204 }
1205 else
hassoe0701b72004-05-20 09:19:34 +00001206 {
1207 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1208 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1209 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1210 }
paul718e3742002-12-13 20:15:29 +00001211 }
1212 }
1213 return 0;
1214}
1215
David Lamparterdfb9bd72016-05-24 18:58:07 +02001216int
1217peer_afc_set (struct peer *peer, afi_t afi, safi_t safi, int enable)
1218{
1219 if (enable)
1220 return peer_activate (peer, afi, safi);
1221 else
1222 return peer_deactivate (peer, afi, safi);
1223}
1224
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001225static void
hasso93406d82005-02-02 14:40:33 +00001226peer_nsf_stop (struct peer *peer)
1227{
1228 afi_t afi;
1229 safi_t safi;
1230
1231 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1232 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1233
1234 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +04001235 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +00001236 peer->nsf[afi][safi] = 0;
1237
1238 if (peer->t_gr_restart)
1239 {
1240 BGP_TIMER_OFF (peer->t_gr_restart);
1241 if (BGP_DEBUG (events, EVENTS))
1242 zlog_debug ("%s graceful restart timer stopped", peer->host);
1243 }
1244 if (peer->t_gr_stale)
1245 {
1246 BGP_TIMER_OFF (peer->t_gr_stale);
1247 if (BGP_DEBUG (events, EVENTS))
1248 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1249 }
1250 bgp_clear_route_all (peer);
1251}
1252
Paul Jakmaca058a32006-09-14 02:58:49 +00001253/* Delete peer from confguration.
1254 *
1255 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1256 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1257 *
1258 * This function /should/ take care to be idempotent, to guard against
1259 * it being called multiple times through stray events that come in
1260 * that happen to result in this function being called again. That
1261 * said, getting here for a "Deleted" peer is a bug in the neighbour
1262 * FSM.
1263 */
paul718e3742002-12-13 20:15:29 +00001264int
1265peer_delete (struct peer *peer)
1266{
1267 int i;
1268 afi_t afi;
1269 safi_t safi;
1270 struct bgp *bgp;
1271 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001272 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001273
Paul Jakmaca058a32006-09-14 02:58:49 +00001274 assert (peer->status != Deleted);
1275
paul718e3742002-12-13 20:15:29 +00001276 bgp = peer->bgp;
1277
hasso93406d82005-02-02 14:40:33 +00001278 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1279 peer_nsf_stop (peer);
1280
Chris Caputo228da422009-07-18 05:44:03 +00001281 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001282 relationship. */
1283 if (peer->group)
1284 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001285 if ((pn = listnode_lookup (peer->group->peer, peer)))
1286 {
1287 peer = peer_unlock (peer); /* group->peer list reference */
1288 list_delete_node (peer->group->peer, pn);
1289 }
paul718e3742002-12-13 20:15:29 +00001290 peer->group = NULL;
1291 }
paul200df112005-06-01 11:17:05 +00001292
paul718e3742002-12-13 20:15:29 +00001293 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001294 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1295 * executed after peer structure is deleted.
1296 */
hassoe0701b72004-05-20 09:19:34 +00001297 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001298 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001299 bgp_fsm_change_status (peer, Deleted);
Paul Jakma19e6c192016-09-06 17:23:48 +01001300
1301 /* Remove from NHT */
1302 bgp_unlink_nexthop_by_peer (peer);
1303
Paul Jakma0df7c912008-07-21 21:02:49 +00001304 /* Password configuration */
1305 if (peer->password)
1306 {
1307 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1308 peer->password = NULL;
1309
1310 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1311 bgp_md5_set (peer);
1312 }
1313
Paul Jakmaca058a32006-09-14 02:58:49 +00001314 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001315
paul718e3742002-12-13 20:15:29 +00001316 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001317 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1318 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001319 {
Chris Caputo228da422009-07-18 05:44:03 +00001320 peer_unlock (peer); /* bgp peer list reference */
1321 list_delete_node (bgp->peer, pn);
1322 }
paul200df112005-06-01 11:17:05 +00001323
Chris Caputo228da422009-07-18 05:44:03 +00001324 if (peer_rsclient_active (peer)
1325 && (pn = listnode_lookup (bgp->rsclient, peer)))
1326 {
1327 peer_unlock (peer); /* rsclient list reference */
1328 list_delete_node (bgp->rsclient, pn);
1329
1330 /* Clear our own rsclient ribs. */
1331 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1332 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1333 if (CHECK_FLAG(peer->af_flags[afi][safi],
1334 PEER_FLAG_RSERVER_CLIENT))
1335 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001336 }
1337
1338 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1339 member of a peer_group. */
1340 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1341 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1342 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001343 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001344
paul200df112005-06-01 11:17:05 +00001345 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001346 if (peer->ibuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001347 {
1348 stream_free (peer->ibuf);
1349 peer->ibuf = NULL;
1350 }
1351
paul718e3742002-12-13 20:15:29 +00001352 if (peer->obuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001353 {
1354 stream_fifo_free (peer->obuf);
1355 peer->obuf = NULL;
1356 }
1357
paul718e3742002-12-13 20:15:29 +00001358 if (peer->work)
Daniel Walton363c9032015-10-21 06:42:54 -07001359 {
1360 stream_free (peer->work);
1361 peer->work = NULL;
1362 }
1363
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00001364 if (peer->scratch)
Daniel Walton363c9032015-10-21 06:42:54 -07001365 {
1366 stream_free(peer->scratch);
1367 peer->scratch = NULL;
1368 }
Paul Jakma18937402006-07-27 19:05:12 +00001369
paul718e3742002-12-13 20:15:29 +00001370 /* Local and remote addresses. */
1371 if (peer->su_local)
Daniel Walton363c9032015-10-21 06:42:54 -07001372 {
1373 sockunion_free (peer->su_local);
1374 peer->su_local = NULL;
1375 }
1376
paul718e3742002-12-13 20:15:29 +00001377 if (peer->su_remote)
Daniel Walton363c9032015-10-21 06:42:54 -07001378 {
1379 sockunion_free (peer->su_remote);
1380 peer->su_remote = NULL;
1381 }
paul200df112005-06-01 11:17:05 +00001382
paul718e3742002-12-13 20:15:29 +00001383 /* Free filter related memory. */
1384 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1385 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1386 {
1387 filter = &peer->filter[afi][safi];
1388
1389 for (i = FILTER_IN; i < FILTER_MAX; i++)
1390 {
1391 if (filter->dlist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001392 {
1393 free(filter->dlist[i].name);
1394 filter->dlist[i].name = NULL;
1395 }
1396
paul718e3742002-12-13 20:15:29 +00001397 if (filter->plist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001398 {
1399 free(filter->plist[i].name);
1400 filter->plist[i].name = NULL;
1401 }
1402
paul718e3742002-12-13 20:15:29 +00001403 if (filter->aslist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001404 {
1405 free(filter->aslist[i].name);
1406 filter->aslist[i].name = NULL;
1407 }
paul200df112005-06-01 11:17:05 +00001408 }
Daniel Walton363c9032015-10-21 06:42:54 -07001409
paul200df112005-06-01 11:17:05 +00001410 for (i = RMAP_IN; i < RMAP_MAX; i++)
1411 {
paul718e3742002-12-13 20:15:29 +00001412 if (filter->map[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001413 {
1414 free (filter->map[i].name);
1415 filter->map[i].name = NULL;
1416 }
paul718e3742002-12-13 20:15:29 +00001417 }
1418
1419 if (filter->usmap.name)
Daniel Walton363c9032015-10-21 06:42:54 -07001420 {
1421 free (filter->usmap.name);
1422 filter->usmap.name = NULL;
1423 }
paul718e3742002-12-13 20:15:29 +00001424
1425 if (peer->default_rmap[afi][safi].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001426 {
1427 free (peer->default_rmap[afi][safi].name);
1428 peer->default_rmap[afi][safi].name = NULL;
1429 }
paul718e3742002-12-13 20:15:29 +00001430 }
paul200df112005-06-01 11:17:05 +00001431
Lou Berger82dd7072016-01-12 13:41:57 -05001432 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETING))
1433 bgp_peer_clear_node_queue_drain_immediate(peer);
1434
paul200df112005-06-01 11:17:05 +00001435 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001436
1437 return 0;
1438}
David Lamparter6b0655a2014-06-04 06:53:35 +02001439
paul94f2b392005-06-28 12:44:16 +00001440static int
paul718e3742002-12-13 20:15:29 +00001441peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1442{
1443 return strcmp (g1->name, g2->name);
1444}
1445
1446/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001447static int
paul718e3742002-12-13 20:15:29 +00001448peer_group_active (struct peer *peer)
1449{
1450 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1451 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1452 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05001453 || peer->af_group[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00001454 || peer->af_group[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05001455 || peer->af_group[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05001456 || peer->af_group[AFI_IP6][SAFI_MPLS_VPN]
1457 || peer->af_group[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00001458 return 1;
1459 return 0;
1460}
1461
1462/* Peer group cofiguration. */
1463static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001464peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001465{
1466 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1467 sizeof (struct peer_group));
1468}
1469
paul94f2b392005-06-28 12:44:16 +00001470static void
paul718e3742002-12-13 20:15:29 +00001471peer_group_free (struct peer_group *group)
1472{
1473 XFREE (MTYPE_PEER_GROUP, group);
1474}
1475
1476struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001477peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001478{
1479 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001480 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001481
paul1eb8ef22005-04-07 07:30:20 +00001482 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001483 {
1484 if (strcmp (group->name, name) == 0)
1485 return group;
1486 }
1487 return NULL;
1488}
1489
1490struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001491peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001492{
1493 struct peer_group *group;
1494
1495 group = peer_group_lookup (bgp, name);
1496 if (group)
1497 return group;
1498
1499 group = peer_group_new ();
1500 group->bgp = bgp;
1501 group->name = strdup (name);
1502 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001503 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001504 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1505 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001506 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001507 group->conf->group = group;
1508 group->conf->as = 0;
1509 group->conf->ttl = 1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001510 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001511 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1512 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1513 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1514 group->conf->keepalive = 0;
1515 group->conf->holdtime = 0;
1516 group->conf->connect = 0;
1517 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1518 listnode_add_sort (bgp->group, group);
1519
1520 return 0;
1521}
1522
paul94f2b392005-06-28 12:44:16 +00001523static void
paul718e3742002-12-13 20:15:29 +00001524peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1525 afi_t afi, safi_t safi)
1526{
1527 int in = FILTER_IN;
1528 int out = FILTER_OUT;
1529 struct peer *conf;
1530 struct bgp_filter *pfilter;
1531 struct bgp_filter *gfilter;
1532
1533 conf = group->conf;
1534 pfilter = &peer->filter[afi][safi];
1535 gfilter = &conf->filter[afi][safi];
1536
1537 /* remote-as */
1538 if (conf->as)
1539 peer->as = conf->as;
1540
1541 /* remote-as */
1542 if (conf->change_local_as)
1543 peer->change_local_as = conf->change_local_as;
1544
1545 /* TTL */
1546 peer->ttl = conf->ttl;
1547
Nick Hilliardfa411a22011-03-23 15:33:17 +00001548 /* GTSM hops */
1549 peer->gtsm_hops = conf->gtsm_hops;
1550
paul718e3742002-12-13 20:15:29 +00001551 /* Weight */
1552 peer->weight = conf->weight;
1553
1554 /* peer flags apply */
1555 peer->flags = conf->flags;
1556 /* peer af_flags apply */
1557 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1558 /* peer config apply */
1559 peer->config = conf->config;
1560
1561 /* peer timers apply */
1562 peer->holdtime = conf->holdtime;
1563 peer->keepalive = conf->keepalive;
1564 peer->connect = conf->connect;
1565 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1566 peer->v_connect = conf->connect;
1567 else
1568 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1569
1570 /* advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +03001571 if (CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
1572 peer->v_routeadv = conf->routeadv;
paul718e3742002-12-13 20:15:29 +00001573 else
Daniel Walton0d7435f2015-10-22 11:35:20 +03001574 if (peer_sort (peer) == BGP_PEER_IBGP)
1575 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1576 else
1577 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul718e3742002-12-13 20:15:29 +00001578
Paul Jakma0df7c912008-07-21 21:02:49 +00001579 /* password apply */
Roman Hoog Antink0e4303d2013-01-18 13:52:03 +01001580 if (conf->password && !peer->password)
Paul Jakma0df7c912008-07-21 21:02:49 +00001581 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
Paul Jakma0df7c912008-07-21 21:02:49 +00001582
1583 bgp_md5_set (peer);
1584
paul718e3742002-12-13 20:15:29 +00001585 /* maximum-prefix */
1586 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001587 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001588 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001589
1590 /* allowas-in */
1591 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1592
paulfee0f4c2004-09-13 05:12:46 +00001593 /* route-server-client */
1594 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1595 {
1596 /* Make peer's RIB point to group's RIB. */
1597 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1598
1599 /* Import policy. */
1600 if (pfilter->map[RMAP_IMPORT].name)
1601 free (pfilter->map[RMAP_IMPORT].name);
1602 if (gfilter->map[RMAP_IMPORT].name)
1603 {
1604 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1605 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1606 }
1607 else
1608 {
1609 pfilter->map[RMAP_IMPORT].name = NULL;
1610 pfilter->map[RMAP_IMPORT].map = NULL;
1611 }
1612
1613 /* Export policy. */
1614 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1615 {
1616 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1617 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1618 }
1619 }
1620
paul718e3742002-12-13 20:15:29 +00001621 /* default-originate route-map */
1622 if (conf->default_rmap[afi][safi].name)
1623 {
1624 if (peer->default_rmap[afi][safi].name)
1625 free (peer->default_rmap[afi][safi].name);
1626 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1627 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1628 }
1629
1630 /* update-source apply */
1631 if (conf->update_source)
1632 {
1633 if (peer->update_source)
1634 sockunion_free (peer->update_source);
1635 if (peer->update_if)
1636 {
1637 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1638 peer->update_if = NULL;
1639 }
1640 peer->update_source = sockunion_dup (conf->update_source);
1641 }
1642 else if (conf->update_if)
1643 {
1644 if (peer->update_if)
1645 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1646 if (peer->update_source)
1647 {
1648 sockunion_free (peer->update_source);
1649 peer->update_source = NULL;
1650 }
1651 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1652 }
1653
1654 /* inbound filter apply */
1655 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1656 {
1657 if (pfilter->dlist[in].name)
1658 free (pfilter->dlist[in].name);
1659 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1660 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1661 }
1662 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1663 {
1664 if (pfilter->plist[in].name)
1665 free (pfilter->plist[in].name);
1666 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1667 pfilter->plist[in].plist = gfilter->plist[in].plist;
1668 }
1669 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1670 {
1671 if (pfilter->aslist[in].name)
1672 free (pfilter->aslist[in].name);
1673 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1674 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1675 }
paulfee0f4c2004-09-13 05:12:46 +00001676 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001677 {
paulfee0f4c2004-09-13 05:12:46 +00001678 if (pfilter->map[RMAP_IN].name)
1679 free (pfilter->map[RMAP_IN].name);
1680 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1681 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001682 }
1683
1684 /* outbound filter apply */
1685 if (gfilter->dlist[out].name)
1686 {
1687 if (pfilter->dlist[out].name)
1688 free (pfilter->dlist[out].name);
1689 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1690 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1691 }
1692 else
1693 {
1694 if (pfilter->dlist[out].name)
1695 free (pfilter->dlist[out].name);
1696 pfilter->dlist[out].name = NULL;
1697 pfilter->dlist[out].alist = NULL;
1698 }
1699 if (gfilter->plist[out].name)
1700 {
1701 if (pfilter->plist[out].name)
1702 free (pfilter->plist[out].name);
1703 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1704 pfilter->plist[out].plist = gfilter->plist[out].plist;
1705 }
1706 else
1707 {
1708 if (pfilter->plist[out].name)
1709 free (pfilter->plist[out].name);
1710 pfilter->plist[out].name = NULL;
1711 pfilter->plist[out].plist = NULL;
1712 }
1713 if (gfilter->aslist[out].name)
1714 {
1715 if (pfilter->aslist[out].name)
1716 free (pfilter->aslist[out].name);
1717 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1718 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1719 }
1720 else
1721 {
1722 if (pfilter->aslist[out].name)
1723 free (pfilter->aslist[out].name);
1724 pfilter->aslist[out].name = NULL;
1725 pfilter->aslist[out].aslist = NULL;
1726 }
paulfee0f4c2004-09-13 05:12:46 +00001727 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001728 {
paulfee0f4c2004-09-13 05:12:46 +00001729 if (pfilter->map[RMAP_OUT].name)
1730 free (pfilter->map[RMAP_OUT].name);
1731 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1732 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001733 }
1734 else
1735 {
paulfee0f4c2004-09-13 05:12:46 +00001736 if (pfilter->map[RMAP_OUT].name)
1737 free (pfilter->map[RMAP_OUT].name);
1738 pfilter->map[RMAP_OUT].name = NULL;
1739 pfilter->map[RMAP_OUT].map = NULL;
1740 }
1741
1742 /* RS-client's import/export route-maps. */
1743 if (gfilter->map[RMAP_IMPORT].name)
1744 {
1745 if (pfilter->map[RMAP_IMPORT].name)
1746 free (pfilter->map[RMAP_IMPORT].name);
1747 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1748 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1749 }
1750 else
1751 {
1752 if (pfilter->map[RMAP_IMPORT].name)
1753 free (pfilter->map[RMAP_IMPORT].name);
1754 pfilter->map[RMAP_IMPORT].name = NULL;
1755 pfilter->map[RMAP_IMPORT].map = NULL;
1756 }
1757 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1758 {
1759 if (pfilter->map[RMAP_EXPORT].name)
1760 free (pfilter->map[RMAP_EXPORT].name);
1761 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1762 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001763 }
1764
1765 if (gfilter->usmap.name)
1766 {
1767 if (pfilter->usmap.name)
1768 free (pfilter->usmap.name);
1769 pfilter->usmap.name = strdup (gfilter->usmap.name);
1770 pfilter->usmap.map = gfilter->usmap.map;
1771 }
1772 else
1773 {
1774 if (pfilter->usmap.name)
1775 free (pfilter->usmap.name);
1776 pfilter->usmap.name = NULL;
1777 pfilter->usmap.map = NULL;
1778 }
1779}
1780
1781/* Peer group's remote AS configuration. */
1782int
paulfd79ac92004-10-13 05:06:08 +00001783peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001784{
1785 struct peer_group *group;
1786 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001787 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001788
1789 group = peer_group_lookup (bgp, group_name);
1790 if (! group)
1791 return -1;
1792
1793 if (group->conf->as == *as)
1794 return 0;
1795
1796 /* When we setup peer-group AS number all peer group member's AS
1797 number must be updated to same number. */
1798 peer_as_change (group->conf, *as);
1799
paul1eb8ef22005-04-07 07:30:20 +00001800 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001801 {
1802 if (peer->as != *as)
1803 peer_as_change (peer, *as);
1804 }
1805
1806 return 0;
1807}
1808
1809int
1810peer_group_delete (struct peer_group *group)
1811{
1812 struct bgp *bgp;
1813 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001814 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001815
1816 bgp = group->bgp;
1817
paul1eb8ef22005-04-07 07:30:20 +00001818 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001819 {
paul718e3742002-12-13 20:15:29 +00001820 peer_delete (peer);
1821 }
1822 list_delete (group->peer);
1823
1824 free (group->name);
1825 group->name = NULL;
1826
1827 group->conf->group = NULL;
1828 peer_delete (group->conf);
1829
1830 /* Delete from all peer_group list. */
1831 listnode_delete (bgp->group, group);
1832
1833 peer_group_free (group);
1834
1835 return 0;
1836}
1837
1838int
1839peer_group_remote_as_delete (struct peer_group *group)
1840{
1841 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001842 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001843
1844 if (! group->conf->as)
1845 return 0;
1846
paul1eb8ef22005-04-07 07:30:20 +00001847 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001848 {
paul718e3742002-12-13 20:15:29 +00001849 peer_delete (peer);
1850 }
1851 list_delete_all_node (group->peer);
1852
1853 group->conf->as = 0;
1854
1855 return 0;
1856}
1857
1858/* Bind specified peer to peer group. */
1859int
1860peer_group_bind (struct bgp *bgp, union sockunion *su,
1861 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1862{
1863 struct peer *peer;
1864 int first_member = 0;
1865
1866 /* Check peer group's address family. */
1867 if (! group->conf->afc[afi][safi])
1868 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1869
1870 /* Lookup the peer. */
1871 peer = peer_lookup (bgp, su);
1872
1873 /* Create a new peer. */
1874 if (! peer)
1875 {
1876 if (! group->conf->as)
1877 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1878
1879 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1880 peer->group = group;
1881 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001882
Paul Jakmaca058a32006-09-14 02:58:49 +00001883 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001884 listnode_add (group->peer, peer);
1885 peer_group2peer_config_copy (group, peer, afi, safi);
1886
1887 return 0;
1888 }
1889
1890 /* When the peer already belongs to peer group, check the consistency. */
1891 if (peer->af_group[afi][safi])
1892 {
1893 if (strcmp (peer->group->name, group->name) != 0)
1894 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1895
1896 return 0;
1897 }
1898
1899 /* Check current peer group configuration. */
1900 if (peer_group_active (peer)
1901 && strcmp (peer->group->name, group->name) != 0)
1902 return BGP_ERR_PEER_GROUP_MISMATCH;
1903
1904 if (! group->conf->as)
1905 {
1906 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1907 && peer_sort (group->conf) != peer_sort (peer))
1908 {
1909 if (as)
1910 *as = peer->as;
1911 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1912 }
1913
1914 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1915 first_member = 1;
1916 }
1917
1918 peer->af_group[afi][safi] = 1;
1919 peer->afc[afi][safi] = 1;
1920 if (! peer->group)
1921 {
1922 peer->group = group;
paul200df112005-06-01 11:17:05 +00001923
Paul Jakmaca058a32006-09-14 02:58:49 +00001924 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001925 listnode_add (group->peer, peer);
1926 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001927 else
1928 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001929
1930 if (first_member)
1931 {
1932 /* Advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +03001933 if (! CHECK_FLAG (group->conf->config, PEER_CONFIG_ROUTEADV))
1934 {
1935 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1936 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1937 else
1938 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1939 }
paul718e3742002-12-13 20:15:29 +00001940
1941 /* ebgp-multihop reset */
1942 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1943 group->conf->ttl = 255;
1944
1945 /* local-as reset */
1946 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1947 {
1948 group->conf->change_local_as = 0;
1949 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001950 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001951 }
1952 }
paulfee0f4c2004-09-13 05:12:46 +00001953
1954 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1955 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001956 struct listnode *pn;
1957
paulfee0f4c2004-09-13 05:12:46 +00001958 /* If it's not configured as RSERVER_CLIENT in any other address
1959 family, without being member of a peer_group, remove it from
1960 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001961 if (! peer_rsclient_active (peer)
1962 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001963 {
1964 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001965 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001966
1967 /* Clear our own rsclient rib for this afi/safi. */
1968 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001969 }
paulfee0f4c2004-09-13 05:12:46 +00001970
Paul Jakmab608d5b2008-07-02 02:12:07 +00001971 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001972
1973 /* Import policy. */
1974 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1975 {
1976 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1977 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1978 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1979 }
1980
1981 /* Export policy. */
1982 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1983 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1984 {
1985 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1986 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1987 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1988 }
1989 }
1990
paul718e3742002-12-13 20:15:29 +00001991 peer_group2peer_config_copy (group, peer, afi, safi);
1992
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001993 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001994 {
1995 peer->last_reset = PEER_DOWN_RMAP_BIND;
1996 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1997 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1998 }
paul718e3742002-12-13 20:15:29 +00001999 else
2000 BGP_EVENT_ADD (peer, BGP_Stop);
2001
2002 return 0;
2003}
2004
2005int
2006peer_group_unbind (struct bgp *bgp, struct peer *peer,
2007 struct peer_group *group, afi_t afi, safi_t safi)
2008{
2009 if (! peer->af_group[afi][safi])
2010 return 0;
2011
2012 if (group != peer->group)
2013 return BGP_ERR_PEER_GROUP_MISMATCH;
2014
2015 peer->af_group[afi][safi] = 0;
2016 peer->afc[afi][safi] = 0;
2017 peer_af_flag_reset (peer, afi, safi);
2018
paulfee0f4c2004-09-13 05:12:46 +00002019 if (peer->rib[afi][safi])
2020 peer->rib[afi][safi] = NULL;
2021
paul718e3742002-12-13 20:15:29 +00002022 if (! peer_group_active (peer))
2023 {
Paul Jakmaca058a32006-09-14 02:58:49 +00002024 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00002025 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00002026 listnode_delete (group->peer, peer);
2027 peer->group = NULL;
2028 if (group->conf->as)
2029 {
2030 peer_delete (peer);
2031 return 0;
2032 }
2033 peer_global_config_reset (peer);
2034 }
2035
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002036 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002037 {
2038 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
2039 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2040 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2041 }
paul718e3742002-12-13 20:15:29 +00002042 else
2043 BGP_EVENT_ADD (peer, BGP_Stop);
2044
2045 return 0;
2046}
David Lamparter6b0655a2014-06-04 06:53:35 +02002047
Vipin Kumardd49eb12014-09-30 14:36:38 -07002048
2049static int
2050bgp_startup_timer_expire (struct thread *thread)
2051{
2052 struct bgp *bgp;
2053
2054 bgp = THREAD_ARG (thread);
2055 bgp->t_startup = NULL;
2056
2057 return 0;
2058}
2059
paul718e3742002-12-13 20:15:29 +00002060/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00002061static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002062bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002063{
2064 struct bgp *bgp;
2065 afi_t afi;
2066 safi_t safi;
2067
paul200df112005-06-01 11:17:05 +00002068 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
2069 return NULL;
2070
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002071 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00002072 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00002073 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00002074
2075 bgp->peer = list_new ();
2076 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
2077
2078 bgp->group = list_new ();
2079 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
2080
paulfee0f4c2004-09-13 05:12:46 +00002081 bgp->rsclient = list_new ();
2082 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
2083
paul718e3742002-12-13 20:15:29 +00002084 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2085 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2086 {
Paul Jakma64e580a2006-02-21 01:09:01 +00002087 bgp->route[afi][safi] = bgp_table_init (afi, safi);
2088 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
2089 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07002090 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
2091 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00002092 }
2093
2094 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
2095 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
2096 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00002097 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
2098 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07002099 bgp_flag_set (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES);
paul718e3742002-12-13 20:15:29 +00002100
2101 bgp->as = *as;
2102
2103 if (name)
2104 bgp->name = strdup (name);
2105
Donald Sharp774914f2015-10-14 08:50:39 -04002106 THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire,
Vipin Kumardd49eb12014-09-30 14:36:38 -07002107 bgp, bgp->restart_time);
2108
paul718e3742002-12-13 20:15:29 +00002109 return bgp;
2110}
2111
2112/* Return first entry of BGP. */
2113struct bgp *
paul94f2b392005-06-28 12:44:16 +00002114bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00002115{
Lou Berger056f3762013-04-10 12:30:04 -07002116 if (bm && bm->bgp && bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00002117 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00002118 return NULL;
2119}
2120
2121/* Lookup BGP entry. */
2122struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002123bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00002124{
2125 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002126 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002127
paul1eb8ef22005-04-07 07:30:20 +00002128 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002129 if (bgp->as == as
2130 && ((bgp->name == NULL && name == NULL)
2131 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
2132 return bgp;
2133 return NULL;
2134}
2135
2136/* Lookup BGP structure by view name. */
2137struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002138bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002139{
2140 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002141 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002142
paul1eb8ef22005-04-07 07:30:20 +00002143 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002144 if ((bgp->name == NULL && name == NULL)
2145 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2146 return bgp;
2147 return NULL;
2148}
2149
2150/* Called from VTY commands. */
2151int
paulfd79ac92004-10-13 05:06:08 +00002152bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002153{
2154 struct bgp *bgp;
2155
2156 /* Multiple instance check. */
2157 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2158 {
2159 if (name)
2160 bgp = bgp_lookup_by_name (name);
2161 else
2162 bgp = bgp_get_default ();
2163
2164 /* Already exists. */
2165 if (bgp)
2166 {
2167 if (bgp->as != *as)
2168 {
2169 *as = bgp->as;
2170 return BGP_ERR_INSTANCE_MISMATCH;
2171 }
2172 *bgp_val = bgp;
2173 return 0;
2174 }
2175 }
2176 else
2177 {
2178 /* BGP instance name can not be specified for single instance. */
2179 if (name)
2180 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2181
2182 /* Get default BGP structure if exists. */
2183 bgp = bgp_get_default ();
2184
2185 if (bgp)
2186 {
2187 if (bgp->as != *as)
2188 {
2189 *as = bgp->as;
2190 return BGP_ERR_AS_MISMATCH;
2191 }
2192 *bgp_val = bgp;
2193 return 0;
2194 }
2195 }
2196
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002197 bgp = bgp_create (as, name);
2198 bgp_router_id_set(bgp, &router_id_zebra);
2199 *bgp_val = bgp;
2200
Paul Jakmaad12dde2012-06-13 22:50:07 +01002201 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002202 if (list_isempty(bm->bgp)
2203 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002204 {
2205 if (bgp_socket (bm->port, bm->address) < 0)
2206 return BGP_ERR_INVALID_VALUE;
2207 }
2208
paul718e3742002-12-13 20:15:29 +00002209 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002210
2211 return 0;
2212}
2213
2214/* Delete BGP instance. */
2215int
2216bgp_delete (struct bgp *bgp)
2217{
2218 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002219 struct peer_group *group;
Denil Vira57cd5e72015-08-10 12:46:14 -07002220 struct listnode *node, *pnode;
2221 struct listnode *next, *pnext;
paul718e3742002-12-13 20:15:29 +00002222 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002223 int i;
2224
Lou Berger82dd7072016-01-12 13:41:57 -05002225 SET_FLAG(bgp->flags, BGP_FLAG_DELETING);
2226
David Lampartercffe7802014-12-07 03:27:13 +01002227 THREAD_OFF (bgp->t_startup);
2228
Daniel Walton9e518dd2015-05-19 17:47:26 -07002229 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2230 {
2231 if (peer->status == Established ||
2232 peer->status == OpenSent ||
2233 peer->status == OpenConfirm)
2234 {
2235 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2236 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
2237 }
2238 }
2239
paul718e3742002-12-13 20:15:29 +00002240 /* Delete static route. */
2241 bgp_static_delete (bgp);
2242
2243 /* Unset redistribution. */
2244 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2245 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2246 if (i != ZEBRA_ROUTE_BGP)
2247 bgp_redistribute_unset (bgp, afi, i);
2248
paul1eb8ef22005-04-07 07:30:20 +00002249 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002250 {
2251 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2252 {
2253 /* Send notify to remote peer. */
2254 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2255 }
2256
2257 peer_delete (peer);
2258 }
paul718e3742002-12-13 20:15:29 +00002259
Chris Caputo228da422009-07-18 05:44:03 +00002260 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002261 {
Denil Vira57cd5e72015-08-10 12:46:14 -07002262 for (ALL_LIST_ELEMENTS (group->peer, pnode, pnext, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002263 {
2264 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2265 {
2266 /* Send notify to remote peer. */
2267 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2268 }
2269 }
2270 peer_group_delete (group);
2271 }
Chris Caputo228da422009-07-18 05:44:03 +00002272
2273 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002274
2275 if (bgp->peer_self) {
2276 peer_delete(bgp->peer_self);
2277 bgp->peer_self = NULL;
2278 }
Lou Berger82dd7072016-01-12 13:41:57 -05002279
2280 /*
2281 * Free pending deleted routes. Unfortunately, it also has to process
2282 * all the pending activity for other instances of struct bgp.
2283 *
2284 * This call was added to achieve clean memory allocation at exit,
2285 * for the sake of valgrind.
2286 */
2287 bgp_process_queues_drain_immediate();
2288
Paul Jakmafd35b942009-07-16 19:27:32 +01002289 /* Remove visibility via the master list - there may however still be
2290 * routes to be processed still referencing the struct bgp.
2291 */
2292 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002293 if (list_isempty(bm->bgp))
2294 bgp_close ();
2295
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002296 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002297
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002298 return 0;
2299}
2300
2301static void bgp_free (struct bgp *);
2302
2303void
2304bgp_lock (struct bgp *bgp)
2305{
2306 ++bgp->lock;
2307}
2308
2309void
2310bgp_unlock(struct bgp *bgp)
2311{
Chris Caputo228da422009-07-18 05:44:03 +00002312 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002313 if (--bgp->lock == 0)
2314 bgp_free (bgp);
2315}
2316
2317static void
2318bgp_free (struct bgp *bgp)
2319{
2320 afi_t afi;
2321 safi_t safi;
2322
2323 list_delete (bgp->group);
2324 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002325 list_delete (bgp->rsclient);
2326
paul718e3742002-12-13 20:15:29 +00002327 if (bgp->name)
2328 free (bgp->name);
2329
2330 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2331 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2332 {
2333 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002334 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002335 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002336 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002337 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002338 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002339 }
2340 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002341}
David Lamparter6b0655a2014-06-04 06:53:35 +02002342
paul718e3742002-12-13 20:15:29 +00002343struct peer *
2344peer_lookup (struct bgp *bgp, union sockunion *su)
2345{
2346 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002347 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002348
Steve Hillfc4dc592009-07-28 17:54:35 +01002349 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002350 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002351 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2352 if (sockunion_same (&peer->su, su)
2353 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2354 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002355 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002356 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002357 {
2358 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002359
Paul Jakma2158ad22009-07-28 18:10:55 +01002360 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2361 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2362 if (sockunion_same (&peer->su, su)
2363 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2364 return peer;
paul718e3742002-12-13 20:15:29 +00002365 }
2366 return NULL;
2367}
2368
2369struct peer *
2370peer_lookup_with_open (union sockunion *su, as_t remote_as,
2371 struct in_addr *remote_id, int *as)
2372{
2373 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002374 struct listnode *node;
2375 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002376 struct bgp *bgp;
2377
Steve Hillfc4dc592009-07-28 17:54:35 +01002378 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002379 return NULL;
2380
Paul Jakma9d878772009-08-05 16:25:16 +01002381 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002382 {
Paul Jakma9d878772009-08-05 16:25:16 +01002383 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2384 {
2385 if (sockunion_same (&peer->su, su)
2386 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2387 {
2388 if (peer->as == remote_as
2389 && peer->remote_id.s_addr == remote_id->s_addr)
2390 return peer;
2391 if (peer->as == remote_as)
2392 *as = 1;
2393 }
2394 }
2395
2396 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2397 {
2398 if (sockunion_same (&peer->su, su)
2399 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2400 {
2401 if (peer->as == remote_as
2402 && peer->remote_id.s_addr == 0)
2403 return peer;
2404 if (peer->as == remote_as)
2405 *as = 1;
2406 }
2407 }
paul718e3742002-12-13 20:15:29 +00002408 }
2409 return NULL;
2410}
David Lamparter6b0655a2014-06-04 06:53:35 +02002411
paul718e3742002-12-13 20:15:29 +00002412/* If peer is configured at least one address family return 1. */
2413int
2414peer_active (struct peer *peer)
2415{
2416 if (peer->afc[AFI_IP][SAFI_UNICAST]
2417 || peer->afc[AFI_IP][SAFI_MULTICAST]
2418 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05002419 || peer->afc[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00002420 || peer->afc[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05002421 || peer->afc[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05002422 || peer->afc[AFI_IP6][SAFI_MPLS_VPN]
2423 || peer->afc[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00002424 return 1;
2425 return 0;
2426}
2427
2428/* If peer is negotiated at least one address family return 1. */
2429int
2430peer_active_nego (struct peer *peer)
2431{
2432 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2433 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2434 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05002435 || peer->afc_nego[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00002436 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05002437 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05002438 || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
2439 || peer->afc_nego[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00002440 return 1;
2441 return 0;
2442}
David Lamparter6b0655a2014-06-04 06:53:35 +02002443
paul718e3742002-12-13 20:15:29 +00002444/* peer_flag_change_type. */
2445enum peer_change_type
2446{
2447 peer_change_none,
2448 peer_change_reset,
2449 peer_change_reset_in,
2450 peer_change_reset_out,
2451};
2452
paul94f2b392005-06-28 12:44:16 +00002453static void
paul718e3742002-12-13 20:15:29 +00002454peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2455 enum peer_change_type type)
2456{
2457 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2458 return;
2459
Stephen Hemmingerd9d4ae52010-01-13 00:32:39 +00002460 if (peer->status != Established)
2461 return;
2462
paul718e3742002-12-13 20:15:29 +00002463 if (type == peer_change_reset)
2464 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2465 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2466 else if (type == peer_change_reset_in)
2467 {
2468 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2469 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2470 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2471 else
2472 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2473 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2474 }
2475 else if (type == peer_change_reset_out)
2476 bgp_announce_route (peer, afi, safi);
2477}
2478
2479struct peer_flag_action
2480{
2481 /* Peer's flag. */
2482 u_int32_t flag;
2483
2484 /* This flag can be set for peer-group member. */
2485 u_char not_for_member;
2486
2487 /* Action when the flag is changed. */
2488 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002489
2490 /* Peer down cause */
2491 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002492};
2493
Stephen Hemminger03621952009-07-21 16:27:20 -07002494static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002495 {
2496 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2497 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2498 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2499 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2500 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002501 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002502 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002503 { 0, 0, 0 }
2504 };
2505
Stephen Hemminger03621952009-07-21 16:27:20 -07002506static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002507 {
2508 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2509 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2510 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2511 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2512 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2513 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2514 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2515 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2516 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2517 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2518 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2519 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2520 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002521 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
Timo Teräs9e7a53c2014-04-24 10:22:37 +03002522 { PEER_FLAG_NEXTHOP_SELF_ALL, 1, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002523 { 0, 0, 0 }
2524 };
2525
2526/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002527static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002528peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002529 struct peer_flag_action *action, u_int32_t flag)
2530{
2531 int i;
2532 int found = 0;
2533 int reset_in = 0;
2534 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002535 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002536
2537 /* Check peer's frag action. */
2538 for (i = 0; i < size; i++)
2539 {
2540 match = &action_list[i];
2541
2542 if (match->flag == 0)
2543 break;
2544
2545 if (match->flag & flag)
2546 {
2547 found = 1;
2548
2549 if (match->type == peer_change_reset_in)
2550 reset_in = 1;
2551 if (match->type == peer_change_reset_out)
2552 reset_out = 1;
2553 if (match->type == peer_change_reset)
2554 {
2555 reset_in = 1;
2556 reset_out = 1;
2557 }
2558 if (match->not_for_member)
2559 action->not_for_member = 1;
2560 }
2561 }
2562
2563 /* Set peer clear type. */
2564 if (reset_in && reset_out)
2565 action->type = peer_change_reset;
2566 else if (reset_in)
2567 action->type = peer_change_reset_in;
2568 else if (reset_out)
2569 action->type = peer_change_reset_out;
2570 else
2571 action->type = peer_change_none;
2572
2573 return found;
2574}
2575
paul94f2b392005-06-28 12:44:16 +00002576static void
paul718e3742002-12-13 20:15:29 +00002577peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2578{
2579 if (flag == PEER_FLAG_SHUTDOWN)
2580 {
2581 if (CHECK_FLAG (peer->flags, flag))
2582 {
hasso93406d82005-02-02 14:40:33 +00002583 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2584 peer_nsf_stop (peer);
2585
hasso0a486e52005-02-01 20:57:17 +00002586 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2587 if (peer->t_pmax_restart)
2588 {
2589 BGP_TIMER_OFF (peer->t_pmax_restart);
2590 if (BGP_DEBUG (events, EVENTS))
2591 zlog_debug ("%s Maximum-prefix restart timer canceled",
2592 peer->host);
2593 }
2594
hasso93406d82005-02-02 14:40:33 +00002595 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2596 peer_nsf_stop (peer);
2597
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002598 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002599 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2600 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2601 else
2602 BGP_EVENT_ADD (peer, BGP_Stop);
2603 }
2604 else
2605 {
2606 peer->v_start = BGP_INIT_START_TIMER;
2607 BGP_EVENT_ADD (peer, BGP_Stop);
2608 }
2609 }
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002610 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002611 {
hassoc9502432005-02-01 22:01:48 +00002612 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2613 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2614 else if (flag == PEER_FLAG_PASSIVE)
2615 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002616 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002617 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002618
hassoc9502432005-02-01 22:01:48 +00002619 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2620 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002621 }
2622 else
2623 BGP_EVENT_ADD (peer, BGP_Stop);
2624}
2625
2626/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002627static int
paul718e3742002-12-13 20:15:29 +00002628peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2629{
2630 int found;
2631 int size;
2632 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002633 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002634 struct peer_flag_action action;
2635
2636 memset (&action, 0, sizeof (struct peer_flag_action));
2637 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2638
2639 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2640
2641 /* No flag action is found. */
2642 if (! found)
2643 return BGP_ERR_INVALID_FLAG;
2644
2645 /* Not for peer-group member. */
2646 if (action.not_for_member && peer_group_active (peer))
2647 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2648
2649 /* When unset the peer-group member's flag we have to check
2650 peer-group configuration. */
2651 if (! set && peer_group_active (peer))
2652 if (CHECK_FLAG (peer->group->conf->flags, flag))
2653 {
2654 if (flag == PEER_FLAG_SHUTDOWN)
2655 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2656 else
2657 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2658 }
2659
2660 /* Flag conflict check. */
2661 if (set
2662 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2663 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2664 return BGP_ERR_PEER_FLAG_CONFLICT;
2665
2666 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2667 {
2668 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2669 return 0;
2670 if (! set && ! CHECK_FLAG (peer->flags, flag))
2671 return 0;
2672 }
2673
2674 if (set)
2675 SET_FLAG (peer->flags, flag);
2676 else
2677 UNSET_FLAG (peer->flags, flag);
2678
2679 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2680 {
2681 if (action.type == peer_change_reset)
2682 peer_flag_modify_action (peer, flag);
2683
2684 return 0;
2685 }
2686
2687 /* peer-group member updates. */
2688 group = peer->group;
2689
paul1eb8ef22005-04-07 07:30:20 +00002690 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002691 {
2692 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2693 continue;
2694
2695 if (! set && ! CHECK_FLAG (peer->flags, flag))
2696 continue;
2697
2698 if (set)
2699 SET_FLAG (peer->flags, flag);
2700 else
2701 UNSET_FLAG (peer->flags, flag);
2702
2703 if (action.type == peer_change_reset)
2704 peer_flag_modify_action (peer, flag);
2705 }
2706 return 0;
2707}
2708
2709int
2710peer_flag_set (struct peer *peer, u_int32_t flag)
2711{
2712 return peer_flag_modify (peer, flag, 1);
2713}
2714
2715int
2716peer_flag_unset (struct peer *peer, u_int32_t flag)
2717{
2718 return peer_flag_modify (peer, flag, 0);
2719}
2720
paul94f2b392005-06-28 12:44:16 +00002721static int
paul718e3742002-12-13 20:15:29 +00002722peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2723{
2724 if (peer->af_group[afi][safi])
2725 return 1;
2726 return 0;
2727}
2728
paul94f2b392005-06-28 12:44:16 +00002729static int
paul718e3742002-12-13 20:15:29 +00002730peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2731 int set)
2732{
2733 int found;
2734 int size;
paul1eb8ef22005-04-07 07:30:20 +00002735 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002736 struct peer_group *group;
2737 struct peer_flag_action action;
2738
2739 memset (&action, 0, sizeof (struct peer_flag_action));
2740 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2741
2742 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2743
2744 /* No flag action is found. */
2745 if (! found)
2746 return BGP_ERR_INVALID_FLAG;
2747
2748 /* Adress family must be activated. */
2749 if (! peer->afc[afi][safi])
2750 return BGP_ERR_PEER_INACTIVE;
2751
2752 /* Not for peer-group member. */
2753 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2754 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2755
2756 /* Spcecial check for reflector client. */
2757 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2758 && peer_sort (peer) != BGP_PEER_IBGP)
2759 return BGP_ERR_NOT_INTERNAL_PEER;
2760
2761 /* Spcecial check for remove-private-AS. */
2762 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2763 && peer_sort (peer) == BGP_PEER_IBGP)
2764 return BGP_ERR_REMOVE_PRIVATE_AS;
2765
2766 /* When unset the peer-group member's flag we have to check
2767 peer-group configuration. */
2768 if (! set && peer->af_group[afi][safi])
2769 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2770 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2771
2772 /* When current flag configuration is same as requested one. */
2773 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2774 {
2775 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2776 return 0;
2777 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2778 return 0;
2779 }
2780
2781 if (set)
2782 SET_FLAG (peer->af_flags[afi][safi], flag);
2783 else
2784 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2785
2786 /* Execute action when peer is established. */
2787 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2788 && peer->status == Established)
2789 {
2790 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2791 bgp_clear_adj_in (peer, afi, safi);
2792 else
hassoe0701b72004-05-20 09:19:34 +00002793 {
2794 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2795 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2796 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2797 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2798 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2799 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2800 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2801 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2802
2803 peer_change_action (peer, afi, safi, action.type);
2804 }
2805
paul718e3742002-12-13 20:15:29 +00002806 }
2807
2808 /* Peer group member updates. */
2809 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2810 {
2811 group = peer->group;
2812
paul1eb8ef22005-04-07 07:30:20 +00002813 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002814 {
2815 if (! peer->af_group[afi][safi])
2816 continue;
2817
2818 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2819 continue;
2820
2821 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2822 continue;
2823
2824 if (set)
2825 SET_FLAG (peer->af_flags[afi][safi], flag);
2826 else
2827 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2828
2829 if (peer->status == Established)
2830 {
2831 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2832 bgp_clear_adj_in (peer, afi, safi);
2833 else
hassoe0701b72004-05-20 09:19:34 +00002834 {
2835 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2836 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2837 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2838 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2839 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2840 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2841 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2842 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2843
2844 peer_change_action (peer, afi, safi, action.type);
2845 }
paul718e3742002-12-13 20:15:29 +00002846 }
2847 }
2848 }
2849 return 0;
2850}
2851
2852int
2853peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2854{
2855 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2856}
2857
2858int
2859peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2860{
2861 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2862}
David Lamparter6b0655a2014-06-04 06:53:35 +02002863
paul718e3742002-12-13 20:15:29 +00002864/* EBGP multihop configuration. */
2865int
2866peer_ebgp_multihop_set (struct peer *peer, int ttl)
2867{
2868 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002869 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002870 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002871
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002872 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002873 return 0;
2874
Nick Hilliardfa411a22011-03-23 15:33:17 +00002875 /* see comment in peer_ttl_security_hops_set() */
2876 if (ttl != MAXTTL)
2877 {
2878 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2879 {
2880 group = peer->group;
2881 if (group->conf->gtsm_hops != 0)
2882 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2883
2884 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2885 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002886 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002887 continue;
2888
2889 if (peer1->gtsm_hops != 0)
2890 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2891 }
2892 }
2893 else
2894 {
2895 if (peer->gtsm_hops != 0)
2896 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2897 }
2898 }
2899
paul718e3742002-12-13 20:15:29 +00002900 peer->ttl = ttl;
2901
2902 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2903 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002904 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002905 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002906 }
2907 else
2908 {
2909 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002910 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002911 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002912 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002913 continue;
paul718e3742002-12-13 20:15:29 +00002914
pauleb821182004-05-01 08:44:08 +00002915 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002916
pauleb821182004-05-01 08:44:08 +00002917 if (peer->fd >= 0)
2918 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2919 }
paul718e3742002-12-13 20:15:29 +00002920 }
2921 return 0;
2922}
2923
2924int
2925peer_ebgp_multihop_unset (struct peer *peer)
2926{
2927 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002928 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002929
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002930 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002931 return 0;
2932
Nick Hilliardfa411a22011-03-23 15:33:17 +00002933 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2934 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2935
paul718e3742002-12-13 20:15:29 +00002936 if (peer_group_active (peer))
2937 peer->ttl = peer->group->conf->ttl;
2938 else
2939 peer->ttl = 1;
2940
2941 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2942 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002943 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002944 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002945 }
2946 else
2947 {
2948 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002949 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002950 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002951 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002952 continue;
paul718e3742002-12-13 20:15:29 +00002953
pauleb821182004-05-01 08:44:08 +00002954 peer->ttl = 1;
2955
2956 if (peer->fd >= 0)
2957 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2958 }
paul718e3742002-12-13 20:15:29 +00002959 }
2960 return 0;
2961}
David Lamparter6b0655a2014-06-04 06:53:35 +02002962
paul718e3742002-12-13 20:15:29 +00002963/* Neighbor description. */
2964int
David Lamparterdfb9bd72016-05-24 18:58:07 +02002965peer_description_set (struct peer *peer, const char *desc)
paul718e3742002-12-13 20:15:29 +00002966{
2967 if (peer->desc)
2968 XFREE (MTYPE_PEER_DESC, peer->desc);
2969
2970 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2971
2972 return 0;
2973}
2974
2975int
2976peer_description_unset (struct peer *peer)
2977{
2978 if (peer->desc)
2979 XFREE (MTYPE_PEER_DESC, peer->desc);
2980
2981 peer->desc = NULL;
2982
2983 return 0;
2984}
David Lamparter6b0655a2014-06-04 06:53:35 +02002985
paul718e3742002-12-13 20:15:29 +00002986/* Neighbor update-source. */
2987int
paulfd79ac92004-10-13 05:06:08 +00002988peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002989{
2990 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002991 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002992
2993 if (peer->update_if)
2994 {
2995 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2996 && strcmp (peer->update_if, ifname) == 0)
2997 return 0;
2998
2999 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3000 peer->update_if = NULL;
3001 }
3002
3003 if (peer->update_source)
3004 {
3005 sockunion_free (peer->update_source);
3006 peer->update_source = NULL;
3007 }
3008
3009 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
3010
3011 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3012 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003013 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003014 {
3015 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3016 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3017 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3018 }
paul718e3742002-12-13 20:15:29 +00003019 else
3020 BGP_EVENT_ADD (peer, BGP_Stop);
3021 return 0;
3022 }
3023
3024 /* peer-group member updates. */
3025 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003026 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003027 {
3028 if (peer->update_if)
3029 {
3030 if (strcmp (peer->update_if, ifname) == 0)
3031 continue;
3032
3033 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3034 peer->update_if = NULL;
3035 }
3036
3037 if (peer->update_source)
3038 {
3039 sockunion_free (peer->update_source);
3040 peer->update_source = NULL;
3041 }
3042
3043 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
3044
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003045 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003046 {
3047 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3048 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3049 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3050 }
paul718e3742002-12-13 20:15:29 +00003051 else
3052 BGP_EVENT_ADD (peer, BGP_Stop);
3053 }
3054 return 0;
3055}
3056
3057int
David Lamparterdfb9bd72016-05-24 18:58:07 +02003058peer_update_source_addr_set (struct peer *peer, const union sockunion *su)
paul718e3742002-12-13 20:15:29 +00003059{
3060 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003061 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003062
3063 if (peer->update_source)
3064 {
3065 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3066 && sockunion_cmp (peer->update_source, su) == 0)
3067 return 0;
3068 sockunion_free (peer->update_source);
3069 peer->update_source = NULL;
3070 }
3071
3072 if (peer->update_if)
3073 {
3074 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3075 peer->update_if = NULL;
3076 }
3077
3078 peer->update_source = sockunion_dup (su);
3079
3080 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3081 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003082 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003083 {
3084 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3085 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3086 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3087 }
paul718e3742002-12-13 20:15:29 +00003088 else
3089 BGP_EVENT_ADD (peer, BGP_Stop);
3090 return 0;
3091 }
3092
3093 /* peer-group member updates. */
3094 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003095 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003096 {
3097 if (peer->update_source)
3098 {
3099 if (sockunion_cmp (peer->update_source, su) == 0)
3100 continue;
3101 sockunion_free (peer->update_source);
3102 peer->update_source = NULL;
3103 }
3104
3105 if (peer->update_if)
3106 {
3107 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3108 peer->update_if = NULL;
3109 }
3110
3111 peer->update_source = sockunion_dup (su);
3112
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003113 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003114 {
3115 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3116 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3117 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3118 }
paul718e3742002-12-13 20:15:29 +00003119 else
3120 BGP_EVENT_ADD (peer, BGP_Stop);
3121 }
3122 return 0;
3123}
3124
3125int
3126peer_update_source_unset (struct peer *peer)
3127{
3128 union sockunion *su;
3129 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003130 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003131
3132 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3133 && ! peer->update_source
3134 && ! peer->update_if)
3135 return 0;
3136
3137 if (peer->update_source)
3138 {
3139 sockunion_free (peer->update_source);
3140 peer->update_source = NULL;
3141 }
3142 if (peer->update_if)
3143 {
3144 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3145 peer->update_if = NULL;
3146 }
3147
3148 if (peer_group_active (peer))
3149 {
3150 group = peer->group;
3151
3152 if (group->conf->update_source)
3153 {
3154 su = sockunion_dup (group->conf->update_source);
3155 peer->update_source = su;
3156 }
3157 else if (group->conf->update_if)
3158 peer->update_if =
3159 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
3160 }
3161
3162 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3163 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003164 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003165 {
3166 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3167 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3168 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3169 }
paul718e3742002-12-13 20:15:29 +00003170 else
3171 BGP_EVENT_ADD (peer, BGP_Stop);
3172 return 0;
3173 }
3174
3175 /* peer-group member updates. */
3176 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003177 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003178 {
3179 if (! peer->update_source && ! peer->update_if)
3180 continue;
3181
3182 if (peer->update_source)
3183 {
3184 sockunion_free (peer->update_source);
3185 peer->update_source = NULL;
3186 }
3187
3188 if (peer->update_if)
3189 {
3190 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3191 peer->update_if = NULL;
3192 }
3193
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003194 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003195 {
3196 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3197 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3198 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3199 }
paul718e3742002-12-13 20:15:29 +00003200 else
3201 BGP_EVENT_ADD (peer, BGP_Stop);
3202 }
3203 return 0;
3204}
David Lamparter6b0655a2014-06-04 06:53:35 +02003205
paul718e3742002-12-13 20:15:29 +00003206int
3207peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003208 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003209{
3210 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003211 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003212
3213 /* Adress family must be activated. */
3214 if (! peer->afc[afi][safi])
3215 return BGP_ERR_PEER_INACTIVE;
3216
3217 /* Default originate can't be used for peer group memeber. */
3218 if (peer_is_group_member (peer, afi, safi))
3219 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3220
3221 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3222 || (rmap && ! peer->default_rmap[afi][safi].name)
3223 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3224 {
3225 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3226
3227 if (rmap)
3228 {
3229 if (peer->default_rmap[afi][safi].name)
3230 free (peer->default_rmap[afi][safi].name);
3231 peer->default_rmap[afi][safi].name = strdup (rmap);
3232 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3233 }
3234 }
3235
3236 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3237 {
3238 if (peer->status == Established && peer->afc_nego[afi][safi])
3239 bgp_default_originate (peer, afi, safi, 0);
3240 return 0;
3241 }
3242
3243 /* peer-group member updates. */
3244 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003245 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003246 {
3247 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3248
3249 if (rmap)
3250 {
3251 if (peer->default_rmap[afi][safi].name)
3252 free (peer->default_rmap[afi][safi].name);
3253 peer->default_rmap[afi][safi].name = strdup (rmap);
3254 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3255 }
3256
3257 if (peer->status == Established && peer->afc_nego[afi][safi])
3258 bgp_default_originate (peer, afi, safi, 0);
3259 }
3260 return 0;
3261}
3262
3263int
3264peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3265{
3266 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003267 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003268
3269 /* Adress family must be activated. */
3270 if (! peer->afc[afi][safi])
3271 return BGP_ERR_PEER_INACTIVE;
3272
3273 /* Default originate can't be used for peer group memeber. */
3274 if (peer_is_group_member (peer, afi, safi))
3275 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3276
3277 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3278 {
3279 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3280
3281 if (peer->default_rmap[afi][safi].name)
3282 free (peer->default_rmap[afi][safi].name);
3283 peer->default_rmap[afi][safi].name = NULL;
3284 peer->default_rmap[afi][safi].map = NULL;
3285 }
3286
3287 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3288 {
3289 if (peer->status == Established && peer->afc_nego[afi][safi])
3290 bgp_default_originate (peer, afi, safi, 1);
3291 return 0;
3292 }
3293
3294 /* peer-group member updates. */
3295 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003296 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003297 {
3298 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3299
3300 if (peer->default_rmap[afi][safi].name)
3301 free (peer->default_rmap[afi][safi].name);
3302 peer->default_rmap[afi][safi].name = NULL;
3303 peer->default_rmap[afi][safi].map = NULL;
3304
3305 if (peer->status == Established && peer->afc_nego[afi][safi])
3306 bgp_default_originate (peer, afi, safi, 1);
3307 }
3308 return 0;
3309}
David Lamparter6b0655a2014-06-04 06:53:35 +02003310
paul718e3742002-12-13 20:15:29 +00003311int
3312peer_port_set (struct peer *peer, u_int16_t port)
3313{
3314 peer->port = port;
3315 return 0;
3316}
3317
3318int
3319peer_port_unset (struct peer *peer)
3320{
3321 peer->port = BGP_PORT_DEFAULT;
3322 return 0;
3323}
David Lamparter6b0655a2014-06-04 06:53:35 +02003324
paul718e3742002-12-13 20:15:29 +00003325/* neighbor weight. */
3326int
3327peer_weight_set (struct peer *peer, u_int16_t weight)
3328{
3329 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003330 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003331
3332 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3333 peer->weight = weight;
3334
3335 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3336 return 0;
3337
3338 /* peer-group member updates. */
3339 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003340 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003341 {
3342 peer->weight = group->conf->weight;
3343 }
3344 return 0;
3345}
3346
3347int
3348peer_weight_unset (struct peer *peer)
3349{
3350 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003351 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003352
3353 /* Set default weight. */
3354 if (peer_group_active (peer))
3355 peer->weight = peer->group->conf->weight;
3356 else
3357 peer->weight = 0;
3358
3359 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3360
3361 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3362 return 0;
3363
3364 /* peer-group member updates. */
3365 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003366 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003367 {
3368 peer->weight = 0;
3369 }
3370 return 0;
3371}
David Lamparter6b0655a2014-06-04 06:53:35 +02003372
paul718e3742002-12-13 20:15:29 +00003373int
3374peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3375{
3376 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003377 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003378
3379 /* Not for peer group memeber. */
3380 if (peer_group_active (peer))
3381 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3382
3383 /* keepalive value check. */
3384 if (keepalive > 65535)
3385 return BGP_ERR_INVALID_VALUE;
3386
3387 /* Holdtime value check. */
3388 if (holdtime > 65535)
3389 return BGP_ERR_INVALID_VALUE;
3390
3391 /* Holdtime value must be either 0 or greater than 3. */
3392 if (holdtime < 3 && holdtime != 0)
3393 return BGP_ERR_INVALID_VALUE;
3394
3395 /* Set value to the configuration. */
3396 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3397 peer->holdtime = holdtime;
3398 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3399
3400 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3401 return 0;
3402
3403 /* peer-group member updates. */
3404 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003405 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003406 {
3407 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3408 peer->holdtime = group->conf->holdtime;
3409 peer->keepalive = group->conf->keepalive;
3410 }
3411 return 0;
3412}
3413
3414int
3415peer_timers_unset (struct peer *peer)
3416{
3417 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003418 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003419
3420 if (peer_group_active (peer))
3421 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3422
3423 /* Clear configuration. */
3424 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3425 peer->keepalive = 0;
3426 peer->holdtime = 0;
3427
3428 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3429 return 0;
3430
3431 /* peer-group member updates. */
3432 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003433 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003434 {
3435 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3436 peer->holdtime = 0;
3437 peer->keepalive = 0;
3438 }
3439
3440 return 0;
3441}
David Lamparter6b0655a2014-06-04 06:53:35 +02003442
paul718e3742002-12-13 20:15:29 +00003443int
3444peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3445{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003446 struct peer_group *group;
3447 struct listnode *node, *nnode;
3448
paul718e3742002-12-13 20:15:29 +00003449 if (peer_group_active (peer))
3450 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3451
3452 if (connect > 65535)
3453 return BGP_ERR_INVALID_VALUE;
3454
3455 /* Set value to the configuration. */
3456 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3457 peer->connect = connect;
3458
3459 /* Set value to timer setting. */
3460 peer->v_connect = connect;
3461
Daniel Walton0d7435f2015-10-22 11:35:20 +03003462 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3463 return 0;
3464
3465 /* peer-group member updates. */
3466 group = peer->group;
3467 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3468 {
3469 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3470 peer->connect = connect;
3471 peer->v_connect = connect;
3472 }
paul718e3742002-12-13 20:15:29 +00003473 return 0;
3474}
3475
3476int
3477peer_timers_connect_unset (struct peer *peer)
3478{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003479 struct peer_group *group;
3480 struct listnode *node, *nnode;
3481
paul718e3742002-12-13 20:15:29 +00003482 if (peer_group_active (peer))
3483 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3484
3485 /* Clear configuration. */
3486 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3487 peer->connect = 0;
3488
3489 /* Set timer setting to default value. */
3490 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3491
Daniel Walton0d7435f2015-10-22 11:35:20 +03003492 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3493 return 0;
3494
3495 /* peer-group member updates. */
3496 group = peer->group;
3497 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3498 {
3499 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3500 peer->connect = 0;
3501 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3502 }
3503 return 0;
paul718e3742002-12-13 20:15:29 +00003504}
David Lamparter6b0655a2014-06-04 06:53:35 +02003505
paul718e3742002-12-13 20:15:29 +00003506int
3507peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3508{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003509 struct peer_group *group;
3510 struct listnode *node, *nnode;
3511
paul718e3742002-12-13 20:15:29 +00003512 if (peer_group_active (peer))
3513 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3514
3515 if (routeadv > 600)
3516 return BGP_ERR_INVALID_VALUE;
3517
3518 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3519 peer->routeadv = routeadv;
3520 peer->v_routeadv = routeadv;
3521
Daniel Walton0d7435f2015-10-22 11:35:20 +03003522 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3523 return 0;
3524
3525 /* peer-group member updates. */
3526 group = peer->group;
3527 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3528 {
3529 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3530 peer->routeadv = routeadv;
3531 peer->v_routeadv = routeadv;
3532 }
3533
paul718e3742002-12-13 20:15:29 +00003534 return 0;
3535}
3536
3537int
3538peer_advertise_interval_unset (struct peer *peer)
3539{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003540 struct peer_group *group;
3541 struct listnode *node, *nnode;
3542
paul718e3742002-12-13 20:15:29 +00003543 if (peer_group_active (peer))
3544 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3545
3546 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3547 peer->routeadv = 0;
3548
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003549 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003550 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3551 else
3552 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
Daniel Walton0d7435f2015-10-22 11:35:20 +03003553
3554 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3555 return 0;
3556
3557 /* peer-group member updates. */
3558 group = peer->group;
3559 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3560 {
3561 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3562 peer->routeadv = 0;
3563
3564 if (peer->sort == BGP_PEER_IBGP)
3565 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3566 else
3567 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3568 }
paul718e3742002-12-13 20:15:29 +00003569
3570 return 0;
3571}
David Lamparter6b0655a2014-06-04 06:53:35 +02003572
paul718e3742002-12-13 20:15:29 +00003573/* neighbor interface */
3574int
paulfd79ac92004-10-13 05:06:08 +00003575peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003576{
3577 if (peer->ifname)
3578 free (peer->ifname);
3579 peer->ifname = strdup (str);
3580
3581 return 0;
3582}
3583
3584int
3585peer_interface_unset (struct peer *peer)
3586{
3587 if (peer->ifname)
3588 free (peer->ifname);
3589 peer->ifname = NULL;
3590
3591 return 0;
3592}
David Lamparter6b0655a2014-06-04 06:53:35 +02003593
paul718e3742002-12-13 20:15:29 +00003594/* Allow-as in. */
3595int
3596peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3597{
3598 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003599 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003600
3601 if (allow_num < 1 || allow_num > 10)
3602 return BGP_ERR_INVALID_VALUE;
3603
3604 if (peer->allowas_in[afi][safi] != allow_num)
3605 {
3606 peer->allowas_in[afi][safi] = allow_num;
3607 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3608 peer_change_action (peer, afi, safi, peer_change_reset_in);
3609 }
3610
3611 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3612 return 0;
3613
3614 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003615 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003616 {
3617 if (peer->allowas_in[afi][safi] != allow_num)
3618 {
3619 peer->allowas_in[afi][safi] = allow_num;
3620 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3621 peer_change_action (peer, afi, safi, peer_change_reset_in);
3622 }
3623
3624 }
3625 return 0;
3626}
3627
3628int
3629peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3630{
3631 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003632 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003633
3634 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3635 {
3636 peer->allowas_in[afi][safi] = 0;
3637 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3638 }
3639
3640 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3641 return 0;
3642
3643 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003644 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003645 {
3646 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3647 {
3648 peer->allowas_in[afi][safi] = 0;
3649 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3650 }
3651 }
3652 return 0;
3653}
David Lamparter6b0655a2014-06-04 06:53:35 +02003654
paul718e3742002-12-13 20:15:29 +00003655int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003656peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003657{
3658 struct bgp *bgp = peer->bgp;
3659 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003660 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003661
3662 if (peer_sort (peer) != BGP_PEER_EBGP
3663 && peer_sort (peer) != BGP_PEER_INTERNAL)
3664 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3665
3666 if (bgp->as == as)
3667 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3668
3669 if (peer_group_active (peer))
3670 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3671
Andrew Certain9d3f9702012-11-07 23:50:07 +00003672 if (peer->as == as)
3673 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3674
paul718e3742002-12-13 20:15:29 +00003675 if (peer->change_local_as == as &&
3676 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003677 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3678 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3679 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003680 return 0;
3681
3682 peer->change_local_as = as;
3683 if (no_prepend)
3684 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3685 else
3686 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3687
Andrew Certain9d3f9702012-11-07 23:50:07 +00003688 if (replace_as)
3689 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3690 else
3691 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3692
paul718e3742002-12-13 20:15:29 +00003693 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3694 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003695 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003696 {
3697 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3698 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3699 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3700 }
paul718e3742002-12-13 20:15:29 +00003701 else
3702 BGP_EVENT_ADD (peer, BGP_Stop);
3703
3704 return 0;
3705 }
3706
3707 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003708 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003709 {
3710 peer->change_local_as = as;
3711 if (no_prepend)
3712 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3713 else
3714 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3715
Andrew Certain9d3f9702012-11-07 23:50:07 +00003716 if (replace_as)
3717 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3718 else
3719 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3720
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003721 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003722 {
3723 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3724 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3725 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3726 }
paul718e3742002-12-13 20:15:29 +00003727 else
3728 BGP_EVENT_ADD (peer, BGP_Stop);
3729 }
3730
3731 return 0;
3732}
3733
3734int
3735peer_local_as_unset (struct peer *peer)
3736{
3737 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003738 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003739
3740 if (peer_group_active (peer))
3741 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3742
3743 if (! peer->change_local_as)
3744 return 0;
3745
3746 peer->change_local_as = 0;
3747 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003748 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003749
3750 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3751 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003752 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003753 {
3754 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3755 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3756 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3757 }
paul718e3742002-12-13 20:15:29 +00003758 else
3759 BGP_EVENT_ADD (peer, BGP_Stop);
3760
3761 return 0;
3762 }
3763
3764 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003765 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003766 {
3767 peer->change_local_as = 0;
3768 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003769 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003770
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003771 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003772 {
3773 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3774 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3775 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3776 }
paul718e3742002-12-13 20:15:29 +00003777 else
3778 BGP_EVENT_ADD (peer, BGP_Stop);
3779 }
3780 return 0;
3781}
David Lamparter6b0655a2014-06-04 06:53:35 +02003782
Paul Jakma0df7c912008-07-21 21:02:49 +00003783/* Set password for authenticating with the peer. */
3784int
3785peer_password_set (struct peer *peer, const char *password)
3786{
3787 struct listnode *nn, *nnode;
3788 int len = password ? strlen(password) : 0;
3789 int ret = BGP_SUCCESS;
3790
3791 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3792 return BGP_ERR_INVALID_VALUE;
3793
3794 if (peer->password && strcmp (peer->password, password) == 0
3795 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3796 return 0;
3797
3798 if (peer->password)
3799 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3800
3801 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3802
3803 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3804 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003805 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3806 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
Paul Jakma0df7c912008-07-21 21:02:49 +00003807 else
3808 BGP_EVENT_ADD (peer, BGP_Stop);
3809
3810 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3811 }
3812
3813 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3814 {
3815 if (peer->password && strcmp (peer->password, password) == 0)
3816 continue;
3817
3818 if (peer->password)
3819 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3820
3821 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3822
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003823 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003824 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3825 else
3826 BGP_EVENT_ADD (peer, BGP_Stop);
3827
3828 if (bgp_md5_set (peer) < 0)
3829 ret = BGP_ERR_TCPSIG_FAILED;
3830 }
3831
3832 return ret;
3833}
3834
3835int
3836peer_password_unset (struct peer *peer)
3837{
3838 struct listnode *nn, *nnode;
3839
3840 if (!peer->password
3841 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3842 return 0;
3843
3844 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3845 {
3846 if (peer_group_active (peer)
3847 && peer->group->conf->password
3848 && strcmp (peer->group->conf->password, peer->password) == 0)
3849 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3850
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003851 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003852 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3853 else
3854 BGP_EVENT_ADD (peer, BGP_Stop);
3855
3856 if (peer->password)
3857 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3858
3859 peer->password = NULL;
3860
3861 bgp_md5_set (peer);
3862
3863 return 0;
3864 }
3865
3866 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3867 peer->password = NULL;
3868
3869 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3870 {
3871 if (!peer->password)
3872 continue;
3873
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003874 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003875 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3876 else
3877 BGP_EVENT_ADD (peer, BGP_Stop);
3878
3879 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3880 peer->password = NULL;
3881
3882 bgp_md5_set (peer);
3883 }
3884
3885 return 0;
3886}
David Lamparter6b0655a2014-06-04 06:53:35 +02003887
paul718e3742002-12-13 20:15:29 +00003888/* Set distribute list to the peer. */
3889int
3890peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003891 const char *name)
paul718e3742002-12-13 20:15:29 +00003892{
3893 struct bgp_filter *filter;
3894 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003895 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003896
3897 if (! peer->afc[afi][safi])
3898 return BGP_ERR_PEER_INACTIVE;
3899
3900 if (direct != FILTER_IN && direct != FILTER_OUT)
3901 return BGP_ERR_INVALID_VALUE;
3902
3903 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3904 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3905
3906 filter = &peer->filter[afi][safi];
3907
3908 if (filter->plist[direct].name)
3909 return BGP_ERR_PEER_FILTER_CONFLICT;
3910
3911 if (filter->dlist[direct].name)
3912 free (filter->dlist[direct].name);
3913 filter->dlist[direct].name = strdup (name);
3914 filter->dlist[direct].alist = access_list_lookup (afi, name);
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 = strdup (name);
3930 filter->dlist[direct].alist = access_list_lookup (afi, name);
3931 }
3932
3933 return 0;
3934}
3935
3936int
3937peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3938{
3939 struct bgp_filter *filter;
3940 struct bgp_filter *gfilter;
3941 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003942 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003943
3944 if (! peer->afc[afi][safi])
3945 return BGP_ERR_PEER_INACTIVE;
3946
3947 if (direct != FILTER_IN && direct != FILTER_OUT)
3948 return BGP_ERR_INVALID_VALUE;
3949
3950 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3951 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3952
3953 filter = &peer->filter[afi][safi];
3954
3955 /* apply peer-group filter */
3956 if (peer->af_group[afi][safi])
3957 {
3958 gfilter = &peer->group->conf->filter[afi][safi];
3959
3960 if (gfilter->dlist[direct].name)
3961 {
3962 if (filter->dlist[direct].name)
3963 free (filter->dlist[direct].name);
3964 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3965 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3966 return 0;
3967 }
3968 }
3969
3970 if (filter->dlist[direct].name)
3971 free (filter->dlist[direct].name);
3972 filter->dlist[direct].name = NULL;
3973 filter->dlist[direct].alist = NULL;
3974
3975 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3976 return 0;
3977
3978 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003979 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003980 {
3981 filter = &peer->filter[afi][safi];
3982
3983 if (! peer->af_group[afi][safi])
3984 continue;
3985
3986 if (filter->dlist[direct].name)
3987 free (filter->dlist[direct].name);
3988 filter->dlist[direct].name = NULL;
3989 filter->dlist[direct].alist = NULL;
3990 }
3991
3992 return 0;
3993}
3994
3995/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003996static void
paul718e3742002-12-13 20:15:29 +00003997peer_distribute_update (struct access_list *access)
3998{
3999 afi_t afi;
4000 safi_t safi;
4001 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004002 struct listnode *mnode, *mnnode;
4003 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004004 struct bgp *bgp;
4005 struct peer *peer;
4006 struct peer_group *group;
4007 struct bgp_filter *filter;
4008
paul1eb8ef22005-04-07 07:30:20 +00004009 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004010 {
paul1eb8ef22005-04-07 07:30:20 +00004011 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004012 {
4013 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4014 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4015 {
4016 filter = &peer->filter[afi][safi];
4017
4018 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4019 {
4020 if (filter->dlist[direct].name)
4021 filter->dlist[direct].alist =
4022 access_list_lookup (afi, filter->dlist[direct].name);
4023 else
4024 filter->dlist[direct].alist = NULL;
4025 }
4026 }
4027 }
paul1eb8ef22005-04-07 07:30:20 +00004028 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004029 {
4030 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4031 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4032 {
4033 filter = &group->conf->filter[afi][safi];
4034
4035 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4036 {
4037 if (filter->dlist[direct].name)
4038 filter->dlist[direct].alist =
4039 access_list_lookup (afi, filter->dlist[direct].name);
4040 else
4041 filter->dlist[direct].alist = NULL;
4042 }
4043 }
4044 }
4045 }
4046}
David Lamparter6b0655a2014-06-04 06:53:35 +02004047
paul718e3742002-12-13 20:15:29 +00004048/* Set prefix list to the peer. */
4049int
4050peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004051 const char *name)
paul718e3742002-12-13 20:15:29 +00004052{
4053 struct bgp_filter *filter;
4054 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004055 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004056
4057 if (! peer->afc[afi][safi])
4058 return BGP_ERR_PEER_INACTIVE;
4059
4060 if (direct != FILTER_IN && direct != FILTER_OUT)
4061 return BGP_ERR_INVALID_VALUE;
4062
4063 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4064 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4065
4066 filter = &peer->filter[afi][safi];
4067
4068 if (filter->dlist[direct].name)
4069 return BGP_ERR_PEER_FILTER_CONFLICT;
4070
4071 if (filter->plist[direct].name)
4072 free (filter->plist[direct].name);
4073 filter->plist[direct].name = strdup (name);
4074 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4075
4076 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4077 return 0;
4078
4079 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004080 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004081 {
4082 filter = &peer->filter[afi][safi];
4083
4084 if (! peer->af_group[afi][safi])
4085 continue;
4086
4087 if (filter->plist[direct].name)
4088 free (filter->plist[direct].name);
4089 filter->plist[direct].name = strdup (name);
4090 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4091 }
4092 return 0;
4093}
4094
4095int
4096peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4097{
4098 struct bgp_filter *filter;
4099 struct bgp_filter *gfilter;
4100 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004101 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004102
4103 if (! peer->afc[afi][safi])
4104 return BGP_ERR_PEER_INACTIVE;
4105
4106 if (direct != FILTER_IN && direct != FILTER_OUT)
4107 return BGP_ERR_INVALID_VALUE;
4108
4109 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4110 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4111
4112 filter = &peer->filter[afi][safi];
4113
4114 /* apply peer-group filter */
4115 if (peer->af_group[afi][safi])
4116 {
4117 gfilter = &peer->group->conf->filter[afi][safi];
4118
4119 if (gfilter->plist[direct].name)
4120 {
4121 if (filter->plist[direct].name)
4122 free (filter->plist[direct].name);
4123 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
4124 filter->plist[direct].plist = gfilter->plist[direct].plist;
4125 return 0;
4126 }
4127 }
4128
4129 if (filter->plist[direct].name)
4130 free (filter->plist[direct].name);
4131 filter->plist[direct].name = NULL;
4132 filter->plist[direct].plist = NULL;
4133
4134 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4135 return 0;
4136
4137 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004138 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004139 {
4140 filter = &peer->filter[afi][safi];
4141
4142 if (! peer->af_group[afi][safi])
4143 continue;
4144
4145 if (filter->plist[direct].name)
4146 free (filter->plist[direct].name);
4147 filter->plist[direct].name = NULL;
4148 filter->plist[direct].plist = NULL;
4149 }
4150
4151 return 0;
4152}
4153
4154/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00004155static void
paul718e3742002-12-13 20:15:29 +00004156peer_prefix_list_update (struct prefix_list *plist)
4157{
paul1eb8ef22005-04-07 07:30:20 +00004158 struct listnode *mnode, *mnnode;
4159 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004160 struct bgp *bgp;
4161 struct peer *peer;
4162 struct peer_group *group;
4163 struct bgp_filter *filter;
4164 afi_t afi;
4165 safi_t safi;
4166 int direct;
4167
paul1eb8ef22005-04-07 07:30:20 +00004168 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004169 {
paul1eb8ef22005-04-07 07:30:20 +00004170 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004171 {
4172 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4173 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4174 {
4175 filter = &peer->filter[afi][safi];
4176
4177 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4178 {
4179 if (filter->plist[direct].name)
4180 filter->plist[direct].plist =
4181 prefix_list_lookup (afi, filter->plist[direct].name);
4182 else
4183 filter->plist[direct].plist = NULL;
4184 }
4185 }
4186 }
paul1eb8ef22005-04-07 07:30:20 +00004187 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004188 {
4189 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4190 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4191 {
4192 filter = &group->conf->filter[afi][safi];
4193
4194 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4195 {
4196 if (filter->plist[direct].name)
4197 filter->plist[direct].plist =
4198 prefix_list_lookup (afi, filter->plist[direct].name);
4199 else
4200 filter->plist[direct].plist = NULL;
4201 }
4202 }
4203 }
4204 }
4205}
David Lamparter6b0655a2014-06-04 06:53:35 +02004206
paul718e3742002-12-13 20:15:29 +00004207int
4208peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004209 const char *name)
paul718e3742002-12-13 20:15:29 +00004210{
4211 struct bgp_filter *filter;
4212 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004213 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004214
4215 if (! peer->afc[afi][safi])
4216 return BGP_ERR_PEER_INACTIVE;
4217
4218 if (direct != FILTER_IN && direct != FILTER_OUT)
4219 return BGP_ERR_INVALID_VALUE;
4220
4221 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4222 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4223
4224 filter = &peer->filter[afi][safi];
4225
4226 if (filter->aslist[direct].name)
4227 free (filter->aslist[direct].name);
4228 filter->aslist[direct].name = strdup (name);
4229 filter->aslist[direct].aslist = as_list_lookup (name);
4230
4231 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4232 return 0;
4233
4234 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004235 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004236 {
4237 filter = &peer->filter[afi][safi];
4238
4239 if (! peer->af_group[afi][safi])
4240 continue;
4241
4242 if (filter->aslist[direct].name)
4243 free (filter->aslist[direct].name);
4244 filter->aslist[direct].name = strdup (name);
4245 filter->aslist[direct].aslist = as_list_lookup (name);
4246 }
4247 return 0;
4248}
4249
4250int
4251peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4252{
4253 struct bgp_filter *filter;
4254 struct bgp_filter *gfilter;
4255 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004256 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004257
4258 if (! peer->afc[afi][safi])
4259 return BGP_ERR_PEER_INACTIVE;
4260
hassob5f29602005-05-25 21:00:28 +00004261 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004262 return BGP_ERR_INVALID_VALUE;
4263
hassob5f29602005-05-25 21:00:28 +00004264 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004265 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4266
4267 filter = &peer->filter[afi][safi];
4268
4269 /* apply peer-group filter */
4270 if (peer->af_group[afi][safi])
4271 {
4272 gfilter = &peer->group->conf->filter[afi][safi];
4273
4274 if (gfilter->aslist[direct].name)
4275 {
4276 if (filter->aslist[direct].name)
4277 free (filter->aslist[direct].name);
4278 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4279 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4280 return 0;
4281 }
4282 }
4283
4284 if (filter->aslist[direct].name)
4285 free (filter->aslist[direct].name);
4286 filter->aslist[direct].name = NULL;
4287 filter->aslist[direct].aslist = NULL;
4288
4289 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4290 return 0;
4291
4292 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004293 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004294 {
4295 filter = &peer->filter[afi][safi];
4296
4297 if (! peer->af_group[afi][safi])
4298 continue;
4299
4300 if (filter->aslist[direct].name)
4301 free (filter->aslist[direct].name);
4302 filter->aslist[direct].name = NULL;
4303 filter->aslist[direct].aslist = NULL;
4304 }
4305
4306 return 0;
4307}
4308
paul94f2b392005-06-28 12:44:16 +00004309static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004310peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004311{
4312 afi_t afi;
4313 safi_t safi;
4314 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004315 struct listnode *mnode, *mnnode;
4316 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004317 struct bgp *bgp;
4318 struct peer *peer;
4319 struct peer_group *group;
4320 struct bgp_filter *filter;
4321
paul1eb8ef22005-04-07 07:30:20 +00004322 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004323 {
paul1eb8ef22005-04-07 07:30:20 +00004324 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004325 {
4326 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4327 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4328 {
4329 filter = &peer->filter[afi][safi];
4330
4331 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4332 {
4333 if (filter->aslist[direct].name)
4334 filter->aslist[direct].aslist =
4335 as_list_lookup (filter->aslist[direct].name);
4336 else
4337 filter->aslist[direct].aslist = NULL;
4338 }
4339 }
4340 }
paul1eb8ef22005-04-07 07:30:20 +00004341 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004342 {
4343 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4344 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4345 {
4346 filter = &group->conf->filter[afi][safi];
4347
4348 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4349 {
4350 if (filter->aslist[direct].name)
4351 filter->aslist[direct].aslist =
4352 as_list_lookup (filter->aslist[direct].name);
4353 else
4354 filter->aslist[direct].aslist = NULL;
4355 }
4356 }
4357 }
4358 }
4359}
David Lamparter6b0655a2014-06-04 06:53:35 +02004360
paul718e3742002-12-13 20:15:29 +00004361/* Set route-map to the peer. */
4362int
4363peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004364 const char *name)
paul718e3742002-12-13 20:15:29 +00004365{
4366 struct bgp_filter *filter;
4367 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004368 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004369
4370 if (! peer->afc[afi][safi])
4371 return BGP_ERR_PEER_INACTIVE;
4372
paulfee0f4c2004-09-13 05:12:46 +00004373 if (direct != RMAP_IN && direct != RMAP_OUT &&
4374 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004375 return BGP_ERR_INVALID_VALUE;
4376
paulfee0f4c2004-09-13 05:12:46 +00004377 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4378 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004379 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4380
4381 filter = &peer->filter[afi][safi];
4382
4383 if (filter->map[direct].name)
4384 free (filter->map[direct].name);
4385
4386 filter->map[direct].name = strdup (name);
4387 filter->map[direct].map = route_map_lookup_by_name (name);
4388
4389 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4390 return 0;
4391
4392 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004393 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004394 {
4395 filter = &peer->filter[afi][safi];
4396
4397 if (! peer->af_group[afi][safi])
4398 continue;
4399
4400 if (filter->map[direct].name)
4401 free (filter->map[direct].name);
4402 filter->map[direct].name = strdup (name);
4403 filter->map[direct].map = route_map_lookup_by_name (name);
4404 }
4405 return 0;
4406}
4407
4408/* Unset route-map from the peer. */
4409int
4410peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4411{
4412 struct bgp_filter *filter;
4413 struct bgp_filter *gfilter;
4414 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004415 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004416
4417 if (! peer->afc[afi][safi])
4418 return BGP_ERR_PEER_INACTIVE;
4419
hassob5f29602005-05-25 21:00:28 +00004420 if (direct != RMAP_IN && direct != RMAP_OUT &&
4421 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004422 return BGP_ERR_INVALID_VALUE;
4423
hassob5f29602005-05-25 21:00:28 +00004424 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4425 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004426 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4427
4428 filter = &peer->filter[afi][safi];
4429
4430 /* apply peer-group filter */
4431 if (peer->af_group[afi][safi])
4432 {
4433 gfilter = &peer->group->conf->filter[afi][safi];
4434
4435 if (gfilter->map[direct].name)
4436 {
4437 if (filter->map[direct].name)
4438 free (filter->map[direct].name);
4439 filter->map[direct].name = strdup (gfilter->map[direct].name);
4440 filter->map[direct].map = gfilter->map[direct].map;
4441 return 0;
4442 }
4443 }
4444
4445 if (filter->map[direct].name)
4446 free (filter->map[direct].name);
4447 filter->map[direct].name = NULL;
4448 filter->map[direct].map = NULL;
4449
4450 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4451 return 0;
4452
4453 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004454 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004455 {
4456 filter = &peer->filter[afi][safi];
4457
4458 if (! peer->af_group[afi][safi])
4459 continue;
4460
4461 if (filter->map[direct].name)
4462 free (filter->map[direct].name);
4463 filter->map[direct].name = NULL;
4464 filter->map[direct].map = NULL;
4465 }
4466 return 0;
4467}
David Lamparter6b0655a2014-06-04 06:53:35 +02004468
paul718e3742002-12-13 20:15:29 +00004469/* Set unsuppress-map to the peer. */
4470int
paulfd79ac92004-10-13 05:06:08 +00004471peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4472 const char *name)
paul718e3742002-12-13 20:15:29 +00004473{
4474 struct bgp_filter *filter;
4475 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004476 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004477
4478 if (! peer->afc[afi][safi])
4479 return BGP_ERR_PEER_INACTIVE;
4480
4481 if (peer_is_group_member (peer, afi, safi))
4482 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4483
4484 filter = &peer->filter[afi][safi];
4485
4486 if (filter->usmap.name)
4487 free (filter->usmap.name);
4488
4489 filter->usmap.name = strdup (name);
4490 filter->usmap.map = route_map_lookup_by_name (name);
4491
4492 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4493 return 0;
4494
4495 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004496 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004497 {
4498 filter = &peer->filter[afi][safi];
4499
4500 if (! peer->af_group[afi][safi])
4501 continue;
4502
4503 if (filter->usmap.name)
4504 free (filter->usmap.name);
4505 filter->usmap.name = strdup (name);
4506 filter->usmap.map = route_map_lookup_by_name (name);
4507 }
4508 return 0;
4509}
4510
4511/* Unset route-map from the peer. */
4512int
4513peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4514{
4515 struct bgp_filter *filter;
4516 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004517 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004518
4519 if (! peer->afc[afi][safi])
4520 return BGP_ERR_PEER_INACTIVE;
4521
4522 if (peer_is_group_member (peer, afi, safi))
4523 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4524
4525 filter = &peer->filter[afi][safi];
4526
4527 if (filter->usmap.name)
4528 free (filter->usmap.name);
4529 filter->usmap.name = NULL;
4530 filter->usmap.map = NULL;
4531
4532 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4533 return 0;
4534
4535 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004536 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004537 {
4538 filter = &peer->filter[afi][safi];
4539
4540 if (! peer->af_group[afi][safi])
4541 continue;
4542
4543 if (filter->usmap.name)
4544 free (filter->usmap.name);
4545 filter->usmap.name = NULL;
4546 filter->usmap.map = NULL;
4547 }
4548 return 0;
4549}
David Lamparter6b0655a2014-06-04 06:53:35 +02004550
paul718e3742002-12-13 20:15:29 +00004551int
4552peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004553 u_int32_t max, u_char threshold,
4554 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004555{
4556 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004557 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004558
4559 if (! peer->afc[afi][safi])
4560 return BGP_ERR_PEER_INACTIVE;
4561
4562 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4563 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004564 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004565 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004566 if (warning)
4567 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4568 else
4569 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4570
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07004571 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
paul718e3742002-12-13 20:15:29 +00004572 {
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07004573 group = peer->group;
4574 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4575 {
4576 if (! peer->af_group[afi][safi])
4577 continue;
paul718e3742002-12-13 20:15:29 +00004578
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07004579 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4580 peer->pmax[afi][safi] = max;
4581 peer->pmax_threshold[afi][safi] = threshold;
4582 peer->pmax_restart[afi][safi] = restart;
4583 if (warning)
4584 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4585 else
4586 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4587
4588 if ((peer->status == Established) && (peer->afc[afi][safi]))
4589 bgp_maximum_prefix_overflow (peer, afi, safi, 1);
4590 }
paul718e3742002-12-13 20:15:29 +00004591 }
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07004592 else
4593 {
4594 if ((peer->status == Established) && (peer->afc[afi][safi]))
4595 bgp_maximum_prefix_overflow (peer, afi, safi, 1);
4596 }
4597
paul718e3742002-12-13 20:15:29 +00004598 return 0;
4599}
4600
4601int
4602peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4603{
4604 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004605 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004606
4607 if (! peer->afc[afi][safi])
4608 return BGP_ERR_PEER_INACTIVE;
4609
4610 /* apply peer-group config */
4611 if (peer->af_group[afi][safi])
4612 {
4613 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4614 PEER_FLAG_MAX_PREFIX))
4615 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4616 else
4617 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4618
4619 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4620 PEER_FLAG_MAX_PREFIX_WARNING))
4621 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4622 else
4623 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4624
4625 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004626 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004627 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004628 return 0;
4629 }
4630
4631 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4632 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4633 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004634 peer->pmax_threshold[afi][safi] = 0;
4635 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004636
4637 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4638 return 0;
4639
4640 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004641 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004642 {
4643 if (! peer->af_group[afi][safi])
4644 continue;
4645
4646 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4647 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4648 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004649 peer->pmax_threshold[afi][safi] = 0;
4650 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004651 }
4652 return 0;
4653}
David Lamparter5f9adb52014-05-19 23:15:02 +02004654
4655static int is_ebgp_multihop_configured (struct peer *peer)
4656{
4657 struct peer_group *group;
4658 struct listnode *node, *nnode;
4659 struct peer *peer1;
4660
4661 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4662 {
4663 group = peer->group;
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004664 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4665 (group->conf->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004666 return 1;
4667
4668 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4669 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004670 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
4671 (peer1->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004672 return 1;
4673 }
4674 }
4675 else
4676 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004677 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4678 (peer->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004679 return 1;
4680 }
4681 return 0;
4682}
4683
Nick Hilliardfa411a22011-03-23 15:33:17 +00004684/* Set # of hops between us and BGP peer. */
4685int
4686peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4687{
4688 struct peer_group *group;
4689 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004690 int ret;
4691
4692 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4693
Nick Hilliardfa411a22011-03-23 15:33:17 +00004694 /* We cannot configure ttl-security hops when ebgp-multihop is already
4695 set. For non peer-groups, the check is simple. For peer-groups, it's
4696 slightly messy, because we need to check both the peer-group structure
4697 and all peer-group members for any trace of ebgp-multihop configuration
4698 before actually applying the ttl-security rules. Cisco really made a
4699 mess of this configuration parameter, and OpenBGPD got it right.
4700 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004701
David Lamparter5f9adb52014-05-19 23:15:02 +02004702 if (peer->gtsm_hops == 0)
4703 {
4704 if (is_ebgp_multihop_configured (peer))
4705 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004706
David Lamparter5f9adb52014-05-19 23:15:02 +02004707 /* specify MAXTTL on outgoing packets */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004708 /* Routine handles iBGP peers correctly */
David Lamparter5f9adb52014-05-19 23:15:02 +02004709 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4710 if (ret != 0)
4711 return ret;
4712 }
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004713
Nick Hilliardfa411a22011-03-23 15:33:17 +00004714 peer->gtsm_hops = gtsm_hops;
4715
Nick Hilliardfa411a22011-03-23 15:33:17 +00004716 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4717 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004718 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004719 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4720 }
4721 else
4722 {
4723 group = peer->group;
4724 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4725 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004726 peer->gtsm_hops = group->conf->gtsm_hops;
4727
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004728 /* Change setting of existing peer
4729 * established then change value (may break connectivity)
4730 * not established yet (teardown session and restart)
4731 * no session then do nothing (will get handled by next connection)
4732 */
4733 if (peer->status == Established)
4734 {
4735 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4736 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4737 MAXTTL + 1 - peer->gtsm_hops);
4738 }
4739 else if (peer->status < Established)
4740 {
4741 if (BGP_DEBUG (events, EVENTS))
4742 zlog_debug ("%s Min-ttl changed", peer->host);
4743 BGP_EVENT_ADD (peer, BGP_Stop);
4744 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004745 }
4746 }
4747
4748 return 0;
4749}
4750
4751int
4752peer_ttl_security_hops_unset (struct peer *peer)
4753{
4754 struct peer_group *group;
4755 struct listnode *node, *nnode;
4756 struct peer *opeer;
4757
4758 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4759
Nick Hilliardfa411a22011-03-23 15:33:17 +00004760 /* if a peer-group member, then reset to peer-group default rather than 0 */
4761 if (peer_group_active (peer))
4762 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4763 else
4764 peer->gtsm_hops = 0;
4765
4766 opeer = peer;
4767 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4768 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004769 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004770 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4771 }
4772 else
4773 {
4774 group = peer->group;
4775 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4776 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004777 peer->gtsm_hops = 0;
4778
4779 if (peer->fd >= 0)
4780 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4781 }
4782 }
4783
4784 return peer_ebgp_multihop_unset (opeer);
4785}
David Lamparter6b0655a2014-06-04 06:53:35 +02004786
paul718e3742002-12-13 20:15:29 +00004787int
4788peer_clear (struct peer *peer)
4789{
4790 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4791 {
hasso0a486e52005-02-01 20:57:17 +00004792 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4793 {
4794 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4795 if (peer->t_pmax_restart)
4796 {
4797 BGP_TIMER_OFF (peer->t_pmax_restart);
4798 if (BGP_DEBUG (events, EVENTS))
4799 zlog_debug ("%s Maximum-prefix restart timer canceled",
4800 peer->host);
4801 }
4802 BGP_EVENT_ADD (peer, BGP_Start);
4803 return 0;
4804 }
4805
paul718e3742002-12-13 20:15:29 +00004806 peer->v_start = BGP_INIT_START_TIMER;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00004807 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00004808 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4809 BGP_NOTIFY_CEASE_ADMIN_RESET);
4810 else
4811 BGP_EVENT_ADD (peer, BGP_Stop);
4812 }
4813 return 0;
4814}
4815
4816int
4817peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4818 enum bgp_clear_type stype)
4819{
4820 if (peer->status != Established)
4821 return 0;
4822
4823 if (! peer->afc[afi][safi])
4824 return BGP_ERR_AF_UNCONFIGURED;
4825
Timo Teräs5a2a1ec2015-10-22 11:35:18 +03004826 peer->rtt = sockopt_tcp_rtt (peer->fd);
4827
paulfee0f4c2004-09-13 05:12:46 +00004828 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4829 {
4830 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4831 return 0;
4832 bgp_check_local_routes_rsclient (peer, afi, safi);
4833 bgp_soft_reconfig_rsclient (peer, afi, safi);
4834 }
4835
paul718e3742002-12-13 20:15:29 +00004836 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4837 bgp_announce_route (peer, afi, safi);
4838
4839 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4840 {
4841 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4842 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4843 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4844 {
4845 struct bgp_filter *filter = &peer->filter[afi][safi];
4846 u_char prefix_type;
4847
4848 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4849 prefix_type = ORF_TYPE_PREFIX;
4850 else
4851 prefix_type = ORF_TYPE_PREFIX_OLD;
4852
4853 if (filter->plist[FILTER_IN].plist)
4854 {
4855 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4856 bgp_route_refresh_send (peer, afi, safi,
4857 prefix_type, REFRESH_DEFER, 1);
4858 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4859 REFRESH_IMMEDIATE, 0);
4860 }
4861 else
4862 {
4863 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4864 bgp_route_refresh_send (peer, afi, safi,
4865 prefix_type, REFRESH_IMMEDIATE, 1);
4866 else
4867 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4868 }
4869 return 0;
4870 }
4871 }
4872
4873 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4874 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4875 {
4876 /* If neighbor has soft reconfiguration inbound flag.
4877 Use Adj-RIB-In database. */
4878 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4879 bgp_soft_reconfig_in (peer, afi, safi);
4880 else
4881 {
4882 /* If neighbor has route refresh capability, send route refresh
4883 message to the peer. */
4884 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4885 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4886 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4887 else
4888 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4889 }
4890 }
4891 return 0;
4892}
David Lamparter6b0655a2014-06-04 06:53:35 +02004893
paulfd79ac92004-10-13 05:06:08 +00004894/* Display peer uptime.*/
4895/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004896char *
4897peer_uptime (time_t uptime2, char *buf, size_t len)
4898{
4899 time_t uptime1;
4900 struct tm *tm;
4901
4902 /* Check buffer length. */
4903 if (len < BGP_UPTIME_LEN)
4904 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004905 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004906 /* XXX: should return status instead of buf... */
4907 snprintf (buf, len, "<error> ");
4908 return buf;
paul718e3742002-12-13 20:15:29 +00004909 }
4910
4911 /* If there is no connection has been done before print `never'. */
4912 if (uptime2 == 0)
4913 {
4914 snprintf (buf, len, "never ");
4915 return buf;
4916 }
4917
4918 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004919 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004920 uptime1 -= uptime2;
4921 tm = gmtime (&uptime1);
Paul Jakma84c38402015-05-26 15:19:38 +01004922
paul718e3742002-12-13 20:15:29 +00004923 /* Making formatted timer strings. */
4924#define ONE_DAY_SECOND 60*60*24
Paul Jakma84c38402015-05-26 15:19:38 +01004925#define ONE_WEEK_SECOND ONE_DAY_SECOND*7
4926#define ONE_YEAR_SECOND ONE_DAY_SECOND*365
paul718e3742002-12-13 20:15:29 +00004927
4928 if (uptime1 < ONE_DAY_SECOND)
4929 snprintf (buf, len, "%02d:%02d:%02d",
4930 tm->tm_hour, tm->tm_min, tm->tm_sec);
4931 else if (uptime1 < ONE_WEEK_SECOND)
4932 snprintf (buf, len, "%dd%02dh%02dm",
4933 tm->tm_yday, tm->tm_hour, tm->tm_min);
Paul Jakma84c38402015-05-26 15:19:38 +01004934 else if (uptime1 < ONE_YEAR_SECOND)
paul718e3742002-12-13 20:15:29 +00004935 snprintf (buf, len, "%02dw%dd%02dh",
4936 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
Paul Jakma84c38402015-05-26 15:19:38 +01004937 else
4938 snprintf (buf, len, "%02dy%02dw%dd",
4939 tm->tm_year - 70, tm->tm_yday/7,
4940 tm->tm_yday - ((tm->tm_yday/7) * 7));
paul718e3742002-12-13 20:15:29 +00004941 return buf;
4942}
David Lamparter6b0655a2014-06-04 06:53:35 +02004943
paul94f2b392005-06-28 12:44:16 +00004944static void
paul718e3742002-12-13 20:15:29 +00004945bgp_config_write_filter (struct vty *vty, struct peer *peer,
4946 afi_t afi, safi_t safi)
4947{
4948 struct bgp_filter *filter;
4949 struct bgp_filter *gfilter = NULL;
4950 char *addr;
4951 int in = FILTER_IN;
4952 int out = FILTER_OUT;
4953
4954 addr = peer->host;
4955 filter = &peer->filter[afi][safi];
4956 if (peer->af_group[afi][safi])
4957 gfilter = &peer->group->conf->filter[afi][safi];
4958
4959 /* distribute-list. */
4960 if (filter->dlist[in].name)
4961 if (! gfilter || ! gfilter->dlist[in].name
4962 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4963 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4964 filter->dlist[in].name, VTY_NEWLINE);
4965 if (filter->dlist[out].name && ! gfilter)
4966 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4967 filter->dlist[out].name, VTY_NEWLINE);
4968
4969 /* prefix-list. */
4970 if (filter->plist[in].name)
4971 if (! gfilter || ! gfilter->plist[in].name
4972 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4973 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4974 filter->plist[in].name, VTY_NEWLINE);
4975 if (filter->plist[out].name && ! gfilter)
4976 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4977 filter->plist[out].name, VTY_NEWLINE);
4978
4979 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004980 if (filter->map[RMAP_IN].name)
4981 if (! gfilter || ! gfilter->map[RMAP_IN].name
4982 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004983 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004984 filter->map[RMAP_IN].name, VTY_NEWLINE);
4985 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004986 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004987 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4988 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4989 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4990 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4991 if (filter->map[RMAP_EXPORT].name)
4992 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4993 || strcmp (filter->map[RMAP_EXPORT].name,
4994 gfilter->map[RMAP_EXPORT].name) != 0)
4995 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4996 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004997
4998 /* unsuppress-map */
4999 if (filter->usmap.name && ! gfilter)
5000 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
5001 filter->usmap.name, VTY_NEWLINE);
5002
5003 /* filter-list. */
5004 if (filter->aslist[in].name)
5005 if (! gfilter || ! gfilter->aslist[in].name
5006 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
5007 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
5008 filter->aslist[in].name, VTY_NEWLINE);
5009 if (filter->aslist[out].name && ! gfilter)
5010 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
5011 filter->aslist[out].name, VTY_NEWLINE);
5012}
5013
5014/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00005015static void
paul718e3742002-12-13 20:15:29 +00005016bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
5017 struct peer *peer, afi_t afi, safi_t safi)
5018{
paul718e3742002-12-13 20:15:29 +00005019 struct peer *g_peer = NULL;
5020 char buf[SU_ADDRSTRLEN];
5021 char *addr;
5022
paul718e3742002-12-13 20:15:29 +00005023 addr = peer->host;
5024 if (peer_group_active (peer))
5025 g_peer = peer->group->conf;
5026
5027 /************************************
5028 ****** Global to the neighbor ******
5029 ************************************/
5030 if (afi == AFI_IP && safi == SAFI_UNICAST)
5031 {
5032 /* remote-as. */
5033 if (! peer_group_active (peer))
5034 {
5035 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5036 vty_out (vty, " neighbor %s peer-group%s", addr,
5037 VTY_NEWLINE);
5038 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005039 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00005040 VTY_NEWLINE);
5041 }
5042 else
5043 {
5044 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005045 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00005046 VTY_NEWLINE);
5047 if (peer->af_group[AFI_IP][SAFI_UNICAST])
5048 vty_out (vty, " neighbor %s peer-group %s%s", addr,
5049 peer->group->name, VTY_NEWLINE);
5050 }
5051
5052 /* local-as. */
5053 if (peer->change_local_as)
5054 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00005055 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00005056 peer->change_local_as,
5057 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00005058 " no-prepend" : "",
5059 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
5060 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005061
5062 /* Description. */
5063 if (peer->desc)
5064 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
5065 VTY_NEWLINE);
5066
5067 /* Shutdown. */
5068 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
5069 if (! peer_group_active (peer) ||
5070 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
5071 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
5072
Paul Jakma0df7c912008-07-21 21:02:49 +00005073 /* Password. */
5074 if (peer->password)
5075 if (!peer_group_active (peer)
5076 || ! g_peer->password
5077 || strcmp (peer->password, g_peer->password) != 0)
5078 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
5079 VTY_NEWLINE);
5080
paul718e3742002-12-13 20:15:29 +00005081 /* BGP port. */
5082 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00005083 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00005084 VTY_NEWLINE);
5085
5086 /* Local interface name. */
5087 if (peer->ifname)
5088 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
5089 VTY_NEWLINE);
5090
5091 /* Passive. */
5092 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
5093 if (! peer_group_active (peer) ||
5094 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
5095 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
5096
5097 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00005098 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00005099 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00005100 if (! peer_group_active (peer) ||
5101 g_peer->ttl != peer->ttl)
5102 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
5103 VTY_NEWLINE);
5104
Nick Hilliardfa411a22011-03-23 15:33:17 +00005105 /* ttl-security hops */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00005106 if (peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00005107 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00005108 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00005109 peer->gtsm_hops, VTY_NEWLINE);
5110
hasso6ffd2072005-02-02 14:50:11 +00005111 /* disable-connected-check. */
5112 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00005113 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00005114 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
5115 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005116
5117 /* Update-source. */
5118 if (peer->update_if)
5119 if (! peer_group_active (peer) || ! g_peer->update_if
5120 || strcmp (g_peer->update_if, peer->update_if) != 0)
5121 vty_out (vty, " neighbor %s update-source %s%s", addr,
5122 peer->update_if, VTY_NEWLINE);
5123 if (peer->update_source)
5124 if (! peer_group_active (peer) || ! g_peer->update_source
5125 || sockunion_cmp (g_peer->update_source,
5126 peer->update_source) != 0)
5127 vty_out (vty, " neighbor %s update-source %s%s", addr,
5128 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
5129 VTY_NEWLINE);
5130
paul718e3742002-12-13 20:15:29 +00005131 /* advertisement-interval */
Daniel Walton0d7435f2015-10-22 11:35:20 +03005132 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV) &&
5133 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00005134 vty_out (vty, " neighbor %s advertisement-interval %d%s",
5135 addr, peer->v_routeadv, VTY_NEWLINE);
5136
5137 /* timers. */
5138 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
5139 && ! peer_group_active (peer))
5140 vty_out (vty, " neighbor %s timers %d %d%s", addr,
5141 peer->keepalive, peer->holdtime, VTY_NEWLINE);
5142
Daniel Walton0d7435f2015-10-22 11:35:20 +03005143 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT) &&
5144 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00005145 vty_out (vty, " neighbor %s timers connect %d%s", addr,
5146 peer->connect, VTY_NEWLINE);
5147
5148 /* Default weight. */
5149 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
5150 if (! peer_group_active (peer) ||
5151 g_peer->weight != peer->weight)
5152 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
5153 VTY_NEWLINE);
5154
paul718e3742002-12-13 20:15:29 +00005155 /* Dynamic capability. */
5156 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5157 if (! peer_group_active (peer) ||
5158 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5159 vty_out (vty, " neighbor %s capability dynamic%s", addr,
5160 VTY_NEWLINE);
5161
5162 /* dont capability negotiation. */
5163 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
5164 if (! peer_group_active (peer) ||
5165 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
5166 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
5167 VTY_NEWLINE);
5168
5169 /* override capability negotiation. */
5170 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5171 if (! peer_group_active (peer) ||
5172 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5173 vty_out (vty, " neighbor %s override-capability%s", addr,
5174 VTY_NEWLINE);
5175
5176 /* strict capability negotiation. */
5177 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5178 if (! peer_group_active (peer) ||
5179 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5180 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
5181 VTY_NEWLINE);
5182
Christian Franke15c71342012-11-19 11:17:31 +00005183 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
paul718e3742002-12-13 20:15:29 +00005184 {
5185 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5186 {
5187 if (peer->afc[AFI_IP][SAFI_UNICAST])
5188 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5189 }
5190 else
5191 {
5192 if (! peer->afc[AFI_IP][SAFI_UNICAST])
5193 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
5194 }
5195 }
5196 }
5197
5198
5199 /************************************
5200 ****** Per AF to the neighbor ******
5201 ************************************/
5202
5203 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
5204 {
5205 if (peer->af_group[afi][safi])
5206 vty_out (vty, " neighbor %s peer-group %s%s", addr,
5207 peer->group->name, VTY_NEWLINE);
5208 else
5209 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5210 }
5211
5212 /* ORF capability. */
5213 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5214 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5215 if (! peer->af_group[afi][safi])
5216 {
5217 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
5218
5219 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5220 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5221 vty_out (vty, " both");
5222 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
5223 vty_out (vty, " send");
5224 else
5225 vty_out (vty, " receive");
5226 vty_out (vty, "%s", VTY_NEWLINE);
5227 }
5228
5229 /* Route reflector client. */
5230 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
5231 && ! peer->af_group[afi][safi])
5232 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
5233 VTY_NEWLINE);
5234
5235 /* Nexthop self. */
5236 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
5237 && ! peer->af_group[afi][safi])
Timo Teräs9e7a53c2014-04-24 10:22:37 +03005238 vty_out (vty, " neighbor %s next-hop-self%s%s", addr,
5239 peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ?
5240 " all" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005241
5242 /* Remove private AS. */
5243 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
5244 && ! peer->af_group[afi][safi])
5245 vty_out (vty, " neighbor %s remove-private-AS%s",
5246 addr, VTY_NEWLINE);
5247
5248 /* send-community print. */
5249 if (! peer->af_group[afi][safi])
5250 {
5251 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5252 {
5253 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5254 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5255 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
5256 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5257 vty_out (vty, " neighbor %s send-community extended%s",
5258 addr, VTY_NEWLINE);
5259 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5260 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
5261 }
5262 else
5263 {
5264 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5265 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5266 vty_out (vty, " no neighbor %s send-community both%s",
5267 addr, VTY_NEWLINE);
5268 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5269 vty_out (vty, " no neighbor %s send-community extended%s",
5270 addr, VTY_NEWLINE);
5271 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5272 vty_out (vty, " no neighbor %s send-community%s",
5273 addr, VTY_NEWLINE);
5274 }
5275 }
5276
5277 /* Default information */
5278 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5279 && ! peer->af_group[afi][safi])
5280 {
5281 vty_out (vty, " neighbor %s default-originate", addr);
5282 if (peer->default_rmap[afi][safi].name)
5283 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5284 vty_out (vty, "%s", VTY_NEWLINE);
5285 }
5286
5287 /* Soft reconfiguration inbound. */
5288 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5289 if (! peer->af_group[afi][safi] ||
5290 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5291 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5292 VTY_NEWLINE);
5293
5294 /* maximum-prefix. */
5295 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5296 if (! peer->af_group[afi][safi]
5297 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005298 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005299 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5300 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005301 {
hasso0a486e52005-02-01 20:57:17 +00005302 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5303 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5304 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5305 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5306 vty_out (vty, " warning-only");
5307 if (peer->pmax_restart[afi][safi])
5308 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5309 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005310 }
paul718e3742002-12-13 20:15:29 +00005311
5312 /* Route server client. */
5313 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5314 && ! peer->af_group[afi][safi])
5315 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5316
Dylan Hall3cf12882011-10-27 15:28:17 +04005317 /* Nexthop-local unchanged. */
5318 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5319 && ! peer->af_group[afi][safi])
5320 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5321
paul718e3742002-12-13 20:15:29 +00005322 /* Allow AS in. */
5323 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5324 if (! peer_group_active (peer)
5325 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5326 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5327 {
5328 if (peer->allowas_in[afi][safi] == 3)
5329 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5330 else
5331 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5332 peer->allowas_in[afi][safi], VTY_NEWLINE);
5333 }
5334
5335 /* Filter. */
5336 bgp_config_write_filter (vty, peer, afi, safi);
5337
5338 /* atribute-unchanged. */
5339 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5340 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5341 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5342 && ! peer->af_group[afi][safi])
5343 {
5344 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5345 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5346 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5347 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5348 else
5349 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5350 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5351 " as-path" : "",
5352 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5353 " next-hop" : "",
5354 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5355 " med" : "", VTY_NEWLINE);
5356 }
5357}
5358
5359/* Display "address-family" configuration header. */
5360void
5361bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5362 int *write)
5363{
5364 if (*write)
5365 return;
5366
5367 if (afi == AFI_IP && safi == SAFI_UNICAST)
5368 return;
5369
5370 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5371
5372 if (afi == AFI_IP)
5373 {
5374 if (safi == SAFI_MULTICAST)
5375 vty_out (vty, "ipv4 multicast");
5376 else if (safi == SAFI_MPLS_VPN)
Lou Bergera3fda882016-01-12 13:42:04 -05005377 vty_out (vty, "vpnv4");
5378 else if (safi == SAFI_ENCAP)
5379 vty_out (vty, "encap");
paul718e3742002-12-13 20:15:29 +00005380 }
5381 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005382 {
Lou Berger13c378d2016-01-12 13:41:56 -05005383 if (safi == SAFI_MPLS_VPN)
5384 vty_out (vty, "vpnv6");
Lou Bergera3fda882016-01-12 13:42:04 -05005385 else if (safi == SAFI_ENCAP)
5386 vty_out (vty, "encapv6");
Lou Berger13c378d2016-01-12 13:41:56 -05005387 else
5388 {
5389 vty_out (vty, "ipv6");
5390 if (safi == SAFI_MULTICAST)
5391 vty_out (vty, " multicast");
5392 }
Paul Jakma37a217a2007-04-10 19:20:29 +00005393 }
paul718e3742002-12-13 20:15:29 +00005394
5395 vty_out (vty, "%s", VTY_NEWLINE);
5396
5397 *write = 1;
5398}
5399
5400/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005401static int
paul718e3742002-12-13 20:15:29 +00005402bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5403 safi_t safi)
5404{
5405 int write = 0;
5406 struct peer *peer;
5407 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005408 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005409
5410 bgp_config_write_network (vty, bgp, afi, safi, &write);
5411
5412 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5413
paul1eb8ef22005-04-07 07:30:20 +00005414 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005415 {
5416 if (group->conf->afc[afi][safi])
5417 {
5418 bgp_config_write_family_header (vty, afi, safi, &write);
5419 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5420 }
5421 }
paul1eb8ef22005-04-07 07:30:20 +00005422 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005423 {
5424 if (peer->afc[afi][safi])
5425 {
5426 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5427 {
5428 bgp_config_write_family_header (vty, afi, safi, &write);
5429 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5430 }
5431 }
5432 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005433
5434 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5435
Roman Hoog Antink6184c392014-03-17 14:01:42 +01005436 bgp_config_write_distance (vty, bgp, afi, safi, &write);
5437
paul718e3742002-12-13 20:15:29 +00005438 if (write)
5439 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5440
5441 return write;
5442}
5443
5444int
5445bgp_config_write (struct vty *vty)
5446{
5447 int write = 0;
5448 struct bgp *bgp;
5449 struct peer_group *group;
5450 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005451 struct listnode *node, *nnode;
5452 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005453
5454 /* BGP Multiple instance. */
5455 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5456 {
5457 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5458 write++;
5459 }
5460
5461 /* BGP Config type. */
5462 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5463 {
5464 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5465 write++;
5466 }
5467
5468 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005469 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005470 {
5471 if (write)
5472 vty_out (vty, "!%s", VTY_NEWLINE);
5473
5474 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005475 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005476
5477 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5478 {
5479 if (bgp->name)
5480 vty_out (vty, " view %s", bgp->name);
5481 }
5482 vty_out (vty, "%s", VTY_NEWLINE);
5483
5484 /* No Synchronization */
5485 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5486 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5487
5488 /* BGP fast-external-failover. */
5489 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5490 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5491
5492 /* BGP router ID. */
5493 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5494 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5495 VTY_NEWLINE);
5496
paul848973c2003-08-13 00:32:49 +00005497 /* BGP log-neighbor-changes. */
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07005498 if (!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5499 vty_out (vty, " no bgp log-neighbor-changes%s", VTY_NEWLINE);
paul848973c2003-08-13 00:32:49 +00005500
paul718e3742002-12-13 20:15:29 +00005501 /* BGP configuration. */
5502 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5503 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5504
5505 /* BGP default ipv4-unicast. */
5506 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5507 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5508
5509 /* BGP default local-preference. */
5510 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5511 vty_out (vty, " bgp default local-preference %d%s",
5512 bgp->default_local_pref, VTY_NEWLINE);
5513
5514 /* BGP client-to-client reflection. */
5515 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5516 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5517
5518 /* BGP cluster ID. */
5519 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5520 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5521 VTY_NEWLINE);
5522
hassoe0701b72004-05-20 09:19:34 +00005523 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005524 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005525 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5526 VTY_NEWLINE);
5527
5528 /* Confederation peer */
5529 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005530 {
hassoe0701b72004-05-20 09:19:34 +00005531 int i;
paul718e3742002-12-13 20:15:29 +00005532
hassoe0701b72004-05-20 09:19:34 +00005533 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005534
hassoe0701b72004-05-20 09:19:34 +00005535 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005536 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005537
hassoe0701b72004-05-20 09:19:34 +00005538 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005539 }
5540
5541 /* BGP enforce-first-as. */
5542 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5543 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5544
5545 /* BGP deterministic-med. */
5546 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5547 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005548
5549 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005550 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5551 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5552 bgp->stalepath_time, VTY_NEWLINE);
Philippe Guibert4afa3dd2016-05-24 16:52:02 +02005553 if (bgp->restart_time != BGP_DEFAULT_RESTART_TIME)
5554 vty_out (vty, " bgp graceful-restart restart-time %d%s",
5555 bgp->restart_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005556 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5557 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5558
paul718e3742002-12-13 20:15:29 +00005559 /* BGP bestpath method. */
5560 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5561 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005562 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5563 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
Pradosh Mohapatra2fdd4552013-09-07 07:02:36 +00005564 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
5565 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
5566 }
Dinesh Dutt083e5e22015-11-09 20:21:54 -05005567 if (bgp_flag_check (bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
5568 vty_out (vty, " bgp route-reflector allow-outbound-policy%s",
5569 VTY_NEWLINE);
5570 }
paul718e3742002-12-13 20:15:29 +00005571 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5572 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5573 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5574 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5575 {
5576 vty_out (vty, " bgp bestpath med");
5577 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5578 vty_out (vty, " confed");
5579 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5580 vty_out (vty, " missing-as-worst");
5581 vty_out (vty, "%s", VTY_NEWLINE);
5582 }
5583
5584 /* BGP network import check. */
5585 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5586 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5587
paul718e3742002-12-13 20:15:29 +00005588 /* BGP flag dampening. */
5589 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5590 BGP_CONFIG_DAMPENING))
5591 bgp_config_write_damp (vty);
5592
5593 /* BGP static route configuration. */
5594 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5595
5596 /* BGP redistribute configuration. */
5597 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5598
5599 /* BGP timers configuration. */
5600 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5601 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5602 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5603 bgp->default_holdtime, VTY_NEWLINE);
5604
5605 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005606 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005607 {
5608 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5609 }
5610
5611 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005612 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005613 {
5614 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5615 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5616 }
5617
Josh Bailey165b5ff2011-07-20 20:43:22 -07005618 /* maximum-paths */
5619 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5620
paul718e3742002-12-13 20:15:29 +00005621 /* Distance configuration. */
Roman Hoog Antink6184c392014-03-17 14:01:42 +01005622 bgp_config_write_distance (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
paul718e3742002-12-13 20:15:29 +00005623
5624 /* No auto-summary */
5625 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5626 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5627
5628 /* IPv4 multicast configuration. */
5629 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5630
5631 /* IPv4 VPN configuration. */
5632 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5633
Lou Bergera3fda882016-01-12 13:42:04 -05005634 /* ENCAPv4 configuration. */
5635 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_ENCAP);
5636
paul718e3742002-12-13 20:15:29 +00005637 /* IPv6 unicast configuration. */
5638 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5639
Paul Jakma37a217a2007-04-10 19:20:29 +00005640 /* IPv6 multicast configuration. */
5641 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5642
Lou Berger13c378d2016-01-12 13:41:56 -05005643 /* IPv6 VPN configuration. */
5644 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MPLS_VPN);
5645
Lou Bergera3fda882016-01-12 13:42:04 -05005646 /* ENCAPv6 configuration. */
5647 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_ENCAP);
5648
5649 vty_out (vty, " exit%s", VTY_NEWLINE);
5650
paul718e3742002-12-13 20:15:29 +00005651 write++;
5652 }
5653 return write;
5654}
5655
5656void
paul94f2b392005-06-28 12:44:16 +00005657bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005658{
5659 memset (&bgp_master, 0, sizeof (struct bgp_master));
5660
5661 bm = &bgp_master;
5662 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005663 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005664 bm->port = BGP_PORT_DEFAULT;
5665 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005666 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005667}
paul200df112005-06-01 11:17:05 +00005668
David Lamparter6b0655a2014-06-04 06:53:35 +02005669
paul718e3742002-12-13 20:15:29 +00005670void
paul94f2b392005-06-28 12:44:16 +00005671bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005672{
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07005673
5674 /* allocates some vital data structures used by peer commands in vty_init */
5675 bgp_scan_init ();
paul718e3742002-12-13 20:15:29 +00005676
paul718e3742002-12-13 20:15:29 +00005677 /* Init zebra. */
Donald Sharp774914f2015-10-14 08:50:39 -04005678 bgp_zebra_init (bm->master);
paul718e3742002-12-13 20:15:29 +00005679
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07005680 /* BGP VTY commands installation. */
5681 bgp_vty_init ();
5682
paul718e3742002-12-13 20:15:29 +00005683 /* BGP inits. */
5684 bgp_attr_init ();
5685 bgp_debug_init ();
5686 bgp_dump_init ();
5687 bgp_route_init ();
5688 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005689 bgp_address_init ();
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07005690 bgp_scan_vty_init();
paul718e3742002-12-13 20:15:29 +00005691 bgp_mplsvpn_init ();
Lou Berger298cc2f2016-01-12 13:42:02 -05005692 bgp_encap_init ();
paul718e3742002-12-13 20:15:29 +00005693
5694 /* Access list initialize. */
5695 access_list_init ();
5696 access_list_add_hook (peer_distribute_update);
5697 access_list_delete_hook (peer_distribute_update);
5698
5699 /* Filter list initialize. */
5700 bgp_filter_init ();
5701 as_list_add_hook (peer_aslist_update);
5702 as_list_delete_hook (peer_aslist_update);
5703
5704 /* Prefix list initialize.*/
5705 prefix_list_init ();
5706 prefix_list_add_hook (peer_prefix_list_update);
5707 prefix_list_delete_hook (peer_prefix_list_update);
5708
5709 /* Community list initialize. */
5710 bgp_clist = community_list_init ();
5711
5712#ifdef HAVE_SNMP
5713 bgp_snmp_init ();
5714#endif /* HAVE_SNMP */
5715}
paul545acaf2004-04-20 15:13:15 +00005716
5717void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005718bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005719{
paul545acaf2004-04-20 15:13:15 +00005720 struct bgp *bgp;
5721 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005722 struct listnode *node, *nnode;
5723 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005724
paul1eb8ef22005-04-07 07:30:20 +00005725 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5726 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005727 if (peer->status == Established)
5728 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5729 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005730
paul545acaf2004-04-20 15:13:15 +00005731 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005732
paule210cf92005-06-15 19:15:35 +00005733 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005734 {
5735 work_queue_free (bm->process_main_queue);
5736 bm->process_main_queue = NULL;
5737 }
paule210cf92005-06-15 19:15:35 +00005738 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005739 {
5740 work_queue_free (bm->process_rsclient_queue);
5741 bm->process_rsclient_queue = NULL;
5742 }
paul545acaf2004-04-20 15:13:15 +00005743}