blob: e70d33774132b5e94fb77b83ecaee55ec51cc3ba [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"
paul718e3742002-12-13 20:15:29 +000064#ifdef HAVE_SNMP
65#include "bgpd/bgp_snmp.h"
66#endif /* HAVE_SNMP */
David Lamparter6b0655a2014-06-04 06:53:35 +020067
paul718e3742002-12-13 20:15:29 +000068/* BGP process wide configuration. */
69static struct bgp_master bgp_master;
70
hasso18a6dce2004-10-03 18:18:34 +000071extern struct in_addr router_id_zebra;
72
paul718e3742002-12-13 20:15:29 +000073/* BGP process wide configuration pointer to export. */
74struct bgp_master *bm;
75
76/* BGP community-list. */
77struct community_list_handler *bgp_clist;
David Lamparter6b0655a2014-06-04 06:53:35 +020078
paul718e3742002-12-13 20:15:29 +000079/* BGP global flag manipulation. */
80int
81bgp_option_set (int flag)
82{
83 switch (flag)
84 {
85 case BGP_OPT_NO_FIB:
86 case BGP_OPT_MULTIPLE_INSTANCE:
87 case BGP_OPT_CONFIG_CISCO:
Paul Jakmacccbc012012-06-14 10:40:26 +010088 case BGP_OPT_NO_LISTEN:
paul718e3742002-12-13 20:15:29 +000089 SET_FLAG (bm->options, flag);
90 break;
91 default:
92 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +000093 }
94 return 0;
95}
96
97int
98bgp_option_unset (int flag)
99{
100 switch (flag)
101 {
102 case BGP_OPT_MULTIPLE_INSTANCE:
103 if (listcount (bm->bgp) > 1)
104 return BGP_ERR_MULTIPLE_INSTANCE_USED;
105 /* Fall through. */
106 case BGP_OPT_NO_FIB:
107 case BGP_OPT_CONFIG_CISCO:
108 UNSET_FLAG (bm->options, flag);
109 break;
110 default:
111 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +0000112 }
113 return 0;
114}
115
116int
117bgp_option_check (int flag)
118{
119 return CHECK_FLAG (bm->options, flag);
120}
David Lamparter6b0655a2014-06-04 06:53:35 +0200121
paul718e3742002-12-13 20:15:29 +0000122/* BGP flag manipulation. */
123int
124bgp_flag_set (struct bgp *bgp, int flag)
125{
126 SET_FLAG (bgp->flags, flag);
127 return 0;
128}
129
130int
131bgp_flag_unset (struct bgp *bgp, int flag)
132{
133 UNSET_FLAG (bgp->flags, flag);
134 return 0;
135}
136
137int
138bgp_flag_check (struct bgp *bgp, int flag)
139{
140 return CHECK_FLAG (bgp->flags, flag);
141}
David Lamparter6b0655a2014-06-04 06:53:35 +0200142
paul718e3742002-12-13 20:15:29 +0000143/* Internal function to set BGP structure configureation flag. */
144static void
145bgp_config_set (struct bgp *bgp, int config)
146{
147 SET_FLAG (bgp->config, config);
148}
149
150static void
151bgp_config_unset (struct bgp *bgp, int config)
152{
153 UNSET_FLAG (bgp->config, config);
154}
155
156static int
157bgp_config_check (struct bgp *bgp, int config)
158{
159 return CHECK_FLAG (bgp->config, config);
160}
David Lamparter6b0655a2014-06-04 06:53:35 +0200161
paul718e3742002-12-13 20:15:29 +0000162/* Set BGP router identifier. */
163int
164bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
165{
166 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000167 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000168
169 if (bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID)
170 && IPV4_ADDR_SAME (&bgp->router_id, id))
171 return 0;
172
173 IPV4_ADDR_COPY (&bgp->router_id, id);
174 bgp_config_set (bgp, BGP_CONFIG_ROUTER_ID);
175
176 /* Set all peer's local identifier with this value. */
paul1eb8ef22005-04-07 07:30:20 +0000177 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000178 {
179 IPV4_ADDR_COPY (&peer->local_id, id);
180
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000181 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000182 {
183 peer->last_reset = PEER_DOWN_RID_CHANGE;
184 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
185 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
186 }
paul718e3742002-12-13 20:15:29 +0000187 }
188 return 0;
189}
190
paul718e3742002-12-13 20:15:29 +0000191/* BGP's cluster-id control. */
192int
193bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
194{
195 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000196 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000197
198 if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)
199 && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id))
200 return 0;
201
202 IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id);
203 bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID);
204
205 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000206 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000207 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000208 if (peer->sort != BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +0000209 continue;
210
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000211 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000212 {
213 peer->last_reset = PEER_DOWN_CLID_CHANGE;
214 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
215 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
216 }
paul718e3742002-12-13 20:15:29 +0000217 }
218 return 0;
219}
220
221int
222bgp_cluster_id_unset (struct bgp *bgp)
223{
224 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000225 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000226
227 if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID))
228 return 0;
229
230 bgp->cluster_id.s_addr = 0;
231 bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID);
232
233 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000234 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000235 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000236 if (peer->sort != BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +0000237 continue;
238
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000239 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000240 {
241 peer->last_reset = PEER_DOWN_CLID_CHANGE;
242 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
243 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
244 }
paul718e3742002-12-13 20:15:29 +0000245 }
246 return 0;
247}
David Lamparter6b0655a2014-06-04 06:53:35 +0200248
Stephen Hemminger65957882010-01-15 16:22:10 +0300249/* time_t value that is monotonicly increasing
250 * and uneffected by adjustments to system clock
251 */
252time_t bgp_clock (void)
253{
254 struct timeval tv;
255
256 quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv);
257 return tv.tv_sec;
258}
259
paul718e3742002-12-13 20:15:29 +0000260/* BGP timer configuration. */
261int
262bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
263{
264 bgp->default_keepalive = (keepalive < holdtime / 3
265 ? keepalive : holdtime / 3);
266 bgp->default_holdtime = holdtime;
267
268 return 0;
269}
270
271int
272bgp_timers_unset (struct bgp *bgp)
273{
274 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
275 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
276
277 return 0;
278}
David Lamparter6b0655a2014-06-04 06:53:35 +0200279
paul718e3742002-12-13 20:15:29 +0000280/* BGP confederation configuration. */
281int
282bgp_confederation_id_set (struct bgp *bgp, as_t as)
283{
284 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000285 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000286 int already_confed;
287
288 if (as == 0)
289 return BGP_ERR_INVALID_AS;
290
291 /* Remember - were we doing confederation before? */
292 already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);
293 bgp->confed_id = as;
294 bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);
295
296 /* If we were doing confederation already, this is just an external
297 AS change. Just Reset EBGP sessions, not CONFED sessions. If we
298 were not doing confederation before, reset all EBGP sessions. */
paul1eb8ef22005-04-07 07:30:20 +0000299 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000300 {
301 /* We're looking for peers who's AS is not local or part of our
302 confederation. */
303 if (already_confed)
304 {
305 if (peer_sort (peer) == BGP_PEER_EBGP)
306 {
307 peer->local_as = as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000308 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000309 {
310 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
311 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
312 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
313 }
314
paul718e3742002-12-13 20:15:29 +0000315 else
316 BGP_EVENT_ADD (peer, BGP_Stop);
317 }
318 }
319 else
320 {
321 /* Not doign confederation before, so reset every non-local
322 session */
323 if (peer_sort (peer) != BGP_PEER_IBGP)
324 {
325 /* Reset the local_as to be our EBGP one */
326 if (peer_sort (peer) == BGP_PEER_EBGP)
327 peer->local_as = as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000328 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000329 {
330 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
331 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
332 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
333 }
paul718e3742002-12-13 20:15:29 +0000334 else
335 BGP_EVENT_ADD (peer, BGP_Stop);
336 }
337 }
338 }
339 return 0;
340}
341
342int
343bgp_confederation_id_unset (struct bgp *bgp)
344{
345 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000346 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000347
348 bgp->confed_id = 0;
349 bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
350
paul1eb8ef22005-04-07 07:30:20 +0000351 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000352 {
353 /* We're looking for peers who's AS is not local */
354 if (peer_sort (peer) != BGP_PEER_IBGP)
355 {
356 peer->local_as = bgp->as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000357 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000358 {
359 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
360 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
361 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
362 }
363
paul718e3742002-12-13 20:15:29 +0000364 else
365 BGP_EVENT_ADD (peer, BGP_Stop);
366 }
367 }
368 return 0;
369}
370
371/* Is an AS part of the confed or not? */
372int
373bgp_confederation_peers_check (struct bgp *bgp, as_t as)
374{
375 int i;
376
377 if (! bgp)
378 return 0;
379
380 for (i = 0; i < bgp->confed_peers_cnt; i++)
381 if (bgp->confed_peers[i] == as)
382 return 1;
383
384 return 0;
385}
386
387/* Add an AS to the confederation set. */
388int
389bgp_confederation_peers_add (struct bgp *bgp, as_t as)
390{
391 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000392 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000393
394 if (! bgp)
395 return BGP_ERR_INVALID_BGP;
396
397 if (bgp->as == as)
398 return BGP_ERR_INVALID_AS;
399
400 if (bgp_confederation_peers_check (bgp, as))
401 return -1;
402
403 if (bgp->confed_peers)
404 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
405 bgp->confed_peers,
406 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
407 else
408 bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST,
409 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
410
411 bgp->confed_peers[bgp->confed_peers_cnt] = as;
412 bgp->confed_peers_cnt++;
413
414 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
415 {
paul1eb8ef22005-04-07 07:30:20 +0000416 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000417 {
418 if (peer->as == as)
419 {
420 peer->local_as = bgp->as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000421 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000422 {
423 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
424 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
425 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
426 }
paul718e3742002-12-13 20:15:29 +0000427 else
428 BGP_EVENT_ADD (peer, BGP_Stop);
429 }
430 }
431 }
432 return 0;
433}
434
435/* Delete an AS from the confederation set. */
436int
437bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
438{
439 int i;
440 int j;
441 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000442 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000443
444 if (! bgp)
445 return -1;
446
447 if (! bgp_confederation_peers_check (bgp, as))
448 return -1;
449
450 for (i = 0; i < bgp->confed_peers_cnt; i++)
451 if (bgp->confed_peers[i] == as)
452 for(j = i + 1; j < bgp->confed_peers_cnt; j++)
453 bgp->confed_peers[j - 1] = bgp->confed_peers[j];
454
455 bgp->confed_peers_cnt--;
456
457 if (bgp->confed_peers_cnt == 0)
458 {
459 if (bgp->confed_peers)
460 XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
461 bgp->confed_peers = NULL;
462 }
463 else
464 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
465 bgp->confed_peers,
466 bgp->confed_peers_cnt * sizeof (as_t));
467
468 /* Now reset any peer who's remote AS has just been removed from the
469 CONFED */
470 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
471 {
paul1eb8ef22005-04-07 07:30:20 +0000472 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000473 {
474 if (peer->as == as)
475 {
476 peer->local_as = bgp->confed_id;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000477 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000478 {
479 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
480 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
481 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
482 }
paul718e3742002-12-13 20:15:29 +0000483 else
484 BGP_EVENT_ADD (peer, BGP_Stop);
485 }
486 }
487 }
488
489 return 0;
490}
David Lamparter6b0655a2014-06-04 06:53:35 +0200491
paul718e3742002-12-13 20:15:29 +0000492/* Local preference configuration. */
493int
494bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
495{
496 if (! bgp)
497 return -1;
498
paul718e3742002-12-13 20:15:29 +0000499 bgp->default_local_pref = local_pref;
500
501 return 0;
502}
503
504int
505bgp_default_local_preference_unset (struct bgp *bgp)
506{
507 if (! bgp)
508 return -1;
509
paul718e3742002-12-13 20:15:29 +0000510 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
511
512 return 0;
513}
David Lamparter6b0655a2014-06-04 06:53:35 +0200514
paulfee0f4c2004-09-13 05:12:46 +0000515/* If peer is RSERVER_CLIENT in at least one address family and is not member
516 of a peer_group for that family, return 1.
517 Used to check wether the peer is included in list bgp->rsclient. */
518int
519peer_rsclient_active (struct peer *peer)
520{
521 int i;
522 int j;
523
524 for (i=AFI_IP; i < AFI_MAX; i++)
525 for (j=SAFI_UNICAST; j < SAFI_MAX; j++)
526 if (CHECK_FLAG(peer->af_flags[i][j], PEER_FLAG_RSERVER_CLIENT)
527 && ! peer->af_group[i][j])
528 return 1;
529 return 0;
530}
531
pauleb821182004-05-01 08:44:08 +0000532/* Peer comparison function for sorting. */
paul718e3742002-12-13 20:15:29 +0000533static int
534peer_cmp (struct peer *p1, struct peer *p2)
535{
pauleb821182004-05-01 08:44:08 +0000536 return sockunion_cmp (&p1->su, &p2->su);
paul718e3742002-12-13 20:15:29 +0000537}
538
539int
540peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
541{
542 return CHECK_FLAG (peer->af_flags[afi][safi], flag);
543}
544
545/* Reset all address family specific configuration. */
546static void
547peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
548{
549 int i;
550 struct bgp_filter *filter;
551 char orf_name[BUFSIZ];
552
553 filter = &peer->filter[afi][safi];
554
555 /* Clear neighbor filter and route-map */
556 for (i = FILTER_IN; i < FILTER_MAX; i++)
557 {
558 if (filter->dlist[i].name)
559 {
560 free (filter->dlist[i].name);
561 filter->dlist[i].name = NULL;
562 }
563 if (filter->plist[i].name)
564 {
565 free (filter->plist[i].name);
566 filter->plist[i].name = NULL;
567 }
568 if (filter->aslist[i].name)
569 {
570 free (filter->aslist[i].name);
571 filter->aslist[i].name = NULL;
572 }
paulfee0f4c2004-09-13 05:12:46 +0000573 }
574 for (i = RMAP_IN; i < RMAP_MAX; i++)
575 {
paul718e3742002-12-13 20:15:29 +0000576 if (filter->map[i].name)
577 {
578 free (filter->map[i].name);
579 filter->map[i].name = NULL;
580 }
581 }
582
583 /* Clear unsuppress map. */
584 if (filter->usmap.name)
585 free (filter->usmap.name);
586 filter->usmap.name = NULL;
587 filter->usmap.map = NULL;
588
589 /* Clear neighbor's all address family flags. */
590 peer->af_flags[afi][safi] = 0;
591
592 /* Clear neighbor's all address family sflags. */
593 peer->af_sflags[afi][safi] = 0;
594
595 /* Clear neighbor's all address family capabilities. */
596 peer->af_cap[afi][safi] = 0;
597
598 /* Clear ORF info */
599 peer->orf_plist[afi][safi] = NULL;
600 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
David Lamparterc9c06d02015-04-13 10:21:35 +0200601 prefix_bgp_orf_remove_all (afi, orf_name);
paul718e3742002-12-13 20:15:29 +0000602
603 /* Set default neighbor send-community. */
604 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
605 {
606 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
607 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
608 }
609
610 /* Clear neighbor default_originate_rmap */
611 if (peer->default_rmap[afi][safi].name)
612 free (peer->default_rmap[afi][safi].name);
613 peer->default_rmap[afi][safi].name = NULL;
614 peer->default_rmap[afi][safi].map = NULL;
615
616 /* Clear neighbor maximum-prefix */
617 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +0000618 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000619}
620
621/* peer global config reset */
paul94f2b392005-06-28 12:44:16 +0000622static void
paul718e3742002-12-13 20:15:29 +0000623peer_global_config_reset (struct peer *peer)
624{
625 peer->weight = 0;
626 peer->change_local_as = 0;
627 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
628 if (peer->update_source)
629 {
630 sockunion_free (peer->update_source);
631 peer->update_source = NULL;
632 }
633 if (peer->update_if)
634 {
635 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
636 peer->update_if = NULL;
637 }
638
639 if (peer_sort (peer) == BGP_PEER_IBGP)
640 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
641 else
642 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
643
644 peer->flags = 0;
645 peer->config = 0;
646 peer->holdtime = 0;
647 peer->keepalive = 0;
648 peer->connect = 0;
649 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
650}
651
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000652/* Check peer's AS number and determines if this peer is IBGP or EBGP */
653static bgp_peer_sort_t
654peer_calc_sort (struct peer *peer)
paul718e3742002-12-13 20:15:29 +0000655{
656 struct bgp *bgp;
657
658 bgp = peer->bgp;
659
660 /* Peer-group */
661 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
662 {
663 if (peer->as)
664 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
665 else
666 {
667 struct peer *peer1;
668 peer1 = listnode_head (peer->group->peer);
669 if (peer1)
670 return (peer1->local_as == peer1->as
671 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
672 }
673 return BGP_PEER_INTERNAL;
674 }
675
676 /* Normal peer */
677 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
678 {
679 if (peer->local_as == 0)
680 return BGP_PEER_INTERNAL;
681
682 if (peer->local_as == peer->as)
683 {
684 if (peer->local_as == bgp->confed_id)
685 return BGP_PEER_EBGP;
686 else
687 return BGP_PEER_IBGP;
688 }
689
690 if (bgp_confederation_peers_check (bgp, peer->as))
691 return BGP_PEER_CONFED;
692
693 return BGP_PEER_EBGP;
694 }
695 else
696 {
697 return (peer->local_as == 0
698 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
699 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
700 }
701}
702
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000703/* Calculate and cache the peer "sort" */
704bgp_peer_sort_t
705peer_sort (struct peer *peer)
706{
707 peer->sort = peer_calc_sort (peer);
708 return peer->sort;
709}
710
Paul Jakmaf63f06d2011-04-08 12:44:43 +0100711static void
paul200df112005-06-01 11:17:05 +0000712peer_free (struct peer *peer)
713{
Paul Jakmaca058a32006-09-14 02:58:49 +0000714 assert (peer->status == Deleted);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700715
716 bgp_unlock(peer->bgp);
717
Paul Jakmaca058a32006-09-14 02:58:49 +0000718 /* this /ought/ to have been done already through bgp_stop earlier,
719 * but just to be sure..
720 */
721 bgp_timer_set (peer);
722 BGP_READ_OFF (peer->t_read);
723 BGP_WRITE_OFF (peer->t_write);
Paul Jakma9fde6622006-09-14 03:02:02 +0000724 BGP_EVENT_FLUSH (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +0000725
paul200df112005-06-01 11:17:05 +0000726 if (peer->desc)
Daniel Walton363c9032015-10-21 06:42:54 -0700727 {
728 XFREE (MTYPE_PEER_DESC, peer->desc);
729 peer->desc = NULL;
730 }
paul200df112005-06-01 11:17:05 +0000731
732 /* Free allocated host character. */
733 if (peer->host)
Daniel Walton363c9032015-10-21 06:42:54 -0700734 {
735 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
736 peer->host = NULL;
737 }
738
paul200df112005-06-01 11:17:05 +0000739 /* Update source configuration. */
740 if (peer->update_source)
Daniel Walton363c9032015-10-21 06:42:54 -0700741 {
742 sockunion_free (peer->update_source);
743 peer->update_source = NULL;
744 }
paul200df112005-06-01 11:17:05 +0000745
746 if (peer->update_if)
Daniel Walton363c9032015-10-21 06:42:54 -0700747 {
748 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
749 peer->update_if = NULL;
750 }
Paul Jakmaa625ca32006-03-30 14:12:38 +0000751
752 if (peer->clear_node_queue)
Daniel Walton363c9032015-10-21 06:42:54 -0700753 {
754 work_queue_free(peer->clear_node_queue);
755 peer->clear_node_queue = NULL;
756 }
Paul Jakmaa625ca32006-03-30 14:12:38 +0000757
Lou Berger056f3762013-04-10 12:30:04 -0700758 if (peer->notify.data)
759 XFREE(MTYPE_TMP, peer->notify.data);
760
Paul Jakmaca058a32006-09-14 02:58:49 +0000761 bgp_sync_delete (peer);
paul200df112005-06-01 11:17:05 +0000762 memset (peer, 0, sizeof (struct peer));
763
764 XFREE (MTYPE_BGP_PEER, peer);
765}
766
767/* increase reference count on a struct peer */
768struct peer *
Donald Sharp104576d2015-09-16 13:17:55 -0400769peer_lock_with_caller (const char *name, struct peer *peer)
paul200df112005-06-01 11:17:05 +0000770{
771 assert (peer && (peer->lock >= 0));
Donald Sharp104576d2015-09-16 13:17:55 -0400772
773#if 0
774 zlog_debug("%s peer_lock %p %d", name, peer, peer->lock);
775#endif
776
paul200df112005-06-01 11:17:05 +0000777 peer->lock++;
778
779 return peer;
780}
781
782/* decrease reference count on a struct peer
783 * struct peer is freed and NULL returned if last reference
784 */
785struct peer *
Donald Sharp104576d2015-09-16 13:17:55 -0400786peer_unlock_with_caller (const char *name, struct peer *peer)
paul200df112005-06-01 11:17:05 +0000787{
788 assert (peer && (peer->lock > 0));
Donald Sharp104576d2015-09-16 13:17:55 -0400789
790#if 0
791 zlog_debug("%s peer_unlock %p %d", name, peer, peer->lock);
792#endif
793
paul200df112005-06-01 11:17:05 +0000794 peer->lock--;
795
796 if (peer->lock == 0)
797 {
paul200df112005-06-01 11:17:05 +0000798 peer_free (peer);
799 return NULL;
800 }
801
paul200df112005-06-01 11:17:05 +0000802 return peer;
803}
804
805/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000806static struct peer *
Paul Jakma6f585442006-10-22 19:13:07 +0000807peer_new (struct bgp *bgp)
paul718e3742002-12-13 20:15:29 +0000808{
809 afi_t afi;
810 safi_t safi;
811 struct peer *peer;
812 struct servent *sp;
Paul Jakma6f585442006-10-22 19:13:07 +0000813
814 /* bgp argument is absolutely required */
815 assert (bgp);
816 if (!bgp)
817 return NULL;
818
paul718e3742002-12-13 20:15:29 +0000819 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000820 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000821
822 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000823 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000824 peer->v_start = BGP_INIT_START_TIMER;
825 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
paul718e3742002-12-13 20:15:29 +0000826 peer->status = Idle;
827 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000828 peer->weight = 0;
Paul Jakma0df7c912008-07-21 21:02:49 +0000829 peer->password = NULL;
Paul Jakma6f585442006-10-22 19:13:07 +0000830 peer->bgp = bgp;
Paul Jakmaca058a32006-09-14 02:58:49 +0000831 peer = peer_lock (peer); /* initial reference */
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700832 bgp_lock (bgp);
paul718e3742002-12-13 20:15:29 +0000833
834 /* Set default flags. */
835 for (afi = AFI_IP; afi < AFI_MAX; afi++)
836 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
837 {
838 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
839 {
840 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
841 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
842 }
843 peer->orf_plist[afi][safi] = NULL;
844 }
845 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
846
847 /* Create buffers. */
848 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
849 peer->obuf = stream_fifo_new ();
850 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000851 peer->scratch = stream_new (BGP_MAX_PACKET_SIZE);
paul718e3742002-12-13 20:15:29 +0000852
853 bgp_sync_init (peer);
854
855 /* Get service port number. */
856 sp = getservbyname ("bgp", "tcp");
857 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
858
859 return peer;
860}
861
862/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000863static struct peer *
paul718e3742002-12-13 20:15:29 +0000864peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
865 as_t remote_as, afi_t afi, safi_t safi)
866{
867 int active;
868 struct peer *peer;
869 char buf[SU_ADDRSTRLEN];
870
Paul Jakma6f585442006-10-22 19:13:07 +0000871 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000872 peer->su = *su;
873 peer->local_as = local_as;
874 peer->as = remote_as;
875 peer->local_id = bgp->router_id;
876 peer->v_holdtime = bgp->default_holdtime;
877 peer->v_keepalive = bgp->default_keepalive;
878 if (peer_sort (peer) == BGP_PEER_IBGP)
879 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
880 else
881 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000882
883 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000884 listnode_add_sort (bgp->peer, peer);
885
886 active = peer_active (peer);
887
888 if (afi && safi)
889 peer->afc[afi][safi] = 1;
890
Stephen Hemminger65957882010-01-15 16:22:10 +0300891 /* Last read and reset time set */
892 peer->readtime = peer->resettime = bgp_clock ();
paul848973c2003-08-13 00:32:49 +0000893
paul718e3742002-12-13 20:15:29 +0000894 /* Default TTL set. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000895 peer->ttl = (peer->sort == BGP_PEER_IBGP) ? 255 : 1;
paul718e3742002-12-13 20:15:29 +0000896
897 /* Make peer's address string. */
898 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000899 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000900
901 /* Set up peer's events and timers. */
902 if (! active && peer_active (peer))
903 bgp_timer_set (peer);
904
905 return peer;
906}
907
pauleb821182004-05-01 08:44:08 +0000908/* Make accept BGP peer. Called from bgp_accept (). */
909struct peer *
910peer_create_accept (struct bgp *bgp)
911{
912 struct peer *peer;
913
Paul Jakma6f585442006-10-22 19:13:07 +0000914 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000915
916 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000917 listnode_add_sort (bgp->peer, peer);
918
919 return peer;
920}
921
paul718e3742002-12-13 20:15:29 +0000922/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000923static void
paul718e3742002-12-13 20:15:29 +0000924peer_as_change (struct peer *peer, as_t as)
925{
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000926 bgp_peer_sort_t type;
Daniel Walton0d7435f2015-10-22 11:35:20 +0300927 struct peer *conf;
paul718e3742002-12-13 20:15:29 +0000928
929 /* Stop peer. */
930 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
931 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000932 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000933 {
934 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
935 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
936 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
937 }
paul718e3742002-12-13 20:15:29 +0000938 else
939 BGP_EVENT_ADD (peer, BGP_Stop);
940 }
941 type = peer_sort (peer);
942 peer->as = as;
943
paul848973c2003-08-13 00:32:49 +0000944 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
945 && ! bgp_confederation_peers_check (peer->bgp, as)
946 && peer->bgp->as != as)
947 peer->local_as = peer->bgp->confed_id;
948 else
949 peer->local_as = peer->bgp->as;
950
paul718e3742002-12-13 20:15:29 +0000951 /* Advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +0300952 conf = NULL;
953 if (peer->group)
954 conf = peer->group->conf;
955
956 if (conf && CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
957 peer->v_routeadv = conf->routeadv;
paul718e3742002-12-13 20:15:29 +0000958 else
Daniel Walton0d7435f2015-10-22 11:35:20 +0300959 if (peer_sort (peer) == BGP_PEER_IBGP)
960 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
961 else
962 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul718e3742002-12-13 20:15:29 +0000963
964 /* TTL reset */
965 if (peer_sort (peer) == BGP_PEER_IBGP)
966 peer->ttl = 255;
967 else if (type == BGP_PEER_IBGP)
968 peer->ttl = 1;
969
970 /* reflector-client reset */
971 if (peer_sort (peer) != BGP_PEER_IBGP)
972 {
973 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
974 PEER_FLAG_REFLECTOR_CLIENT);
975 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
976 PEER_FLAG_REFLECTOR_CLIENT);
977 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
978 PEER_FLAG_REFLECTOR_CLIENT);
Lou Berger298cc2f2016-01-12 13:42:02 -0500979 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_ENCAP],
980 PEER_FLAG_REFLECTOR_CLIENT);
paul718e3742002-12-13 20:15:29 +0000981 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
982 PEER_FLAG_REFLECTOR_CLIENT);
983 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
984 PEER_FLAG_REFLECTOR_CLIENT);
Lou Berger9da04bc2016-01-12 13:41:55 -0500985 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MPLS_VPN],
986 PEER_FLAG_REFLECTOR_CLIENT);
Lou Berger298cc2f2016-01-12 13:42:02 -0500987 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_ENCAP],
988 PEER_FLAG_REFLECTOR_CLIENT);
paul718e3742002-12-13 20:15:29 +0000989 }
990
991 /* local-as reset */
992 if (peer_sort (peer) != BGP_PEER_EBGP)
993 {
994 peer->change_local_as = 0;
995 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +0000996 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +0000997 }
998}
999
1000/* If peer does not exist, create new one. If peer already exists,
1001 set AS number to the peer. */
1002int
1003peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
1004 afi_t afi, safi_t safi)
1005{
1006 struct peer *peer;
1007 as_t local_as;
1008
1009 peer = peer_lookup (bgp, su);
1010
1011 if (peer)
1012 {
1013 /* When this peer is a member of peer-group. */
1014 if (peer->group)
1015 {
1016 if (peer->group->conf->as)
1017 {
1018 /* Return peer group's AS number. */
1019 *as = peer->group->conf->as;
1020 return BGP_ERR_PEER_GROUP_MEMBER;
1021 }
1022 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
1023 {
1024 if (bgp->as != *as)
1025 {
1026 *as = peer->as;
1027 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1028 }
1029 }
1030 else
1031 {
1032 if (bgp->as == *as)
1033 {
1034 *as = peer->as;
1035 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1036 }
1037 }
1038 }
1039
1040 /* Existing peer's AS number change. */
1041 if (peer->as != *as)
1042 peer_as_change (peer, *as);
1043 }
1044 else
1045 {
1046
1047 /* If the peer is not part of our confederation, and its not an
1048 iBGP peer then spoof the source AS */
1049 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1050 && ! bgp_confederation_peers_check (bgp, *as)
1051 && bgp->as != *as)
1052 local_as = bgp->confed_id;
1053 else
1054 local_as = bgp->as;
1055
1056 /* If this is IPv4 unicast configuration and "no bgp default
1057 ipv4-unicast" is specified. */
1058
1059 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1060 && afi == AFI_IP && safi == SAFI_UNICAST)
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001061 peer_create (su, bgp, local_as, *as, 0, 0);
paul718e3742002-12-13 20:15:29 +00001062 else
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001063 peer_create (su, bgp, local_as, *as, afi, safi);
paul718e3742002-12-13 20:15:29 +00001064 }
1065
1066 return 0;
1067}
1068
1069/* Activate the peer or peer group for specified AFI and SAFI. */
1070int
1071peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1072{
1073 int active;
1074
1075 if (peer->afc[afi][safi])
1076 return 0;
1077
1078 /* Activate the address family configuration. */
1079 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1080 peer->afc[afi][safi] = 1;
1081 else
1082 {
1083 active = peer_active (peer);
1084
1085 peer->afc[afi][safi] = 1;
1086
1087 if (! active && peer_active (peer))
1088 bgp_timer_set (peer);
1089 else
1090 {
1091 if (peer->status == Established)
1092 {
1093 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1094 {
1095 peer->afc_adv[afi][safi] = 1;
1096 bgp_capability_send (peer, afi, safi,
1097 CAPABILITY_CODE_MP,
1098 CAPABILITY_ACTION_SET);
1099 if (peer->afc_recv[afi][safi])
1100 {
1101 peer->afc_nego[afi][safi] = 1;
1102 bgp_announce_route (peer, afi, safi);
1103 }
1104 }
1105 else
hassoe0701b72004-05-20 09:19:34 +00001106 {
1107 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1108 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1109 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1110 }
paul718e3742002-12-13 20:15:29 +00001111 }
1112 }
1113 }
1114 return 0;
1115}
1116
1117int
1118peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1119{
1120 struct peer_group *group;
1121 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001122 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001123
1124 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1125 {
1126 group = peer->group;
1127
paul1eb8ef22005-04-07 07:30:20 +00001128 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001129 {
1130 if (peer1->af_group[afi][safi])
1131 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1132 }
1133 }
1134 else
1135 {
1136 if (peer->af_group[afi][safi])
1137 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1138 }
1139
1140 if (! peer->afc[afi][safi])
1141 return 0;
1142
1143 /* De-activate the address family configuration. */
1144 peer->afc[afi][safi] = 0;
1145 peer_af_flag_reset (peer, afi, safi);
1146
1147 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1148 {
1149 if (peer->status == Established)
1150 {
1151 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1152 {
1153 peer->afc_adv[afi][safi] = 0;
1154 peer->afc_nego[afi][safi] = 0;
1155
1156 if (peer_active_nego (peer))
1157 {
1158 bgp_capability_send (peer, afi, safi,
1159 CAPABILITY_CODE_MP,
1160 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001161 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001162 peer->pcount[afi][safi] = 0;
1163 }
1164 else
hassoe0701b72004-05-20 09:19:34 +00001165 {
1166 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1167 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1168 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1169 }
paul718e3742002-12-13 20:15:29 +00001170 }
1171 else
hassoe0701b72004-05-20 09:19:34 +00001172 {
1173 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1174 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1175 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1176 }
paul718e3742002-12-13 20:15:29 +00001177 }
1178 }
1179 return 0;
1180}
1181
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001182static void
hasso93406d82005-02-02 14:40:33 +00001183peer_nsf_stop (struct peer *peer)
1184{
1185 afi_t afi;
1186 safi_t safi;
1187
1188 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1189 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1190
1191 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +04001192 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +00001193 peer->nsf[afi][safi] = 0;
1194
1195 if (peer->t_gr_restart)
1196 {
1197 BGP_TIMER_OFF (peer->t_gr_restart);
1198 if (BGP_DEBUG (events, EVENTS))
1199 zlog_debug ("%s graceful restart timer stopped", peer->host);
1200 }
1201 if (peer->t_gr_stale)
1202 {
1203 BGP_TIMER_OFF (peer->t_gr_stale);
1204 if (BGP_DEBUG (events, EVENTS))
1205 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1206 }
1207 bgp_clear_route_all (peer);
1208}
1209
Paul Jakmaca058a32006-09-14 02:58:49 +00001210/* Delete peer from confguration.
1211 *
1212 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1213 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1214 *
1215 * This function /should/ take care to be idempotent, to guard against
1216 * it being called multiple times through stray events that come in
1217 * that happen to result in this function being called again. That
1218 * said, getting here for a "Deleted" peer is a bug in the neighbour
1219 * FSM.
1220 */
paul718e3742002-12-13 20:15:29 +00001221int
1222peer_delete (struct peer *peer)
1223{
1224 int i;
1225 afi_t afi;
1226 safi_t safi;
1227 struct bgp *bgp;
1228 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001229 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001230
Paul Jakmaca058a32006-09-14 02:58:49 +00001231 assert (peer->status != Deleted);
1232
paul718e3742002-12-13 20:15:29 +00001233 bgp = peer->bgp;
1234
hasso93406d82005-02-02 14:40:33 +00001235 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1236 peer_nsf_stop (peer);
1237
Chris Caputo228da422009-07-18 05:44:03 +00001238 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001239 relationship. */
1240 if (peer->group)
1241 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001242 if ((pn = listnode_lookup (peer->group->peer, peer)))
1243 {
1244 peer = peer_unlock (peer); /* group->peer list reference */
1245 list_delete_node (peer->group->peer, pn);
1246 }
paul718e3742002-12-13 20:15:29 +00001247 peer->group = NULL;
1248 }
paul200df112005-06-01 11:17:05 +00001249
paul718e3742002-12-13 20:15:29 +00001250 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001251 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1252 * executed after peer structure is deleted.
1253 */
hassoe0701b72004-05-20 09:19:34 +00001254 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001255 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001256 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001257
1258 /* Password configuration */
1259 if (peer->password)
1260 {
1261 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1262 peer->password = NULL;
1263
1264 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1265 bgp_md5_set (peer);
1266 }
1267
Paul Jakmaca058a32006-09-14 02:58:49 +00001268 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001269
paul718e3742002-12-13 20:15:29 +00001270 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001271 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1272 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001273 {
Chris Caputo228da422009-07-18 05:44:03 +00001274 peer_unlock (peer); /* bgp peer list reference */
1275 list_delete_node (bgp->peer, pn);
1276 }
paul200df112005-06-01 11:17:05 +00001277
Chris Caputo228da422009-07-18 05:44:03 +00001278 if (peer_rsclient_active (peer)
1279 && (pn = listnode_lookup (bgp->rsclient, peer)))
1280 {
1281 peer_unlock (peer); /* rsclient list reference */
1282 list_delete_node (bgp->rsclient, pn);
1283
1284 /* Clear our own rsclient ribs. */
1285 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1286 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1287 if (CHECK_FLAG(peer->af_flags[afi][safi],
1288 PEER_FLAG_RSERVER_CLIENT))
1289 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001290 }
1291
1292 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1293 member of a peer_group. */
1294 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1295 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1296 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001297 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001298
paul200df112005-06-01 11:17:05 +00001299 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001300 if (peer->ibuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001301 {
1302 stream_free (peer->ibuf);
1303 peer->ibuf = NULL;
1304 }
1305
paul718e3742002-12-13 20:15:29 +00001306 if (peer->obuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001307 {
1308 stream_fifo_free (peer->obuf);
1309 peer->obuf = NULL;
1310 }
1311
paul718e3742002-12-13 20:15:29 +00001312 if (peer->work)
Daniel Walton363c9032015-10-21 06:42:54 -07001313 {
1314 stream_free (peer->work);
1315 peer->work = NULL;
1316 }
1317
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00001318 if (peer->scratch)
Daniel Walton363c9032015-10-21 06:42:54 -07001319 {
1320 stream_free(peer->scratch);
1321 peer->scratch = NULL;
1322 }
Paul Jakma18937402006-07-27 19:05:12 +00001323
paul718e3742002-12-13 20:15:29 +00001324 /* Local and remote addresses. */
1325 if (peer->su_local)
Daniel Walton363c9032015-10-21 06:42:54 -07001326 {
1327 sockunion_free (peer->su_local);
1328 peer->su_local = NULL;
1329 }
1330
paul718e3742002-12-13 20:15:29 +00001331 if (peer->su_remote)
Daniel Walton363c9032015-10-21 06:42:54 -07001332 {
1333 sockunion_free (peer->su_remote);
1334 peer->su_remote = NULL;
1335 }
paul200df112005-06-01 11:17:05 +00001336
paul718e3742002-12-13 20:15:29 +00001337 /* Free filter related memory. */
1338 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1339 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1340 {
1341 filter = &peer->filter[afi][safi];
1342
1343 for (i = FILTER_IN; i < FILTER_MAX; i++)
1344 {
1345 if (filter->dlist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001346 {
1347 free(filter->dlist[i].name);
1348 filter->dlist[i].name = NULL;
1349 }
1350
paul718e3742002-12-13 20:15:29 +00001351 if (filter->plist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001352 {
1353 free(filter->plist[i].name);
1354 filter->plist[i].name = NULL;
1355 }
1356
paul718e3742002-12-13 20:15:29 +00001357 if (filter->aslist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001358 {
1359 free(filter->aslist[i].name);
1360 filter->aslist[i].name = NULL;
1361 }
paul200df112005-06-01 11:17:05 +00001362 }
Daniel Walton363c9032015-10-21 06:42:54 -07001363
paul200df112005-06-01 11:17:05 +00001364 for (i = RMAP_IN; i < RMAP_MAX; i++)
1365 {
paul718e3742002-12-13 20:15:29 +00001366 if (filter->map[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001367 {
1368 free (filter->map[i].name);
1369 filter->map[i].name = NULL;
1370 }
paul718e3742002-12-13 20:15:29 +00001371 }
1372
1373 if (filter->usmap.name)
Daniel Walton363c9032015-10-21 06:42:54 -07001374 {
1375 free (filter->usmap.name);
1376 filter->usmap.name = NULL;
1377 }
paul718e3742002-12-13 20:15:29 +00001378
1379 if (peer->default_rmap[afi][safi].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001380 {
1381 free (peer->default_rmap[afi][safi].name);
1382 peer->default_rmap[afi][safi].name = NULL;
1383 }
paul718e3742002-12-13 20:15:29 +00001384 }
paul200df112005-06-01 11:17:05 +00001385
Lou Berger82dd7072016-01-12 13:41:57 -05001386 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETING))
1387 bgp_peer_clear_node_queue_drain_immediate(peer);
1388
paul200df112005-06-01 11:17:05 +00001389 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001390
1391 return 0;
1392}
David Lamparter6b0655a2014-06-04 06:53:35 +02001393
paul94f2b392005-06-28 12:44:16 +00001394static int
paul718e3742002-12-13 20:15:29 +00001395peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1396{
1397 return strcmp (g1->name, g2->name);
1398}
1399
1400/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001401static int
paul718e3742002-12-13 20:15:29 +00001402peer_group_active (struct peer *peer)
1403{
1404 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1405 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1406 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05001407 || peer->af_group[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00001408 || peer->af_group[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05001409 || peer->af_group[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05001410 || peer->af_group[AFI_IP6][SAFI_MPLS_VPN]
1411 || peer->af_group[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00001412 return 1;
1413 return 0;
1414}
1415
1416/* Peer group cofiguration. */
1417static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001418peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001419{
1420 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1421 sizeof (struct peer_group));
1422}
1423
paul94f2b392005-06-28 12:44:16 +00001424static void
paul718e3742002-12-13 20:15:29 +00001425peer_group_free (struct peer_group *group)
1426{
1427 XFREE (MTYPE_PEER_GROUP, group);
1428}
1429
1430struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001431peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001432{
1433 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001434 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001435
paul1eb8ef22005-04-07 07:30:20 +00001436 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001437 {
1438 if (strcmp (group->name, name) == 0)
1439 return group;
1440 }
1441 return NULL;
1442}
1443
1444struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001445peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001446{
1447 struct peer_group *group;
1448
1449 group = peer_group_lookup (bgp, name);
1450 if (group)
1451 return group;
1452
1453 group = peer_group_new ();
1454 group->bgp = bgp;
1455 group->name = strdup (name);
1456 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001457 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001458 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1459 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001460 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001461 group->conf->group = group;
1462 group->conf->as = 0;
1463 group->conf->ttl = 1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001464 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001465 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1466 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1467 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1468 group->conf->keepalive = 0;
1469 group->conf->holdtime = 0;
1470 group->conf->connect = 0;
1471 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1472 listnode_add_sort (bgp->group, group);
1473
1474 return 0;
1475}
1476
paul94f2b392005-06-28 12:44:16 +00001477static void
paul718e3742002-12-13 20:15:29 +00001478peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1479 afi_t afi, safi_t safi)
1480{
1481 int in = FILTER_IN;
1482 int out = FILTER_OUT;
1483 struct peer *conf;
1484 struct bgp_filter *pfilter;
1485 struct bgp_filter *gfilter;
1486
1487 conf = group->conf;
1488 pfilter = &peer->filter[afi][safi];
1489 gfilter = &conf->filter[afi][safi];
1490
1491 /* remote-as */
1492 if (conf->as)
1493 peer->as = conf->as;
1494
1495 /* remote-as */
1496 if (conf->change_local_as)
1497 peer->change_local_as = conf->change_local_as;
1498
1499 /* TTL */
1500 peer->ttl = conf->ttl;
1501
Nick Hilliardfa411a22011-03-23 15:33:17 +00001502 /* GTSM hops */
1503 peer->gtsm_hops = conf->gtsm_hops;
1504
paul718e3742002-12-13 20:15:29 +00001505 /* Weight */
1506 peer->weight = conf->weight;
1507
1508 /* peer flags apply */
1509 peer->flags = conf->flags;
1510 /* peer af_flags apply */
1511 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1512 /* peer config apply */
1513 peer->config = conf->config;
1514
1515 /* peer timers apply */
1516 peer->holdtime = conf->holdtime;
1517 peer->keepalive = conf->keepalive;
1518 peer->connect = conf->connect;
1519 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1520 peer->v_connect = conf->connect;
1521 else
1522 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1523
1524 /* advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +03001525 if (CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
1526 peer->v_routeadv = conf->routeadv;
paul718e3742002-12-13 20:15:29 +00001527 else
Daniel Walton0d7435f2015-10-22 11:35:20 +03001528 if (peer_sort (peer) == BGP_PEER_IBGP)
1529 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1530 else
1531 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul718e3742002-12-13 20:15:29 +00001532
Paul Jakma0df7c912008-07-21 21:02:49 +00001533 /* password apply */
Roman Hoog Antink0e4303d2013-01-18 13:52:03 +01001534 if (conf->password && !peer->password)
Paul Jakma0df7c912008-07-21 21:02:49 +00001535 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
Paul Jakma0df7c912008-07-21 21:02:49 +00001536
1537 bgp_md5_set (peer);
1538
paul718e3742002-12-13 20:15:29 +00001539 /* maximum-prefix */
1540 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001541 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001542 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001543
1544 /* allowas-in */
1545 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1546
paulfee0f4c2004-09-13 05:12:46 +00001547 /* route-server-client */
1548 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1549 {
1550 /* Make peer's RIB point to group's RIB. */
1551 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1552
1553 /* Import policy. */
1554 if (pfilter->map[RMAP_IMPORT].name)
1555 free (pfilter->map[RMAP_IMPORT].name);
1556 if (gfilter->map[RMAP_IMPORT].name)
1557 {
1558 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1559 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1560 }
1561 else
1562 {
1563 pfilter->map[RMAP_IMPORT].name = NULL;
1564 pfilter->map[RMAP_IMPORT].map = NULL;
1565 }
1566
1567 /* Export policy. */
1568 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1569 {
1570 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1571 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1572 }
1573 }
1574
paul718e3742002-12-13 20:15:29 +00001575 /* default-originate route-map */
1576 if (conf->default_rmap[afi][safi].name)
1577 {
1578 if (peer->default_rmap[afi][safi].name)
1579 free (peer->default_rmap[afi][safi].name);
1580 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1581 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1582 }
1583
1584 /* update-source apply */
1585 if (conf->update_source)
1586 {
1587 if (peer->update_source)
1588 sockunion_free (peer->update_source);
1589 if (peer->update_if)
1590 {
1591 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1592 peer->update_if = NULL;
1593 }
1594 peer->update_source = sockunion_dup (conf->update_source);
1595 }
1596 else if (conf->update_if)
1597 {
1598 if (peer->update_if)
1599 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1600 if (peer->update_source)
1601 {
1602 sockunion_free (peer->update_source);
1603 peer->update_source = NULL;
1604 }
1605 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1606 }
1607
1608 /* inbound filter apply */
1609 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1610 {
1611 if (pfilter->dlist[in].name)
1612 free (pfilter->dlist[in].name);
1613 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1614 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1615 }
1616 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1617 {
1618 if (pfilter->plist[in].name)
1619 free (pfilter->plist[in].name);
1620 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1621 pfilter->plist[in].plist = gfilter->plist[in].plist;
1622 }
1623 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1624 {
1625 if (pfilter->aslist[in].name)
1626 free (pfilter->aslist[in].name);
1627 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1628 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1629 }
paulfee0f4c2004-09-13 05:12:46 +00001630 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001631 {
paulfee0f4c2004-09-13 05:12:46 +00001632 if (pfilter->map[RMAP_IN].name)
1633 free (pfilter->map[RMAP_IN].name);
1634 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1635 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001636 }
1637
1638 /* outbound filter apply */
1639 if (gfilter->dlist[out].name)
1640 {
1641 if (pfilter->dlist[out].name)
1642 free (pfilter->dlist[out].name);
1643 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1644 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1645 }
1646 else
1647 {
1648 if (pfilter->dlist[out].name)
1649 free (pfilter->dlist[out].name);
1650 pfilter->dlist[out].name = NULL;
1651 pfilter->dlist[out].alist = NULL;
1652 }
1653 if (gfilter->plist[out].name)
1654 {
1655 if (pfilter->plist[out].name)
1656 free (pfilter->plist[out].name);
1657 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1658 pfilter->plist[out].plist = gfilter->plist[out].plist;
1659 }
1660 else
1661 {
1662 if (pfilter->plist[out].name)
1663 free (pfilter->plist[out].name);
1664 pfilter->plist[out].name = NULL;
1665 pfilter->plist[out].plist = NULL;
1666 }
1667 if (gfilter->aslist[out].name)
1668 {
1669 if (pfilter->aslist[out].name)
1670 free (pfilter->aslist[out].name);
1671 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1672 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1673 }
1674 else
1675 {
1676 if (pfilter->aslist[out].name)
1677 free (pfilter->aslist[out].name);
1678 pfilter->aslist[out].name = NULL;
1679 pfilter->aslist[out].aslist = NULL;
1680 }
paulfee0f4c2004-09-13 05:12:46 +00001681 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001682 {
paulfee0f4c2004-09-13 05:12:46 +00001683 if (pfilter->map[RMAP_OUT].name)
1684 free (pfilter->map[RMAP_OUT].name);
1685 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1686 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001687 }
1688 else
1689 {
paulfee0f4c2004-09-13 05:12:46 +00001690 if (pfilter->map[RMAP_OUT].name)
1691 free (pfilter->map[RMAP_OUT].name);
1692 pfilter->map[RMAP_OUT].name = NULL;
1693 pfilter->map[RMAP_OUT].map = NULL;
1694 }
1695
1696 /* RS-client's import/export route-maps. */
1697 if (gfilter->map[RMAP_IMPORT].name)
1698 {
1699 if (pfilter->map[RMAP_IMPORT].name)
1700 free (pfilter->map[RMAP_IMPORT].name);
1701 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1702 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1703 }
1704 else
1705 {
1706 if (pfilter->map[RMAP_IMPORT].name)
1707 free (pfilter->map[RMAP_IMPORT].name);
1708 pfilter->map[RMAP_IMPORT].name = NULL;
1709 pfilter->map[RMAP_IMPORT].map = NULL;
1710 }
1711 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1712 {
1713 if (pfilter->map[RMAP_EXPORT].name)
1714 free (pfilter->map[RMAP_EXPORT].name);
1715 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1716 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001717 }
1718
1719 if (gfilter->usmap.name)
1720 {
1721 if (pfilter->usmap.name)
1722 free (pfilter->usmap.name);
1723 pfilter->usmap.name = strdup (gfilter->usmap.name);
1724 pfilter->usmap.map = gfilter->usmap.map;
1725 }
1726 else
1727 {
1728 if (pfilter->usmap.name)
1729 free (pfilter->usmap.name);
1730 pfilter->usmap.name = NULL;
1731 pfilter->usmap.map = NULL;
1732 }
1733}
1734
1735/* Peer group's remote AS configuration. */
1736int
paulfd79ac92004-10-13 05:06:08 +00001737peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001738{
1739 struct peer_group *group;
1740 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001741 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001742
1743 group = peer_group_lookup (bgp, group_name);
1744 if (! group)
1745 return -1;
1746
1747 if (group->conf->as == *as)
1748 return 0;
1749
1750 /* When we setup peer-group AS number all peer group member's AS
1751 number must be updated to same number. */
1752 peer_as_change (group->conf, *as);
1753
paul1eb8ef22005-04-07 07:30:20 +00001754 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001755 {
1756 if (peer->as != *as)
1757 peer_as_change (peer, *as);
1758 }
1759
1760 return 0;
1761}
1762
1763int
1764peer_group_delete (struct peer_group *group)
1765{
1766 struct bgp *bgp;
1767 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001768 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001769
1770 bgp = group->bgp;
1771
paul1eb8ef22005-04-07 07:30:20 +00001772 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001773 {
paul718e3742002-12-13 20:15:29 +00001774 peer_delete (peer);
1775 }
1776 list_delete (group->peer);
1777
1778 free (group->name);
1779 group->name = NULL;
1780
1781 group->conf->group = NULL;
1782 peer_delete (group->conf);
1783
1784 /* Delete from all peer_group list. */
1785 listnode_delete (bgp->group, group);
1786
1787 peer_group_free (group);
1788
1789 return 0;
1790}
1791
1792int
1793peer_group_remote_as_delete (struct peer_group *group)
1794{
1795 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001796 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001797
1798 if (! group->conf->as)
1799 return 0;
1800
paul1eb8ef22005-04-07 07:30:20 +00001801 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001802 {
paul718e3742002-12-13 20:15:29 +00001803 peer_delete (peer);
1804 }
1805 list_delete_all_node (group->peer);
1806
1807 group->conf->as = 0;
1808
1809 return 0;
1810}
1811
1812/* Bind specified peer to peer group. */
1813int
1814peer_group_bind (struct bgp *bgp, union sockunion *su,
1815 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1816{
1817 struct peer *peer;
1818 int first_member = 0;
1819
1820 /* Check peer group's address family. */
1821 if (! group->conf->afc[afi][safi])
1822 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1823
1824 /* Lookup the peer. */
1825 peer = peer_lookup (bgp, su);
1826
1827 /* Create a new peer. */
1828 if (! peer)
1829 {
1830 if (! group->conf->as)
1831 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1832
1833 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1834 peer->group = group;
1835 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001836
Paul Jakmaca058a32006-09-14 02:58:49 +00001837 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001838 listnode_add (group->peer, peer);
1839 peer_group2peer_config_copy (group, peer, afi, safi);
1840
1841 return 0;
1842 }
1843
1844 /* When the peer already belongs to peer group, check the consistency. */
1845 if (peer->af_group[afi][safi])
1846 {
1847 if (strcmp (peer->group->name, group->name) != 0)
1848 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1849
1850 return 0;
1851 }
1852
1853 /* Check current peer group configuration. */
1854 if (peer_group_active (peer)
1855 && strcmp (peer->group->name, group->name) != 0)
1856 return BGP_ERR_PEER_GROUP_MISMATCH;
1857
1858 if (! group->conf->as)
1859 {
1860 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1861 && peer_sort (group->conf) != peer_sort (peer))
1862 {
1863 if (as)
1864 *as = peer->as;
1865 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1866 }
1867
1868 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1869 first_member = 1;
1870 }
1871
1872 peer->af_group[afi][safi] = 1;
1873 peer->afc[afi][safi] = 1;
1874 if (! peer->group)
1875 {
1876 peer->group = group;
paul200df112005-06-01 11:17:05 +00001877
Paul Jakmaca058a32006-09-14 02:58:49 +00001878 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001879 listnode_add (group->peer, peer);
1880 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001881 else
1882 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001883
1884 if (first_member)
1885 {
1886 /* Advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +03001887 if (! CHECK_FLAG (group->conf->config, PEER_CONFIG_ROUTEADV))
1888 {
1889 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1890 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1891 else
1892 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1893 }
paul718e3742002-12-13 20:15:29 +00001894
1895 /* ebgp-multihop reset */
1896 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1897 group->conf->ttl = 255;
1898
1899 /* local-as reset */
1900 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1901 {
1902 group->conf->change_local_as = 0;
1903 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001904 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001905 }
1906 }
paulfee0f4c2004-09-13 05:12:46 +00001907
1908 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1909 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001910 struct listnode *pn;
1911
paulfee0f4c2004-09-13 05:12:46 +00001912 /* If it's not configured as RSERVER_CLIENT in any other address
1913 family, without being member of a peer_group, remove it from
1914 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001915 if (! peer_rsclient_active (peer)
1916 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001917 {
1918 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001919 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001920
1921 /* Clear our own rsclient rib for this afi/safi. */
1922 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001923 }
paulfee0f4c2004-09-13 05:12:46 +00001924
Paul Jakmab608d5b2008-07-02 02:12:07 +00001925 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001926
1927 /* Import policy. */
1928 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1929 {
1930 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1931 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1932 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1933 }
1934
1935 /* Export policy. */
1936 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1937 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1938 {
1939 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1940 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1941 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1942 }
1943 }
1944
paul718e3742002-12-13 20:15:29 +00001945 peer_group2peer_config_copy (group, peer, afi, safi);
1946
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001947 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001948 {
1949 peer->last_reset = PEER_DOWN_RMAP_BIND;
1950 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1951 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1952 }
paul718e3742002-12-13 20:15:29 +00001953 else
1954 BGP_EVENT_ADD (peer, BGP_Stop);
1955
1956 return 0;
1957}
1958
1959int
1960peer_group_unbind (struct bgp *bgp, struct peer *peer,
1961 struct peer_group *group, afi_t afi, safi_t safi)
1962{
1963 if (! peer->af_group[afi][safi])
1964 return 0;
1965
1966 if (group != peer->group)
1967 return BGP_ERR_PEER_GROUP_MISMATCH;
1968
1969 peer->af_group[afi][safi] = 0;
1970 peer->afc[afi][safi] = 0;
1971 peer_af_flag_reset (peer, afi, safi);
1972
paulfee0f4c2004-09-13 05:12:46 +00001973 if (peer->rib[afi][safi])
1974 peer->rib[afi][safi] = NULL;
1975
paul718e3742002-12-13 20:15:29 +00001976 if (! peer_group_active (peer))
1977 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001978 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001979 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001980 listnode_delete (group->peer, peer);
1981 peer->group = NULL;
1982 if (group->conf->as)
1983 {
1984 peer_delete (peer);
1985 return 0;
1986 }
1987 peer_global_config_reset (peer);
1988 }
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_UNBIND;
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}
David Lamparter6b0655a2014-06-04 06:53:35 +02002001
Vipin Kumardd49eb12014-09-30 14:36:38 -07002002
2003static int
2004bgp_startup_timer_expire (struct thread *thread)
2005{
2006 struct bgp *bgp;
2007
2008 bgp = THREAD_ARG (thread);
2009 bgp->t_startup = NULL;
2010
2011 return 0;
2012}
2013
paul718e3742002-12-13 20:15:29 +00002014/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00002015static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002016bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002017{
2018 struct bgp *bgp;
2019 afi_t afi;
2020 safi_t safi;
2021
paul200df112005-06-01 11:17:05 +00002022 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
2023 return NULL;
2024
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002025 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00002026 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00002027 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00002028
2029 bgp->peer = list_new ();
2030 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
2031
2032 bgp->group = list_new ();
2033 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
2034
paulfee0f4c2004-09-13 05:12:46 +00002035 bgp->rsclient = list_new ();
2036 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
2037
paul718e3742002-12-13 20:15:29 +00002038 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2039 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2040 {
Paul Jakma64e580a2006-02-21 01:09:01 +00002041 bgp->route[afi][safi] = bgp_table_init (afi, safi);
2042 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
2043 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07002044 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
2045 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00002046 }
2047
2048 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
2049 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
2050 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00002051 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
2052 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07002053 bgp_flag_set (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES);
paul718e3742002-12-13 20:15:29 +00002054
2055 bgp->as = *as;
2056
2057 if (name)
2058 bgp->name = strdup (name);
2059
Donald Sharp774914f2015-10-14 08:50:39 -04002060 THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire,
Vipin Kumardd49eb12014-09-30 14:36:38 -07002061 bgp, bgp->restart_time);
2062
paul718e3742002-12-13 20:15:29 +00002063 return bgp;
2064}
2065
2066/* Return first entry of BGP. */
2067struct bgp *
paul94f2b392005-06-28 12:44:16 +00002068bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00002069{
Lou Berger056f3762013-04-10 12:30:04 -07002070 if (bm && bm->bgp && bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00002071 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00002072 return NULL;
2073}
2074
2075/* Lookup BGP entry. */
2076struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002077bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00002078{
2079 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002080 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002081
paul1eb8ef22005-04-07 07:30:20 +00002082 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002083 if (bgp->as == as
2084 && ((bgp->name == NULL && name == NULL)
2085 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
2086 return bgp;
2087 return NULL;
2088}
2089
2090/* Lookup BGP structure by view name. */
2091struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002092bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002093{
2094 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002095 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002096
paul1eb8ef22005-04-07 07:30:20 +00002097 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002098 if ((bgp->name == NULL && name == NULL)
2099 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2100 return bgp;
2101 return NULL;
2102}
2103
2104/* Called from VTY commands. */
2105int
paulfd79ac92004-10-13 05:06:08 +00002106bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002107{
2108 struct bgp *bgp;
2109
2110 /* Multiple instance check. */
2111 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2112 {
2113 if (name)
2114 bgp = bgp_lookup_by_name (name);
2115 else
2116 bgp = bgp_get_default ();
2117
2118 /* Already exists. */
2119 if (bgp)
2120 {
2121 if (bgp->as != *as)
2122 {
2123 *as = bgp->as;
2124 return BGP_ERR_INSTANCE_MISMATCH;
2125 }
2126 *bgp_val = bgp;
2127 return 0;
2128 }
2129 }
2130 else
2131 {
2132 /* BGP instance name can not be specified for single instance. */
2133 if (name)
2134 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2135
2136 /* Get default BGP structure if exists. */
2137 bgp = bgp_get_default ();
2138
2139 if (bgp)
2140 {
2141 if (bgp->as != *as)
2142 {
2143 *as = bgp->as;
2144 return BGP_ERR_AS_MISMATCH;
2145 }
2146 *bgp_val = bgp;
2147 return 0;
2148 }
2149 }
2150
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002151 bgp = bgp_create (as, name);
2152 bgp_router_id_set(bgp, &router_id_zebra);
2153 *bgp_val = bgp;
2154
Paul Jakmaad12dde2012-06-13 22:50:07 +01002155 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002156 if (list_isempty(bm->bgp)
2157 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002158 {
2159 if (bgp_socket (bm->port, bm->address) < 0)
2160 return BGP_ERR_INVALID_VALUE;
2161 }
2162
paul718e3742002-12-13 20:15:29 +00002163 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002164
2165 return 0;
2166}
2167
2168/* Delete BGP instance. */
2169int
2170bgp_delete (struct bgp *bgp)
2171{
2172 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002173 struct peer_group *group;
Denil Vira57cd5e72015-08-10 12:46:14 -07002174 struct listnode *node, *pnode;
2175 struct listnode *next, *pnext;
paul718e3742002-12-13 20:15:29 +00002176 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002177 int i;
2178
Lou Berger82dd7072016-01-12 13:41:57 -05002179 SET_FLAG(bgp->flags, BGP_FLAG_DELETING);
2180
David Lampartercffe7802014-12-07 03:27:13 +01002181 THREAD_OFF (bgp->t_startup);
2182
paul718e3742002-12-13 20:15:29 +00002183 /* Delete static route. */
2184 bgp_static_delete (bgp);
2185
2186 /* Unset redistribution. */
2187 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2188 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2189 if (i != ZEBRA_ROUTE_BGP)
2190 bgp_redistribute_unset (bgp, afi, i);
2191
paul1eb8ef22005-04-07 07:30:20 +00002192 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002193 {
2194 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2195 {
2196 /* Send notify to remote peer. */
2197 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2198 }
2199
2200 peer_delete (peer);
2201 }
paul718e3742002-12-13 20:15:29 +00002202
Chris Caputo228da422009-07-18 05:44:03 +00002203 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002204 {
Denil Vira57cd5e72015-08-10 12:46:14 -07002205 for (ALL_LIST_ELEMENTS (group->peer, pnode, pnext, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002206 {
2207 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2208 {
2209 /* Send notify to remote peer. */
2210 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2211 }
2212 }
2213 peer_group_delete (group);
2214 }
Chris Caputo228da422009-07-18 05:44:03 +00002215
2216 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002217
2218 if (bgp->peer_self) {
2219 peer_delete(bgp->peer_self);
2220 bgp->peer_self = NULL;
2221 }
Lou Berger82dd7072016-01-12 13:41:57 -05002222
2223 /*
2224 * Free pending deleted routes. Unfortunately, it also has to process
2225 * all the pending activity for other instances of struct bgp.
2226 *
2227 * This call was added to achieve clean memory allocation at exit,
2228 * for the sake of valgrind.
2229 */
2230 bgp_process_queues_drain_immediate();
2231
2232 bgp_zebra_destroy();
2233 bgp_scan_destroy();
2234 bgp_address_destroy();
Paul Jakmafd35b942009-07-16 19:27:32 +01002235
Lou Berger82dd7072016-01-12 13:41:57 -05002236
Paul Jakmafd35b942009-07-16 19:27:32 +01002237 /* Remove visibility via the master list - there may however still be
2238 * routes to be processed still referencing the struct bgp.
2239 */
2240 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002241 if (list_isempty(bm->bgp))
2242 bgp_close ();
2243
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002244 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002245
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002246 return 0;
2247}
2248
2249static void bgp_free (struct bgp *);
2250
2251void
2252bgp_lock (struct bgp *bgp)
2253{
2254 ++bgp->lock;
2255}
2256
2257void
2258bgp_unlock(struct bgp *bgp)
2259{
Chris Caputo228da422009-07-18 05:44:03 +00002260 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002261 if (--bgp->lock == 0)
2262 bgp_free (bgp);
2263}
2264
2265static void
2266bgp_free (struct bgp *bgp)
2267{
2268 afi_t afi;
2269 safi_t safi;
2270
2271 list_delete (bgp->group);
2272 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002273 list_delete (bgp->rsclient);
2274
paul718e3742002-12-13 20:15:29 +00002275 if (bgp->name)
2276 free (bgp->name);
2277
2278 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2279 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2280 {
2281 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002282 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002283 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002284 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002285 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002286 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002287 }
2288 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002289}
David Lamparter6b0655a2014-06-04 06:53:35 +02002290
paul718e3742002-12-13 20:15:29 +00002291struct peer *
2292peer_lookup (struct bgp *bgp, union sockunion *su)
2293{
2294 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002295 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002296
Steve Hillfc4dc592009-07-28 17:54:35 +01002297 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002298 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002299 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2300 if (sockunion_same (&peer->su, su)
2301 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2302 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002303 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002304 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002305 {
2306 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002307
Paul Jakma2158ad22009-07-28 18:10:55 +01002308 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2309 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2310 if (sockunion_same (&peer->su, su)
2311 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2312 return peer;
paul718e3742002-12-13 20:15:29 +00002313 }
2314 return NULL;
2315}
2316
2317struct peer *
2318peer_lookup_with_open (union sockunion *su, as_t remote_as,
2319 struct in_addr *remote_id, int *as)
2320{
2321 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002322 struct listnode *node;
2323 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002324 struct bgp *bgp;
2325
Steve Hillfc4dc592009-07-28 17:54:35 +01002326 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002327 return NULL;
2328
Paul Jakma9d878772009-08-05 16:25:16 +01002329 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002330 {
Paul Jakma9d878772009-08-05 16:25:16 +01002331 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2332 {
2333 if (sockunion_same (&peer->su, su)
2334 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2335 {
2336 if (peer->as == remote_as
2337 && peer->remote_id.s_addr == remote_id->s_addr)
2338 return peer;
2339 if (peer->as == remote_as)
2340 *as = 1;
2341 }
2342 }
2343
2344 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2345 {
2346 if (sockunion_same (&peer->su, su)
2347 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2348 {
2349 if (peer->as == remote_as
2350 && peer->remote_id.s_addr == 0)
2351 return peer;
2352 if (peer->as == remote_as)
2353 *as = 1;
2354 }
2355 }
paul718e3742002-12-13 20:15:29 +00002356 }
2357 return NULL;
2358}
David Lamparter6b0655a2014-06-04 06:53:35 +02002359
paul718e3742002-12-13 20:15:29 +00002360/* If peer is configured at least one address family return 1. */
2361int
2362peer_active (struct peer *peer)
2363{
2364 if (peer->afc[AFI_IP][SAFI_UNICAST]
2365 || peer->afc[AFI_IP][SAFI_MULTICAST]
2366 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05002367 || peer->afc[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00002368 || peer->afc[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05002369 || peer->afc[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05002370 || peer->afc[AFI_IP6][SAFI_MPLS_VPN]
2371 || peer->afc[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00002372 return 1;
2373 return 0;
2374}
2375
2376/* If peer is negotiated at least one address family return 1. */
2377int
2378peer_active_nego (struct peer *peer)
2379{
2380 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2381 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2382 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05002383 || peer->afc_nego[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00002384 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05002385 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05002386 || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
2387 || peer->afc_nego[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00002388 return 1;
2389 return 0;
2390}
David Lamparter6b0655a2014-06-04 06:53:35 +02002391
paul718e3742002-12-13 20:15:29 +00002392/* peer_flag_change_type. */
2393enum peer_change_type
2394{
2395 peer_change_none,
2396 peer_change_reset,
2397 peer_change_reset_in,
2398 peer_change_reset_out,
2399};
2400
paul94f2b392005-06-28 12:44:16 +00002401static void
paul718e3742002-12-13 20:15:29 +00002402peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2403 enum peer_change_type type)
2404{
2405 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2406 return;
2407
Stephen Hemmingerd9d4ae52010-01-13 00:32:39 +00002408 if (peer->status != Established)
2409 return;
2410
paul718e3742002-12-13 20:15:29 +00002411 if (type == peer_change_reset)
2412 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2413 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2414 else if (type == peer_change_reset_in)
2415 {
2416 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2417 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2418 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2419 else
2420 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2421 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2422 }
2423 else if (type == peer_change_reset_out)
2424 bgp_announce_route (peer, afi, safi);
2425}
2426
2427struct peer_flag_action
2428{
2429 /* Peer's flag. */
2430 u_int32_t flag;
2431
2432 /* This flag can be set for peer-group member. */
2433 u_char not_for_member;
2434
2435 /* Action when the flag is changed. */
2436 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002437
2438 /* Peer down cause */
2439 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002440};
2441
Stephen Hemminger03621952009-07-21 16:27:20 -07002442static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002443 {
2444 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2445 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2446 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2447 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2448 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002449 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002450 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002451 { 0, 0, 0 }
2452 };
2453
Stephen Hemminger03621952009-07-21 16:27:20 -07002454static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002455 {
2456 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2457 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2458 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2459 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2460 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2461 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2462 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2463 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2464 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2465 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2466 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2467 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2468 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002469 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
Timo Teräs9e7a53c2014-04-24 10:22:37 +03002470 { PEER_FLAG_NEXTHOP_SELF_ALL, 1, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002471 { 0, 0, 0 }
2472 };
2473
2474/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002475static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002476peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002477 struct peer_flag_action *action, u_int32_t flag)
2478{
2479 int i;
2480 int found = 0;
2481 int reset_in = 0;
2482 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002483 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002484
2485 /* Check peer's frag action. */
2486 for (i = 0; i < size; i++)
2487 {
2488 match = &action_list[i];
2489
2490 if (match->flag == 0)
2491 break;
2492
2493 if (match->flag & flag)
2494 {
2495 found = 1;
2496
2497 if (match->type == peer_change_reset_in)
2498 reset_in = 1;
2499 if (match->type == peer_change_reset_out)
2500 reset_out = 1;
2501 if (match->type == peer_change_reset)
2502 {
2503 reset_in = 1;
2504 reset_out = 1;
2505 }
2506 if (match->not_for_member)
2507 action->not_for_member = 1;
2508 }
2509 }
2510
2511 /* Set peer clear type. */
2512 if (reset_in && reset_out)
2513 action->type = peer_change_reset;
2514 else if (reset_in)
2515 action->type = peer_change_reset_in;
2516 else if (reset_out)
2517 action->type = peer_change_reset_out;
2518 else
2519 action->type = peer_change_none;
2520
2521 return found;
2522}
2523
paul94f2b392005-06-28 12:44:16 +00002524static void
paul718e3742002-12-13 20:15:29 +00002525peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2526{
2527 if (flag == PEER_FLAG_SHUTDOWN)
2528 {
2529 if (CHECK_FLAG (peer->flags, flag))
2530 {
hasso93406d82005-02-02 14:40:33 +00002531 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2532 peer_nsf_stop (peer);
2533
hasso0a486e52005-02-01 20:57:17 +00002534 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2535 if (peer->t_pmax_restart)
2536 {
2537 BGP_TIMER_OFF (peer->t_pmax_restart);
2538 if (BGP_DEBUG (events, EVENTS))
2539 zlog_debug ("%s Maximum-prefix restart timer canceled",
2540 peer->host);
2541 }
2542
hasso93406d82005-02-02 14:40:33 +00002543 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2544 peer_nsf_stop (peer);
2545
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002546 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002547 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2548 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2549 else
2550 BGP_EVENT_ADD (peer, BGP_Stop);
2551 }
2552 else
2553 {
2554 peer->v_start = BGP_INIT_START_TIMER;
2555 BGP_EVENT_ADD (peer, BGP_Stop);
2556 }
2557 }
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002558 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002559 {
hassoc9502432005-02-01 22:01:48 +00002560 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2561 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2562 else if (flag == PEER_FLAG_PASSIVE)
2563 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002564 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002565 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002566
hassoc9502432005-02-01 22:01:48 +00002567 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2568 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002569 }
2570 else
2571 BGP_EVENT_ADD (peer, BGP_Stop);
2572}
2573
2574/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002575static int
paul718e3742002-12-13 20:15:29 +00002576peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2577{
2578 int found;
2579 int size;
2580 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002581 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002582 struct peer_flag_action action;
2583
2584 memset (&action, 0, sizeof (struct peer_flag_action));
2585 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2586
2587 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2588
2589 /* No flag action is found. */
2590 if (! found)
2591 return BGP_ERR_INVALID_FLAG;
2592
2593 /* Not for peer-group member. */
2594 if (action.not_for_member && peer_group_active (peer))
2595 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2596
2597 /* When unset the peer-group member's flag we have to check
2598 peer-group configuration. */
2599 if (! set && peer_group_active (peer))
2600 if (CHECK_FLAG (peer->group->conf->flags, flag))
2601 {
2602 if (flag == PEER_FLAG_SHUTDOWN)
2603 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2604 else
2605 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2606 }
2607
2608 /* Flag conflict check. */
2609 if (set
2610 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2611 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2612 return BGP_ERR_PEER_FLAG_CONFLICT;
2613
2614 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2615 {
2616 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2617 return 0;
2618 if (! set && ! CHECK_FLAG (peer->flags, flag))
2619 return 0;
2620 }
2621
2622 if (set)
2623 SET_FLAG (peer->flags, flag);
2624 else
2625 UNSET_FLAG (peer->flags, flag);
2626
2627 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2628 {
2629 if (action.type == peer_change_reset)
2630 peer_flag_modify_action (peer, flag);
2631
2632 return 0;
2633 }
2634
2635 /* peer-group member updates. */
2636 group = peer->group;
2637
paul1eb8ef22005-04-07 07:30:20 +00002638 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002639 {
2640 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2641 continue;
2642
2643 if (! set && ! CHECK_FLAG (peer->flags, flag))
2644 continue;
2645
2646 if (set)
2647 SET_FLAG (peer->flags, flag);
2648 else
2649 UNSET_FLAG (peer->flags, flag);
2650
2651 if (action.type == peer_change_reset)
2652 peer_flag_modify_action (peer, flag);
2653 }
2654 return 0;
2655}
2656
2657int
2658peer_flag_set (struct peer *peer, u_int32_t flag)
2659{
2660 return peer_flag_modify (peer, flag, 1);
2661}
2662
2663int
2664peer_flag_unset (struct peer *peer, u_int32_t flag)
2665{
2666 return peer_flag_modify (peer, flag, 0);
2667}
2668
paul94f2b392005-06-28 12:44:16 +00002669static int
paul718e3742002-12-13 20:15:29 +00002670peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2671{
2672 if (peer->af_group[afi][safi])
2673 return 1;
2674 return 0;
2675}
2676
paul94f2b392005-06-28 12:44:16 +00002677static int
paul718e3742002-12-13 20:15:29 +00002678peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2679 int set)
2680{
2681 int found;
2682 int size;
paul1eb8ef22005-04-07 07:30:20 +00002683 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002684 struct peer_group *group;
2685 struct peer_flag_action action;
2686
2687 memset (&action, 0, sizeof (struct peer_flag_action));
2688 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2689
2690 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2691
2692 /* No flag action is found. */
2693 if (! found)
2694 return BGP_ERR_INVALID_FLAG;
2695
2696 /* Adress family must be activated. */
2697 if (! peer->afc[afi][safi])
2698 return BGP_ERR_PEER_INACTIVE;
2699
2700 /* Not for peer-group member. */
2701 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2702 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2703
2704 /* Spcecial check for reflector client. */
2705 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2706 && peer_sort (peer) != BGP_PEER_IBGP)
2707 return BGP_ERR_NOT_INTERNAL_PEER;
2708
2709 /* Spcecial check for remove-private-AS. */
2710 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2711 && peer_sort (peer) == BGP_PEER_IBGP)
2712 return BGP_ERR_REMOVE_PRIVATE_AS;
2713
2714 /* When unset the peer-group member's flag we have to check
2715 peer-group configuration. */
2716 if (! set && peer->af_group[afi][safi])
2717 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2718 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2719
2720 /* When current flag configuration is same as requested one. */
2721 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2722 {
2723 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2724 return 0;
2725 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2726 return 0;
2727 }
2728
2729 if (set)
2730 SET_FLAG (peer->af_flags[afi][safi], flag);
2731 else
2732 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2733
2734 /* Execute action when peer is established. */
2735 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2736 && peer->status == Established)
2737 {
2738 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2739 bgp_clear_adj_in (peer, afi, safi);
2740 else
hassoe0701b72004-05-20 09:19:34 +00002741 {
2742 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2743 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2744 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2745 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2746 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2747 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2748 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2749 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2750
2751 peer_change_action (peer, afi, safi, action.type);
2752 }
2753
paul718e3742002-12-13 20:15:29 +00002754 }
2755
2756 /* Peer group member updates. */
2757 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2758 {
2759 group = peer->group;
2760
paul1eb8ef22005-04-07 07:30:20 +00002761 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002762 {
2763 if (! peer->af_group[afi][safi])
2764 continue;
2765
2766 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2767 continue;
2768
2769 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2770 continue;
2771
2772 if (set)
2773 SET_FLAG (peer->af_flags[afi][safi], flag);
2774 else
2775 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2776
2777 if (peer->status == Established)
2778 {
2779 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2780 bgp_clear_adj_in (peer, afi, safi);
2781 else
hassoe0701b72004-05-20 09:19:34 +00002782 {
2783 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2784 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2785 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2786 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2787 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2788 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2789 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2790 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2791
2792 peer_change_action (peer, afi, safi, action.type);
2793 }
paul718e3742002-12-13 20:15:29 +00002794 }
2795 }
2796 }
2797 return 0;
2798}
2799
2800int
2801peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2802{
2803 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2804}
2805
2806int
2807peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2808{
2809 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2810}
David Lamparter6b0655a2014-06-04 06:53:35 +02002811
paul718e3742002-12-13 20:15:29 +00002812/* EBGP multihop configuration. */
2813int
2814peer_ebgp_multihop_set (struct peer *peer, int ttl)
2815{
2816 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002817 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002818 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002819
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002820 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002821 return 0;
2822
Nick Hilliardfa411a22011-03-23 15:33:17 +00002823 /* see comment in peer_ttl_security_hops_set() */
2824 if (ttl != MAXTTL)
2825 {
2826 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2827 {
2828 group = peer->group;
2829 if (group->conf->gtsm_hops != 0)
2830 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2831
2832 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2833 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002834 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002835 continue;
2836
2837 if (peer1->gtsm_hops != 0)
2838 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2839 }
2840 }
2841 else
2842 {
2843 if (peer->gtsm_hops != 0)
2844 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2845 }
2846 }
2847
paul718e3742002-12-13 20:15:29 +00002848 peer->ttl = ttl;
2849
2850 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2851 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002852 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002853 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002854 }
2855 else
2856 {
2857 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002858 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002859 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002860 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002861 continue;
paul718e3742002-12-13 20:15:29 +00002862
pauleb821182004-05-01 08:44:08 +00002863 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002864
pauleb821182004-05-01 08:44:08 +00002865 if (peer->fd >= 0)
2866 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2867 }
paul718e3742002-12-13 20:15:29 +00002868 }
2869 return 0;
2870}
2871
2872int
2873peer_ebgp_multihop_unset (struct peer *peer)
2874{
2875 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002876 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002877
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002878 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002879 return 0;
2880
Nick Hilliardfa411a22011-03-23 15:33:17 +00002881 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2882 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2883
paul718e3742002-12-13 20:15:29 +00002884 if (peer_group_active (peer))
2885 peer->ttl = peer->group->conf->ttl;
2886 else
2887 peer->ttl = 1;
2888
2889 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2890 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002891 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002892 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002893 }
2894 else
2895 {
2896 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002897 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002898 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002899 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002900 continue;
paul718e3742002-12-13 20:15:29 +00002901
pauleb821182004-05-01 08:44:08 +00002902 peer->ttl = 1;
2903
2904 if (peer->fd >= 0)
2905 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2906 }
paul718e3742002-12-13 20:15:29 +00002907 }
2908 return 0;
2909}
David Lamparter6b0655a2014-06-04 06:53:35 +02002910
paul718e3742002-12-13 20:15:29 +00002911/* Neighbor description. */
2912int
2913peer_description_set (struct peer *peer, char *desc)
2914{
2915 if (peer->desc)
2916 XFREE (MTYPE_PEER_DESC, peer->desc);
2917
2918 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2919
2920 return 0;
2921}
2922
2923int
2924peer_description_unset (struct peer *peer)
2925{
2926 if (peer->desc)
2927 XFREE (MTYPE_PEER_DESC, peer->desc);
2928
2929 peer->desc = NULL;
2930
2931 return 0;
2932}
David Lamparter6b0655a2014-06-04 06:53:35 +02002933
paul718e3742002-12-13 20:15:29 +00002934/* Neighbor update-source. */
2935int
paulfd79ac92004-10-13 05:06:08 +00002936peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002937{
2938 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002939 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002940
2941 if (peer->update_if)
2942 {
2943 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2944 && strcmp (peer->update_if, ifname) == 0)
2945 return 0;
2946
2947 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2948 peer->update_if = NULL;
2949 }
2950
2951 if (peer->update_source)
2952 {
2953 sockunion_free (peer->update_source);
2954 peer->update_source = NULL;
2955 }
2956
2957 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2958
2959 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2960 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002961 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002962 {
2963 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2964 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2965 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2966 }
paul718e3742002-12-13 20:15:29 +00002967 else
2968 BGP_EVENT_ADD (peer, BGP_Stop);
2969 return 0;
2970 }
2971
2972 /* peer-group member updates. */
2973 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002974 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002975 {
2976 if (peer->update_if)
2977 {
2978 if (strcmp (peer->update_if, ifname) == 0)
2979 continue;
2980
2981 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2982 peer->update_if = NULL;
2983 }
2984
2985 if (peer->update_source)
2986 {
2987 sockunion_free (peer->update_source);
2988 peer->update_source = NULL;
2989 }
2990
2991 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2992
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002993 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002994 {
2995 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2996 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2997 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2998 }
paul718e3742002-12-13 20:15:29 +00002999 else
3000 BGP_EVENT_ADD (peer, BGP_Stop);
3001 }
3002 return 0;
3003}
3004
3005int
3006peer_update_source_addr_set (struct peer *peer, union sockunion *su)
3007{
3008 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003009 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003010
3011 if (peer->update_source)
3012 {
3013 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3014 && sockunion_cmp (peer->update_source, su) == 0)
3015 return 0;
3016 sockunion_free (peer->update_source);
3017 peer->update_source = NULL;
3018 }
3019
3020 if (peer->update_if)
3021 {
3022 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3023 peer->update_if = NULL;
3024 }
3025
3026 peer->update_source = sockunion_dup (su);
3027
3028 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3029 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003030 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003031 {
3032 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3033 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3034 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3035 }
paul718e3742002-12-13 20:15:29 +00003036 else
3037 BGP_EVENT_ADD (peer, BGP_Stop);
3038 return 0;
3039 }
3040
3041 /* peer-group member updates. */
3042 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003043 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003044 {
3045 if (peer->update_source)
3046 {
3047 if (sockunion_cmp (peer->update_source, su) == 0)
3048 continue;
3049 sockunion_free (peer->update_source);
3050 peer->update_source = NULL;
3051 }
3052
3053 if (peer->update_if)
3054 {
3055 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3056 peer->update_if = NULL;
3057 }
3058
3059 peer->update_source = sockunion_dup (su);
3060
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003061 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003062 {
3063 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3064 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3065 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3066 }
paul718e3742002-12-13 20:15:29 +00003067 else
3068 BGP_EVENT_ADD (peer, BGP_Stop);
3069 }
3070 return 0;
3071}
3072
3073int
3074peer_update_source_unset (struct peer *peer)
3075{
3076 union sockunion *su;
3077 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003078 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003079
3080 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3081 && ! peer->update_source
3082 && ! peer->update_if)
3083 return 0;
3084
3085 if (peer->update_source)
3086 {
3087 sockunion_free (peer->update_source);
3088 peer->update_source = NULL;
3089 }
3090 if (peer->update_if)
3091 {
3092 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3093 peer->update_if = NULL;
3094 }
3095
3096 if (peer_group_active (peer))
3097 {
3098 group = peer->group;
3099
3100 if (group->conf->update_source)
3101 {
3102 su = sockunion_dup (group->conf->update_source);
3103 peer->update_source = su;
3104 }
3105 else if (group->conf->update_if)
3106 peer->update_if =
3107 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
3108 }
3109
3110 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3111 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003112 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003113 {
3114 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3115 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3116 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3117 }
paul718e3742002-12-13 20:15:29 +00003118 else
3119 BGP_EVENT_ADD (peer, BGP_Stop);
3120 return 0;
3121 }
3122
3123 /* peer-group member updates. */
3124 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003125 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003126 {
3127 if (! peer->update_source && ! peer->update_if)
3128 continue;
3129
3130 if (peer->update_source)
3131 {
3132 sockunion_free (peer->update_source);
3133 peer->update_source = NULL;
3134 }
3135
3136 if (peer->update_if)
3137 {
3138 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3139 peer->update_if = NULL;
3140 }
3141
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003142 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003143 {
3144 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3145 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3146 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3147 }
paul718e3742002-12-13 20:15:29 +00003148 else
3149 BGP_EVENT_ADD (peer, BGP_Stop);
3150 }
3151 return 0;
3152}
David Lamparter6b0655a2014-06-04 06:53:35 +02003153
paul718e3742002-12-13 20:15:29 +00003154int
3155peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003156 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003157{
3158 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003159 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003160
3161 /* Adress family must be activated. */
3162 if (! peer->afc[afi][safi])
3163 return BGP_ERR_PEER_INACTIVE;
3164
3165 /* Default originate can't be used for peer group memeber. */
3166 if (peer_is_group_member (peer, afi, safi))
3167 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3168
3169 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3170 || (rmap && ! peer->default_rmap[afi][safi].name)
3171 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3172 {
3173 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3174
3175 if (rmap)
3176 {
3177 if (peer->default_rmap[afi][safi].name)
3178 free (peer->default_rmap[afi][safi].name);
3179 peer->default_rmap[afi][safi].name = strdup (rmap);
3180 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3181 }
3182 }
3183
3184 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3185 {
3186 if (peer->status == Established && peer->afc_nego[afi][safi])
3187 bgp_default_originate (peer, afi, safi, 0);
3188 return 0;
3189 }
3190
3191 /* peer-group member updates. */
3192 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003193 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003194 {
3195 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3196
3197 if (rmap)
3198 {
3199 if (peer->default_rmap[afi][safi].name)
3200 free (peer->default_rmap[afi][safi].name);
3201 peer->default_rmap[afi][safi].name = strdup (rmap);
3202 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3203 }
3204
3205 if (peer->status == Established && peer->afc_nego[afi][safi])
3206 bgp_default_originate (peer, afi, safi, 0);
3207 }
3208 return 0;
3209}
3210
3211int
3212peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3213{
3214 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003215 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003216
3217 /* Adress family must be activated. */
3218 if (! peer->afc[afi][safi])
3219 return BGP_ERR_PEER_INACTIVE;
3220
3221 /* Default originate can't be used for peer group memeber. */
3222 if (peer_is_group_member (peer, afi, safi))
3223 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3224
3225 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3226 {
3227 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3228
3229 if (peer->default_rmap[afi][safi].name)
3230 free (peer->default_rmap[afi][safi].name);
3231 peer->default_rmap[afi][safi].name = NULL;
3232 peer->default_rmap[afi][safi].map = NULL;
3233 }
3234
3235 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3236 {
3237 if (peer->status == Established && peer->afc_nego[afi][safi])
3238 bgp_default_originate (peer, afi, safi, 1);
3239 return 0;
3240 }
3241
3242 /* peer-group member updates. */
3243 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003244 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003245 {
3246 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3247
3248 if (peer->default_rmap[afi][safi].name)
3249 free (peer->default_rmap[afi][safi].name);
3250 peer->default_rmap[afi][safi].name = NULL;
3251 peer->default_rmap[afi][safi].map = NULL;
3252
3253 if (peer->status == Established && peer->afc_nego[afi][safi])
3254 bgp_default_originate (peer, afi, safi, 1);
3255 }
3256 return 0;
3257}
David Lamparter6b0655a2014-06-04 06:53:35 +02003258
paul718e3742002-12-13 20:15:29 +00003259int
3260peer_port_set (struct peer *peer, u_int16_t port)
3261{
3262 peer->port = port;
3263 return 0;
3264}
3265
3266int
3267peer_port_unset (struct peer *peer)
3268{
3269 peer->port = BGP_PORT_DEFAULT;
3270 return 0;
3271}
David Lamparter6b0655a2014-06-04 06:53:35 +02003272
paul718e3742002-12-13 20:15:29 +00003273/* neighbor weight. */
3274int
3275peer_weight_set (struct peer *peer, u_int16_t weight)
3276{
3277 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003278 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003279
3280 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3281 peer->weight = weight;
3282
3283 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3284 return 0;
3285
3286 /* peer-group member updates. */
3287 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003288 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003289 {
3290 peer->weight = group->conf->weight;
3291 }
3292 return 0;
3293}
3294
3295int
3296peer_weight_unset (struct peer *peer)
3297{
3298 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003299 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003300
3301 /* Set default weight. */
3302 if (peer_group_active (peer))
3303 peer->weight = peer->group->conf->weight;
3304 else
3305 peer->weight = 0;
3306
3307 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3308
3309 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3310 return 0;
3311
3312 /* peer-group member updates. */
3313 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003314 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003315 {
3316 peer->weight = 0;
3317 }
3318 return 0;
3319}
David Lamparter6b0655a2014-06-04 06:53:35 +02003320
paul718e3742002-12-13 20:15:29 +00003321int
3322peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3323{
3324 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003325 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003326
3327 /* Not for peer group memeber. */
3328 if (peer_group_active (peer))
3329 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3330
3331 /* keepalive value check. */
3332 if (keepalive > 65535)
3333 return BGP_ERR_INVALID_VALUE;
3334
3335 /* Holdtime value check. */
3336 if (holdtime > 65535)
3337 return BGP_ERR_INVALID_VALUE;
3338
3339 /* Holdtime value must be either 0 or greater than 3. */
3340 if (holdtime < 3 && holdtime != 0)
3341 return BGP_ERR_INVALID_VALUE;
3342
3343 /* Set value to the configuration. */
3344 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3345 peer->holdtime = holdtime;
3346 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3347
3348 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3349 return 0;
3350
3351 /* peer-group member updates. */
3352 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003353 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003354 {
3355 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3356 peer->holdtime = group->conf->holdtime;
3357 peer->keepalive = group->conf->keepalive;
3358 }
3359 return 0;
3360}
3361
3362int
3363peer_timers_unset (struct peer *peer)
3364{
3365 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003366 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003367
3368 if (peer_group_active (peer))
3369 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3370
3371 /* Clear configuration. */
3372 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3373 peer->keepalive = 0;
3374 peer->holdtime = 0;
3375
3376 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3377 return 0;
3378
3379 /* peer-group member updates. */
3380 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003381 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003382 {
3383 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3384 peer->holdtime = 0;
3385 peer->keepalive = 0;
3386 }
3387
3388 return 0;
3389}
David Lamparter6b0655a2014-06-04 06:53:35 +02003390
paul718e3742002-12-13 20:15:29 +00003391int
3392peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3393{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003394 struct peer_group *group;
3395 struct listnode *node, *nnode;
3396
paul718e3742002-12-13 20:15:29 +00003397 if (peer_group_active (peer))
3398 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3399
3400 if (connect > 65535)
3401 return BGP_ERR_INVALID_VALUE;
3402
3403 /* Set value to the configuration. */
3404 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3405 peer->connect = connect;
3406
3407 /* Set value to timer setting. */
3408 peer->v_connect = connect;
3409
Daniel Walton0d7435f2015-10-22 11:35:20 +03003410 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3411 return 0;
3412
3413 /* peer-group member updates. */
3414 group = peer->group;
3415 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3416 {
3417 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3418 peer->connect = connect;
3419 peer->v_connect = connect;
3420 }
paul718e3742002-12-13 20:15:29 +00003421 return 0;
3422}
3423
3424int
3425peer_timers_connect_unset (struct peer *peer)
3426{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003427 struct peer_group *group;
3428 struct listnode *node, *nnode;
3429
paul718e3742002-12-13 20:15:29 +00003430 if (peer_group_active (peer))
3431 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3432
3433 /* Clear configuration. */
3434 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3435 peer->connect = 0;
3436
3437 /* Set timer setting to default value. */
3438 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3439
Daniel Walton0d7435f2015-10-22 11:35:20 +03003440 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3441 return 0;
3442
3443 /* peer-group member updates. */
3444 group = peer->group;
3445 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3446 {
3447 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3448 peer->connect = 0;
3449 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3450 }
3451 return 0;
paul718e3742002-12-13 20:15:29 +00003452}
David Lamparter6b0655a2014-06-04 06:53:35 +02003453
paul718e3742002-12-13 20:15:29 +00003454int
3455peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3456{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003457 struct peer_group *group;
3458 struct listnode *node, *nnode;
3459
paul718e3742002-12-13 20:15:29 +00003460 if (peer_group_active (peer))
3461 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3462
3463 if (routeadv > 600)
3464 return BGP_ERR_INVALID_VALUE;
3465
3466 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3467 peer->routeadv = routeadv;
3468 peer->v_routeadv = routeadv;
3469
Daniel Walton0d7435f2015-10-22 11:35:20 +03003470 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3471 return 0;
3472
3473 /* peer-group member updates. */
3474 group = peer->group;
3475 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3476 {
3477 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3478 peer->routeadv = routeadv;
3479 peer->v_routeadv = routeadv;
3480 }
3481
paul718e3742002-12-13 20:15:29 +00003482 return 0;
3483}
3484
3485int
3486peer_advertise_interval_unset (struct peer *peer)
3487{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003488 struct peer_group *group;
3489 struct listnode *node, *nnode;
3490
paul718e3742002-12-13 20:15:29 +00003491 if (peer_group_active (peer))
3492 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3493
3494 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3495 peer->routeadv = 0;
3496
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003497 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003498 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3499 else
3500 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
Daniel Walton0d7435f2015-10-22 11:35:20 +03003501
3502 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3503 return 0;
3504
3505 /* peer-group member updates. */
3506 group = peer->group;
3507 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3508 {
3509 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3510 peer->routeadv = 0;
3511
3512 if (peer->sort == BGP_PEER_IBGP)
3513 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3514 else
3515 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3516 }
paul718e3742002-12-13 20:15:29 +00003517
3518 return 0;
3519}
David Lamparter6b0655a2014-06-04 06:53:35 +02003520
paul718e3742002-12-13 20:15:29 +00003521/* neighbor interface */
3522int
paulfd79ac92004-10-13 05:06:08 +00003523peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003524{
3525 if (peer->ifname)
3526 free (peer->ifname);
3527 peer->ifname = strdup (str);
3528
3529 return 0;
3530}
3531
3532int
3533peer_interface_unset (struct peer *peer)
3534{
3535 if (peer->ifname)
3536 free (peer->ifname);
3537 peer->ifname = NULL;
3538
3539 return 0;
3540}
David Lamparter6b0655a2014-06-04 06:53:35 +02003541
paul718e3742002-12-13 20:15:29 +00003542/* Allow-as in. */
3543int
3544peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3545{
3546 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003547 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003548
3549 if (allow_num < 1 || allow_num > 10)
3550 return BGP_ERR_INVALID_VALUE;
3551
3552 if (peer->allowas_in[afi][safi] != allow_num)
3553 {
3554 peer->allowas_in[afi][safi] = allow_num;
3555 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3556 peer_change_action (peer, afi, safi, peer_change_reset_in);
3557 }
3558
3559 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3560 return 0;
3561
3562 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003563 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003564 {
3565 if (peer->allowas_in[afi][safi] != allow_num)
3566 {
3567 peer->allowas_in[afi][safi] = allow_num;
3568 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3569 peer_change_action (peer, afi, safi, peer_change_reset_in);
3570 }
3571
3572 }
3573 return 0;
3574}
3575
3576int
3577peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3578{
3579 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003580 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003581
3582 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3583 {
3584 peer->allowas_in[afi][safi] = 0;
3585 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3586 }
3587
3588 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3589 return 0;
3590
3591 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003592 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003593 {
3594 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3595 {
3596 peer->allowas_in[afi][safi] = 0;
3597 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3598 }
3599 }
3600 return 0;
3601}
David Lamparter6b0655a2014-06-04 06:53:35 +02003602
paul718e3742002-12-13 20:15:29 +00003603int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003604peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003605{
3606 struct bgp *bgp = peer->bgp;
3607 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003608 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003609
3610 if (peer_sort (peer) != BGP_PEER_EBGP
3611 && peer_sort (peer) != BGP_PEER_INTERNAL)
3612 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3613
3614 if (bgp->as == as)
3615 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3616
3617 if (peer_group_active (peer))
3618 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3619
Andrew Certain9d3f9702012-11-07 23:50:07 +00003620 if (peer->as == as)
3621 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3622
paul718e3742002-12-13 20:15:29 +00003623 if (peer->change_local_as == as &&
3624 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003625 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3626 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3627 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003628 return 0;
3629
3630 peer->change_local_as = as;
3631 if (no_prepend)
3632 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3633 else
3634 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3635
Andrew Certain9d3f9702012-11-07 23:50:07 +00003636 if (replace_as)
3637 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3638 else
3639 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3640
paul718e3742002-12-13 20:15:29 +00003641 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3642 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003643 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003644 {
3645 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3646 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3647 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3648 }
paul718e3742002-12-13 20:15:29 +00003649 else
3650 BGP_EVENT_ADD (peer, BGP_Stop);
3651
3652 return 0;
3653 }
3654
3655 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003656 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003657 {
3658 peer->change_local_as = as;
3659 if (no_prepend)
3660 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3661 else
3662 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3663
Andrew Certain9d3f9702012-11-07 23:50:07 +00003664 if (replace_as)
3665 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3666 else
3667 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3668
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003669 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003670 {
3671 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3672 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3673 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3674 }
paul718e3742002-12-13 20:15:29 +00003675 else
3676 BGP_EVENT_ADD (peer, BGP_Stop);
3677 }
3678
3679 return 0;
3680}
3681
3682int
3683peer_local_as_unset (struct peer *peer)
3684{
3685 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003686 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003687
3688 if (peer_group_active (peer))
3689 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3690
3691 if (! peer->change_local_as)
3692 return 0;
3693
3694 peer->change_local_as = 0;
3695 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003696 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003697
3698 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3699 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003700 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003701 {
3702 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3703 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3704 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3705 }
paul718e3742002-12-13 20:15:29 +00003706 else
3707 BGP_EVENT_ADD (peer, BGP_Stop);
3708
3709 return 0;
3710 }
3711
3712 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003713 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003714 {
3715 peer->change_local_as = 0;
3716 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003717 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003718
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003719 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003720 {
3721 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3722 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3723 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3724 }
paul718e3742002-12-13 20:15:29 +00003725 else
3726 BGP_EVENT_ADD (peer, BGP_Stop);
3727 }
3728 return 0;
3729}
David Lamparter6b0655a2014-06-04 06:53:35 +02003730
Paul Jakma0df7c912008-07-21 21:02:49 +00003731/* Set password for authenticating with the peer. */
3732int
3733peer_password_set (struct peer *peer, const char *password)
3734{
3735 struct listnode *nn, *nnode;
3736 int len = password ? strlen(password) : 0;
3737 int ret = BGP_SUCCESS;
3738
3739 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3740 return BGP_ERR_INVALID_VALUE;
3741
3742 if (peer->password && strcmp (peer->password, password) == 0
3743 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3744 return 0;
3745
3746 if (peer->password)
3747 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3748
3749 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3750
3751 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3752 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003753 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3754 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
Paul Jakma0df7c912008-07-21 21:02:49 +00003755 else
3756 BGP_EVENT_ADD (peer, BGP_Stop);
3757
3758 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3759 }
3760
3761 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3762 {
3763 if (peer->password && strcmp (peer->password, password) == 0)
3764 continue;
3765
3766 if (peer->password)
3767 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3768
3769 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3770
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003771 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003772 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3773 else
3774 BGP_EVENT_ADD (peer, BGP_Stop);
3775
3776 if (bgp_md5_set (peer) < 0)
3777 ret = BGP_ERR_TCPSIG_FAILED;
3778 }
3779
3780 return ret;
3781}
3782
3783int
3784peer_password_unset (struct peer *peer)
3785{
3786 struct listnode *nn, *nnode;
3787
3788 if (!peer->password
3789 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3790 return 0;
3791
3792 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3793 {
3794 if (peer_group_active (peer)
3795 && peer->group->conf->password
3796 && strcmp (peer->group->conf->password, peer->password) == 0)
3797 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3798
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003799 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003800 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3801 else
3802 BGP_EVENT_ADD (peer, BGP_Stop);
3803
3804 if (peer->password)
3805 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3806
3807 peer->password = NULL;
3808
3809 bgp_md5_set (peer);
3810
3811 return 0;
3812 }
3813
3814 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3815 peer->password = NULL;
3816
3817 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3818 {
3819 if (!peer->password)
3820 continue;
3821
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003822 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003823 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3824 else
3825 BGP_EVENT_ADD (peer, BGP_Stop);
3826
3827 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3828 peer->password = NULL;
3829
3830 bgp_md5_set (peer);
3831 }
3832
3833 return 0;
3834}
David Lamparter6b0655a2014-06-04 06:53:35 +02003835
paul718e3742002-12-13 20:15:29 +00003836/* Set distribute list to the peer. */
3837int
3838peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003839 const char *name)
paul718e3742002-12-13 20:15:29 +00003840{
3841 struct bgp_filter *filter;
3842 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003843 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003844
3845 if (! peer->afc[afi][safi])
3846 return BGP_ERR_PEER_INACTIVE;
3847
3848 if (direct != FILTER_IN && direct != FILTER_OUT)
3849 return BGP_ERR_INVALID_VALUE;
3850
3851 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3852 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3853
3854 filter = &peer->filter[afi][safi];
3855
3856 if (filter->plist[direct].name)
3857 return BGP_ERR_PEER_FILTER_CONFLICT;
3858
3859 if (filter->dlist[direct].name)
3860 free (filter->dlist[direct].name);
3861 filter->dlist[direct].name = strdup (name);
3862 filter->dlist[direct].alist = access_list_lookup (afi, name);
3863
3864 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3865 return 0;
3866
3867 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003868 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003869 {
3870 filter = &peer->filter[afi][safi];
3871
3872 if (! peer->af_group[afi][safi])
3873 continue;
3874
3875 if (filter->dlist[direct].name)
3876 free (filter->dlist[direct].name);
3877 filter->dlist[direct].name = strdup (name);
3878 filter->dlist[direct].alist = access_list_lookup (afi, name);
3879 }
3880
3881 return 0;
3882}
3883
3884int
3885peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3886{
3887 struct bgp_filter *filter;
3888 struct bgp_filter *gfilter;
3889 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003890 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003891
3892 if (! peer->afc[afi][safi])
3893 return BGP_ERR_PEER_INACTIVE;
3894
3895 if (direct != FILTER_IN && direct != FILTER_OUT)
3896 return BGP_ERR_INVALID_VALUE;
3897
3898 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3899 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3900
3901 filter = &peer->filter[afi][safi];
3902
3903 /* apply peer-group filter */
3904 if (peer->af_group[afi][safi])
3905 {
3906 gfilter = &peer->group->conf->filter[afi][safi];
3907
3908 if (gfilter->dlist[direct].name)
3909 {
3910 if (filter->dlist[direct].name)
3911 free (filter->dlist[direct].name);
3912 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3913 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3914 return 0;
3915 }
3916 }
3917
3918 if (filter->dlist[direct].name)
3919 free (filter->dlist[direct].name);
3920 filter->dlist[direct].name = NULL;
3921 filter->dlist[direct].alist = NULL;
3922
3923 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3924 return 0;
3925
3926 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003927 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003928 {
3929 filter = &peer->filter[afi][safi];
3930
3931 if (! peer->af_group[afi][safi])
3932 continue;
3933
3934 if (filter->dlist[direct].name)
3935 free (filter->dlist[direct].name);
3936 filter->dlist[direct].name = NULL;
3937 filter->dlist[direct].alist = NULL;
3938 }
3939
3940 return 0;
3941}
3942
3943/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003944static void
paul718e3742002-12-13 20:15:29 +00003945peer_distribute_update (struct access_list *access)
3946{
3947 afi_t afi;
3948 safi_t safi;
3949 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003950 struct listnode *mnode, *mnnode;
3951 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003952 struct bgp *bgp;
3953 struct peer *peer;
3954 struct peer_group *group;
3955 struct bgp_filter *filter;
3956
paul1eb8ef22005-04-07 07:30:20 +00003957 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003958 {
paul1eb8ef22005-04-07 07:30:20 +00003959 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003960 {
3961 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3962 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3963 {
3964 filter = &peer->filter[afi][safi];
3965
3966 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3967 {
3968 if (filter->dlist[direct].name)
3969 filter->dlist[direct].alist =
3970 access_list_lookup (afi, filter->dlist[direct].name);
3971 else
3972 filter->dlist[direct].alist = NULL;
3973 }
3974 }
3975 }
paul1eb8ef22005-04-07 07:30:20 +00003976 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003977 {
3978 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3979 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3980 {
3981 filter = &group->conf->filter[afi][safi];
3982
3983 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3984 {
3985 if (filter->dlist[direct].name)
3986 filter->dlist[direct].alist =
3987 access_list_lookup (afi, filter->dlist[direct].name);
3988 else
3989 filter->dlist[direct].alist = NULL;
3990 }
3991 }
3992 }
3993 }
3994}
David Lamparter6b0655a2014-06-04 06:53:35 +02003995
paul718e3742002-12-13 20:15:29 +00003996/* Set prefix list to the peer. */
3997int
3998peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003999 const char *name)
paul718e3742002-12-13 20:15:29 +00004000{
4001 struct bgp_filter *filter;
4002 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004003 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004004
4005 if (! peer->afc[afi][safi])
4006 return BGP_ERR_PEER_INACTIVE;
4007
4008 if (direct != FILTER_IN && direct != FILTER_OUT)
4009 return BGP_ERR_INVALID_VALUE;
4010
4011 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4012 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4013
4014 filter = &peer->filter[afi][safi];
4015
4016 if (filter->dlist[direct].name)
4017 return BGP_ERR_PEER_FILTER_CONFLICT;
4018
4019 if (filter->plist[direct].name)
4020 free (filter->plist[direct].name);
4021 filter->plist[direct].name = strdup (name);
4022 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4023
4024 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4025 return 0;
4026
4027 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004028 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004029 {
4030 filter = &peer->filter[afi][safi];
4031
4032 if (! peer->af_group[afi][safi])
4033 continue;
4034
4035 if (filter->plist[direct].name)
4036 free (filter->plist[direct].name);
4037 filter->plist[direct].name = strdup (name);
4038 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4039 }
4040 return 0;
4041}
4042
4043int
4044peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4045{
4046 struct bgp_filter *filter;
4047 struct bgp_filter *gfilter;
4048 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004049 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004050
4051 if (! peer->afc[afi][safi])
4052 return BGP_ERR_PEER_INACTIVE;
4053
4054 if (direct != FILTER_IN && direct != FILTER_OUT)
4055 return BGP_ERR_INVALID_VALUE;
4056
4057 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4058 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4059
4060 filter = &peer->filter[afi][safi];
4061
4062 /* apply peer-group filter */
4063 if (peer->af_group[afi][safi])
4064 {
4065 gfilter = &peer->group->conf->filter[afi][safi];
4066
4067 if (gfilter->plist[direct].name)
4068 {
4069 if (filter->plist[direct].name)
4070 free (filter->plist[direct].name);
4071 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
4072 filter->plist[direct].plist = gfilter->plist[direct].plist;
4073 return 0;
4074 }
4075 }
4076
4077 if (filter->plist[direct].name)
4078 free (filter->plist[direct].name);
4079 filter->plist[direct].name = NULL;
4080 filter->plist[direct].plist = NULL;
4081
4082 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4083 return 0;
4084
4085 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004086 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004087 {
4088 filter = &peer->filter[afi][safi];
4089
4090 if (! peer->af_group[afi][safi])
4091 continue;
4092
4093 if (filter->plist[direct].name)
4094 free (filter->plist[direct].name);
4095 filter->plist[direct].name = NULL;
4096 filter->plist[direct].plist = NULL;
4097 }
4098
4099 return 0;
4100}
4101
4102/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00004103static void
paul718e3742002-12-13 20:15:29 +00004104peer_prefix_list_update (struct prefix_list *plist)
4105{
paul1eb8ef22005-04-07 07:30:20 +00004106 struct listnode *mnode, *mnnode;
4107 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004108 struct bgp *bgp;
4109 struct peer *peer;
4110 struct peer_group *group;
4111 struct bgp_filter *filter;
4112 afi_t afi;
4113 safi_t safi;
4114 int direct;
4115
paul1eb8ef22005-04-07 07:30:20 +00004116 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004117 {
paul1eb8ef22005-04-07 07:30:20 +00004118 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004119 {
4120 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4121 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4122 {
4123 filter = &peer->filter[afi][safi];
4124
4125 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4126 {
4127 if (filter->plist[direct].name)
4128 filter->plist[direct].plist =
4129 prefix_list_lookup (afi, filter->plist[direct].name);
4130 else
4131 filter->plist[direct].plist = NULL;
4132 }
4133 }
4134 }
paul1eb8ef22005-04-07 07:30:20 +00004135 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004136 {
4137 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4138 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4139 {
4140 filter = &group->conf->filter[afi][safi];
4141
4142 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4143 {
4144 if (filter->plist[direct].name)
4145 filter->plist[direct].plist =
4146 prefix_list_lookup (afi, filter->plist[direct].name);
4147 else
4148 filter->plist[direct].plist = NULL;
4149 }
4150 }
4151 }
4152 }
4153}
David Lamparter6b0655a2014-06-04 06:53:35 +02004154
paul718e3742002-12-13 20:15:29 +00004155int
4156peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004157 const char *name)
paul718e3742002-12-13 20:15:29 +00004158{
4159 struct bgp_filter *filter;
4160 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004161 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004162
4163 if (! peer->afc[afi][safi])
4164 return BGP_ERR_PEER_INACTIVE;
4165
4166 if (direct != FILTER_IN && direct != FILTER_OUT)
4167 return BGP_ERR_INVALID_VALUE;
4168
4169 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4170 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4171
4172 filter = &peer->filter[afi][safi];
4173
4174 if (filter->aslist[direct].name)
4175 free (filter->aslist[direct].name);
4176 filter->aslist[direct].name = strdup (name);
4177 filter->aslist[direct].aslist = as_list_lookup (name);
4178
4179 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4180 return 0;
4181
4182 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004183 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004184 {
4185 filter = &peer->filter[afi][safi];
4186
4187 if (! peer->af_group[afi][safi])
4188 continue;
4189
4190 if (filter->aslist[direct].name)
4191 free (filter->aslist[direct].name);
4192 filter->aslist[direct].name = strdup (name);
4193 filter->aslist[direct].aslist = as_list_lookup (name);
4194 }
4195 return 0;
4196}
4197
4198int
4199peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4200{
4201 struct bgp_filter *filter;
4202 struct bgp_filter *gfilter;
4203 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004204 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004205
4206 if (! peer->afc[afi][safi])
4207 return BGP_ERR_PEER_INACTIVE;
4208
hassob5f29602005-05-25 21:00:28 +00004209 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004210 return BGP_ERR_INVALID_VALUE;
4211
hassob5f29602005-05-25 21:00:28 +00004212 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004213 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4214
4215 filter = &peer->filter[afi][safi];
4216
4217 /* apply peer-group filter */
4218 if (peer->af_group[afi][safi])
4219 {
4220 gfilter = &peer->group->conf->filter[afi][safi];
4221
4222 if (gfilter->aslist[direct].name)
4223 {
4224 if (filter->aslist[direct].name)
4225 free (filter->aslist[direct].name);
4226 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4227 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4228 return 0;
4229 }
4230 }
4231
4232 if (filter->aslist[direct].name)
4233 free (filter->aslist[direct].name);
4234 filter->aslist[direct].name = NULL;
4235 filter->aslist[direct].aslist = NULL;
4236
4237 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4238 return 0;
4239
4240 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004241 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004242 {
4243 filter = &peer->filter[afi][safi];
4244
4245 if (! peer->af_group[afi][safi])
4246 continue;
4247
4248 if (filter->aslist[direct].name)
4249 free (filter->aslist[direct].name);
4250 filter->aslist[direct].name = NULL;
4251 filter->aslist[direct].aslist = NULL;
4252 }
4253
4254 return 0;
4255}
4256
paul94f2b392005-06-28 12:44:16 +00004257static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004258peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004259{
4260 afi_t afi;
4261 safi_t safi;
4262 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004263 struct listnode *mnode, *mnnode;
4264 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004265 struct bgp *bgp;
4266 struct peer *peer;
4267 struct peer_group *group;
4268 struct bgp_filter *filter;
4269
paul1eb8ef22005-04-07 07:30:20 +00004270 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004271 {
paul1eb8ef22005-04-07 07:30:20 +00004272 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004273 {
4274 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4275 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4276 {
4277 filter = &peer->filter[afi][safi];
4278
4279 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4280 {
4281 if (filter->aslist[direct].name)
4282 filter->aslist[direct].aslist =
4283 as_list_lookup (filter->aslist[direct].name);
4284 else
4285 filter->aslist[direct].aslist = NULL;
4286 }
4287 }
4288 }
paul1eb8ef22005-04-07 07:30:20 +00004289 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004290 {
4291 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4292 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4293 {
4294 filter = &group->conf->filter[afi][safi];
4295
4296 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4297 {
4298 if (filter->aslist[direct].name)
4299 filter->aslist[direct].aslist =
4300 as_list_lookup (filter->aslist[direct].name);
4301 else
4302 filter->aslist[direct].aslist = NULL;
4303 }
4304 }
4305 }
4306 }
4307}
David Lamparter6b0655a2014-06-04 06:53:35 +02004308
paul718e3742002-12-13 20:15:29 +00004309/* Set route-map to the peer. */
4310int
4311peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004312 const char *name)
paul718e3742002-12-13 20:15:29 +00004313{
4314 struct bgp_filter *filter;
4315 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004316 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004317
4318 if (! peer->afc[afi][safi])
4319 return BGP_ERR_PEER_INACTIVE;
4320
paulfee0f4c2004-09-13 05:12:46 +00004321 if (direct != RMAP_IN && direct != RMAP_OUT &&
4322 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004323 return BGP_ERR_INVALID_VALUE;
4324
paulfee0f4c2004-09-13 05:12:46 +00004325 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4326 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004327 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4328
4329 filter = &peer->filter[afi][safi];
4330
4331 if (filter->map[direct].name)
4332 free (filter->map[direct].name);
4333
4334 filter->map[direct].name = strdup (name);
4335 filter->map[direct].map = route_map_lookup_by_name (name);
4336
4337 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4338 return 0;
4339
4340 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004341 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004342 {
4343 filter = &peer->filter[afi][safi];
4344
4345 if (! peer->af_group[afi][safi])
4346 continue;
4347
4348 if (filter->map[direct].name)
4349 free (filter->map[direct].name);
4350 filter->map[direct].name = strdup (name);
4351 filter->map[direct].map = route_map_lookup_by_name (name);
4352 }
4353 return 0;
4354}
4355
4356/* Unset route-map from the peer. */
4357int
4358peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4359{
4360 struct bgp_filter *filter;
4361 struct bgp_filter *gfilter;
4362 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004363 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004364
4365 if (! peer->afc[afi][safi])
4366 return BGP_ERR_PEER_INACTIVE;
4367
hassob5f29602005-05-25 21:00:28 +00004368 if (direct != RMAP_IN && direct != RMAP_OUT &&
4369 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004370 return BGP_ERR_INVALID_VALUE;
4371
hassob5f29602005-05-25 21:00:28 +00004372 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4373 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004374 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4375
4376 filter = &peer->filter[afi][safi];
4377
4378 /* apply peer-group filter */
4379 if (peer->af_group[afi][safi])
4380 {
4381 gfilter = &peer->group->conf->filter[afi][safi];
4382
4383 if (gfilter->map[direct].name)
4384 {
4385 if (filter->map[direct].name)
4386 free (filter->map[direct].name);
4387 filter->map[direct].name = strdup (gfilter->map[direct].name);
4388 filter->map[direct].map = gfilter->map[direct].map;
4389 return 0;
4390 }
4391 }
4392
4393 if (filter->map[direct].name)
4394 free (filter->map[direct].name);
4395 filter->map[direct].name = NULL;
4396 filter->map[direct].map = NULL;
4397
4398 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4399 return 0;
4400
4401 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004402 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004403 {
4404 filter = &peer->filter[afi][safi];
4405
4406 if (! peer->af_group[afi][safi])
4407 continue;
4408
4409 if (filter->map[direct].name)
4410 free (filter->map[direct].name);
4411 filter->map[direct].name = NULL;
4412 filter->map[direct].map = NULL;
4413 }
4414 return 0;
4415}
David Lamparter6b0655a2014-06-04 06:53:35 +02004416
paul718e3742002-12-13 20:15:29 +00004417/* Set unsuppress-map to the peer. */
4418int
paulfd79ac92004-10-13 05:06:08 +00004419peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4420 const char *name)
paul718e3742002-12-13 20:15:29 +00004421{
4422 struct bgp_filter *filter;
4423 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004424 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004425
4426 if (! peer->afc[afi][safi])
4427 return BGP_ERR_PEER_INACTIVE;
4428
4429 if (peer_is_group_member (peer, afi, safi))
4430 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4431
4432 filter = &peer->filter[afi][safi];
4433
4434 if (filter->usmap.name)
4435 free (filter->usmap.name);
4436
4437 filter->usmap.name = strdup (name);
4438 filter->usmap.map = route_map_lookup_by_name (name);
4439
4440 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4441 return 0;
4442
4443 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004444 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004445 {
4446 filter = &peer->filter[afi][safi];
4447
4448 if (! peer->af_group[afi][safi])
4449 continue;
4450
4451 if (filter->usmap.name)
4452 free (filter->usmap.name);
4453 filter->usmap.name = strdup (name);
4454 filter->usmap.map = route_map_lookup_by_name (name);
4455 }
4456 return 0;
4457}
4458
4459/* Unset route-map from the peer. */
4460int
4461peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4462{
4463 struct bgp_filter *filter;
4464 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004465 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004466
4467 if (! peer->afc[afi][safi])
4468 return BGP_ERR_PEER_INACTIVE;
4469
4470 if (peer_is_group_member (peer, afi, safi))
4471 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4472
4473 filter = &peer->filter[afi][safi];
4474
4475 if (filter->usmap.name)
4476 free (filter->usmap.name);
4477 filter->usmap.name = NULL;
4478 filter->usmap.map = NULL;
4479
4480 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4481 return 0;
4482
4483 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004484 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004485 {
4486 filter = &peer->filter[afi][safi];
4487
4488 if (! peer->af_group[afi][safi])
4489 continue;
4490
4491 if (filter->usmap.name)
4492 free (filter->usmap.name);
4493 filter->usmap.name = NULL;
4494 filter->usmap.map = NULL;
4495 }
4496 return 0;
4497}
David Lamparter6b0655a2014-06-04 06:53:35 +02004498
paul718e3742002-12-13 20:15:29 +00004499int
4500peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004501 u_int32_t max, u_char threshold,
4502 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004503{
4504 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004505 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004506
4507 if (! peer->afc[afi][safi])
4508 return BGP_ERR_PEER_INACTIVE;
4509
4510 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4511 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004512 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004513 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004514 if (warning)
4515 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4516 else
4517 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4518
4519 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4520 return 0;
4521
4522 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004523 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004524 {
4525 if (! peer->af_group[afi][safi])
4526 continue;
4527
4528 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4529 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004530 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004531 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004532 if (warning)
4533 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4534 else
4535 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4536 }
4537 return 0;
4538}
4539
4540int
4541peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4542{
4543 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004544 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004545
4546 if (! peer->afc[afi][safi])
4547 return BGP_ERR_PEER_INACTIVE;
4548
4549 /* apply peer-group config */
4550 if (peer->af_group[afi][safi])
4551 {
4552 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4553 PEER_FLAG_MAX_PREFIX))
4554 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4555 else
4556 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4557
4558 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4559 PEER_FLAG_MAX_PREFIX_WARNING))
4560 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4561 else
4562 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4563
4564 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004565 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004566 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004567 return 0;
4568 }
4569
4570 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4571 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4572 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004573 peer->pmax_threshold[afi][safi] = 0;
4574 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004575
4576 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4577 return 0;
4578
4579 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004580 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004581 {
4582 if (! peer->af_group[afi][safi])
4583 continue;
4584
4585 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4586 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4587 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004588 peer->pmax_threshold[afi][safi] = 0;
4589 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004590 }
4591 return 0;
4592}
David Lamparter5f9adb52014-05-19 23:15:02 +02004593
4594static int is_ebgp_multihop_configured (struct peer *peer)
4595{
4596 struct peer_group *group;
4597 struct listnode *node, *nnode;
4598 struct peer *peer1;
4599
4600 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4601 {
4602 group = peer->group;
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004603 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4604 (group->conf->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004605 return 1;
4606
4607 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4608 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004609 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
4610 (peer1->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004611 return 1;
4612 }
4613 }
4614 else
4615 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004616 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4617 (peer->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004618 return 1;
4619 }
4620 return 0;
4621}
4622
Nick Hilliardfa411a22011-03-23 15:33:17 +00004623/* Set # of hops between us and BGP peer. */
4624int
4625peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4626{
4627 struct peer_group *group;
4628 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004629 int ret;
4630
4631 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4632
Nick Hilliardfa411a22011-03-23 15:33:17 +00004633 /* We cannot configure ttl-security hops when ebgp-multihop is already
4634 set. For non peer-groups, the check is simple. For peer-groups, it's
4635 slightly messy, because we need to check both the peer-group structure
4636 and all peer-group members for any trace of ebgp-multihop configuration
4637 before actually applying the ttl-security rules. Cisco really made a
4638 mess of this configuration parameter, and OpenBGPD got it right.
4639 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004640
David Lamparter5f9adb52014-05-19 23:15:02 +02004641 if (peer->gtsm_hops == 0)
4642 {
4643 if (is_ebgp_multihop_configured (peer))
4644 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004645
David Lamparter5f9adb52014-05-19 23:15:02 +02004646 /* specify MAXTTL on outgoing packets */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004647 /* Routine handles iBGP peers correctly */
David Lamparter5f9adb52014-05-19 23:15:02 +02004648 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4649 if (ret != 0)
4650 return ret;
4651 }
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004652
Nick Hilliardfa411a22011-03-23 15:33:17 +00004653 peer->gtsm_hops = gtsm_hops;
4654
Nick Hilliardfa411a22011-03-23 15:33:17 +00004655 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4656 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004657 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004658 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4659 }
4660 else
4661 {
4662 group = peer->group;
4663 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4664 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004665 peer->gtsm_hops = group->conf->gtsm_hops;
4666
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004667 /* Change setting of existing peer
4668 * established then change value (may break connectivity)
4669 * not established yet (teardown session and restart)
4670 * no session then do nothing (will get handled by next connection)
4671 */
4672 if (peer->status == Established)
4673 {
4674 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4675 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4676 MAXTTL + 1 - peer->gtsm_hops);
4677 }
4678 else if (peer->status < Established)
4679 {
4680 if (BGP_DEBUG (events, EVENTS))
4681 zlog_debug ("%s Min-ttl changed", peer->host);
4682 BGP_EVENT_ADD (peer, BGP_Stop);
4683 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004684 }
4685 }
4686
4687 return 0;
4688}
4689
4690int
4691peer_ttl_security_hops_unset (struct peer *peer)
4692{
4693 struct peer_group *group;
4694 struct listnode *node, *nnode;
4695 struct peer *opeer;
4696
4697 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4698
Nick Hilliardfa411a22011-03-23 15:33:17 +00004699 /* if a peer-group member, then reset to peer-group default rather than 0 */
4700 if (peer_group_active (peer))
4701 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4702 else
4703 peer->gtsm_hops = 0;
4704
4705 opeer = peer;
4706 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4707 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004708 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004709 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4710 }
4711 else
4712 {
4713 group = peer->group;
4714 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4715 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004716 peer->gtsm_hops = 0;
4717
4718 if (peer->fd >= 0)
4719 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4720 }
4721 }
4722
4723 return peer_ebgp_multihop_unset (opeer);
4724}
David Lamparter6b0655a2014-06-04 06:53:35 +02004725
paul718e3742002-12-13 20:15:29 +00004726int
4727peer_clear (struct peer *peer)
4728{
4729 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4730 {
hasso0a486e52005-02-01 20:57:17 +00004731 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4732 {
4733 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4734 if (peer->t_pmax_restart)
4735 {
4736 BGP_TIMER_OFF (peer->t_pmax_restart);
4737 if (BGP_DEBUG (events, EVENTS))
4738 zlog_debug ("%s Maximum-prefix restart timer canceled",
4739 peer->host);
4740 }
4741 BGP_EVENT_ADD (peer, BGP_Start);
4742 return 0;
4743 }
4744
paul718e3742002-12-13 20:15:29 +00004745 peer->v_start = BGP_INIT_START_TIMER;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00004746 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00004747 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4748 BGP_NOTIFY_CEASE_ADMIN_RESET);
4749 else
4750 BGP_EVENT_ADD (peer, BGP_Stop);
4751 }
4752 return 0;
4753}
4754
4755int
4756peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4757 enum bgp_clear_type stype)
4758{
4759 if (peer->status != Established)
4760 return 0;
4761
4762 if (! peer->afc[afi][safi])
4763 return BGP_ERR_AF_UNCONFIGURED;
4764
Timo Teräs5a2a1ec2015-10-22 11:35:18 +03004765 peer->rtt = sockopt_tcp_rtt (peer->fd);
4766
paulfee0f4c2004-09-13 05:12:46 +00004767 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4768 {
4769 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4770 return 0;
4771 bgp_check_local_routes_rsclient (peer, afi, safi);
4772 bgp_soft_reconfig_rsclient (peer, afi, safi);
4773 }
4774
paul718e3742002-12-13 20:15:29 +00004775 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4776 bgp_announce_route (peer, afi, safi);
4777
4778 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4779 {
4780 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4781 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4782 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4783 {
4784 struct bgp_filter *filter = &peer->filter[afi][safi];
4785 u_char prefix_type;
4786
4787 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4788 prefix_type = ORF_TYPE_PREFIX;
4789 else
4790 prefix_type = ORF_TYPE_PREFIX_OLD;
4791
4792 if (filter->plist[FILTER_IN].plist)
4793 {
4794 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4795 bgp_route_refresh_send (peer, afi, safi,
4796 prefix_type, REFRESH_DEFER, 1);
4797 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4798 REFRESH_IMMEDIATE, 0);
4799 }
4800 else
4801 {
4802 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4803 bgp_route_refresh_send (peer, afi, safi,
4804 prefix_type, REFRESH_IMMEDIATE, 1);
4805 else
4806 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4807 }
4808 return 0;
4809 }
4810 }
4811
4812 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4813 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4814 {
4815 /* If neighbor has soft reconfiguration inbound flag.
4816 Use Adj-RIB-In database. */
4817 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4818 bgp_soft_reconfig_in (peer, afi, safi);
4819 else
4820 {
4821 /* If neighbor has route refresh capability, send route refresh
4822 message to the peer. */
4823 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4824 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4825 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4826 else
4827 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4828 }
4829 }
4830 return 0;
4831}
David Lamparter6b0655a2014-06-04 06:53:35 +02004832
paulfd79ac92004-10-13 05:06:08 +00004833/* Display peer uptime.*/
4834/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004835char *
4836peer_uptime (time_t uptime2, char *buf, size_t len)
4837{
4838 time_t uptime1;
4839 struct tm *tm;
4840
4841 /* Check buffer length. */
4842 if (len < BGP_UPTIME_LEN)
4843 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004844 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004845 /* XXX: should return status instead of buf... */
4846 snprintf (buf, len, "<error> ");
4847 return buf;
paul718e3742002-12-13 20:15:29 +00004848 }
4849
4850 /* If there is no connection has been done before print `never'. */
4851 if (uptime2 == 0)
4852 {
4853 snprintf (buf, len, "never ");
4854 return buf;
4855 }
4856
4857 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004858 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004859 uptime1 -= uptime2;
4860 tm = gmtime (&uptime1);
Paul Jakma84c38402015-05-26 15:19:38 +01004861
paul718e3742002-12-13 20:15:29 +00004862 /* Making formatted timer strings. */
4863#define ONE_DAY_SECOND 60*60*24
Paul Jakma84c38402015-05-26 15:19:38 +01004864#define ONE_WEEK_SECOND ONE_DAY_SECOND*7
4865#define ONE_YEAR_SECOND ONE_DAY_SECOND*365
paul718e3742002-12-13 20:15:29 +00004866
4867 if (uptime1 < ONE_DAY_SECOND)
4868 snprintf (buf, len, "%02d:%02d:%02d",
4869 tm->tm_hour, tm->tm_min, tm->tm_sec);
4870 else if (uptime1 < ONE_WEEK_SECOND)
4871 snprintf (buf, len, "%dd%02dh%02dm",
4872 tm->tm_yday, tm->tm_hour, tm->tm_min);
Paul Jakma84c38402015-05-26 15:19:38 +01004873 else if (uptime1 < ONE_YEAR_SECOND)
paul718e3742002-12-13 20:15:29 +00004874 snprintf (buf, len, "%02dw%dd%02dh",
4875 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
Paul Jakma84c38402015-05-26 15:19:38 +01004876 else
4877 snprintf (buf, len, "%02dy%02dw%dd",
4878 tm->tm_year - 70, tm->tm_yday/7,
4879 tm->tm_yday - ((tm->tm_yday/7) * 7));
paul718e3742002-12-13 20:15:29 +00004880 return buf;
4881}
David Lamparter6b0655a2014-06-04 06:53:35 +02004882
paul94f2b392005-06-28 12:44:16 +00004883static void
paul718e3742002-12-13 20:15:29 +00004884bgp_config_write_filter (struct vty *vty, struct peer *peer,
4885 afi_t afi, safi_t safi)
4886{
4887 struct bgp_filter *filter;
4888 struct bgp_filter *gfilter = NULL;
4889 char *addr;
4890 int in = FILTER_IN;
4891 int out = FILTER_OUT;
4892
4893 addr = peer->host;
4894 filter = &peer->filter[afi][safi];
4895 if (peer->af_group[afi][safi])
4896 gfilter = &peer->group->conf->filter[afi][safi];
4897
4898 /* distribute-list. */
4899 if (filter->dlist[in].name)
4900 if (! gfilter || ! gfilter->dlist[in].name
4901 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4902 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4903 filter->dlist[in].name, VTY_NEWLINE);
4904 if (filter->dlist[out].name && ! gfilter)
4905 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4906 filter->dlist[out].name, VTY_NEWLINE);
4907
4908 /* prefix-list. */
4909 if (filter->plist[in].name)
4910 if (! gfilter || ! gfilter->plist[in].name
4911 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4912 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4913 filter->plist[in].name, VTY_NEWLINE);
4914 if (filter->plist[out].name && ! gfilter)
4915 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4916 filter->plist[out].name, VTY_NEWLINE);
4917
4918 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004919 if (filter->map[RMAP_IN].name)
4920 if (! gfilter || ! gfilter->map[RMAP_IN].name
4921 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004922 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004923 filter->map[RMAP_IN].name, VTY_NEWLINE);
4924 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004925 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004926 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4927 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4928 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4929 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4930 if (filter->map[RMAP_EXPORT].name)
4931 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4932 || strcmp (filter->map[RMAP_EXPORT].name,
4933 gfilter->map[RMAP_EXPORT].name) != 0)
4934 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4935 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004936
4937 /* unsuppress-map */
4938 if (filter->usmap.name && ! gfilter)
4939 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4940 filter->usmap.name, VTY_NEWLINE);
4941
4942 /* filter-list. */
4943 if (filter->aslist[in].name)
4944 if (! gfilter || ! gfilter->aslist[in].name
4945 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4946 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4947 filter->aslist[in].name, VTY_NEWLINE);
4948 if (filter->aslist[out].name && ! gfilter)
4949 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4950 filter->aslist[out].name, VTY_NEWLINE);
4951}
4952
4953/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004954static void
paul718e3742002-12-13 20:15:29 +00004955bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4956 struct peer *peer, afi_t afi, safi_t safi)
4957{
paul718e3742002-12-13 20:15:29 +00004958 struct peer *g_peer = NULL;
4959 char buf[SU_ADDRSTRLEN];
4960 char *addr;
4961
paul718e3742002-12-13 20:15:29 +00004962 addr = peer->host;
4963 if (peer_group_active (peer))
4964 g_peer = peer->group->conf;
4965
4966 /************************************
4967 ****** Global to the neighbor ******
4968 ************************************/
4969 if (afi == AFI_IP && safi == SAFI_UNICAST)
4970 {
4971 /* remote-as. */
4972 if (! peer_group_active (peer))
4973 {
4974 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4975 vty_out (vty, " neighbor %s peer-group%s", addr,
4976 VTY_NEWLINE);
4977 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004978 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004979 VTY_NEWLINE);
4980 }
4981 else
4982 {
4983 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004984 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004985 VTY_NEWLINE);
4986 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4987 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4988 peer->group->name, VTY_NEWLINE);
4989 }
4990
4991 /* local-as. */
4992 if (peer->change_local_as)
4993 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00004994 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004995 peer->change_local_as,
4996 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00004997 " no-prepend" : "",
4998 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
4999 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005000
5001 /* Description. */
5002 if (peer->desc)
5003 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
5004 VTY_NEWLINE);
5005
5006 /* Shutdown. */
5007 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
5008 if (! peer_group_active (peer) ||
5009 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
5010 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
5011
Paul Jakma0df7c912008-07-21 21:02:49 +00005012 /* Password. */
5013 if (peer->password)
5014 if (!peer_group_active (peer)
5015 || ! g_peer->password
5016 || strcmp (peer->password, g_peer->password) != 0)
5017 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
5018 VTY_NEWLINE);
5019
paul718e3742002-12-13 20:15:29 +00005020 /* BGP port. */
5021 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00005022 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00005023 VTY_NEWLINE);
5024
5025 /* Local interface name. */
5026 if (peer->ifname)
5027 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
5028 VTY_NEWLINE);
5029
5030 /* Passive. */
5031 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
5032 if (! peer_group_active (peer) ||
5033 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
5034 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
5035
5036 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00005037 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00005038 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00005039 if (! peer_group_active (peer) ||
5040 g_peer->ttl != peer->ttl)
5041 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
5042 VTY_NEWLINE);
5043
Nick Hilliardfa411a22011-03-23 15:33:17 +00005044 /* ttl-security hops */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00005045 if (peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00005046 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00005047 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00005048 peer->gtsm_hops, VTY_NEWLINE);
5049
hasso6ffd2072005-02-02 14:50:11 +00005050 /* disable-connected-check. */
5051 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00005052 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00005053 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
5054 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005055
5056 /* Update-source. */
5057 if (peer->update_if)
5058 if (! peer_group_active (peer) || ! g_peer->update_if
5059 || strcmp (g_peer->update_if, peer->update_if) != 0)
5060 vty_out (vty, " neighbor %s update-source %s%s", addr,
5061 peer->update_if, VTY_NEWLINE);
5062 if (peer->update_source)
5063 if (! peer_group_active (peer) || ! g_peer->update_source
5064 || sockunion_cmp (g_peer->update_source,
5065 peer->update_source) != 0)
5066 vty_out (vty, " neighbor %s update-source %s%s", addr,
5067 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
5068 VTY_NEWLINE);
5069
paul718e3742002-12-13 20:15:29 +00005070 /* advertisement-interval */
Daniel Walton0d7435f2015-10-22 11:35:20 +03005071 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV) &&
5072 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00005073 vty_out (vty, " neighbor %s advertisement-interval %d%s",
5074 addr, peer->v_routeadv, VTY_NEWLINE);
5075
5076 /* timers. */
5077 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
5078 && ! peer_group_active (peer))
5079 vty_out (vty, " neighbor %s timers %d %d%s", addr,
5080 peer->keepalive, peer->holdtime, VTY_NEWLINE);
5081
Daniel Walton0d7435f2015-10-22 11:35:20 +03005082 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT) &&
5083 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00005084 vty_out (vty, " neighbor %s timers connect %d%s", addr,
5085 peer->connect, VTY_NEWLINE);
5086
5087 /* Default weight. */
5088 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
5089 if (! peer_group_active (peer) ||
5090 g_peer->weight != peer->weight)
5091 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
5092 VTY_NEWLINE);
5093
paul718e3742002-12-13 20:15:29 +00005094 /* Dynamic capability. */
5095 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5096 if (! peer_group_active (peer) ||
5097 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5098 vty_out (vty, " neighbor %s capability dynamic%s", addr,
5099 VTY_NEWLINE);
5100
5101 /* dont capability negotiation. */
5102 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
5103 if (! peer_group_active (peer) ||
5104 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
5105 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
5106 VTY_NEWLINE);
5107
5108 /* override capability negotiation. */
5109 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5110 if (! peer_group_active (peer) ||
5111 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5112 vty_out (vty, " neighbor %s override-capability%s", addr,
5113 VTY_NEWLINE);
5114
5115 /* strict capability negotiation. */
5116 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5117 if (! peer_group_active (peer) ||
5118 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5119 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
5120 VTY_NEWLINE);
5121
Christian Franke15c71342012-11-19 11:17:31 +00005122 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
paul718e3742002-12-13 20:15:29 +00005123 {
5124 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5125 {
5126 if (peer->afc[AFI_IP][SAFI_UNICAST])
5127 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5128 }
5129 else
5130 {
5131 if (! peer->afc[AFI_IP][SAFI_UNICAST])
5132 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
5133 }
5134 }
5135 }
5136
5137
5138 /************************************
5139 ****** Per AF to the neighbor ******
5140 ************************************/
5141
5142 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
5143 {
5144 if (peer->af_group[afi][safi])
5145 vty_out (vty, " neighbor %s peer-group %s%s", addr,
5146 peer->group->name, VTY_NEWLINE);
5147 else
5148 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5149 }
5150
5151 /* ORF capability. */
5152 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5153 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5154 if (! peer->af_group[afi][safi])
5155 {
5156 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
5157
5158 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5159 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5160 vty_out (vty, " both");
5161 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
5162 vty_out (vty, " send");
5163 else
5164 vty_out (vty, " receive");
5165 vty_out (vty, "%s", VTY_NEWLINE);
5166 }
5167
5168 /* Route reflector client. */
5169 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
5170 && ! peer->af_group[afi][safi])
5171 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
5172 VTY_NEWLINE);
5173
5174 /* Nexthop self. */
5175 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
5176 && ! peer->af_group[afi][safi])
Timo Teräs9e7a53c2014-04-24 10:22:37 +03005177 vty_out (vty, " neighbor %s next-hop-self%s%s", addr,
5178 peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ?
5179 " all" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005180
5181 /* Remove private AS. */
5182 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
5183 && ! peer->af_group[afi][safi])
5184 vty_out (vty, " neighbor %s remove-private-AS%s",
5185 addr, VTY_NEWLINE);
5186
5187 /* send-community print. */
5188 if (! peer->af_group[afi][safi])
5189 {
5190 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5191 {
5192 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5193 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5194 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
5195 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5196 vty_out (vty, " neighbor %s send-community extended%s",
5197 addr, VTY_NEWLINE);
5198 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5199 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
5200 }
5201 else
5202 {
5203 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5204 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5205 vty_out (vty, " no neighbor %s send-community both%s",
5206 addr, VTY_NEWLINE);
5207 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5208 vty_out (vty, " no neighbor %s send-community extended%s",
5209 addr, VTY_NEWLINE);
5210 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5211 vty_out (vty, " no neighbor %s send-community%s",
5212 addr, VTY_NEWLINE);
5213 }
5214 }
5215
5216 /* Default information */
5217 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5218 && ! peer->af_group[afi][safi])
5219 {
5220 vty_out (vty, " neighbor %s default-originate", addr);
5221 if (peer->default_rmap[afi][safi].name)
5222 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5223 vty_out (vty, "%s", VTY_NEWLINE);
5224 }
5225
5226 /* Soft reconfiguration inbound. */
5227 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5228 if (! peer->af_group[afi][safi] ||
5229 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5230 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5231 VTY_NEWLINE);
5232
5233 /* maximum-prefix. */
5234 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5235 if (! peer->af_group[afi][safi]
5236 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005237 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005238 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5239 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005240 {
hasso0a486e52005-02-01 20:57:17 +00005241 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5242 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5243 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5244 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5245 vty_out (vty, " warning-only");
5246 if (peer->pmax_restart[afi][safi])
5247 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5248 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005249 }
paul718e3742002-12-13 20:15:29 +00005250
5251 /* Route server client. */
5252 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5253 && ! peer->af_group[afi][safi])
5254 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5255
Dylan Hall3cf12882011-10-27 15:28:17 +04005256 /* Nexthop-local unchanged. */
5257 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5258 && ! peer->af_group[afi][safi])
5259 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5260
paul718e3742002-12-13 20:15:29 +00005261 /* Allow AS in. */
5262 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5263 if (! peer_group_active (peer)
5264 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5265 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5266 {
5267 if (peer->allowas_in[afi][safi] == 3)
5268 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5269 else
5270 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5271 peer->allowas_in[afi][safi], VTY_NEWLINE);
5272 }
5273
5274 /* Filter. */
5275 bgp_config_write_filter (vty, peer, afi, safi);
5276
5277 /* atribute-unchanged. */
5278 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5279 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5280 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5281 && ! peer->af_group[afi][safi])
5282 {
5283 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5284 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5285 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5286 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5287 else
5288 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5289 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5290 " as-path" : "",
5291 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5292 " next-hop" : "",
5293 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5294 " med" : "", VTY_NEWLINE);
5295 }
5296}
5297
5298/* Display "address-family" configuration header. */
5299void
5300bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5301 int *write)
5302{
5303 if (*write)
5304 return;
5305
5306 if (afi == AFI_IP && safi == SAFI_UNICAST)
5307 return;
5308
5309 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5310
5311 if (afi == AFI_IP)
5312 {
5313 if (safi == SAFI_MULTICAST)
5314 vty_out (vty, "ipv4 multicast");
5315 else if (safi == SAFI_MPLS_VPN)
5316 vty_out (vty, "vpnv4 unicast");
5317 }
5318 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005319 {
Lou Berger13c378d2016-01-12 13:41:56 -05005320 if (safi == SAFI_MPLS_VPN)
5321 vty_out (vty, "vpnv6");
5322 else
5323 {
5324 vty_out (vty, "ipv6");
5325 if (safi == SAFI_MULTICAST)
5326 vty_out (vty, " multicast");
5327 }
Paul Jakma37a217a2007-04-10 19:20:29 +00005328 }
paul718e3742002-12-13 20:15:29 +00005329
5330 vty_out (vty, "%s", VTY_NEWLINE);
5331
5332 *write = 1;
5333}
5334
5335/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005336static int
paul718e3742002-12-13 20:15:29 +00005337bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5338 safi_t safi)
5339{
5340 int write = 0;
5341 struct peer *peer;
5342 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005343 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005344
5345 bgp_config_write_network (vty, bgp, afi, safi, &write);
5346
5347 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5348
paul1eb8ef22005-04-07 07:30:20 +00005349 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005350 {
5351 if (group->conf->afc[afi][safi])
5352 {
5353 bgp_config_write_family_header (vty, afi, safi, &write);
5354 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5355 }
5356 }
paul1eb8ef22005-04-07 07:30:20 +00005357 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005358 {
5359 if (peer->afc[afi][safi])
5360 {
5361 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5362 {
5363 bgp_config_write_family_header (vty, afi, safi, &write);
5364 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5365 }
5366 }
5367 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005368
5369 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5370
paul718e3742002-12-13 20:15:29 +00005371 if (write)
5372 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5373
5374 return write;
5375}
5376
5377int
5378bgp_config_write (struct vty *vty)
5379{
5380 int write = 0;
5381 struct bgp *bgp;
5382 struct peer_group *group;
5383 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005384 struct listnode *node, *nnode;
5385 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005386
5387 /* BGP Multiple instance. */
5388 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5389 {
5390 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5391 write++;
5392 }
5393
5394 /* BGP Config type. */
5395 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5396 {
5397 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5398 write++;
5399 }
5400
5401 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005402 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005403 {
5404 if (write)
5405 vty_out (vty, "!%s", VTY_NEWLINE);
5406
5407 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005408 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005409
5410 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5411 {
5412 if (bgp->name)
5413 vty_out (vty, " view %s", bgp->name);
5414 }
5415 vty_out (vty, "%s", VTY_NEWLINE);
5416
5417 /* No Synchronization */
5418 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5419 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5420
5421 /* BGP fast-external-failover. */
5422 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5423 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5424
5425 /* BGP router ID. */
5426 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5427 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5428 VTY_NEWLINE);
5429
paul848973c2003-08-13 00:32:49 +00005430 /* BGP log-neighbor-changes. */
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07005431 if (!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5432 vty_out (vty, " no bgp log-neighbor-changes%s", VTY_NEWLINE);
paul848973c2003-08-13 00:32:49 +00005433
paul718e3742002-12-13 20:15:29 +00005434 /* BGP configuration. */
5435 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5436 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5437
5438 /* BGP default ipv4-unicast. */
5439 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5440 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5441
5442 /* BGP default local-preference. */
5443 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5444 vty_out (vty, " bgp default local-preference %d%s",
5445 bgp->default_local_pref, VTY_NEWLINE);
5446
5447 /* BGP client-to-client reflection. */
5448 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5449 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5450
5451 /* BGP cluster ID. */
5452 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5453 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5454 VTY_NEWLINE);
5455
hassoe0701b72004-05-20 09:19:34 +00005456 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005457 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005458 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5459 VTY_NEWLINE);
5460
5461 /* Confederation peer */
5462 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005463 {
hassoe0701b72004-05-20 09:19:34 +00005464 int i;
paul718e3742002-12-13 20:15:29 +00005465
hassoe0701b72004-05-20 09:19:34 +00005466 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005467
hassoe0701b72004-05-20 09:19:34 +00005468 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005469 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005470
hassoe0701b72004-05-20 09:19:34 +00005471 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005472 }
5473
5474 /* BGP enforce-first-as. */
5475 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5476 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5477
5478 /* BGP deterministic-med. */
5479 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5480 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005481
5482 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005483 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5484 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5485 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005486 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5487 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5488
paul718e3742002-12-13 20:15:29 +00005489 /* BGP bestpath method. */
5490 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5491 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005492 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5493 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
Pradosh Mohapatra2fdd4552013-09-07 07:02:36 +00005494 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
5495 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
5496 }
paul718e3742002-12-13 20:15:29 +00005497 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5498 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5499 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5500 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5501 {
5502 vty_out (vty, " bgp bestpath med");
5503 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5504 vty_out (vty, " confed");
5505 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5506 vty_out (vty, " missing-as-worst");
5507 vty_out (vty, "%s", VTY_NEWLINE);
5508 }
5509
5510 /* BGP network import check. */
5511 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5512 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5513
5514 /* BGP scan interval. */
5515 bgp_config_write_scan_time (vty);
5516
5517 /* BGP flag dampening. */
5518 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5519 BGP_CONFIG_DAMPENING))
5520 bgp_config_write_damp (vty);
5521
5522 /* BGP static route configuration. */
5523 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5524
5525 /* BGP redistribute configuration. */
5526 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5527
5528 /* BGP timers configuration. */
5529 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5530 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5531 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5532 bgp->default_holdtime, VTY_NEWLINE);
5533
5534 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005535 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005536 {
5537 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5538 }
5539
5540 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005541 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005542 {
5543 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5544 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5545 }
5546
Josh Bailey165b5ff2011-07-20 20:43:22 -07005547 /* maximum-paths */
5548 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5549
paul718e3742002-12-13 20:15:29 +00005550 /* Distance configuration. */
5551 bgp_config_write_distance (vty, bgp);
5552
5553 /* No auto-summary */
5554 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5555 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5556
5557 /* IPv4 multicast configuration. */
5558 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5559
5560 /* IPv4 VPN configuration. */
5561 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5562
5563 /* IPv6 unicast configuration. */
5564 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5565
Paul Jakma37a217a2007-04-10 19:20:29 +00005566 /* IPv6 multicast configuration. */
5567 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5568
Lou Berger13c378d2016-01-12 13:41:56 -05005569 /* IPv6 VPN configuration. */
5570 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MPLS_VPN);
5571
paul718e3742002-12-13 20:15:29 +00005572 write++;
5573 }
5574 return write;
5575}
5576
5577void
paul94f2b392005-06-28 12:44:16 +00005578bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005579{
5580 memset (&bgp_master, 0, sizeof (struct bgp_master));
5581
5582 bm = &bgp_master;
5583 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005584 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005585 bm->port = BGP_PORT_DEFAULT;
5586 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005587 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005588}
paul200df112005-06-01 11:17:05 +00005589
David Lamparter6b0655a2014-06-04 06:53:35 +02005590
paul718e3742002-12-13 20:15:29 +00005591void
paul94f2b392005-06-28 12:44:16 +00005592bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005593{
paul718e3742002-12-13 20:15:29 +00005594 /* BGP VTY commands installation. */
5595 bgp_vty_init ();
5596
paul718e3742002-12-13 20:15:29 +00005597 /* Init zebra. */
Donald Sharp774914f2015-10-14 08:50:39 -04005598 bgp_zebra_init (bm->master);
paul718e3742002-12-13 20:15:29 +00005599
5600 /* BGP inits. */
5601 bgp_attr_init ();
5602 bgp_debug_init ();
5603 bgp_dump_init ();
5604 bgp_route_init ();
5605 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005606 bgp_address_init ();
paul718e3742002-12-13 20:15:29 +00005607 bgp_scan_init ();
5608 bgp_mplsvpn_init ();
Lou Berger298cc2f2016-01-12 13:42:02 -05005609 bgp_encap_init ();
paul718e3742002-12-13 20:15:29 +00005610
5611 /* Access list initialize. */
5612 access_list_init ();
5613 access_list_add_hook (peer_distribute_update);
5614 access_list_delete_hook (peer_distribute_update);
5615
5616 /* Filter list initialize. */
5617 bgp_filter_init ();
5618 as_list_add_hook (peer_aslist_update);
5619 as_list_delete_hook (peer_aslist_update);
5620
5621 /* Prefix list initialize.*/
5622 prefix_list_init ();
5623 prefix_list_add_hook (peer_prefix_list_update);
5624 prefix_list_delete_hook (peer_prefix_list_update);
5625
5626 /* Community list initialize. */
5627 bgp_clist = community_list_init ();
5628
5629#ifdef HAVE_SNMP
5630 bgp_snmp_init ();
5631#endif /* HAVE_SNMP */
5632}
paul545acaf2004-04-20 15:13:15 +00005633
5634void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005635bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005636{
paul545acaf2004-04-20 15:13:15 +00005637 struct bgp *bgp;
5638 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005639 struct listnode *node, *nnode;
5640 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005641
paul1eb8ef22005-04-07 07:30:20 +00005642 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5643 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005644 if (peer->status == Established)
5645 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5646 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005647
paul545acaf2004-04-20 15:13:15 +00005648 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005649
paule210cf92005-06-15 19:15:35 +00005650 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005651 {
5652 work_queue_free (bm->process_main_queue);
5653 bm->process_main_queue = NULL;
5654 }
paule210cf92005-06-15 19:15:35 +00005655 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005656 {
5657 work_queue_free (bm->process_rsclient_queue);
5658 bm->process_rsclient_queue = NULL;
5659 }
paul545acaf2004-04-20 15:13:15 +00005660}