blob: 249d20f32eb765314fdca374e713c0614cebf344 [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
Paul Jakmafd35b942009-07-16 19:27:32 +01002232 /* Remove visibility via the master list - there may however still be
2233 * routes to be processed still referencing the struct bgp.
2234 */
2235 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002236 if (list_isempty(bm->bgp))
2237 bgp_close ();
2238
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002239 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002240
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002241 return 0;
2242}
2243
2244static void bgp_free (struct bgp *);
2245
2246void
2247bgp_lock (struct bgp *bgp)
2248{
2249 ++bgp->lock;
2250}
2251
2252void
2253bgp_unlock(struct bgp *bgp)
2254{
Chris Caputo228da422009-07-18 05:44:03 +00002255 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002256 if (--bgp->lock == 0)
2257 bgp_free (bgp);
2258}
2259
2260static void
2261bgp_free (struct bgp *bgp)
2262{
2263 afi_t afi;
2264 safi_t safi;
2265
2266 list_delete (bgp->group);
2267 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002268 list_delete (bgp->rsclient);
2269
paul718e3742002-12-13 20:15:29 +00002270 if (bgp->name)
2271 free (bgp->name);
2272
2273 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2274 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2275 {
2276 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002277 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002278 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002279 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002280 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002281 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002282 }
2283 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002284}
David Lamparter6b0655a2014-06-04 06:53:35 +02002285
paul718e3742002-12-13 20:15:29 +00002286struct peer *
2287peer_lookup (struct bgp *bgp, union sockunion *su)
2288{
2289 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002290 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002291
Steve Hillfc4dc592009-07-28 17:54:35 +01002292 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002293 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002294 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2295 if (sockunion_same (&peer->su, su)
2296 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2297 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002298 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002299 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002300 {
2301 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002302
Paul Jakma2158ad22009-07-28 18:10:55 +01002303 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2304 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2305 if (sockunion_same (&peer->su, su)
2306 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2307 return peer;
paul718e3742002-12-13 20:15:29 +00002308 }
2309 return NULL;
2310}
2311
2312struct peer *
2313peer_lookup_with_open (union sockunion *su, as_t remote_as,
2314 struct in_addr *remote_id, int *as)
2315{
2316 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002317 struct listnode *node;
2318 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002319 struct bgp *bgp;
2320
Steve Hillfc4dc592009-07-28 17:54:35 +01002321 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002322 return NULL;
2323
Paul Jakma9d878772009-08-05 16:25:16 +01002324 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002325 {
Paul Jakma9d878772009-08-05 16:25:16 +01002326 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2327 {
2328 if (sockunion_same (&peer->su, su)
2329 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2330 {
2331 if (peer->as == remote_as
2332 && peer->remote_id.s_addr == remote_id->s_addr)
2333 return peer;
2334 if (peer->as == remote_as)
2335 *as = 1;
2336 }
2337 }
2338
2339 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2340 {
2341 if (sockunion_same (&peer->su, su)
2342 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2343 {
2344 if (peer->as == remote_as
2345 && peer->remote_id.s_addr == 0)
2346 return peer;
2347 if (peer->as == remote_as)
2348 *as = 1;
2349 }
2350 }
paul718e3742002-12-13 20:15:29 +00002351 }
2352 return NULL;
2353}
David Lamparter6b0655a2014-06-04 06:53:35 +02002354
paul718e3742002-12-13 20:15:29 +00002355/* If peer is configured at least one address family return 1. */
2356int
2357peer_active (struct peer *peer)
2358{
2359 if (peer->afc[AFI_IP][SAFI_UNICAST]
2360 || peer->afc[AFI_IP][SAFI_MULTICAST]
2361 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05002362 || peer->afc[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00002363 || peer->afc[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05002364 || peer->afc[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05002365 || peer->afc[AFI_IP6][SAFI_MPLS_VPN]
2366 || peer->afc[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00002367 return 1;
2368 return 0;
2369}
2370
2371/* If peer is negotiated at least one address family return 1. */
2372int
2373peer_active_nego (struct peer *peer)
2374{
2375 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2376 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2377 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05002378 || peer->afc_nego[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00002379 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05002380 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05002381 || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
2382 || peer->afc_nego[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00002383 return 1;
2384 return 0;
2385}
David Lamparter6b0655a2014-06-04 06:53:35 +02002386
paul718e3742002-12-13 20:15:29 +00002387/* peer_flag_change_type. */
2388enum peer_change_type
2389{
2390 peer_change_none,
2391 peer_change_reset,
2392 peer_change_reset_in,
2393 peer_change_reset_out,
2394};
2395
paul94f2b392005-06-28 12:44:16 +00002396static void
paul718e3742002-12-13 20:15:29 +00002397peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2398 enum peer_change_type type)
2399{
2400 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2401 return;
2402
Stephen Hemmingerd9d4ae52010-01-13 00:32:39 +00002403 if (peer->status != Established)
2404 return;
2405
paul718e3742002-12-13 20:15:29 +00002406 if (type == peer_change_reset)
2407 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2408 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2409 else if (type == peer_change_reset_in)
2410 {
2411 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2412 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2413 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2414 else
2415 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2416 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2417 }
2418 else if (type == peer_change_reset_out)
2419 bgp_announce_route (peer, afi, safi);
2420}
2421
2422struct peer_flag_action
2423{
2424 /* Peer's flag. */
2425 u_int32_t flag;
2426
2427 /* This flag can be set for peer-group member. */
2428 u_char not_for_member;
2429
2430 /* Action when the flag is changed. */
2431 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002432
2433 /* Peer down cause */
2434 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002435};
2436
Stephen Hemminger03621952009-07-21 16:27:20 -07002437static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002438 {
2439 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2440 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2441 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2442 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2443 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002444 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002445 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002446 { 0, 0, 0 }
2447 };
2448
Stephen Hemminger03621952009-07-21 16:27:20 -07002449static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002450 {
2451 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2452 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2453 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2454 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2455 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2456 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2457 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2458 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2459 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2460 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2461 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2462 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2463 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002464 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
Timo Teräs9e7a53c2014-04-24 10:22:37 +03002465 { PEER_FLAG_NEXTHOP_SELF_ALL, 1, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002466 { 0, 0, 0 }
2467 };
2468
2469/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002470static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002471peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002472 struct peer_flag_action *action, u_int32_t flag)
2473{
2474 int i;
2475 int found = 0;
2476 int reset_in = 0;
2477 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002478 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002479
2480 /* Check peer's frag action. */
2481 for (i = 0; i < size; i++)
2482 {
2483 match = &action_list[i];
2484
2485 if (match->flag == 0)
2486 break;
2487
2488 if (match->flag & flag)
2489 {
2490 found = 1;
2491
2492 if (match->type == peer_change_reset_in)
2493 reset_in = 1;
2494 if (match->type == peer_change_reset_out)
2495 reset_out = 1;
2496 if (match->type == peer_change_reset)
2497 {
2498 reset_in = 1;
2499 reset_out = 1;
2500 }
2501 if (match->not_for_member)
2502 action->not_for_member = 1;
2503 }
2504 }
2505
2506 /* Set peer clear type. */
2507 if (reset_in && reset_out)
2508 action->type = peer_change_reset;
2509 else if (reset_in)
2510 action->type = peer_change_reset_in;
2511 else if (reset_out)
2512 action->type = peer_change_reset_out;
2513 else
2514 action->type = peer_change_none;
2515
2516 return found;
2517}
2518
paul94f2b392005-06-28 12:44:16 +00002519static void
paul718e3742002-12-13 20:15:29 +00002520peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2521{
2522 if (flag == PEER_FLAG_SHUTDOWN)
2523 {
2524 if (CHECK_FLAG (peer->flags, flag))
2525 {
hasso93406d82005-02-02 14:40:33 +00002526 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2527 peer_nsf_stop (peer);
2528
hasso0a486e52005-02-01 20:57:17 +00002529 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2530 if (peer->t_pmax_restart)
2531 {
2532 BGP_TIMER_OFF (peer->t_pmax_restart);
2533 if (BGP_DEBUG (events, EVENTS))
2534 zlog_debug ("%s Maximum-prefix restart timer canceled",
2535 peer->host);
2536 }
2537
hasso93406d82005-02-02 14:40:33 +00002538 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2539 peer_nsf_stop (peer);
2540
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002541 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002542 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2543 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2544 else
2545 BGP_EVENT_ADD (peer, BGP_Stop);
2546 }
2547 else
2548 {
2549 peer->v_start = BGP_INIT_START_TIMER;
2550 BGP_EVENT_ADD (peer, BGP_Stop);
2551 }
2552 }
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002553 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002554 {
hassoc9502432005-02-01 22:01:48 +00002555 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2556 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2557 else if (flag == PEER_FLAG_PASSIVE)
2558 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002559 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002560 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002561
hassoc9502432005-02-01 22:01:48 +00002562 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2563 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002564 }
2565 else
2566 BGP_EVENT_ADD (peer, BGP_Stop);
2567}
2568
2569/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002570static int
paul718e3742002-12-13 20:15:29 +00002571peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2572{
2573 int found;
2574 int size;
2575 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002576 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002577 struct peer_flag_action action;
2578
2579 memset (&action, 0, sizeof (struct peer_flag_action));
2580 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2581
2582 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2583
2584 /* No flag action is found. */
2585 if (! found)
2586 return BGP_ERR_INVALID_FLAG;
2587
2588 /* Not for peer-group member. */
2589 if (action.not_for_member && peer_group_active (peer))
2590 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2591
2592 /* When unset the peer-group member's flag we have to check
2593 peer-group configuration. */
2594 if (! set && peer_group_active (peer))
2595 if (CHECK_FLAG (peer->group->conf->flags, flag))
2596 {
2597 if (flag == PEER_FLAG_SHUTDOWN)
2598 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2599 else
2600 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2601 }
2602
2603 /* Flag conflict check. */
2604 if (set
2605 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2606 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2607 return BGP_ERR_PEER_FLAG_CONFLICT;
2608
2609 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2610 {
2611 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2612 return 0;
2613 if (! set && ! CHECK_FLAG (peer->flags, flag))
2614 return 0;
2615 }
2616
2617 if (set)
2618 SET_FLAG (peer->flags, flag);
2619 else
2620 UNSET_FLAG (peer->flags, flag);
2621
2622 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2623 {
2624 if (action.type == peer_change_reset)
2625 peer_flag_modify_action (peer, flag);
2626
2627 return 0;
2628 }
2629
2630 /* peer-group member updates. */
2631 group = peer->group;
2632
paul1eb8ef22005-04-07 07:30:20 +00002633 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002634 {
2635 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2636 continue;
2637
2638 if (! set && ! CHECK_FLAG (peer->flags, flag))
2639 continue;
2640
2641 if (set)
2642 SET_FLAG (peer->flags, flag);
2643 else
2644 UNSET_FLAG (peer->flags, flag);
2645
2646 if (action.type == peer_change_reset)
2647 peer_flag_modify_action (peer, flag);
2648 }
2649 return 0;
2650}
2651
2652int
2653peer_flag_set (struct peer *peer, u_int32_t flag)
2654{
2655 return peer_flag_modify (peer, flag, 1);
2656}
2657
2658int
2659peer_flag_unset (struct peer *peer, u_int32_t flag)
2660{
2661 return peer_flag_modify (peer, flag, 0);
2662}
2663
paul94f2b392005-06-28 12:44:16 +00002664static int
paul718e3742002-12-13 20:15:29 +00002665peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2666{
2667 if (peer->af_group[afi][safi])
2668 return 1;
2669 return 0;
2670}
2671
paul94f2b392005-06-28 12:44:16 +00002672static int
paul718e3742002-12-13 20:15:29 +00002673peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2674 int set)
2675{
2676 int found;
2677 int size;
paul1eb8ef22005-04-07 07:30:20 +00002678 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002679 struct peer_group *group;
2680 struct peer_flag_action action;
2681
2682 memset (&action, 0, sizeof (struct peer_flag_action));
2683 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2684
2685 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2686
2687 /* No flag action is found. */
2688 if (! found)
2689 return BGP_ERR_INVALID_FLAG;
2690
2691 /* Adress family must be activated. */
2692 if (! peer->afc[afi][safi])
2693 return BGP_ERR_PEER_INACTIVE;
2694
2695 /* Not for peer-group member. */
2696 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2697 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2698
2699 /* Spcecial check for reflector client. */
2700 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2701 && peer_sort (peer) != BGP_PEER_IBGP)
2702 return BGP_ERR_NOT_INTERNAL_PEER;
2703
2704 /* Spcecial check for remove-private-AS. */
2705 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2706 && peer_sort (peer) == BGP_PEER_IBGP)
2707 return BGP_ERR_REMOVE_PRIVATE_AS;
2708
2709 /* When unset the peer-group member's flag we have to check
2710 peer-group configuration. */
2711 if (! set && peer->af_group[afi][safi])
2712 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2713 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2714
2715 /* When current flag configuration is same as requested one. */
2716 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2717 {
2718 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2719 return 0;
2720 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2721 return 0;
2722 }
2723
2724 if (set)
2725 SET_FLAG (peer->af_flags[afi][safi], flag);
2726 else
2727 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2728
2729 /* Execute action when peer is established. */
2730 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2731 && peer->status == Established)
2732 {
2733 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2734 bgp_clear_adj_in (peer, afi, safi);
2735 else
hassoe0701b72004-05-20 09:19:34 +00002736 {
2737 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2738 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2739 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2740 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2741 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2742 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2743 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2744 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2745
2746 peer_change_action (peer, afi, safi, action.type);
2747 }
2748
paul718e3742002-12-13 20:15:29 +00002749 }
2750
2751 /* Peer group member updates. */
2752 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2753 {
2754 group = peer->group;
2755
paul1eb8ef22005-04-07 07:30:20 +00002756 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002757 {
2758 if (! peer->af_group[afi][safi])
2759 continue;
2760
2761 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2762 continue;
2763
2764 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2765 continue;
2766
2767 if (set)
2768 SET_FLAG (peer->af_flags[afi][safi], flag);
2769 else
2770 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2771
2772 if (peer->status == Established)
2773 {
2774 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2775 bgp_clear_adj_in (peer, afi, safi);
2776 else
hassoe0701b72004-05-20 09:19:34 +00002777 {
2778 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2779 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2780 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2781 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2782 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2783 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2784 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2785 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2786
2787 peer_change_action (peer, afi, safi, action.type);
2788 }
paul718e3742002-12-13 20:15:29 +00002789 }
2790 }
2791 }
2792 return 0;
2793}
2794
2795int
2796peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2797{
2798 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2799}
2800
2801int
2802peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2803{
2804 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2805}
David Lamparter6b0655a2014-06-04 06:53:35 +02002806
paul718e3742002-12-13 20:15:29 +00002807/* EBGP multihop configuration. */
2808int
2809peer_ebgp_multihop_set (struct peer *peer, int ttl)
2810{
2811 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002812 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002813 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002814
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002815 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002816 return 0;
2817
Nick Hilliardfa411a22011-03-23 15:33:17 +00002818 /* see comment in peer_ttl_security_hops_set() */
2819 if (ttl != MAXTTL)
2820 {
2821 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2822 {
2823 group = peer->group;
2824 if (group->conf->gtsm_hops != 0)
2825 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2826
2827 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2828 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002829 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002830 continue;
2831
2832 if (peer1->gtsm_hops != 0)
2833 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2834 }
2835 }
2836 else
2837 {
2838 if (peer->gtsm_hops != 0)
2839 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2840 }
2841 }
2842
paul718e3742002-12-13 20:15:29 +00002843 peer->ttl = ttl;
2844
2845 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2846 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002847 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002848 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002849 }
2850 else
2851 {
2852 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002853 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002854 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002855 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002856 continue;
paul718e3742002-12-13 20:15:29 +00002857
pauleb821182004-05-01 08:44:08 +00002858 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002859
pauleb821182004-05-01 08:44:08 +00002860 if (peer->fd >= 0)
2861 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2862 }
paul718e3742002-12-13 20:15:29 +00002863 }
2864 return 0;
2865}
2866
2867int
2868peer_ebgp_multihop_unset (struct peer *peer)
2869{
2870 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002871 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002872
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002873 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002874 return 0;
2875
Nick Hilliardfa411a22011-03-23 15:33:17 +00002876 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2877 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2878
paul718e3742002-12-13 20:15:29 +00002879 if (peer_group_active (peer))
2880 peer->ttl = peer->group->conf->ttl;
2881 else
2882 peer->ttl = 1;
2883
2884 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2885 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002886 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002887 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002888 }
2889 else
2890 {
2891 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002892 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002893 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002894 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002895 continue;
paul718e3742002-12-13 20:15:29 +00002896
pauleb821182004-05-01 08:44:08 +00002897 peer->ttl = 1;
2898
2899 if (peer->fd >= 0)
2900 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2901 }
paul718e3742002-12-13 20:15:29 +00002902 }
2903 return 0;
2904}
David Lamparter6b0655a2014-06-04 06:53:35 +02002905
paul718e3742002-12-13 20:15:29 +00002906/* Neighbor description. */
2907int
2908peer_description_set (struct peer *peer, char *desc)
2909{
2910 if (peer->desc)
2911 XFREE (MTYPE_PEER_DESC, peer->desc);
2912
2913 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2914
2915 return 0;
2916}
2917
2918int
2919peer_description_unset (struct peer *peer)
2920{
2921 if (peer->desc)
2922 XFREE (MTYPE_PEER_DESC, peer->desc);
2923
2924 peer->desc = NULL;
2925
2926 return 0;
2927}
David Lamparter6b0655a2014-06-04 06:53:35 +02002928
paul718e3742002-12-13 20:15:29 +00002929/* Neighbor update-source. */
2930int
paulfd79ac92004-10-13 05:06:08 +00002931peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002932{
2933 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002934 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002935
2936 if (peer->update_if)
2937 {
2938 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2939 && strcmp (peer->update_if, ifname) == 0)
2940 return 0;
2941
2942 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2943 peer->update_if = NULL;
2944 }
2945
2946 if (peer->update_source)
2947 {
2948 sockunion_free (peer->update_source);
2949 peer->update_source = NULL;
2950 }
2951
2952 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2953
2954 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2955 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002956 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002957 {
2958 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2959 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2960 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2961 }
paul718e3742002-12-13 20:15:29 +00002962 else
2963 BGP_EVENT_ADD (peer, BGP_Stop);
2964 return 0;
2965 }
2966
2967 /* peer-group member updates. */
2968 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002969 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002970 {
2971 if (peer->update_if)
2972 {
2973 if (strcmp (peer->update_if, ifname) == 0)
2974 continue;
2975
2976 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2977 peer->update_if = NULL;
2978 }
2979
2980 if (peer->update_source)
2981 {
2982 sockunion_free (peer->update_source);
2983 peer->update_source = NULL;
2984 }
2985
2986 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2987
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002988 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002989 {
2990 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2991 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2992 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2993 }
paul718e3742002-12-13 20:15:29 +00002994 else
2995 BGP_EVENT_ADD (peer, BGP_Stop);
2996 }
2997 return 0;
2998}
2999
3000int
3001peer_update_source_addr_set (struct peer *peer, union sockunion *su)
3002{
3003 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003004 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003005
3006 if (peer->update_source)
3007 {
3008 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3009 && sockunion_cmp (peer->update_source, su) == 0)
3010 return 0;
3011 sockunion_free (peer->update_source);
3012 peer->update_source = NULL;
3013 }
3014
3015 if (peer->update_if)
3016 {
3017 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3018 peer->update_if = NULL;
3019 }
3020
3021 peer->update_source = sockunion_dup (su);
3022
3023 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3024 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003025 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003026 {
3027 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3028 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3029 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3030 }
paul718e3742002-12-13 20:15:29 +00003031 else
3032 BGP_EVENT_ADD (peer, BGP_Stop);
3033 return 0;
3034 }
3035
3036 /* peer-group member updates. */
3037 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003038 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003039 {
3040 if (peer->update_source)
3041 {
3042 if (sockunion_cmp (peer->update_source, su) == 0)
3043 continue;
3044 sockunion_free (peer->update_source);
3045 peer->update_source = NULL;
3046 }
3047
3048 if (peer->update_if)
3049 {
3050 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3051 peer->update_if = NULL;
3052 }
3053
3054 peer->update_source = sockunion_dup (su);
3055
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003056 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003057 {
3058 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3059 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3060 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3061 }
paul718e3742002-12-13 20:15:29 +00003062 else
3063 BGP_EVENT_ADD (peer, BGP_Stop);
3064 }
3065 return 0;
3066}
3067
3068int
3069peer_update_source_unset (struct peer *peer)
3070{
3071 union sockunion *su;
3072 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003073 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003074
3075 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3076 && ! peer->update_source
3077 && ! peer->update_if)
3078 return 0;
3079
3080 if (peer->update_source)
3081 {
3082 sockunion_free (peer->update_source);
3083 peer->update_source = NULL;
3084 }
3085 if (peer->update_if)
3086 {
3087 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3088 peer->update_if = NULL;
3089 }
3090
3091 if (peer_group_active (peer))
3092 {
3093 group = peer->group;
3094
3095 if (group->conf->update_source)
3096 {
3097 su = sockunion_dup (group->conf->update_source);
3098 peer->update_source = su;
3099 }
3100 else if (group->conf->update_if)
3101 peer->update_if =
3102 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
3103 }
3104
3105 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3106 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003107 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003108 {
3109 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3110 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3111 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3112 }
paul718e3742002-12-13 20:15:29 +00003113 else
3114 BGP_EVENT_ADD (peer, BGP_Stop);
3115 return 0;
3116 }
3117
3118 /* peer-group member updates. */
3119 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003120 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003121 {
3122 if (! peer->update_source && ! peer->update_if)
3123 continue;
3124
3125 if (peer->update_source)
3126 {
3127 sockunion_free (peer->update_source);
3128 peer->update_source = NULL;
3129 }
3130
3131 if (peer->update_if)
3132 {
3133 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3134 peer->update_if = NULL;
3135 }
3136
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003137 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003138 {
3139 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3140 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3141 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3142 }
paul718e3742002-12-13 20:15:29 +00003143 else
3144 BGP_EVENT_ADD (peer, BGP_Stop);
3145 }
3146 return 0;
3147}
David Lamparter6b0655a2014-06-04 06:53:35 +02003148
paul718e3742002-12-13 20:15:29 +00003149int
3150peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003151 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003152{
3153 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003154 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003155
3156 /* Adress family must be activated. */
3157 if (! peer->afc[afi][safi])
3158 return BGP_ERR_PEER_INACTIVE;
3159
3160 /* Default originate can't be used for peer group memeber. */
3161 if (peer_is_group_member (peer, afi, safi))
3162 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3163
3164 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3165 || (rmap && ! peer->default_rmap[afi][safi].name)
3166 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3167 {
3168 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3169
3170 if (rmap)
3171 {
3172 if (peer->default_rmap[afi][safi].name)
3173 free (peer->default_rmap[afi][safi].name);
3174 peer->default_rmap[afi][safi].name = strdup (rmap);
3175 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3176 }
3177 }
3178
3179 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3180 {
3181 if (peer->status == Established && peer->afc_nego[afi][safi])
3182 bgp_default_originate (peer, afi, safi, 0);
3183 return 0;
3184 }
3185
3186 /* peer-group member updates. */
3187 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003188 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003189 {
3190 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3191
3192 if (rmap)
3193 {
3194 if (peer->default_rmap[afi][safi].name)
3195 free (peer->default_rmap[afi][safi].name);
3196 peer->default_rmap[afi][safi].name = strdup (rmap);
3197 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3198 }
3199
3200 if (peer->status == Established && peer->afc_nego[afi][safi])
3201 bgp_default_originate (peer, afi, safi, 0);
3202 }
3203 return 0;
3204}
3205
3206int
3207peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3208{
3209 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003210 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003211
3212 /* Adress family must be activated. */
3213 if (! peer->afc[afi][safi])
3214 return BGP_ERR_PEER_INACTIVE;
3215
3216 /* Default originate can't be used for peer group memeber. */
3217 if (peer_is_group_member (peer, afi, safi))
3218 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3219
3220 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3221 {
3222 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3223
3224 if (peer->default_rmap[afi][safi].name)
3225 free (peer->default_rmap[afi][safi].name);
3226 peer->default_rmap[afi][safi].name = NULL;
3227 peer->default_rmap[afi][safi].map = NULL;
3228 }
3229
3230 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3231 {
3232 if (peer->status == Established && peer->afc_nego[afi][safi])
3233 bgp_default_originate (peer, afi, safi, 1);
3234 return 0;
3235 }
3236
3237 /* peer-group member updates. */
3238 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003239 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003240 {
3241 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3242
3243 if (peer->default_rmap[afi][safi].name)
3244 free (peer->default_rmap[afi][safi].name);
3245 peer->default_rmap[afi][safi].name = NULL;
3246 peer->default_rmap[afi][safi].map = NULL;
3247
3248 if (peer->status == Established && peer->afc_nego[afi][safi])
3249 bgp_default_originate (peer, afi, safi, 1);
3250 }
3251 return 0;
3252}
David Lamparter6b0655a2014-06-04 06:53:35 +02003253
paul718e3742002-12-13 20:15:29 +00003254int
3255peer_port_set (struct peer *peer, u_int16_t port)
3256{
3257 peer->port = port;
3258 return 0;
3259}
3260
3261int
3262peer_port_unset (struct peer *peer)
3263{
3264 peer->port = BGP_PORT_DEFAULT;
3265 return 0;
3266}
David Lamparter6b0655a2014-06-04 06:53:35 +02003267
paul718e3742002-12-13 20:15:29 +00003268/* neighbor weight. */
3269int
3270peer_weight_set (struct peer *peer, u_int16_t weight)
3271{
3272 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003273 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003274
3275 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3276 peer->weight = weight;
3277
3278 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3279 return 0;
3280
3281 /* peer-group member updates. */
3282 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003283 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003284 {
3285 peer->weight = group->conf->weight;
3286 }
3287 return 0;
3288}
3289
3290int
3291peer_weight_unset (struct peer *peer)
3292{
3293 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003294 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003295
3296 /* Set default weight. */
3297 if (peer_group_active (peer))
3298 peer->weight = peer->group->conf->weight;
3299 else
3300 peer->weight = 0;
3301
3302 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3303
3304 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3305 return 0;
3306
3307 /* peer-group member updates. */
3308 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003309 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003310 {
3311 peer->weight = 0;
3312 }
3313 return 0;
3314}
David Lamparter6b0655a2014-06-04 06:53:35 +02003315
paul718e3742002-12-13 20:15:29 +00003316int
3317peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3318{
3319 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003320 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003321
3322 /* Not for peer group memeber. */
3323 if (peer_group_active (peer))
3324 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3325
3326 /* keepalive value check. */
3327 if (keepalive > 65535)
3328 return BGP_ERR_INVALID_VALUE;
3329
3330 /* Holdtime value check. */
3331 if (holdtime > 65535)
3332 return BGP_ERR_INVALID_VALUE;
3333
3334 /* Holdtime value must be either 0 or greater than 3. */
3335 if (holdtime < 3 && holdtime != 0)
3336 return BGP_ERR_INVALID_VALUE;
3337
3338 /* Set value to the configuration. */
3339 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3340 peer->holdtime = holdtime;
3341 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3342
3343 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3344 return 0;
3345
3346 /* peer-group member updates. */
3347 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003348 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003349 {
3350 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3351 peer->holdtime = group->conf->holdtime;
3352 peer->keepalive = group->conf->keepalive;
3353 }
3354 return 0;
3355}
3356
3357int
3358peer_timers_unset (struct peer *peer)
3359{
3360 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003361 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003362
3363 if (peer_group_active (peer))
3364 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3365
3366 /* Clear configuration. */
3367 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3368 peer->keepalive = 0;
3369 peer->holdtime = 0;
3370
3371 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3372 return 0;
3373
3374 /* peer-group member updates. */
3375 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003376 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003377 {
3378 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3379 peer->holdtime = 0;
3380 peer->keepalive = 0;
3381 }
3382
3383 return 0;
3384}
David Lamparter6b0655a2014-06-04 06:53:35 +02003385
paul718e3742002-12-13 20:15:29 +00003386int
3387peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3388{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003389 struct peer_group *group;
3390 struct listnode *node, *nnode;
3391
paul718e3742002-12-13 20:15:29 +00003392 if (peer_group_active (peer))
3393 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3394
3395 if (connect > 65535)
3396 return BGP_ERR_INVALID_VALUE;
3397
3398 /* Set value to the configuration. */
3399 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3400 peer->connect = connect;
3401
3402 /* Set value to timer setting. */
3403 peer->v_connect = connect;
3404
Daniel Walton0d7435f2015-10-22 11:35:20 +03003405 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3406 return 0;
3407
3408 /* peer-group member updates. */
3409 group = peer->group;
3410 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3411 {
3412 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3413 peer->connect = connect;
3414 peer->v_connect = connect;
3415 }
paul718e3742002-12-13 20:15:29 +00003416 return 0;
3417}
3418
3419int
3420peer_timers_connect_unset (struct peer *peer)
3421{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003422 struct peer_group *group;
3423 struct listnode *node, *nnode;
3424
paul718e3742002-12-13 20:15:29 +00003425 if (peer_group_active (peer))
3426 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3427
3428 /* Clear configuration. */
3429 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3430 peer->connect = 0;
3431
3432 /* Set timer setting to default value. */
3433 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3434
Daniel Walton0d7435f2015-10-22 11:35:20 +03003435 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3436 return 0;
3437
3438 /* peer-group member updates. */
3439 group = peer->group;
3440 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3441 {
3442 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3443 peer->connect = 0;
3444 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3445 }
3446 return 0;
paul718e3742002-12-13 20:15:29 +00003447}
David Lamparter6b0655a2014-06-04 06:53:35 +02003448
paul718e3742002-12-13 20:15:29 +00003449int
3450peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3451{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003452 struct peer_group *group;
3453 struct listnode *node, *nnode;
3454
paul718e3742002-12-13 20:15:29 +00003455 if (peer_group_active (peer))
3456 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3457
3458 if (routeadv > 600)
3459 return BGP_ERR_INVALID_VALUE;
3460
3461 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3462 peer->routeadv = routeadv;
3463 peer->v_routeadv = routeadv;
3464
Daniel Walton0d7435f2015-10-22 11:35:20 +03003465 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3466 return 0;
3467
3468 /* peer-group member updates. */
3469 group = peer->group;
3470 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3471 {
3472 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3473 peer->routeadv = routeadv;
3474 peer->v_routeadv = routeadv;
3475 }
3476
paul718e3742002-12-13 20:15:29 +00003477 return 0;
3478}
3479
3480int
3481peer_advertise_interval_unset (struct peer *peer)
3482{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003483 struct peer_group *group;
3484 struct listnode *node, *nnode;
3485
paul718e3742002-12-13 20:15:29 +00003486 if (peer_group_active (peer))
3487 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3488
3489 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3490 peer->routeadv = 0;
3491
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003492 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003493 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3494 else
3495 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
Daniel Walton0d7435f2015-10-22 11:35:20 +03003496
3497 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3498 return 0;
3499
3500 /* peer-group member updates. */
3501 group = peer->group;
3502 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3503 {
3504 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3505 peer->routeadv = 0;
3506
3507 if (peer->sort == BGP_PEER_IBGP)
3508 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3509 else
3510 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3511 }
paul718e3742002-12-13 20:15:29 +00003512
3513 return 0;
3514}
David Lamparter6b0655a2014-06-04 06:53:35 +02003515
paul718e3742002-12-13 20:15:29 +00003516/* neighbor interface */
3517int
paulfd79ac92004-10-13 05:06:08 +00003518peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003519{
3520 if (peer->ifname)
3521 free (peer->ifname);
3522 peer->ifname = strdup (str);
3523
3524 return 0;
3525}
3526
3527int
3528peer_interface_unset (struct peer *peer)
3529{
3530 if (peer->ifname)
3531 free (peer->ifname);
3532 peer->ifname = NULL;
3533
3534 return 0;
3535}
David Lamparter6b0655a2014-06-04 06:53:35 +02003536
paul718e3742002-12-13 20:15:29 +00003537/* Allow-as in. */
3538int
3539peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3540{
3541 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003542 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003543
3544 if (allow_num < 1 || allow_num > 10)
3545 return BGP_ERR_INVALID_VALUE;
3546
3547 if (peer->allowas_in[afi][safi] != allow_num)
3548 {
3549 peer->allowas_in[afi][safi] = allow_num;
3550 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3551 peer_change_action (peer, afi, safi, peer_change_reset_in);
3552 }
3553
3554 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3555 return 0;
3556
3557 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003558 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003559 {
3560 if (peer->allowas_in[afi][safi] != allow_num)
3561 {
3562 peer->allowas_in[afi][safi] = allow_num;
3563 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3564 peer_change_action (peer, afi, safi, peer_change_reset_in);
3565 }
3566
3567 }
3568 return 0;
3569}
3570
3571int
3572peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3573{
3574 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003575 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003576
3577 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3578 {
3579 peer->allowas_in[afi][safi] = 0;
3580 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3581 }
3582
3583 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3584 return 0;
3585
3586 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003587 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003588 {
3589 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3590 {
3591 peer->allowas_in[afi][safi] = 0;
3592 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3593 }
3594 }
3595 return 0;
3596}
David Lamparter6b0655a2014-06-04 06:53:35 +02003597
paul718e3742002-12-13 20:15:29 +00003598int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003599peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003600{
3601 struct bgp *bgp = peer->bgp;
3602 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003603 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003604
3605 if (peer_sort (peer) != BGP_PEER_EBGP
3606 && peer_sort (peer) != BGP_PEER_INTERNAL)
3607 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3608
3609 if (bgp->as == as)
3610 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3611
3612 if (peer_group_active (peer))
3613 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3614
Andrew Certain9d3f9702012-11-07 23:50:07 +00003615 if (peer->as == as)
3616 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3617
paul718e3742002-12-13 20:15:29 +00003618 if (peer->change_local_as == as &&
3619 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003620 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3621 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3622 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003623 return 0;
3624
3625 peer->change_local_as = as;
3626 if (no_prepend)
3627 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3628 else
3629 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3630
Andrew Certain9d3f9702012-11-07 23:50:07 +00003631 if (replace_as)
3632 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3633 else
3634 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3635
paul718e3742002-12-13 20:15:29 +00003636 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3637 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003638 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003639 {
3640 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3641 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3642 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3643 }
paul718e3742002-12-13 20:15:29 +00003644 else
3645 BGP_EVENT_ADD (peer, BGP_Stop);
3646
3647 return 0;
3648 }
3649
3650 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003651 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003652 {
3653 peer->change_local_as = as;
3654 if (no_prepend)
3655 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3656 else
3657 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3658
Andrew Certain9d3f9702012-11-07 23:50:07 +00003659 if (replace_as)
3660 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3661 else
3662 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3663
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003664 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003665 {
3666 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3667 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3668 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3669 }
paul718e3742002-12-13 20:15:29 +00003670 else
3671 BGP_EVENT_ADD (peer, BGP_Stop);
3672 }
3673
3674 return 0;
3675}
3676
3677int
3678peer_local_as_unset (struct peer *peer)
3679{
3680 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003681 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003682
3683 if (peer_group_active (peer))
3684 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3685
3686 if (! peer->change_local_as)
3687 return 0;
3688
3689 peer->change_local_as = 0;
3690 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003691 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003692
3693 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3694 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003695 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003696 {
3697 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3698 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3699 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3700 }
paul718e3742002-12-13 20:15:29 +00003701 else
3702 BGP_EVENT_ADD (peer, BGP_Stop);
3703
3704 return 0;
3705 }
3706
3707 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003708 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003709 {
3710 peer->change_local_as = 0;
3711 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003712 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003713
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003714 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003715 {
3716 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3717 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3718 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3719 }
paul718e3742002-12-13 20:15:29 +00003720 else
3721 BGP_EVENT_ADD (peer, BGP_Stop);
3722 }
3723 return 0;
3724}
David Lamparter6b0655a2014-06-04 06:53:35 +02003725
Paul Jakma0df7c912008-07-21 21:02:49 +00003726/* Set password for authenticating with the peer. */
3727int
3728peer_password_set (struct peer *peer, const char *password)
3729{
3730 struct listnode *nn, *nnode;
3731 int len = password ? strlen(password) : 0;
3732 int ret = BGP_SUCCESS;
3733
3734 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3735 return BGP_ERR_INVALID_VALUE;
3736
3737 if (peer->password && strcmp (peer->password, password) == 0
3738 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3739 return 0;
3740
3741 if (peer->password)
3742 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3743
3744 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3745
3746 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3747 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003748 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3749 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
Paul Jakma0df7c912008-07-21 21:02:49 +00003750 else
3751 BGP_EVENT_ADD (peer, BGP_Stop);
3752
3753 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3754 }
3755
3756 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3757 {
3758 if (peer->password && strcmp (peer->password, password) == 0)
3759 continue;
3760
3761 if (peer->password)
3762 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3763
3764 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3765
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003766 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003767 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3768 else
3769 BGP_EVENT_ADD (peer, BGP_Stop);
3770
3771 if (bgp_md5_set (peer) < 0)
3772 ret = BGP_ERR_TCPSIG_FAILED;
3773 }
3774
3775 return ret;
3776}
3777
3778int
3779peer_password_unset (struct peer *peer)
3780{
3781 struct listnode *nn, *nnode;
3782
3783 if (!peer->password
3784 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3785 return 0;
3786
3787 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3788 {
3789 if (peer_group_active (peer)
3790 && peer->group->conf->password
3791 && strcmp (peer->group->conf->password, peer->password) == 0)
3792 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3793
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003794 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003795 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3796 else
3797 BGP_EVENT_ADD (peer, BGP_Stop);
3798
3799 if (peer->password)
3800 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3801
3802 peer->password = NULL;
3803
3804 bgp_md5_set (peer);
3805
3806 return 0;
3807 }
3808
3809 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3810 peer->password = NULL;
3811
3812 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3813 {
3814 if (!peer->password)
3815 continue;
3816
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003817 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003818 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3819 else
3820 BGP_EVENT_ADD (peer, BGP_Stop);
3821
3822 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3823 peer->password = NULL;
3824
3825 bgp_md5_set (peer);
3826 }
3827
3828 return 0;
3829}
David Lamparter6b0655a2014-06-04 06:53:35 +02003830
paul718e3742002-12-13 20:15:29 +00003831/* Set distribute list to the peer. */
3832int
3833peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003834 const char *name)
paul718e3742002-12-13 20:15:29 +00003835{
3836 struct bgp_filter *filter;
3837 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003838 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003839
3840 if (! peer->afc[afi][safi])
3841 return BGP_ERR_PEER_INACTIVE;
3842
3843 if (direct != FILTER_IN && direct != FILTER_OUT)
3844 return BGP_ERR_INVALID_VALUE;
3845
3846 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3847 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3848
3849 filter = &peer->filter[afi][safi];
3850
3851 if (filter->plist[direct].name)
3852 return BGP_ERR_PEER_FILTER_CONFLICT;
3853
3854 if (filter->dlist[direct].name)
3855 free (filter->dlist[direct].name);
3856 filter->dlist[direct].name = strdup (name);
3857 filter->dlist[direct].alist = access_list_lookup (afi, name);
3858
3859 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3860 return 0;
3861
3862 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003863 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003864 {
3865 filter = &peer->filter[afi][safi];
3866
3867 if (! peer->af_group[afi][safi])
3868 continue;
3869
3870 if (filter->dlist[direct].name)
3871 free (filter->dlist[direct].name);
3872 filter->dlist[direct].name = strdup (name);
3873 filter->dlist[direct].alist = access_list_lookup (afi, name);
3874 }
3875
3876 return 0;
3877}
3878
3879int
3880peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3881{
3882 struct bgp_filter *filter;
3883 struct bgp_filter *gfilter;
3884 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003885 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003886
3887 if (! peer->afc[afi][safi])
3888 return BGP_ERR_PEER_INACTIVE;
3889
3890 if (direct != FILTER_IN && direct != FILTER_OUT)
3891 return BGP_ERR_INVALID_VALUE;
3892
3893 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3894 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3895
3896 filter = &peer->filter[afi][safi];
3897
3898 /* apply peer-group filter */
3899 if (peer->af_group[afi][safi])
3900 {
3901 gfilter = &peer->group->conf->filter[afi][safi];
3902
3903 if (gfilter->dlist[direct].name)
3904 {
3905 if (filter->dlist[direct].name)
3906 free (filter->dlist[direct].name);
3907 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3908 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3909 return 0;
3910 }
3911 }
3912
3913 if (filter->dlist[direct].name)
3914 free (filter->dlist[direct].name);
3915 filter->dlist[direct].name = NULL;
3916 filter->dlist[direct].alist = NULL;
3917
3918 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3919 return 0;
3920
3921 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003922 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003923 {
3924 filter = &peer->filter[afi][safi];
3925
3926 if (! peer->af_group[afi][safi])
3927 continue;
3928
3929 if (filter->dlist[direct].name)
3930 free (filter->dlist[direct].name);
3931 filter->dlist[direct].name = NULL;
3932 filter->dlist[direct].alist = NULL;
3933 }
3934
3935 return 0;
3936}
3937
3938/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003939static void
paul718e3742002-12-13 20:15:29 +00003940peer_distribute_update (struct access_list *access)
3941{
3942 afi_t afi;
3943 safi_t safi;
3944 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003945 struct listnode *mnode, *mnnode;
3946 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003947 struct bgp *bgp;
3948 struct peer *peer;
3949 struct peer_group *group;
3950 struct bgp_filter *filter;
3951
paul1eb8ef22005-04-07 07:30:20 +00003952 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003953 {
paul1eb8ef22005-04-07 07:30:20 +00003954 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003955 {
3956 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3957 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3958 {
3959 filter = &peer->filter[afi][safi];
3960
3961 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3962 {
3963 if (filter->dlist[direct].name)
3964 filter->dlist[direct].alist =
3965 access_list_lookup (afi, filter->dlist[direct].name);
3966 else
3967 filter->dlist[direct].alist = NULL;
3968 }
3969 }
3970 }
paul1eb8ef22005-04-07 07:30:20 +00003971 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003972 {
3973 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3974 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3975 {
3976 filter = &group->conf->filter[afi][safi];
3977
3978 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3979 {
3980 if (filter->dlist[direct].name)
3981 filter->dlist[direct].alist =
3982 access_list_lookup (afi, filter->dlist[direct].name);
3983 else
3984 filter->dlist[direct].alist = NULL;
3985 }
3986 }
3987 }
3988 }
3989}
David Lamparter6b0655a2014-06-04 06:53:35 +02003990
paul718e3742002-12-13 20:15:29 +00003991/* Set prefix list to the peer. */
3992int
3993peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003994 const char *name)
paul718e3742002-12-13 20:15:29 +00003995{
3996 struct bgp_filter *filter;
3997 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003998 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003999
4000 if (! peer->afc[afi][safi])
4001 return BGP_ERR_PEER_INACTIVE;
4002
4003 if (direct != FILTER_IN && direct != FILTER_OUT)
4004 return BGP_ERR_INVALID_VALUE;
4005
4006 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4007 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4008
4009 filter = &peer->filter[afi][safi];
4010
4011 if (filter->dlist[direct].name)
4012 return BGP_ERR_PEER_FILTER_CONFLICT;
4013
4014 if (filter->plist[direct].name)
4015 free (filter->plist[direct].name);
4016 filter->plist[direct].name = strdup (name);
4017 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4018
4019 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4020 return 0;
4021
4022 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004023 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004024 {
4025 filter = &peer->filter[afi][safi];
4026
4027 if (! peer->af_group[afi][safi])
4028 continue;
4029
4030 if (filter->plist[direct].name)
4031 free (filter->plist[direct].name);
4032 filter->plist[direct].name = strdup (name);
4033 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4034 }
4035 return 0;
4036}
4037
4038int
4039peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4040{
4041 struct bgp_filter *filter;
4042 struct bgp_filter *gfilter;
4043 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004044 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004045
4046 if (! peer->afc[afi][safi])
4047 return BGP_ERR_PEER_INACTIVE;
4048
4049 if (direct != FILTER_IN && direct != FILTER_OUT)
4050 return BGP_ERR_INVALID_VALUE;
4051
4052 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4053 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4054
4055 filter = &peer->filter[afi][safi];
4056
4057 /* apply peer-group filter */
4058 if (peer->af_group[afi][safi])
4059 {
4060 gfilter = &peer->group->conf->filter[afi][safi];
4061
4062 if (gfilter->plist[direct].name)
4063 {
4064 if (filter->plist[direct].name)
4065 free (filter->plist[direct].name);
4066 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
4067 filter->plist[direct].plist = gfilter->plist[direct].plist;
4068 return 0;
4069 }
4070 }
4071
4072 if (filter->plist[direct].name)
4073 free (filter->plist[direct].name);
4074 filter->plist[direct].name = NULL;
4075 filter->plist[direct].plist = NULL;
4076
4077 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4078 return 0;
4079
4080 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004081 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004082 {
4083 filter = &peer->filter[afi][safi];
4084
4085 if (! peer->af_group[afi][safi])
4086 continue;
4087
4088 if (filter->plist[direct].name)
4089 free (filter->plist[direct].name);
4090 filter->plist[direct].name = NULL;
4091 filter->plist[direct].plist = NULL;
4092 }
4093
4094 return 0;
4095}
4096
4097/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00004098static void
paul718e3742002-12-13 20:15:29 +00004099peer_prefix_list_update (struct prefix_list *plist)
4100{
paul1eb8ef22005-04-07 07:30:20 +00004101 struct listnode *mnode, *mnnode;
4102 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004103 struct bgp *bgp;
4104 struct peer *peer;
4105 struct peer_group *group;
4106 struct bgp_filter *filter;
4107 afi_t afi;
4108 safi_t safi;
4109 int direct;
4110
paul1eb8ef22005-04-07 07:30:20 +00004111 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004112 {
paul1eb8ef22005-04-07 07:30:20 +00004113 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004114 {
4115 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4116 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4117 {
4118 filter = &peer->filter[afi][safi];
4119
4120 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4121 {
4122 if (filter->plist[direct].name)
4123 filter->plist[direct].plist =
4124 prefix_list_lookup (afi, filter->plist[direct].name);
4125 else
4126 filter->plist[direct].plist = NULL;
4127 }
4128 }
4129 }
paul1eb8ef22005-04-07 07:30:20 +00004130 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004131 {
4132 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4133 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4134 {
4135 filter = &group->conf->filter[afi][safi];
4136
4137 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4138 {
4139 if (filter->plist[direct].name)
4140 filter->plist[direct].plist =
4141 prefix_list_lookup (afi, filter->plist[direct].name);
4142 else
4143 filter->plist[direct].plist = NULL;
4144 }
4145 }
4146 }
4147 }
4148}
David Lamparter6b0655a2014-06-04 06:53:35 +02004149
paul718e3742002-12-13 20:15:29 +00004150int
4151peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004152 const char *name)
paul718e3742002-12-13 20:15:29 +00004153{
4154 struct bgp_filter *filter;
4155 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004156 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004157
4158 if (! peer->afc[afi][safi])
4159 return BGP_ERR_PEER_INACTIVE;
4160
4161 if (direct != FILTER_IN && direct != FILTER_OUT)
4162 return BGP_ERR_INVALID_VALUE;
4163
4164 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4165 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4166
4167 filter = &peer->filter[afi][safi];
4168
4169 if (filter->aslist[direct].name)
4170 free (filter->aslist[direct].name);
4171 filter->aslist[direct].name = strdup (name);
4172 filter->aslist[direct].aslist = as_list_lookup (name);
4173
4174 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4175 return 0;
4176
4177 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004178 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004179 {
4180 filter = &peer->filter[afi][safi];
4181
4182 if (! peer->af_group[afi][safi])
4183 continue;
4184
4185 if (filter->aslist[direct].name)
4186 free (filter->aslist[direct].name);
4187 filter->aslist[direct].name = strdup (name);
4188 filter->aslist[direct].aslist = as_list_lookup (name);
4189 }
4190 return 0;
4191}
4192
4193int
4194peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4195{
4196 struct bgp_filter *filter;
4197 struct bgp_filter *gfilter;
4198 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004199 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004200
4201 if (! peer->afc[afi][safi])
4202 return BGP_ERR_PEER_INACTIVE;
4203
hassob5f29602005-05-25 21:00:28 +00004204 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004205 return BGP_ERR_INVALID_VALUE;
4206
hassob5f29602005-05-25 21:00:28 +00004207 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004208 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4209
4210 filter = &peer->filter[afi][safi];
4211
4212 /* apply peer-group filter */
4213 if (peer->af_group[afi][safi])
4214 {
4215 gfilter = &peer->group->conf->filter[afi][safi];
4216
4217 if (gfilter->aslist[direct].name)
4218 {
4219 if (filter->aslist[direct].name)
4220 free (filter->aslist[direct].name);
4221 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4222 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4223 return 0;
4224 }
4225 }
4226
4227 if (filter->aslist[direct].name)
4228 free (filter->aslist[direct].name);
4229 filter->aslist[direct].name = NULL;
4230 filter->aslist[direct].aslist = NULL;
4231
4232 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4233 return 0;
4234
4235 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004236 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004237 {
4238 filter = &peer->filter[afi][safi];
4239
4240 if (! peer->af_group[afi][safi])
4241 continue;
4242
4243 if (filter->aslist[direct].name)
4244 free (filter->aslist[direct].name);
4245 filter->aslist[direct].name = NULL;
4246 filter->aslist[direct].aslist = NULL;
4247 }
4248
4249 return 0;
4250}
4251
paul94f2b392005-06-28 12:44:16 +00004252static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004253peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004254{
4255 afi_t afi;
4256 safi_t safi;
4257 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004258 struct listnode *mnode, *mnnode;
4259 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004260 struct bgp *bgp;
4261 struct peer *peer;
4262 struct peer_group *group;
4263 struct bgp_filter *filter;
4264
paul1eb8ef22005-04-07 07:30:20 +00004265 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004266 {
paul1eb8ef22005-04-07 07:30:20 +00004267 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004268 {
4269 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4270 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4271 {
4272 filter = &peer->filter[afi][safi];
4273
4274 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4275 {
4276 if (filter->aslist[direct].name)
4277 filter->aslist[direct].aslist =
4278 as_list_lookup (filter->aslist[direct].name);
4279 else
4280 filter->aslist[direct].aslist = NULL;
4281 }
4282 }
4283 }
paul1eb8ef22005-04-07 07:30:20 +00004284 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004285 {
4286 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4287 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4288 {
4289 filter = &group->conf->filter[afi][safi];
4290
4291 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4292 {
4293 if (filter->aslist[direct].name)
4294 filter->aslist[direct].aslist =
4295 as_list_lookup (filter->aslist[direct].name);
4296 else
4297 filter->aslist[direct].aslist = NULL;
4298 }
4299 }
4300 }
4301 }
4302}
David Lamparter6b0655a2014-06-04 06:53:35 +02004303
paul718e3742002-12-13 20:15:29 +00004304/* Set route-map to the peer. */
4305int
4306peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004307 const char *name)
paul718e3742002-12-13 20:15:29 +00004308{
4309 struct bgp_filter *filter;
4310 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004311 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004312
4313 if (! peer->afc[afi][safi])
4314 return BGP_ERR_PEER_INACTIVE;
4315
paulfee0f4c2004-09-13 05:12:46 +00004316 if (direct != RMAP_IN && direct != RMAP_OUT &&
4317 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004318 return BGP_ERR_INVALID_VALUE;
4319
paulfee0f4c2004-09-13 05:12:46 +00004320 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4321 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004322 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4323
4324 filter = &peer->filter[afi][safi];
4325
4326 if (filter->map[direct].name)
4327 free (filter->map[direct].name);
4328
4329 filter->map[direct].name = strdup (name);
4330 filter->map[direct].map = route_map_lookup_by_name (name);
4331
4332 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4333 return 0;
4334
4335 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004336 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004337 {
4338 filter = &peer->filter[afi][safi];
4339
4340 if (! peer->af_group[afi][safi])
4341 continue;
4342
4343 if (filter->map[direct].name)
4344 free (filter->map[direct].name);
4345 filter->map[direct].name = strdup (name);
4346 filter->map[direct].map = route_map_lookup_by_name (name);
4347 }
4348 return 0;
4349}
4350
4351/* Unset route-map from the peer. */
4352int
4353peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4354{
4355 struct bgp_filter *filter;
4356 struct bgp_filter *gfilter;
4357 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004358 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004359
4360 if (! peer->afc[afi][safi])
4361 return BGP_ERR_PEER_INACTIVE;
4362
hassob5f29602005-05-25 21:00:28 +00004363 if (direct != RMAP_IN && direct != RMAP_OUT &&
4364 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004365 return BGP_ERR_INVALID_VALUE;
4366
hassob5f29602005-05-25 21:00:28 +00004367 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4368 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004369 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4370
4371 filter = &peer->filter[afi][safi];
4372
4373 /* apply peer-group filter */
4374 if (peer->af_group[afi][safi])
4375 {
4376 gfilter = &peer->group->conf->filter[afi][safi];
4377
4378 if (gfilter->map[direct].name)
4379 {
4380 if (filter->map[direct].name)
4381 free (filter->map[direct].name);
4382 filter->map[direct].name = strdup (gfilter->map[direct].name);
4383 filter->map[direct].map = gfilter->map[direct].map;
4384 return 0;
4385 }
4386 }
4387
4388 if (filter->map[direct].name)
4389 free (filter->map[direct].name);
4390 filter->map[direct].name = NULL;
4391 filter->map[direct].map = NULL;
4392
4393 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4394 return 0;
4395
4396 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004397 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004398 {
4399 filter = &peer->filter[afi][safi];
4400
4401 if (! peer->af_group[afi][safi])
4402 continue;
4403
4404 if (filter->map[direct].name)
4405 free (filter->map[direct].name);
4406 filter->map[direct].name = NULL;
4407 filter->map[direct].map = NULL;
4408 }
4409 return 0;
4410}
David Lamparter6b0655a2014-06-04 06:53:35 +02004411
paul718e3742002-12-13 20:15:29 +00004412/* Set unsuppress-map to the peer. */
4413int
paulfd79ac92004-10-13 05:06:08 +00004414peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4415 const char *name)
paul718e3742002-12-13 20:15:29 +00004416{
4417 struct bgp_filter *filter;
4418 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004419 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004420
4421 if (! peer->afc[afi][safi])
4422 return BGP_ERR_PEER_INACTIVE;
4423
4424 if (peer_is_group_member (peer, afi, safi))
4425 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4426
4427 filter = &peer->filter[afi][safi];
4428
4429 if (filter->usmap.name)
4430 free (filter->usmap.name);
4431
4432 filter->usmap.name = strdup (name);
4433 filter->usmap.map = route_map_lookup_by_name (name);
4434
4435 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4436 return 0;
4437
4438 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004439 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004440 {
4441 filter = &peer->filter[afi][safi];
4442
4443 if (! peer->af_group[afi][safi])
4444 continue;
4445
4446 if (filter->usmap.name)
4447 free (filter->usmap.name);
4448 filter->usmap.name = strdup (name);
4449 filter->usmap.map = route_map_lookup_by_name (name);
4450 }
4451 return 0;
4452}
4453
4454/* Unset route-map from the peer. */
4455int
4456peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4457{
4458 struct bgp_filter *filter;
4459 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004460 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004461
4462 if (! peer->afc[afi][safi])
4463 return BGP_ERR_PEER_INACTIVE;
4464
4465 if (peer_is_group_member (peer, afi, safi))
4466 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4467
4468 filter = &peer->filter[afi][safi];
4469
4470 if (filter->usmap.name)
4471 free (filter->usmap.name);
4472 filter->usmap.name = NULL;
4473 filter->usmap.map = NULL;
4474
4475 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4476 return 0;
4477
4478 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004479 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004480 {
4481 filter = &peer->filter[afi][safi];
4482
4483 if (! peer->af_group[afi][safi])
4484 continue;
4485
4486 if (filter->usmap.name)
4487 free (filter->usmap.name);
4488 filter->usmap.name = NULL;
4489 filter->usmap.map = NULL;
4490 }
4491 return 0;
4492}
David Lamparter6b0655a2014-06-04 06:53:35 +02004493
paul718e3742002-12-13 20:15:29 +00004494int
4495peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004496 u_int32_t max, u_char threshold,
4497 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004498{
4499 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004500 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004501
4502 if (! peer->afc[afi][safi])
4503 return BGP_ERR_PEER_INACTIVE;
4504
4505 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4506 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004507 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004508 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004509 if (warning)
4510 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4511 else
4512 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4513
4514 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4515 return 0;
4516
4517 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004518 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004519 {
4520 if (! peer->af_group[afi][safi])
4521 continue;
4522
4523 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4524 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004525 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004526 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004527 if (warning)
4528 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4529 else
4530 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4531 }
4532 return 0;
4533}
4534
4535int
4536peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4537{
4538 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004539 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004540
4541 if (! peer->afc[afi][safi])
4542 return BGP_ERR_PEER_INACTIVE;
4543
4544 /* apply peer-group config */
4545 if (peer->af_group[afi][safi])
4546 {
4547 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4548 PEER_FLAG_MAX_PREFIX))
4549 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4550 else
4551 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4552
4553 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4554 PEER_FLAG_MAX_PREFIX_WARNING))
4555 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4556 else
4557 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4558
4559 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004560 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004561 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004562 return 0;
4563 }
4564
4565 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4566 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4567 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004568 peer->pmax_threshold[afi][safi] = 0;
4569 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004570
4571 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4572 return 0;
4573
4574 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004575 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004576 {
4577 if (! peer->af_group[afi][safi])
4578 continue;
4579
4580 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4581 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4582 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004583 peer->pmax_threshold[afi][safi] = 0;
4584 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004585 }
4586 return 0;
4587}
David Lamparter5f9adb52014-05-19 23:15:02 +02004588
4589static int is_ebgp_multihop_configured (struct peer *peer)
4590{
4591 struct peer_group *group;
4592 struct listnode *node, *nnode;
4593 struct peer *peer1;
4594
4595 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4596 {
4597 group = peer->group;
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004598 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4599 (group->conf->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004600 return 1;
4601
4602 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4603 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004604 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
4605 (peer1->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004606 return 1;
4607 }
4608 }
4609 else
4610 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004611 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4612 (peer->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004613 return 1;
4614 }
4615 return 0;
4616}
4617
Nick Hilliardfa411a22011-03-23 15:33:17 +00004618/* Set # of hops between us and BGP peer. */
4619int
4620peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4621{
4622 struct peer_group *group;
4623 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004624 int ret;
4625
4626 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4627
Nick Hilliardfa411a22011-03-23 15:33:17 +00004628 /* We cannot configure ttl-security hops when ebgp-multihop is already
4629 set. For non peer-groups, the check is simple. For peer-groups, it's
4630 slightly messy, because we need to check both the peer-group structure
4631 and all peer-group members for any trace of ebgp-multihop configuration
4632 before actually applying the ttl-security rules. Cisco really made a
4633 mess of this configuration parameter, and OpenBGPD got it right.
4634 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004635
David Lamparter5f9adb52014-05-19 23:15:02 +02004636 if (peer->gtsm_hops == 0)
4637 {
4638 if (is_ebgp_multihop_configured (peer))
4639 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004640
David Lamparter5f9adb52014-05-19 23:15:02 +02004641 /* specify MAXTTL on outgoing packets */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004642 /* Routine handles iBGP peers correctly */
David Lamparter5f9adb52014-05-19 23:15:02 +02004643 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4644 if (ret != 0)
4645 return ret;
4646 }
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004647
Nick Hilliardfa411a22011-03-23 15:33:17 +00004648 peer->gtsm_hops = gtsm_hops;
4649
Nick Hilliardfa411a22011-03-23 15:33:17 +00004650 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4651 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004652 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004653 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4654 }
4655 else
4656 {
4657 group = peer->group;
4658 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4659 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004660 peer->gtsm_hops = group->conf->gtsm_hops;
4661
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004662 /* Change setting of existing peer
4663 * established then change value (may break connectivity)
4664 * not established yet (teardown session and restart)
4665 * no session then do nothing (will get handled by next connection)
4666 */
4667 if (peer->status == Established)
4668 {
4669 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4670 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4671 MAXTTL + 1 - peer->gtsm_hops);
4672 }
4673 else if (peer->status < Established)
4674 {
4675 if (BGP_DEBUG (events, EVENTS))
4676 zlog_debug ("%s Min-ttl changed", peer->host);
4677 BGP_EVENT_ADD (peer, BGP_Stop);
4678 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004679 }
4680 }
4681
4682 return 0;
4683}
4684
4685int
4686peer_ttl_security_hops_unset (struct peer *peer)
4687{
4688 struct peer_group *group;
4689 struct listnode *node, *nnode;
4690 struct peer *opeer;
4691
4692 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4693
Nick Hilliardfa411a22011-03-23 15:33:17 +00004694 /* if a peer-group member, then reset to peer-group default rather than 0 */
4695 if (peer_group_active (peer))
4696 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4697 else
4698 peer->gtsm_hops = 0;
4699
4700 opeer = peer;
4701 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4702 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004703 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004704 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4705 }
4706 else
4707 {
4708 group = peer->group;
4709 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4710 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004711 peer->gtsm_hops = 0;
4712
4713 if (peer->fd >= 0)
4714 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4715 }
4716 }
4717
4718 return peer_ebgp_multihop_unset (opeer);
4719}
David Lamparter6b0655a2014-06-04 06:53:35 +02004720
paul718e3742002-12-13 20:15:29 +00004721int
4722peer_clear (struct peer *peer)
4723{
4724 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4725 {
hasso0a486e52005-02-01 20:57:17 +00004726 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4727 {
4728 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4729 if (peer->t_pmax_restart)
4730 {
4731 BGP_TIMER_OFF (peer->t_pmax_restart);
4732 if (BGP_DEBUG (events, EVENTS))
4733 zlog_debug ("%s Maximum-prefix restart timer canceled",
4734 peer->host);
4735 }
4736 BGP_EVENT_ADD (peer, BGP_Start);
4737 return 0;
4738 }
4739
paul718e3742002-12-13 20:15:29 +00004740 peer->v_start = BGP_INIT_START_TIMER;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00004741 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00004742 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4743 BGP_NOTIFY_CEASE_ADMIN_RESET);
4744 else
4745 BGP_EVENT_ADD (peer, BGP_Stop);
4746 }
4747 return 0;
4748}
4749
4750int
4751peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4752 enum bgp_clear_type stype)
4753{
4754 if (peer->status != Established)
4755 return 0;
4756
4757 if (! peer->afc[afi][safi])
4758 return BGP_ERR_AF_UNCONFIGURED;
4759
Timo Teräs5a2a1ec2015-10-22 11:35:18 +03004760 peer->rtt = sockopt_tcp_rtt (peer->fd);
4761
paulfee0f4c2004-09-13 05:12:46 +00004762 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4763 {
4764 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4765 return 0;
4766 bgp_check_local_routes_rsclient (peer, afi, safi);
4767 bgp_soft_reconfig_rsclient (peer, afi, safi);
4768 }
4769
paul718e3742002-12-13 20:15:29 +00004770 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4771 bgp_announce_route (peer, afi, safi);
4772
4773 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4774 {
4775 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4776 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4777 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4778 {
4779 struct bgp_filter *filter = &peer->filter[afi][safi];
4780 u_char prefix_type;
4781
4782 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4783 prefix_type = ORF_TYPE_PREFIX;
4784 else
4785 prefix_type = ORF_TYPE_PREFIX_OLD;
4786
4787 if (filter->plist[FILTER_IN].plist)
4788 {
4789 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4790 bgp_route_refresh_send (peer, afi, safi,
4791 prefix_type, REFRESH_DEFER, 1);
4792 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4793 REFRESH_IMMEDIATE, 0);
4794 }
4795 else
4796 {
4797 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4798 bgp_route_refresh_send (peer, afi, safi,
4799 prefix_type, REFRESH_IMMEDIATE, 1);
4800 else
4801 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4802 }
4803 return 0;
4804 }
4805 }
4806
4807 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4808 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4809 {
4810 /* If neighbor has soft reconfiguration inbound flag.
4811 Use Adj-RIB-In database. */
4812 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4813 bgp_soft_reconfig_in (peer, afi, safi);
4814 else
4815 {
4816 /* If neighbor has route refresh capability, send route refresh
4817 message to the peer. */
4818 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4819 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4820 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4821 else
4822 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4823 }
4824 }
4825 return 0;
4826}
David Lamparter6b0655a2014-06-04 06:53:35 +02004827
paulfd79ac92004-10-13 05:06:08 +00004828/* Display peer uptime.*/
4829/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004830char *
4831peer_uptime (time_t uptime2, char *buf, size_t len)
4832{
4833 time_t uptime1;
4834 struct tm *tm;
4835
4836 /* Check buffer length. */
4837 if (len < BGP_UPTIME_LEN)
4838 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004839 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004840 /* XXX: should return status instead of buf... */
4841 snprintf (buf, len, "<error> ");
4842 return buf;
paul718e3742002-12-13 20:15:29 +00004843 }
4844
4845 /* If there is no connection has been done before print `never'. */
4846 if (uptime2 == 0)
4847 {
4848 snprintf (buf, len, "never ");
4849 return buf;
4850 }
4851
4852 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004853 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004854 uptime1 -= uptime2;
4855 tm = gmtime (&uptime1);
Paul Jakma84c38402015-05-26 15:19:38 +01004856
paul718e3742002-12-13 20:15:29 +00004857 /* Making formatted timer strings. */
4858#define ONE_DAY_SECOND 60*60*24
Paul Jakma84c38402015-05-26 15:19:38 +01004859#define ONE_WEEK_SECOND ONE_DAY_SECOND*7
4860#define ONE_YEAR_SECOND ONE_DAY_SECOND*365
paul718e3742002-12-13 20:15:29 +00004861
4862 if (uptime1 < ONE_DAY_SECOND)
4863 snprintf (buf, len, "%02d:%02d:%02d",
4864 tm->tm_hour, tm->tm_min, tm->tm_sec);
4865 else if (uptime1 < ONE_WEEK_SECOND)
4866 snprintf (buf, len, "%dd%02dh%02dm",
4867 tm->tm_yday, tm->tm_hour, tm->tm_min);
Paul Jakma84c38402015-05-26 15:19:38 +01004868 else if (uptime1 < ONE_YEAR_SECOND)
paul718e3742002-12-13 20:15:29 +00004869 snprintf (buf, len, "%02dw%dd%02dh",
4870 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
Paul Jakma84c38402015-05-26 15:19:38 +01004871 else
4872 snprintf (buf, len, "%02dy%02dw%dd",
4873 tm->tm_year - 70, tm->tm_yday/7,
4874 tm->tm_yday - ((tm->tm_yday/7) * 7));
paul718e3742002-12-13 20:15:29 +00004875 return buf;
4876}
David Lamparter6b0655a2014-06-04 06:53:35 +02004877
paul94f2b392005-06-28 12:44:16 +00004878static void
paul718e3742002-12-13 20:15:29 +00004879bgp_config_write_filter (struct vty *vty, struct peer *peer,
4880 afi_t afi, safi_t safi)
4881{
4882 struct bgp_filter *filter;
4883 struct bgp_filter *gfilter = NULL;
4884 char *addr;
4885 int in = FILTER_IN;
4886 int out = FILTER_OUT;
4887
4888 addr = peer->host;
4889 filter = &peer->filter[afi][safi];
4890 if (peer->af_group[afi][safi])
4891 gfilter = &peer->group->conf->filter[afi][safi];
4892
4893 /* distribute-list. */
4894 if (filter->dlist[in].name)
4895 if (! gfilter || ! gfilter->dlist[in].name
4896 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4897 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4898 filter->dlist[in].name, VTY_NEWLINE);
4899 if (filter->dlist[out].name && ! gfilter)
4900 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4901 filter->dlist[out].name, VTY_NEWLINE);
4902
4903 /* prefix-list. */
4904 if (filter->plist[in].name)
4905 if (! gfilter || ! gfilter->plist[in].name
4906 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4907 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4908 filter->plist[in].name, VTY_NEWLINE);
4909 if (filter->plist[out].name && ! gfilter)
4910 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4911 filter->plist[out].name, VTY_NEWLINE);
4912
4913 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004914 if (filter->map[RMAP_IN].name)
4915 if (! gfilter || ! gfilter->map[RMAP_IN].name
4916 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004917 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004918 filter->map[RMAP_IN].name, VTY_NEWLINE);
4919 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004920 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004921 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4922 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4923 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4924 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4925 if (filter->map[RMAP_EXPORT].name)
4926 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4927 || strcmp (filter->map[RMAP_EXPORT].name,
4928 gfilter->map[RMAP_EXPORT].name) != 0)
4929 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4930 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004931
4932 /* unsuppress-map */
4933 if (filter->usmap.name && ! gfilter)
4934 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4935 filter->usmap.name, VTY_NEWLINE);
4936
4937 /* filter-list. */
4938 if (filter->aslist[in].name)
4939 if (! gfilter || ! gfilter->aslist[in].name
4940 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4941 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4942 filter->aslist[in].name, VTY_NEWLINE);
4943 if (filter->aslist[out].name && ! gfilter)
4944 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4945 filter->aslist[out].name, VTY_NEWLINE);
4946}
4947
4948/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004949static void
paul718e3742002-12-13 20:15:29 +00004950bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4951 struct peer *peer, afi_t afi, safi_t safi)
4952{
paul718e3742002-12-13 20:15:29 +00004953 struct peer *g_peer = NULL;
4954 char buf[SU_ADDRSTRLEN];
4955 char *addr;
4956
paul718e3742002-12-13 20:15:29 +00004957 addr = peer->host;
4958 if (peer_group_active (peer))
4959 g_peer = peer->group->conf;
4960
4961 /************************************
4962 ****** Global to the neighbor ******
4963 ************************************/
4964 if (afi == AFI_IP && safi == SAFI_UNICAST)
4965 {
4966 /* remote-as. */
4967 if (! peer_group_active (peer))
4968 {
4969 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4970 vty_out (vty, " neighbor %s peer-group%s", addr,
4971 VTY_NEWLINE);
4972 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004973 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004974 VTY_NEWLINE);
4975 }
4976 else
4977 {
4978 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004979 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004980 VTY_NEWLINE);
4981 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4982 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4983 peer->group->name, VTY_NEWLINE);
4984 }
4985
4986 /* local-as. */
4987 if (peer->change_local_as)
4988 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00004989 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004990 peer->change_local_as,
4991 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00004992 " no-prepend" : "",
4993 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
4994 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004995
4996 /* Description. */
4997 if (peer->desc)
4998 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4999 VTY_NEWLINE);
5000
5001 /* Shutdown. */
5002 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
5003 if (! peer_group_active (peer) ||
5004 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
5005 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
5006
Paul Jakma0df7c912008-07-21 21:02:49 +00005007 /* Password. */
5008 if (peer->password)
5009 if (!peer_group_active (peer)
5010 || ! g_peer->password
5011 || strcmp (peer->password, g_peer->password) != 0)
5012 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
5013 VTY_NEWLINE);
5014
paul718e3742002-12-13 20:15:29 +00005015 /* BGP port. */
5016 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00005017 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00005018 VTY_NEWLINE);
5019
5020 /* Local interface name. */
5021 if (peer->ifname)
5022 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
5023 VTY_NEWLINE);
5024
5025 /* Passive. */
5026 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
5027 if (! peer_group_active (peer) ||
5028 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
5029 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
5030
5031 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00005032 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00005033 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00005034 if (! peer_group_active (peer) ||
5035 g_peer->ttl != peer->ttl)
5036 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
5037 VTY_NEWLINE);
5038
Nick Hilliardfa411a22011-03-23 15:33:17 +00005039 /* ttl-security hops */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00005040 if (peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00005041 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00005042 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00005043 peer->gtsm_hops, VTY_NEWLINE);
5044
hasso6ffd2072005-02-02 14:50:11 +00005045 /* disable-connected-check. */
5046 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00005047 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00005048 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
5049 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005050
5051 /* Update-source. */
5052 if (peer->update_if)
5053 if (! peer_group_active (peer) || ! g_peer->update_if
5054 || strcmp (g_peer->update_if, peer->update_if) != 0)
5055 vty_out (vty, " neighbor %s update-source %s%s", addr,
5056 peer->update_if, VTY_NEWLINE);
5057 if (peer->update_source)
5058 if (! peer_group_active (peer) || ! g_peer->update_source
5059 || sockunion_cmp (g_peer->update_source,
5060 peer->update_source) != 0)
5061 vty_out (vty, " neighbor %s update-source %s%s", addr,
5062 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
5063 VTY_NEWLINE);
5064
paul718e3742002-12-13 20:15:29 +00005065 /* advertisement-interval */
Daniel Walton0d7435f2015-10-22 11:35:20 +03005066 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV) &&
5067 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00005068 vty_out (vty, " neighbor %s advertisement-interval %d%s",
5069 addr, peer->v_routeadv, VTY_NEWLINE);
5070
5071 /* timers. */
5072 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
5073 && ! peer_group_active (peer))
5074 vty_out (vty, " neighbor %s timers %d %d%s", addr,
5075 peer->keepalive, peer->holdtime, VTY_NEWLINE);
5076
Daniel Walton0d7435f2015-10-22 11:35:20 +03005077 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT) &&
5078 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00005079 vty_out (vty, " neighbor %s timers connect %d%s", addr,
5080 peer->connect, VTY_NEWLINE);
5081
5082 /* Default weight. */
5083 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
5084 if (! peer_group_active (peer) ||
5085 g_peer->weight != peer->weight)
5086 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
5087 VTY_NEWLINE);
5088
paul718e3742002-12-13 20:15:29 +00005089 /* Dynamic capability. */
5090 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5091 if (! peer_group_active (peer) ||
5092 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5093 vty_out (vty, " neighbor %s capability dynamic%s", addr,
5094 VTY_NEWLINE);
5095
5096 /* dont capability negotiation. */
5097 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
5098 if (! peer_group_active (peer) ||
5099 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
5100 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
5101 VTY_NEWLINE);
5102
5103 /* override capability negotiation. */
5104 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5105 if (! peer_group_active (peer) ||
5106 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5107 vty_out (vty, " neighbor %s override-capability%s", addr,
5108 VTY_NEWLINE);
5109
5110 /* strict capability negotiation. */
5111 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5112 if (! peer_group_active (peer) ||
5113 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5114 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
5115 VTY_NEWLINE);
5116
Christian Franke15c71342012-11-19 11:17:31 +00005117 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
paul718e3742002-12-13 20:15:29 +00005118 {
5119 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5120 {
5121 if (peer->afc[AFI_IP][SAFI_UNICAST])
5122 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5123 }
5124 else
5125 {
5126 if (! peer->afc[AFI_IP][SAFI_UNICAST])
5127 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
5128 }
5129 }
5130 }
5131
5132
5133 /************************************
5134 ****** Per AF to the neighbor ******
5135 ************************************/
5136
5137 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
5138 {
5139 if (peer->af_group[afi][safi])
5140 vty_out (vty, " neighbor %s peer-group %s%s", addr,
5141 peer->group->name, VTY_NEWLINE);
5142 else
5143 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5144 }
5145
5146 /* ORF capability. */
5147 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5148 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5149 if (! peer->af_group[afi][safi])
5150 {
5151 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
5152
5153 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5154 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5155 vty_out (vty, " both");
5156 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
5157 vty_out (vty, " send");
5158 else
5159 vty_out (vty, " receive");
5160 vty_out (vty, "%s", VTY_NEWLINE);
5161 }
5162
5163 /* Route reflector client. */
5164 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
5165 && ! peer->af_group[afi][safi])
5166 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
5167 VTY_NEWLINE);
5168
5169 /* Nexthop self. */
5170 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
5171 && ! peer->af_group[afi][safi])
Timo Teräs9e7a53c2014-04-24 10:22:37 +03005172 vty_out (vty, " neighbor %s next-hop-self%s%s", addr,
5173 peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ?
5174 " all" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005175
5176 /* Remove private AS. */
5177 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
5178 && ! peer->af_group[afi][safi])
5179 vty_out (vty, " neighbor %s remove-private-AS%s",
5180 addr, VTY_NEWLINE);
5181
5182 /* send-community print. */
5183 if (! peer->af_group[afi][safi])
5184 {
5185 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5186 {
5187 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5188 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5189 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
5190 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5191 vty_out (vty, " neighbor %s send-community extended%s",
5192 addr, VTY_NEWLINE);
5193 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5194 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
5195 }
5196 else
5197 {
5198 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5199 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5200 vty_out (vty, " no neighbor %s send-community both%s",
5201 addr, VTY_NEWLINE);
5202 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5203 vty_out (vty, " no neighbor %s send-community extended%s",
5204 addr, VTY_NEWLINE);
5205 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5206 vty_out (vty, " no neighbor %s send-community%s",
5207 addr, VTY_NEWLINE);
5208 }
5209 }
5210
5211 /* Default information */
5212 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5213 && ! peer->af_group[afi][safi])
5214 {
5215 vty_out (vty, " neighbor %s default-originate", addr);
5216 if (peer->default_rmap[afi][safi].name)
5217 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5218 vty_out (vty, "%s", VTY_NEWLINE);
5219 }
5220
5221 /* Soft reconfiguration inbound. */
5222 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5223 if (! peer->af_group[afi][safi] ||
5224 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5225 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5226 VTY_NEWLINE);
5227
5228 /* maximum-prefix. */
5229 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5230 if (! peer->af_group[afi][safi]
5231 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005232 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005233 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5234 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005235 {
hasso0a486e52005-02-01 20:57:17 +00005236 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5237 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5238 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5239 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5240 vty_out (vty, " warning-only");
5241 if (peer->pmax_restart[afi][safi])
5242 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5243 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005244 }
paul718e3742002-12-13 20:15:29 +00005245
5246 /* Route server client. */
5247 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5248 && ! peer->af_group[afi][safi])
5249 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5250
Dylan Hall3cf12882011-10-27 15:28:17 +04005251 /* Nexthop-local unchanged. */
5252 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5253 && ! peer->af_group[afi][safi])
5254 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5255
paul718e3742002-12-13 20:15:29 +00005256 /* Allow AS in. */
5257 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5258 if (! peer_group_active (peer)
5259 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5260 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5261 {
5262 if (peer->allowas_in[afi][safi] == 3)
5263 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5264 else
5265 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5266 peer->allowas_in[afi][safi], VTY_NEWLINE);
5267 }
5268
5269 /* Filter. */
5270 bgp_config_write_filter (vty, peer, afi, safi);
5271
5272 /* atribute-unchanged. */
5273 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5274 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5275 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5276 && ! peer->af_group[afi][safi])
5277 {
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 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5282 else
5283 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5284 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5285 " as-path" : "",
5286 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5287 " next-hop" : "",
5288 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5289 " med" : "", VTY_NEWLINE);
5290 }
5291}
5292
5293/* Display "address-family" configuration header. */
5294void
5295bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5296 int *write)
5297{
5298 if (*write)
5299 return;
5300
5301 if (afi == AFI_IP && safi == SAFI_UNICAST)
5302 return;
5303
5304 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5305
5306 if (afi == AFI_IP)
5307 {
5308 if (safi == SAFI_MULTICAST)
5309 vty_out (vty, "ipv4 multicast");
5310 else if (safi == SAFI_MPLS_VPN)
Lou Bergera3fda882016-01-12 13:42:04 -05005311 vty_out (vty, "vpnv4");
5312 else if (safi == SAFI_ENCAP)
5313 vty_out (vty, "encap");
paul718e3742002-12-13 20:15:29 +00005314 }
5315 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005316 {
Lou Berger13c378d2016-01-12 13:41:56 -05005317 if (safi == SAFI_MPLS_VPN)
5318 vty_out (vty, "vpnv6");
Lou Bergera3fda882016-01-12 13:42:04 -05005319 else if (safi == SAFI_ENCAP)
5320 vty_out (vty, "encapv6");
Lou Berger13c378d2016-01-12 13:41:56 -05005321 else
5322 {
5323 vty_out (vty, "ipv6");
5324 if (safi == SAFI_MULTICAST)
5325 vty_out (vty, " multicast");
5326 }
Paul Jakma37a217a2007-04-10 19:20:29 +00005327 }
paul718e3742002-12-13 20:15:29 +00005328
5329 vty_out (vty, "%s", VTY_NEWLINE);
5330
5331 *write = 1;
5332}
5333
5334/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005335static int
paul718e3742002-12-13 20:15:29 +00005336bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5337 safi_t safi)
5338{
5339 int write = 0;
5340 struct peer *peer;
5341 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005342 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005343
5344 bgp_config_write_network (vty, bgp, afi, safi, &write);
5345
5346 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5347
paul1eb8ef22005-04-07 07:30:20 +00005348 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005349 {
5350 if (group->conf->afc[afi][safi])
5351 {
5352 bgp_config_write_family_header (vty, afi, safi, &write);
5353 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5354 }
5355 }
paul1eb8ef22005-04-07 07:30:20 +00005356 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005357 {
5358 if (peer->afc[afi][safi])
5359 {
5360 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5361 {
5362 bgp_config_write_family_header (vty, afi, safi, &write);
5363 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5364 }
5365 }
5366 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005367
5368 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5369
paul718e3742002-12-13 20:15:29 +00005370 if (write)
5371 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5372
5373 return write;
5374}
5375
5376int
5377bgp_config_write (struct vty *vty)
5378{
5379 int write = 0;
5380 struct bgp *bgp;
5381 struct peer_group *group;
5382 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005383 struct listnode *node, *nnode;
5384 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005385
5386 /* BGP Multiple instance. */
5387 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5388 {
5389 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5390 write++;
5391 }
5392
5393 /* BGP Config type. */
5394 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5395 {
5396 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5397 write++;
5398 }
5399
5400 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005401 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005402 {
5403 if (write)
5404 vty_out (vty, "!%s", VTY_NEWLINE);
5405
5406 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005407 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005408
5409 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5410 {
5411 if (bgp->name)
5412 vty_out (vty, " view %s", bgp->name);
5413 }
5414 vty_out (vty, "%s", VTY_NEWLINE);
5415
5416 /* No Synchronization */
5417 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5418 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5419
5420 /* BGP fast-external-failover. */
5421 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5422 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5423
5424 /* BGP router ID. */
5425 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5426 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5427 VTY_NEWLINE);
5428
paul848973c2003-08-13 00:32:49 +00005429 /* BGP log-neighbor-changes. */
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07005430 if (!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5431 vty_out (vty, " no bgp log-neighbor-changes%s", VTY_NEWLINE);
paul848973c2003-08-13 00:32:49 +00005432
paul718e3742002-12-13 20:15:29 +00005433 /* BGP configuration. */
5434 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5435 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5436
5437 /* BGP default ipv4-unicast. */
5438 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5439 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5440
5441 /* BGP default local-preference. */
5442 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5443 vty_out (vty, " bgp default local-preference %d%s",
5444 bgp->default_local_pref, VTY_NEWLINE);
5445
5446 /* BGP client-to-client reflection. */
5447 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5448 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5449
5450 /* BGP cluster ID. */
5451 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5452 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5453 VTY_NEWLINE);
5454
hassoe0701b72004-05-20 09:19:34 +00005455 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005456 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005457 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5458 VTY_NEWLINE);
5459
5460 /* Confederation peer */
5461 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005462 {
hassoe0701b72004-05-20 09:19:34 +00005463 int i;
paul718e3742002-12-13 20:15:29 +00005464
hassoe0701b72004-05-20 09:19:34 +00005465 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005466
hassoe0701b72004-05-20 09:19:34 +00005467 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005468 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005469
hassoe0701b72004-05-20 09:19:34 +00005470 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005471 }
5472
5473 /* BGP enforce-first-as. */
5474 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5475 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5476
5477 /* BGP deterministic-med. */
5478 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5479 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005480
5481 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005482 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5483 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5484 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005485 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5486 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5487
paul718e3742002-12-13 20:15:29 +00005488 /* BGP bestpath method. */
5489 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5490 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005491 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5492 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
Pradosh Mohapatra2fdd4552013-09-07 07:02:36 +00005493 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
5494 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
5495 }
paul718e3742002-12-13 20:15:29 +00005496 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5497 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5498 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5499 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5500 {
5501 vty_out (vty, " bgp bestpath med");
5502 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5503 vty_out (vty, " confed");
5504 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5505 vty_out (vty, " missing-as-worst");
5506 vty_out (vty, "%s", VTY_NEWLINE);
5507 }
5508
5509 /* BGP network import check. */
5510 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5511 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5512
5513 /* BGP scan interval. */
5514 bgp_config_write_scan_time (vty);
5515
5516 /* BGP flag dampening. */
5517 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5518 BGP_CONFIG_DAMPENING))
5519 bgp_config_write_damp (vty);
5520
5521 /* BGP static route configuration. */
5522 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5523
5524 /* BGP redistribute configuration. */
5525 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5526
5527 /* BGP timers configuration. */
5528 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5529 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5530 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5531 bgp->default_holdtime, VTY_NEWLINE);
5532
5533 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005534 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005535 {
5536 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5537 }
5538
5539 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005540 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005541 {
5542 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5543 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5544 }
5545
Josh Bailey165b5ff2011-07-20 20:43:22 -07005546 /* maximum-paths */
5547 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5548
paul718e3742002-12-13 20:15:29 +00005549 /* Distance configuration. */
5550 bgp_config_write_distance (vty, bgp);
5551
5552 /* No auto-summary */
5553 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5554 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5555
5556 /* IPv4 multicast configuration. */
5557 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5558
5559 /* IPv4 VPN configuration. */
5560 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5561
Lou Bergera3fda882016-01-12 13:42:04 -05005562 /* ENCAPv4 configuration. */
5563 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_ENCAP);
5564
paul718e3742002-12-13 20:15:29 +00005565 /* IPv6 unicast configuration. */
5566 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5567
Paul Jakma37a217a2007-04-10 19:20:29 +00005568 /* IPv6 multicast configuration. */
5569 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5570
Lou Berger13c378d2016-01-12 13:41:56 -05005571 /* IPv6 VPN configuration. */
5572 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MPLS_VPN);
5573
Lou Bergera3fda882016-01-12 13:42:04 -05005574 /* ENCAPv6 configuration. */
5575 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_ENCAP);
5576
5577 vty_out (vty, " exit%s", VTY_NEWLINE);
5578
paul718e3742002-12-13 20:15:29 +00005579 write++;
5580 }
5581 return write;
5582}
5583
5584void
paul94f2b392005-06-28 12:44:16 +00005585bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005586{
5587 memset (&bgp_master, 0, sizeof (struct bgp_master));
5588
5589 bm = &bgp_master;
5590 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005591 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005592 bm->port = BGP_PORT_DEFAULT;
5593 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005594 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005595}
paul200df112005-06-01 11:17:05 +00005596
David Lamparter6b0655a2014-06-04 06:53:35 +02005597
paul718e3742002-12-13 20:15:29 +00005598void
paul94f2b392005-06-28 12:44:16 +00005599bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005600{
paul718e3742002-12-13 20:15:29 +00005601 /* BGP VTY commands installation. */
5602 bgp_vty_init ();
5603
paul718e3742002-12-13 20:15:29 +00005604 /* Init zebra. */
Donald Sharp774914f2015-10-14 08:50:39 -04005605 bgp_zebra_init (bm->master);
paul718e3742002-12-13 20:15:29 +00005606
5607 /* BGP inits. */
5608 bgp_attr_init ();
5609 bgp_debug_init ();
5610 bgp_dump_init ();
5611 bgp_route_init ();
5612 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005613 bgp_address_init ();
paul718e3742002-12-13 20:15:29 +00005614 bgp_scan_init ();
5615 bgp_mplsvpn_init ();
Lou Berger298cc2f2016-01-12 13:42:02 -05005616 bgp_encap_init ();
paul718e3742002-12-13 20:15:29 +00005617
5618 /* Access list initialize. */
5619 access_list_init ();
5620 access_list_add_hook (peer_distribute_update);
5621 access_list_delete_hook (peer_distribute_update);
5622
5623 /* Filter list initialize. */
5624 bgp_filter_init ();
5625 as_list_add_hook (peer_aslist_update);
5626 as_list_delete_hook (peer_aslist_update);
5627
5628 /* Prefix list initialize.*/
5629 prefix_list_init ();
5630 prefix_list_add_hook (peer_prefix_list_update);
5631 prefix_list_delete_hook (peer_prefix_list_update);
5632
5633 /* Community list initialize. */
5634 bgp_clist = community_list_init ();
5635
5636#ifdef HAVE_SNMP
5637 bgp_snmp_init ();
5638#endif /* HAVE_SNMP */
5639}
paul545acaf2004-04-20 15:13:15 +00005640
5641void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005642bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005643{
paul545acaf2004-04-20 15:13:15 +00005644 struct bgp *bgp;
5645 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005646 struct listnode *node, *nnode;
5647 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005648
paul1eb8ef22005-04-07 07:30:20 +00005649 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5650 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005651 if (peer->status == Established)
5652 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5653 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005654
paul545acaf2004-04-20 15:13:15 +00005655 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005656
paule210cf92005-06-15 19:15:35 +00005657 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005658 {
5659 work_queue_free (bm->process_main_queue);
5660 bm->process_main_queue = NULL;
5661 }
paule210cf92005-06-15 19:15:35 +00005662 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005663 {
5664 work_queue_free (bm->process_rsclient_queue);
5665 bm->process_rsclient_queue = NULL;
5666 }
paul545acaf2004-04-20 15:13:15 +00005667}