blob: 9521927085061ad4cdadc3e2ea40428985d8f8ad [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
David Lamparterdfb9bd72016-05-24 18:58:07 +02001182int
1183peer_afc_set (struct peer *peer, afi_t afi, safi_t safi, int enable)
1184{
1185 if (enable)
1186 return peer_activate (peer, afi, safi);
1187 else
1188 return peer_deactivate (peer, afi, safi);
1189}
1190
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001191static void
hasso93406d82005-02-02 14:40:33 +00001192peer_nsf_stop (struct peer *peer)
1193{
1194 afi_t afi;
1195 safi_t safi;
1196
1197 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1198 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1199
1200 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +04001201 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +00001202 peer->nsf[afi][safi] = 0;
1203
1204 if (peer->t_gr_restart)
1205 {
1206 BGP_TIMER_OFF (peer->t_gr_restart);
1207 if (BGP_DEBUG (events, EVENTS))
1208 zlog_debug ("%s graceful restart timer stopped", peer->host);
1209 }
1210 if (peer->t_gr_stale)
1211 {
1212 BGP_TIMER_OFF (peer->t_gr_stale);
1213 if (BGP_DEBUG (events, EVENTS))
1214 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1215 }
1216 bgp_clear_route_all (peer);
1217}
1218
Paul Jakmaca058a32006-09-14 02:58:49 +00001219/* Delete peer from confguration.
1220 *
1221 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1222 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1223 *
1224 * This function /should/ take care to be idempotent, to guard against
1225 * it being called multiple times through stray events that come in
1226 * that happen to result in this function being called again. That
1227 * said, getting here for a "Deleted" peer is a bug in the neighbour
1228 * FSM.
1229 */
paul718e3742002-12-13 20:15:29 +00001230int
1231peer_delete (struct peer *peer)
1232{
1233 int i;
1234 afi_t afi;
1235 safi_t safi;
1236 struct bgp *bgp;
1237 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001238 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001239
Paul Jakmaca058a32006-09-14 02:58:49 +00001240 assert (peer->status != Deleted);
1241
paul718e3742002-12-13 20:15:29 +00001242 bgp = peer->bgp;
1243
hasso93406d82005-02-02 14:40:33 +00001244 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1245 peer_nsf_stop (peer);
1246
Chris Caputo228da422009-07-18 05:44:03 +00001247 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001248 relationship. */
1249 if (peer->group)
1250 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001251 if ((pn = listnode_lookup (peer->group->peer, peer)))
1252 {
1253 peer = peer_unlock (peer); /* group->peer list reference */
1254 list_delete_node (peer->group->peer, pn);
1255 }
paul718e3742002-12-13 20:15:29 +00001256 peer->group = NULL;
1257 }
paul200df112005-06-01 11:17:05 +00001258
paul718e3742002-12-13 20:15:29 +00001259 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001260 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1261 * executed after peer structure is deleted.
1262 */
hassoe0701b72004-05-20 09:19:34 +00001263 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001264 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001265 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001266
1267 /* Password configuration */
1268 if (peer->password)
1269 {
1270 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1271 peer->password = NULL;
1272
1273 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1274 bgp_md5_set (peer);
1275 }
1276
Paul Jakmaca058a32006-09-14 02:58:49 +00001277 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001278
paul718e3742002-12-13 20:15:29 +00001279 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001280 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1281 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001282 {
Chris Caputo228da422009-07-18 05:44:03 +00001283 peer_unlock (peer); /* bgp peer list reference */
1284 list_delete_node (bgp->peer, pn);
1285 }
paul200df112005-06-01 11:17:05 +00001286
Chris Caputo228da422009-07-18 05:44:03 +00001287 if (peer_rsclient_active (peer)
1288 && (pn = listnode_lookup (bgp->rsclient, peer)))
1289 {
1290 peer_unlock (peer); /* rsclient list reference */
1291 list_delete_node (bgp->rsclient, pn);
1292
1293 /* Clear our own rsclient ribs. */
1294 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1295 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1296 if (CHECK_FLAG(peer->af_flags[afi][safi],
1297 PEER_FLAG_RSERVER_CLIENT))
1298 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001299 }
1300
1301 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1302 member of a peer_group. */
1303 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1304 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1305 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001306 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001307
paul200df112005-06-01 11:17:05 +00001308 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001309 if (peer->ibuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001310 {
1311 stream_free (peer->ibuf);
1312 peer->ibuf = NULL;
1313 }
1314
paul718e3742002-12-13 20:15:29 +00001315 if (peer->obuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001316 {
1317 stream_fifo_free (peer->obuf);
1318 peer->obuf = NULL;
1319 }
1320
paul718e3742002-12-13 20:15:29 +00001321 if (peer->work)
Daniel Walton363c9032015-10-21 06:42:54 -07001322 {
1323 stream_free (peer->work);
1324 peer->work = NULL;
1325 }
1326
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00001327 if (peer->scratch)
Daniel Walton363c9032015-10-21 06:42:54 -07001328 {
1329 stream_free(peer->scratch);
1330 peer->scratch = NULL;
1331 }
Paul Jakma18937402006-07-27 19:05:12 +00001332
paul718e3742002-12-13 20:15:29 +00001333 /* Local and remote addresses. */
1334 if (peer->su_local)
Daniel Walton363c9032015-10-21 06:42:54 -07001335 {
1336 sockunion_free (peer->su_local);
1337 peer->su_local = NULL;
1338 }
1339
paul718e3742002-12-13 20:15:29 +00001340 if (peer->su_remote)
Daniel Walton363c9032015-10-21 06:42:54 -07001341 {
1342 sockunion_free (peer->su_remote);
1343 peer->su_remote = NULL;
1344 }
paul200df112005-06-01 11:17:05 +00001345
paul718e3742002-12-13 20:15:29 +00001346 /* Free filter related memory. */
1347 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1348 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1349 {
1350 filter = &peer->filter[afi][safi];
1351
1352 for (i = FILTER_IN; i < FILTER_MAX; i++)
1353 {
1354 if (filter->dlist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001355 {
1356 free(filter->dlist[i].name);
1357 filter->dlist[i].name = NULL;
1358 }
1359
paul718e3742002-12-13 20:15:29 +00001360 if (filter->plist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001361 {
1362 free(filter->plist[i].name);
1363 filter->plist[i].name = NULL;
1364 }
1365
paul718e3742002-12-13 20:15:29 +00001366 if (filter->aslist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001367 {
1368 free(filter->aslist[i].name);
1369 filter->aslist[i].name = NULL;
1370 }
paul200df112005-06-01 11:17:05 +00001371 }
Daniel Walton363c9032015-10-21 06:42:54 -07001372
paul200df112005-06-01 11:17:05 +00001373 for (i = RMAP_IN; i < RMAP_MAX; i++)
1374 {
paul718e3742002-12-13 20:15:29 +00001375 if (filter->map[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001376 {
1377 free (filter->map[i].name);
1378 filter->map[i].name = NULL;
1379 }
paul718e3742002-12-13 20:15:29 +00001380 }
1381
1382 if (filter->usmap.name)
Daniel Walton363c9032015-10-21 06:42:54 -07001383 {
1384 free (filter->usmap.name);
1385 filter->usmap.name = NULL;
1386 }
paul718e3742002-12-13 20:15:29 +00001387
1388 if (peer->default_rmap[afi][safi].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001389 {
1390 free (peer->default_rmap[afi][safi].name);
1391 peer->default_rmap[afi][safi].name = NULL;
1392 }
paul718e3742002-12-13 20:15:29 +00001393 }
paul200df112005-06-01 11:17:05 +00001394
Lou Berger82dd7072016-01-12 13:41:57 -05001395 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETING))
1396 bgp_peer_clear_node_queue_drain_immediate(peer);
1397
paul200df112005-06-01 11:17:05 +00001398 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001399
1400 return 0;
1401}
David Lamparter6b0655a2014-06-04 06:53:35 +02001402
paul94f2b392005-06-28 12:44:16 +00001403static int
paul718e3742002-12-13 20:15:29 +00001404peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1405{
1406 return strcmp (g1->name, g2->name);
1407}
1408
1409/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001410static int
paul718e3742002-12-13 20:15:29 +00001411peer_group_active (struct peer *peer)
1412{
1413 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1414 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1415 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05001416 || peer->af_group[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00001417 || peer->af_group[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05001418 || peer->af_group[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05001419 || peer->af_group[AFI_IP6][SAFI_MPLS_VPN]
1420 || peer->af_group[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00001421 return 1;
1422 return 0;
1423}
1424
1425/* Peer group cofiguration. */
1426static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001427peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001428{
1429 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1430 sizeof (struct peer_group));
1431}
1432
paul94f2b392005-06-28 12:44:16 +00001433static void
paul718e3742002-12-13 20:15:29 +00001434peer_group_free (struct peer_group *group)
1435{
1436 XFREE (MTYPE_PEER_GROUP, group);
1437}
1438
1439struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001440peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001441{
1442 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001443 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001444
paul1eb8ef22005-04-07 07:30:20 +00001445 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001446 {
1447 if (strcmp (group->name, name) == 0)
1448 return group;
1449 }
1450 return NULL;
1451}
1452
1453struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001454peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001455{
1456 struct peer_group *group;
1457
1458 group = peer_group_lookup (bgp, name);
1459 if (group)
1460 return group;
1461
1462 group = peer_group_new ();
1463 group->bgp = bgp;
1464 group->name = strdup (name);
1465 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001466 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001467 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1468 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001469 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001470 group->conf->group = group;
1471 group->conf->as = 0;
1472 group->conf->ttl = 1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001473 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001474 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1475 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1476 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1477 group->conf->keepalive = 0;
1478 group->conf->holdtime = 0;
1479 group->conf->connect = 0;
1480 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1481 listnode_add_sort (bgp->group, group);
1482
1483 return 0;
1484}
1485
paul94f2b392005-06-28 12:44:16 +00001486static void
paul718e3742002-12-13 20:15:29 +00001487peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1488 afi_t afi, safi_t safi)
1489{
1490 int in = FILTER_IN;
1491 int out = FILTER_OUT;
1492 struct peer *conf;
1493 struct bgp_filter *pfilter;
1494 struct bgp_filter *gfilter;
1495
1496 conf = group->conf;
1497 pfilter = &peer->filter[afi][safi];
1498 gfilter = &conf->filter[afi][safi];
1499
1500 /* remote-as */
1501 if (conf->as)
1502 peer->as = conf->as;
1503
1504 /* remote-as */
1505 if (conf->change_local_as)
1506 peer->change_local_as = conf->change_local_as;
1507
1508 /* TTL */
1509 peer->ttl = conf->ttl;
1510
Nick Hilliardfa411a22011-03-23 15:33:17 +00001511 /* GTSM hops */
1512 peer->gtsm_hops = conf->gtsm_hops;
1513
paul718e3742002-12-13 20:15:29 +00001514 /* Weight */
1515 peer->weight = conf->weight;
1516
1517 /* peer flags apply */
1518 peer->flags = conf->flags;
1519 /* peer af_flags apply */
1520 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1521 /* peer config apply */
1522 peer->config = conf->config;
1523
1524 /* peer timers apply */
1525 peer->holdtime = conf->holdtime;
1526 peer->keepalive = conf->keepalive;
1527 peer->connect = conf->connect;
1528 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1529 peer->v_connect = conf->connect;
1530 else
1531 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1532
1533 /* advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +03001534 if (CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
1535 peer->v_routeadv = conf->routeadv;
paul718e3742002-12-13 20:15:29 +00001536 else
Daniel Walton0d7435f2015-10-22 11:35:20 +03001537 if (peer_sort (peer) == BGP_PEER_IBGP)
1538 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1539 else
1540 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul718e3742002-12-13 20:15:29 +00001541
Paul Jakma0df7c912008-07-21 21:02:49 +00001542 /* password apply */
Roman Hoog Antink0e4303d2013-01-18 13:52:03 +01001543 if (conf->password && !peer->password)
Paul Jakma0df7c912008-07-21 21:02:49 +00001544 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
Paul Jakma0df7c912008-07-21 21:02:49 +00001545
1546 bgp_md5_set (peer);
1547
paul718e3742002-12-13 20:15:29 +00001548 /* maximum-prefix */
1549 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001550 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001551 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001552
1553 /* allowas-in */
1554 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1555
paulfee0f4c2004-09-13 05:12:46 +00001556 /* route-server-client */
1557 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1558 {
1559 /* Make peer's RIB point to group's RIB. */
1560 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1561
1562 /* Import policy. */
1563 if (pfilter->map[RMAP_IMPORT].name)
1564 free (pfilter->map[RMAP_IMPORT].name);
1565 if (gfilter->map[RMAP_IMPORT].name)
1566 {
1567 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1568 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1569 }
1570 else
1571 {
1572 pfilter->map[RMAP_IMPORT].name = NULL;
1573 pfilter->map[RMAP_IMPORT].map = NULL;
1574 }
1575
1576 /* Export policy. */
1577 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1578 {
1579 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1580 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1581 }
1582 }
1583
paul718e3742002-12-13 20:15:29 +00001584 /* default-originate route-map */
1585 if (conf->default_rmap[afi][safi].name)
1586 {
1587 if (peer->default_rmap[afi][safi].name)
1588 free (peer->default_rmap[afi][safi].name);
1589 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1590 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1591 }
1592
1593 /* update-source apply */
1594 if (conf->update_source)
1595 {
1596 if (peer->update_source)
1597 sockunion_free (peer->update_source);
1598 if (peer->update_if)
1599 {
1600 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1601 peer->update_if = NULL;
1602 }
1603 peer->update_source = sockunion_dup (conf->update_source);
1604 }
1605 else if (conf->update_if)
1606 {
1607 if (peer->update_if)
1608 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1609 if (peer->update_source)
1610 {
1611 sockunion_free (peer->update_source);
1612 peer->update_source = NULL;
1613 }
1614 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1615 }
1616
1617 /* inbound filter apply */
1618 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1619 {
1620 if (pfilter->dlist[in].name)
1621 free (pfilter->dlist[in].name);
1622 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1623 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1624 }
1625 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1626 {
1627 if (pfilter->plist[in].name)
1628 free (pfilter->plist[in].name);
1629 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1630 pfilter->plist[in].plist = gfilter->plist[in].plist;
1631 }
1632 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1633 {
1634 if (pfilter->aslist[in].name)
1635 free (pfilter->aslist[in].name);
1636 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1637 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1638 }
paulfee0f4c2004-09-13 05:12:46 +00001639 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001640 {
paulfee0f4c2004-09-13 05:12:46 +00001641 if (pfilter->map[RMAP_IN].name)
1642 free (pfilter->map[RMAP_IN].name);
1643 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1644 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001645 }
1646
1647 /* outbound filter apply */
1648 if (gfilter->dlist[out].name)
1649 {
1650 if (pfilter->dlist[out].name)
1651 free (pfilter->dlist[out].name);
1652 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1653 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1654 }
1655 else
1656 {
1657 if (pfilter->dlist[out].name)
1658 free (pfilter->dlist[out].name);
1659 pfilter->dlist[out].name = NULL;
1660 pfilter->dlist[out].alist = NULL;
1661 }
1662 if (gfilter->plist[out].name)
1663 {
1664 if (pfilter->plist[out].name)
1665 free (pfilter->plist[out].name);
1666 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1667 pfilter->plist[out].plist = gfilter->plist[out].plist;
1668 }
1669 else
1670 {
1671 if (pfilter->plist[out].name)
1672 free (pfilter->plist[out].name);
1673 pfilter->plist[out].name = NULL;
1674 pfilter->plist[out].plist = NULL;
1675 }
1676 if (gfilter->aslist[out].name)
1677 {
1678 if (pfilter->aslist[out].name)
1679 free (pfilter->aslist[out].name);
1680 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1681 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1682 }
1683 else
1684 {
1685 if (pfilter->aslist[out].name)
1686 free (pfilter->aslist[out].name);
1687 pfilter->aslist[out].name = NULL;
1688 pfilter->aslist[out].aslist = NULL;
1689 }
paulfee0f4c2004-09-13 05:12:46 +00001690 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001691 {
paulfee0f4c2004-09-13 05:12:46 +00001692 if (pfilter->map[RMAP_OUT].name)
1693 free (pfilter->map[RMAP_OUT].name);
1694 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1695 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001696 }
1697 else
1698 {
paulfee0f4c2004-09-13 05:12:46 +00001699 if (pfilter->map[RMAP_OUT].name)
1700 free (pfilter->map[RMAP_OUT].name);
1701 pfilter->map[RMAP_OUT].name = NULL;
1702 pfilter->map[RMAP_OUT].map = NULL;
1703 }
1704
1705 /* RS-client's import/export route-maps. */
1706 if (gfilter->map[RMAP_IMPORT].name)
1707 {
1708 if (pfilter->map[RMAP_IMPORT].name)
1709 free (pfilter->map[RMAP_IMPORT].name);
1710 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1711 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1712 }
1713 else
1714 {
1715 if (pfilter->map[RMAP_IMPORT].name)
1716 free (pfilter->map[RMAP_IMPORT].name);
1717 pfilter->map[RMAP_IMPORT].name = NULL;
1718 pfilter->map[RMAP_IMPORT].map = NULL;
1719 }
1720 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1721 {
1722 if (pfilter->map[RMAP_EXPORT].name)
1723 free (pfilter->map[RMAP_EXPORT].name);
1724 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1725 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001726 }
1727
1728 if (gfilter->usmap.name)
1729 {
1730 if (pfilter->usmap.name)
1731 free (pfilter->usmap.name);
1732 pfilter->usmap.name = strdup (gfilter->usmap.name);
1733 pfilter->usmap.map = gfilter->usmap.map;
1734 }
1735 else
1736 {
1737 if (pfilter->usmap.name)
1738 free (pfilter->usmap.name);
1739 pfilter->usmap.name = NULL;
1740 pfilter->usmap.map = NULL;
1741 }
1742}
1743
1744/* Peer group's remote AS configuration. */
1745int
paulfd79ac92004-10-13 05:06:08 +00001746peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001747{
1748 struct peer_group *group;
1749 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001750 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001751
1752 group = peer_group_lookup (bgp, group_name);
1753 if (! group)
1754 return -1;
1755
1756 if (group->conf->as == *as)
1757 return 0;
1758
1759 /* When we setup peer-group AS number all peer group member's AS
1760 number must be updated to same number. */
1761 peer_as_change (group->conf, *as);
1762
paul1eb8ef22005-04-07 07:30:20 +00001763 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001764 {
1765 if (peer->as != *as)
1766 peer_as_change (peer, *as);
1767 }
1768
1769 return 0;
1770}
1771
1772int
1773peer_group_delete (struct peer_group *group)
1774{
1775 struct bgp *bgp;
1776 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001777 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001778
1779 bgp = group->bgp;
1780
paul1eb8ef22005-04-07 07:30:20 +00001781 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001782 {
paul718e3742002-12-13 20:15:29 +00001783 peer_delete (peer);
1784 }
1785 list_delete (group->peer);
1786
1787 free (group->name);
1788 group->name = NULL;
1789
1790 group->conf->group = NULL;
1791 peer_delete (group->conf);
1792
1793 /* Delete from all peer_group list. */
1794 listnode_delete (bgp->group, group);
1795
1796 peer_group_free (group);
1797
1798 return 0;
1799}
1800
1801int
1802peer_group_remote_as_delete (struct peer_group *group)
1803{
1804 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001805 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001806
1807 if (! group->conf->as)
1808 return 0;
1809
paul1eb8ef22005-04-07 07:30:20 +00001810 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001811 {
paul718e3742002-12-13 20:15:29 +00001812 peer_delete (peer);
1813 }
1814 list_delete_all_node (group->peer);
1815
1816 group->conf->as = 0;
1817
1818 return 0;
1819}
1820
1821/* Bind specified peer to peer group. */
1822int
1823peer_group_bind (struct bgp *bgp, union sockunion *su,
1824 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1825{
1826 struct peer *peer;
1827 int first_member = 0;
1828
1829 /* Check peer group's address family. */
1830 if (! group->conf->afc[afi][safi])
1831 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1832
1833 /* Lookup the peer. */
1834 peer = peer_lookup (bgp, su);
1835
1836 /* Create a new peer. */
1837 if (! peer)
1838 {
1839 if (! group->conf->as)
1840 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1841
1842 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1843 peer->group = group;
1844 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001845
Paul Jakmaca058a32006-09-14 02:58:49 +00001846 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001847 listnode_add (group->peer, peer);
1848 peer_group2peer_config_copy (group, peer, afi, safi);
1849
1850 return 0;
1851 }
1852
1853 /* When the peer already belongs to peer group, check the consistency. */
1854 if (peer->af_group[afi][safi])
1855 {
1856 if (strcmp (peer->group->name, group->name) != 0)
1857 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1858
1859 return 0;
1860 }
1861
1862 /* Check current peer group configuration. */
1863 if (peer_group_active (peer)
1864 && strcmp (peer->group->name, group->name) != 0)
1865 return BGP_ERR_PEER_GROUP_MISMATCH;
1866
1867 if (! group->conf->as)
1868 {
1869 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1870 && peer_sort (group->conf) != peer_sort (peer))
1871 {
1872 if (as)
1873 *as = peer->as;
1874 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1875 }
1876
1877 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1878 first_member = 1;
1879 }
1880
1881 peer->af_group[afi][safi] = 1;
1882 peer->afc[afi][safi] = 1;
1883 if (! peer->group)
1884 {
1885 peer->group = group;
paul200df112005-06-01 11:17:05 +00001886
Paul Jakmaca058a32006-09-14 02:58:49 +00001887 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001888 listnode_add (group->peer, peer);
1889 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001890 else
1891 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001892
1893 if (first_member)
1894 {
1895 /* Advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +03001896 if (! CHECK_FLAG (group->conf->config, PEER_CONFIG_ROUTEADV))
1897 {
1898 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1899 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1900 else
1901 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1902 }
paul718e3742002-12-13 20:15:29 +00001903
1904 /* ebgp-multihop reset */
1905 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1906 group->conf->ttl = 255;
1907
1908 /* local-as reset */
1909 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1910 {
1911 group->conf->change_local_as = 0;
1912 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001913 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001914 }
1915 }
paulfee0f4c2004-09-13 05:12:46 +00001916
1917 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1918 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001919 struct listnode *pn;
1920
paulfee0f4c2004-09-13 05:12:46 +00001921 /* If it's not configured as RSERVER_CLIENT in any other address
1922 family, without being member of a peer_group, remove it from
1923 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001924 if (! peer_rsclient_active (peer)
1925 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001926 {
1927 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001928 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001929
1930 /* Clear our own rsclient rib for this afi/safi. */
1931 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001932 }
paulfee0f4c2004-09-13 05:12:46 +00001933
Paul Jakmab608d5b2008-07-02 02:12:07 +00001934 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001935
1936 /* Import policy. */
1937 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1938 {
1939 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1940 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1941 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1942 }
1943
1944 /* Export policy. */
1945 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1946 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1947 {
1948 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1949 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1950 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1951 }
1952 }
1953
paul718e3742002-12-13 20:15:29 +00001954 peer_group2peer_config_copy (group, peer, afi, safi);
1955
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001956 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001957 {
1958 peer->last_reset = PEER_DOWN_RMAP_BIND;
1959 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1960 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1961 }
paul718e3742002-12-13 20:15:29 +00001962 else
1963 BGP_EVENT_ADD (peer, BGP_Stop);
1964
1965 return 0;
1966}
1967
1968int
1969peer_group_unbind (struct bgp *bgp, struct peer *peer,
1970 struct peer_group *group, afi_t afi, safi_t safi)
1971{
1972 if (! peer->af_group[afi][safi])
1973 return 0;
1974
1975 if (group != peer->group)
1976 return BGP_ERR_PEER_GROUP_MISMATCH;
1977
1978 peer->af_group[afi][safi] = 0;
1979 peer->afc[afi][safi] = 0;
1980 peer_af_flag_reset (peer, afi, safi);
1981
paulfee0f4c2004-09-13 05:12:46 +00001982 if (peer->rib[afi][safi])
1983 peer->rib[afi][safi] = NULL;
1984
paul718e3742002-12-13 20:15:29 +00001985 if (! peer_group_active (peer))
1986 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001987 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001988 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001989 listnode_delete (group->peer, peer);
1990 peer->group = NULL;
1991 if (group->conf->as)
1992 {
1993 peer_delete (peer);
1994 return 0;
1995 }
1996 peer_global_config_reset (peer);
1997 }
1998
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001999 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002000 {
2001 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
2002 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2003 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2004 }
paul718e3742002-12-13 20:15:29 +00002005 else
2006 BGP_EVENT_ADD (peer, BGP_Stop);
2007
2008 return 0;
2009}
David Lamparter6b0655a2014-06-04 06:53:35 +02002010
Vipin Kumardd49eb12014-09-30 14:36:38 -07002011
2012static int
2013bgp_startup_timer_expire (struct thread *thread)
2014{
2015 struct bgp *bgp;
2016
2017 bgp = THREAD_ARG (thread);
2018 bgp->t_startup = NULL;
2019
2020 return 0;
2021}
2022
paul718e3742002-12-13 20:15:29 +00002023/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00002024static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002025bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002026{
2027 struct bgp *bgp;
2028 afi_t afi;
2029 safi_t safi;
2030
paul200df112005-06-01 11:17:05 +00002031 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
2032 return NULL;
2033
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002034 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00002035 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00002036 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00002037
2038 bgp->peer = list_new ();
2039 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
2040
2041 bgp->group = list_new ();
2042 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
2043
paulfee0f4c2004-09-13 05:12:46 +00002044 bgp->rsclient = list_new ();
2045 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
2046
paul718e3742002-12-13 20:15:29 +00002047 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2048 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2049 {
Paul Jakma64e580a2006-02-21 01:09:01 +00002050 bgp->route[afi][safi] = bgp_table_init (afi, safi);
2051 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
2052 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07002053 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
2054 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00002055 }
2056
2057 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
2058 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
2059 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00002060 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
2061 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07002062 bgp_flag_set (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES);
paul718e3742002-12-13 20:15:29 +00002063
2064 bgp->as = *as;
2065
2066 if (name)
2067 bgp->name = strdup (name);
2068
Donald Sharp774914f2015-10-14 08:50:39 -04002069 THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire,
Vipin Kumardd49eb12014-09-30 14:36:38 -07002070 bgp, bgp->restart_time);
2071
paul718e3742002-12-13 20:15:29 +00002072 return bgp;
2073}
2074
2075/* Return first entry of BGP. */
2076struct bgp *
paul94f2b392005-06-28 12:44:16 +00002077bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00002078{
Lou Berger056f3762013-04-10 12:30:04 -07002079 if (bm && bm->bgp && bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00002080 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00002081 return NULL;
2082}
2083
2084/* Lookup BGP entry. */
2085struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002086bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00002087{
2088 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002089 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002090
paul1eb8ef22005-04-07 07:30:20 +00002091 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002092 if (bgp->as == as
2093 && ((bgp->name == NULL && name == NULL)
2094 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
2095 return bgp;
2096 return NULL;
2097}
2098
2099/* Lookup BGP structure by view name. */
2100struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002101bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002102{
2103 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002104 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002105
paul1eb8ef22005-04-07 07:30:20 +00002106 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002107 if ((bgp->name == NULL && name == NULL)
2108 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2109 return bgp;
2110 return NULL;
2111}
2112
2113/* Called from VTY commands. */
2114int
paulfd79ac92004-10-13 05:06:08 +00002115bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002116{
2117 struct bgp *bgp;
2118
2119 /* Multiple instance check. */
2120 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2121 {
2122 if (name)
2123 bgp = bgp_lookup_by_name (name);
2124 else
2125 bgp = bgp_get_default ();
2126
2127 /* Already exists. */
2128 if (bgp)
2129 {
2130 if (bgp->as != *as)
2131 {
2132 *as = bgp->as;
2133 return BGP_ERR_INSTANCE_MISMATCH;
2134 }
2135 *bgp_val = bgp;
2136 return 0;
2137 }
2138 }
2139 else
2140 {
2141 /* BGP instance name can not be specified for single instance. */
2142 if (name)
2143 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2144
2145 /* Get default BGP structure if exists. */
2146 bgp = bgp_get_default ();
2147
2148 if (bgp)
2149 {
2150 if (bgp->as != *as)
2151 {
2152 *as = bgp->as;
2153 return BGP_ERR_AS_MISMATCH;
2154 }
2155 *bgp_val = bgp;
2156 return 0;
2157 }
2158 }
2159
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002160 bgp = bgp_create (as, name);
2161 bgp_router_id_set(bgp, &router_id_zebra);
2162 *bgp_val = bgp;
2163
Paul Jakmaad12dde2012-06-13 22:50:07 +01002164 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002165 if (list_isempty(bm->bgp)
2166 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002167 {
2168 if (bgp_socket (bm->port, bm->address) < 0)
2169 return BGP_ERR_INVALID_VALUE;
2170 }
2171
paul718e3742002-12-13 20:15:29 +00002172 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002173
2174 return 0;
2175}
2176
2177/* Delete BGP instance. */
2178int
2179bgp_delete (struct bgp *bgp)
2180{
2181 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002182 struct peer_group *group;
Denil Vira57cd5e72015-08-10 12:46:14 -07002183 struct listnode *node, *pnode;
2184 struct listnode *next, *pnext;
paul718e3742002-12-13 20:15:29 +00002185 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002186 int i;
2187
Lou Berger82dd7072016-01-12 13:41:57 -05002188 SET_FLAG(bgp->flags, BGP_FLAG_DELETING);
2189
David Lampartercffe7802014-12-07 03:27:13 +01002190 THREAD_OFF (bgp->t_startup);
2191
paul718e3742002-12-13 20:15:29 +00002192 /* Delete static route. */
2193 bgp_static_delete (bgp);
2194
2195 /* Unset redistribution. */
2196 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2197 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2198 if (i != ZEBRA_ROUTE_BGP)
2199 bgp_redistribute_unset (bgp, afi, i);
2200
paul1eb8ef22005-04-07 07:30:20 +00002201 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002202 {
2203 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2204 {
2205 /* Send notify to remote peer. */
2206 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2207 }
2208
2209 peer_delete (peer);
2210 }
paul718e3742002-12-13 20:15:29 +00002211
Chris Caputo228da422009-07-18 05:44:03 +00002212 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002213 {
Denil Vira57cd5e72015-08-10 12:46:14 -07002214 for (ALL_LIST_ELEMENTS (group->peer, pnode, pnext, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002215 {
2216 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2217 {
2218 /* Send notify to remote peer. */
2219 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2220 }
2221 }
2222 peer_group_delete (group);
2223 }
Chris Caputo228da422009-07-18 05:44:03 +00002224
2225 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002226
2227 if (bgp->peer_self) {
2228 peer_delete(bgp->peer_self);
2229 bgp->peer_self = NULL;
2230 }
Lou Berger82dd7072016-01-12 13:41:57 -05002231
2232 /*
2233 * Free pending deleted routes. Unfortunately, it also has to process
2234 * all the pending activity for other instances of struct bgp.
2235 *
2236 * This call was added to achieve clean memory allocation at exit,
2237 * for the sake of valgrind.
2238 */
2239 bgp_process_queues_drain_immediate();
2240
Paul Jakmafd35b942009-07-16 19:27:32 +01002241 /* Remove visibility via the master list - there may however still be
2242 * routes to be processed still referencing the struct bgp.
2243 */
2244 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002245 if (list_isempty(bm->bgp))
2246 bgp_close ();
2247
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002248 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002249
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002250 return 0;
2251}
2252
2253static void bgp_free (struct bgp *);
2254
2255void
2256bgp_lock (struct bgp *bgp)
2257{
2258 ++bgp->lock;
2259}
2260
2261void
2262bgp_unlock(struct bgp *bgp)
2263{
Chris Caputo228da422009-07-18 05:44:03 +00002264 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002265 if (--bgp->lock == 0)
2266 bgp_free (bgp);
2267}
2268
2269static void
2270bgp_free (struct bgp *bgp)
2271{
2272 afi_t afi;
2273 safi_t safi;
2274
2275 list_delete (bgp->group);
2276 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002277 list_delete (bgp->rsclient);
2278
paul718e3742002-12-13 20:15:29 +00002279 if (bgp->name)
2280 free (bgp->name);
2281
2282 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2283 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2284 {
2285 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002286 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002287 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002288 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002289 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002290 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002291 }
2292 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002293}
David Lamparter6b0655a2014-06-04 06:53:35 +02002294
paul718e3742002-12-13 20:15:29 +00002295struct peer *
2296peer_lookup (struct bgp *bgp, union sockunion *su)
2297{
2298 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002299 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002300
Steve Hillfc4dc592009-07-28 17:54:35 +01002301 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002302 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002303 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2304 if (sockunion_same (&peer->su, su)
2305 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2306 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002307 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002308 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002309 {
2310 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002311
Paul Jakma2158ad22009-07-28 18:10:55 +01002312 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2313 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2314 if (sockunion_same (&peer->su, su)
2315 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2316 return peer;
paul718e3742002-12-13 20:15:29 +00002317 }
2318 return NULL;
2319}
2320
2321struct peer *
2322peer_lookup_with_open (union sockunion *su, as_t remote_as,
2323 struct in_addr *remote_id, int *as)
2324{
2325 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002326 struct listnode *node;
2327 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002328 struct bgp *bgp;
2329
Steve Hillfc4dc592009-07-28 17:54:35 +01002330 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002331 return NULL;
2332
Paul Jakma9d878772009-08-05 16:25:16 +01002333 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002334 {
Paul Jakma9d878772009-08-05 16:25:16 +01002335 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2336 {
2337 if (sockunion_same (&peer->su, su)
2338 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2339 {
2340 if (peer->as == remote_as
2341 && peer->remote_id.s_addr == remote_id->s_addr)
2342 return peer;
2343 if (peer->as == remote_as)
2344 *as = 1;
2345 }
2346 }
2347
2348 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2349 {
2350 if (sockunion_same (&peer->su, su)
2351 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2352 {
2353 if (peer->as == remote_as
2354 && peer->remote_id.s_addr == 0)
2355 return peer;
2356 if (peer->as == remote_as)
2357 *as = 1;
2358 }
2359 }
paul718e3742002-12-13 20:15:29 +00002360 }
2361 return NULL;
2362}
David Lamparter6b0655a2014-06-04 06:53:35 +02002363
paul718e3742002-12-13 20:15:29 +00002364/* If peer is configured at least one address family return 1. */
2365int
2366peer_active (struct peer *peer)
2367{
2368 if (peer->afc[AFI_IP][SAFI_UNICAST]
2369 || peer->afc[AFI_IP][SAFI_MULTICAST]
2370 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05002371 || peer->afc[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00002372 || peer->afc[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05002373 || peer->afc[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05002374 || peer->afc[AFI_IP6][SAFI_MPLS_VPN]
2375 || peer->afc[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00002376 return 1;
2377 return 0;
2378}
2379
2380/* If peer is negotiated at least one address family return 1. */
2381int
2382peer_active_nego (struct peer *peer)
2383{
2384 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2385 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2386 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05002387 || peer->afc_nego[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00002388 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05002389 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05002390 || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
2391 || peer->afc_nego[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00002392 return 1;
2393 return 0;
2394}
David Lamparter6b0655a2014-06-04 06:53:35 +02002395
paul718e3742002-12-13 20:15:29 +00002396/* peer_flag_change_type. */
2397enum peer_change_type
2398{
2399 peer_change_none,
2400 peer_change_reset,
2401 peer_change_reset_in,
2402 peer_change_reset_out,
2403};
2404
paul94f2b392005-06-28 12:44:16 +00002405static void
paul718e3742002-12-13 20:15:29 +00002406peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2407 enum peer_change_type type)
2408{
2409 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2410 return;
2411
Stephen Hemmingerd9d4ae52010-01-13 00:32:39 +00002412 if (peer->status != Established)
2413 return;
2414
paul718e3742002-12-13 20:15:29 +00002415 if (type == peer_change_reset)
2416 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2417 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2418 else if (type == peer_change_reset_in)
2419 {
2420 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2421 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2422 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2423 else
2424 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2425 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2426 }
2427 else if (type == peer_change_reset_out)
2428 bgp_announce_route (peer, afi, safi);
2429}
2430
2431struct peer_flag_action
2432{
2433 /* Peer's flag. */
2434 u_int32_t flag;
2435
2436 /* This flag can be set for peer-group member. */
2437 u_char not_for_member;
2438
2439 /* Action when the flag is changed. */
2440 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002441
2442 /* Peer down cause */
2443 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002444};
2445
Stephen Hemminger03621952009-07-21 16:27:20 -07002446static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002447 {
2448 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2449 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2450 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2451 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2452 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002453 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002454 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002455 { 0, 0, 0 }
2456 };
2457
Stephen Hemminger03621952009-07-21 16:27:20 -07002458static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002459 {
2460 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2461 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2462 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2463 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2464 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2465 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2466 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2467 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2468 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2469 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2470 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2471 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2472 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002473 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
Timo Teräs9e7a53c2014-04-24 10:22:37 +03002474 { PEER_FLAG_NEXTHOP_SELF_ALL, 1, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002475 { 0, 0, 0 }
2476 };
2477
2478/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002479static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002480peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002481 struct peer_flag_action *action, u_int32_t flag)
2482{
2483 int i;
2484 int found = 0;
2485 int reset_in = 0;
2486 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002487 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002488
2489 /* Check peer's frag action. */
2490 for (i = 0; i < size; i++)
2491 {
2492 match = &action_list[i];
2493
2494 if (match->flag == 0)
2495 break;
2496
2497 if (match->flag & flag)
2498 {
2499 found = 1;
2500
2501 if (match->type == peer_change_reset_in)
2502 reset_in = 1;
2503 if (match->type == peer_change_reset_out)
2504 reset_out = 1;
2505 if (match->type == peer_change_reset)
2506 {
2507 reset_in = 1;
2508 reset_out = 1;
2509 }
2510 if (match->not_for_member)
2511 action->not_for_member = 1;
2512 }
2513 }
2514
2515 /* Set peer clear type. */
2516 if (reset_in && reset_out)
2517 action->type = peer_change_reset;
2518 else if (reset_in)
2519 action->type = peer_change_reset_in;
2520 else if (reset_out)
2521 action->type = peer_change_reset_out;
2522 else
2523 action->type = peer_change_none;
2524
2525 return found;
2526}
2527
paul94f2b392005-06-28 12:44:16 +00002528static void
paul718e3742002-12-13 20:15:29 +00002529peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2530{
2531 if (flag == PEER_FLAG_SHUTDOWN)
2532 {
2533 if (CHECK_FLAG (peer->flags, flag))
2534 {
hasso93406d82005-02-02 14:40:33 +00002535 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2536 peer_nsf_stop (peer);
2537
hasso0a486e52005-02-01 20:57:17 +00002538 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2539 if (peer->t_pmax_restart)
2540 {
2541 BGP_TIMER_OFF (peer->t_pmax_restart);
2542 if (BGP_DEBUG (events, EVENTS))
2543 zlog_debug ("%s Maximum-prefix restart timer canceled",
2544 peer->host);
2545 }
2546
hasso93406d82005-02-02 14:40:33 +00002547 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2548 peer_nsf_stop (peer);
2549
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002550 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002551 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2552 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2553 else
2554 BGP_EVENT_ADD (peer, BGP_Stop);
2555 }
2556 else
2557 {
2558 peer->v_start = BGP_INIT_START_TIMER;
2559 BGP_EVENT_ADD (peer, BGP_Stop);
2560 }
2561 }
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002562 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002563 {
hassoc9502432005-02-01 22:01:48 +00002564 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2565 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2566 else if (flag == PEER_FLAG_PASSIVE)
2567 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002568 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002569 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002570
hassoc9502432005-02-01 22:01:48 +00002571 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2572 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002573 }
2574 else
2575 BGP_EVENT_ADD (peer, BGP_Stop);
2576}
2577
2578/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002579static int
paul718e3742002-12-13 20:15:29 +00002580peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2581{
2582 int found;
2583 int size;
2584 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002585 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002586 struct peer_flag_action action;
2587
2588 memset (&action, 0, sizeof (struct peer_flag_action));
2589 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2590
2591 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2592
2593 /* No flag action is found. */
2594 if (! found)
2595 return BGP_ERR_INVALID_FLAG;
2596
2597 /* Not for peer-group member. */
2598 if (action.not_for_member && peer_group_active (peer))
2599 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2600
2601 /* When unset the peer-group member's flag we have to check
2602 peer-group configuration. */
2603 if (! set && peer_group_active (peer))
2604 if (CHECK_FLAG (peer->group->conf->flags, flag))
2605 {
2606 if (flag == PEER_FLAG_SHUTDOWN)
2607 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2608 else
2609 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2610 }
2611
2612 /* Flag conflict check. */
2613 if (set
2614 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2615 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2616 return BGP_ERR_PEER_FLAG_CONFLICT;
2617
2618 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2619 {
2620 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2621 return 0;
2622 if (! set && ! CHECK_FLAG (peer->flags, flag))
2623 return 0;
2624 }
2625
2626 if (set)
2627 SET_FLAG (peer->flags, flag);
2628 else
2629 UNSET_FLAG (peer->flags, flag);
2630
2631 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2632 {
2633 if (action.type == peer_change_reset)
2634 peer_flag_modify_action (peer, flag);
2635
2636 return 0;
2637 }
2638
2639 /* peer-group member updates. */
2640 group = peer->group;
2641
paul1eb8ef22005-04-07 07:30:20 +00002642 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002643 {
2644 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2645 continue;
2646
2647 if (! set && ! CHECK_FLAG (peer->flags, flag))
2648 continue;
2649
2650 if (set)
2651 SET_FLAG (peer->flags, flag);
2652 else
2653 UNSET_FLAG (peer->flags, flag);
2654
2655 if (action.type == peer_change_reset)
2656 peer_flag_modify_action (peer, flag);
2657 }
2658 return 0;
2659}
2660
2661int
2662peer_flag_set (struct peer *peer, u_int32_t flag)
2663{
2664 return peer_flag_modify (peer, flag, 1);
2665}
2666
2667int
2668peer_flag_unset (struct peer *peer, u_int32_t flag)
2669{
2670 return peer_flag_modify (peer, flag, 0);
2671}
2672
paul94f2b392005-06-28 12:44:16 +00002673static int
paul718e3742002-12-13 20:15:29 +00002674peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2675{
2676 if (peer->af_group[afi][safi])
2677 return 1;
2678 return 0;
2679}
2680
paul94f2b392005-06-28 12:44:16 +00002681static int
paul718e3742002-12-13 20:15:29 +00002682peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2683 int set)
2684{
2685 int found;
2686 int size;
paul1eb8ef22005-04-07 07:30:20 +00002687 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002688 struct peer_group *group;
2689 struct peer_flag_action action;
2690
2691 memset (&action, 0, sizeof (struct peer_flag_action));
2692 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2693
2694 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2695
2696 /* No flag action is found. */
2697 if (! found)
2698 return BGP_ERR_INVALID_FLAG;
2699
2700 /* Adress family must be activated. */
2701 if (! peer->afc[afi][safi])
2702 return BGP_ERR_PEER_INACTIVE;
2703
2704 /* Not for peer-group member. */
2705 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2706 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2707
2708 /* Spcecial check for reflector client. */
2709 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2710 && peer_sort (peer) != BGP_PEER_IBGP)
2711 return BGP_ERR_NOT_INTERNAL_PEER;
2712
2713 /* Spcecial check for remove-private-AS. */
2714 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2715 && peer_sort (peer) == BGP_PEER_IBGP)
2716 return BGP_ERR_REMOVE_PRIVATE_AS;
2717
2718 /* When unset the peer-group member's flag we have to check
2719 peer-group configuration. */
2720 if (! set && peer->af_group[afi][safi])
2721 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2722 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2723
2724 /* When current flag configuration is same as requested one. */
2725 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2726 {
2727 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2728 return 0;
2729 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2730 return 0;
2731 }
2732
2733 if (set)
2734 SET_FLAG (peer->af_flags[afi][safi], flag);
2735 else
2736 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2737
2738 /* Execute action when peer is established. */
2739 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2740 && peer->status == Established)
2741 {
2742 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2743 bgp_clear_adj_in (peer, afi, safi);
2744 else
hassoe0701b72004-05-20 09:19:34 +00002745 {
2746 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2747 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2748 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2749 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2750 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2751 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2752 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2753 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2754
2755 peer_change_action (peer, afi, safi, action.type);
2756 }
2757
paul718e3742002-12-13 20:15:29 +00002758 }
2759
2760 /* Peer group member updates. */
2761 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2762 {
2763 group = peer->group;
2764
paul1eb8ef22005-04-07 07:30:20 +00002765 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002766 {
2767 if (! peer->af_group[afi][safi])
2768 continue;
2769
2770 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2771 continue;
2772
2773 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2774 continue;
2775
2776 if (set)
2777 SET_FLAG (peer->af_flags[afi][safi], flag);
2778 else
2779 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2780
2781 if (peer->status == Established)
2782 {
2783 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2784 bgp_clear_adj_in (peer, afi, safi);
2785 else
hassoe0701b72004-05-20 09:19:34 +00002786 {
2787 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2788 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2789 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2790 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2791 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2792 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2793 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2794 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2795
2796 peer_change_action (peer, afi, safi, action.type);
2797 }
paul718e3742002-12-13 20:15:29 +00002798 }
2799 }
2800 }
2801 return 0;
2802}
2803
2804int
2805peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2806{
2807 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2808}
2809
2810int
2811peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2812{
2813 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2814}
David Lamparter6b0655a2014-06-04 06:53:35 +02002815
paul718e3742002-12-13 20:15:29 +00002816/* EBGP multihop configuration. */
2817int
2818peer_ebgp_multihop_set (struct peer *peer, int ttl)
2819{
2820 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002821 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002822 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002823
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002824 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002825 return 0;
2826
Nick Hilliardfa411a22011-03-23 15:33:17 +00002827 /* see comment in peer_ttl_security_hops_set() */
2828 if (ttl != MAXTTL)
2829 {
2830 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2831 {
2832 group = peer->group;
2833 if (group->conf->gtsm_hops != 0)
2834 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2835
2836 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2837 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002838 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002839 continue;
2840
2841 if (peer1->gtsm_hops != 0)
2842 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2843 }
2844 }
2845 else
2846 {
2847 if (peer->gtsm_hops != 0)
2848 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2849 }
2850 }
2851
paul718e3742002-12-13 20:15:29 +00002852 peer->ttl = ttl;
2853
2854 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2855 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002856 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002857 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002858 }
2859 else
2860 {
2861 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002862 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002863 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002864 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002865 continue;
paul718e3742002-12-13 20:15:29 +00002866
pauleb821182004-05-01 08:44:08 +00002867 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002868
pauleb821182004-05-01 08:44:08 +00002869 if (peer->fd >= 0)
2870 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2871 }
paul718e3742002-12-13 20:15:29 +00002872 }
2873 return 0;
2874}
2875
2876int
2877peer_ebgp_multihop_unset (struct peer *peer)
2878{
2879 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002880 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002881
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002882 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002883 return 0;
2884
Nick Hilliardfa411a22011-03-23 15:33:17 +00002885 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2886 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2887
paul718e3742002-12-13 20:15:29 +00002888 if (peer_group_active (peer))
2889 peer->ttl = peer->group->conf->ttl;
2890 else
2891 peer->ttl = 1;
2892
2893 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2894 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002895 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002896 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002897 }
2898 else
2899 {
2900 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002901 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002902 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002903 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002904 continue;
paul718e3742002-12-13 20:15:29 +00002905
pauleb821182004-05-01 08:44:08 +00002906 peer->ttl = 1;
2907
2908 if (peer->fd >= 0)
2909 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2910 }
paul718e3742002-12-13 20:15:29 +00002911 }
2912 return 0;
2913}
David Lamparter6b0655a2014-06-04 06:53:35 +02002914
paul718e3742002-12-13 20:15:29 +00002915/* Neighbor description. */
2916int
David Lamparterdfb9bd72016-05-24 18:58:07 +02002917peer_description_set (struct peer *peer, const char *desc)
paul718e3742002-12-13 20:15:29 +00002918{
2919 if (peer->desc)
2920 XFREE (MTYPE_PEER_DESC, peer->desc);
2921
2922 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2923
2924 return 0;
2925}
2926
2927int
2928peer_description_unset (struct peer *peer)
2929{
2930 if (peer->desc)
2931 XFREE (MTYPE_PEER_DESC, peer->desc);
2932
2933 peer->desc = NULL;
2934
2935 return 0;
2936}
David Lamparter6b0655a2014-06-04 06:53:35 +02002937
paul718e3742002-12-13 20:15:29 +00002938/* Neighbor update-source. */
2939int
paulfd79ac92004-10-13 05:06:08 +00002940peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002941{
2942 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002943 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002944
2945 if (peer->update_if)
2946 {
2947 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2948 && strcmp (peer->update_if, ifname) == 0)
2949 return 0;
2950
2951 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2952 peer->update_if = NULL;
2953 }
2954
2955 if (peer->update_source)
2956 {
2957 sockunion_free (peer->update_source);
2958 peer->update_source = NULL;
2959 }
2960
2961 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2962
2963 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2964 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002965 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002966 {
2967 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2968 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2969 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2970 }
paul718e3742002-12-13 20:15:29 +00002971 else
2972 BGP_EVENT_ADD (peer, BGP_Stop);
2973 return 0;
2974 }
2975
2976 /* peer-group member updates. */
2977 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002978 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002979 {
2980 if (peer->update_if)
2981 {
2982 if (strcmp (peer->update_if, ifname) == 0)
2983 continue;
2984
2985 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2986 peer->update_if = NULL;
2987 }
2988
2989 if (peer->update_source)
2990 {
2991 sockunion_free (peer->update_source);
2992 peer->update_source = NULL;
2993 }
2994
2995 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2996
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002997 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002998 {
2999 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3000 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3001 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3002 }
paul718e3742002-12-13 20:15:29 +00003003 else
3004 BGP_EVENT_ADD (peer, BGP_Stop);
3005 }
3006 return 0;
3007}
3008
3009int
David Lamparterdfb9bd72016-05-24 18:58:07 +02003010peer_update_source_addr_set (struct peer *peer, const union sockunion *su)
paul718e3742002-12-13 20:15:29 +00003011{
3012 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003013 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003014
3015 if (peer->update_source)
3016 {
3017 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3018 && sockunion_cmp (peer->update_source, su) == 0)
3019 return 0;
3020 sockunion_free (peer->update_source);
3021 peer->update_source = NULL;
3022 }
3023
3024 if (peer->update_if)
3025 {
3026 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3027 peer->update_if = NULL;
3028 }
3029
3030 peer->update_source = sockunion_dup (su);
3031
3032 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3033 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003034 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003035 {
3036 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3037 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3038 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3039 }
paul718e3742002-12-13 20:15:29 +00003040 else
3041 BGP_EVENT_ADD (peer, BGP_Stop);
3042 return 0;
3043 }
3044
3045 /* peer-group member updates. */
3046 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003047 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003048 {
3049 if (peer->update_source)
3050 {
3051 if (sockunion_cmp (peer->update_source, su) == 0)
3052 continue;
3053 sockunion_free (peer->update_source);
3054 peer->update_source = NULL;
3055 }
3056
3057 if (peer->update_if)
3058 {
3059 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3060 peer->update_if = NULL;
3061 }
3062
3063 peer->update_source = sockunion_dup (su);
3064
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003065 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003066 {
3067 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3068 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3069 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3070 }
paul718e3742002-12-13 20:15:29 +00003071 else
3072 BGP_EVENT_ADD (peer, BGP_Stop);
3073 }
3074 return 0;
3075}
3076
3077int
3078peer_update_source_unset (struct peer *peer)
3079{
3080 union sockunion *su;
3081 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003082 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003083
3084 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3085 && ! peer->update_source
3086 && ! peer->update_if)
3087 return 0;
3088
3089 if (peer->update_source)
3090 {
3091 sockunion_free (peer->update_source);
3092 peer->update_source = NULL;
3093 }
3094 if (peer->update_if)
3095 {
3096 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3097 peer->update_if = NULL;
3098 }
3099
3100 if (peer_group_active (peer))
3101 {
3102 group = peer->group;
3103
3104 if (group->conf->update_source)
3105 {
3106 su = sockunion_dup (group->conf->update_source);
3107 peer->update_source = su;
3108 }
3109 else if (group->conf->update_if)
3110 peer->update_if =
3111 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
3112 }
3113
3114 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3115 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003116 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003117 {
3118 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3119 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3120 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3121 }
paul718e3742002-12-13 20:15:29 +00003122 else
3123 BGP_EVENT_ADD (peer, BGP_Stop);
3124 return 0;
3125 }
3126
3127 /* peer-group member updates. */
3128 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003129 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003130 {
3131 if (! peer->update_source && ! peer->update_if)
3132 continue;
3133
3134 if (peer->update_source)
3135 {
3136 sockunion_free (peer->update_source);
3137 peer->update_source = NULL;
3138 }
3139
3140 if (peer->update_if)
3141 {
3142 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3143 peer->update_if = NULL;
3144 }
3145
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003146 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003147 {
3148 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3149 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3150 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3151 }
paul718e3742002-12-13 20:15:29 +00003152 else
3153 BGP_EVENT_ADD (peer, BGP_Stop);
3154 }
3155 return 0;
3156}
David Lamparter6b0655a2014-06-04 06:53:35 +02003157
paul718e3742002-12-13 20:15:29 +00003158int
3159peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003160 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003161{
3162 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003163 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003164
3165 /* Adress family must be activated. */
3166 if (! peer->afc[afi][safi])
3167 return BGP_ERR_PEER_INACTIVE;
3168
3169 /* Default originate can't be used for peer group memeber. */
3170 if (peer_is_group_member (peer, afi, safi))
3171 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3172
3173 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3174 || (rmap && ! peer->default_rmap[afi][safi].name)
3175 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3176 {
3177 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3178
3179 if (rmap)
3180 {
3181 if (peer->default_rmap[afi][safi].name)
3182 free (peer->default_rmap[afi][safi].name);
3183 peer->default_rmap[afi][safi].name = strdup (rmap);
3184 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3185 }
3186 }
3187
3188 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3189 {
3190 if (peer->status == Established && peer->afc_nego[afi][safi])
3191 bgp_default_originate (peer, afi, safi, 0);
3192 return 0;
3193 }
3194
3195 /* peer-group member updates. */
3196 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003197 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003198 {
3199 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3200
3201 if (rmap)
3202 {
3203 if (peer->default_rmap[afi][safi].name)
3204 free (peer->default_rmap[afi][safi].name);
3205 peer->default_rmap[afi][safi].name = strdup (rmap);
3206 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3207 }
3208
3209 if (peer->status == Established && peer->afc_nego[afi][safi])
3210 bgp_default_originate (peer, afi, safi, 0);
3211 }
3212 return 0;
3213}
3214
3215int
3216peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3217{
3218 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003219 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003220
3221 /* Adress family must be activated. */
3222 if (! peer->afc[afi][safi])
3223 return BGP_ERR_PEER_INACTIVE;
3224
3225 /* Default originate can't be used for peer group memeber. */
3226 if (peer_is_group_member (peer, afi, safi))
3227 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3228
3229 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3230 {
3231 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3232
3233 if (peer->default_rmap[afi][safi].name)
3234 free (peer->default_rmap[afi][safi].name);
3235 peer->default_rmap[afi][safi].name = NULL;
3236 peer->default_rmap[afi][safi].map = NULL;
3237 }
3238
3239 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3240 {
3241 if (peer->status == Established && peer->afc_nego[afi][safi])
3242 bgp_default_originate (peer, afi, safi, 1);
3243 return 0;
3244 }
3245
3246 /* peer-group member updates. */
3247 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003248 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003249 {
3250 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3251
3252 if (peer->default_rmap[afi][safi].name)
3253 free (peer->default_rmap[afi][safi].name);
3254 peer->default_rmap[afi][safi].name = NULL;
3255 peer->default_rmap[afi][safi].map = NULL;
3256
3257 if (peer->status == Established && peer->afc_nego[afi][safi])
3258 bgp_default_originate (peer, afi, safi, 1);
3259 }
3260 return 0;
3261}
David Lamparter6b0655a2014-06-04 06:53:35 +02003262
paul718e3742002-12-13 20:15:29 +00003263int
3264peer_port_set (struct peer *peer, u_int16_t port)
3265{
3266 peer->port = port;
3267 return 0;
3268}
3269
3270int
3271peer_port_unset (struct peer *peer)
3272{
3273 peer->port = BGP_PORT_DEFAULT;
3274 return 0;
3275}
David Lamparter6b0655a2014-06-04 06:53:35 +02003276
paul718e3742002-12-13 20:15:29 +00003277/* neighbor weight. */
3278int
3279peer_weight_set (struct peer *peer, u_int16_t weight)
3280{
3281 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003282 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003283
3284 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3285 peer->weight = weight;
3286
3287 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3288 return 0;
3289
3290 /* peer-group member updates. */
3291 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003292 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003293 {
3294 peer->weight = group->conf->weight;
3295 }
3296 return 0;
3297}
3298
3299int
3300peer_weight_unset (struct peer *peer)
3301{
3302 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003303 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003304
3305 /* Set default weight. */
3306 if (peer_group_active (peer))
3307 peer->weight = peer->group->conf->weight;
3308 else
3309 peer->weight = 0;
3310
3311 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3312
3313 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3314 return 0;
3315
3316 /* peer-group member updates. */
3317 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003318 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003319 {
3320 peer->weight = 0;
3321 }
3322 return 0;
3323}
David Lamparter6b0655a2014-06-04 06:53:35 +02003324
paul718e3742002-12-13 20:15:29 +00003325int
3326peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3327{
3328 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003329 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003330
3331 /* Not for peer group memeber. */
3332 if (peer_group_active (peer))
3333 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3334
3335 /* keepalive value check. */
3336 if (keepalive > 65535)
3337 return BGP_ERR_INVALID_VALUE;
3338
3339 /* Holdtime value check. */
3340 if (holdtime > 65535)
3341 return BGP_ERR_INVALID_VALUE;
3342
3343 /* Holdtime value must be either 0 or greater than 3. */
3344 if (holdtime < 3 && holdtime != 0)
3345 return BGP_ERR_INVALID_VALUE;
3346
3347 /* Set value to the configuration. */
3348 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3349 peer->holdtime = holdtime;
3350 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3351
3352 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3353 return 0;
3354
3355 /* peer-group member updates. */
3356 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003357 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003358 {
3359 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3360 peer->holdtime = group->conf->holdtime;
3361 peer->keepalive = group->conf->keepalive;
3362 }
3363 return 0;
3364}
3365
3366int
3367peer_timers_unset (struct peer *peer)
3368{
3369 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003370 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003371
3372 if (peer_group_active (peer))
3373 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3374
3375 /* Clear configuration. */
3376 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3377 peer->keepalive = 0;
3378 peer->holdtime = 0;
3379
3380 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3381 return 0;
3382
3383 /* peer-group member updates. */
3384 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003385 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003386 {
3387 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3388 peer->holdtime = 0;
3389 peer->keepalive = 0;
3390 }
3391
3392 return 0;
3393}
David Lamparter6b0655a2014-06-04 06:53:35 +02003394
paul718e3742002-12-13 20:15:29 +00003395int
3396peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3397{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003398 struct peer_group *group;
3399 struct listnode *node, *nnode;
3400
paul718e3742002-12-13 20:15:29 +00003401 if (peer_group_active (peer))
3402 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3403
3404 if (connect > 65535)
3405 return BGP_ERR_INVALID_VALUE;
3406
3407 /* Set value to the configuration. */
3408 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3409 peer->connect = connect;
3410
3411 /* Set value to timer setting. */
3412 peer->v_connect = connect;
3413
Daniel Walton0d7435f2015-10-22 11:35:20 +03003414 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3415 return 0;
3416
3417 /* peer-group member updates. */
3418 group = peer->group;
3419 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3420 {
3421 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3422 peer->connect = connect;
3423 peer->v_connect = connect;
3424 }
paul718e3742002-12-13 20:15:29 +00003425 return 0;
3426}
3427
3428int
3429peer_timers_connect_unset (struct peer *peer)
3430{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003431 struct peer_group *group;
3432 struct listnode *node, *nnode;
3433
paul718e3742002-12-13 20:15:29 +00003434 if (peer_group_active (peer))
3435 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3436
3437 /* Clear configuration. */
3438 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3439 peer->connect = 0;
3440
3441 /* Set timer setting to default value. */
3442 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3443
Daniel Walton0d7435f2015-10-22 11:35:20 +03003444 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3445 return 0;
3446
3447 /* peer-group member updates. */
3448 group = peer->group;
3449 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3450 {
3451 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3452 peer->connect = 0;
3453 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3454 }
3455 return 0;
paul718e3742002-12-13 20:15:29 +00003456}
David Lamparter6b0655a2014-06-04 06:53:35 +02003457
paul718e3742002-12-13 20:15:29 +00003458int
3459peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3460{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003461 struct peer_group *group;
3462 struct listnode *node, *nnode;
3463
paul718e3742002-12-13 20:15:29 +00003464 if (peer_group_active (peer))
3465 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3466
3467 if (routeadv > 600)
3468 return BGP_ERR_INVALID_VALUE;
3469
3470 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3471 peer->routeadv = routeadv;
3472 peer->v_routeadv = routeadv;
3473
Daniel Walton0d7435f2015-10-22 11:35:20 +03003474 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3475 return 0;
3476
3477 /* peer-group member updates. */
3478 group = peer->group;
3479 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3480 {
3481 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3482 peer->routeadv = routeadv;
3483 peer->v_routeadv = routeadv;
3484 }
3485
paul718e3742002-12-13 20:15:29 +00003486 return 0;
3487}
3488
3489int
3490peer_advertise_interval_unset (struct peer *peer)
3491{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003492 struct peer_group *group;
3493 struct listnode *node, *nnode;
3494
paul718e3742002-12-13 20:15:29 +00003495 if (peer_group_active (peer))
3496 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3497
3498 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3499 peer->routeadv = 0;
3500
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003501 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003502 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3503 else
3504 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
Daniel Walton0d7435f2015-10-22 11:35:20 +03003505
3506 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3507 return 0;
3508
3509 /* peer-group member updates. */
3510 group = peer->group;
3511 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3512 {
3513 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3514 peer->routeadv = 0;
3515
3516 if (peer->sort == BGP_PEER_IBGP)
3517 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3518 else
3519 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3520 }
paul718e3742002-12-13 20:15:29 +00003521
3522 return 0;
3523}
David Lamparter6b0655a2014-06-04 06:53:35 +02003524
paul718e3742002-12-13 20:15:29 +00003525/* neighbor interface */
3526int
paulfd79ac92004-10-13 05:06:08 +00003527peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003528{
3529 if (peer->ifname)
3530 free (peer->ifname);
3531 peer->ifname = strdup (str);
3532
3533 return 0;
3534}
3535
3536int
3537peer_interface_unset (struct peer *peer)
3538{
3539 if (peer->ifname)
3540 free (peer->ifname);
3541 peer->ifname = NULL;
3542
3543 return 0;
3544}
David Lamparter6b0655a2014-06-04 06:53:35 +02003545
paul718e3742002-12-13 20:15:29 +00003546/* Allow-as in. */
3547int
3548peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3549{
3550 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003551 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003552
3553 if (allow_num < 1 || allow_num > 10)
3554 return BGP_ERR_INVALID_VALUE;
3555
3556 if (peer->allowas_in[afi][safi] != allow_num)
3557 {
3558 peer->allowas_in[afi][safi] = allow_num;
3559 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3560 peer_change_action (peer, afi, safi, peer_change_reset_in);
3561 }
3562
3563 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3564 return 0;
3565
3566 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003567 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003568 {
3569 if (peer->allowas_in[afi][safi] != allow_num)
3570 {
3571 peer->allowas_in[afi][safi] = allow_num;
3572 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3573 peer_change_action (peer, afi, safi, peer_change_reset_in);
3574 }
3575
3576 }
3577 return 0;
3578}
3579
3580int
3581peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3582{
3583 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003584 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003585
3586 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3587 {
3588 peer->allowas_in[afi][safi] = 0;
3589 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3590 }
3591
3592 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3593 return 0;
3594
3595 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003596 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003597 {
3598 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3599 {
3600 peer->allowas_in[afi][safi] = 0;
3601 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3602 }
3603 }
3604 return 0;
3605}
David Lamparter6b0655a2014-06-04 06:53:35 +02003606
paul718e3742002-12-13 20:15:29 +00003607int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003608peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003609{
3610 struct bgp *bgp = peer->bgp;
3611 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003612 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003613
3614 if (peer_sort (peer) != BGP_PEER_EBGP
3615 && peer_sort (peer) != BGP_PEER_INTERNAL)
3616 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3617
3618 if (bgp->as == as)
3619 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3620
3621 if (peer_group_active (peer))
3622 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3623
Andrew Certain9d3f9702012-11-07 23:50:07 +00003624 if (peer->as == as)
3625 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3626
paul718e3742002-12-13 20:15:29 +00003627 if (peer->change_local_as == as &&
3628 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003629 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3630 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3631 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003632 return 0;
3633
3634 peer->change_local_as = as;
3635 if (no_prepend)
3636 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3637 else
3638 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3639
Andrew Certain9d3f9702012-11-07 23:50:07 +00003640 if (replace_as)
3641 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3642 else
3643 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3644
paul718e3742002-12-13 20:15:29 +00003645 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3646 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003647 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003648 {
3649 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3650 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3651 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3652 }
paul718e3742002-12-13 20:15:29 +00003653 else
3654 BGP_EVENT_ADD (peer, BGP_Stop);
3655
3656 return 0;
3657 }
3658
3659 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003660 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003661 {
3662 peer->change_local_as = as;
3663 if (no_prepend)
3664 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3665 else
3666 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3667
Andrew Certain9d3f9702012-11-07 23:50:07 +00003668 if (replace_as)
3669 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3670 else
3671 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3672
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003673 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003674 {
3675 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3676 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3677 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3678 }
paul718e3742002-12-13 20:15:29 +00003679 else
3680 BGP_EVENT_ADD (peer, BGP_Stop);
3681 }
3682
3683 return 0;
3684}
3685
3686int
3687peer_local_as_unset (struct peer *peer)
3688{
3689 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003690 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003691
3692 if (peer_group_active (peer))
3693 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3694
3695 if (! peer->change_local_as)
3696 return 0;
3697
3698 peer->change_local_as = 0;
3699 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003700 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003701
3702 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3703 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003704 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003705 {
3706 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3707 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3708 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3709 }
paul718e3742002-12-13 20:15:29 +00003710 else
3711 BGP_EVENT_ADD (peer, BGP_Stop);
3712
3713 return 0;
3714 }
3715
3716 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003717 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003718 {
3719 peer->change_local_as = 0;
3720 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003721 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003722
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003723 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003724 {
3725 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3726 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3727 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3728 }
paul718e3742002-12-13 20:15:29 +00003729 else
3730 BGP_EVENT_ADD (peer, BGP_Stop);
3731 }
3732 return 0;
3733}
David Lamparter6b0655a2014-06-04 06:53:35 +02003734
Paul Jakma0df7c912008-07-21 21:02:49 +00003735/* Set password for authenticating with the peer. */
3736int
3737peer_password_set (struct peer *peer, const char *password)
3738{
3739 struct listnode *nn, *nnode;
3740 int len = password ? strlen(password) : 0;
3741 int ret = BGP_SUCCESS;
3742
3743 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3744 return BGP_ERR_INVALID_VALUE;
3745
3746 if (peer->password && strcmp (peer->password, password) == 0
3747 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3748 return 0;
3749
3750 if (peer->password)
3751 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3752
3753 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3754
3755 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3756 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003757 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3758 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
Paul Jakma0df7c912008-07-21 21:02:49 +00003759 else
3760 BGP_EVENT_ADD (peer, BGP_Stop);
3761
3762 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3763 }
3764
3765 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3766 {
3767 if (peer->password && strcmp (peer->password, password) == 0)
3768 continue;
3769
3770 if (peer->password)
3771 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3772
3773 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3774
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003775 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003776 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3777 else
3778 BGP_EVENT_ADD (peer, BGP_Stop);
3779
3780 if (bgp_md5_set (peer) < 0)
3781 ret = BGP_ERR_TCPSIG_FAILED;
3782 }
3783
3784 return ret;
3785}
3786
3787int
3788peer_password_unset (struct peer *peer)
3789{
3790 struct listnode *nn, *nnode;
3791
3792 if (!peer->password
3793 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3794 return 0;
3795
3796 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3797 {
3798 if (peer_group_active (peer)
3799 && peer->group->conf->password
3800 && strcmp (peer->group->conf->password, peer->password) == 0)
3801 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3802
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003803 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003804 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3805 else
3806 BGP_EVENT_ADD (peer, BGP_Stop);
3807
3808 if (peer->password)
3809 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3810
3811 peer->password = NULL;
3812
3813 bgp_md5_set (peer);
3814
3815 return 0;
3816 }
3817
3818 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3819 peer->password = NULL;
3820
3821 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3822 {
3823 if (!peer->password)
3824 continue;
3825
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003826 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003827 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3828 else
3829 BGP_EVENT_ADD (peer, BGP_Stop);
3830
3831 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3832 peer->password = NULL;
3833
3834 bgp_md5_set (peer);
3835 }
3836
3837 return 0;
3838}
David Lamparter6b0655a2014-06-04 06:53:35 +02003839
paul718e3742002-12-13 20:15:29 +00003840/* Set distribute list to the peer. */
3841int
3842peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003843 const char *name)
paul718e3742002-12-13 20:15:29 +00003844{
3845 struct bgp_filter *filter;
3846 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003847 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003848
3849 if (! peer->afc[afi][safi])
3850 return BGP_ERR_PEER_INACTIVE;
3851
3852 if (direct != FILTER_IN && direct != FILTER_OUT)
3853 return BGP_ERR_INVALID_VALUE;
3854
3855 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3856 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3857
3858 filter = &peer->filter[afi][safi];
3859
3860 if (filter->plist[direct].name)
3861 return BGP_ERR_PEER_FILTER_CONFLICT;
3862
3863 if (filter->dlist[direct].name)
3864 free (filter->dlist[direct].name);
3865 filter->dlist[direct].name = strdup (name);
3866 filter->dlist[direct].alist = access_list_lookup (afi, name);
3867
3868 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3869 return 0;
3870
3871 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003872 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003873 {
3874 filter = &peer->filter[afi][safi];
3875
3876 if (! peer->af_group[afi][safi])
3877 continue;
3878
3879 if (filter->dlist[direct].name)
3880 free (filter->dlist[direct].name);
3881 filter->dlist[direct].name = strdup (name);
3882 filter->dlist[direct].alist = access_list_lookup (afi, name);
3883 }
3884
3885 return 0;
3886}
3887
3888int
3889peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3890{
3891 struct bgp_filter *filter;
3892 struct bgp_filter *gfilter;
3893 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003894 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003895
3896 if (! peer->afc[afi][safi])
3897 return BGP_ERR_PEER_INACTIVE;
3898
3899 if (direct != FILTER_IN && direct != FILTER_OUT)
3900 return BGP_ERR_INVALID_VALUE;
3901
3902 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3903 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3904
3905 filter = &peer->filter[afi][safi];
3906
3907 /* apply peer-group filter */
3908 if (peer->af_group[afi][safi])
3909 {
3910 gfilter = &peer->group->conf->filter[afi][safi];
3911
3912 if (gfilter->dlist[direct].name)
3913 {
3914 if (filter->dlist[direct].name)
3915 free (filter->dlist[direct].name);
3916 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3917 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3918 return 0;
3919 }
3920 }
3921
3922 if (filter->dlist[direct].name)
3923 free (filter->dlist[direct].name);
3924 filter->dlist[direct].name = NULL;
3925 filter->dlist[direct].alist = NULL;
3926
3927 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3928 return 0;
3929
3930 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003931 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003932 {
3933 filter = &peer->filter[afi][safi];
3934
3935 if (! peer->af_group[afi][safi])
3936 continue;
3937
3938 if (filter->dlist[direct].name)
3939 free (filter->dlist[direct].name);
3940 filter->dlist[direct].name = NULL;
3941 filter->dlist[direct].alist = NULL;
3942 }
3943
3944 return 0;
3945}
3946
3947/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003948static void
paul718e3742002-12-13 20:15:29 +00003949peer_distribute_update (struct access_list *access)
3950{
3951 afi_t afi;
3952 safi_t safi;
3953 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003954 struct listnode *mnode, *mnnode;
3955 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003956 struct bgp *bgp;
3957 struct peer *peer;
3958 struct peer_group *group;
3959 struct bgp_filter *filter;
3960
paul1eb8ef22005-04-07 07:30:20 +00003961 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003962 {
paul1eb8ef22005-04-07 07:30:20 +00003963 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003964 {
3965 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3966 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3967 {
3968 filter = &peer->filter[afi][safi];
3969
3970 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3971 {
3972 if (filter->dlist[direct].name)
3973 filter->dlist[direct].alist =
3974 access_list_lookup (afi, filter->dlist[direct].name);
3975 else
3976 filter->dlist[direct].alist = NULL;
3977 }
3978 }
3979 }
paul1eb8ef22005-04-07 07:30:20 +00003980 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003981 {
3982 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3983 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3984 {
3985 filter = &group->conf->filter[afi][safi];
3986
3987 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3988 {
3989 if (filter->dlist[direct].name)
3990 filter->dlist[direct].alist =
3991 access_list_lookup (afi, filter->dlist[direct].name);
3992 else
3993 filter->dlist[direct].alist = NULL;
3994 }
3995 }
3996 }
3997 }
3998}
David Lamparter6b0655a2014-06-04 06:53:35 +02003999
paul718e3742002-12-13 20:15:29 +00004000/* Set prefix list to the peer. */
4001int
4002peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004003 const char *name)
paul718e3742002-12-13 20:15:29 +00004004{
4005 struct bgp_filter *filter;
4006 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004007 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004008
4009 if (! peer->afc[afi][safi])
4010 return BGP_ERR_PEER_INACTIVE;
4011
4012 if (direct != FILTER_IN && direct != FILTER_OUT)
4013 return BGP_ERR_INVALID_VALUE;
4014
4015 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4016 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4017
4018 filter = &peer->filter[afi][safi];
4019
4020 if (filter->dlist[direct].name)
4021 return BGP_ERR_PEER_FILTER_CONFLICT;
4022
4023 if (filter->plist[direct].name)
4024 free (filter->plist[direct].name);
4025 filter->plist[direct].name = strdup (name);
4026 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4027
4028 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4029 return 0;
4030
4031 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004032 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004033 {
4034 filter = &peer->filter[afi][safi];
4035
4036 if (! peer->af_group[afi][safi])
4037 continue;
4038
4039 if (filter->plist[direct].name)
4040 free (filter->plist[direct].name);
4041 filter->plist[direct].name = strdup (name);
4042 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4043 }
4044 return 0;
4045}
4046
4047int
4048peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4049{
4050 struct bgp_filter *filter;
4051 struct bgp_filter *gfilter;
4052 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004053 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004054
4055 if (! peer->afc[afi][safi])
4056 return BGP_ERR_PEER_INACTIVE;
4057
4058 if (direct != FILTER_IN && direct != FILTER_OUT)
4059 return BGP_ERR_INVALID_VALUE;
4060
4061 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4062 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4063
4064 filter = &peer->filter[afi][safi];
4065
4066 /* apply peer-group filter */
4067 if (peer->af_group[afi][safi])
4068 {
4069 gfilter = &peer->group->conf->filter[afi][safi];
4070
4071 if (gfilter->plist[direct].name)
4072 {
4073 if (filter->plist[direct].name)
4074 free (filter->plist[direct].name);
4075 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
4076 filter->plist[direct].plist = gfilter->plist[direct].plist;
4077 return 0;
4078 }
4079 }
4080
4081 if (filter->plist[direct].name)
4082 free (filter->plist[direct].name);
4083 filter->plist[direct].name = NULL;
4084 filter->plist[direct].plist = NULL;
4085
4086 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4087 return 0;
4088
4089 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004090 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004091 {
4092 filter = &peer->filter[afi][safi];
4093
4094 if (! peer->af_group[afi][safi])
4095 continue;
4096
4097 if (filter->plist[direct].name)
4098 free (filter->plist[direct].name);
4099 filter->plist[direct].name = NULL;
4100 filter->plist[direct].plist = NULL;
4101 }
4102
4103 return 0;
4104}
4105
4106/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00004107static void
paul718e3742002-12-13 20:15:29 +00004108peer_prefix_list_update (struct prefix_list *plist)
4109{
paul1eb8ef22005-04-07 07:30:20 +00004110 struct listnode *mnode, *mnnode;
4111 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004112 struct bgp *bgp;
4113 struct peer *peer;
4114 struct peer_group *group;
4115 struct bgp_filter *filter;
4116 afi_t afi;
4117 safi_t safi;
4118 int direct;
4119
paul1eb8ef22005-04-07 07:30:20 +00004120 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004121 {
paul1eb8ef22005-04-07 07:30:20 +00004122 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004123 {
4124 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4125 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4126 {
4127 filter = &peer->filter[afi][safi];
4128
4129 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4130 {
4131 if (filter->plist[direct].name)
4132 filter->plist[direct].plist =
4133 prefix_list_lookup (afi, filter->plist[direct].name);
4134 else
4135 filter->plist[direct].plist = NULL;
4136 }
4137 }
4138 }
paul1eb8ef22005-04-07 07:30:20 +00004139 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004140 {
4141 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4142 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4143 {
4144 filter = &group->conf->filter[afi][safi];
4145
4146 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4147 {
4148 if (filter->plist[direct].name)
4149 filter->plist[direct].plist =
4150 prefix_list_lookup (afi, filter->plist[direct].name);
4151 else
4152 filter->plist[direct].plist = NULL;
4153 }
4154 }
4155 }
4156 }
4157}
David Lamparter6b0655a2014-06-04 06:53:35 +02004158
paul718e3742002-12-13 20:15:29 +00004159int
4160peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004161 const char *name)
paul718e3742002-12-13 20:15:29 +00004162{
4163 struct bgp_filter *filter;
4164 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004165 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004166
4167 if (! peer->afc[afi][safi])
4168 return BGP_ERR_PEER_INACTIVE;
4169
4170 if (direct != FILTER_IN && direct != FILTER_OUT)
4171 return BGP_ERR_INVALID_VALUE;
4172
4173 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4174 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4175
4176 filter = &peer->filter[afi][safi];
4177
4178 if (filter->aslist[direct].name)
4179 free (filter->aslist[direct].name);
4180 filter->aslist[direct].name = strdup (name);
4181 filter->aslist[direct].aslist = as_list_lookup (name);
4182
4183 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4184 return 0;
4185
4186 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004187 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004188 {
4189 filter = &peer->filter[afi][safi];
4190
4191 if (! peer->af_group[afi][safi])
4192 continue;
4193
4194 if (filter->aslist[direct].name)
4195 free (filter->aslist[direct].name);
4196 filter->aslist[direct].name = strdup (name);
4197 filter->aslist[direct].aslist = as_list_lookup (name);
4198 }
4199 return 0;
4200}
4201
4202int
4203peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4204{
4205 struct bgp_filter *filter;
4206 struct bgp_filter *gfilter;
4207 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004208 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004209
4210 if (! peer->afc[afi][safi])
4211 return BGP_ERR_PEER_INACTIVE;
4212
hassob5f29602005-05-25 21:00:28 +00004213 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004214 return BGP_ERR_INVALID_VALUE;
4215
hassob5f29602005-05-25 21:00:28 +00004216 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004217 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4218
4219 filter = &peer->filter[afi][safi];
4220
4221 /* apply peer-group filter */
4222 if (peer->af_group[afi][safi])
4223 {
4224 gfilter = &peer->group->conf->filter[afi][safi];
4225
4226 if (gfilter->aslist[direct].name)
4227 {
4228 if (filter->aslist[direct].name)
4229 free (filter->aslist[direct].name);
4230 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4231 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4232 return 0;
4233 }
4234 }
4235
4236 if (filter->aslist[direct].name)
4237 free (filter->aslist[direct].name);
4238 filter->aslist[direct].name = NULL;
4239 filter->aslist[direct].aslist = NULL;
4240
4241 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4242 return 0;
4243
4244 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004245 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004246 {
4247 filter = &peer->filter[afi][safi];
4248
4249 if (! peer->af_group[afi][safi])
4250 continue;
4251
4252 if (filter->aslist[direct].name)
4253 free (filter->aslist[direct].name);
4254 filter->aslist[direct].name = NULL;
4255 filter->aslist[direct].aslist = NULL;
4256 }
4257
4258 return 0;
4259}
4260
paul94f2b392005-06-28 12:44:16 +00004261static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004262peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004263{
4264 afi_t afi;
4265 safi_t safi;
4266 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004267 struct listnode *mnode, *mnnode;
4268 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004269 struct bgp *bgp;
4270 struct peer *peer;
4271 struct peer_group *group;
4272 struct bgp_filter *filter;
4273
paul1eb8ef22005-04-07 07:30:20 +00004274 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004275 {
paul1eb8ef22005-04-07 07:30:20 +00004276 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004277 {
4278 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4279 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4280 {
4281 filter = &peer->filter[afi][safi];
4282
4283 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4284 {
4285 if (filter->aslist[direct].name)
4286 filter->aslist[direct].aslist =
4287 as_list_lookup (filter->aslist[direct].name);
4288 else
4289 filter->aslist[direct].aslist = NULL;
4290 }
4291 }
4292 }
paul1eb8ef22005-04-07 07:30:20 +00004293 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004294 {
4295 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4296 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4297 {
4298 filter = &group->conf->filter[afi][safi];
4299
4300 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4301 {
4302 if (filter->aslist[direct].name)
4303 filter->aslist[direct].aslist =
4304 as_list_lookup (filter->aslist[direct].name);
4305 else
4306 filter->aslist[direct].aslist = NULL;
4307 }
4308 }
4309 }
4310 }
4311}
David Lamparter6b0655a2014-06-04 06:53:35 +02004312
paul718e3742002-12-13 20:15:29 +00004313/* Set route-map to the peer. */
4314int
4315peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004316 const char *name)
paul718e3742002-12-13 20:15:29 +00004317{
4318 struct bgp_filter *filter;
4319 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004320 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004321
4322 if (! peer->afc[afi][safi])
4323 return BGP_ERR_PEER_INACTIVE;
4324
paulfee0f4c2004-09-13 05:12:46 +00004325 if (direct != RMAP_IN && direct != RMAP_OUT &&
4326 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004327 return BGP_ERR_INVALID_VALUE;
4328
paulfee0f4c2004-09-13 05:12:46 +00004329 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4330 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004331 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4332
4333 filter = &peer->filter[afi][safi];
4334
4335 if (filter->map[direct].name)
4336 free (filter->map[direct].name);
4337
4338 filter->map[direct].name = strdup (name);
4339 filter->map[direct].map = route_map_lookup_by_name (name);
4340
4341 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4342 return 0;
4343
4344 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004345 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004346 {
4347 filter = &peer->filter[afi][safi];
4348
4349 if (! peer->af_group[afi][safi])
4350 continue;
4351
4352 if (filter->map[direct].name)
4353 free (filter->map[direct].name);
4354 filter->map[direct].name = strdup (name);
4355 filter->map[direct].map = route_map_lookup_by_name (name);
4356 }
4357 return 0;
4358}
4359
4360/* Unset route-map from the peer. */
4361int
4362peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4363{
4364 struct bgp_filter *filter;
4365 struct bgp_filter *gfilter;
4366 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004367 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004368
4369 if (! peer->afc[afi][safi])
4370 return BGP_ERR_PEER_INACTIVE;
4371
hassob5f29602005-05-25 21:00:28 +00004372 if (direct != RMAP_IN && direct != RMAP_OUT &&
4373 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004374 return BGP_ERR_INVALID_VALUE;
4375
hassob5f29602005-05-25 21:00:28 +00004376 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4377 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004378 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4379
4380 filter = &peer->filter[afi][safi];
4381
4382 /* apply peer-group filter */
4383 if (peer->af_group[afi][safi])
4384 {
4385 gfilter = &peer->group->conf->filter[afi][safi];
4386
4387 if (gfilter->map[direct].name)
4388 {
4389 if (filter->map[direct].name)
4390 free (filter->map[direct].name);
4391 filter->map[direct].name = strdup (gfilter->map[direct].name);
4392 filter->map[direct].map = gfilter->map[direct].map;
4393 return 0;
4394 }
4395 }
4396
4397 if (filter->map[direct].name)
4398 free (filter->map[direct].name);
4399 filter->map[direct].name = NULL;
4400 filter->map[direct].map = NULL;
4401
4402 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4403 return 0;
4404
4405 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004406 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004407 {
4408 filter = &peer->filter[afi][safi];
4409
4410 if (! peer->af_group[afi][safi])
4411 continue;
4412
4413 if (filter->map[direct].name)
4414 free (filter->map[direct].name);
4415 filter->map[direct].name = NULL;
4416 filter->map[direct].map = NULL;
4417 }
4418 return 0;
4419}
David Lamparter6b0655a2014-06-04 06:53:35 +02004420
paul718e3742002-12-13 20:15:29 +00004421/* Set unsuppress-map to the peer. */
4422int
paulfd79ac92004-10-13 05:06:08 +00004423peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4424 const char *name)
paul718e3742002-12-13 20:15:29 +00004425{
4426 struct bgp_filter *filter;
4427 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004428 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004429
4430 if (! peer->afc[afi][safi])
4431 return BGP_ERR_PEER_INACTIVE;
4432
4433 if (peer_is_group_member (peer, afi, safi))
4434 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4435
4436 filter = &peer->filter[afi][safi];
4437
4438 if (filter->usmap.name)
4439 free (filter->usmap.name);
4440
4441 filter->usmap.name = strdup (name);
4442 filter->usmap.map = route_map_lookup_by_name (name);
4443
4444 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4445 return 0;
4446
4447 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004448 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004449 {
4450 filter = &peer->filter[afi][safi];
4451
4452 if (! peer->af_group[afi][safi])
4453 continue;
4454
4455 if (filter->usmap.name)
4456 free (filter->usmap.name);
4457 filter->usmap.name = strdup (name);
4458 filter->usmap.map = route_map_lookup_by_name (name);
4459 }
4460 return 0;
4461}
4462
4463/* Unset route-map from the peer. */
4464int
4465peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4466{
4467 struct bgp_filter *filter;
4468 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004469 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004470
4471 if (! peer->afc[afi][safi])
4472 return BGP_ERR_PEER_INACTIVE;
4473
4474 if (peer_is_group_member (peer, afi, safi))
4475 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4476
4477 filter = &peer->filter[afi][safi];
4478
4479 if (filter->usmap.name)
4480 free (filter->usmap.name);
4481 filter->usmap.name = NULL;
4482 filter->usmap.map = NULL;
4483
4484 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4485 return 0;
4486
4487 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004488 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004489 {
4490 filter = &peer->filter[afi][safi];
4491
4492 if (! peer->af_group[afi][safi])
4493 continue;
4494
4495 if (filter->usmap.name)
4496 free (filter->usmap.name);
4497 filter->usmap.name = NULL;
4498 filter->usmap.map = NULL;
4499 }
4500 return 0;
4501}
David Lamparter6b0655a2014-06-04 06:53:35 +02004502
paul718e3742002-12-13 20:15:29 +00004503int
4504peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004505 u_int32_t max, u_char threshold,
4506 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004507{
4508 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004509 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004510
4511 if (! peer->afc[afi][safi])
4512 return BGP_ERR_PEER_INACTIVE;
4513
4514 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4515 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004516 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004517 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004518 if (warning)
4519 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4520 else
4521 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4522
4523 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4524 return 0;
4525
4526 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004527 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004528 {
4529 if (! peer->af_group[afi][safi])
4530 continue;
4531
4532 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4533 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004534 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004535 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004536 if (warning)
4537 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4538 else
4539 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4540 }
4541 return 0;
4542}
4543
4544int
4545peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4546{
4547 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004548 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004549
4550 if (! peer->afc[afi][safi])
4551 return BGP_ERR_PEER_INACTIVE;
4552
4553 /* apply peer-group config */
4554 if (peer->af_group[afi][safi])
4555 {
4556 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4557 PEER_FLAG_MAX_PREFIX))
4558 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4559 else
4560 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4561
4562 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4563 PEER_FLAG_MAX_PREFIX_WARNING))
4564 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4565 else
4566 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4567
4568 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004569 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004570 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004571 return 0;
4572 }
4573
4574 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4575 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4576 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004577 peer->pmax_threshold[afi][safi] = 0;
4578 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004579
4580 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4581 return 0;
4582
4583 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004584 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004585 {
4586 if (! peer->af_group[afi][safi])
4587 continue;
4588
4589 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4590 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4591 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004592 peer->pmax_threshold[afi][safi] = 0;
4593 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004594 }
4595 return 0;
4596}
David Lamparter5f9adb52014-05-19 23:15:02 +02004597
4598static int is_ebgp_multihop_configured (struct peer *peer)
4599{
4600 struct peer_group *group;
4601 struct listnode *node, *nnode;
4602 struct peer *peer1;
4603
4604 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4605 {
4606 group = peer->group;
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004607 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4608 (group->conf->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004609 return 1;
4610
4611 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4612 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004613 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
4614 (peer1->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004615 return 1;
4616 }
4617 }
4618 else
4619 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004620 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4621 (peer->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004622 return 1;
4623 }
4624 return 0;
4625}
4626
Nick Hilliardfa411a22011-03-23 15:33:17 +00004627/* Set # of hops between us and BGP peer. */
4628int
4629peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4630{
4631 struct peer_group *group;
4632 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004633 int ret;
4634
4635 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4636
Nick Hilliardfa411a22011-03-23 15:33:17 +00004637 /* We cannot configure ttl-security hops when ebgp-multihop is already
4638 set. For non peer-groups, the check is simple. For peer-groups, it's
4639 slightly messy, because we need to check both the peer-group structure
4640 and all peer-group members for any trace of ebgp-multihop configuration
4641 before actually applying the ttl-security rules. Cisco really made a
4642 mess of this configuration parameter, and OpenBGPD got it right.
4643 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004644
David Lamparter5f9adb52014-05-19 23:15:02 +02004645 if (peer->gtsm_hops == 0)
4646 {
4647 if (is_ebgp_multihop_configured (peer))
4648 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004649
David Lamparter5f9adb52014-05-19 23:15:02 +02004650 /* specify MAXTTL on outgoing packets */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004651 /* Routine handles iBGP peers correctly */
David Lamparter5f9adb52014-05-19 23:15:02 +02004652 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4653 if (ret != 0)
4654 return ret;
4655 }
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004656
Nick Hilliardfa411a22011-03-23 15:33:17 +00004657 peer->gtsm_hops = gtsm_hops;
4658
Nick Hilliardfa411a22011-03-23 15:33:17 +00004659 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4660 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004661 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004662 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4663 }
4664 else
4665 {
4666 group = peer->group;
4667 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4668 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004669 peer->gtsm_hops = group->conf->gtsm_hops;
4670
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004671 /* Change setting of existing peer
4672 * established then change value (may break connectivity)
4673 * not established yet (teardown session and restart)
4674 * no session then do nothing (will get handled by next connection)
4675 */
4676 if (peer->status == Established)
4677 {
4678 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4679 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4680 MAXTTL + 1 - peer->gtsm_hops);
4681 }
4682 else if (peer->status < Established)
4683 {
4684 if (BGP_DEBUG (events, EVENTS))
4685 zlog_debug ("%s Min-ttl changed", peer->host);
4686 BGP_EVENT_ADD (peer, BGP_Stop);
4687 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004688 }
4689 }
4690
4691 return 0;
4692}
4693
4694int
4695peer_ttl_security_hops_unset (struct peer *peer)
4696{
4697 struct peer_group *group;
4698 struct listnode *node, *nnode;
4699 struct peer *opeer;
4700
4701 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4702
Nick Hilliardfa411a22011-03-23 15:33:17 +00004703 /* if a peer-group member, then reset to peer-group default rather than 0 */
4704 if (peer_group_active (peer))
4705 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4706 else
4707 peer->gtsm_hops = 0;
4708
4709 opeer = peer;
4710 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4711 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004712 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004713 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4714 }
4715 else
4716 {
4717 group = peer->group;
4718 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4719 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004720 peer->gtsm_hops = 0;
4721
4722 if (peer->fd >= 0)
4723 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4724 }
4725 }
4726
4727 return peer_ebgp_multihop_unset (opeer);
4728}
David Lamparter6b0655a2014-06-04 06:53:35 +02004729
paul718e3742002-12-13 20:15:29 +00004730int
4731peer_clear (struct peer *peer)
4732{
4733 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4734 {
hasso0a486e52005-02-01 20:57:17 +00004735 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4736 {
4737 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4738 if (peer->t_pmax_restart)
4739 {
4740 BGP_TIMER_OFF (peer->t_pmax_restart);
4741 if (BGP_DEBUG (events, EVENTS))
4742 zlog_debug ("%s Maximum-prefix restart timer canceled",
4743 peer->host);
4744 }
4745 BGP_EVENT_ADD (peer, BGP_Start);
4746 return 0;
4747 }
4748
paul718e3742002-12-13 20:15:29 +00004749 peer->v_start = BGP_INIT_START_TIMER;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00004750 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00004751 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4752 BGP_NOTIFY_CEASE_ADMIN_RESET);
4753 else
4754 BGP_EVENT_ADD (peer, BGP_Stop);
4755 }
4756 return 0;
4757}
4758
4759int
4760peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4761 enum bgp_clear_type stype)
4762{
4763 if (peer->status != Established)
4764 return 0;
4765
4766 if (! peer->afc[afi][safi])
4767 return BGP_ERR_AF_UNCONFIGURED;
4768
Timo Teräs5a2a1ec2015-10-22 11:35:18 +03004769 peer->rtt = sockopt_tcp_rtt (peer->fd);
4770
paulfee0f4c2004-09-13 05:12:46 +00004771 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4772 {
4773 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4774 return 0;
4775 bgp_check_local_routes_rsclient (peer, afi, safi);
4776 bgp_soft_reconfig_rsclient (peer, afi, safi);
4777 }
4778
paul718e3742002-12-13 20:15:29 +00004779 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4780 bgp_announce_route (peer, afi, safi);
4781
4782 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4783 {
4784 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4785 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4786 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4787 {
4788 struct bgp_filter *filter = &peer->filter[afi][safi];
4789 u_char prefix_type;
4790
4791 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4792 prefix_type = ORF_TYPE_PREFIX;
4793 else
4794 prefix_type = ORF_TYPE_PREFIX_OLD;
4795
4796 if (filter->plist[FILTER_IN].plist)
4797 {
4798 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4799 bgp_route_refresh_send (peer, afi, safi,
4800 prefix_type, REFRESH_DEFER, 1);
4801 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4802 REFRESH_IMMEDIATE, 0);
4803 }
4804 else
4805 {
4806 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4807 bgp_route_refresh_send (peer, afi, safi,
4808 prefix_type, REFRESH_IMMEDIATE, 1);
4809 else
4810 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4811 }
4812 return 0;
4813 }
4814 }
4815
4816 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4817 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4818 {
4819 /* If neighbor has soft reconfiguration inbound flag.
4820 Use Adj-RIB-In database. */
4821 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4822 bgp_soft_reconfig_in (peer, afi, safi);
4823 else
4824 {
4825 /* If neighbor has route refresh capability, send route refresh
4826 message to the peer. */
4827 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4828 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4829 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4830 else
4831 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4832 }
4833 }
4834 return 0;
4835}
David Lamparter6b0655a2014-06-04 06:53:35 +02004836
paulfd79ac92004-10-13 05:06:08 +00004837/* Display peer uptime.*/
4838/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004839char *
4840peer_uptime (time_t uptime2, char *buf, size_t len)
4841{
4842 time_t uptime1;
4843 struct tm *tm;
4844
4845 /* Check buffer length. */
4846 if (len < BGP_UPTIME_LEN)
4847 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004848 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004849 /* XXX: should return status instead of buf... */
4850 snprintf (buf, len, "<error> ");
4851 return buf;
paul718e3742002-12-13 20:15:29 +00004852 }
4853
4854 /* If there is no connection has been done before print `never'. */
4855 if (uptime2 == 0)
4856 {
4857 snprintf (buf, len, "never ");
4858 return buf;
4859 }
4860
4861 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004862 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004863 uptime1 -= uptime2;
4864 tm = gmtime (&uptime1);
Paul Jakma84c38402015-05-26 15:19:38 +01004865
paul718e3742002-12-13 20:15:29 +00004866 /* Making formatted timer strings. */
4867#define ONE_DAY_SECOND 60*60*24
Paul Jakma84c38402015-05-26 15:19:38 +01004868#define ONE_WEEK_SECOND ONE_DAY_SECOND*7
4869#define ONE_YEAR_SECOND ONE_DAY_SECOND*365
paul718e3742002-12-13 20:15:29 +00004870
4871 if (uptime1 < ONE_DAY_SECOND)
4872 snprintf (buf, len, "%02d:%02d:%02d",
4873 tm->tm_hour, tm->tm_min, tm->tm_sec);
4874 else if (uptime1 < ONE_WEEK_SECOND)
4875 snprintf (buf, len, "%dd%02dh%02dm",
4876 tm->tm_yday, tm->tm_hour, tm->tm_min);
Paul Jakma84c38402015-05-26 15:19:38 +01004877 else if (uptime1 < ONE_YEAR_SECOND)
paul718e3742002-12-13 20:15:29 +00004878 snprintf (buf, len, "%02dw%dd%02dh",
4879 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
Paul Jakma84c38402015-05-26 15:19:38 +01004880 else
4881 snprintf (buf, len, "%02dy%02dw%dd",
4882 tm->tm_year - 70, tm->tm_yday/7,
4883 tm->tm_yday - ((tm->tm_yday/7) * 7));
paul718e3742002-12-13 20:15:29 +00004884 return buf;
4885}
David Lamparter6b0655a2014-06-04 06:53:35 +02004886
paul94f2b392005-06-28 12:44:16 +00004887static void
paul718e3742002-12-13 20:15:29 +00004888bgp_config_write_filter (struct vty *vty, struct peer *peer,
4889 afi_t afi, safi_t safi)
4890{
4891 struct bgp_filter *filter;
4892 struct bgp_filter *gfilter = NULL;
4893 char *addr;
4894 int in = FILTER_IN;
4895 int out = FILTER_OUT;
4896
4897 addr = peer->host;
4898 filter = &peer->filter[afi][safi];
4899 if (peer->af_group[afi][safi])
4900 gfilter = &peer->group->conf->filter[afi][safi];
4901
4902 /* distribute-list. */
4903 if (filter->dlist[in].name)
4904 if (! gfilter || ! gfilter->dlist[in].name
4905 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4906 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4907 filter->dlist[in].name, VTY_NEWLINE);
4908 if (filter->dlist[out].name && ! gfilter)
4909 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4910 filter->dlist[out].name, VTY_NEWLINE);
4911
4912 /* prefix-list. */
4913 if (filter->plist[in].name)
4914 if (! gfilter || ! gfilter->plist[in].name
4915 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4916 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4917 filter->plist[in].name, VTY_NEWLINE);
4918 if (filter->plist[out].name && ! gfilter)
4919 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4920 filter->plist[out].name, VTY_NEWLINE);
4921
4922 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004923 if (filter->map[RMAP_IN].name)
4924 if (! gfilter || ! gfilter->map[RMAP_IN].name
4925 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004926 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004927 filter->map[RMAP_IN].name, VTY_NEWLINE);
4928 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004929 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004930 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4931 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4932 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4933 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4934 if (filter->map[RMAP_EXPORT].name)
4935 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4936 || strcmp (filter->map[RMAP_EXPORT].name,
4937 gfilter->map[RMAP_EXPORT].name) != 0)
4938 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4939 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004940
4941 /* unsuppress-map */
4942 if (filter->usmap.name && ! gfilter)
4943 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4944 filter->usmap.name, VTY_NEWLINE);
4945
4946 /* filter-list. */
4947 if (filter->aslist[in].name)
4948 if (! gfilter || ! gfilter->aslist[in].name
4949 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4950 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4951 filter->aslist[in].name, VTY_NEWLINE);
4952 if (filter->aslist[out].name && ! gfilter)
4953 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4954 filter->aslist[out].name, VTY_NEWLINE);
4955}
4956
4957/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004958static void
paul718e3742002-12-13 20:15:29 +00004959bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4960 struct peer *peer, afi_t afi, safi_t safi)
4961{
paul718e3742002-12-13 20:15:29 +00004962 struct peer *g_peer = NULL;
4963 char buf[SU_ADDRSTRLEN];
4964 char *addr;
4965
paul718e3742002-12-13 20:15:29 +00004966 addr = peer->host;
4967 if (peer_group_active (peer))
4968 g_peer = peer->group->conf;
4969
4970 /************************************
4971 ****** Global to the neighbor ******
4972 ************************************/
4973 if (afi == AFI_IP && safi == SAFI_UNICAST)
4974 {
4975 /* remote-as. */
4976 if (! peer_group_active (peer))
4977 {
4978 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4979 vty_out (vty, " neighbor %s peer-group%s", addr,
4980 VTY_NEWLINE);
4981 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004982 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004983 VTY_NEWLINE);
4984 }
4985 else
4986 {
4987 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004988 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004989 VTY_NEWLINE);
4990 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4991 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4992 peer->group->name, VTY_NEWLINE);
4993 }
4994
4995 /* local-as. */
4996 if (peer->change_local_as)
4997 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00004998 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004999 peer->change_local_as,
5000 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00005001 " no-prepend" : "",
5002 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
5003 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005004
5005 /* Description. */
5006 if (peer->desc)
5007 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
5008 VTY_NEWLINE);
5009
5010 /* Shutdown. */
5011 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
5012 if (! peer_group_active (peer) ||
5013 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
5014 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
5015
Paul Jakma0df7c912008-07-21 21:02:49 +00005016 /* Password. */
5017 if (peer->password)
5018 if (!peer_group_active (peer)
5019 || ! g_peer->password
5020 || strcmp (peer->password, g_peer->password) != 0)
5021 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
5022 VTY_NEWLINE);
5023
paul718e3742002-12-13 20:15:29 +00005024 /* BGP port. */
5025 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00005026 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00005027 VTY_NEWLINE);
5028
5029 /* Local interface name. */
5030 if (peer->ifname)
5031 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
5032 VTY_NEWLINE);
5033
5034 /* Passive. */
5035 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
5036 if (! peer_group_active (peer) ||
5037 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
5038 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
5039
5040 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00005041 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00005042 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00005043 if (! peer_group_active (peer) ||
5044 g_peer->ttl != peer->ttl)
5045 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
5046 VTY_NEWLINE);
5047
Nick Hilliardfa411a22011-03-23 15:33:17 +00005048 /* ttl-security hops */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00005049 if (peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00005050 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00005051 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00005052 peer->gtsm_hops, VTY_NEWLINE);
5053
hasso6ffd2072005-02-02 14:50:11 +00005054 /* disable-connected-check. */
5055 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00005056 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00005057 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
5058 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005059
5060 /* Update-source. */
5061 if (peer->update_if)
5062 if (! peer_group_active (peer) || ! g_peer->update_if
5063 || strcmp (g_peer->update_if, peer->update_if) != 0)
5064 vty_out (vty, " neighbor %s update-source %s%s", addr,
5065 peer->update_if, VTY_NEWLINE);
5066 if (peer->update_source)
5067 if (! peer_group_active (peer) || ! g_peer->update_source
5068 || sockunion_cmp (g_peer->update_source,
5069 peer->update_source) != 0)
5070 vty_out (vty, " neighbor %s update-source %s%s", addr,
5071 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
5072 VTY_NEWLINE);
5073
paul718e3742002-12-13 20:15:29 +00005074 /* advertisement-interval */
Daniel Walton0d7435f2015-10-22 11:35:20 +03005075 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV) &&
5076 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00005077 vty_out (vty, " neighbor %s advertisement-interval %d%s",
5078 addr, peer->v_routeadv, VTY_NEWLINE);
5079
5080 /* timers. */
5081 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
5082 && ! peer_group_active (peer))
5083 vty_out (vty, " neighbor %s timers %d %d%s", addr,
5084 peer->keepalive, peer->holdtime, VTY_NEWLINE);
5085
Daniel Walton0d7435f2015-10-22 11:35:20 +03005086 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT) &&
5087 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00005088 vty_out (vty, " neighbor %s timers connect %d%s", addr,
5089 peer->connect, VTY_NEWLINE);
5090
5091 /* Default weight. */
5092 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
5093 if (! peer_group_active (peer) ||
5094 g_peer->weight != peer->weight)
5095 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
5096 VTY_NEWLINE);
5097
paul718e3742002-12-13 20:15:29 +00005098 /* Dynamic capability. */
5099 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5100 if (! peer_group_active (peer) ||
5101 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5102 vty_out (vty, " neighbor %s capability dynamic%s", addr,
5103 VTY_NEWLINE);
5104
5105 /* dont capability negotiation. */
5106 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
5107 if (! peer_group_active (peer) ||
5108 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
5109 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
5110 VTY_NEWLINE);
5111
5112 /* override capability negotiation. */
5113 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5114 if (! peer_group_active (peer) ||
5115 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5116 vty_out (vty, " neighbor %s override-capability%s", addr,
5117 VTY_NEWLINE);
5118
5119 /* strict capability negotiation. */
5120 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5121 if (! peer_group_active (peer) ||
5122 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5123 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
5124 VTY_NEWLINE);
5125
Christian Franke15c71342012-11-19 11:17:31 +00005126 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
paul718e3742002-12-13 20:15:29 +00005127 {
5128 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5129 {
5130 if (peer->afc[AFI_IP][SAFI_UNICAST])
5131 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5132 }
5133 else
5134 {
5135 if (! peer->afc[AFI_IP][SAFI_UNICAST])
5136 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
5137 }
5138 }
5139 }
5140
5141
5142 /************************************
5143 ****** Per AF to the neighbor ******
5144 ************************************/
5145
5146 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
5147 {
5148 if (peer->af_group[afi][safi])
5149 vty_out (vty, " neighbor %s peer-group %s%s", addr,
5150 peer->group->name, VTY_NEWLINE);
5151 else
5152 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5153 }
5154
5155 /* ORF capability. */
5156 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5157 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5158 if (! peer->af_group[afi][safi])
5159 {
5160 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
5161
5162 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5163 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5164 vty_out (vty, " both");
5165 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
5166 vty_out (vty, " send");
5167 else
5168 vty_out (vty, " receive");
5169 vty_out (vty, "%s", VTY_NEWLINE);
5170 }
5171
5172 /* Route reflector client. */
5173 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
5174 && ! peer->af_group[afi][safi])
5175 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
5176 VTY_NEWLINE);
5177
5178 /* Nexthop self. */
5179 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
5180 && ! peer->af_group[afi][safi])
Timo Teräs9e7a53c2014-04-24 10:22:37 +03005181 vty_out (vty, " neighbor %s next-hop-self%s%s", addr,
5182 peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ?
5183 " all" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005184
5185 /* Remove private AS. */
5186 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
5187 && ! peer->af_group[afi][safi])
5188 vty_out (vty, " neighbor %s remove-private-AS%s",
5189 addr, VTY_NEWLINE);
5190
5191 /* send-community print. */
5192 if (! peer->af_group[afi][safi])
5193 {
5194 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5195 {
5196 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5197 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5198 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
5199 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5200 vty_out (vty, " neighbor %s send-community extended%s",
5201 addr, VTY_NEWLINE);
5202 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5203 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
5204 }
5205 else
5206 {
5207 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5208 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5209 vty_out (vty, " no neighbor %s send-community both%s",
5210 addr, VTY_NEWLINE);
5211 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5212 vty_out (vty, " no neighbor %s send-community extended%s",
5213 addr, VTY_NEWLINE);
5214 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5215 vty_out (vty, " no neighbor %s send-community%s",
5216 addr, VTY_NEWLINE);
5217 }
5218 }
5219
5220 /* Default information */
5221 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5222 && ! peer->af_group[afi][safi])
5223 {
5224 vty_out (vty, " neighbor %s default-originate", addr);
5225 if (peer->default_rmap[afi][safi].name)
5226 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5227 vty_out (vty, "%s", VTY_NEWLINE);
5228 }
5229
5230 /* Soft reconfiguration inbound. */
5231 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5232 if (! peer->af_group[afi][safi] ||
5233 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5234 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5235 VTY_NEWLINE);
5236
5237 /* maximum-prefix. */
5238 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5239 if (! peer->af_group[afi][safi]
5240 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005241 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005242 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5243 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005244 {
hasso0a486e52005-02-01 20:57:17 +00005245 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5246 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5247 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5248 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5249 vty_out (vty, " warning-only");
5250 if (peer->pmax_restart[afi][safi])
5251 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5252 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005253 }
paul718e3742002-12-13 20:15:29 +00005254
5255 /* Route server client. */
5256 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5257 && ! peer->af_group[afi][safi])
5258 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5259
Dylan Hall3cf12882011-10-27 15:28:17 +04005260 /* Nexthop-local unchanged. */
5261 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5262 && ! peer->af_group[afi][safi])
5263 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5264
paul718e3742002-12-13 20:15:29 +00005265 /* Allow AS in. */
5266 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5267 if (! peer_group_active (peer)
5268 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5269 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5270 {
5271 if (peer->allowas_in[afi][safi] == 3)
5272 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5273 else
5274 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5275 peer->allowas_in[afi][safi], VTY_NEWLINE);
5276 }
5277
5278 /* Filter. */
5279 bgp_config_write_filter (vty, peer, afi, safi);
5280
5281 /* atribute-unchanged. */
5282 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5283 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5284 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5285 && ! peer->af_group[afi][safi])
5286 {
5287 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5288 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5289 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5290 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5291 else
5292 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5293 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5294 " as-path" : "",
5295 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5296 " next-hop" : "",
5297 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5298 " med" : "", VTY_NEWLINE);
5299 }
5300}
5301
5302/* Display "address-family" configuration header. */
5303void
5304bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5305 int *write)
5306{
5307 if (*write)
5308 return;
5309
5310 if (afi == AFI_IP && safi == SAFI_UNICAST)
5311 return;
5312
5313 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5314
5315 if (afi == AFI_IP)
5316 {
5317 if (safi == SAFI_MULTICAST)
5318 vty_out (vty, "ipv4 multicast");
5319 else if (safi == SAFI_MPLS_VPN)
Lou Bergera3fda882016-01-12 13:42:04 -05005320 vty_out (vty, "vpnv4");
5321 else if (safi == SAFI_ENCAP)
5322 vty_out (vty, "encap");
paul718e3742002-12-13 20:15:29 +00005323 }
5324 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005325 {
Lou Berger13c378d2016-01-12 13:41:56 -05005326 if (safi == SAFI_MPLS_VPN)
5327 vty_out (vty, "vpnv6");
Lou Bergera3fda882016-01-12 13:42:04 -05005328 else if (safi == SAFI_ENCAP)
5329 vty_out (vty, "encapv6");
Lou Berger13c378d2016-01-12 13:41:56 -05005330 else
5331 {
5332 vty_out (vty, "ipv6");
5333 if (safi == SAFI_MULTICAST)
5334 vty_out (vty, " multicast");
5335 }
Paul Jakma37a217a2007-04-10 19:20:29 +00005336 }
paul718e3742002-12-13 20:15:29 +00005337
5338 vty_out (vty, "%s", VTY_NEWLINE);
5339
5340 *write = 1;
5341}
5342
5343/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005344static int
paul718e3742002-12-13 20:15:29 +00005345bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5346 safi_t safi)
5347{
5348 int write = 0;
5349 struct peer *peer;
5350 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005351 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005352
5353 bgp_config_write_network (vty, bgp, afi, safi, &write);
5354
5355 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5356
paul1eb8ef22005-04-07 07:30:20 +00005357 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005358 {
5359 if (group->conf->afc[afi][safi])
5360 {
5361 bgp_config_write_family_header (vty, afi, safi, &write);
5362 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5363 }
5364 }
paul1eb8ef22005-04-07 07:30:20 +00005365 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005366 {
5367 if (peer->afc[afi][safi])
5368 {
5369 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5370 {
5371 bgp_config_write_family_header (vty, afi, safi, &write);
5372 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5373 }
5374 }
5375 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005376
5377 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5378
Roman Hoog Antink6184c392014-03-17 14:01:42 +01005379 bgp_config_write_distance (vty, bgp, afi, safi, &write);
5380
paul718e3742002-12-13 20:15:29 +00005381 if (write)
5382 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5383
5384 return write;
5385}
5386
5387int
5388bgp_config_write (struct vty *vty)
5389{
5390 int write = 0;
5391 struct bgp *bgp;
5392 struct peer_group *group;
5393 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005394 struct listnode *node, *nnode;
5395 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005396
5397 /* BGP Multiple instance. */
5398 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5399 {
5400 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5401 write++;
5402 }
5403
5404 /* BGP Config type. */
5405 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5406 {
5407 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5408 write++;
5409 }
5410
5411 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005412 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005413 {
5414 if (write)
5415 vty_out (vty, "!%s", VTY_NEWLINE);
5416
5417 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005418 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005419
5420 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5421 {
5422 if (bgp->name)
5423 vty_out (vty, " view %s", bgp->name);
5424 }
5425 vty_out (vty, "%s", VTY_NEWLINE);
5426
5427 /* No Synchronization */
5428 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5429 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5430
5431 /* BGP fast-external-failover. */
5432 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5433 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5434
5435 /* BGP router ID. */
5436 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5437 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5438 VTY_NEWLINE);
5439
paul848973c2003-08-13 00:32:49 +00005440 /* BGP log-neighbor-changes. */
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07005441 if (!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5442 vty_out (vty, " no bgp log-neighbor-changes%s", VTY_NEWLINE);
paul848973c2003-08-13 00:32:49 +00005443
paul718e3742002-12-13 20:15:29 +00005444 /* BGP configuration. */
5445 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5446 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5447
5448 /* BGP default ipv4-unicast. */
5449 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5450 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5451
5452 /* BGP default local-preference. */
5453 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5454 vty_out (vty, " bgp default local-preference %d%s",
5455 bgp->default_local_pref, VTY_NEWLINE);
5456
5457 /* BGP client-to-client reflection. */
5458 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5459 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5460
5461 /* BGP cluster ID. */
5462 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5463 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5464 VTY_NEWLINE);
5465
hassoe0701b72004-05-20 09:19:34 +00005466 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005467 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005468 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5469 VTY_NEWLINE);
5470
5471 /* Confederation peer */
5472 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005473 {
hassoe0701b72004-05-20 09:19:34 +00005474 int i;
paul718e3742002-12-13 20:15:29 +00005475
hassoe0701b72004-05-20 09:19:34 +00005476 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005477
hassoe0701b72004-05-20 09:19:34 +00005478 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005479 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005480
hassoe0701b72004-05-20 09:19:34 +00005481 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005482 }
5483
5484 /* BGP enforce-first-as. */
5485 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5486 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5487
5488 /* BGP deterministic-med. */
5489 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5490 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005491
5492 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005493 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5494 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5495 bgp->stalepath_time, VTY_NEWLINE);
Philippe Guibert4afa3dd2016-05-24 16:52:02 +02005496 if (bgp->restart_time != BGP_DEFAULT_RESTART_TIME)
5497 vty_out (vty, " bgp graceful-restart restart-time %d%s",
5498 bgp->restart_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005499 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5500 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5501
paul718e3742002-12-13 20:15:29 +00005502 /* BGP bestpath method. */
5503 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5504 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005505 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5506 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
Pradosh Mohapatra2fdd4552013-09-07 07:02:36 +00005507 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
5508 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
5509 }
paul718e3742002-12-13 20:15:29 +00005510 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5511 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5512 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5513 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5514 {
5515 vty_out (vty, " bgp bestpath med");
5516 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5517 vty_out (vty, " confed");
5518 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5519 vty_out (vty, " missing-as-worst");
5520 vty_out (vty, "%s", VTY_NEWLINE);
5521 }
5522
5523 /* BGP network import check. */
5524 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5525 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5526
5527 /* BGP scan interval. */
5528 bgp_config_write_scan_time (vty);
5529
5530 /* BGP flag dampening. */
5531 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5532 BGP_CONFIG_DAMPENING))
5533 bgp_config_write_damp (vty);
5534
5535 /* BGP static route configuration. */
5536 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5537
5538 /* BGP redistribute configuration. */
5539 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5540
5541 /* BGP timers configuration. */
5542 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5543 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5544 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5545 bgp->default_holdtime, VTY_NEWLINE);
5546
5547 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005548 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005549 {
5550 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5551 }
5552
5553 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005554 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005555 {
5556 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5557 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5558 }
5559
Josh Bailey165b5ff2011-07-20 20:43:22 -07005560 /* maximum-paths */
5561 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5562
paul718e3742002-12-13 20:15:29 +00005563 /* Distance configuration. */
Roman Hoog Antink6184c392014-03-17 14:01:42 +01005564 bgp_config_write_distance (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
paul718e3742002-12-13 20:15:29 +00005565
5566 /* No auto-summary */
5567 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5568 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5569
5570 /* IPv4 multicast configuration. */
5571 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5572
5573 /* IPv4 VPN configuration. */
5574 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5575
Lou Bergera3fda882016-01-12 13:42:04 -05005576 /* ENCAPv4 configuration. */
5577 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_ENCAP);
5578
paul718e3742002-12-13 20:15:29 +00005579 /* IPv6 unicast configuration. */
5580 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5581
Paul Jakma37a217a2007-04-10 19:20:29 +00005582 /* IPv6 multicast configuration. */
5583 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5584
Lou Berger13c378d2016-01-12 13:41:56 -05005585 /* IPv6 VPN configuration. */
5586 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MPLS_VPN);
5587
Lou Bergera3fda882016-01-12 13:42:04 -05005588 /* ENCAPv6 configuration. */
5589 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_ENCAP);
5590
5591 vty_out (vty, " exit%s", VTY_NEWLINE);
5592
paul718e3742002-12-13 20:15:29 +00005593 write++;
5594 }
5595 return write;
5596}
5597
5598void
paul94f2b392005-06-28 12:44:16 +00005599bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005600{
5601 memset (&bgp_master, 0, sizeof (struct bgp_master));
5602
5603 bm = &bgp_master;
5604 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005605 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005606 bm->port = BGP_PORT_DEFAULT;
5607 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005608 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005609}
paul200df112005-06-01 11:17:05 +00005610
David Lamparter6b0655a2014-06-04 06:53:35 +02005611
paul718e3742002-12-13 20:15:29 +00005612void
paul94f2b392005-06-28 12:44:16 +00005613bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005614{
paul718e3742002-12-13 20:15:29 +00005615 /* BGP VTY commands installation. */
5616 bgp_vty_init ();
5617
paul718e3742002-12-13 20:15:29 +00005618 /* Init zebra. */
Donald Sharp774914f2015-10-14 08:50:39 -04005619 bgp_zebra_init (bm->master);
paul718e3742002-12-13 20:15:29 +00005620
5621 /* BGP inits. */
5622 bgp_attr_init ();
5623 bgp_debug_init ();
5624 bgp_dump_init ();
5625 bgp_route_init ();
5626 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005627 bgp_address_init ();
paul718e3742002-12-13 20:15:29 +00005628 bgp_scan_init ();
5629 bgp_mplsvpn_init ();
Lou Berger298cc2f2016-01-12 13:42:02 -05005630 bgp_encap_init ();
paul718e3742002-12-13 20:15:29 +00005631
5632 /* Access list initialize. */
5633 access_list_init ();
5634 access_list_add_hook (peer_distribute_update);
5635 access_list_delete_hook (peer_distribute_update);
5636
5637 /* Filter list initialize. */
5638 bgp_filter_init ();
5639 as_list_add_hook (peer_aslist_update);
5640 as_list_delete_hook (peer_aslist_update);
5641
5642 /* Prefix list initialize.*/
5643 prefix_list_init ();
5644 prefix_list_add_hook (peer_prefix_list_update);
5645 prefix_list_delete_hook (peer_prefix_list_update);
5646
5647 /* Community list initialize. */
5648 bgp_clist = community_list_init ();
5649
5650#ifdef HAVE_SNMP
5651 bgp_snmp_init ();
5652#endif /* HAVE_SNMP */
5653}
paul545acaf2004-04-20 15:13:15 +00005654
5655void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005656bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005657{
paul545acaf2004-04-20 15:13:15 +00005658 struct bgp *bgp;
5659 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005660 struct listnode *node, *nnode;
5661 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005662
paul1eb8ef22005-04-07 07:30:20 +00005663 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5664 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005665 if (peer->status == Established)
5666 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5667 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005668
paul545acaf2004-04-20 15:13:15 +00005669 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005670
paule210cf92005-06-15 19:15:35 +00005671 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005672 {
5673 work_queue_free (bm->process_main_queue);
5674 bm->process_main_queue = NULL;
5675 }
paule210cf92005-06-15 19:15:35 +00005676 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005677 {
5678 work_queue_free (bm->process_rsclient_queue);
5679 bm->process_rsclient_queue = NULL;
5680 }
paul545acaf2004-04-20 15:13:15 +00005681}