blob: eacf80442e14638e265524c272c96acbe4633be5 [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 Jakma0df7c912008-07-21 21:02:49 +00001300
1301 /* Password configuration */
1302 if (peer->password)
1303 {
1304 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1305 peer->password = NULL;
1306
1307 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1308 bgp_md5_set (peer);
1309 }
1310
Paul Jakmaca058a32006-09-14 02:58:49 +00001311 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001312
paul718e3742002-12-13 20:15:29 +00001313 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001314 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1315 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001316 {
Chris Caputo228da422009-07-18 05:44:03 +00001317 peer_unlock (peer); /* bgp peer list reference */
1318 list_delete_node (bgp->peer, pn);
1319 }
paul200df112005-06-01 11:17:05 +00001320
Chris Caputo228da422009-07-18 05:44:03 +00001321 if (peer_rsclient_active (peer)
1322 && (pn = listnode_lookup (bgp->rsclient, peer)))
1323 {
1324 peer_unlock (peer); /* rsclient list reference */
1325 list_delete_node (bgp->rsclient, pn);
1326
1327 /* Clear our own rsclient ribs. */
1328 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1329 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1330 if (CHECK_FLAG(peer->af_flags[afi][safi],
1331 PEER_FLAG_RSERVER_CLIENT))
1332 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001333 }
1334
1335 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1336 member of a peer_group. */
1337 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1338 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1339 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001340 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001341
paul200df112005-06-01 11:17:05 +00001342 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001343 if (peer->ibuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001344 {
1345 stream_free (peer->ibuf);
1346 peer->ibuf = NULL;
1347 }
1348
paul718e3742002-12-13 20:15:29 +00001349 if (peer->obuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001350 {
1351 stream_fifo_free (peer->obuf);
1352 peer->obuf = NULL;
1353 }
1354
paul718e3742002-12-13 20:15:29 +00001355 if (peer->work)
Daniel Walton363c9032015-10-21 06:42:54 -07001356 {
1357 stream_free (peer->work);
1358 peer->work = NULL;
1359 }
1360
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00001361 if (peer->scratch)
Daniel Walton363c9032015-10-21 06:42:54 -07001362 {
1363 stream_free(peer->scratch);
1364 peer->scratch = NULL;
1365 }
Paul Jakma18937402006-07-27 19:05:12 +00001366
paul718e3742002-12-13 20:15:29 +00001367 /* Local and remote addresses. */
1368 if (peer->su_local)
Daniel Walton363c9032015-10-21 06:42:54 -07001369 {
1370 sockunion_free (peer->su_local);
1371 peer->su_local = NULL;
1372 }
1373
paul718e3742002-12-13 20:15:29 +00001374 if (peer->su_remote)
Daniel Walton363c9032015-10-21 06:42:54 -07001375 {
1376 sockunion_free (peer->su_remote);
1377 peer->su_remote = NULL;
1378 }
paul200df112005-06-01 11:17:05 +00001379
paul718e3742002-12-13 20:15:29 +00001380 /* Free filter related memory. */
1381 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1382 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1383 {
1384 filter = &peer->filter[afi][safi];
1385
1386 for (i = FILTER_IN; i < FILTER_MAX; i++)
1387 {
1388 if (filter->dlist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001389 {
1390 free(filter->dlist[i].name);
1391 filter->dlist[i].name = NULL;
1392 }
1393
paul718e3742002-12-13 20:15:29 +00001394 if (filter->plist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001395 {
1396 free(filter->plist[i].name);
1397 filter->plist[i].name = NULL;
1398 }
1399
paul718e3742002-12-13 20:15:29 +00001400 if (filter->aslist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001401 {
1402 free(filter->aslist[i].name);
1403 filter->aslist[i].name = NULL;
1404 }
paul200df112005-06-01 11:17:05 +00001405 }
Daniel Walton363c9032015-10-21 06:42:54 -07001406
paul200df112005-06-01 11:17:05 +00001407 for (i = RMAP_IN; i < RMAP_MAX; i++)
1408 {
paul718e3742002-12-13 20:15:29 +00001409 if (filter->map[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001410 {
1411 free (filter->map[i].name);
1412 filter->map[i].name = NULL;
1413 }
paul718e3742002-12-13 20:15:29 +00001414 }
1415
1416 if (filter->usmap.name)
Daniel Walton363c9032015-10-21 06:42:54 -07001417 {
1418 free (filter->usmap.name);
1419 filter->usmap.name = NULL;
1420 }
paul718e3742002-12-13 20:15:29 +00001421
1422 if (peer->default_rmap[afi][safi].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001423 {
1424 free (peer->default_rmap[afi][safi].name);
1425 peer->default_rmap[afi][safi].name = NULL;
1426 }
paul718e3742002-12-13 20:15:29 +00001427 }
paul200df112005-06-01 11:17:05 +00001428
Lou Berger82dd7072016-01-12 13:41:57 -05001429 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETING))
1430 bgp_peer_clear_node_queue_drain_immediate(peer);
1431
paul200df112005-06-01 11:17:05 +00001432 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001433
1434 return 0;
1435}
David Lamparter6b0655a2014-06-04 06:53:35 +02001436
paul94f2b392005-06-28 12:44:16 +00001437static int
paul718e3742002-12-13 20:15:29 +00001438peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1439{
1440 return strcmp (g1->name, g2->name);
1441}
1442
1443/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001444static int
paul718e3742002-12-13 20:15:29 +00001445peer_group_active (struct peer *peer)
1446{
1447 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1448 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1449 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05001450 || peer->af_group[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00001451 || peer->af_group[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05001452 || peer->af_group[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05001453 || peer->af_group[AFI_IP6][SAFI_MPLS_VPN]
1454 || peer->af_group[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00001455 return 1;
1456 return 0;
1457}
1458
1459/* Peer group cofiguration. */
1460static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001461peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001462{
1463 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1464 sizeof (struct peer_group));
1465}
1466
paul94f2b392005-06-28 12:44:16 +00001467static void
paul718e3742002-12-13 20:15:29 +00001468peer_group_free (struct peer_group *group)
1469{
1470 XFREE (MTYPE_PEER_GROUP, group);
1471}
1472
1473struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001474peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001475{
1476 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001477 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001478
paul1eb8ef22005-04-07 07:30:20 +00001479 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001480 {
1481 if (strcmp (group->name, name) == 0)
1482 return group;
1483 }
1484 return NULL;
1485}
1486
1487struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001488peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001489{
1490 struct peer_group *group;
1491
1492 group = peer_group_lookup (bgp, name);
1493 if (group)
1494 return group;
1495
1496 group = peer_group_new ();
1497 group->bgp = bgp;
1498 group->name = strdup (name);
1499 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001500 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001501 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1502 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001503 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001504 group->conf->group = group;
1505 group->conf->as = 0;
1506 group->conf->ttl = 1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001507 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001508 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1509 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1510 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1511 group->conf->keepalive = 0;
1512 group->conf->holdtime = 0;
1513 group->conf->connect = 0;
1514 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1515 listnode_add_sort (bgp->group, group);
1516
1517 return 0;
1518}
1519
paul94f2b392005-06-28 12:44:16 +00001520static void
paul718e3742002-12-13 20:15:29 +00001521peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1522 afi_t afi, safi_t safi)
1523{
1524 int in = FILTER_IN;
1525 int out = FILTER_OUT;
1526 struct peer *conf;
1527 struct bgp_filter *pfilter;
1528 struct bgp_filter *gfilter;
1529
1530 conf = group->conf;
1531 pfilter = &peer->filter[afi][safi];
1532 gfilter = &conf->filter[afi][safi];
1533
1534 /* remote-as */
1535 if (conf->as)
1536 peer->as = conf->as;
1537
1538 /* remote-as */
1539 if (conf->change_local_as)
1540 peer->change_local_as = conf->change_local_as;
1541
1542 /* TTL */
1543 peer->ttl = conf->ttl;
1544
Nick Hilliardfa411a22011-03-23 15:33:17 +00001545 /* GTSM hops */
1546 peer->gtsm_hops = conf->gtsm_hops;
1547
paul718e3742002-12-13 20:15:29 +00001548 /* Weight */
1549 peer->weight = conf->weight;
1550
1551 /* peer flags apply */
1552 peer->flags = conf->flags;
1553 /* peer af_flags apply */
1554 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1555 /* peer config apply */
1556 peer->config = conf->config;
1557
1558 /* peer timers apply */
1559 peer->holdtime = conf->holdtime;
1560 peer->keepalive = conf->keepalive;
1561 peer->connect = conf->connect;
1562 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1563 peer->v_connect = conf->connect;
1564 else
1565 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1566
1567 /* advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +03001568 if (CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
1569 peer->v_routeadv = conf->routeadv;
paul718e3742002-12-13 20:15:29 +00001570 else
Daniel Walton0d7435f2015-10-22 11:35:20 +03001571 if (peer_sort (peer) == BGP_PEER_IBGP)
1572 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1573 else
1574 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul718e3742002-12-13 20:15:29 +00001575
Paul Jakma0df7c912008-07-21 21:02:49 +00001576 /* password apply */
Roman Hoog Antink0e4303d2013-01-18 13:52:03 +01001577 if (conf->password && !peer->password)
Paul Jakma0df7c912008-07-21 21:02:49 +00001578 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
Paul Jakma0df7c912008-07-21 21:02:49 +00001579
1580 bgp_md5_set (peer);
1581
paul718e3742002-12-13 20:15:29 +00001582 /* maximum-prefix */
1583 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001584 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001585 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001586
1587 /* allowas-in */
1588 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1589
paulfee0f4c2004-09-13 05:12:46 +00001590 /* route-server-client */
1591 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1592 {
1593 /* Make peer's RIB point to group's RIB. */
1594 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1595
1596 /* Import policy. */
1597 if (pfilter->map[RMAP_IMPORT].name)
1598 free (pfilter->map[RMAP_IMPORT].name);
1599 if (gfilter->map[RMAP_IMPORT].name)
1600 {
1601 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1602 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1603 }
1604 else
1605 {
1606 pfilter->map[RMAP_IMPORT].name = NULL;
1607 pfilter->map[RMAP_IMPORT].map = NULL;
1608 }
1609
1610 /* Export policy. */
1611 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1612 {
1613 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1614 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1615 }
1616 }
1617
paul718e3742002-12-13 20:15:29 +00001618 /* default-originate route-map */
1619 if (conf->default_rmap[afi][safi].name)
1620 {
1621 if (peer->default_rmap[afi][safi].name)
1622 free (peer->default_rmap[afi][safi].name);
1623 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1624 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1625 }
1626
1627 /* update-source apply */
1628 if (conf->update_source)
1629 {
1630 if (peer->update_source)
1631 sockunion_free (peer->update_source);
1632 if (peer->update_if)
1633 {
1634 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1635 peer->update_if = NULL;
1636 }
1637 peer->update_source = sockunion_dup (conf->update_source);
1638 }
1639 else if (conf->update_if)
1640 {
1641 if (peer->update_if)
1642 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1643 if (peer->update_source)
1644 {
1645 sockunion_free (peer->update_source);
1646 peer->update_source = NULL;
1647 }
1648 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1649 }
1650
1651 /* inbound filter apply */
1652 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1653 {
1654 if (pfilter->dlist[in].name)
1655 free (pfilter->dlist[in].name);
1656 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1657 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1658 }
1659 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1660 {
1661 if (pfilter->plist[in].name)
1662 free (pfilter->plist[in].name);
1663 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1664 pfilter->plist[in].plist = gfilter->plist[in].plist;
1665 }
1666 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1667 {
1668 if (pfilter->aslist[in].name)
1669 free (pfilter->aslist[in].name);
1670 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1671 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1672 }
paulfee0f4c2004-09-13 05:12:46 +00001673 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001674 {
paulfee0f4c2004-09-13 05:12:46 +00001675 if (pfilter->map[RMAP_IN].name)
1676 free (pfilter->map[RMAP_IN].name);
1677 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1678 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001679 }
1680
1681 /* outbound filter apply */
1682 if (gfilter->dlist[out].name)
1683 {
1684 if (pfilter->dlist[out].name)
1685 free (pfilter->dlist[out].name);
1686 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1687 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1688 }
1689 else
1690 {
1691 if (pfilter->dlist[out].name)
1692 free (pfilter->dlist[out].name);
1693 pfilter->dlist[out].name = NULL;
1694 pfilter->dlist[out].alist = NULL;
1695 }
1696 if (gfilter->plist[out].name)
1697 {
1698 if (pfilter->plist[out].name)
1699 free (pfilter->plist[out].name);
1700 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1701 pfilter->plist[out].plist = gfilter->plist[out].plist;
1702 }
1703 else
1704 {
1705 if (pfilter->plist[out].name)
1706 free (pfilter->plist[out].name);
1707 pfilter->plist[out].name = NULL;
1708 pfilter->plist[out].plist = NULL;
1709 }
1710 if (gfilter->aslist[out].name)
1711 {
1712 if (pfilter->aslist[out].name)
1713 free (pfilter->aslist[out].name);
1714 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1715 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1716 }
1717 else
1718 {
1719 if (pfilter->aslist[out].name)
1720 free (pfilter->aslist[out].name);
1721 pfilter->aslist[out].name = NULL;
1722 pfilter->aslist[out].aslist = NULL;
1723 }
paulfee0f4c2004-09-13 05:12:46 +00001724 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001725 {
paulfee0f4c2004-09-13 05:12:46 +00001726 if (pfilter->map[RMAP_OUT].name)
1727 free (pfilter->map[RMAP_OUT].name);
1728 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1729 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001730 }
1731 else
1732 {
paulfee0f4c2004-09-13 05:12:46 +00001733 if (pfilter->map[RMAP_OUT].name)
1734 free (pfilter->map[RMAP_OUT].name);
1735 pfilter->map[RMAP_OUT].name = NULL;
1736 pfilter->map[RMAP_OUT].map = NULL;
1737 }
1738
1739 /* RS-client's import/export route-maps. */
1740 if (gfilter->map[RMAP_IMPORT].name)
1741 {
1742 if (pfilter->map[RMAP_IMPORT].name)
1743 free (pfilter->map[RMAP_IMPORT].name);
1744 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1745 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1746 }
1747 else
1748 {
1749 if (pfilter->map[RMAP_IMPORT].name)
1750 free (pfilter->map[RMAP_IMPORT].name);
1751 pfilter->map[RMAP_IMPORT].name = NULL;
1752 pfilter->map[RMAP_IMPORT].map = NULL;
1753 }
1754 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1755 {
1756 if (pfilter->map[RMAP_EXPORT].name)
1757 free (pfilter->map[RMAP_EXPORT].name);
1758 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1759 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001760 }
1761
1762 if (gfilter->usmap.name)
1763 {
1764 if (pfilter->usmap.name)
1765 free (pfilter->usmap.name);
1766 pfilter->usmap.name = strdup (gfilter->usmap.name);
1767 pfilter->usmap.map = gfilter->usmap.map;
1768 }
1769 else
1770 {
1771 if (pfilter->usmap.name)
1772 free (pfilter->usmap.name);
1773 pfilter->usmap.name = NULL;
1774 pfilter->usmap.map = NULL;
1775 }
1776}
1777
1778/* Peer group's remote AS configuration. */
1779int
paulfd79ac92004-10-13 05:06:08 +00001780peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001781{
1782 struct peer_group *group;
1783 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001784 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001785
1786 group = peer_group_lookup (bgp, group_name);
1787 if (! group)
1788 return -1;
1789
1790 if (group->conf->as == *as)
1791 return 0;
1792
1793 /* When we setup peer-group AS number all peer group member's AS
1794 number must be updated to same number. */
1795 peer_as_change (group->conf, *as);
1796
paul1eb8ef22005-04-07 07:30:20 +00001797 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001798 {
1799 if (peer->as != *as)
1800 peer_as_change (peer, *as);
1801 }
1802
1803 return 0;
1804}
1805
1806int
1807peer_group_delete (struct peer_group *group)
1808{
1809 struct bgp *bgp;
1810 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001811 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001812
1813 bgp = group->bgp;
1814
paul1eb8ef22005-04-07 07:30:20 +00001815 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001816 {
paul718e3742002-12-13 20:15:29 +00001817 peer_delete (peer);
1818 }
1819 list_delete (group->peer);
1820
1821 free (group->name);
1822 group->name = NULL;
1823
1824 group->conf->group = NULL;
1825 peer_delete (group->conf);
1826
1827 /* Delete from all peer_group list. */
1828 listnode_delete (bgp->group, group);
1829
1830 peer_group_free (group);
1831
1832 return 0;
1833}
1834
1835int
1836peer_group_remote_as_delete (struct peer_group *group)
1837{
1838 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001839 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001840
1841 if (! group->conf->as)
1842 return 0;
1843
paul1eb8ef22005-04-07 07:30:20 +00001844 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001845 {
paul718e3742002-12-13 20:15:29 +00001846 peer_delete (peer);
1847 }
1848 list_delete_all_node (group->peer);
1849
1850 group->conf->as = 0;
1851
1852 return 0;
1853}
1854
1855/* Bind specified peer to peer group. */
1856int
1857peer_group_bind (struct bgp *bgp, union sockunion *su,
1858 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1859{
1860 struct peer *peer;
1861 int first_member = 0;
1862
1863 /* Check peer group's address family. */
1864 if (! group->conf->afc[afi][safi])
1865 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1866
1867 /* Lookup the peer. */
1868 peer = peer_lookup (bgp, su);
1869
1870 /* Create a new peer. */
1871 if (! peer)
1872 {
1873 if (! group->conf->as)
1874 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1875
1876 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1877 peer->group = group;
1878 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001879
Paul Jakmaca058a32006-09-14 02:58:49 +00001880 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001881 listnode_add (group->peer, peer);
1882 peer_group2peer_config_copy (group, peer, afi, safi);
1883
1884 return 0;
1885 }
1886
1887 /* When the peer already belongs to peer group, check the consistency. */
1888 if (peer->af_group[afi][safi])
1889 {
1890 if (strcmp (peer->group->name, group->name) != 0)
1891 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1892
1893 return 0;
1894 }
1895
1896 /* Check current peer group configuration. */
1897 if (peer_group_active (peer)
1898 && strcmp (peer->group->name, group->name) != 0)
1899 return BGP_ERR_PEER_GROUP_MISMATCH;
1900
1901 if (! group->conf->as)
1902 {
1903 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1904 && peer_sort (group->conf) != peer_sort (peer))
1905 {
1906 if (as)
1907 *as = peer->as;
1908 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1909 }
1910
1911 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1912 first_member = 1;
1913 }
1914
1915 peer->af_group[afi][safi] = 1;
1916 peer->afc[afi][safi] = 1;
1917 if (! peer->group)
1918 {
1919 peer->group = group;
paul200df112005-06-01 11:17:05 +00001920
Paul Jakmaca058a32006-09-14 02:58:49 +00001921 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001922 listnode_add (group->peer, peer);
1923 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001924 else
1925 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001926
1927 if (first_member)
1928 {
1929 /* Advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +03001930 if (! CHECK_FLAG (group->conf->config, PEER_CONFIG_ROUTEADV))
1931 {
1932 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1933 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1934 else
1935 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1936 }
paul718e3742002-12-13 20:15:29 +00001937
1938 /* ebgp-multihop reset */
1939 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1940 group->conf->ttl = 255;
1941
1942 /* local-as reset */
1943 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1944 {
1945 group->conf->change_local_as = 0;
1946 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001947 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001948 }
1949 }
paulfee0f4c2004-09-13 05:12:46 +00001950
1951 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1952 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001953 struct listnode *pn;
1954
paulfee0f4c2004-09-13 05:12:46 +00001955 /* If it's not configured as RSERVER_CLIENT in any other address
1956 family, without being member of a peer_group, remove it from
1957 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001958 if (! peer_rsclient_active (peer)
1959 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001960 {
1961 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001962 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001963
1964 /* Clear our own rsclient rib for this afi/safi. */
1965 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001966 }
paulfee0f4c2004-09-13 05:12:46 +00001967
Paul Jakmab608d5b2008-07-02 02:12:07 +00001968 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001969
1970 /* Import policy. */
1971 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1972 {
1973 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1974 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1975 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1976 }
1977
1978 /* Export policy. */
1979 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1980 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1981 {
1982 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1983 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1984 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1985 }
1986 }
1987
paul718e3742002-12-13 20:15:29 +00001988 peer_group2peer_config_copy (group, peer, afi, safi);
1989
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001990 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001991 {
1992 peer->last_reset = PEER_DOWN_RMAP_BIND;
1993 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1994 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1995 }
paul718e3742002-12-13 20:15:29 +00001996 else
1997 BGP_EVENT_ADD (peer, BGP_Stop);
1998
1999 return 0;
2000}
2001
2002int
2003peer_group_unbind (struct bgp *bgp, struct peer *peer,
2004 struct peer_group *group, afi_t afi, safi_t safi)
2005{
2006 if (! peer->af_group[afi][safi])
2007 return 0;
2008
2009 if (group != peer->group)
2010 return BGP_ERR_PEER_GROUP_MISMATCH;
2011
2012 peer->af_group[afi][safi] = 0;
2013 peer->afc[afi][safi] = 0;
2014 peer_af_flag_reset (peer, afi, safi);
2015
paulfee0f4c2004-09-13 05:12:46 +00002016 if (peer->rib[afi][safi])
2017 peer->rib[afi][safi] = NULL;
2018
paul718e3742002-12-13 20:15:29 +00002019 if (! peer_group_active (peer))
2020 {
Paul Jakmaca058a32006-09-14 02:58:49 +00002021 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00002022 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00002023 listnode_delete (group->peer, peer);
2024 peer->group = NULL;
2025 if (group->conf->as)
2026 {
2027 peer_delete (peer);
2028 return 0;
2029 }
2030 peer_global_config_reset (peer);
2031 }
2032
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002033 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002034 {
2035 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
2036 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2037 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2038 }
paul718e3742002-12-13 20:15:29 +00002039 else
2040 BGP_EVENT_ADD (peer, BGP_Stop);
2041
2042 return 0;
2043}
David Lamparter6b0655a2014-06-04 06:53:35 +02002044
Vipin Kumardd49eb12014-09-30 14:36:38 -07002045
2046static int
2047bgp_startup_timer_expire (struct thread *thread)
2048{
2049 struct bgp *bgp;
2050
2051 bgp = THREAD_ARG (thread);
2052 bgp->t_startup = NULL;
2053
2054 return 0;
2055}
2056
paul718e3742002-12-13 20:15:29 +00002057/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00002058static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002059bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002060{
2061 struct bgp *bgp;
2062 afi_t afi;
2063 safi_t safi;
2064
paul200df112005-06-01 11:17:05 +00002065 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
2066 return NULL;
2067
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002068 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00002069 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00002070 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00002071
2072 bgp->peer = list_new ();
2073 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
2074
2075 bgp->group = list_new ();
2076 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
2077
paulfee0f4c2004-09-13 05:12:46 +00002078 bgp->rsclient = list_new ();
2079 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
2080
paul718e3742002-12-13 20:15:29 +00002081 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2082 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2083 {
Paul Jakma64e580a2006-02-21 01:09:01 +00002084 bgp->route[afi][safi] = bgp_table_init (afi, safi);
2085 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
2086 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07002087 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
2088 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00002089 }
2090
2091 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
2092 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
2093 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00002094 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
2095 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07002096 bgp_flag_set (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES);
paul718e3742002-12-13 20:15:29 +00002097
2098 bgp->as = *as;
2099
2100 if (name)
2101 bgp->name = strdup (name);
2102
Donald Sharp774914f2015-10-14 08:50:39 -04002103 THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire,
Vipin Kumardd49eb12014-09-30 14:36:38 -07002104 bgp, bgp->restart_time);
2105
paul718e3742002-12-13 20:15:29 +00002106 return bgp;
2107}
2108
2109/* Return first entry of BGP. */
2110struct bgp *
paul94f2b392005-06-28 12:44:16 +00002111bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00002112{
Lou Berger056f3762013-04-10 12:30:04 -07002113 if (bm && bm->bgp && bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00002114 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00002115 return NULL;
2116}
2117
2118/* Lookup BGP entry. */
2119struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002120bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00002121{
2122 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002123 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002124
paul1eb8ef22005-04-07 07:30:20 +00002125 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002126 if (bgp->as == as
2127 && ((bgp->name == NULL && name == NULL)
2128 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
2129 return bgp;
2130 return NULL;
2131}
2132
2133/* Lookup BGP structure by view name. */
2134struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002135bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002136{
2137 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002138 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002139
paul1eb8ef22005-04-07 07:30:20 +00002140 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002141 if ((bgp->name == NULL && name == NULL)
2142 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2143 return bgp;
2144 return NULL;
2145}
2146
2147/* Called from VTY commands. */
2148int
paulfd79ac92004-10-13 05:06:08 +00002149bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002150{
2151 struct bgp *bgp;
2152
2153 /* Multiple instance check. */
2154 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2155 {
2156 if (name)
2157 bgp = bgp_lookup_by_name (name);
2158 else
2159 bgp = bgp_get_default ();
2160
2161 /* Already exists. */
2162 if (bgp)
2163 {
2164 if (bgp->as != *as)
2165 {
2166 *as = bgp->as;
2167 return BGP_ERR_INSTANCE_MISMATCH;
2168 }
2169 *bgp_val = bgp;
2170 return 0;
2171 }
2172 }
2173 else
2174 {
2175 /* BGP instance name can not be specified for single instance. */
2176 if (name)
2177 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2178
2179 /* Get default BGP structure if exists. */
2180 bgp = bgp_get_default ();
2181
2182 if (bgp)
2183 {
2184 if (bgp->as != *as)
2185 {
2186 *as = bgp->as;
2187 return BGP_ERR_AS_MISMATCH;
2188 }
2189 *bgp_val = bgp;
2190 return 0;
2191 }
2192 }
2193
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002194 bgp = bgp_create (as, name);
2195 bgp_router_id_set(bgp, &router_id_zebra);
2196 *bgp_val = bgp;
2197
Paul Jakmaad12dde2012-06-13 22:50:07 +01002198 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002199 if (list_isempty(bm->bgp)
2200 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002201 {
2202 if (bgp_socket (bm->port, bm->address) < 0)
2203 return BGP_ERR_INVALID_VALUE;
2204 }
2205
paul718e3742002-12-13 20:15:29 +00002206 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002207
2208 return 0;
2209}
2210
2211/* Delete BGP instance. */
2212int
2213bgp_delete (struct bgp *bgp)
2214{
2215 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002216 struct peer_group *group;
Denil Vira57cd5e72015-08-10 12:46:14 -07002217 struct listnode *node, *pnode;
2218 struct listnode *next, *pnext;
paul718e3742002-12-13 20:15:29 +00002219 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002220 int i;
2221
Lou Berger82dd7072016-01-12 13:41:57 -05002222 SET_FLAG(bgp->flags, BGP_FLAG_DELETING);
2223
David Lampartercffe7802014-12-07 03:27:13 +01002224 THREAD_OFF (bgp->t_startup);
2225
Daniel Walton9e518dd2015-05-19 17:47:26 -07002226 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2227 {
2228 if (peer->status == Established ||
2229 peer->status == OpenSent ||
2230 peer->status == OpenConfirm)
2231 {
2232 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2233 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
2234 }
2235 }
2236
paul718e3742002-12-13 20:15:29 +00002237 /* Delete static route. */
2238 bgp_static_delete (bgp);
2239
2240 /* Unset redistribution. */
2241 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2242 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2243 if (i != ZEBRA_ROUTE_BGP)
2244 bgp_redistribute_unset (bgp, afi, i);
2245
paul1eb8ef22005-04-07 07:30:20 +00002246 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002247 {
2248 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2249 {
2250 /* Send notify to remote peer. */
2251 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2252 }
2253
2254 peer_delete (peer);
2255 }
paul718e3742002-12-13 20:15:29 +00002256
Chris Caputo228da422009-07-18 05:44:03 +00002257 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002258 {
Denil Vira57cd5e72015-08-10 12:46:14 -07002259 for (ALL_LIST_ELEMENTS (group->peer, pnode, pnext, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002260 {
2261 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2262 {
2263 /* Send notify to remote peer. */
2264 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2265 }
2266 }
2267 peer_group_delete (group);
2268 }
Chris Caputo228da422009-07-18 05:44:03 +00002269
2270 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002271
2272 if (bgp->peer_self) {
2273 peer_delete(bgp->peer_self);
2274 bgp->peer_self = NULL;
2275 }
Lou Berger82dd7072016-01-12 13:41:57 -05002276
2277 /*
2278 * Free pending deleted routes. Unfortunately, it also has to process
2279 * all the pending activity for other instances of struct bgp.
2280 *
2281 * This call was added to achieve clean memory allocation at exit,
2282 * for the sake of valgrind.
2283 */
2284 bgp_process_queues_drain_immediate();
2285
Paul Jakmafd35b942009-07-16 19:27:32 +01002286 /* Remove visibility via the master list - there may however still be
2287 * routes to be processed still referencing the struct bgp.
2288 */
2289 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002290 if (list_isempty(bm->bgp))
2291 bgp_close ();
2292
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002293 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002294
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002295 return 0;
2296}
2297
2298static void bgp_free (struct bgp *);
2299
2300void
2301bgp_lock (struct bgp *bgp)
2302{
2303 ++bgp->lock;
2304}
2305
2306void
2307bgp_unlock(struct bgp *bgp)
2308{
Chris Caputo228da422009-07-18 05:44:03 +00002309 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002310 if (--bgp->lock == 0)
2311 bgp_free (bgp);
2312}
2313
2314static void
2315bgp_free (struct bgp *bgp)
2316{
2317 afi_t afi;
2318 safi_t safi;
2319
2320 list_delete (bgp->group);
2321 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002322 list_delete (bgp->rsclient);
2323
paul718e3742002-12-13 20:15:29 +00002324 if (bgp->name)
2325 free (bgp->name);
2326
2327 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2328 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2329 {
2330 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002331 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002332 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002333 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002334 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002335 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002336 }
2337 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002338}
David Lamparter6b0655a2014-06-04 06:53:35 +02002339
paul718e3742002-12-13 20:15:29 +00002340struct peer *
2341peer_lookup (struct bgp *bgp, union sockunion *su)
2342{
2343 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002344 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002345
Steve Hillfc4dc592009-07-28 17:54:35 +01002346 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002347 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002348 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2349 if (sockunion_same (&peer->su, su)
2350 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2351 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002352 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002353 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002354 {
2355 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002356
Paul Jakma2158ad22009-07-28 18:10:55 +01002357 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2358 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2359 if (sockunion_same (&peer->su, su)
2360 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2361 return peer;
paul718e3742002-12-13 20:15:29 +00002362 }
2363 return NULL;
2364}
2365
2366struct peer *
2367peer_lookup_with_open (union sockunion *su, as_t remote_as,
2368 struct in_addr *remote_id, int *as)
2369{
2370 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002371 struct listnode *node;
2372 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002373 struct bgp *bgp;
2374
Steve Hillfc4dc592009-07-28 17:54:35 +01002375 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002376 return NULL;
2377
Paul Jakma9d878772009-08-05 16:25:16 +01002378 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002379 {
Paul Jakma9d878772009-08-05 16:25:16 +01002380 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2381 {
2382 if (sockunion_same (&peer->su, su)
2383 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2384 {
2385 if (peer->as == remote_as
2386 && peer->remote_id.s_addr == remote_id->s_addr)
2387 return peer;
2388 if (peer->as == remote_as)
2389 *as = 1;
2390 }
2391 }
2392
2393 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2394 {
2395 if (sockunion_same (&peer->su, su)
2396 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2397 {
2398 if (peer->as == remote_as
2399 && peer->remote_id.s_addr == 0)
2400 return peer;
2401 if (peer->as == remote_as)
2402 *as = 1;
2403 }
2404 }
paul718e3742002-12-13 20:15:29 +00002405 }
2406 return NULL;
2407}
David Lamparter6b0655a2014-06-04 06:53:35 +02002408
paul718e3742002-12-13 20:15:29 +00002409/* If peer is configured at least one address family return 1. */
2410int
2411peer_active (struct peer *peer)
2412{
2413 if (peer->afc[AFI_IP][SAFI_UNICAST]
2414 || peer->afc[AFI_IP][SAFI_MULTICAST]
2415 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05002416 || peer->afc[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00002417 || peer->afc[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05002418 || peer->afc[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05002419 || peer->afc[AFI_IP6][SAFI_MPLS_VPN]
2420 || peer->afc[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00002421 return 1;
2422 return 0;
2423}
2424
2425/* If peer is negotiated at least one address family return 1. */
2426int
2427peer_active_nego (struct peer *peer)
2428{
2429 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2430 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2431 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05002432 || peer->afc_nego[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00002433 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05002434 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05002435 || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
2436 || peer->afc_nego[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00002437 return 1;
2438 return 0;
2439}
David Lamparter6b0655a2014-06-04 06:53:35 +02002440
paul718e3742002-12-13 20:15:29 +00002441/* peer_flag_change_type. */
2442enum peer_change_type
2443{
2444 peer_change_none,
2445 peer_change_reset,
2446 peer_change_reset_in,
2447 peer_change_reset_out,
2448};
2449
paul94f2b392005-06-28 12:44:16 +00002450static void
paul718e3742002-12-13 20:15:29 +00002451peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2452 enum peer_change_type type)
2453{
2454 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2455 return;
2456
Stephen Hemmingerd9d4ae52010-01-13 00:32:39 +00002457 if (peer->status != Established)
2458 return;
2459
paul718e3742002-12-13 20:15:29 +00002460 if (type == peer_change_reset)
2461 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2462 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2463 else if (type == peer_change_reset_in)
2464 {
2465 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2466 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2467 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2468 else
2469 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2470 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2471 }
2472 else if (type == peer_change_reset_out)
2473 bgp_announce_route (peer, afi, safi);
2474}
2475
2476struct peer_flag_action
2477{
2478 /* Peer's flag. */
2479 u_int32_t flag;
2480
2481 /* This flag can be set for peer-group member. */
2482 u_char not_for_member;
2483
2484 /* Action when the flag is changed. */
2485 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002486
2487 /* Peer down cause */
2488 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002489};
2490
Stephen Hemminger03621952009-07-21 16:27:20 -07002491static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002492 {
2493 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2494 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2495 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2496 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2497 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002498 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002499 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002500 { 0, 0, 0 }
2501 };
2502
Stephen Hemminger03621952009-07-21 16:27:20 -07002503static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002504 {
2505 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2506 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2507 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2508 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2509 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2510 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2511 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2512 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2513 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2514 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2515 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2516 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2517 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002518 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
Timo Teräs9e7a53c2014-04-24 10:22:37 +03002519 { PEER_FLAG_NEXTHOP_SELF_ALL, 1, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002520 { 0, 0, 0 }
2521 };
2522
2523/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002524static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002525peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002526 struct peer_flag_action *action, u_int32_t flag)
2527{
2528 int i;
2529 int found = 0;
2530 int reset_in = 0;
2531 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002532 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002533
2534 /* Check peer's frag action. */
2535 for (i = 0; i < size; i++)
2536 {
2537 match = &action_list[i];
2538
2539 if (match->flag == 0)
2540 break;
2541
2542 if (match->flag & flag)
2543 {
2544 found = 1;
2545
2546 if (match->type == peer_change_reset_in)
2547 reset_in = 1;
2548 if (match->type == peer_change_reset_out)
2549 reset_out = 1;
2550 if (match->type == peer_change_reset)
2551 {
2552 reset_in = 1;
2553 reset_out = 1;
2554 }
2555 if (match->not_for_member)
2556 action->not_for_member = 1;
2557 }
2558 }
2559
2560 /* Set peer clear type. */
2561 if (reset_in && reset_out)
2562 action->type = peer_change_reset;
2563 else if (reset_in)
2564 action->type = peer_change_reset_in;
2565 else if (reset_out)
2566 action->type = peer_change_reset_out;
2567 else
2568 action->type = peer_change_none;
2569
2570 return found;
2571}
2572
paul94f2b392005-06-28 12:44:16 +00002573static void
paul718e3742002-12-13 20:15:29 +00002574peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2575{
2576 if (flag == PEER_FLAG_SHUTDOWN)
2577 {
2578 if (CHECK_FLAG (peer->flags, flag))
2579 {
hasso93406d82005-02-02 14:40:33 +00002580 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2581 peer_nsf_stop (peer);
2582
hasso0a486e52005-02-01 20:57:17 +00002583 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2584 if (peer->t_pmax_restart)
2585 {
2586 BGP_TIMER_OFF (peer->t_pmax_restart);
2587 if (BGP_DEBUG (events, EVENTS))
2588 zlog_debug ("%s Maximum-prefix restart timer canceled",
2589 peer->host);
2590 }
2591
hasso93406d82005-02-02 14:40:33 +00002592 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2593 peer_nsf_stop (peer);
2594
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002595 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002596 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2597 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2598 else
2599 BGP_EVENT_ADD (peer, BGP_Stop);
2600 }
2601 else
2602 {
2603 peer->v_start = BGP_INIT_START_TIMER;
2604 BGP_EVENT_ADD (peer, BGP_Stop);
2605 }
2606 }
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002607 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002608 {
hassoc9502432005-02-01 22:01:48 +00002609 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2610 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2611 else if (flag == PEER_FLAG_PASSIVE)
2612 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002613 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002614 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002615
hassoc9502432005-02-01 22:01:48 +00002616 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2617 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002618 }
2619 else
2620 BGP_EVENT_ADD (peer, BGP_Stop);
2621}
2622
2623/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002624static int
paul718e3742002-12-13 20:15:29 +00002625peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2626{
2627 int found;
2628 int size;
2629 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002630 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002631 struct peer_flag_action action;
2632
2633 memset (&action, 0, sizeof (struct peer_flag_action));
2634 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2635
2636 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2637
2638 /* No flag action is found. */
2639 if (! found)
2640 return BGP_ERR_INVALID_FLAG;
2641
2642 /* Not for peer-group member. */
2643 if (action.not_for_member && peer_group_active (peer))
2644 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2645
2646 /* When unset the peer-group member's flag we have to check
2647 peer-group configuration. */
2648 if (! set && peer_group_active (peer))
2649 if (CHECK_FLAG (peer->group->conf->flags, flag))
2650 {
2651 if (flag == PEER_FLAG_SHUTDOWN)
2652 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2653 else
2654 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2655 }
2656
2657 /* Flag conflict check. */
2658 if (set
2659 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2660 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2661 return BGP_ERR_PEER_FLAG_CONFLICT;
2662
2663 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2664 {
2665 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2666 return 0;
2667 if (! set && ! CHECK_FLAG (peer->flags, flag))
2668 return 0;
2669 }
2670
2671 if (set)
2672 SET_FLAG (peer->flags, flag);
2673 else
2674 UNSET_FLAG (peer->flags, flag);
2675
2676 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2677 {
2678 if (action.type == peer_change_reset)
2679 peer_flag_modify_action (peer, flag);
2680
2681 return 0;
2682 }
2683
2684 /* peer-group member updates. */
2685 group = peer->group;
2686
paul1eb8ef22005-04-07 07:30:20 +00002687 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002688 {
2689 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2690 continue;
2691
2692 if (! set && ! CHECK_FLAG (peer->flags, flag))
2693 continue;
2694
2695 if (set)
2696 SET_FLAG (peer->flags, flag);
2697 else
2698 UNSET_FLAG (peer->flags, flag);
2699
2700 if (action.type == peer_change_reset)
2701 peer_flag_modify_action (peer, flag);
2702 }
2703 return 0;
2704}
2705
2706int
2707peer_flag_set (struct peer *peer, u_int32_t flag)
2708{
2709 return peer_flag_modify (peer, flag, 1);
2710}
2711
2712int
2713peer_flag_unset (struct peer *peer, u_int32_t flag)
2714{
2715 return peer_flag_modify (peer, flag, 0);
2716}
2717
paul94f2b392005-06-28 12:44:16 +00002718static int
paul718e3742002-12-13 20:15:29 +00002719peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2720{
2721 if (peer->af_group[afi][safi])
2722 return 1;
2723 return 0;
2724}
2725
paul94f2b392005-06-28 12:44:16 +00002726static int
paul718e3742002-12-13 20:15:29 +00002727peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2728 int set)
2729{
2730 int found;
2731 int size;
paul1eb8ef22005-04-07 07:30:20 +00002732 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002733 struct peer_group *group;
2734 struct peer_flag_action action;
2735
2736 memset (&action, 0, sizeof (struct peer_flag_action));
2737 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2738
2739 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2740
2741 /* No flag action is found. */
2742 if (! found)
2743 return BGP_ERR_INVALID_FLAG;
2744
2745 /* Adress family must be activated. */
2746 if (! peer->afc[afi][safi])
2747 return BGP_ERR_PEER_INACTIVE;
2748
2749 /* Not for peer-group member. */
2750 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2751 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2752
2753 /* Spcecial check for reflector client. */
2754 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2755 && peer_sort (peer) != BGP_PEER_IBGP)
2756 return BGP_ERR_NOT_INTERNAL_PEER;
2757
2758 /* Spcecial check for remove-private-AS. */
2759 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2760 && peer_sort (peer) == BGP_PEER_IBGP)
2761 return BGP_ERR_REMOVE_PRIVATE_AS;
2762
2763 /* When unset the peer-group member's flag we have to check
2764 peer-group configuration. */
2765 if (! set && peer->af_group[afi][safi])
2766 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2767 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2768
2769 /* When current flag configuration is same as requested one. */
2770 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2771 {
2772 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2773 return 0;
2774 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2775 return 0;
2776 }
2777
2778 if (set)
2779 SET_FLAG (peer->af_flags[afi][safi], flag);
2780 else
2781 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2782
2783 /* Execute action when peer is established. */
2784 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2785 && peer->status == Established)
2786 {
2787 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2788 bgp_clear_adj_in (peer, afi, safi);
2789 else
hassoe0701b72004-05-20 09:19:34 +00002790 {
2791 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2792 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2793 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2794 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2795 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2796 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2797 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2798 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2799
2800 peer_change_action (peer, afi, safi, action.type);
2801 }
2802
paul718e3742002-12-13 20:15:29 +00002803 }
2804
2805 /* Peer group member updates. */
2806 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2807 {
2808 group = peer->group;
2809
paul1eb8ef22005-04-07 07:30:20 +00002810 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002811 {
2812 if (! peer->af_group[afi][safi])
2813 continue;
2814
2815 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2816 continue;
2817
2818 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2819 continue;
2820
2821 if (set)
2822 SET_FLAG (peer->af_flags[afi][safi], flag);
2823 else
2824 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2825
2826 if (peer->status == Established)
2827 {
2828 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2829 bgp_clear_adj_in (peer, afi, safi);
2830 else
hassoe0701b72004-05-20 09:19:34 +00002831 {
2832 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2833 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2834 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2835 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2836 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2837 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2838 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2839 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2840
2841 peer_change_action (peer, afi, safi, action.type);
2842 }
paul718e3742002-12-13 20:15:29 +00002843 }
2844 }
2845 }
2846 return 0;
2847}
2848
2849int
2850peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2851{
2852 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2853}
2854
2855int
2856peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2857{
2858 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2859}
David Lamparter6b0655a2014-06-04 06:53:35 +02002860
paul718e3742002-12-13 20:15:29 +00002861/* EBGP multihop configuration. */
2862int
2863peer_ebgp_multihop_set (struct peer *peer, int ttl)
2864{
2865 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002866 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002867 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002868
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002869 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002870 return 0;
2871
Nick Hilliardfa411a22011-03-23 15:33:17 +00002872 /* see comment in peer_ttl_security_hops_set() */
2873 if (ttl != MAXTTL)
2874 {
2875 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2876 {
2877 group = peer->group;
2878 if (group->conf->gtsm_hops != 0)
2879 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2880
2881 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2882 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002883 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002884 continue;
2885
2886 if (peer1->gtsm_hops != 0)
2887 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2888 }
2889 }
2890 else
2891 {
2892 if (peer->gtsm_hops != 0)
2893 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2894 }
2895 }
2896
paul718e3742002-12-13 20:15:29 +00002897 peer->ttl = ttl;
2898
2899 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2900 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002901 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002902 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002903 }
2904 else
2905 {
2906 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002907 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002908 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002909 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002910 continue;
paul718e3742002-12-13 20:15:29 +00002911
pauleb821182004-05-01 08:44:08 +00002912 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002913
pauleb821182004-05-01 08:44:08 +00002914 if (peer->fd >= 0)
2915 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2916 }
paul718e3742002-12-13 20:15:29 +00002917 }
2918 return 0;
2919}
2920
2921int
2922peer_ebgp_multihop_unset (struct peer *peer)
2923{
2924 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002925 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002926
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002927 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002928 return 0;
2929
Nick Hilliardfa411a22011-03-23 15:33:17 +00002930 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2931 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2932
paul718e3742002-12-13 20:15:29 +00002933 if (peer_group_active (peer))
2934 peer->ttl = peer->group->conf->ttl;
2935 else
2936 peer->ttl = 1;
2937
2938 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2939 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002940 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002941 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002942 }
2943 else
2944 {
2945 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002946 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002947 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002948 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002949 continue;
paul718e3742002-12-13 20:15:29 +00002950
pauleb821182004-05-01 08:44:08 +00002951 peer->ttl = 1;
2952
2953 if (peer->fd >= 0)
2954 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2955 }
paul718e3742002-12-13 20:15:29 +00002956 }
2957 return 0;
2958}
David Lamparter6b0655a2014-06-04 06:53:35 +02002959
paul718e3742002-12-13 20:15:29 +00002960/* Neighbor description. */
2961int
David Lamparterdfb9bd72016-05-24 18:58:07 +02002962peer_description_set (struct peer *peer, const char *desc)
paul718e3742002-12-13 20:15:29 +00002963{
2964 if (peer->desc)
2965 XFREE (MTYPE_PEER_DESC, peer->desc);
2966
2967 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2968
2969 return 0;
2970}
2971
2972int
2973peer_description_unset (struct peer *peer)
2974{
2975 if (peer->desc)
2976 XFREE (MTYPE_PEER_DESC, peer->desc);
2977
2978 peer->desc = NULL;
2979
2980 return 0;
2981}
David Lamparter6b0655a2014-06-04 06:53:35 +02002982
paul718e3742002-12-13 20:15:29 +00002983/* Neighbor update-source. */
2984int
paulfd79ac92004-10-13 05:06:08 +00002985peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002986{
2987 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002988 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002989
2990 if (peer->update_if)
2991 {
2992 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2993 && strcmp (peer->update_if, ifname) == 0)
2994 return 0;
2995
2996 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2997 peer->update_if = NULL;
2998 }
2999
3000 if (peer->update_source)
3001 {
3002 sockunion_free (peer->update_source);
3003 peer->update_source = NULL;
3004 }
3005
3006 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
3007
3008 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3009 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003010 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003011 {
3012 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3013 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3014 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3015 }
paul718e3742002-12-13 20:15:29 +00003016 else
3017 BGP_EVENT_ADD (peer, BGP_Stop);
3018 return 0;
3019 }
3020
3021 /* peer-group member updates. */
3022 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003023 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003024 {
3025 if (peer->update_if)
3026 {
3027 if (strcmp (peer->update_if, ifname) == 0)
3028 continue;
3029
3030 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3031 peer->update_if = NULL;
3032 }
3033
3034 if (peer->update_source)
3035 {
3036 sockunion_free (peer->update_source);
3037 peer->update_source = NULL;
3038 }
3039
3040 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
3041
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003042 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003043 {
3044 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3045 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3046 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3047 }
paul718e3742002-12-13 20:15:29 +00003048 else
3049 BGP_EVENT_ADD (peer, BGP_Stop);
3050 }
3051 return 0;
3052}
3053
3054int
David Lamparterdfb9bd72016-05-24 18:58:07 +02003055peer_update_source_addr_set (struct peer *peer, const union sockunion *su)
paul718e3742002-12-13 20:15:29 +00003056{
3057 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003058 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003059
3060 if (peer->update_source)
3061 {
3062 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3063 && sockunion_cmp (peer->update_source, su) == 0)
3064 return 0;
3065 sockunion_free (peer->update_source);
3066 peer->update_source = NULL;
3067 }
3068
3069 if (peer->update_if)
3070 {
3071 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3072 peer->update_if = NULL;
3073 }
3074
3075 peer->update_source = sockunion_dup (su);
3076
3077 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3078 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003079 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003080 {
3081 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3082 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3083 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3084 }
paul718e3742002-12-13 20:15:29 +00003085 else
3086 BGP_EVENT_ADD (peer, BGP_Stop);
3087 return 0;
3088 }
3089
3090 /* peer-group member updates. */
3091 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003092 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003093 {
3094 if (peer->update_source)
3095 {
3096 if (sockunion_cmp (peer->update_source, su) == 0)
3097 continue;
3098 sockunion_free (peer->update_source);
3099 peer->update_source = NULL;
3100 }
3101
3102 if (peer->update_if)
3103 {
3104 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3105 peer->update_if = NULL;
3106 }
3107
3108 peer->update_source = sockunion_dup (su);
3109
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003110 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003111 {
3112 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3113 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3114 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3115 }
paul718e3742002-12-13 20:15:29 +00003116 else
3117 BGP_EVENT_ADD (peer, BGP_Stop);
3118 }
3119 return 0;
3120}
3121
3122int
3123peer_update_source_unset (struct peer *peer)
3124{
3125 union sockunion *su;
3126 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003127 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003128
3129 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3130 && ! peer->update_source
3131 && ! peer->update_if)
3132 return 0;
3133
3134 if (peer->update_source)
3135 {
3136 sockunion_free (peer->update_source);
3137 peer->update_source = NULL;
3138 }
3139 if (peer->update_if)
3140 {
3141 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3142 peer->update_if = NULL;
3143 }
3144
3145 if (peer_group_active (peer))
3146 {
3147 group = peer->group;
3148
3149 if (group->conf->update_source)
3150 {
3151 su = sockunion_dup (group->conf->update_source);
3152 peer->update_source = su;
3153 }
3154 else if (group->conf->update_if)
3155 peer->update_if =
3156 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
3157 }
3158
3159 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3160 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003161 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003162 {
3163 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3164 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3165 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3166 }
paul718e3742002-12-13 20:15:29 +00003167 else
3168 BGP_EVENT_ADD (peer, BGP_Stop);
3169 return 0;
3170 }
3171
3172 /* peer-group member updates. */
3173 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003174 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003175 {
3176 if (! peer->update_source && ! peer->update_if)
3177 continue;
3178
3179 if (peer->update_source)
3180 {
3181 sockunion_free (peer->update_source);
3182 peer->update_source = NULL;
3183 }
3184
3185 if (peer->update_if)
3186 {
3187 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3188 peer->update_if = NULL;
3189 }
3190
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003191 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003192 {
3193 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3194 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3195 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3196 }
paul718e3742002-12-13 20:15:29 +00003197 else
3198 BGP_EVENT_ADD (peer, BGP_Stop);
3199 }
3200 return 0;
3201}
David Lamparter6b0655a2014-06-04 06:53:35 +02003202
paul718e3742002-12-13 20:15:29 +00003203int
3204peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003205 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003206{
3207 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003208 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003209
3210 /* Adress family must be activated. */
3211 if (! peer->afc[afi][safi])
3212 return BGP_ERR_PEER_INACTIVE;
3213
3214 /* Default originate can't be used for peer group memeber. */
3215 if (peer_is_group_member (peer, afi, safi))
3216 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3217
3218 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3219 || (rmap && ! peer->default_rmap[afi][safi].name)
3220 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3221 {
3222 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3223
3224 if (rmap)
3225 {
3226 if (peer->default_rmap[afi][safi].name)
3227 free (peer->default_rmap[afi][safi].name);
3228 peer->default_rmap[afi][safi].name = strdup (rmap);
3229 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3230 }
3231 }
3232
3233 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3234 {
3235 if (peer->status == Established && peer->afc_nego[afi][safi])
3236 bgp_default_originate (peer, afi, safi, 0);
3237 return 0;
3238 }
3239
3240 /* peer-group member updates. */
3241 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003242 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003243 {
3244 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3245
3246 if (rmap)
3247 {
3248 if (peer->default_rmap[afi][safi].name)
3249 free (peer->default_rmap[afi][safi].name);
3250 peer->default_rmap[afi][safi].name = strdup (rmap);
3251 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3252 }
3253
3254 if (peer->status == Established && peer->afc_nego[afi][safi])
3255 bgp_default_originate (peer, afi, safi, 0);
3256 }
3257 return 0;
3258}
3259
3260int
3261peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3262{
3263 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003264 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003265
3266 /* Adress family must be activated. */
3267 if (! peer->afc[afi][safi])
3268 return BGP_ERR_PEER_INACTIVE;
3269
3270 /* Default originate can't be used for peer group memeber. */
3271 if (peer_is_group_member (peer, afi, safi))
3272 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3273
3274 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3275 {
3276 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3277
3278 if (peer->default_rmap[afi][safi].name)
3279 free (peer->default_rmap[afi][safi].name);
3280 peer->default_rmap[afi][safi].name = NULL;
3281 peer->default_rmap[afi][safi].map = NULL;
3282 }
3283
3284 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3285 {
3286 if (peer->status == Established && peer->afc_nego[afi][safi])
3287 bgp_default_originate (peer, afi, safi, 1);
3288 return 0;
3289 }
3290
3291 /* peer-group member updates. */
3292 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003293 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003294 {
3295 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3296
3297 if (peer->default_rmap[afi][safi].name)
3298 free (peer->default_rmap[afi][safi].name);
3299 peer->default_rmap[afi][safi].name = NULL;
3300 peer->default_rmap[afi][safi].map = NULL;
3301
3302 if (peer->status == Established && peer->afc_nego[afi][safi])
3303 bgp_default_originate (peer, afi, safi, 1);
3304 }
3305 return 0;
3306}
David Lamparter6b0655a2014-06-04 06:53:35 +02003307
paul718e3742002-12-13 20:15:29 +00003308int
3309peer_port_set (struct peer *peer, u_int16_t port)
3310{
3311 peer->port = port;
3312 return 0;
3313}
3314
3315int
3316peer_port_unset (struct peer *peer)
3317{
3318 peer->port = BGP_PORT_DEFAULT;
3319 return 0;
3320}
David Lamparter6b0655a2014-06-04 06:53:35 +02003321
paul718e3742002-12-13 20:15:29 +00003322/* neighbor weight. */
3323int
3324peer_weight_set (struct peer *peer, u_int16_t weight)
3325{
3326 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003327 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003328
3329 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3330 peer->weight = weight;
3331
3332 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3333 return 0;
3334
3335 /* peer-group member updates. */
3336 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003337 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003338 {
3339 peer->weight = group->conf->weight;
3340 }
3341 return 0;
3342}
3343
3344int
3345peer_weight_unset (struct peer *peer)
3346{
3347 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003348 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003349
3350 /* Set default weight. */
3351 if (peer_group_active (peer))
3352 peer->weight = peer->group->conf->weight;
3353 else
3354 peer->weight = 0;
3355
3356 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3357
3358 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3359 return 0;
3360
3361 /* peer-group member updates. */
3362 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003363 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003364 {
3365 peer->weight = 0;
3366 }
3367 return 0;
3368}
David Lamparter6b0655a2014-06-04 06:53:35 +02003369
paul718e3742002-12-13 20:15:29 +00003370int
3371peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3372{
3373 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003374 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003375
3376 /* Not for peer group memeber. */
3377 if (peer_group_active (peer))
3378 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3379
3380 /* keepalive value check. */
3381 if (keepalive > 65535)
3382 return BGP_ERR_INVALID_VALUE;
3383
3384 /* Holdtime value check. */
3385 if (holdtime > 65535)
3386 return BGP_ERR_INVALID_VALUE;
3387
3388 /* Holdtime value must be either 0 or greater than 3. */
3389 if (holdtime < 3 && holdtime != 0)
3390 return BGP_ERR_INVALID_VALUE;
3391
3392 /* Set value to the configuration. */
3393 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3394 peer->holdtime = holdtime;
3395 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3396
3397 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3398 return 0;
3399
3400 /* peer-group member updates. */
3401 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003402 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003403 {
3404 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3405 peer->holdtime = group->conf->holdtime;
3406 peer->keepalive = group->conf->keepalive;
3407 }
3408 return 0;
3409}
3410
3411int
3412peer_timers_unset (struct peer *peer)
3413{
3414 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003415 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003416
3417 if (peer_group_active (peer))
3418 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3419
3420 /* Clear configuration. */
3421 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3422 peer->keepalive = 0;
3423 peer->holdtime = 0;
3424
3425 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3426 return 0;
3427
3428 /* peer-group member updates. */
3429 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003430 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003431 {
3432 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3433 peer->holdtime = 0;
3434 peer->keepalive = 0;
3435 }
3436
3437 return 0;
3438}
David Lamparter6b0655a2014-06-04 06:53:35 +02003439
paul718e3742002-12-13 20:15:29 +00003440int
3441peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3442{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003443 struct peer_group *group;
3444 struct listnode *node, *nnode;
3445
paul718e3742002-12-13 20:15:29 +00003446 if (peer_group_active (peer))
3447 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3448
3449 if (connect > 65535)
3450 return BGP_ERR_INVALID_VALUE;
3451
3452 /* Set value to the configuration. */
3453 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3454 peer->connect = connect;
3455
3456 /* Set value to timer setting. */
3457 peer->v_connect = connect;
3458
Daniel Walton0d7435f2015-10-22 11:35:20 +03003459 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3460 return 0;
3461
3462 /* peer-group member updates. */
3463 group = peer->group;
3464 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3465 {
3466 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3467 peer->connect = connect;
3468 peer->v_connect = connect;
3469 }
paul718e3742002-12-13 20:15:29 +00003470 return 0;
3471}
3472
3473int
3474peer_timers_connect_unset (struct peer *peer)
3475{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003476 struct peer_group *group;
3477 struct listnode *node, *nnode;
3478
paul718e3742002-12-13 20:15:29 +00003479 if (peer_group_active (peer))
3480 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3481
3482 /* Clear configuration. */
3483 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3484 peer->connect = 0;
3485
3486 /* Set timer setting to default value. */
3487 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3488
Daniel Walton0d7435f2015-10-22 11:35:20 +03003489 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3490 return 0;
3491
3492 /* peer-group member updates. */
3493 group = peer->group;
3494 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3495 {
3496 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3497 peer->connect = 0;
3498 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3499 }
3500 return 0;
paul718e3742002-12-13 20:15:29 +00003501}
David Lamparter6b0655a2014-06-04 06:53:35 +02003502
paul718e3742002-12-13 20:15:29 +00003503int
3504peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3505{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003506 struct peer_group *group;
3507 struct listnode *node, *nnode;
3508
paul718e3742002-12-13 20:15:29 +00003509 if (peer_group_active (peer))
3510 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3511
3512 if (routeadv > 600)
3513 return BGP_ERR_INVALID_VALUE;
3514
3515 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3516 peer->routeadv = routeadv;
3517 peer->v_routeadv = routeadv;
3518
Daniel Walton0d7435f2015-10-22 11:35:20 +03003519 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3520 return 0;
3521
3522 /* peer-group member updates. */
3523 group = peer->group;
3524 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3525 {
3526 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3527 peer->routeadv = routeadv;
3528 peer->v_routeadv = routeadv;
3529 }
3530
paul718e3742002-12-13 20:15:29 +00003531 return 0;
3532}
3533
3534int
3535peer_advertise_interval_unset (struct peer *peer)
3536{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003537 struct peer_group *group;
3538 struct listnode *node, *nnode;
3539
paul718e3742002-12-13 20:15:29 +00003540 if (peer_group_active (peer))
3541 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3542
3543 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3544 peer->routeadv = 0;
3545
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003546 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003547 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3548 else
3549 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
Daniel Walton0d7435f2015-10-22 11:35:20 +03003550
3551 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3552 return 0;
3553
3554 /* peer-group member updates. */
3555 group = peer->group;
3556 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3557 {
3558 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3559 peer->routeadv = 0;
3560
3561 if (peer->sort == BGP_PEER_IBGP)
3562 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3563 else
3564 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3565 }
paul718e3742002-12-13 20:15:29 +00003566
3567 return 0;
3568}
David Lamparter6b0655a2014-06-04 06:53:35 +02003569
paul718e3742002-12-13 20:15:29 +00003570/* neighbor interface */
3571int
paulfd79ac92004-10-13 05:06:08 +00003572peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003573{
3574 if (peer->ifname)
3575 free (peer->ifname);
3576 peer->ifname = strdup (str);
3577
3578 return 0;
3579}
3580
3581int
3582peer_interface_unset (struct peer *peer)
3583{
3584 if (peer->ifname)
3585 free (peer->ifname);
3586 peer->ifname = NULL;
3587
3588 return 0;
3589}
David Lamparter6b0655a2014-06-04 06:53:35 +02003590
paul718e3742002-12-13 20:15:29 +00003591/* Allow-as in. */
3592int
3593peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3594{
3595 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003596 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003597
3598 if (allow_num < 1 || allow_num > 10)
3599 return BGP_ERR_INVALID_VALUE;
3600
3601 if (peer->allowas_in[afi][safi] != allow_num)
3602 {
3603 peer->allowas_in[afi][safi] = allow_num;
3604 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3605 peer_change_action (peer, afi, safi, peer_change_reset_in);
3606 }
3607
3608 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3609 return 0;
3610
3611 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003612 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003613 {
3614 if (peer->allowas_in[afi][safi] != allow_num)
3615 {
3616 peer->allowas_in[afi][safi] = allow_num;
3617 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3618 peer_change_action (peer, afi, safi, peer_change_reset_in);
3619 }
3620
3621 }
3622 return 0;
3623}
3624
3625int
3626peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3627{
3628 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003629 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003630
3631 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3632 {
3633 peer->allowas_in[afi][safi] = 0;
3634 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3635 }
3636
3637 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3638 return 0;
3639
3640 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003641 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003642 {
3643 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3644 {
3645 peer->allowas_in[afi][safi] = 0;
3646 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3647 }
3648 }
3649 return 0;
3650}
David Lamparter6b0655a2014-06-04 06:53:35 +02003651
paul718e3742002-12-13 20:15:29 +00003652int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003653peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003654{
3655 struct bgp *bgp = peer->bgp;
3656 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003657 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003658
3659 if (peer_sort (peer) != BGP_PEER_EBGP
3660 && peer_sort (peer) != BGP_PEER_INTERNAL)
3661 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3662
3663 if (bgp->as == as)
3664 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3665
3666 if (peer_group_active (peer))
3667 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3668
Andrew Certain9d3f9702012-11-07 23:50:07 +00003669 if (peer->as == as)
3670 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3671
paul718e3742002-12-13 20:15:29 +00003672 if (peer->change_local_as == as &&
3673 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003674 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3675 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3676 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003677 return 0;
3678
3679 peer->change_local_as = as;
3680 if (no_prepend)
3681 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3682 else
3683 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3684
Andrew Certain9d3f9702012-11-07 23:50:07 +00003685 if (replace_as)
3686 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3687 else
3688 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3689
paul718e3742002-12-13 20:15:29 +00003690 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3691 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003692 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003693 {
3694 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3695 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3696 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3697 }
paul718e3742002-12-13 20:15:29 +00003698 else
3699 BGP_EVENT_ADD (peer, BGP_Stop);
3700
3701 return 0;
3702 }
3703
3704 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003705 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003706 {
3707 peer->change_local_as = as;
3708 if (no_prepend)
3709 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3710 else
3711 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3712
Andrew Certain9d3f9702012-11-07 23:50:07 +00003713 if (replace_as)
3714 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3715 else
3716 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3717
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003718 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003719 {
3720 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3721 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3722 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3723 }
paul718e3742002-12-13 20:15:29 +00003724 else
3725 BGP_EVENT_ADD (peer, BGP_Stop);
3726 }
3727
3728 return 0;
3729}
3730
3731int
3732peer_local_as_unset (struct peer *peer)
3733{
3734 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003735 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003736
3737 if (peer_group_active (peer))
3738 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3739
3740 if (! peer->change_local_as)
3741 return 0;
3742
3743 peer->change_local_as = 0;
3744 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003745 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003746
3747 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3748 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003749 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003750 {
3751 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3752 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3753 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3754 }
paul718e3742002-12-13 20:15:29 +00003755 else
3756 BGP_EVENT_ADD (peer, BGP_Stop);
3757
3758 return 0;
3759 }
3760
3761 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003762 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003763 {
3764 peer->change_local_as = 0;
3765 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003766 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003767
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003768 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003769 {
3770 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3771 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3772 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3773 }
paul718e3742002-12-13 20:15:29 +00003774 else
3775 BGP_EVENT_ADD (peer, BGP_Stop);
3776 }
3777 return 0;
3778}
David Lamparter6b0655a2014-06-04 06:53:35 +02003779
Paul Jakma0df7c912008-07-21 21:02:49 +00003780/* Set password for authenticating with the peer. */
3781int
3782peer_password_set (struct peer *peer, const char *password)
3783{
3784 struct listnode *nn, *nnode;
3785 int len = password ? strlen(password) : 0;
3786 int ret = BGP_SUCCESS;
3787
3788 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3789 return BGP_ERR_INVALID_VALUE;
3790
3791 if (peer->password && strcmp (peer->password, password) == 0
3792 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3793 return 0;
3794
3795 if (peer->password)
3796 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3797
3798 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3799
3800 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3801 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003802 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3803 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
Paul Jakma0df7c912008-07-21 21:02:49 +00003804 else
3805 BGP_EVENT_ADD (peer, BGP_Stop);
3806
3807 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3808 }
3809
3810 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3811 {
3812 if (peer->password && strcmp (peer->password, password) == 0)
3813 continue;
3814
3815 if (peer->password)
3816 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3817
3818 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3819
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003820 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003821 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3822 else
3823 BGP_EVENT_ADD (peer, BGP_Stop);
3824
3825 if (bgp_md5_set (peer) < 0)
3826 ret = BGP_ERR_TCPSIG_FAILED;
3827 }
3828
3829 return ret;
3830}
3831
3832int
3833peer_password_unset (struct peer *peer)
3834{
3835 struct listnode *nn, *nnode;
3836
3837 if (!peer->password
3838 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3839 return 0;
3840
3841 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3842 {
3843 if (peer_group_active (peer)
3844 && peer->group->conf->password
3845 && strcmp (peer->group->conf->password, peer->password) == 0)
3846 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3847
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003848 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003849 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3850 else
3851 BGP_EVENT_ADD (peer, BGP_Stop);
3852
3853 if (peer->password)
3854 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3855
3856 peer->password = NULL;
3857
3858 bgp_md5_set (peer);
3859
3860 return 0;
3861 }
3862
3863 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3864 peer->password = NULL;
3865
3866 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3867 {
3868 if (!peer->password)
3869 continue;
3870
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003871 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003872 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3873 else
3874 BGP_EVENT_ADD (peer, BGP_Stop);
3875
3876 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3877 peer->password = NULL;
3878
3879 bgp_md5_set (peer);
3880 }
3881
3882 return 0;
3883}
David Lamparter6b0655a2014-06-04 06:53:35 +02003884
paul718e3742002-12-13 20:15:29 +00003885/* Set distribute list to the peer. */
3886int
3887peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003888 const char *name)
paul718e3742002-12-13 20:15:29 +00003889{
3890 struct bgp_filter *filter;
3891 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003892 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003893
3894 if (! peer->afc[afi][safi])
3895 return BGP_ERR_PEER_INACTIVE;
3896
3897 if (direct != FILTER_IN && direct != FILTER_OUT)
3898 return BGP_ERR_INVALID_VALUE;
3899
3900 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3901 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3902
3903 filter = &peer->filter[afi][safi];
3904
3905 if (filter->plist[direct].name)
3906 return BGP_ERR_PEER_FILTER_CONFLICT;
3907
3908 if (filter->dlist[direct].name)
3909 free (filter->dlist[direct].name);
3910 filter->dlist[direct].name = strdup (name);
3911 filter->dlist[direct].alist = access_list_lookup (afi, name);
3912
3913 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3914 return 0;
3915
3916 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003917 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003918 {
3919 filter = &peer->filter[afi][safi];
3920
3921 if (! peer->af_group[afi][safi])
3922 continue;
3923
3924 if (filter->dlist[direct].name)
3925 free (filter->dlist[direct].name);
3926 filter->dlist[direct].name = strdup (name);
3927 filter->dlist[direct].alist = access_list_lookup (afi, name);
3928 }
3929
3930 return 0;
3931}
3932
3933int
3934peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3935{
3936 struct bgp_filter *filter;
3937 struct bgp_filter *gfilter;
3938 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003939 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003940
3941 if (! peer->afc[afi][safi])
3942 return BGP_ERR_PEER_INACTIVE;
3943
3944 if (direct != FILTER_IN && direct != FILTER_OUT)
3945 return BGP_ERR_INVALID_VALUE;
3946
3947 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3948 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3949
3950 filter = &peer->filter[afi][safi];
3951
3952 /* apply peer-group filter */
3953 if (peer->af_group[afi][safi])
3954 {
3955 gfilter = &peer->group->conf->filter[afi][safi];
3956
3957 if (gfilter->dlist[direct].name)
3958 {
3959 if (filter->dlist[direct].name)
3960 free (filter->dlist[direct].name);
3961 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3962 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3963 return 0;
3964 }
3965 }
3966
3967 if (filter->dlist[direct].name)
3968 free (filter->dlist[direct].name);
3969 filter->dlist[direct].name = NULL;
3970 filter->dlist[direct].alist = NULL;
3971
3972 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3973 return 0;
3974
3975 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003976 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003977 {
3978 filter = &peer->filter[afi][safi];
3979
3980 if (! peer->af_group[afi][safi])
3981 continue;
3982
3983 if (filter->dlist[direct].name)
3984 free (filter->dlist[direct].name);
3985 filter->dlist[direct].name = NULL;
3986 filter->dlist[direct].alist = NULL;
3987 }
3988
3989 return 0;
3990}
3991
3992/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003993static void
paul718e3742002-12-13 20:15:29 +00003994peer_distribute_update (struct access_list *access)
3995{
3996 afi_t afi;
3997 safi_t safi;
3998 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003999 struct listnode *mnode, *mnnode;
4000 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004001 struct bgp *bgp;
4002 struct peer *peer;
4003 struct peer_group *group;
4004 struct bgp_filter *filter;
4005
paul1eb8ef22005-04-07 07:30:20 +00004006 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004007 {
paul1eb8ef22005-04-07 07:30:20 +00004008 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004009 {
4010 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4011 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4012 {
4013 filter = &peer->filter[afi][safi];
4014
4015 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4016 {
4017 if (filter->dlist[direct].name)
4018 filter->dlist[direct].alist =
4019 access_list_lookup (afi, filter->dlist[direct].name);
4020 else
4021 filter->dlist[direct].alist = NULL;
4022 }
4023 }
4024 }
paul1eb8ef22005-04-07 07:30:20 +00004025 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004026 {
4027 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4028 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4029 {
4030 filter = &group->conf->filter[afi][safi];
4031
4032 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4033 {
4034 if (filter->dlist[direct].name)
4035 filter->dlist[direct].alist =
4036 access_list_lookup (afi, filter->dlist[direct].name);
4037 else
4038 filter->dlist[direct].alist = NULL;
4039 }
4040 }
4041 }
4042 }
4043}
David Lamparter6b0655a2014-06-04 06:53:35 +02004044
paul718e3742002-12-13 20:15:29 +00004045/* Set prefix list to the peer. */
4046int
4047peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004048 const char *name)
paul718e3742002-12-13 20:15:29 +00004049{
4050 struct bgp_filter *filter;
4051 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004052 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004053
4054 if (! peer->afc[afi][safi])
4055 return BGP_ERR_PEER_INACTIVE;
4056
4057 if (direct != FILTER_IN && direct != FILTER_OUT)
4058 return BGP_ERR_INVALID_VALUE;
4059
4060 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4061 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4062
4063 filter = &peer->filter[afi][safi];
4064
4065 if (filter->dlist[direct].name)
4066 return BGP_ERR_PEER_FILTER_CONFLICT;
4067
4068 if (filter->plist[direct].name)
4069 free (filter->plist[direct].name);
4070 filter->plist[direct].name = strdup (name);
4071 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4072
4073 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4074 return 0;
4075
4076 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004077 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004078 {
4079 filter = &peer->filter[afi][safi];
4080
4081 if (! peer->af_group[afi][safi])
4082 continue;
4083
4084 if (filter->plist[direct].name)
4085 free (filter->plist[direct].name);
4086 filter->plist[direct].name = strdup (name);
4087 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4088 }
4089 return 0;
4090}
4091
4092int
4093peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4094{
4095 struct bgp_filter *filter;
4096 struct bgp_filter *gfilter;
4097 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004098 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004099
4100 if (! peer->afc[afi][safi])
4101 return BGP_ERR_PEER_INACTIVE;
4102
4103 if (direct != FILTER_IN && direct != FILTER_OUT)
4104 return BGP_ERR_INVALID_VALUE;
4105
4106 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4107 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4108
4109 filter = &peer->filter[afi][safi];
4110
4111 /* apply peer-group filter */
4112 if (peer->af_group[afi][safi])
4113 {
4114 gfilter = &peer->group->conf->filter[afi][safi];
4115
4116 if (gfilter->plist[direct].name)
4117 {
4118 if (filter->plist[direct].name)
4119 free (filter->plist[direct].name);
4120 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
4121 filter->plist[direct].plist = gfilter->plist[direct].plist;
4122 return 0;
4123 }
4124 }
4125
4126 if (filter->plist[direct].name)
4127 free (filter->plist[direct].name);
4128 filter->plist[direct].name = NULL;
4129 filter->plist[direct].plist = NULL;
4130
4131 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4132 return 0;
4133
4134 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004135 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004136 {
4137 filter = &peer->filter[afi][safi];
4138
4139 if (! peer->af_group[afi][safi])
4140 continue;
4141
4142 if (filter->plist[direct].name)
4143 free (filter->plist[direct].name);
4144 filter->plist[direct].name = NULL;
4145 filter->plist[direct].plist = NULL;
4146 }
4147
4148 return 0;
4149}
4150
4151/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00004152static void
paul718e3742002-12-13 20:15:29 +00004153peer_prefix_list_update (struct prefix_list *plist)
4154{
paul1eb8ef22005-04-07 07:30:20 +00004155 struct listnode *mnode, *mnnode;
4156 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004157 struct bgp *bgp;
4158 struct peer *peer;
4159 struct peer_group *group;
4160 struct bgp_filter *filter;
4161 afi_t afi;
4162 safi_t safi;
4163 int direct;
4164
paul1eb8ef22005-04-07 07:30:20 +00004165 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004166 {
paul1eb8ef22005-04-07 07:30:20 +00004167 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004168 {
4169 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4170 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4171 {
4172 filter = &peer->filter[afi][safi];
4173
4174 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4175 {
4176 if (filter->plist[direct].name)
4177 filter->plist[direct].plist =
4178 prefix_list_lookup (afi, filter->plist[direct].name);
4179 else
4180 filter->plist[direct].plist = NULL;
4181 }
4182 }
4183 }
paul1eb8ef22005-04-07 07:30:20 +00004184 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004185 {
4186 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4187 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4188 {
4189 filter = &group->conf->filter[afi][safi];
4190
4191 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4192 {
4193 if (filter->plist[direct].name)
4194 filter->plist[direct].plist =
4195 prefix_list_lookup (afi, filter->plist[direct].name);
4196 else
4197 filter->plist[direct].plist = NULL;
4198 }
4199 }
4200 }
4201 }
4202}
David Lamparter6b0655a2014-06-04 06:53:35 +02004203
paul718e3742002-12-13 20:15:29 +00004204int
4205peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004206 const char *name)
paul718e3742002-12-13 20:15:29 +00004207{
4208 struct bgp_filter *filter;
4209 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004210 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004211
4212 if (! peer->afc[afi][safi])
4213 return BGP_ERR_PEER_INACTIVE;
4214
4215 if (direct != FILTER_IN && direct != FILTER_OUT)
4216 return BGP_ERR_INVALID_VALUE;
4217
4218 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4219 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4220
4221 filter = &peer->filter[afi][safi];
4222
4223 if (filter->aslist[direct].name)
4224 free (filter->aslist[direct].name);
4225 filter->aslist[direct].name = strdup (name);
4226 filter->aslist[direct].aslist = as_list_lookup (name);
4227
4228 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4229 return 0;
4230
4231 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004232 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004233 {
4234 filter = &peer->filter[afi][safi];
4235
4236 if (! peer->af_group[afi][safi])
4237 continue;
4238
4239 if (filter->aslist[direct].name)
4240 free (filter->aslist[direct].name);
4241 filter->aslist[direct].name = strdup (name);
4242 filter->aslist[direct].aslist = as_list_lookup (name);
4243 }
4244 return 0;
4245}
4246
4247int
4248peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4249{
4250 struct bgp_filter *filter;
4251 struct bgp_filter *gfilter;
4252 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004253 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004254
4255 if (! peer->afc[afi][safi])
4256 return BGP_ERR_PEER_INACTIVE;
4257
hassob5f29602005-05-25 21:00:28 +00004258 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004259 return BGP_ERR_INVALID_VALUE;
4260
hassob5f29602005-05-25 21:00:28 +00004261 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004262 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4263
4264 filter = &peer->filter[afi][safi];
4265
4266 /* apply peer-group filter */
4267 if (peer->af_group[afi][safi])
4268 {
4269 gfilter = &peer->group->conf->filter[afi][safi];
4270
4271 if (gfilter->aslist[direct].name)
4272 {
4273 if (filter->aslist[direct].name)
4274 free (filter->aslist[direct].name);
4275 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4276 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4277 return 0;
4278 }
4279 }
4280
4281 if (filter->aslist[direct].name)
4282 free (filter->aslist[direct].name);
4283 filter->aslist[direct].name = NULL;
4284 filter->aslist[direct].aslist = NULL;
4285
4286 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4287 return 0;
4288
4289 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004290 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004291 {
4292 filter = &peer->filter[afi][safi];
4293
4294 if (! peer->af_group[afi][safi])
4295 continue;
4296
4297 if (filter->aslist[direct].name)
4298 free (filter->aslist[direct].name);
4299 filter->aslist[direct].name = NULL;
4300 filter->aslist[direct].aslist = NULL;
4301 }
4302
4303 return 0;
4304}
4305
paul94f2b392005-06-28 12:44:16 +00004306static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004307peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004308{
4309 afi_t afi;
4310 safi_t safi;
4311 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004312 struct listnode *mnode, *mnnode;
4313 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004314 struct bgp *bgp;
4315 struct peer *peer;
4316 struct peer_group *group;
4317 struct bgp_filter *filter;
4318
paul1eb8ef22005-04-07 07:30:20 +00004319 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004320 {
paul1eb8ef22005-04-07 07:30:20 +00004321 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004322 {
4323 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4324 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4325 {
4326 filter = &peer->filter[afi][safi];
4327
4328 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4329 {
4330 if (filter->aslist[direct].name)
4331 filter->aslist[direct].aslist =
4332 as_list_lookup (filter->aslist[direct].name);
4333 else
4334 filter->aslist[direct].aslist = NULL;
4335 }
4336 }
4337 }
paul1eb8ef22005-04-07 07:30:20 +00004338 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004339 {
4340 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4341 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4342 {
4343 filter = &group->conf->filter[afi][safi];
4344
4345 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4346 {
4347 if (filter->aslist[direct].name)
4348 filter->aslist[direct].aslist =
4349 as_list_lookup (filter->aslist[direct].name);
4350 else
4351 filter->aslist[direct].aslist = NULL;
4352 }
4353 }
4354 }
4355 }
4356}
David Lamparter6b0655a2014-06-04 06:53:35 +02004357
paul718e3742002-12-13 20:15:29 +00004358/* Set route-map to the peer. */
4359int
4360peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004361 const char *name)
paul718e3742002-12-13 20:15:29 +00004362{
4363 struct bgp_filter *filter;
4364 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004365 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004366
4367 if (! peer->afc[afi][safi])
4368 return BGP_ERR_PEER_INACTIVE;
4369
paulfee0f4c2004-09-13 05:12:46 +00004370 if (direct != RMAP_IN && direct != RMAP_OUT &&
4371 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004372 return BGP_ERR_INVALID_VALUE;
4373
paulfee0f4c2004-09-13 05:12:46 +00004374 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4375 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004376 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4377
4378 filter = &peer->filter[afi][safi];
4379
4380 if (filter->map[direct].name)
4381 free (filter->map[direct].name);
4382
4383 filter->map[direct].name = strdup (name);
4384 filter->map[direct].map = route_map_lookup_by_name (name);
4385
4386 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4387 return 0;
4388
4389 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004390 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004391 {
4392 filter = &peer->filter[afi][safi];
4393
4394 if (! peer->af_group[afi][safi])
4395 continue;
4396
4397 if (filter->map[direct].name)
4398 free (filter->map[direct].name);
4399 filter->map[direct].name = strdup (name);
4400 filter->map[direct].map = route_map_lookup_by_name (name);
4401 }
4402 return 0;
4403}
4404
4405/* Unset route-map from the peer. */
4406int
4407peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4408{
4409 struct bgp_filter *filter;
4410 struct bgp_filter *gfilter;
4411 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004412 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004413
4414 if (! peer->afc[afi][safi])
4415 return BGP_ERR_PEER_INACTIVE;
4416
hassob5f29602005-05-25 21:00:28 +00004417 if (direct != RMAP_IN && direct != RMAP_OUT &&
4418 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004419 return BGP_ERR_INVALID_VALUE;
4420
hassob5f29602005-05-25 21:00:28 +00004421 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4422 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004423 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4424
4425 filter = &peer->filter[afi][safi];
4426
4427 /* apply peer-group filter */
4428 if (peer->af_group[afi][safi])
4429 {
4430 gfilter = &peer->group->conf->filter[afi][safi];
4431
4432 if (gfilter->map[direct].name)
4433 {
4434 if (filter->map[direct].name)
4435 free (filter->map[direct].name);
4436 filter->map[direct].name = strdup (gfilter->map[direct].name);
4437 filter->map[direct].map = gfilter->map[direct].map;
4438 return 0;
4439 }
4440 }
4441
4442 if (filter->map[direct].name)
4443 free (filter->map[direct].name);
4444 filter->map[direct].name = NULL;
4445 filter->map[direct].map = NULL;
4446
4447 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4448 return 0;
4449
4450 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004451 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004452 {
4453 filter = &peer->filter[afi][safi];
4454
4455 if (! peer->af_group[afi][safi])
4456 continue;
4457
4458 if (filter->map[direct].name)
4459 free (filter->map[direct].name);
4460 filter->map[direct].name = NULL;
4461 filter->map[direct].map = NULL;
4462 }
4463 return 0;
4464}
David Lamparter6b0655a2014-06-04 06:53:35 +02004465
paul718e3742002-12-13 20:15:29 +00004466/* Set unsuppress-map to the peer. */
4467int
paulfd79ac92004-10-13 05:06:08 +00004468peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4469 const char *name)
paul718e3742002-12-13 20:15:29 +00004470{
4471 struct bgp_filter *filter;
4472 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004473 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004474
4475 if (! peer->afc[afi][safi])
4476 return BGP_ERR_PEER_INACTIVE;
4477
4478 if (peer_is_group_member (peer, afi, safi))
4479 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4480
4481 filter = &peer->filter[afi][safi];
4482
4483 if (filter->usmap.name)
4484 free (filter->usmap.name);
4485
4486 filter->usmap.name = strdup (name);
4487 filter->usmap.map = route_map_lookup_by_name (name);
4488
4489 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4490 return 0;
4491
4492 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004493 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004494 {
4495 filter = &peer->filter[afi][safi];
4496
4497 if (! peer->af_group[afi][safi])
4498 continue;
4499
4500 if (filter->usmap.name)
4501 free (filter->usmap.name);
4502 filter->usmap.name = strdup (name);
4503 filter->usmap.map = route_map_lookup_by_name (name);
4504 }
4505 return 0;
4506}
4507
4508/* Unset route-map from the peer. */
4509int
4510peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4511{
4512 struct bgp_filter *filter;
4513 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004514 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004515
4516 if (! peer->afc[afi][safi])
4517 return BGP_ERR_PEER_INACTIVE;
4518
4519 if (peer_is_group_member (peer, afi, safi))
4520 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4521
4522 filter = &peer->filter[afi][safi];
4523
4524 if (filter->usmap.name)
4525 free (filter->usmap.name);
4526 filter->usmap.name = NULL;
4527 filter->usmap.map = NULL;
4528
4529 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4530 return 0;
4531
4532 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004533 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004534 {
4535 filter = &peer->filter[afi][safi];
4536
4537 if (! peer->af_group[afi][safi])
4538 continue;
4539
4540 if (filter->usmap.name)
4541 free (filter->usmap.name);
4542 filter->usmap.name = NULL;
4543 filter->usmap.map = NULL;
4544 }
4545 return 0;
4546}
David Lamparter6b0655a2014-06-04 06:53:35 +02004547
paul718e3742002-12-13 20:15:29 +00004548int
4549peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004550 u_int32_t max, u_char threshold,
4551 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004552{
4553 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004554 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004555
4556 if (! peer->afc[afi][safi])
4557 return BGP_ERR_PEER_INACTIVE;
4558
4559 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4560 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004561 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004562 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004563 if (warning)
4564 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4565 else
4566 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4567
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07004568 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
paul718e3742002-12-13 20:15:29 +00004569 {
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07004570 group = peer->group;
4571 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4572 {
4573 if (! peer->af_group[afi][safi])
4574 continue;
paul718e3742002-12-13 20:15:29 +00004575
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07004576 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4577 peer->pmax[afi][safi] = max;
4578 peer->pmax_threshold[afi][safi] = threshold;
4579 peer->pmax_restart[afi][safi] = restart;
4580 if (warning)
4581 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4582 else
4583 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4584
4585 if ((peer->status == Established) && (peer->afc[afi][safi]))
4586 bgp_maximum_prefix_overflow (peer, afi, safi, 1);
4587 }
paul718e3742002-12-13 20:15:29 +00004588 }
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07004589 else
4590 {
4591 if ((peer->status == Established) && (peer->afc[afi][safi]))
4592 bgp_maximum_prefix_overflow (peer, afi, safi, 1);
4593 }
4594
paul718e3742002-12-13 20:15:29 +00004595 return 0;
4596}
4597
4598int
4599peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4600{
4601 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004602 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004603
4604 if (! peer->afc[afi][safi])
4605 return BGP_ERR_PEER_INACTIVE;
4606
4607 /* apply peer-group config */
4608 if (peer->af_group[afi][safi])
4609 {
4610 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4611 PEER_FLAG_MAX_PREFIX))
4612 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4613 else
4614 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4615
4616 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4617 PEER_FLAG_MAX_PREFIX_WARNING))
4618 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4619 else
4620 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4621
4622 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004623 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004624 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004625 return 0;
4626 }
4627
4628 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4629 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4630 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004631 peer->pmax_threshold[afi][safi] = 0;
4632 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004633
4634 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4635 return 0;
4636
4637 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004638 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004639 {
4640 if (! peer->af_group[afi][safi])
4641 continue;
4642
4643 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4644 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4645 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004646 peer->pmax_threshold[afi][safi] = 0;
4647 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004648 }
4649 return 0;
4650}
David Lamparter5f9adb52014-05-19 23:15:02 +02004651
4652static int is_ebgp_multihop_configured (struct peer *peer)
4653{
4654 struct peer_group *group;
4655 struct listnode *node, *nnode;
4656 struct peer *peer1;
4657
4658 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4659 {
4660 group = peer->group;
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004661 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4662 (group->conf->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004663 return 1;
4664
4665 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4666 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004667 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
4668 (peer1->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004669 return 1;
4670 }
4671 }
4672 else
4673 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004674 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4675 (peer->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004676 return 1;
4677 }
4678 return 0;
4679}
4680
Nick Hilliardfa411a22011-03-23 15:33:17 +00004681/* Set # of hops between us and BGP peer. */
4682int
4683peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4684{
4685 struct peer_group *group;
4686 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004687 int ret;
4688
4689 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4690
Nick Hilliardfa411a22011-03-23 15:33:17 +00004691 /* We cannot configure ttl-security hops when ebgp-multihop is already
4692 set. For non peer-groups, the check is simple. For peer-groups, it's
4693 slightly messy, because we need to check both the peer-group structure
4694 and all peer-group members for any trace of ebgp-multihop configuration
4695 before actually applying the ttl-security rules. Cisco really made a
4696 mess of this configuration parameter, and OpenBGPD got it right.
4697 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004698
David Lamparter5f9adb52014-05-19 23:15:02 +02004699 if (peer->gtsm_hops == 0)
4700 {
4701 if (is_ebgp_multihop_configured (peer))
4702 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004703
David Lamparter5f9adb52014-05-19 23:15:02 +02004704 /* specify MAXTTL on outgoing packets */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004705 /* Routine handles iBGP peers correctly */
David Lamparter5f9adb52014-05-19 23:15:02 +02004706 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4707 if (ret != 0)
4708 return ret;
4709 }
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004710
Nick Hilliardfa411a22011-03-23 15:33:17 +00004711 peer->gtsm_hops = gtsm_hops;
4712
Nick Hilliardfa411a22011-03-23 15:33:17 +00004713 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4714 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004715 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004716 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4717 }
4718 else
4719 {
4720 group = peer->group;
4721 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4722 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004723 peer->gtsm_hops = group->conf->gtsm_hops;
4724
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004725 /* Change setting of existing peer
4726 * established then change value (may break connectivity)
4727 * not established yet (teardown session and restart)
4728 * no session then do nothing (will get handled by next connection)
4729 */
4730 if (peer->status == Established)
4731 {
4732 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4733 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4734 MAXTTL + 1 - peer->gtsm_hops);
4735 }
4736 else if (peer->status < Established)
4737 {
4738 if (BGP_DEBUG (events, EVENTS))
4739 zlog_debug ("%s Min-ttl changed", peer->host);
4740 BGP_EVENT_ADD (peer, BGP_Stop);
4741 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004742 }
4743 }
4744
4745 return 0;
4746}
4747
4748int
4749peer_ttl_security_hops_unset (struct peer *peer)
4750{
4751 struct peer_group *group;
4752 struct listnode *node, *nnode;
4753 struct peer *opeer;
4754
4755 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4756
Nick Hilliardfa411a22011-03-23 15:33:17 +00004757 /* if a peer-group member, then reset to peer-group default rather than 0 */
4758 if (peer_group_active (peer))
4759 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4760 else
4761 peer->gtsm_hops = 0;
4762
4763 opeer = peer;
4764 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4765 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004766 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004767 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4768 }
4769 else
4770 {
4771 group = peer->group;
4772 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4773 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004774 peer->gtsm_hops = 0;
4775
4776 if (peer->fd >= 0)
4777 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4778 }
4779 }
4780
4781 return peer_ebgp_multihop_unset (opeer);
4782}
David Lamparter6b0655a2014-06-04 06:53:35 +02004783
paul718e3742002-12-13 20:15:29 +00004784int
4785peer_clear (struct peer *peer)
4786{
4787 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4788 {
hasso0a486e52005-02-01 20:57:17 +00004789 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4790 {
4791 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4792 if (peer->t_pmax_restart)
4793 {
4794 BGP_TIMER_OFF (peer->t_pmax_restart);
4795 if (BGP_DEBUG (events, EVENTS))
4796 zlog_debug ("%s Maximum-prefix restart timer canceled",
4797 peer->host);
4798 }
4799 BGP_EVENT_ADD (peer, BGP_Start);
4800 return 0;
4801 }
4802
paul718e3742002-12-13 20:15:29 +00004803 peer->v_start = BGP_INIT_START_TIMER;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00004804 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00004805 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4806 BGP_NOTIFY_CEASE_ADMIN_RESET);
4807 else
4808 BGP_EVENT_ADD (peer, BGP_Stop);
4809 }
4810 return 0;
4811}
4812
4813int
4814peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4815 enum bgp_clear_type stype)
4816{
4817 if (peer->status != Established)
4818 return 0;
4819
4820 if (! peer->afc[afi][safi])
4821 return BGP_ERR_AF_UNCONFIGURED;
4822
Timo Teräs5a2a1ec2015-10-22 11:35:18 +03004823 peer->rtt = sockopt_tcp_rtt (peer->fd);
4824
paulfee0f4c2004-09-13 05:12:46 +00004825 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4826 {
4827 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4828 return 0;
4829 bgp_check_local_routes_rsclient (peer, afi, safi);
4830 bgp_soft_reconfig_rsclient (peer, afi, safi);
4831 }
4832
paul718e3742002-12-13 20:15:29 +00004833 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4834 bgp_announce_route (peer, afi, safi);
4835
4836 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4837 {
4838 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4839 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4840 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4841 {
4842 struct bgp_filter *filter = &peer->filter[afi][safi];
4843 u_char prefix_type;
4844
4845 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4846 prefix_type = ORF_TYPE_PREFIX;
4847 else
4848 prefix_type = ORF_TYPE_PREFIX_OLD;
4849
4850 if (filter->plist[FILTER_IN].plist)
4851 {
4852 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4853 bgp_route_refresh_send (peer, afi, safi,
4854 prefix_type, REFRESH_DEFER, 1);
4855 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4856 REFRESH_IMMEDIATE, 0);
4857 }
4858 else
4859 {
4860 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4861 bgp_route_refresh_send (peer, afi, safi,
4862 prefix_type, REFRESH_IMMEDIATE, 1);
4863 else
4864 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4865 }
4866 return 0;
4867 }
4868 }
4869
4870 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4871 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4872 {
4873 /* If neighbor has soft reconfiguration inbound flag.
4874 Use Adj-RIB-In database. */
4875 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4876 bgp_soft_reconfig_in (peer, afi, safi);
4877 else
4878 {
4879 /* If neighbor has route refresh capability, send route refresh
4880 message to the peer. */
4881 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4882 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4883 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4884 else
4885 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4886 }
4887 }
4888 return 0;
4889}
David Lamparter6b0655a2014-06-04 06:53:35 +02004890
paulfd79ac92004-10-13 05:06:08 +00004891/* Display peer uptime.*/
4892/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004893char *
4894peer_uptime (time_t uptime2, char *buf, size_t len)
4895{
4896 time_t uptime1;
4897 struct tm *tm;
4898
4899 /* Check buffer length. */
4900 if (len < BGP_UPTIME_LEN)
4901 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004902 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004903 /* XXX: should return status instead of buf... */
4904 snprintf (buf, len, "<error> ");
4905 return buf;
paul718e3742002-12-13 20:15:29 +00004906 }
4907
4908 /* If there is no connection has been done before print `never'. */
4909 if (uptime2 == 0)
4910 {
4911 snprintf (buf, len, "never ");
4912 return buf;
4913 }
4914
4915 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004916 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004917 uptime1 -= uptime2;
4918 tm = gmtime (&uptime1);
Paul Jakma84c38402015-05-26 15:19:38 +01004919
paul718e3742002-12-13 20:15:29 +00004920 /* Making formatted timer strings. */
4921#define ONE_DAY_SECOND 60*60*24
Paul Jakma84c38402015-05-26 15:19:38 +01004922#define ONE_WEEK_SECOND ONE_DAY_SECOND*7
4923#define ONE_YEAR_SECOND ONE_DAY_SECOND*365
paul718e3742002-12-13 20:15:29 +00004924
4925 if (uptime1 < ONE_DAY_SECOND)
4926 snprintf (buf, len, "%02d:%02d:%02d",
4927 tm->tm_hour, tm->tm_min, tm->tm_sec);
4928 else if (uptime1 < ONE_WEEK_SECOND)
4929 snprintf (buf, len, "%dd%02dh%02dm",
4930 tm->tm_yday, tm->tm_hour, tm->tm_min);
Paul Jakma84c38402015-05-26 15:19:38 +01004931 else if (uptime1 < ONE_YEAR_SECOND)
paul718e3742002-12-13 20:15:29 +00004932 snprintf (buf, len, "%02dw%dd%02dh",
4933 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
Paul Jakma84c38402015-05-26 15:19:38 +01004934 else
4935 snprintf (buf, len, "%02dy%02dw%dd",
4936 tm->tm_year - 70, tm->tm_yday/7,
4937 tm->tm_yday - ((tm->tm_yday/7) * 7));
paul718e3742002-12-13 20:15:29 +00004938 return buf;
4939}
David Lamparter6b0655a2014-06-04 06:53:35 +02004940
paul94f2b392005-06-28 12:44:16 +00004941static void
paul718e3742002-12-13 20:15:29 +00004942bgp_config_write_filter (struct vty *vty, struct peer *peer,
4943 afi_t afi, safi_t safi)
4944{
4945 struct bgp_filter *filter;
4946 struct bgp_filter *gfilter = NULL;
4947 char *addr;
4948 int in = FILTER_IN;
4949 int out = FILTER_OUT;
4950
4951 addr = peer->host;
4952 filter = &peer->filter[afi][safi];
4953 if (peer->af_group[afi][safi])
4954 gfilter = &peer->group->conf->filter[afi][safi];
4955
4956 /* distribute-list. */
4957 if (filter->dlist[in].name)
4958 if (! gfilter || ! gfilter->dlist[in].name
4959 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4960 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4961 filter->dlist[in].name, VTY_NEWLINE);
4962 if (filter->dlist[out].name && ! gfilter)
4963 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4964 filter->dlist[out].name, VTY_NEWLINE);
4965
4966 /* prefix-list. */
4967 if (filter->plist[in].name)
4968 if (! gfilter || ! gfilter->plist[in].name
4969 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4970 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4971 filter->plist[in].name, VTY_NEWLINE);
4972 if (filter->plist[out].name && ! gfilter)
4973 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4974 filter->plist[out].name, VTY_NEWLINE);
4975
4976 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004977 if (filter->map[RMAP_IN].name)
4978 if (! gfilter || ! gfilter->map[RMAP_IN].name
4979 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004980 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004981 filter->map[RMAP_IN].name, VTY_NEWLINE);
4982 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004983 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004984 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4985 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4986 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4987 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4988 if (filter->map[RMAP_EXPORT].name)
4989 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4990 || strcmp (filter->map[RMAP_EXPORT].name,
4991 gfilter->map[RMAP_EXPORT].name) != 0)
4992 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4993 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004994
4995 /* unsuppress-map */
4996 if (filter->usmap.name && ! gfilter)
4997 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4998 filter->usmap.name, VTY_NEWLINE);
4999
5000 /* filter-list. */
5001 if (filter->aslist[in].name)
5002 if (! gfilter || ! gfilter->aslist[in].name
5003 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
5004 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
5005 filter->aslist[in].name, VTY_NEWLINE);
5006 if (filter->aslist[out].name && ! gfilter)
5007 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
5008 filter->aslist[out].name, VTY_NEWLINE);
5009}
5010
5011/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00005012static void
paul718e3742002-12-13 20:15:29 +00005013bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
5014 struct peer *peer, afi_t afi, safi_t safi)
5015{
paul718e3742002-12-13 20:15:29 +00005016 struct peer *g_peer = NULL;
5017 char buf[SU_ADDRSTRLEN];
5018 char *addr;
5019
paul718e3742002-12-13 20:15:29 +00005020 addr = peer->host;
5021 if (peer_group_active (peer))
5022 g_peer = peer->group->conf;
5023
5024 /************************************
5025 ****** Global to the neighbor ******
5026 ************************************/
5027 if (afi == AFI_IP && safi == SAFI_UNICAST)
5028 {
5029 /* remote-as. */
5030 if (! peer_group_active (peer))
5031 {
5032 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5033 vty_out (vty, " neighbor %s peer-group%s", addr,
5034 VTY_NEWLINE);
5035 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005036 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00005037 VTY_NEWLINE);
5038 }
5039 else
5040 {
5041 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005042 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00005043 VTY_NEWLINE);
5044 if (peer->af_group[AFI_IP][SAFI_UNICAST])
5045 vty_out (vty, " neighbor %s peer-group %s%s", addr,
5046 peer->group->name, VTY_NEWLINE);
5047 }
5048
5049 /* local-as. */
5050 if (peer->change_local_as)
5051 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00005052 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00005053 peer->change_local_as,
5054 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00005055 " no-prepend" : "",
5056 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
5057 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005058
5059 /* Description. */
5060 if (peer->desc)
5061 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
5062 VTY_NEWLINE);
5063
5064 /* Shutdown. */
5065 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
5066 if (! peer_group_active (peer) ||
5067 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
5068 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
5069
Paul Jakma0df7c912008-07-21 21:02:49 +00005070 /* Password. */
5071 if (peer->password)
5072 if (!peer_group_active (peer)
5073 || ! g_peer->password
5074 || strcmp (peer->password, g_peer->password) != 0)
5075 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
5076 VTY_NEWLINE);
5077
paul718e3742002-12-13 20:15:29 +00005078 /* BGP port. */
5079 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00005080 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00005081 VTY_NEWLINE);
5082
5083 /* Local interface name. */
5084 if (peer->ifname)
5085 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
5086 VTY_NEWLINE);
5087
5088 /* Passive. */
5089 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
5090 if (! peer_group_active (peer) ||
5091 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
5092 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
5093
5094 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00005095 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00005096 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00005097 if (! peer_group_active (peer) ||
5098 g_peer->ttl != peer->ttl)
5099 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
5100 VTY_NEWLINE);
5101
Nick Hilliardfa411a22011-03-23 15:33:17 +00005102 /* ttl-security hops */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00005103 if (peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00005104 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00005105 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00005106 peer->gtsm_hops, VTY_NEWLINE);
5107
hasso6ffd2072005-02-02 14:50:11 +00005108 /* disable-connected-check. */
5109 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00005110 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00005111 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
5112 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005113
5114 /* Update-source. */
5115 if (peer->update_if)
5116 if (! peer_group_active (peer) || ! g_peer->update_if
5117 || strcmp (g_peer->update_if, peer->update_if) != 0)
5118 vty_out (vty, " neighbor %s update-source %s%s", addr,
5119 peer->update_if, VTY_NEWLINE);
5120 if (peer->update_source)
5121 if (! peer_group_active (peer) || ! g_peer->update_source
5122 || sockunion_cmp (g_peer->update_source,
5123 peer->update_source) != 0)
5124 vty_out (vty, " neighbor %s update-source %s%s", addr,
5125 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
5126 VTY_NEWLINE);
5127
paul718e3742002-12-13 20:15:29 +00005128 /* advertisement-interval */
Daniel Walton0d7435f2015-10-22 11:35:20 +03005129 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV) &&
5130 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00005131 vty_out (vty, " neighbor %s advertisement-interval %d%s",
5132 addr, peer->v_routeadv, VTY_NEWLINE);
5133
5134 /* timers. */
5135 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
5136 && ! peer_group_active (peer))
5137 vty_out (vty, " neighbor %s timers %d %d%s", addr,
5138 peer->keepalive, peer->holdtime, VTY_NEWLINE);
5139
Daniel Walton0d7435f2015-10-22 11:35:20 +03005140 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT) &&
5141 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00005142 vty_out (vty, " neighbor %s timers connect %d%s", addr,
5143 peer->connect, VTY_NEWLINE);
5144
5145 /* Default weight. */
5146 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
5147 if (! peer_group_active (peer) ||
5148 g_peer->weight != peer->weight)
5149 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
5150 VTY_NEWLINE);
5151
paul718e3742002-12-13 20:15:29 +00005152 /* Dynamic capability. */
5153 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5154 if (! peer_group_active (peer) ||
5155 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5156 vty_out (vty, " neighbor %s capability dynamic%s", addr,
5157 VTY_NEWLINE);
5158
5159 /* dont capability negotiation. */
5160 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
5161 if (! peer_group_active (peer) ||
5162 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
5163 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
5164 VTY_NEWLINE);
5165
5166 /* override capability negotiation. */
5167 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5168 if (! peer_group_active (peer) ||
5169 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5170 vty_out (vty, " neighbor %s override-capability%s", addr,
5171 VTY_NEWLINE);
5172
5173 /* strict capability negotiation. */
5174 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5175 if (! peer_group_active (peer) ||
5176 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5177 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
5178 VTY_NEWLINE);
5179
Christian Franke15c71342012-11-19 11:17:31 +00005180 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
paul718e3742002-12-13 20:15:29 +00005181 {
5182 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5183 {
5184 if (peer->afc[AFI_IP][SAFI_UNICAST])
5185 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5186 }
5187 else
5188 {
5189 if (! peer->afc[AFI_IP][SAFI_UNICAST])
5190 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
5191 }
5192 }
5193 }
5194
5195
5196 /************************************
5197 ****** Per AF to the neighbor ******
5198 ************************************/
5199
5200 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
5201 {
5202 if (peer->af_group[afi][safi])
5203 vty_out (vty, " neighbor %s peer-group %s%s", addr,
5204 peer->group->name, VTY_NEWLINE);
5205 else
5206 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5207 }
5208
5209 /* ORF capability. */
5210 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5211 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5212 if (! peer->af_group[afi][safi])
5213 {
5214 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
5215
5216 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5217 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5218 vty_out (vty, " both");
5219 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
5220 vty_out (vty, " send");
5221 else
5222 vty_out (vty, " receive");
5223 vty_out (vty, "%s", VTY_NEWLINE);
5224 }
5225
5226 /* Route reflector client. */
5227 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
5228 && ! peer->af_group[afi][safi])
5229 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
5230 VTY_NEWLINE);
5231
5232 /* Nexthop self. */
5233 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
5234 && ! peer->af_group[afi][safi])
Timo Teräs9e7a53c2014-04-24 10:22:37 +03005235 vty_out (vty, " neighbor %s next-hop-self%s%s", addr,
5236 peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ?
5237 " all" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005238
5239 /* Remove private AS. */
5240 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
5241 && ! peer->af_group[afi][safi])
5242 vty_out (vty, " neighbor %s remove-private-AS%s",
5243 addr, VTY_NEWLINE);
5244
5245 /* send-community print. */
5246 if (! peer->af_group[afi][safi])
5247 {
5248 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5249 {
5250 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5251 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5252 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
5253 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5254 vty_out (vty, " neighbor %s send-community extended%s",
5255 addr, VTY_NEWLINE);
5256 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5257 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
5258 }
5259 else
5260 {
5261 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5262 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5263 vty_out (vty, " no neighbor %s send-community both%s",
5264 addr, VTY_NEWLINE);
5265 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5266 vty_out (vty, " no neighbor %s send-community extended%s",
5267 addr, VTY_NEWLINE);
5268 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5269 vty_out (vty, " no neighbor %s send-community%s",
5270 addr, VTY_NEWLINE);
5271 }
5272 }
5273
5274 /* Default information */
5275 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5276 && ! peer->af_group[afi][safi])
5277 {
5278 vty_out (vty, " neighbor %s default-originate", addr);
5279 if (peer->default_rmap[afi][safi].name)
5280 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5281 vty_out (vty, "%s", VTY_NEWLINE);
5282 }
5283
5284 /* Soft reconfiguration inbound. */
5285 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5286 if (! peer->af_group[afi][safi] ||
5287 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5288 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5289 VTY_NEWLINE);
5290
5291 /* maximum-prefix. */
5292 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5293 if (! peer->af_group[afi][safi]
5294 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005295 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005296 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5297 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005298 {
hasso0a486e52005-02-01 20:57:17 +00005299 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5300 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5301 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5302 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5303 vty_out (vty, " warning-only");
5304 if (peer->pmax_restart[afi][safi])
5305 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5306 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005307 }
paul718e3742002-12-13 20:15:29 +00005308
5309 /* Route server client. */
5310 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5311 && ! peer->af_group[afi][safi])
5312 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5313
Dylan Hall3cf12882011-10-27 15:28:17 +04005314 /* Nexthop-local unchanged. */
5315 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5316 && ! peer->af_group[afi][safi])
5317 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5318
paul718e3742002-12-13 20:15:29 +00005319 /* Allow AS in. */
5320 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5321 if (! peer_group_active (peer)
5322 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5323 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5324 {
5325 if (peer->allowas_in[afi][safi] == 3)
5326 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5327 else
5328 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5329 peer->allowas_in[afi][safi], VTY_NEWLINE);
5330 }
5331
5332 /* Filter. */
5333 bgp_config_write_filter (vty, peer, afi, safi);
5334
5335 /* atribute-unchanged. */
5336 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5337 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5338 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5339 && ! peer->af_group[afi][safi])
5340 {
5341 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5342 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5343 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5344 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5345 else
5346 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5347 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5348 " as-path" : "",
5349 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5350 " next-hop" : "",
5351 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5352 " med" : "", VTY_NEWLINE);
5353 }
5354}
5355
5356/* Display "address-family" configuration header. */
5357void
5358bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5359 int *write)
5360{
5361 if (*write)
5362 return;
5363
5364 if (afi == AFI_IP && safi == SAFI_UNICAST)
5365 return;
5366
5367 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5368
5369 if (afi == AFI_IP)
5370 {
5371 if (safi == SAFI_MULTICAST)
5372 vty_out (vty, "ipv4 multicast");
5373 else if (safi == SAFI_MPLS_VPN)
Lou Bergera3fda882016-01-12 13:42:04 -05005374 vty_out (vty, "vpnv4");
5375 else if (safi == SAFI_ENCAP)
5376 vty_out (vty, "encap");
paul718e3742002-12-13 20:15:29 +00005377 }
5378 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005379 {
Lou Berger13c378d2016-01-12 13:41:56 -05005380 if (safi == SAFI_MPLS_VPN)
5381 vty_out (vty, "vpnv6");
Lou Bergera3fda882016-01-12 13:42:04 -05005382 else if (safi == SAFI_ENCAP)
5383 vty_out (vty, "encapv6");
Lou Berger13c378d2016-01-12 13:41:56 -05005384 else
5385 {
5386 vty_out (vty, "ipv6");
5387 if (safi == SAFI_MULTICAST)
5388 vty_out (vty, " multicast");
5389 }
Paul Jakma37a217a2007-04-10 19:20:29 +00005390 }
paul718e3742002-12-13 20:15:29 +00005391
5392 vty_out (vty, "%s", VTY_NEWLINE);
5393
5394 *write = 1;
5395}
5396
5397/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005398static int
paul718e3742002-12-13 20:15:29 +00005399bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5400 safi_t safi)
5401{
5402 int write = 0;
5403 struct peer *peer;
5404 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005405 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005406
5407 bgp_config_write_network (vty, bgp, afi, safi, &write);
5408
5409 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5410
paul1eb8ef22005-04-07 07:30:20 +00005411 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005412 {
5413 if (group->conf->afc[afi][safi])
5414 {
5415 bgp_config_write_family_header (vty, afi, safi, &write);
5416 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5417 }
5418 }
paul1eb8ef22005-04-07 07:30:20 +00005419 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005420 {
5421 if (peer->afc[afi][safi])
5422 {
5423 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5424 {
5425 bgp_config_write_family_header (vty, afi, safi, &write);
5426 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5427 }
5428 }
5429 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005430
5431 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5432
Roman Hoog Antink6184c392014-03-17 14:01:42 +01005433 bgp_config_write_distance (vty, bgp, afi, safi, &write);
5434
paul718e3742002-12-13 20:15:29 +00005435 if (write)
5436 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5437
5438 return write;
5439}
5440
5441int
5442bgp_config_write (struct vty *vty)
5443{
5444 int write = 0;
5445 struct bgp *bgp;
5446 struct peer_group *group;
5447 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005448 struct listnode *node, *nnode;
5449 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005450
5451 /* BGP Multiple instance. */
5452 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5453 {
5454 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5455 write++;
5456 }
5457
5458 /* BGP Config type. */
5459 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5460 {
5461 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5462 write++;
5463 }
5464
5465 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005466 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005467 {
5468 if (write)
5469 vty_out (vty, "!%s", VTY_NEWLINE);
5470
5471 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005472 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005473
5474 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5475 {
5476 if (bgp->name)
5477 vty_out (vty, " view %s", bgp->name);
5478 }
5479 vty_out (vty, "%s", VTY_NEWLINE);
5480
5481 /* No Synchronization */
5482 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5483 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5484
5485 /* BGP fast-external-failover. */
5486 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5487 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5488
5489 /* BGP router ID. */
5490 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5491 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5492 VTY_NEWLINE);
5493
paul848973c2003-08-13 00:32:49 +00005494 /* BGP log-neighbor-changes. */
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07005495 if (!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5496 vty_out (vty, " no bgp log-neighbor-changes%s", VTY_NEWLINE);
paul848973c2003-08-13 00:32:49 +00005497
paul718e3742002-12-13 20:15:29 +00005498 /* BGP configuration. */
5499 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5500 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5501
5502 /* BGP default ipv4-unicast. */
5503 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5504 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5505
5506 /* BGP default local-preference. */
5507 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5508 vty_out (vty, " bgp default local-preference %d%s",
5509 bgp->default_local_pref, VTY_NEWLINE);
5510
5511 /* BGP client-to-client reflection. */
5512 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5513 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5514
5515 /* BGP cluster ID. */
5516 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5517 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5518 VTY_NEWLINE);
5519
hassoe0701b72004-05-20 09:19:34 +00005520 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005521 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005522 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5523 VTY_NEWLINE);
5524
5525 /* Confederation peer */
5526 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005527 {
hassoe0701b72004-05-20 09:19:34 +00005528 int i;
paul718e3742002-12-13 20:15:29 +00005529
hassoe0701b72004-05-20 09:19:34 +00005530 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005531
hassoe0701b72004-05-20 09:19:34 +00005532 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005533 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005534
hassoe0701b72004-05-20 09:19:34 +00005535 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005536 }
5537
5538 /* BGP enforce-first-as. */
5539 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5540 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5541
5542 /* BGP deterministic-med. */
5543 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5544 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005545
5546 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005547 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5548 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5549 bgp->stalepath_time, VTY_NEWLINE);
Philippe Guibert4afa3dd2016-05-24 16:52:02 +02005550 if (bgp->restart_time != BGP_DEFAULT_RESTART_TIME)
5551 vty_out (vty, " bgp graceful-restart restart-time %d%s",
5552 bgp->restart_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005553 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5554 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5555
paul718e3742002-12-13 20:15:29 +00005556 /* BGP bestpath method. */
5557 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5558 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005559 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5560 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
Pradosh Mohapatra2fdd4552013-09-07 07:02:36 +00005561 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
5562 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
5563 }
Dinesh Dutt083e5e22015-11-09 20:21:54 -05005564 if (bgp_flag_check (bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
5565 vty_out (vty, " bgp route-reflector allow-outbound-policy%s",
5566 VTY_NEWLINE);
5567 }
paul718e3742002-12-13 20:15:29 +00005568 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5569 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5570 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5571 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5572 {
5573 vty_out (vty, " bgp bestpath med");
5574 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5575 vty_out (vty, " confed");
5576 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5577 vty_out (vty, " missing-as-worst");
5578 vty_out (vty, "%s", VTY_NEWLINE);
5579 }
5580
5581 /* BGP network import check. */
5582 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5583 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5584
paul718e3742002-12-13 20:15:29 +00005585 /* BGP flag dampening. */
5586 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5587 BGP_CONFIG_DAMPENING))
5588 bgp_config_write_damp (vty);
5589
5590 /* BGP static route configuration. */
5591 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5592
5593 /* BGP redistribute configuration. */
5594 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5595
5596 /* BGP timers configuration. */
5597 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5598 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5599 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5600 bgp->default_holdtime, VTY_NEWLINE);
5601
5602 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005603 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005604 {
5605 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5606 }
5607
5608 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005609 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005610 {
5611 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5612 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5613 }
5614
Josh Bailey165b5ff2011-07-20 20:43:22 -07005615 /* maximum-paths */
5616 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5617
paul718e3742002-12-13 20:15:29 +00005618 /* Distance configuration. */
Roman Hoog Antink6184c392014-03-17 14:01:42 +01005619 bgp_config_write_distance (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
paul718e3742002-12-13 20:15:29 +00005620
5621 /* No auto-summary */
5622 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5623 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5624
5625 /* IPv4 multicast configuration. */
5626 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5627
5628 /* IPv4 VPN configuration. */
5629 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5630
Lou Bergera3fda882016-01-12 13:42:04 -05005631 /* ENCAPv4 configuration. */
5632 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_ENCAP);
5633
paul718e3742002-12-13 20:15:29 +00005634 /* IPv6 unicast configuration. */
5635 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5636
Paul Jakma37a217a2007-04-10 19:20:29 +00005637 /* IPv6 multicast configuration. */
5638 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5639
Lou Berger13c378d2016-01-12 13:41:56 -05005640 /* IPv6 VPN configuration. */
5641 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MPLS_VPN);
5642
Lou Bergera3fda882016-01-12 13:42:04 -05005643 /* ENCAPv6 configuration. */
5644 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_ENCAP);
5645
5646 vty_out (vty, " exit%s", VTY_NEWLINE);
5647
paul718e3742002-12-13 20:15:29 +00005648 write++;
5649 }
5650 return write;
5651}
5652
5653void
paul94f2b392005-06-28 12:44:16 +00005654bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005655{
5656 memset (&bgp_master, 0, sizeof (struct bgp_master));
5657
5658 bm = &bgp_master;
5659 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005660 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005661 bm->port = BGP_PORT_DEFAULT;
5662 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005663 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005664}
paul200df112005-06-01 11:17:05 +00005665
David Lamparter6b0655a2014-06-04 06:53:35 +02005666
paul718e3742002-12-13 20:15:29 +00005667void
paul94f2b392005-06-28 12:44:16 +00005668bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005669{
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07005670
5671 /* allocates some vital data structures used by peer commands in vty_init */
5672 bgp_scan_init ();
paul718e3742002-12-13 20:15:29 +00005673
paul718e3742002-12-13 20:15:29 +00005674 /* Init zebra. */
Donald Sharp774914f2015-10-14 08:50:39 -04005675 bgp_zebra_init (bm->master);
paul718e3742002-12-13 20:15:29 +00005676
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07005677 /* BGP VTY commands installation. */
5678 bgp_vty_init ();
5679
paul718e3742002-12-13 20:15:29 +00005680 /* BGP inits. */
5681 bgp_attr_init ();
5682 bgp_debug_init ();
5683 bgp_dump_init ();
5684 bgp_route_init ();
5685 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005686 bgp_address_init ();
Dinesh Duttd9ab53a2015-05-19 17:47:21 -07005687 bgp_scan_vty_init();
paul718e3742002-12-13 20:15:29 +00005688 bgp_mplsvpn_init ();
Lou Berger298cc2f2016-01-12 13:42:02 -05005689 bgp_encap_init ();
paul718e3742002-12-13 20:15:29 +00005690
5691 /* Access list initialize. */
5692 access_list_init ();
5693 access_list_add_hook (peer_distribute_update);
5694 access_list_delete_hook (peer_distribute_update);
5695
5696 /* Filter list initialize. */
5697 bgp_filter_init ();
5698 as_list_add_hook (peer_aslist_update);
5699 as_list_delete_hook (peer_aslist_update);
5700
5701 /* Prefix list initialize.*/
5702 prefix_list_init ();
5703 prefix_list_add_hook (peer_prefix_list_update);
5704 prefix_list_delete_hook (peer_prefix_list_update);
5705
5706 /* Community list initialize. */
5707 bgp_clist = community_list_init ();
5708
5709#ifdef HAVE_SNMP
5710 bgp_snmp_init ();
5711#endif /* HAVE_SNMP */
5712}
paul545acaf2004-04-20 15:13:15 +00005713
5714void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005715bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005716{
paul545acaf2004-04-20 15:13:15 +00005717 struct bgp *bgp;
5718 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005719 struct listnode *node, *nnode;
5720 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005721
paul1eb8ef22005-04-07 07:30:20 +00005722 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5723 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005724 if (peer->status == Established)
5725 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5726 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005727
paul545acaf2004-04-20 15:13:15 +00005728 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005729
paule210cf92005-06-15 19:15:35 +00005730 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005731 {
5732 work_queue_free (bm->process_main_queue);
5733 bm->process_main_queue = NULL;
5734 }
paule210cf92005-06-15 19:15:35 +00005735 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005736 {
5737 work_queue_free (bm->process_rsclient_queue);
5738 bm->process_rsclient_queue = NULL;
5739 }
paul545acaf2004-04-20 15:13:15 +00005740}