blob: 669782dfca0df584bf533aa6256e67b99de62eb1 [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. */
David Lamparter584083d2016-05-24 18:58:08 +0200163static int
paul718e3742002-12-13 20:15:29 +0000164bgp_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
David Lamparter584083d2016-05-24 18:58:08 +0200191void
192bgp_router_id_zebra_bump (void)
193{
194 struct listnode *node, *nnode;
195 struct bgp *bgp;
196
197 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
198 {
199 if (!bgp->router_id_static.s_addr)
200 bgp_router_id_set (bgp, &router_id_zebra);
201 }
202}
203
204int
205bgp_router_id_static_set (struct bgp *bgp, struct in_addr id)
206{
207 bgp->router_id_static = id;
208 bgp_router_id_set (bgp, id.s_addr ? &id : &router_id_zebra);
209 return 0;
210}
211
paul718e3742002-12-13 20:15:29 +0000212/* BGP's cluster-id control. */
213int
214bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
215{
216 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000217 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000218
219 if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)
220 && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id))
221 return 0;
222
223 IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id);
224 bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID);
225
226 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000227 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000228 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000229 if (peer->sort != BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +0000230 continue;
231
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000232 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000233 {
234 peer->last_reset = PEER_DOWN_CLID_CHANGE;
235 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
236 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
237 }
paul718e3742002-12-13 20:15:29 +0000238 }
239 return 0;
240}
241
242int
243bgp_cluster_id_unset (struct bgp *bgp)
244{
245 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000246 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000247
248 if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID))
249 return 0;
250
251 bgp->cluster_id.s_addr = 0;
252 bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID);
253
254 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000255 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000256 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000257 if (peer->sort != BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +0000258 continue;
259
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000260 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000261 {
262 peer->last_reset = PEER_DOWN_CLID_CHANGE;
263 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
264 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
265 }
paul718e3742002-12-13 20:15:29 +0000266 }
267 return 0;
268}
David Lamparter6b0655a2014-06-04 06:53:35 +0200269
Stephen Hemminger65957882010-01-15 16:22:10 +0300270/* time_t value that is monotonicly increasing
271 * and uneffected by adjustments to system clock
272 */
273time_t bgp_clock (void)
274{
275 struct timeval tv;
276
277 quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv);
278 return tv.tv_sec;
279}
280
paul718e3742002-12-13 20:15:29 +0000281/* BGP timer configuration. */
282int
283bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
284{
285 bgp->default_keepalive = (keepalive < holdtime / 3
286 ? keepalive : holdtime / 3);
287 bgp->default_holdtime = holdtime;
288
289 return 0;
290}
291
292int
293bgp_timers_unset (struct bgp *bgp)
294{
295 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
296 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
297
298 return 0;
299}
David Lamparter6b0655a2014-06-04 06:53:35 +0200300
paul718e3742002-12-13 20:15:29 +0000301/* BGP confederation configuration. */
302int
303bgp_confederation_id_set (struct bgp *bgp, as_t as)
304{
305 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000306 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000307 int already_confed;
308
309 if (as == 0)
310 return BGP_ERR_INVALID_AS;
311
312 /* Remember - were we doing confederation before? */
313 already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);
314 bgp->confed_id = as;
315 bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);
316
317 /* If we were doing confederation already, this is just an external
318 AS change. Just Reset EBGP sessions, not CONFED sessions. If we
319 were not doing confederation before, reset all EBGP sessions. */
paul1eb8ef22005-04-07 07:30:20 +0000320 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000321 {
322 /* We're looking for peers who's AS is not local or part of our
323 confederation. */
324 if (already_confed)
325 {
326 if (peer_sort (peer) == BGP_PEER_EBGP)
327 {
328 peer->local_as = as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000329 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000330 {
331 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
332 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
333 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
334 }
335
paul718e3742002-12-13 20:15:29 +0000336 else
337 BGP_EVENT_ADD (peer, BGP_Stop);
338 }
339 }
340 else
341 {
342 /* Not doign confederation before, so reset every non-local
343 session */
344 if (peer_sort (peer) != BGP_PEER_IBGP)
345 {
346 /* Reset the local_as to be our EBGP one */
347 if (peer_sort (peer) == BGP_PEER_EBGP)
348 peer->local_as = as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000349 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000350 {
351 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
352 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
353 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
354 }
paul718e3742002-12-13 20:15:29 +0000355 else
356 BGP_EVENT_ADD (peer, BGP_Stop);
357 }
358 }
359 }
360 return 0;
361}
362
363int
364bgp_confederation_id_unset (struct bgp *bgp)
365{
366 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000367 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000368
369 bgp->confed_id = 0;
370 bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
371
paul1eb8ef22005-04-07 07:30:20 +0000372 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000373 {
374 /* We're looking for peers who's AS is not local */
375 if (peer_sort (peer) != BGP_PEER_IBGP)
376 {
377 peer->local_as = bgp->as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000378 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000379 {
380 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
381 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
382 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
383 }
384
paul718e3742002-12-13 20:15:29 +0000385 else
386 BGP_EVENT_ADD (peer, BGP_Stop);
387 }
388 }
389 return 0;
390}
391
392/* Is an AS part of the confed or not? */
393int
394bgp_confederation_peers_check (struct bgp *bgp, as_t as)
395{
396 int i;
397
398 if (! bgp)
399 return 0;
400
401 for (i = 0; i < bgp->confed_peers_cnt; i++)
402 if (bgp->confed_peers[i] == as)
403 return 1;
404
405 return 0;
406}
407
408/* Add an AS to the confederation set. */
409int
410bgp_confederation_peers_add (struct bgp *bgp, as_t as)
411{
412 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000413 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000414
415 if (! bgp)
416 return BGP_ERR_INVALID_BGP;
417
418 if (bgp->as == as)
419 return BGP_ERR_INVALID_AS;
420
421 if (bgp_confederation_peers_check (bgp, as))
422 return -1;
423
424 if (bgp->confed_peers)
425 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
426 bgp->confed_peers,
427 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
428 else
429 bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST,
430 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
431
432 bgp->confed_peers[bgp->confed_peers_cnt] = as;
433 bgp->confed_peers_cnt++;
434
435 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
436 {
paul1eb8ef22005-04-07 07:30:20 +0000437 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000438 {
439 if (peer->as == as)
440 {
441 peer->local_as = bgp->as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000442 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000443 {
444 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
445 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
446 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
447 }
paul718e3742002-12-13 20:15:29 +0000448 else
449 BGP_EVENT_ADD (peer, BGP_Stop);
450 }
451 }
452 }
453 return 0;
454}
455
456/* Delete an AS from the confederation set. */
457int
458bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
459{
460 int i;
461 int j;
462 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000463 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000464
465 if (! bgp)
466 return -1;
467
468 if (! bgp_confederation_peers_check (bgp, as))
469 return -1;
470
471 for (i = 0; i < bgp->confed_peers_cnt; i++)
472 if (bgp->confed_peers[i] == as)
473 for(j = i + 1; j < bgp->confed_peers_cnt; j++)
474 bgp->confed_peers[j - 1] = bgp->confed_peers[j];
475
476 bgp->confed_peers_cnt--;
477
478 if (bgp->confed_peers_cnt == 0)
479 {
480 if (bgp->confed_peers)
481 XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
482 bgp->confed_peers = NULL;
483 }
484 else
485 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
486 bgp->confed_peers,
487 bgp->confed_peers_cnt * sizeof (as_t));
488
489 /* Now reset any peer who's remote AS has just been removed from the
490 CONFED */
491 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
492 {
paul1eb8ef22005-04-07 07:30:20 +0000493 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000494 {
495 if (peer->as == as)
496 {
497 peer->local_as = bgp->confed_id;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000498 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000499 {
500 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
501 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
502 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
503 }
paul718e3742002-12-13 20:15:29 +0000504 else
505 BGP_EVENT_ADD (peer, BGP_Stop);
506 }
507 }
508 }
509
510 return 0;
511}
David Lamparter6b0655a2014-06-04 06:53:35 +0200512
paul718e3742002-12-13 20:15:29 +0000513/* Local preference configuration. */
514int
515bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
516{
517 if (! bgp)
518 return -1;
519
paul718e3742002-12-13 20:15:29 +0000520 bgp->default_local_pref = local_pref;
521
522 return 0;
523}
524
525int
526bgp_default_local_preference_unset (struct bgp *bgp)
527{
528 if (! bgp)
529 return -1;
530
paul718e3742002-12-13 20:15:29 +0000531 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
532
533 return 0;
534}
David Lamparter6b0655a2014-06-04 06:53:35 +0200535
paulfee0f4c2004-09-13 05:12:46 +0000536/* If peer is RSERVER_CLIENT in at least one address family and is not member
537 of a peer_group for that family, return 1.
538 Used to check wether the peer is included in list bgp->rsclient. */
539int
540peer_rsclient_active (struct peer *peer)
541{
542 int i;
543 int j;
544
545 for (i=AFI_IP; i < AFI_MAX; i++)
546 for (j=SAFI_UNICAST; j < SAFI_MAX; j++)
547 if (CHECK_FLAG(peer->af_flags[i][j], PEER_FLAG_RSERVER_CLIENT)
548 && ! peer->af_group[i][j])
549 return 1;
550 return 0;
551}
552
pauleb821182004-05-01 08:44:08 +0000553/* Peer comparison function for sorting. */
paul718e3742002-12-13 20:15:29 +0000554static int
555peer_cmp (struct peer *p1, struct peer *p2)
556{
pauleb821182004-05-01 08:44:08 +0000557 return sockunion_cmp (&p1->su, &p2->su);
paul718e3742002-12-13 20:15:29 +0000558}
559
560int
561peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
562{
563 return CHECK_FLAG (peer->af_flags[afi][safi], flag);
564}
565
566/* Reset all address family specific configuration. */
567static void
568peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
569{
570 int i;
571 struct bgp_filter *filter;
572 char orf_name[BUFSIZ];
573
574 filter = &peer->filter[afi][safi];
575
576 /* Clear neighbor filter and route-map */
577 for (i = FILTER_IN; i < FILTER_MAX; i++)
578 {
579 if (filter->dlist[i].name)
580 {
581 free (filter->dlist[i].name);
582 filter->dlist[i].name = NULL;
583 }
584 if (filter->plist[i].name)
585 {
586 free (filter->plist[i].name);
587 filter->plist[i].name = NULL;
588 }
589 if (filter->aslist[i].name)
590 {
591 free (filter->aslist[i].name);
592 filter->aslist[i].name = NULL;
593 }
paulfee0f4c2004-09-13 05:12:46 +0000594 }
595 for (i = RMAP_IN; i < RMAP_MAX; i++)
596 {
paul718e3742002-12-13 20:15:29 +0000597 if (filter->map[i].name)
598 {
599 free (filter->map[i].name);
600 filter->map[i].name = NULL;
601 }
602 }
603
604 /* Clear unsuppress map. */
605 if (filter->usmap.name)
606 free (filter->usmap.name);
607 filter->usmap.name = NULL;
608 filter->usmap.map = NULL;
609
610 /* Clear neighbor's all address family flags. */
611 peer->af_flags[afi][safi] = 0;
612
613 /* Clear neighbor's all address family sflags. */
614 peer->af_sflags[afi][safi] = 0;
615
616 /* Clear neighbor's all address family capabilities. */
617 peer->af_cap[afi][safi] = 0;
618
619 /* Clear ORF info */
620 peer->orf_plist[afi][safi] = NULL;
621 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
David Lamparterc9c06d02015-04-13 10:21:35 +0200622 prefix_bgp_orf_remove_all (afi, orf_name);
paul718e3742002-12-13 20:15:29 +0000623
624 /* Set default neighbor send-community. */
625 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
626 {
627 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
628 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
629 }
630
631 /* Clear neighbor default_originate_rmap */
632 if (peer->default_rmap[afi][safi].name)
633 free (peer->default_rmap[afi][safi].name);
634 peer->default_rmap[afi][safi].name = NULL;
635 peer->default_rmap[afi][safi].map = NULL;
636
637 /* Clear neighbor maximum-prefix */
638 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +0000639 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000640}
641
642/* peer global config reset */
paul94f2b392005-06-28 12:44:16 +0000643static void
paul718e3742002-12-13 20:15:29 +0000644peer_global_config_reset (struct peer *peer)
645{
646 peer->weight = 0;
647 peer->change_local_as = 0;
648 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
649 if (peer->update_source)
650 {
651 sockunion_free (peer->update_source);
652 peer->update_source = NULL;
653 }
654 if (peer->update_if)
655 {
656 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
657 peer->update_if = NULL;
658 }
659
660 if (peer_sort (peer) == BGP_PEER_IBGP)
661 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
662 else
663 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
664
665 peer->flags = 0;
666 peer->config = 0;
667 peer->holdtime = 0;
668 peer->keepalive = 0;
669 peer->connect = 0;
670 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
671}
672
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000673/* Check peer's AS number and determines if this peer is IBGP or EBGP */
674static bgp_peer_sort_t
675peer_calc_sort (struct peer *peer)
paul718e3742002-12-13 20:15:29 +0000676{
677 struct bgp *bgp;
678
679 bgp = peer->bgp;
680
681 /* Peer-group */
682 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
683 {
684 if (peer->as)
685 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
686 else
687 {
688 struct peer *peer1;
689 peer1 = listnode_head (peer->group->peer);
690 if (peer1)
691 return (peer1->local_as == peer1->as
692 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
693 }
694 return BGP_PEER_INTERNAL;
695 }
696
697 /* Normal peer */
698 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
699 {
700 if (peer->local_as == 0)
701 return BGP_PEER_INTERNAL;
702
703 if (peer->local_as == peer->as)
704 {
705 if (peer->local_as == bgp->confed_id)
706 return BGP_PEER_EBGP;
707 else
708 return BGP_PEER_IBGP;
709 }
710
711 if (bgp_confederation_peers_check (bgp, peer->as))
712 return BGP_PEER_CONFED;
713
714 return BGP_PEER_EBGP;
715 }
716 else
717 {
718 return (peer->local_as == 0
719 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
720 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
721 }
722}
723
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000724/* Calculate and cache the peer "sort" */
725bgp_peer_sort_t
726peer_sort (struct peer *peer)
727{
728 peer->sort = peer_calc_sort (peer);
729 return peer->sort;
730}
731
Paul Jakmaf63f06d2011-04-08 12:44:43 +0100732static void
paul200df112005-06-01 11:17:05 +0000733peer_free (struct peer *peer)
734{
Paul Jakmaca058a32006-09-14 02:58:49 +0000735 assert (peer->status == Deleted);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700736
737 bgp_unlock(peer->bgp);
738
Paul Jakmaca058a32006-09-14 02:58:49 +0000739 /* this /ought/ to have been done already through bgp_stop earlier,
740 * but just to be sure..
741 */
742 bgp_timer_set (peer);
743 BGP_READ_OFF (peer->t_read);
744 BGP_WRITE_OFF (peer->t_write);
Paul Jakma9fde6622006-09-14 03:02:02 +0000745 BGP_EVENT_FLUSH (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +0000746
paul200df112005-06-01 11:17:05 +0000747 if (peer->desc)
Daniel Walton363c9032015-10-21 06:42:54 -0700748 {
749 XFREE (MTYPE_PEER_DESC, peer->desc);
750 peer->desc = NULL;
751 }
paul200df112005-06-01 11:17:05 +0000752
753 /* Free allocated host character. */
754 if (peer->host)
Daniel Walton363c9032015-10-21 06:42:54 -0700755 {
756 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
757 peer->host = NULL;
758 }
759
paul200df112005-06-01 11:17:05 +0000760 /* Update source configuration. */
761 if (peer->update_source)
Daniel Walton363c9032015-10-21 06:42:54 -0700762 {
763 sockunion_free (peer->update_source);
764 peer->update_source = NULL;
765 }
paul200df112005-06-01 11:17:05 +0000766
767 if (peer->update_if)
Daniel Walton363c9032015-10-21 06:42:54 -0700768 {
769 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
770 peer->update_if = NULL;
771 }
Paul Jakmaa625ca32006-03-30 14:12:38 +0000772
773 if (peer->clear_node_queue)
Daniel Walton363c9032015-10-21 06:42:54 -0700774 {
775 work_queue_free(peer->clear_node_queue);
776 peer->clear_node_queue = NULL;
777 }
Paul Jakmaa625ca32006-03-30 14:12:38 +0000778
Lou Berger056f3762013-04-10 12:30:04 -0700779 if (peer->notify.data)
780 XFREE(MTYPE_TMP, peer->notify.data);
781
Paul Jakmaca058a32006-09-14 02:58:49 +0000782 bgp_sync_delete (peer);
paul200df112005-06-01 11:17:05 +0000783 memset (peer, 0, sizeof (struct peer));
784
785 XFREE (MTYPE_BGP_PEER, peer);
786}
787
788/* increase reference count on a struct peer */
789struct peer *
Donald Sharp104576d2015-09-16 13:17:55 -0400790peer_lock_with_caller (const char *name, struct peer *peer)
paul200df112005-06-01 11:17:05 +0000791{
792 assert (peer && (peer->lock >= 0));
Donald Sharp104576d2015-09-16 13:17:55 -0400793
794#if 0
795 zlog_debug("%s peer_lock %p %d", name, peer, peer->lock);
796#endif
797
paul200df112005-06-01 11:17:05 +0000798 peer->lock++;
799
800 return peer;
801}
802
803/* decrease reference count on a struct peer
804 * struct peer is freed and NULL returned if last reference
805 */
806struct peer *
Donald Sharp104576d2015-09-16 13:17:55 -0400807peer_unlock_with_caller (const char *name, struct peer *peer)
paul200df112005-06-01 11:17:05 +0000808{
809 assert (peer && (peer->lock > 0));
Donald Sharp104576d2015-09-16 13:17:55 -0400810
811#if 0
812 zlog_debug("%s peer_unlock %p %d", name, peer, peer->lock);
813#endif
814
paul200df112005-06-01 11:17:05 +0000815 peer->lock--;
816
817 if (peer->lock == 0)
818 {
paul200df112005-06-01 11:17:05 +0000819 peer_free (peer);
820 return NULL;
821 }
822
paul200df112005-06-01 11:17:05 +0000823 return peer;
824}
825
826/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000827static struct peer *
Paul Jakma6f585442006-10-22 19:13:07 +0000828peer_new (struct bgp *bgp)
paul718e3742002-12-13 20:15:29 +0000829{
830 afi_t afi;
831 safi_t safi;
832 struct peer *peer;
833 struct servent *sp;
Paul Jakma6f585442006-10-22 19:13:07 +0000834
835 /* bgp argument is absolutely required */
836 assert (bgp);
837 if (!bgp)
838 return NULL;
839
paul718e3742002-12-13 20:15:29 +0000840 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000841 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000842
843 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000844 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000845 peer->v_start = BGP_INIT_START_TIMER;
846 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
paul718e3742002-12-13 20:15:29 +0000847 peer->status = Idle;
848 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000849 peer->weight = 0;
Paul Jakma0df7c912008-07-21 21:02:49 +0000850 peer->password = NULL;
Paul Jakma6f585442006-10-22 19:13:07 +0000851 peer->bgp = bgp;
Paul Jakmaca058a32006-09-14 02:58:49 +0000852 peer = peer_lock (peer); /* initial reference */
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700853 bgp_lock (bgp);
paul718e3742002-12-13 20:15:29 +0000854
855 /* Set default flags. */
856 for (afi = AFI_IP; afi < AFI_MAX; afi++)
857 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
858 {
859 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
860 {
861 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
862 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
863 }
864 peer->orf_plist[afi][safi] = NULL;
865 }
866 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
867
868 /* Create buffers. */
869 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
870 peer->obuf = stream_fifo_new ();
871 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000872 peer->scratch = stream_new (BGP_MAX_PACKET_SIZE);
paul718e3742002-12-13 20:15:29 +0000873
874 bgp_sync_init (peer);
875
876 /* Get service port number. */
877 sp = getservbyname ("bgp", "tcp");
878 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
879
880 return peer;
881}
882
883/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000884static struct peer *
paul718e3742002-12-13 20:15:29 +0000885peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
886 as_t remote_as, afi_t afi, safi_t safi)
887{
888 int active;
889 struct peer *peer;
890 char buf[SU_ADDRSTRLEN];
891
Paul Jakma6f585442006-10-22 19:13:07 +0000892 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000893 peer->su = *su;
894 peer->local_as = local_as;
895 peer->as = remote_as;
896 peer->local_id = bgp->router_id;
897 peer->v_holdtime = bgp->default_holdtime;
898 peer->v_keepalive = bgp->default_keepalive;
899 if (peer_sort (peer) == BGP_PEER_IBGP)
900 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
901 else
902 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000903
904 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000905 listnode_add_sort (bgp->peer, peer);
906
907 active = peer_active (peer);
908
909 if (afi && safi)
910 peer->afc[afi][safi] = 1;
911
Stephen Hemminger65957882010-01-15 16:22:10 +0300912 /* Last read and reset time set */
913 peer->readtime = peer->resettime = bgp_clock ();
paul848973c2003-08-13 00:32:49 +0000914
paul718e3742002-12-13 20:15:29 +0000915 /* Default TTL set. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000916 peer->ttl = (peer->sort == BGP_PEER_IBGP) ? 255 : 1;
paul718e3742002-12-13 20:15:29 +0000917
918 /* Make peer's address string. */
919 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000920 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000921
922 /* Set up peer's events and timers. */
923 if (! active && peer_active (peer))
924 bgp_timer_set (peer);
925
926 return peer;
927}
928
pauleb821182004-05-01 08:44:08 +0000929/* Make accept BGP peer. Called from bgp_accept (). */
930struct peer *
931peer_create_accept (struct bgp *bgp)
932{
933 struct peer *peer;
934
Paul Jakma6f585442006-10-22 19:13:07 +0000935 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000936
937 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000938 listnode_add_sort (bgp->peer, peer);
939
940 return peer;
941}
942
paul718e3742002-12-13 20:15:29 +0000943/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000944static void
paul718e3742002-12-13 20:15:29 +0000945peer_as_change (struct peer *peer, as_t as)
946{
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000947 bgp_peer_sort_t type;
Daniel Walton0d7435f2015-10-22 11:35:20 +0300948 struct peer *conf;
paul718e3742002-12-13 20:15:29 +0000949
950 /* Stop peer. */
951 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
952 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000953 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000954 {
955 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
956 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
957 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
958 }
paul718e3742002-12-13 20:15:29 +0000959 else
960 BGP_EVENT_ADD (peer, BGP_Stop);
961 }
962 type = peer_sort (peer);
963 peer->as = as;
964
paul848973c2003-08-13 00:32:49 +0000965 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
966 && ! bgp_confederation_peers_check (peer->bgp, as)
967 && peer->bgp->as != as)
968 peer->local_as = peer->bgp->confed_id;
969 else
970 peer->local_as = peer->bgp->as;
971
paul718e3742002-12-13 20:15:29 +0000972 /* Advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +0300973 conf = NULL;
974 if (peer->group)
975 conf = peer->group->conf;
976
977 if (conf && CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
978 peer->v_routeadv = conf->routeadv;
paul718e3742002-12-13 20:15:29 +0000979 else
Daniel Walton0d7435f2015-10-22 11:35:20 +0300980 if (peer_sort (peer) == BGP_PEER_IBGP)
981 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
982 else
983 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul718e3742002-12-13 20:15:29 +0000984
985 /* TTL reset */
986 if (peer_sort (peer) == BGP_PEER_IBGP)
987 peer->ttl = 255;
988 else if (type == BGP_PEER_IBGP)
989 peer->ttl = 1;
990
991 /* reflector-client reset */
992 if (peer_sort (peer) != BGP_PEER_IBGP)
993 {
994 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
995 PEER_FLAG_REFLECTOR_CLIENT);
996 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
997 PEER_FLAG_REFLECTOR_CLIENT);
998 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
999 PEER_FLAG_REFLECTOR_CLIENT);
Lou Berger298cc2f2016-01-12 13:42:02 -05001000 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_ENCAP],
1001 PEER_FLAG_REFLECTOR_CLIENT);
paul718e3742002-12-13 20:15:29 +00001002 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
1003 PEER_FLAG_REFLECTOR_CLIENT);
1004 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
1005 PEER_FLAG_REFLECTOR_CLIENT);
Lou Berger9da04bc2016-01-12 13:41:55 -05001006 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MPLS_VPN],
1007 PEER_FLAG_REFLECTOR_CLIENT);
Lou Berger298cc2f2016-01-12 13:42:02 -05001008 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_ENCAP],
1009 PEER_FLAG_REFLECTOR_CLIENT);
paul718e3742002-12-13 20:15:29 +00001010 }
1011
1012 /* local-as reset */
1013 if (peer_sort (peer) != BGP_PEER_EBGP)
1014 {
1015 peer->change_local_as = 0;
1016 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001017 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001018 }
1019}
1020
1021/* If peer does not exist, create new one. If peer already exists,
1022 set AS number to the peer. */
1023int
1024peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
1025 afi_t afi, safi_t safi)
1026{
1027 struct peer *peer;
1028 as_t local_as;
1029
1030 peer = peer_lookup (bgp, su);
1031
1032 if (peer)
1033 {
1034 /* When this peer is a member of peer-group. */
1035 if (peer->group)
1036 {
1037 if (peer->group->conf->as)
1038 {
1039 /* Return peer group's AS number. */
1040 *as = peer->group->conf->as;
1041 return BGP_ERR_PEER_GROUP_MEMBER;
1042 }
1043 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
1044 {
1045 if (bgp->as != *as)
1046 {
1047 *as = peer->as;
1048 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1049 }
1050 }
1051 else
1052 {
1053 if (bgp->as == *as)
1054 {
1055 *as = peer->as;
1056 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1057 }
1058 }
1059 }
1060
1061 /* Existing peer's AS number change. */
1062 if (peer->as != *as)
1063 peer_as_change (peer, *as);
1064 }
1065 else
1066 {
1067
1068 /* If the peer is not part of our confederation, and its not an
1069 iBGP peer then spoof the source AS */
1070 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1071 && ! bgp_confederation_peers_check (bgp, *as)
1072 && bgp->as != *as)
1073 local_as = bgp->confed_id;
1074 else
1075 local_as = bgp->as;
1076
1077 /* If this is IPv4 unicast configuration and "no bgp default
1078 ipv4-unicast" is specified. */
1079
1080 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1081 && afi == AFI_IP && safi == SAFI_UNICAST)
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001082 peer_create (su, bgp, local_as, *as, 0, 0);
paul718e3742002-12-13 20:15:29 +00001083 else
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001084 peer_create (su, bgp, local_as, *as, afi, safi);
paul718e3742002-12-13 20:15:29 +00001085 }
1086
1087 return 0;
1088}
1089
1090/* Activate the peer or peer group for specified AFI and SAFI. */
1091int
1092peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1093{
1094 int active;
1095
1096 if (peer->afc[afi][safi])
1097 return 0;
1098
1099 /* Activate the address family configuration. */
1100 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1101 peer->afc[afi][safi] = 1;
1102 else
1103 {
1104 active = peer_active (peer);
1105
1106 peer->afc[afi][safi] = 1;
1107
1108 if (! active && peer_active (peer))
1109 bgp_timer_set (peer);
1110 else
1111 {
1112 if (peer->status == Established)
1113 {
1114 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1115 {
1116 peer->afc_adv[afi][safi] = 1;
1117 bgp_capability_send (peer, afi, safi,
1118 CAPABILITY_CODE_MP,
1119 CAPABILITY_ACTION_SET);
1120 if (peer->afc_recv[afi][safi])
1121 {
1122 peer->afc_nego[afi][safi] = 1;
1123 bgp_announce_route (peer, afi, safi);
1124 }
1125 }
1126 else
hassoe0701b72004-05-20 09:19:34 +00001127 {
1128 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1129 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1130 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1131 }
paul718e3742002-12-13 20:15:29 +00001132 }
1133 }
1134 }
1135 return 0;
1136}
1137
1138int
1139peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1140{
1141 struct peer_group *group;
1142 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001143 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001144
1145 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1146 {
1147 group = peer->group;
1148
paul1eb8ef22005-04-07 07:30:20 +00001149 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001150 {
1151 if (peer1->af_group[afi][safi])
1152 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1153 }
1154 }
1155 else
1156 {
1157 if (peer->af_group[afi][safi])
1158 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1159 }
1160
1161 if (! peer->afc[afi][safi])
1162 return 0;
1163
1164 /* De-activate the address family configuration. */
1165 peer->afc[afi][safi] = 0;
1166 peer_af_flag_reset (peer, afi, safi);
1167
1168 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1169 {
1170 if (peer->status == Established)
1171 {
1172 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1173 {
1174 peer->afc_adv[afi][safi] = 0;
1175 peer->afc_nego[afi][safi] = 0;
1176
1177 if (peer_active_nego (peer))
1178 {
1179 bgp_capability_send (peer, afi, safi,
1180 CAPABILITY_CODE_MP,
1181 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001182 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001183 peer->pcount[afi][safi] = 0;
1184 }
1185 else
hassoe0701b72004-05-20 09:19:34 +00001186 {
1187 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1188 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1189 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1190 }
paul718e3742002-12-13 20:15:29 +00001191 }
1192 else
hassoe0701b72004-05-20 09:19:34 +00001193 {
1194 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1195 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1196 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1197 }
paul718e3742002-12-13 20:15:29 +00001198 }
1199 }
1200 return 0;
1201}
1202
David Lamparterdfb9bd72016-05-24 18:58:07 +02001203int
1204peer_afc_set (struct peer *peer, afi_t afi, safi_t safi, int enable)
1205{
1206 if (enable)
1207 return peer_activate (peer, afi, safi);
1208 else
1209 return peer_deactivate (peer, afi, safi);
1210}
1211
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001212static void
hasso93406d82005-02-02 14:40:33 +00001213peer_nsf_stop (struct peer *peer)
1214{
1215 afi_t afi;
1216 safi_t safi;
1217
1218 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1219 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1220
1221 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +04001222 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +00001223 peer->nsf[afi][safi] = 0;
1224
1225 if (peer->t_gr_restart)
1226 {
1227 BGP_TIMER_OFF (peer->t_gr_restart);
1228 if (BGP_DEBUG (events, EVENTS))
1229 zlog_debug ("%s graceful restart timer stopped", peer->host);
1230 }
1231 if (peer->t_gr_stale)
1232 {
1233 BGP_TIMER_OFF (peer->t_gr_stale);
1234 if (BGP_DEBUG (events, EVENTS))
1235 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1236 }
1237 bgp_clear_route_all (peer);
1238}
1239
Paul Jakmaca058a32006-09-14 02:58:49 +00001240/* Delete peer from confguration.
1241 *
1242 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1243 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1244 *
1245 * This function /should/ take care to be idempotent, to guard against
1246 * it being called multiple times through stray events that come in
1247 * that happen to result in this function being called again. That
1248 * said, getting here for a "Deleted" peer is a bug in the neighbour
1249 * FSM.
1250 */
paul718e3742002-12-13 20:15:29 +00001251int
1252peer_delete (struct peer *peer)
1253{
1254 int i;
1255 afi_t afi;
1256 safi_t safi;
1257 struct bgp *bgp;
1258 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001259 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001260
Paul Jakmaca058a32006-09-14 02:58:49 +00001261 assert (peer->status != Deleted);
1262
paul718e3742002-12-13 20:15:29 +00001263 bgp = peer->bgp;
1264
hasso93406d82005-02-02 14:40:33 +00001265 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1266 peer_nsf_stop (peer);
1267
Chris Caputo228da422009-07-18 05:44:03 +00001268 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001269 relationship. */
1270 if (peer->group)
1271 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001272 if ((pn = listnode_lookup (peer->group->peer, peer)))
1273 {
1274 peer = peer_unlock (peer); /* group->peer list reference */
1275 list_delete_node (peer->group->peer, pn);
1276 }
paul718e3742002-12-13 20:15:29 +00001277 peer->group = NULL;
1278 }
paul200df112005-06-01 11:17:05 +00001279
paul718e3742002-12-13 20:15:29 +00001280 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001281 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1282 * executed after peer structure is deleted.
1283 */
hassoe0701b72004-05-20 09:19:34 +00001284 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001285 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001286 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001287
1288 /* Password configuration */
1289 if (peer->password)
1290 {
1291 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1292 peer->password = NULL;
1293
1294 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1295 bgp_md5_set (peer);
1296 }
1297
Paul Jakmaca058a32006-09-14 02:58:49 +00001298 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001299
paul718e3742002-12-13 20:15:29 +00001300 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001301 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1302 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001303 {
Chris Caputo228da422009-07-18 05:44:03 +00001304 peer_unlock (peer); /* bgp peer list reference */
1305 list_delete_node (bgp->peer, pn);
1306 }
paul200df112005-06-01 11:17:05 +00001307
Chris Caputo228da422009-07-18 05:44:03 +00001308 if (peer_rsclient_active (peer)
1309 && (pn = listnode_lookup (bgp->rsclient, peer)))
1310 {
1311 peer_unlock (peer); /* rsclient list reference */
1312 list_delete_node (bgp->rsclient, pn);
1313
1314 /* Clear our own rsclient ribs. */
1315 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1316 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1317 if (CHECK_FLAG(peer->af_flags[afi][safi],
1318 PEER_FLAG_RSERVER_CLIENT))
1319 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001320 }
1321
1322 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1323 member of a peer_group. */
1324 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1325 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1326 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001327 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001328
paul200df112005-06-01 11:17:05 +00001329 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001330 if (peer->ibuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001331 {
1332 stream_free (peer->ibuf);
1333 peer->ibuf = NULL;
1334 }
1335
paul718e3742002-12-13 20:15:29 +00001336 if (peer->obuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001337 {
1338 stream_fifo_free (peer->obuf);
1339 peer->obuf = NULL;
1340 }
1341
paul718e3742002-12-13 20:15:29 +00001342 if (peer->work)
Daniel Walton363c9032015-10-21 06:42:54 -07001343 {
1344 stream_free (peer->work);
1345 peer->work = NULL;
1346 }
1347
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00001348 if (peer->scratch)
Daniel Walton363c9032015-10-21 06:42:54 -07001349 {
1350 stream_free(peer->scratch);
1351 peer->scratch = NULL;
1352 }
Paul Jakma18937402006-07-27 19:05:12 +00001353
paul718e3742002-12-13 20:15:29 +00001354 /* Local and remote addresses. */
1355 if (peer->su_local)
Daniel Walton363c9032015-10-21 06:42:54 -07001356 {
1357 sockunion_free (peer->su_local);
1358 peer->su_local = NULL;
1359 }
1360
paul718e3742002-12-13 20:15:29 +00001361 if (peer->su_remote)
Daniel Walton363c9032015-10-21 06:42:54 -07001362 {
1363 sockunion_free (peer->su_remote);
1364 peer->su_remote = NULL;
1365 }
paul200df112005-06-01 11:17:05 +00001366
paul718e3742002-12-13 20:15:29 +00001367 /* Free filter related memory. */
1368 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1369 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1370 {
1371 filter = &peer->filter[afi][safi];
1372
1373 for (i = FILTER_IN; i < FILTER_MAX; i++)
1374 {
1375 if (filter->dlist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001376 {
1377 free(filter->dlist[i].name);
1378 filter->dlist[i].name = NULL;
1379 }
1380
paul718e3742002-12-13 20:15:29 +00001381 if (filter->plist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001382 {
1383 free(filter->plist[i].name);
1384 filter->plist[i].name = NULL;
1385 }
1386
paul718e3742002-12-13 20:15:29 +00001387 if (filter->aslist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001388 {
1389 free(filter->aslist[i].name);
1390 filter->aslist[i].name = NULL;
1391 }
paul200df112005-06-01 11:17:05 +00001392 }
Daniel Walton363c9032015-10-21 06:42:54 -07001393
paul200df112005-06-01 11:17:05 +00001394 for (i = RMAP_IN; i < RMAP_MAX; i++)
1395 {
paul718e3742002-12-13 20:15:29 +00001396 if (filter->map[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001397 {
1398 free (filter->map[i].name);
1399 filter->map[i].name = NULL;
1400 }
paul718e3742002-12-13 20:15:29 +00001401 }
1402
1403 if (filter->usmap.name)
Daniel Walton363c9032015-10-21 06:42:54 -07001404 {
1405 free (filter->usmap.name);
1406 filter->usmap.name = NULL;
1407 }
paul718e3742002-12-13 20:15:29 +00001408
1409 if (peer->default_rmap[afi][safi].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001410 {
1411 free (peer->default_rmap[afi][safi].name);
1412 peer->default_rmap[afi][safi].name = NULL;
1413 }
paul718e3742002-12-13 20:15:29 +00001414 }
paul200df112005-06-01 11:17:05 +00001415
Lou Berger82dd7072016-01-12 13:41:57 -05001416 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETING))
1417 bgp_peer_clear_node_queue_drain_immediate(peer);
1418
paul200df112005-06-01 11:17:05 +00001419 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001420
1421 return 0;
1422}
David Lamparter6b0655a2014-06-04 06:53:35 +02001423
paul94f2b392005-06-28 12:44:16 +00001424static int
paul718e3742002-12-13 20:15:29 +00001425peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1426{
1427 return strcmp (g1->name, g2->name);
1428}
1429
1430/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001431static int
paul718e3742002-12-13 20:15:29 +00001432peer_group_active (struct peer *peer)
1433{
1434 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1435 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1436 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05001437 || peer->af_group[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00001438 || peer->af_group[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05001439 || peer->af_group[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05001440 || peer->af_group[AFI_IP6][SAFI_MPLS_VPN]
1441 || peer->af_group[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00001442 return 1;
1443 return 0;
1444}
1445
1446/* Peer group cofiguration. */
1447static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001448peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001449{
1450 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1451 sizeof (struct peer_group));
1452}
1453
paul94f2b392005-06-28 12:44:16 +00001454static void
paul718e3742002-12-13 20:15:29 +00001455peer_group_free (struct peer_group *group)
1456{
1457 XFREE (MTYPE_PEER_GROUP, group);
1458}
1459
1460struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001461peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001462{
1463 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001464 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001465
paul1eb8ef22005-04-07 07:30:20 +00001466 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001467 {
1468 if (strcmp (group->name, name) == 0)
1469 return group;
1470 }
1471 return NULL;
1472}
1473
1474struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001475peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001476{
1477 struct peer_group *group;
1478
1479 group = peer_group_lookup (bgp, name);
1480 if (group)
1481 return group;
1482
1483 group = peer_group_new ();
1484 group->bgp = bgp;
1485 group->name = strdup (name);
1486 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001487 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001488 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1489 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001490 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001491 group->conf->group = group;
1492 group->conf->as = 0;
1493 group->conf->ttl = 1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001494 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001495 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1496 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1497 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1498 group->conf->keepalive = 0;
1499 group->conf->holdtime = 0;
1500 group->conf->connect = 0;
1501 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1502 listnode_add_sort (bgp->group, group);
1503
1504 return 0;
1505}
1506
paul94f2b392005-06-28 12:44:16 +00001507static void
paul718e3742002-12-13 20:15:29 +00001508peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1509 afi_t afi, safi_t safi)
1510{
1511 int in = FILTER_IN;
1512 int out = FILTER_OUT;
1513 struct peer *conf;
1514 struct bgp_filter *pfilter;
1515 struct bgp_filter *gfilter;
1516
1517 conf = group->conf;
1518 pfilter = &peer->filter[afi][safi];
1519 gfilter = &conf->filter[afi][safi];
1520
1521 /* remote-as */
1522 if (conf->as)
1523 peer->as = conf->as;
1524
1525 /* remote-as */
1526 if (conf->change_local_as)
1527 peer->change_local_as = conf->change_local_as;
1528
1529 /* TTL */
1530 peer->ttl = conf->ttl;
1531
Nick Hilliardfa411a22011-03-23 15:33:17 +00001532 /* GTSM hops */
1533 peer->gtsm_hops = conf->gtsm_hops;
1534
paul718e3742002-12-13 20:15:29 +00001535 /* Weight */
1536 peer->weight = conf->weight;
1537
1538 /* peer flags apply */
1539 peer->flags = conf->flags;
1540 /* peer af_flags apply */
1541 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1542 /* peer config apply */
1543 peer->config = conf->config;
1544
1545 /* peer timers apply */
1546 peer->holdtime = conf->holdtime;
1547 peer->keepalive = conf->keepalive;
1548 peer->connect = conf->connect;
1549 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1550 peer->v_connect = conf->connect;
1551 else
1552 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1553
1554 /* advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +03001555 if (CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
1556 peer->v_routeadv = conf->routeadv;
paul718e3742002-12-13 20:15:29 +00001557 else
Daniel Walton0d7435f2015-10-22 11:35:20 +03001558 if (peer_sort (peer) == BGP_PEER_IBGP)
1559 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1560 else
1561 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul718e3742002-12-13 20:15:29 +00001562
Paul Jakma0df7c912008-07-21 21:02:49 +00001563 /* password apply */
Roman Hoog Antink0e4303d2013-01-18 13:52:03 +01001564 if (conf->password && !peer->password)
Paul Jakma0df7c912008-07-21 21:02:49 +00001565 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
Paul Jakma0df7c912008-07-21 21:02:49 +00001566
1567 bgp_md5_set (peer);
1568
paul718e3742002-12-13 20:15:29 +00001569 /* maximum-prefix */
1570 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001571 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001572 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001573
1574 /* allowas-in */
1575 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1576
paulfee0f4c2004-09-13 05:12:46 +00001577 /* route-server-client */
1578 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1579 {
1580 /* Make peer's RIB point to group's RIB. */
1581 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1582
1583 /* Import policy. */
1584 if (pfilter->map[RMAP_IMPORT].name)
1585 free (pfilter->map[RMAP_IMPORT].name);
1586 if (gfilter->map[RMAP_IMPORT].name)
1587 {
1588 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1589 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1590 }
1591 else
1592 {
1593 pfilter->map[RMAP_IMPORT].name = NULL;
1594 pfilter->map[RMAP_IMPORT].map = NULL;
1595 }
1596
1597 /* Export policy. */
1598 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1599 {
1600 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1601 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1602 }
1603 }
1604
paul718e3742002-12-13 20:15:29 +00001605 /* default-originate route-map */
1606 if (conf->default_rmap[afi][safi].name)
1607 {
1608 if (peer->default_rmap[afi][safi].name)
1609 free (peer->default_rmap[afi][safi].name);
1610 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1611 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1612 }
1613
1614 /* update-source apply */
1615 if (conf->update_source)
1616 {
1617 if (peer->update_source)
1618 sockunion_free (peer->update_source);
1619 if (peer->update_if)
1620 {
1621 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1622 peer->update_if = NULL;
1623 }
1624 peer->update_source = sockunion_dup (conf->update_source);
1625 }
1626 else if (conf->update_if)
1627 {
1628 if (peer->update_if)
1629 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1630 if (peer->update_source)
1631 {
1632 sockunion_free (peer->update_source);
1633 peer->update_source = NULL;
1634 }
1635 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1636 }
1637
1638 /* inbound filter apply */
1639 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1640 {
1641 if (pfilter->dlist[in].name)
1642 free (pfilter->dlist[in].name);
1643 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1644 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1645 }
1646 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1647 {
1648 if (pfilter->plist[in].name)
1649 free (pfilter->plist[in].name);
1650 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1651 pfilter->plist[in].plist = gfilter->plist[in].plist;
1652 }
1653 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1654 {
1655 if (pfilter->aslist[in].name)
1656 free (pfilter->aslist[in].name);
1657 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1658 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1659 }
paulfee0f4c2004-09-13 05:12:46 +00001660 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001661 {
paulfee0f4c2004-09-13 05:12:46 +00001662 if (pfilter->map[RMAP_IN].name)
1663 free (pfilter->map[RMAP_IN].name);
1664 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1665 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001666 }
1667
1668 /* outbound filter apply */
1669 if (gfilter->dlist[out].name)
1670 {
1671 if (pfilter->dlist[out].name)
1672 free (pfilter->dlist[out].name);
1673 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1674 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1675 }
1676 else
1677 {
1678 if (pfilter->dlist[out].name)
1679 free (pfilter->dlist[out].name);
1680 pfilter->dlist[out].name = NULL;
1681 pfilter->dlist[out].alist = NULL;
1682 }
1683 if (gfilter->plist[out].name)
1684 {
1685 if (pfilter->plist[out].name)
1686 free (pfilter->plist[out].name);
1687 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1688 pfilter->plist[out].plist = gfilter->plist[out].plist;
1689 }
1690 else
1691 {
1692 if (pfilter->plist[out].name)
1693 free (pfilter->plist[out].name);
1694 pfilter->plist[out].name = NULL;
1695 pfilter->plist[out].plist = NULL;
1696 }
1697 if (gfilter->aslist[out].name)
1698 {
1699 if (pfilter->aslist[out].name)
1700 free (pfilter->aslist[out].name);
1701 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1702 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1703 }
1704 else
1705 {
1706 if (pfilter->aslist[out].name)
1707 free (pfilter->aslist[out].name);
1708 pfilter->aslist[out].name = NULL;
1709 pfilter->aslist[out].aslist = NULL;
1710 }
paulfee0f4c2004-09-13 05:12:46 +00001711 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001712 {
paulfee0f4c2004-09-13 05:12:46 +00001713 if (pfilter->map[RMAP_OUT].name)
1714 free (pfilter->map[RMAP_OUT].name);
1715 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1716 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001717 }
1718 else
1719 {
paulfee0f4c2004-09-13 05:12:46 +00001720 if (pfilter->map[RMAP_OUT].name)
1721 free (pfilter->map[RMAP_OUT].name);
1722 pfilter->map[RMAP_OUT].name = NULL;
1723 pfilter->map[RMAP_OUT].map = NULL;
1724 }
1725
1726 /* RS-client's import/export route-maps. */
1727 if (gfilter->map[RMAP_IMPORT].name)
1728 {
1729 if (pfilter->map[RMAP_IMPORT].name)
1730 free (pfilter->map[RMAP_IMPORT].name);
1731 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1732 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1733 }
1734 else
1735 {
1736 if (pfilter->map[RMAP_IMPORT].name)
1737 free (pfilter->map[RMAP_IMPORT].name);
1738 pfilter->map[RMAP_IMPORT].name = NULL;
1739 pfilter->map[RMAP_IMPORT].map = NULL;
1740 }
1741 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1742 {
1743 if (pfilter->map[RMAP_EXPORT].name)
1744 free (pfilter->map[RMAP_EXPORT].name);
1745 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1746 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001747 }
1748
1749 if (gfilter->usmap.name)
1750 {
1751 if (pfilter->usmap.name)
1752 free (pfilter->usmap.name);
1753 pfilter->usmap.name = strdup (gfilter->usmap.name);
1754 pfilter->usmap.map = gfilter->usmap.map;
1755 }
1756 else
1757 {
1758 if (pfilter->usmap.name)
1759 free (pfilter->usmap.name);
1760 pfilter->usmap.name = NULL;
1761 pfilter->usmap.map = NULL;
1762 }
1763}
1764
1765/* Peer group's remote AS configuration. */
1766int
paulfd79ac92004-10-13 05:06:08 +00001767peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001768{
1769 struct peer_group *group;
1770 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001771 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001772
1773 group = peer_group_lookup (bgp, group_name);
1774 if (! group)
1775 return -1;
1776
1777 if (group->conf->as == *as)
1778 return 0;
1779
1780 /* When we setup peer-group AS number all peer group member's AS
1781 number must be updated to same number. */
1782 peer_as_change (group->conf, *as);
1783
paul1eb8ef22005-04-07 07:30:20 +00001784 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001785 {
1786 if (peer->as != *as)
1787 peer_as_change (peer, *as);
1788 }
1789
1790 return 0;
1791}
1792
1793int
1794peer_group_delete (struct peer_group *group)
1795{
1796 struct bgp *bgp;
1797 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001798 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001799
1800 bgp = group->bgp;
1801
paul1eb8ef22005-04-07 07:30:20 +00001802 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001803 {
paul718e3742002-12-13 20:15:29 +00001804 peer_delete (peer);
1805 }
1806 list_delete (group->peer);
1807
1808 free (group->name);
1809 group->name = NULL;
1810
1811 group->conf->group = NULL;
1812 peer_delete (group->conf);
1813
1814 /* Delete from all peer_group list. */
1815 listnode_delete (bgp->group, group);
1816
1817 peer_group_free (group);
1818
1819 return 0;
1820}
1821
1822int
1823peer_group_remote_as_delete (struct peer_group *group)
1824{
1825 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001826 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001827
1828 if (! group->conf->as)
1829 return 0;
1830
paul1eb8ef22005-04-07 07:30:20 +00001831 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001832 {
paul718e3742002-12-13 20:15:29 +00001833 peer_delete (peer);
1834 }
1835 list_delete_all_node (group->peer);
1836
1837 group->conf->as = 0;
1838
1839 return 0;
1840}
1841
1842/* Bind specified peer to peer group. */
1843int
1844peer_group_bind (struct bgp *bgp, union sockunion *su,
1845 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1846{
1847 struct peer *peer;
1848 int first_member = 0;
1849
1850 /* Check peer group's address family. */
1851 if (! group->conf->afc[afi][safi])
1852 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1853
1854 /* Lookup the peer. */
1855 peer = peer_lookup (bgp, su);
1856
1857 /* Create a new peer. */
1858 if (! peer)
1859 {
1860 if (! group->conf->as)
1861 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1862
1863 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1864 peer->group = group;
1865 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001866
Paul Jakmaca058a32006-09-14 02:58:49 +00001867 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001868 listnode_add (group->peer, peer);
1869 peer_group2peer_config_copy (group, peer, afi, safi);
1870
1871 return 0;
1872 }
1873
1874 /* When the peer already belongs to peer group, check the consistency. */
1875 if (peer->af_group[afi][safi])
1876 {
1877 if (strcmp (peer->group->name, group->name) != 0)
1878 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1879
1880 return 0;
1881 }
1882
1883 /* Check current peer group configuration. */
1884 if (peer_group_active (peer)
1885 && strcmp (peer->group->name, group->name) != 0)
1886 return BGP_ERR_PEER_GROUP_MISMATCH;
1887
1888 if (! group->conf->as)
1889 {
1890 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1891 && peer_sort (group->conf) != peer_sort (peer))
1892 {
1893 if (as)
1894 *as = peer->as;
1895 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1896 }
1897
1898 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1899 first_member = 1;
1900 }
1901
1902 peer->af_group[afi][safi] = 1;
1903 peer->afc[afi][safi] = 1;
1904 if (! peer->group)
1905 {
1906 peer->group = group;
paul200df112005-06-01 11:17:05 +00001907
Paul Jakmaca058a32006-09-14 02:58:49 +00001908 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001909 listnode_add (group->peer, peer);
1910 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001911 else
1912 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001913
1914 if (first_member)
1915 {
1916 /* Advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +03001917 if (! CHECK_FLAG (group->conf->config, PEER_CONFIG_ROUTEADV))
1918 {
1919 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1920 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1921 else
1922 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1923 }
paul718e3742002-12-13 20:15:29 +00001924
1925 /* ebgp-multihop reset */
1926 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1927 group->conf->ttl = 255;
1928
1929 /* local-as reset */
1930 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1931 {
1932 group->conf->change_local_as = 0;
1933 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001934 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001935 }
1936 }
paulfee0f4c2004-09-13 05:12:46 +00001937
1938 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1939 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001940 struct listnode *pn;
1941
paulfee0f4c2004-09-13 05:12:46 +00001942 /* If it's not configured as RSERVER_CLIENT in any other address
1943 family, without being member of a peer_group, remove it from
1944 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001945 if (! peer_rsclient_active (peer)
1946 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001947 {
1948 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001949 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001950
1951 /* Clear our own rsclient rib for this afi/safi. */
1952 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001953 }
paulfee0f4c2004-09-13 05:12:46 +00001954
Paul Jakmab608d5b2008-07-02 02:12:07 +00001955 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001956
1957 /* Import policy. */
1958 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1959 {
1960 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1961 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1962 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1963 }
1964
1965 /* Export policy. */
1966 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1967 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1968 {
1969 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1970 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1971 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1972 }
1973 }
1974
paul718e3742002-12-13 20:15:29 +00001975 peer_group2peer_config_copy (group, peer, afi, safi);
1976
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001977 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001978 {
1979 peer->last_reset = PEER_DOWN_RMAP_BIND;
1980 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1981 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1982 }
paul718e3742002-12-13 20:15:29 +00001983 else
1984 BGP_EVENT_ADD (peer, BGP_Stop);
1985
1986 return 0;
1987}
1988
1989int
1990peer_group_unbind (struct bgp *bgp, struct peer *peer,
1991 struct peer_group *group, afi_t afi, safi_t safi)
1992{
1993 if (! peer->af_group[afi][safi])
1994 return 0;
1995
1996 if (group != peer->group)
1997 return BGP_ERR_PEER_GROUP_MISMATCH;
1998
1999 peer->af_group[afi][safi] = 0;
2000 peer->afc[afi][safi] = 0;
2001 peer_af_flag_reset (peer, afi, safi);
2002
paulfee0f4c2004-09-13 05:12:46 +00002003 if (peer->rib[afi][safi])
2004 peer->rib[afi][safi] = NULL;
2005
paul718e3742002-12-13 20:15:29 +00002006 if (! peer_group_active (peer))
2007 {
Paul Jakmaca058a32006-09-14 02:58:49 +00002008 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00002009 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00002010 listnode_delete (group->peer, peer);
2011 peer->group = NULL;
2012 if (group->conf->as)
2013 {
2014 peer_delete (peer);
2015 return 0;
2016 }
2017 peer_global_config_reset (peer);
2018 }
2019
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002020 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002021 {
2022 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
2023 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2024 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2025 }
paul718e3742002-12-13 20:15:29 +00002026 else
2027 BGP_EVENT_ADD (peer, BGP_Stop);
2028
2029 return 0;
2030}
David Lamparter6b0655a2014-06-04 06:53:35 +02002031
Vipin Kumardd49eb12014-09-30 14:36:38 -07002032
2033static int
2034bgp_startup_timer_expire (struct thread *thread)
2035{
2036 struct bgp *bgp;
2037
2038 bgp = THREAD_ARG (thread);
2039 bgp->t_startup = NULL;
2040
2041 return 0;
2042}
2043
paul718e3742002-12-13 20:15:29 +00002044/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00002045static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002046bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002047{
2048 struct bgp *bgp;
2049 afi_t afi;
2050 safi_t safi;
2051
paul200df112005-06-01 11:17:05 +00002052 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
2053 return NULL;
2054
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002055 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00002056 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00002057 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00002058
2059 bgp->peer = list_new ();
2060 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
2061
2062 bgp->group = list_new ();
2063 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
2064
paulfee0f4c2004-09-13 05:12:46 +00002065 bgp->rsclient = list_new ();
2066 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
2067
paul718e3742002-12-13 20:15:29 +00002068 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2069 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2070 {
Paul Jakma64e580a2006-02-21 01:09:01 +00002071 bgp->route[afi][safi] = bgp_table_init (afi, safi);
2072 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
2073 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07002074 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
2075 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00002076 }
2077
2078 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
2079 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
2080 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00002081 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
2082 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07002083 bgp_flag_set (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES);
paul718e3742002-12-13 20:15:29 +00002084
2085 bgp->as = *as;
2086
2087 if (name)
2088 bgp->name = strdup (name);
2089
Donald Sharp774914f2015-10-14 08:50:39 -04002090 THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire,
Vipin Kumardd49eb12014-09-30 14:36:38 -07002091 bgp, bgp->restart_time);
2092
paul718e3742002-12-13 20:15:29 +00002093 return bgp;
2094}
2095
2096/* Return first entry of BGP. */
2097struct bgp *
paul94f2b392005-06-28 12:44:16 +00002098bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00002099{
Lou Berger056f3762013-04-10 12:30:04 -07002100 if (bm && bm->bgp && bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00002101 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00002102 return NULL;
2103}
2104
2105/* Lookup BGP entry. */
2106struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002107bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00002108{
2109 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002110 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002111
paul1eb8ef22005-04-07 07:30:20 +00002112 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002113 if (bgp->as == as
2114 && ((bgp->name == NULL && name == NULL)
2115 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
2116 return bgp;
2117 return NULL;
2118}
2119
2120/* Lookup BGP structure by view name. */
2121struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002122bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002123{
2124 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002125 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002126
paul1eb8ef22005-04-07 07:30:20 +00002127 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002128 if ((bgp->name == NULL && name == NULL)
2129 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2130 return bgp;
2131 return NULL;
2132}
2133
2134/* Called from VTY commands. */
2135int
paulfd79ac92004-10-13 05:06:08 +00002136bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002137{
2138 struct bgp *bgp;
2139
2140 /* Multiple instance check. */
2141 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2142 {
2143 if (name)
2144 bgp = bgp_lookup_by_name (name);
2145 else
2146 bgp = bgp_get_default ();
2147
2148 /* Already exists. */
2149 if (bgp)
2150 {
2151 if (bgp->as != *as)
2152 {
2153 *as = bgp->as;
2154 return BGP_ERR_INSTANCE_MISMATCH;
2155 }
2156 *bgp_val = bgp;
2157 return 0;
2158 }
2159 }
2160 else
2161 {
2162 /* BGP instance name can not be specified for single instance. */
2163 if (name)
2164 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2165
2166 /* Get default BGP structure if exists. */
2167 bgp = bgp_get_default ();
2168
2169 if (bgp)
2170 {
2171 if (bgp->as != *as)
2172 {
2173 *as = bgp->as;
2174 return BGP_ERR_AS_MISMATCH;
2175 }
2176 *bgp_val = bgp;
2177 return 0;
2178 }
2179 }
2180
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002181 bgp = bgp_create (as, name);
2182 bgp_router_id_set(bgp, &router_id_zebra);
2183 *bgp_val = bgp;
2184
Paul Jakmaad12dde2012-06-13 22:50:07 +01002185 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002186 if (list_isempty(bm->bgp)
2187 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002188 {
2189 if (bgp_socket (bm->port, bm->address) < 0)
2190 return BGP_ERR_INVALID_VALUE;
2191 }
2192
paul718e3742002-12-13 20:15:29 +00002193 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002194
2195 return 0;
2196}
2197
2198/* Delete BGP instance. */
2199int
2200bgp_delete (struct bgp *bgp)
2201{
2202 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002203 struct peer_group *group;
Denil Vira57cd5e72015-08-10 12:46:14 -07002204 struct listnode *node, *pnode;
2205 struct listnode *next, *pnext;
paul718e3742002-12-13 20:15:29 +00002206 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002207 int i;
2208
Lou Berger82dd7072016-01-12 13:41:57 -05002209 SET_FLAG(bgp->flags, BGP_FLAG_DELETING);
2210
David Lampartercffe7802014-12-07 03:27:13 +01002211 THREAD_OFF (bgp->t_startup);
2212
Daniel Walton9e518dd2015-05-19 17:47:26 -07002213 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2214 {
2215 if (peer->status == Established ||
2216 peer->status == OpenSent ||
2217 peer->status == OpenConfirm)
2218 {
2219 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2220 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
2221 }
2222 }
2223
paul718e3742002-12-13 20:15:29 +00002224 /* Delete static route. */
2225 bgp_static_delete (bgp);
2226
2227 /* Unset redistribution. */
2228 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2229 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2230 if (i != ZEBRA_ROUTE_BGP)
2231 bgp_redistribute_unset (bgp, afi, i);
2232
paul1eb8ef22005-04-07 07:30:20 +00002233 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002234 {
2235 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2236 {
2237 /* Send notify to remote peer. */
2238 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2239 }
2240
2241 peer_delete (peer);
2242 }
paul718e3742002-12-13 20:15:29 +00002243
Chris Caputo228da422009-07-18 05:44:03 +00002244 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002245 {
Denil Vira57cd5e72015-08-10 12:46:14 -07002246 for (ALL_LIST_ELEMENTS (group->peer, pnode, pnext, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002247 {
2248 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2249 {
2250 /* Send notify to remote peer. */
2251 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2252 }
2253 }
2254 peer_group_delete (group);
2255 }
Chris Caputo228da422009-07-18 05:44:03 +00002256
2257 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002258
2259 if (bgp->peer_self) {
2260 peer_delete(bgp->peer_self);
2261 bgp->peer_self = NULL;
2262 }
Lou Berger82dd7072016-01-12 13:41:57 -05002263
2264 /*
2265 * Free pending deleted routes. Unfortunately, it also has to process
2266 * all the pending activity for other instances of struct bgp.
2267 *
2268 * This call was added to achieve clean memory allocation at exit,
2269 * for the sake of valgrind.
2270 */
2271 bgp_process_queues_drain_immediate();
2272
Paul Jakmafd35b942009-07-16 19:27:32 +01002273 /* Remove visibility via the master list - there may however still be
2274 * routes to be processed still referencing the struct bgp.
2275 */
2276 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002277 if (list_isempty(bm->bgp))
2278 bgp_close ();
2279
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002280 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002281
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002282 return 0;
2283}
2284
2285static void bgp_free (struct bgp *);
2286
2287void
2288bgp_lock (struct bgp *bgp)
2289{
2290 ++bgp->lock;
2291}
2292
2293void
2294bgp_unlock(struct bgp *bgp)
2295{
Chris Caputo228da422009-07-18 05:44:03 +00002296 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002297 if (--bgp->lock == 0)
2298 bgp_free (bgp);
2299}
2300
2301static void
2302bgp_free (struct bgp *bgp)
2303{
2304 afi_t afi;
2305 safi_t safi;
2306
2307 list_delete (bgp->group);
2308 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002309 list_delete (bgp->rsclient);
2310
paul718e3742002-12-13 20:15:29 +00002311 if (bgp->name)
2312 free (bgp->name);
2313
2314 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2315 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2316 {
2317 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002318 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002319 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002320 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002321 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002322 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002323 }
2324 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002325}
David Lamparter6b0655a2014-06-04 06:53:35 +02002326
paul718e3742002-12-13 20:15:29 +00002327struct peer *
2328peer_lookup (struct bgp *bgp, union sockunion *su)
2329{
2330 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002331 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002332
Steve Hillfc4dc592009-07-28 17:54:35 +01002333 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002334 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002335 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2336 if (sockunion_same (&peer->su, su)
2337 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2338 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002339 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002340 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002341 {
2342 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002343
Paul Jakma2158ad22009-07-28 18:10:55 +01002344 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2345 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2346 if (sockunion_same (&peer->su, su)
2347 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2348 return peer;
paul718e3742002-12-13 20:15:29 +00002349 }
2350 return NULL;
2351}
2352
2353struct peer *
2354peer_lookup_with_open (union sockunion *su, as_t remote_as,
2355 struct in_addr *remote_id, int *as)
2356{
2357 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002358 struct listnode *node;
2359 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002360 struct bgp *bgp;
2361
Steve Hillfc4dc592009-07-28 17:54:35 +01002362 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002363 return NULL;
2364
Paul Jakma9d878772009-08-05 16:25:16 +01002365 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002366 {
Paul Jakma9d878772009-08-05 16:25:16 +01002367 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2368 {
2369 if (sockunion_same (&peer->su, su)
2370 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2371 {
2372 if (peer->as == remote_as
2373 && peer->remote_id.s_addr == remote_id->s_addr)
2374 return peer;
2375 if (peer->as == remote_as)
2376 *as = 1;
2377 }
2378 }
2379
2380 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2381 {
2382 if (sockunion_same (&peer->su, su)
2383 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2384 {
2385 if (peer->as == remote_as
2386 && peer->remote_id.s_addr == 0)
2387 return peer;
2388 if (peer->as == remote_as)
2389 *as = 1;
2390 }
2391 }
paul718e3742002-12-13 20:15:29 +00002392 }
2393 return NULL;
2394}
David Lamparter6b0655a2014-06-04 06:53:35 +02002395
paul718e3742002-12-13 20:15:29 +00002396/* If peer is configured at least one address family return 1. */
2397int
2398peer_active (struct peer *peer)
2399{
2400 if (peer->afc[AFI_IP][SAFI_UNICAST]
2401 || peer->afc[AFI_IP][SAFI_MULTICAST]
2402 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05002403 || peer->afc[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00002404 || peer->afc[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05002405 || peer->afc[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05002406 || peer->afc[AFI_IP6][SAFI_MPLS_VPN]
2407 || peer->afc[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00002408 return 1;
2409 return 0;
2410}
2411
2412/* If peer is negotiated at least one address family return 1. */
2413int
2414peer_active_nego (struct peer *peer)
2415{
2416 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2417 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2418 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05002419 || peer->afc_nego[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00002420 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05002421 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05002422 || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
2423 || peer->afc_nego[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00002424 return 1;
2425 return 0;
2426}
David Lamparter6b0655a2014-06-04 06:53:35 +02002427
paul718e3742002-12-13 20:15:29 +00002428/* peer_flag_change_type. */
2429enum peer_change_type
2430{
2431 peer_change_none,
2432 peer_change_reset,
2433 peer_change_reset_in,
2434 peer_change_reset_out,
2435};
2436
paul94f2b392005-06-28 12:44:16 +00002437static void
paul718e3742002-12-13 20:15:29 +00002438peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2439 enum peer_change_type type)
2440{
2441 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2442 return;
2443
Stephen Hemmingerd9d4ae52010-01-13 00:32:39 +00002444 if (peer->status != Established)
2445 return;
2446
paul718e3742002-12-13 20:15:29 +00002447 if (type == peer_change_reset)
2448 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2449 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2450 else if (type == peer_change_reset_in)
2451 {
2452 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2453 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2454 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2455 else
2456 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2457 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2458 }
2459 else if (type == peer_change_reset_out)
2460 bgp_announce_route (peer, afi, safi);
2461}
2462
2463struct peer_flag_action
2464{
2465 /* Peer's flag. */
2466 u_int32_t flag;
2467
2468 /* This flag can be set for peer-group member. */
2469 u_char not_for_member;
2470
2471 /* Action when the flag is changed. */
2472 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002473
2474 /* Peer down cause */
2475 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002476};
2477
Stephen Hemminger03621952009-07-21 16:27:20 -07002478static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002479 {
2480 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2481 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2482 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2483 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2484 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002485 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002486 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002487 { 0, 0, 0 }
2488 };
2489
Stephen Hemminger03621952009-07-21 16:27:20 -07002490static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002491 {
2492 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2493 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2494 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2495 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2496 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2497 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2498 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2499 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2500 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2501 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2502 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2503 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2504 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002505 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
Timo Teräs9e7a53c2014-04-24 10:22:37 +03002506 { PEER_FLAG_NEXTHOP_SELF_ALL, 1, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002507 { 0, 0, 0 }
2508 };
2509
2510/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002511static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002512peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002513 struct peer_flag_action *action, u_int32_t flag)
2514{
2515 int i;
2516 int found = 0;
2517 int reset_in = 0;
2518 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002519 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002520
2521 /* Check peer's frag action. */
2522 for (i = 0; i < size; i++)
2523 {
2524 match = &action_list[i];
2525
2526 if (match->flag == 0)
2527 break;
2528
2529 if (match->flag & flag)
2530 {
2531 found = 1;
2532
2533 if (match->type == peer_change_reset_in)
2534 reset_in = 1;
2535 if (match->type == peer_change_reset_out)
2536 reset_out = 1;
2537 if (match->type == peer_change_reset)
2538 {
2539 reset_in = 1;
2540 reset_out = 1;
2541 }
2542 if (match->not_for_member)
2543 action->not_for_member = 1;
2544 }
2545 }
2546
2547 /* Set peer clear type. */
2548 if (reset_in && reset_out)
2549 action->type = peer_change_reset;
2550 else if (reset_in)
2551 action->type = peer_change_reset_in;
2552 else if (reset_out)
2553 action->type = peer_change_reset_out;
2554 else
2555 action->type = peer_change_none;
2556
2557 return found;
2558}
2559
paul94f2b392005-06-28 12:44:16 +00002560static void
paul718e3742002-12-13 20:15:29 +00002561peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2562{
2563 if (flag == PEER_FLAG_SHUTDOWN)
2564 {
2565 if (CHECK_FLAG (peer->flags, flag))
2566 {
hasso93406d82005-02-02 14:40:33 +00002567 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2568 peer_nsf_stop (peer);
2569
hasso0a486e52005-02-01 20:57:17 +00002570 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2571 if (peer->t_pmax_restart)
2572 {
2573 BGP_TIMER_OFF (peer->t_pmax_restart);
2574 if (BGP_DEBUG (events, EVENTS))
2575 zlog_debug ("%s Maximum-prefix restart timer canceled",
2576 peer->host);
2577 }
2578
hasso93406d82005-02-02 14:40:33 +00002579 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2580 peer_nsf_stop (peer);
2581
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002582 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002583 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2584 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2585 else
2586 BGP_EVENT_ADD (peer, BGP_Stop);
2587 }
2588 else
2589 {
2590 peer->v_start = BGP_INIT_START_TIMER;
2591 BGP_EVENT_ADD (peer, BGP_Stop);
2592 }
2593 }
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002594 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002595 {
hassoc9502432005-02-01 22:01:48 +00002596 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2597 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2598 else if (flag == PEER_FLAG_PASSIVE)
2599 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002600 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002601 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002602
hassoc9502432005-02-01 22:01:48 +00002603 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2604 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002605 }
2606 else
2607 BGP_EVENT_ADD (peer, BGP_Stop);
2608}
2609
2610/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002611static int
paul718e3742002-12-13 20:15:29 +00002612peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2613{
2614 int found;
2615 int size;
2616 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002617 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002618 struct peer_flag_action action;
2619
2620 memset (&action, 0, sizeof (struct peer_flag_action));
2621 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2622
2623 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2624
2625 /* No flag action is found. */
2626 if (! found)
2627 return BGP_ERR_INVALID_FLAG;
2628
2629 /* Not for peer-group member. */
2630 if (action.not_for_member && peer_group_active (peer))
2631 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2632
2633 /* When unset the peer-group member's flag we have to check
2634 peer-group configuration. */
2635 if (! set && peer_group_active (peer))
2636 if (CHECK_FLAG (peer->group->conf->flags, flag))
2637 {
2638 if (flag == PEER_FLAG_SHUTDOWN)
2639 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2640 else
2641 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2642 }
2643
2644 /* Flag conflict check. */
2645 if (set
2646 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2647 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2648 return BGP_ERR_PEER_FLAG_CONFLICT;
2649
2650 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2651 {
2652 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2653 return 0;
2654 if (! set && ! CHECK_FLAG (peer->flags, flag))
2655 return 0;
2656 }
2657
2658 if (set)
2659 SET_FLAG (peer->flags, flag);
2660 else
2661 UNSET_FLAG (peer->flags, flag);
2662
2663 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2664 {
2665 if (action.type == peer_change_reset)
2666 peer_flag_modify_action (peer, flag);
2667
2668 return 0;
2669 }
2670
2671 /* peer-group member updates. */
2672 group = peer->group;
2673
paul1eb8ef22005-04-07 07:30:20 +00002674 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002675 {
2676 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2677 continue;
2678
2679 if (! set && ! CHECK_FLAG (peer->flags, flag))
2680 continue;
2681
2682 if (set)
2683 SET_FLAG (peer->flags, flag);
2684 else
2685 UNSET_FLAG (peer->flags, flag);
2686
2687 if (action.type == peer_change_reset)
2688 peer_flag_modify_action (peer, flag);
2689 }
2690 return 0;
2691}
2692
2693int
2694peer_flag_set (struct peer *peer, u_int32_t flag)
2695{
2696 return peer_flag_modify (peer, flag, 1);
2697}
2698
2699int
2700peer_flag_unset (struct peer *peer, u_int32_t flag)
2701{
2702 return peer_flag_modify (peer, flag, 0);
2703}
2704
paul94f2b392005-06-28 12:44:16 +00002705static int
paul718e3742002-12-13 20:15:29 +00002706peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2707{
2708 if (peer->af_group[afi][safi])
2709 return 1;
2710 return 0;
2711}
2712
paul94f2b392005-06-28 12:44:16 +00002713static int
paul718e3742002-12-13 20:15:29 +00002714peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2715 int set)
2716{
2717 int found;
2718 int size;
paul1eb8ef22005-04-07 07:30:20 +00002719 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002720 struct peer_group *group;
2721 struct peer_flag_action action;
2722
2723 memset (&action, 0, sizeof (struct peer_flag_action));
2724 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2725
2726 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2727
2728 /* No flag action is found. */
2729 if (! found)
2730 return BGP_ERR_INVALID_FLAG;
2731
2732 /* Adress family must be activated. */
2733 if (! peer->afc[afi][safi])
2734 return BGP_ERR_PEER_INACTIVE;
2735
2736 /* Not for peer-group member. */
2737 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2738 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2739
2740 /* Spcecial check for reflector client. */
2741 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2742 && peer_sort (peer) != BGP_PEER_IBGP)
2743 return BGP_ERR_NOT_INTERNAL_PEER;
2744
2745 /* Spcecial check for remove-private-AS. */
2746 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2747 && peer_sort (peer) == BGP_PEER_IBGP)
2748 return BGP_ERR_REMOVE_PRIVATE_AS;
2749
2750 /* When unset the peer-group member's flag we have to check
2751 peer-group configuration. */
2752 if (! set && peer->af_group[afi][safi])
2753 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2754 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2755
2756 /* When current flag configuration is same as requested one. */
2757 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2758 {
2759 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2760 return 0;
2761 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2762 return 0;
2763 }
2764
2765 if (set)
2766 SET_FLAG (peer->af_flags[afi][safi], flag);
2767 else
2768 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2769
2770 /* Execute action when peer is established. */
2771 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2772 && peer->status == Established)
2773 {
2774 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2775 bgp_clear_adj_in (peer, afi, safi);
2776 else
hassoe0701b72004-05-20 09:19:34 +00002777 {
2778 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2779 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2780 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2781 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2782 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2783 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2784 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2785 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2786
2787 peer_change_action (peer, afi, safi, action.type);
2788 }
2789
paul718e3742002-12-13 20:15:29 +00002790 }
2791
2792 /* Peer group member updates. */
2793 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2794 {
2795 group = peer->group;
2796
paul1eb8ef22005-04-07 07:30:20 +00002797 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002798 {
2799 if (! peer->af_group[afi][safi])
2800 continue;
2801
2802 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2803 continue;
2804
2805 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2806 continue;
2807
2808 if (set)
2809 SET_FLAG (peer->af_flags[afi][safi], flag);
2810 else
2811 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2812
2813 if (peer->status == Established)
2814 {
2815 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2816 bgp_clear_adj_in (peer, afi, safi);
2817 else
hassoe0701b72004-05-20 09:19:34 +00002818 {
2819 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2820 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2821 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2822 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2823 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2824 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2825 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2826 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2827
2828 peer_change_action (peer, afi, safi, action.type);
2829 }
paul718e3742002-12-13 20:15:29 +00002830 }
2831 }
2832 }
2833 return 0;
2834}
2835
2836int
2837peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2838{
2839 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2840}
2841
2842int
2843peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2844{
2845 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2846}
David Lamparter6b0655a2014-06-04 06:53:35 +02002847
paul718e3742002-12-13 20:15:29 +00002848/* EBGP multihop configuration. */
2849int
2850peer_ebgp_multihop_set (struct peer *peer, int ttl)
2851{
2852 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002853 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002854 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002855
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002856 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002857 return 0;
2858
Nick Hilliardfa411a22011-03-23 15:33:17 +00002859 /* see comment in peer_ttl_security_hops_set() */
2860 if (ttl != MAXTTL)
2861 {
2862 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2863 {
2864 group = peer->group;
2865 if (group->conf->gtsm_hops != 0)
2866 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2867
2868 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2869 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002870 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002871 continue;
2872
2873 if (peer1->gtsm_hops != 0)
2874 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2875 }
2876 }
2877 else
2878 {
2879 if (peer->gtsm_hops != 0)
2880 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2881 }
2882 }
2883
paul718e3742002-12-13 20:15:29 +00002884 peer->ttl = ttl;
2885
2886 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2887 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002888 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002889 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002890 }
2891 else
2892 {
2893 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002894 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002895 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002896 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002897 continue;
paul718e3742002-12-13 20:15:29 +00002898
pauleb821182004-05-01 08:44:08 +00002899 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002900
pauleb821182004-05-01 08:44:08 +00002901 if (peer->fd >= 0)
2902 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2903 }
paul718e3742002-12-13 20:15:29 +00002904 }
2905 return 0;
2906}
2907
2908int
2909peer_ebgp_multihop_unset (struct peer *peer)
2910{
2911 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002912 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002913
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002914 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002915 return 0;
2916
Nick Hilliardfa411a22011-03-23 15:33:17 +00002917 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2918 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2919
paul718e3742002-12-13 20:15:29 +00002920 if (peer_group_active (peer))
2921 peer->ttl = peer->group->conf->ttl;
2922 else
2923 peer->ttl = 1;
2924
2925 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2926 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002927 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002928 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002929 }
2930 else
2931 {
2932 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002933 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002934 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002935 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002936 continue;
paul718e3742002-12-13 20:15:29 +00002937
pauleb821182004-05-01 08:44:08 +00002938 peer->ttl = 1;
2939
2940 if (peer->fd >= 0)
2941 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2942 }
paul718e3742002-12-13 20:15:29 +00002943 }
2944 return 0;
2945}
David Lamparter6b0655a2014-06-04 06:53:35 +02002946
paul718e3742002-12-13 20:15:29 +00002947/* Neighbor description. */
2948int
David Lamparterdfb9bd72016-05-24 18:58:07 +02002949peer_description_set (struct peer *peer, const char *desc)
paul718e3742002-12-13 20:15:29 +00002950{
2951 if (peer->desc)
2952 XFREE (MTYPE_PEER_DESC, peer->desc);
2953
2954 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2955
2956 return 0;
2957}
2958
2959int
2960peer_description_unset (struct peer *peer)
2961{
2962 if (peer->desc)
2963 XFREE (MTYPE_PEER_DESC, peer->desc);
2964
2965 peer->desc = NULL;
2966
2967 return 0;
2968}
David Lamparter6b0655a2014-06-04 06:53:35 +02002969
paul718e3742002-12-13 20:15:29 +00002970/* Neighbor update-source. */
2971int
paulfd79ac92004-10-13 05:06:08 +00002972peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002973{
2974 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002975 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002976
2977 if (peer->update_if)
2978 {
2979 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2980 && strcmp (peer->update_if, ifname) == 0)
2981 return 0;
2982
2983 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2984 peer->update_if = NULL;
2985 }
2986
2987 if (peer->update_source)
2988 {
2989 sockunion_free (peer->update_source);
2990 peer->update_source = NULL;
2991 }
2992
2993 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2994
2995 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
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 return 0;
3006 }
3007
3008 /* peer-group member updates. */
3009 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003010 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003011 {
3012 if (peer->update_if)
3013 {
3014 if (strcmp (peer->update_if, ifname) == 0)
3015 continue;
3016
3017 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3018 peer->update_if = NULL;
3019 }
3020
3021 if (peer->update_source)
3022 {
3023 sockunion_free (peer->update_source);
3024 peer->update_source = NULL;
3025 }
3026
3027 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
3028
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003029 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003030 {
3031 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3032 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3033 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3034 }
paul718e3742002-12-13 20:15:29 +00003035 else
3036 BGP_EVENT_ADD (peer, BGP_Stop);
3037 }
3038 return 0;
3039}
3040
3041int
David Lamparterdfb9bd72016-05-24 18:58:07 +02003042peer_update_source_addr_set (struct peer *peer, const union sockunion *su)
paul718e3742002-12-13 20:15:29 +00003043{
3044 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003045 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003046
3047 if (peer->update_source)
3048 {
3049 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3050 && sockunion_cmp (peer->update_source, su) == 0)
3051 return 0;
3052 sockunion_free (peer->update_source);
3053 peer->update_source = NULL;
3054 }
3055
3056 if (peer->update_if)
3057 {
3058 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3059 peer->update_if = NULL;
3060 }
3061
3062 peer->update_source = sockunion_dup (su);
3063
3064 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3065 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003066 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003067 {
3068 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3069 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3070 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3071 }
paul718e3742002-12-13 20:15:29 +00003072 else
3073 BGP_EVENT_ADD (peer, BGP_Stop);
3074 return 0;
3075 }
3076
3077 /* peer-group member updates. */
3078 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003079 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003080 {
3081 if (peer->update_source)
3082 {
3083 if (sockunion_cmp (peer->update_source, su) == 0)
3084 continue;
3085 sockunion_free (peer->update_source);
3086 peer->update_source = NULL;
3087 }
3088
3089 if (peer->update_if)
3090 {
3091 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3092 peer->update_if = NULL;
3093 }
3094
3095 peer->update_source = sockunion_dup (su);
3096
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003097 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003098 {
3099 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3100 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3101 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3102 }
paul718e3742002-12-13 20:15:29 +00003103 else
3104 BGP_EVENT_ADD (peer, BGP_Stop);
3105 }
3106 return 0;
3107}
3108
3109int
3110peer_update_source_unset (struct peer *peer)
3111{
3112 union sockunion *su;
3113 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003114 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003115
3116 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3117 && ! peer->update_source
3118 && ! peer->update_if)
3119 return 0;
3120
3121 if (peer->update_source)
3122 {
3123 sockunion_free (peer->update_source);
3124 peer->update_source = NULL;
3125 }
3126 if (peer->update_if)
3127 {
3128 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3129 peer->update_if = NULL;
3130 }
3131
3132 if (peer_group_active (peer))
3133 {
3134 group = peer->group;
3135
3136 if (group->conf->update_source)
3137 {
3138 su = sockunion_dup (group->conf->update_source);
3139 peer->update_source = su;
3140 }
3141 else if (group->conf->update_if)
3142 peer->update_if =
3143 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
3144 }
3145
3146 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3147 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003148 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003149 {
3150 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3151 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3152 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3153 }
paul718e3742002-12-13 20:15:29 +00003154 else
3155 BGP_EVENT_ADD (peer, BGP_Stop);
3156 return 0;
3157 }
3158
3159 /* peer-group member updates. */
3160 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003161 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003162 {
3163 if (! peer->update_source && ! peer->update_if)
3164 continue;
3165
3166 if (peer->update_source)
3167 {
3168 sockunion_free (peer->update_source);
3169 peer->update_source = NULL;
3170 }
3171
3172 if (peer->update_if)
3173 {
3174 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3175 peer->update_if = NULL;
3176 }
3177
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003178 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003179 {
3180 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3181 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3182 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3183 }
paul718e3742002-12-13 20:15:29 +00003184 else
3185 BGP_EVENT_ADD (peer, BGP_Stop);
3186 }
3187 return 0;
3188}
David Lamparter6b0655a2014-06-04 06:53:35 +02003189
paul718e3742002-12-13 20:15:29 +00003190int
3191peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003192 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003193{
3194 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003195 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003196
3197 /* Adress family must be activated. */
3198 if (! peer->afc[afi][safi])
3199 return BGP_ERR_PEER_INACTIVE;
3200
3201 /* Default originate can't be used for peer group memeber. */
3202 if (peer_is_group_member (peer, afi, safi))
3203 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3204
3205 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3206 || (rmap && ! peer->default_rmap[afi][safi].name)
3207 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3208 {
3209 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3210
3211 if (rmap)
3212 {
3213 if (peer->default_rmap[afi][safi].name)
3214 free (peer->default_rmap[afi][safi].name);
3215 peer->default_rmap[afi][safi].name = strdup (rmap);
3216 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3217 }
3218 }
3219
3220 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3221 {
3222 if (peer->status == Established && peer->afc_nego[afi][safi])
3223 bgp_default_originate (peer, afi, safi, 0);
3224 return 0;
3225 }
3226
3227 /* peer-group member updates. */
3228 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003229 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003230 {
3231 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3232
3233 if (rmap)
3234 {
3235 if (peer->default_rmap[afi][safi].name)
3236 free (peer->default_rmap[afi][safi].name);
3237 peer->default_rmap[afi][safi].name = strdup (rmap);
3238 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3239 }
3240
3241 if (peer->status == Established && peer->afc_nego[afi][safi])
3242 bgp_default_originate (peer, afi, safi, 0);
3243 }
3244 return 0;
3245}
3246
3247int
3248peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3249{
3250 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003251 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003252
3253 /* Adress family must be activated. */
3254 if (! peer->afc[afi][safi])
3255 return BGP_ERR_PEER_INACTIVE;
3256
3257 /* Default originate can't be used for peer group memeber. */
3258 if (peer_is_group_member (peer, afi, safi))
3259 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3260
3261 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3262 {
3263 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3264
3265 if (peer->default_rmap[afi][safi].name)
3266 free (peer->default_rmap[afi][safi].name);
3267 peer->default_rmap[afi][safi].name = NULL;
3268 peer->default_rmap[afi][safi].map = NULL;
3269 }
3270
3271 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3272 {
3273 if (peer->status == Established && peer->afc_nego[afi][safi])
3274 bgp_default_originate (peer, afi, safi, 1);
3275 return 0;
3276 }
3277
3278 /* peer-group member updates. */
3279 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003280 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003281 {
3282 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3283
3284 if (peer->default_rmap[afi][safi].name)
3285 free (peer->default_rmap[afi][safi].name);
3286 peer->default_rmap[afi][safi].name = NULL;
3287 peer->default_rmap[afi][safi].map = NULL;
3288
3289 if (peer->status == Established && peer->afc_nego[afi][safi])
3290 bgp_default_originate (peer, afi, safi, 1);
3291 }
3292 return 0;
3293}
David Lamparter6b0655a2014-06-04 06:53:35 +02003294
paul718e3742002-12-13 20:15:29 +00003295int
3296peer_port_set (struct peer *peer, u_int16_t port)
3297{
3298 peer->port = port;
3299 return 0;
3300}
3301
3302int
3303peer_port_unset (struct peer *peer)
3304{
3305 peer->port = BGP_PORT_DEFAULT;
3306 return 0;
3307}
David Lamparter6b0655a2014-06-04 06:53:35 +02003308
paul718e3742002-12-13 20:15:29 +00003309/* neighbor weight. */
3310int
3311peer_weight_set (struct peer *peer, u_int16_t weight)
3312{
3313 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003314 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003315
3316 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3317 peer->weight = weight;
3318
3319 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3320 return 0;
3321
3322 /* peer-group member updates. */
3323 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003324 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003325 {
3326 peer->weight = group->conf->weight;
3327 }
3328 return 0;
3329}
3330
3331int
3332peer_weight_unset (struct peer *peer)
3333{
3334 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003335 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003336
3337 /* Set default weight. */
3338 if (peer_group_active (peer))
3339 peer->weight = peer->group->conf->weight;
3340 else
3341 peer->weight = 0;
3342
3343 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3344
3345 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3346 return 0;
3347
3348 /* peer-group member updates. */
3349 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003350 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003351 {
3352 peer->weight = 0;
3353 }
3354 return 0;
3355}
David Lamparter6b0655a2014-06-04 06:53:35 +02003356
paul718e3742002-12-13 20:15:29 +00003357int
3358peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3359{
3360 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003361 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003362
3363 /* Not for peer group memeber. */
3364 if (peer_group_active (peer))
3365 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3366
3367 /* keepalive value check. */
3368 if (keepalive > 65535)
3369 return BGP_ERR_INVALID_VALUE;
3370
3371 /* Holdtime value check. */
3372 if (holdtime > 65535)
3373 return BGP_ERR_INVALID_VALUE;
3374
3375 /* Holdtime value must be either 0 or greater than 3. */
3376 if (holdtime < 3 && holdtime != 0)
3377 return BGP_ERR_INVALID_VALUE;
3378
3379 /* Set value to the configuration. */
3380 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3381 peer->holdtime = holdtime;
3382 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3383
3384 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3385 return 0;
3386
3387 /* peer-group member updates. */
3388 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003389 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003390 {
3391 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3392 peer->holdtime = group->conf->holdtime;
3393 peer->keepalive = group->conf->keepalive;
3394 }
3395 return 0;
3396}
3397
3398int
3399peer_timers_unset (struct peer *peer)
3400{
3401 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003402 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003403
3404 if (peer_group_active (peer))
3405 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3406
3407 /* Clear configuration. */
3408 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3409 peer->keepalive = 0;
3410 peer->holdtime = 0;
3411
3412 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3413 return 0;
3414
3415 /* peer-group member updates. */
3416 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003417 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003418 {
3419 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3420 peer->holdtime = 0;
3421 peer->keepalive = 0;
3422 }
3423
3424 return 0;
3425}
David Lamparter6b0655a2014-06-04 06:53:35 +02003426
paul718e3742002-12-13 20:15:29 +00003427int
3428peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3429{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003430 struct peer_group *group;
3431 struct listnode *node, *nnode;
3432
paul718e3742002-12-13 20:15:29 +00003433 if (peer_group_active (peer))
3434 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3435
3436 if (connect > 65535)
3437 return BGP_ERR_INVALID_VALUE;
3438
3439 /* Set value to the configuration. */
3440 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3441 peer->connect = connect;
3442
3443 /* Set value to timer setting. */
3444 peer->v_connect = connect;
3445
Daniel Walton0d7435f2015-10-22 11:35:20 +03003446 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3447 return 0;
3448
3449 /* peer-group member updates. */
3450 group = peer->group;
3451 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3452 {
3453 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3454 peer->connect = connect;
3455 peer->v_connect = connect;
3456 }
paul718e3742002-12-13 20:15:29 +00003457 return 0;
3458}
3459
3460int
3461peer_timers_connect_unset (struct peer *peer)
3462{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003463 struct peer_group *group;
3464 struct listnode *node, *nnode;
3465
paul718e3742002-12-13 20:15:29 +00003466 if (peer_group_active (peer))
3467 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3468
3469 /* Clear configuration. */
3470 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3471 peer->connect = 0;
3472
3473 /* Set timer setting to default value. */
3474 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3475
Daniel Walton0d7435f2015-10-22 11:35:20 +03003476 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3477 return 0;
3478
3479 /* peer-group member updates. */
3480 group = peer->group;
3481 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3482 {
3483 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3484 peer->connect = 0;
3485 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3486 }
3487 return 0;
paul718e3742002-12-13 20:15:29 +00003488}
David Lamparter6b0655a2014-06-04 06:53:35 +02003489
paul718e3742002-12-13 20:15:29 +00003490int
3491peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3492{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003493 struct peer_group *group;
3494 struct listnode *node, *nnode;
3495
paul718e3742002-12-13 20:15:29 +00003496 if (peer_group_active (peer))
3497 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3498
3499 if (routeadv > 600)
3500 return BGP_ERR_INVALID_VALUE;
3501
3502 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3503 peer->routeadv = routeadv;
3504 peer->v_routeadv = routeadv;
3505
Daniel Walton0d7435f2015-10-22 11:35:20 +03003506 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 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3514 peer->routeadv = routeadv;
3515 peer->v_routeadv = routeadv;
3516 }
3517
paul718e3742002-12-13 20:15:29 +00003518 return 0;
3519}
3520
3521int
3522peer_advertise_interval_unset (struct peer *peer)
3523{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003524 struct peer_group *group;
3525 struct listnode *node, *nnode;
3526
paul718e3742002-12-13 20:15:29 +00003527 if (peer_group_active (peer))
3528 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3529
3530 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3531 peer->routeadv = 0;
3532
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003533 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003534 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3535 else
3536 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
Daniel Walton0d7435f2015-10-22 11:35:20 +03003537
3538 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3539 return 0;
3540
3541 /* peer-group member updates. */
3542 group = peer->group;
3543 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3544 {
3545 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3546 peer->routeadv = 0;
3547
3548 if (peer->sort == BGP_PEER_IBGP)
3549 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3550 else
3551 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3552 }
paul718e3742002-12-13 20:15:29 +00003553
3554 return 0;
3555}
David Lamparter6b0655a2014-06-04 06:53:35 +02003556
paul718e3742002-12-13 20:15:29 +00003557/* neighbor interface */
3558int
paulfd79ac92004-10-13 05:06:08 +00003559peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003560{
3561 if (peer->ifname)
3562 free (peer->ifname);
3563 peer->ifname = strdup (str);
3564
3565 return 0;
3566}
3567
3568int
3569peer_interface_unset (struct peer *peer)
3570{
3571 if (peer->ifname)
3572 free (peer->ifname);
3573 peer->ifname = NULL;
3574
3575 return 0;
3576}
David Lamparter6b0655a2014-06-04 06:53:35 +02003577
paul718e3742002-12-13 20:15:29 +00003578/* Allow-as in. */
3579int
3580peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3581{
3582 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003583 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003584
3585 if (allow_num < 1 || allow_num > 10)
3586 return BGP_ERR_INVALID_VALUE;
3587
3588 if (peer->allowas_in[afi][safi] != allow_num)
3589 {
3590 peer->allowas_in[afi][safi] = allow_num;
3591 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3592 peer_change_action (peer, afi, safi, peer_change_reset_in);
3593 }
3594
3595 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3596 return 0;
3597
3598 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003599 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003600 {
3601 if (peer->allowas_in[afi][safi] != allow_num)
3602 {
3603 peer->allowas_in[afi][safi] = allow_num;
3604 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3605 peer_change_action (peer, afi, safi, peer_change_reset_in);
3606 }
3607
3608 }
3609 return 0;
3610}
3611
3612int
3613peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3614{
3615 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003616 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003617
3618 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3619 {
3620 peer->allowas_in[afi][safi] = 0;
3621 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3622 }
3623
3624 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3625 return 0;
3626
3627 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003628 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003629 {
3630 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3631 {
3632 peer->allowas_in[afi][safi] = 0;
3633 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3634 }
3635 }
3636 return 0;
3637}
David Lamparter6b0655a2014-06-04 06:53:35 +02003638
paul718e3742002-12-13 20:15:29 +00003639int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003640peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003641{
3642 struct bgp *bgp = peer->bgp;
3643 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003644 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003645
3646 if (peer_sort (peer) != BGP_PEER_EBGP
3647 && peer_sort (peer) != BGP_PEER_INTERNAL)
3648 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3649
3650 if (bgp->as == as)
3651 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3652
3653 if (peer_group_active (peer))
3654 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3655
Andrew Certain9d3f9702012-11-07 23:50:07 +00003656 if (peer->as == as)
3657 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3658
paul718e3742002-12-13 20:15:29 +00003659 if (peer->change_local_as == as &&
3660 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003661 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3662 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3663 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003664 return 0;
3665
3666 peer->change_local_as = as;
3667 if (no_prepend)
3668 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3669 else
3670 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3671
Andrew Certain9d3f9702012-11-07 23:50:07 +00003672 if (replace_as)
3673 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3674 else
3675 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3676
paul718e3742002-12-13 20:15:29 +00003677 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3678 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003679 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003680 {
3681 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3682 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3683 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3684 }
paul718e3742002-12-13 20:15:29 +00003685 else
3686 BGP_EVENT_ADD (peer, BGP_Stop);
3687
3688 return 0;
3689 }
3690
3691 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003692 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003693 {
3694 peer->change_local_as = as;
3695 if (no_prepend)
3696 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3697 else
3698 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3699
Andrew Certain9d3f9702012-11-07 23:50:07 +00003700 if (replace_as)
3701 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3702 else
3703 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3704
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003705 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003706 {
3707 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3708 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3709 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3710 }
paul718e3742002-12-13 20:15:29 +00003711 else
3712 BGP_EVENT_ADD (peer, BGP_Stop);
3713 }
3714
3715 return 0;
3716}
3717
3718int
3719peer_local_as_unset (struct peer *peer)
3720{
3721 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003722 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003723
3724 if (peer_group_active (peer))
3725 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3726
3727 if (! peer->change_local_as)
3728 return 0;
3729
3730 peer->change_local_as = 0;
3731 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003732 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003733
3734 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3735 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003736 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003737 {
3738 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3739 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3740 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3741 }
paul718e3742002-12-13 20:15:29 +00003742 else
3743 BGP_EVENT_ADD (peer, BGP_Stop);
3744
3745 return 0;
3746 }
3747
3748 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003749 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003750 {
3751 peer->change_local_as = 0;
3752 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003753 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003754
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003755 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003756 {
3757 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3758 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3759 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3760 }
paul718e3742002-12-13 20:15:29 +00003761 else
3762 BGP_EVENT_ADD (peer, BGP_Stop);
3763 }
3764 return 0;
3765}
David Lamparter6b0655a2014-06-04 06:53:35 +02003766
Paul Jakma0df7c912008-07-21 21:02:49 +00003767/* Set password for authenticating with the peer. */
3768int
3769peer_password_set (struct peer *peer, const char *password)
3770{
3771 struct listnode *nn, *nnode;
3772 int len = password ? strlen(password) : 0;
3773 int ret = BGP_SUCCESS;
3774
3775 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3776 return BGP_ERR_INVALID_VALUE;
3777
3778 if (peer->password && strcmp (peer->password, password) == 0
3779 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3780 return 0;
3781
3782 if (peer->password)
3783 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3784
3785 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3786
3787 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3788 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003789 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3790 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
Paul Jakma0df7c912008-07-21 21:02:49 +00003791 else
3792 BGP_EVENT_ADD (peer, BGP_Stop);
3793
3794 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3795 }
3796
3797 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3798 {
3799 if (peer->password && strcmp (peer->password, password) == 0)
3800 continue;
3801
3802 if (peer->password)
3803 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3804
3805 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3806
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003807 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003808 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3809 else
3810 BGP_EVENT_ADD (peer, BGP_Stop);
3811
3812 if (bgp_md5_set (peer) < 0)
3813 ret = BGP_ERR_TCPSIG_FAILED;
3814 }
3815
3816 return ret;
3817}
3818
3819int
3820peer_password_unset (struct peer *peer)
3821{
3822 struct listnode *nn, *nnode;
3823
3824 if (!peer->password
3825 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3826 return 0;
3827
3828 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3829 {
3830 if (peer_group_active (peer)
3831 && peer->group->conf->password
3832 && strcmp (peer->group->conf->password, peer->password) == 0)
3833 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3834
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003835 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003836 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3837 else
3838 BGP_EVENT_ADD (peer, BGP_Stop);
3839
3840 if (peer->password)
3841 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3842
3843 peer->password = NULL;
3844
3845 bgp_md5_set (peer);
3846
3847 return 0;
3848 }
3849
3850 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3851 peer->password = NULL;
3852
3853 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3854 {
3855 if (!peer->password)
3856 continue;
3857
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003858 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003859 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3860 else
3861 BGP_EVENT_ADD (peer, BGP_Stop);
3862
3863 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3864 peer->password = NULL;
3865
3866 bgp_md5_set (peer);
3867 }
3868
3869 return 0;
3870}
David Lamparter6b0655a2014-06-04 06:53:35 +02003871
paul718e3742002-12-13 20:15:29 +00003872/* Set distribute list to the peer. */
3873int
3874peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003875 const char *name)
paul718e3742002-12-13 20:15:29 +00003876{
3877 struct bgp_filter *filter;
3878 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003879 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003880
3881 if (! peer->afc[afi][safi])
3882 return BGP_ERR_PEER_INACTIVE;
3883
3884 if (direct != FILTER_IN && direct != FILTER_OUT)
3885 return BGP_ERR_INVALID_VALUE;
3886
3887 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3888 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3889
3890 filter = &peer->filter[afi][safi];
3891
3892 if (filter->plist[direct].name)
3893 return BGP_ERR_PEER_FILTER_CONFLICT;
3894
3895 if (filter->dlist[direct].name)
3896 free (filter->dlist[direct].name);
3897 filter->dlist[direct].name = strdup (name);
3898 filter->dlist[direct].alist = access_list_lookup (afi, name);
3899
3900 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3901 return 0;
3902
3903 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003904 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003905 {
3906 filter = &peer->filter[afi][safi];
3907
3908 if (! peer->af_group[afi][safi])
3909 continue;
3910
3911 if (filter->dlist[direct].name)
3912 free (filter->dlist[direct].name);
3913 filter->dlist[direct].name = strdup (name);
3914 filter->dlist[direct].alist = access_list_lookup (afi, name);
3915 }
3916
3917 return 0;
3918}
3919
3920int
3921peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3922{
3923 struct bgp_filter *filter;
3924 struct bgp_filter *gfilter;
3925 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003926 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003927
3928 if (! peer->afc[afi][safi])
3929 return BGP_ERR_PEER_INACTIVE;
3930
3931 if (direct != FILTER_IN && direct != FILTER_OUT)
3932 return BGP_ERR_INVALID_VALUE;
3933
3934 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3935 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3936
3937 filter = &peer->filter[afi][safi];
3938
3939 /* apply peer-group filter */
3940 if (peer->af_group[afi][safi])
3941 {
3942 gfilter = &peer->group->conf->filter[afi][safi];
3943
3944 if (gfilter->dlist[direct].name)
3945 {
3946 if (filter->dlist[direct].name)
3947 free (filter->dlist[direct].name);
3948 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3949 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3950 return 0;
3951 }
3952 }
3953
3954 if (filter->dlist[direct].name)
3955 free (filter->dlist[direct].name);
3956 filter->dlist[direct].name = NULL;
3957 filter->dlist[direct].alist = NULL;
3958
3959 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3960 return 0;
3961
3962 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003963 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003964 {
3965 filter = &peer->filter[afi][safi];
3966
3967 if (! peer->af_group[afi][safi])
3968 continue;
3969
3970 if (filter->dlist[direct].name)
3971 free (filter->dlist[direct].name);
3972 filter->dlist[direct].name = NULL;
3973 filter->dlist[direct].alist = NULL;
3974 }
3975
3976 return 0;
3977}
3978
3979/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003980static void
paul718e3742002-12-13 20:15:29 +00003981peer_distribute_update (struct access_list *access)
3982{
3983 afi_t afi;
3984 safi_t safi;
3985 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003986 struct listnode *mnode, *mnnode;
3987 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003988 struct bgp *bgp;
3989 struct peer *peer;
3990 struct peer_group *group;
3991 struct bgp_filter *filter;
3992
paul1eb8ef22005-04-07 07:30:20 +00003993 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003994 {
paul1eb8ef22005-04-07 07:30:20 +00003995 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003996 {
3997 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3998 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3999 {
4000 filter = &peer->filter[afi][safi];
4001
4002 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4003 {
4004 if (filter->dlist[direct].name)
4005 filter->dlist[direct].alist =
4006 access_list_lookup (afi, filter->dlist[direct].name);
4007 else
4008 filter->dlist[direct].alist = NULL;
4009 }
4010 }
4011 }
paul1eb8ef22005-04-07 07:30:20 +00004012 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004013 {
4014 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4015 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4016 {
4017 filter = &group->conf->filter[afi][safi];
4018
4019 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4020 {
4021 if (filter->dlist[direct].name)
4022 filter->dlist[direct].alist =
4023 access_list_lookup (afi, filter->dlist[direct].name);
4024 else
4025 filter->dlist[direct].alist = NULL;
4026 }
4027 }
4028 }
4029 }
4030}
David Lamparter6b0655a2014-06-04 06:53:35 +02004031
paul718e3742002-12-13 20:15:29 +00004032/* Set prefix list to the peer. */
4033int
4034peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004035 const char *name)
paul718e3742002-12-13 20:15:29 +00004036{
4037 struct bgp_filter *filter;
4038 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004039 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004040
4041 if (! peer->afc[afi][safi])
4042 return BGP_ERR_PEER_INACTIVE;
4043
4044 if (direct != FILTER_IN && direct != FILTER_OUT)
4045 return BGP_ERR_INVALID_VALUE;
4046
4047 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4048 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4049
4050 filter = &peer->filter[afi][safi];
4051
4052 if (filter->dlist[direct].name)
4053 return BGP_ERR_PEER_FILTER_CONFLICT;
4054
4055 if (filter->plist[direct].name)
4056 free (filter->plist[direct].name);
4057 filter->plist[direct].name = strdup (name);
4058 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4059
4060 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4061 return 0;
4062
4063 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004064 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004065 {
4066 filter = &peer->filter[afi][safi];
4067
4068 if (! peer->af_group[afi][safi])
4069 continue;
4070
4071 if (filter->plist[direct].name)
4072 free (filter->plist[direct].name);
4073 filter->plist[direct].name = strdup (name);
4074 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4075 }
4076 return 0;
4077}
4078
4079int
4080peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4081{
4082 struct bgp_filter *filter;
4083 struct bgp_filter *gfilter;
4084 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004085 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004086
4087 if (! peer->afc[afi][safi])
4088 return BGP_ERR_PEER_INACTIVE;
4089
4090 if (direct != FILTER_IN && direct != FILTER_OUT)
4091 return BGP_ERR_INVALID_VALUE;
4092
4093 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4094 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4095
4096 filter = &peer->filter[afi][safi];
4097
4098 /* apply peer-group filter */
4099 if (peer->af_group[afi][safi])
4100 {
4101 gfilter = &peer->group->conf->filter[afi][safi];
4102
4103 if (gfilter->plist[direct].name)
4104 {
4105 if (filter->plist[direct].name)
4106 free (filter->plist[direct].name);
4107 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
4108 filter->plist[direct].plist = gfilter->plist[direct].plist;
4109 return 0;
4110 }
4111 }
4112
4113 if (filter->plist[direct].name)
4114 free (filter->plist[direct].name);
4115 filter->plist[direct].name = NULL;
4116 filter->plist[direct].plist = NULL;
4117
4118 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4119 return 0;
4120
4121 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004122 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004123 {
4124 filter = &peer->filter[afi][safi];
4125
4126 if (! peer->af_group[afi][safi])
4127 continue;
4128
4129 if (filter->plist[direct].name)
4130 free (filter->plist[direct].name);
4131 filter->plist[direct].name = NULL;
4132 filter->plist[direct].plist = NULL;
4133 }
4134
4135 return 0;
4136}
4137
4138/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00004139static void
paul718e3742002-12-13 20:15:29 +00004140peer_prefix_list_update (struct prefix_list *plist)
4141{
paul1eb8ef22005-04-07 07:30:20 +00004142 struct listnode *mnode, *mnnode;
4143 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004144 struct bgp *bgp;
4145 struct peer *peer;
4146 struct peer_group *group;
4147 struct bgp_filter *filter;
4148 afi_t afi;
4149 safi_t safi;
4150 int direct;
4151
paul1eb8ef22005-04-07 07:30:20 +00004152 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004153 {
paul1eb8ef22005-04-07 07:30:20 +00004154 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004155 {
4156 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4157 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4158 {
4159 filter = &peer->filter[afi][safi];
4160
4161 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4162 {
4163 if (filter->plist[direct].name)
4164 filter->plist[direct].plist =
4165 prefix_list_lookup (afi, filter->plist[direct].name);
4166 else
4167 filter->plist[direct].plist = NULL;
4168 }
4169 }
4170 }
paul1eb8ef22005-04-07 07:30:20 +00004171 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004172 {
4173 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4174 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4175 {
4176 filter = &group->conf->filter[afi][safi];
4177
4178 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4179 {
4180 if (filter->plist[direct].name)
4181 filter->plist[direct].plist =
4182 prefix_list_lookup (afi, filter->plist[direct].name);
4183 else
4184 filter->plist[direct].plist = NULL;
4185 }
4186 }
4187 }
4188 }
4189}
David Lamparter6b0655a2014-06-04 06:53:35 +02004190
paul718e3742002-12-13 20:15:29 +00004191int
4192peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004193 const char *name)
paul718e3742002-12-13 20:15:29 +00004194{
4195 struct bgp_filter *filter;
4196 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004197 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004198
4199 if (! peer->afc[afi][safi])
4200 return BGP_ERR_PEER_INACTIVE;
4201
4202 if (direct != FILTER_IN && direct != FILTER_OUT)
4203 return BGP_ERR_INVALID_VALUE;
4204
4205 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4206 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4207
4208 filter = &peer->filter[afi][safi];
4209
4210 if (filter->aslist[direct].name)
4211 free (filter->aslist[direct].name);
4212 filter->aslist[direct].name = strdup (name);
4213 filter->aslist[direct].aslist = as_list_lookup (name);
4214
4215 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4216 return 0;
4217
4218 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004219 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004220 {
4221 filter = &peer->filter[afi][safi];
4222
4223 if (! peer->af_group[afi][safi])
4224 continue;
4225
4226 if (filter->aslist[direct].name)
4227 free (filter->aslist[direct].name);
4228 filter->aslist[direct].name = strdup (name);
4229 filter->aslist[direct].aslist = as_list_lookup (name);
4230 }
4231 return 0;
4232}
4233
4234int
4235peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4236{
4237 struct bgp_filter *filter;
4238 struct bgp_filter *gfilter;
4239 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004240 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004241
4242 if (! peer->afc[afi][safi])
4243 return BGP_ERR_PEER_INACTIVE;
4244
hassob5f29602005-05-25 21:00:28 +00004245 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004246 return BGP_ERR_INVALID_VALUE;
4247
hassob5f29602005-05-25 21:00:28 +00004248 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004249 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4250
4251 filter = &peer->filter[afi][safi];
4252
4253 /* apply peer-group filter */
4254 if (peer->af_group[afi][safi])
4255 {
4256 gfilter = &peer->group->conf->filter[afi][safi];
4257
4258 if (gfilter->aslist[direct].name)
4259 {
4260 if (filter->aslist[direct].name)
4261 free (filter->aslist[direct].name);
4262 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4263 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4264 return 0;
4265 }
4266 }
4267
4268 if (filter->aslist[direct].name)
4269 free (filter->aslist[direct].name);
4270 filter->aslist[direct].name = NULL;
4271 filter->aslist[direct].aslist = NULL;
4272
4273 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4274 return 0;
4275
4276 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004277 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004278 {
4279 filter = &peer->filter[afi][safi];
4280
4281 if (! peer->af_group[afi][safi])
4282 continue;
4283
4284 if (filter->aslist[direct].name)
4285 free (filter->aslist[direct].name);
4286 filter->aslist[direct].name = NULL;
4287 filter->aslist[direct].aslist = NULL;
4288 }
4289
4290 return 0;
4291}
4292
paul94f2b392005-06-28 12:44:16 +00004293static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004294peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004295{
4296 afi_t afi;
4297 safi_t safi;
4298 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004299 struct listnode *mnode, *mnnode;
4300 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004301 struct bgp *bgp;
4302 struct peer *peer;
4303 struct peer_group *group;
4304 struct bgp_filter *filter;
4305
paul1eb8ef22005-04-07 07:30:20 +00004306 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004307 {
paul1eb8ef22005-04-07 07:30:20 +00004308 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004309 {
4310 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4311 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4312 {
4313 filter = &peer->filter[afi][safi];
4314
4315 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4316 {
4317 if (filter->aslist[direct].name)
4318 filter->aslist[direct].aslist =
4319 as_list_lookup (filter->aslist[direct].name);
4320 else
4321 filter->aslist[direct].aslist = NULL;
4322 }
4323 }
4324 }
paul1eb8ef22005-04-07 07:30:20 +00004325 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004326 {
4327 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4328 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4329 {
4330 filter = &group->conf->filter[afi][safi];
4331
4332 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4333 {
4334 if (filter->aslist[direct].name)
4335 filter->aslist[direct].aslist =
4336 as_list_lookup (filter->aslist[direct].name);
4337 else
4338 filter->aslist[direct].aslist = NULL;
4339 }
4340 }
4341 }
4342 }
4343}
David Lamparter6b0655a2014-06-04 06:53:35 +02004344
paul718e3742002-12-13 20:15:29 +00004345/* Set route-map to the peer. */
4346int
4347peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004348 const char *name)
paul718e3742002-12-13 20:15:29 +00004349{
4350 struct bgp_filter *filter;
4351 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004352 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004353
4354 if (! peer->afc[afi][safi])
4355 return BGP_ERR_PEER_INACTIVE;
4356
paulfee0f4c2004-09-13 05:12:46 +00004357 if (direct != RMAP_IN && direct != RMAP_OUT &&
4358 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004359 return BGP_ERR_INVALID_VALUE;
4360
paulfee0f4c2004-09-13 05:12:46 +00004361 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4362 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004363 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4364
4365 filter = &peer->filter[afi][safi];
4366
4367 if (filter->map[direct].name)
4368 free (filter->map[direct].name);
4369
4370 filter->map[direct].name = strdup (name);
4371 filter->map[direct].map = route_map_lookup_by_name (name);
4372
4373 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4374 return 0;
4375
4376 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004377 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004378 {
4379 filter = &peer->filter[afi][safi];
4380
4381 if (! peer->af_group[afi][safi])
4382 continue;
4383
4384 if (filter->map[direct].name)
4385 free (filter->map[direct].name);
4386 filter->map[direct].name = strdup (name);
4387 filter->map[direct].map = route_map_lookup_by_name (name);
4388 }
4389 return 0;
4390}
4391
4392/* Unset route-map from the peer. */
4393int
4394peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4395{
4396 struct bgp_filter *filter;
4397 struct bgp_filter *gfilter;
4398 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004399 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004400
4401 if (! peer->afc[afi][safi])
4402 return BGP_ERR_PEER_INACTIVE;
4403
hassob5f29602005-05-25 21:00:28 +00004404 if (direct != RMAP_IN && direct != RMAP_OUT &&
4405 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004406 return BGP_ERR_INVALID_VALUE;
4407
hassob5f29602005-05-25 21:00:28 +00004408 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4409 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004410 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4411
4412 filter = &peer->filter[afi][safi];
4413
4414 /* apply peer-group filter */
4415 if (peer->af_group[afi][safi])
4416 {
4417 gfilter = &peer->group->conf->filter[afi][safi];
4418
4419 if (gfilter->map[direct].name)
4420 {
4421 if (filter->map[direct].name)
4422 free (filter->map[direct].name);
4423 filter->map[direct].name = strdup (gfilter->map[direct].name);
4424 filter->map[direct].map = gfilter->map[direct].map;
4425 return 0;
4426 }
4427 }
4428
4429 if (filter->map[direct].name)
4430 free (filter->map[direct].name);
4431 filter->map[direct].name = NULL;
4432 filter->map[direct].map = NULL;
4433
4434 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4435 return 0;
4436
4437 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004438 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004439 {
4440 filter = &peer->filter[afi][safi];
4441
4442 if (! peer->af_group[afi][safi])
4443 continue;
4444
4445 if (filter->map[direct].name)
4446 free (filter->map[direct].name);
4447 filter->map[direct].name = NULL;
4448 filter->map[direct].map = NULL;
4449 }
4450 return 0;
4451}
David Lamparter6b0655a2014-06-04 06:53:35 +02004452
paul718e3742002-12-13 20:15:29 +00004453/* Set unsuppress-map to the peer. */
4454int
paulfd79ac92004-10-13 05:06:08 +00004455peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4456 const char *name)
paul718e3742002-12-13 20:15:29 +00004457{
4458 struct bgp_filter *filter;
4459 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004460 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004461
4462 if (! peer->afc[afi][safi])
4463 return BGP_ERR_PEER_INACTIVE;
4464
4465 if (peer_is_group_member (peer, afi, safi))
4466 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4467
4468 filter = &peer->filter[afi][safi];
4469
4470 if (filter->usmap.name)
4471 free (filter->usmap.name);
4472
4473 filter->usmap.name = strdup (name);
4474 filter->usmap.map = route_map_lookup_by_name (name);
4475
4476 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4477 return 0;
4478
4479 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004480 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004481 {
4482 filter = &peer->filter[afi][safi];
4483
4484 if (! peer->af_group[afi][safi])
4485 continue;
4486
4487 if (filter->usmap.name)
4488 free (filter->usmap.name);
4489 filter->usmap.name = strdup (name);
4490 filter->usmap.map = route_map_lookup_by_name (name);
4491 }
4492 return 0;
4493}
4494
4495/* Unset route-map from the peer. */
4496int
4497peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4498{
4499 struct bgp_filter *filter;
4500 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004501 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004502
4503 if (! peer->afc[afi][safi])
4504 return BGP_ERR_PEER_INACTIVE;
4505
4506 if (peer_is_group_member (peer, afi, safi))
4507 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4508
4509 filter = &peer->filter[afi][safi];
4510
4511 if (filter->usmap.name)
4512 free (filter->usmap.name);
4513 filter->usmap.name = NULL;
4514 filter->usmap.map = NULL;
4515
4516 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4517 return 0;
4518
4519 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004520 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004521 {
4522 filter = &peer->filter[afi][safi];
4523
4524 if (! peer->af_group[afi][safi])
4525 continue;
4526
4527 if (filter->usmap.name)
4528 free (filter->usmap.name);
4529 filter->usmap.name = NULL;
4530 filter->usmap.map = NULL;
4531 }
4532 return 0;
4533}
David Lamparter6b0655a2014-06-04 06:53:35 +02004534
paul718e3742002-12-13 20:15:29 +00004535int
4536peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004537 u_int32_t max, u_char threshold,
4538 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004539{
4540 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004541 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004542
4543 if (! peer->afc[afi][safi])
4544 return BGP_ERR_PEER_INACTIVE;
4545
4546 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4547 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004548 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004549 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004550 if (warning)
4551 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4552 else
4553 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4554
4555 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4556 return 0;
4557
4558 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004559 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004560 {
4561 if (! peer->af_group[afi][safi])
4562 continue;
4563
4564 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4565 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004566 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004567 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004568 if (warning)
4569 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4570 else
4571 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4572 }
4573 return 0;
4574}
4575
4576int
4577peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4578{
4579 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004580 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004581
4582 if (! peer->afc[afi][safi])
4583 return BGP_ERR_PEER_INACTIVE;
4584
4585 /* apply peer-group config */
4586 if (peer->af_group[afi][safi])
4587 {
4588 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4589 PEER_FLAG_MAX_PREFIX))
4590 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4591 else
4592 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4593
4594 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4595 PEER_FLAG_MAX_PREFIX_WARNING))
4596 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4597 else
4598 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4599
4600 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004601 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004602 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004603 return 0;
4604 }
4605
4606 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4607 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4608 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004609 peer->pmax_threshold[afi][safi] = 0;
4610 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004611
4612 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4613 return 0;
4614
4615 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004616 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004617 {
4618 if (! peer->af_group[afi][safi])
4619 continue;
4620
4621 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4622 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4623 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004624 peer->pmax_threshold[afi][safi] = 0;
4625 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004626 }
4627 return 0;
4628}
David Lamparter5f9adb52014-05-19 23:15:02 +02004629
4630static int is_ebgp_multihop_configured (struct peer *peer)
4631{
4632 struct peer_group *group;
4633 struct listnode *node, *nnode;
4634 struct peer *peer1;
4635
4636 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4637 {
4638 group = peer->group;
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004639 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4640 (group->conf->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004641 return 1;
4642
4643 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4644 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004645 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
4646 (peer1->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004647 return 1;
4648 }
4649 }
4650 else
4651 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004652 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4653 (peer->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004654 return 1;
4655 }
4656 return 0;
4657}
4658
Nick Hilliardfa411a22011-03-23 15:33:17 +00004659/* Set # of hops between us and BGP peer. */
4660int
4661peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4662{
4663 struct peer_group *group;
4664 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004665 int ret;
4666
4667 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4668
Nick Hilliardfa411a22011-03-23 15:33:17 +00004669 /* We cannot configure ttl-security hops when ebgp-multihop is already
4670 set. For non peer-groups, the check is simple. For peer-groups, it's
4671 slightly messy, because we need to check both the peer-group structure
4672 and all peer-group members for any trace of ebgp-multihop configuration
4673 before actually applying the ttl-security rules. Cisco really made a
4674 mess of this configuration parameter, and OpenBGPD got it right.
4675 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004676
David Lamparter5f9adb52014-05-19 23:15:02 +02004677 if (peer->gtsm_hops == 0)
4678 {
4679 if (is_ebgp_multihop_configured (peer))
4680 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004681
David Lamparter5f9adb52014-05-19 23:15:02 +02004682 /* specify MAXTTL on outgoing packets */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004683 /* Routine handles iBGP peers correctly */
David Lamparter5f9adb52014-05-19 23:15:02 +02004684 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4685 if (ret != 0)
4686 return ret;
4687 }
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004688
Nick Hilliardfa411a22011-03-23 15:33:17 +00004689 peer->gtsm_hops = gtsm_hops;
4690
Nick Hilliardfa411a22011-03-23 15:33:17 +00004691 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4692 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004693 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004694 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4695 }
4696 else
4697 {
4698 group = peer->group;
4699 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4700 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004701 peer->gtsm_hops = group->conf->gtsm_hops;
4702
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004703 /* Change setting of existing peer
4704 * established then change value (may break connectivity)
4705 * not established yet (teardown session and restart)
4706 * no session then do nothing (will get handled by next connection)
4707 */
4708 if (peer->status == Established)
4709 {
4710 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4711 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4712 MAXTTL + 1 - peer->gtsm_hops);
4713 }
4714 else if (peer->status < Established)
4715 {
4716 if (BGP_DEBUG (events, EVENTS))
4717 zlog_debug ("%s Min-ttl changed", peer->host);
4718 BGP_EVENT_ADD (peer, BGP_Stop);
4719 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004720 }
4721 }
4722
4723 return 0;
4724}
4725
4726int
4727peer_ttl_security_hops_unset (struct peer *peer)
4728{
4729 struct peer_group *group;
4730 struct listnode *node, *nnode;
4731 struct peer *opeer;
4732
4733 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4734
Nick Hilliardfa411a22011-03-23 15:33:17 +00004735 /* if a peer-group member, then reset to peer-group default rather than 0 */
4736 if (peer_group_active (peer))
4737 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4738 else
4739 peer->gtsm_hops = 0;
4740
4741 opeer = peer;
4742 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4743 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004744 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004745 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4746 }
4747 else
4748 {
4749 group = peer->group;
4750 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4751 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004752 peer->gtsm_hops = 0;
4753
4754 if (peer->fd >= 0)
4755 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4756 }
4757 }
4758
4759 return peer_ebgp_multihop_unset (opeer);
4760}
David Lamparter6b0655a2014-06-04 06:53:35 +02004761
paul718e3742002-12-13 20:15:29 +00004762int
4763peer_clear (struct peer *peer)
4764{
4765 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4766 {
hasso0a486e52005-02-01 20:57:17 +00004767 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4768 {
4769 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4770 if (peer->t_pmax_restart)
4771 {
4772 BGP_TIMER_OFF (peer->t_pmax_restart);
4773 if (BGP_DEBUG (events, EVENTS))
4774 zlog_debug ("%s Maximum-prefix restart timer canceled",
4775 peer->host);
4776 }
4777 BGP_EVENT_ADD (peer, BGP_Start);
4778 return 0;
4779 }
4780
paul718e3742002-12-13 20:15:29 +00004781 peer->v_start = BGP_INIT_START_TIMER;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00004782 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00004783 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4784 BGP_NOTIFY_CEASE_ADMIN_RESET);
4785 else
4786 BGP_EVENT_ADD (peer, BGP_Stop);
4787 }
4788 return 0;
4789}
4790
4791int
4792peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4793 enum bgp_clear_type stype)
4794{
4795 if (peer->status != Established)
4796 return 0;
4797
4798 if (! peer->afc[afi][safi])
4799 return BGP_ERR_AF_UNCONFIGURED;
4800
Timo Teräs5a2a1ec2015-10-22 11:35:18 +03004801 peer->rtt = sockopt_tcp_rtt (peer->fd);
4802
paulfee0f4c2004-09-13 05:12:46 +00004803 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4804 {
4805 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4806 return 0;
4807 bgp_check_local_routes_rsclient (peer, afi, safi);
4808 bgp_soft_reconfig_rsclient (peer, afi, safi);
4809 }
4810
paul718e3742002-12-13 20:15:29 +00004811 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4812 bgp_announce_route (peer, afi, safi);
4813
4814 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4815 {
4816 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4817 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4818 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4819 {
4820 struct bgp_filter *filter = &peer->filter[afi][safi];
4821 u_char prefix_type;
4822
4823 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4824 prefix_type = ORF_TYPE_PREFIX;
4825 else
4826 prefix_type = ORF_TYPE_PREFIX_OLD;
4827
4828 if (filter->plist[FILTER_IN].plist)
4829 {
4830 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4831 bgp_route_refresh_send (peer, afi, safi,
4832 prefix_type, REFRESH_DEFER, 1);
4833 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4834 REFRESH_IMMEDIATE, 0);
4835 }
4836 else
4837 {
4838 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4839 bgp_route_refresh_send (peer, afi, safi,
4840 prefix_type, REFRESH_IMMEDIATE, 1);
4841 else
4842 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4843 }
4844 return 0;
4845 }
4846 }
4847
4848 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4849 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4850 {
4851 /* If neighbor has soft reconfiguration inbound flag.
4852 Use Adj-RIB-In database. */
4853 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4854 bgp_soft_reconfig_in (peer, afi, safi);
4855 else
4856 {
4857 /* If neighbor has route refresh capability, send route refresh
4858 message to the peer. */
4859 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4860 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4861 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4862 else
4863 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4864 }
4865 }
4866 return 0;
4867}
David Lamparter6b0655a2014-06-04 06:53:35 +02004868
paulfd79ac92004-10-13 05:06:08 +00004869/* Display peer uptime.*/
4870/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004871char *
4872peer_uptime (time_t uptime2, char *buf, size_t len)
4873{
4874 time_t uptime1;
4875 struct tm *tm;
4876
4877 /* Check buffer length. */
4878 if (len < BGP_UPTIME_LEN)
4879 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004880 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004881 /* XXX: should return status instead of buf... */
4882 snprintf (buf, len, "<error> ");
4883 return buf;
paul718e3742002-12-13 20:15:29 +00004884 }
4885
4886 /* If there is no connection has been done before print `never'. */
4887 if (uptime2 == 0)
4888 {
4889 snprintf (buf, len, "never ");
4890 return buf;
4891 }
4892
4893 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004894 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004895 uptime1 -= uptime2;
4896 tm = gmtime (&uptime1);
Paul Jakma84c38402015-05-26 15:19:38 +01004897
paul718e3742002-12-13 20:15:29 +00004898 /* Making formatted timer strings. */
4899#define ONE_DAY_SECOND 60*60*24
Paul Jakma84c38402015-05-26 15:19:38 +01004900#define ONE_WEEK_SECOND ONE_DAY_SECOND*7
4901#define ONE_YEAR_SECOND ONE_DAY_SECOND*365
paul718e3742002-12-13 20:15:29 +00004902
4903 if (uptime1 < ONE_DAY_SECOND)
4904 snprintf (buf, len, "%02d:%02d:%02d",
4905 tm->tm_hour, tm->tm_min, tm->tm_sec);
4906 else if (uptime1 < ONE_WEEK_SECOND)
4907 snprintf (buf, len, "%dd%02dh%02dm",
4908 tm->tm_yday, tm->tm_hour, tm->tm_min);
Paul Jakma84c38402015-05-26 15:19:38 +01004909 else if (uptime1 < ONE_YEAR_SECOND)
paul718e3742002-12-13 20:15:29 +00004910 snprintf (buf, len, "%02dw%dd%02dh",
4911 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
Paul Jakma84c38402015-05-26 15:19:38 +01004912 else
4913 snprintf (buf, len, "%02dy%02dw%dd",
4914 tm->tm_year - 70, tm->tm_yday/7,
4915 tm->tm_yday - ((tm->tm_yday/7) * 7));
paul718e3742002-12-13 20:15:29 +00004916 return buf;
4917}
David Lamparter6b0655a2014-06-04 06:53:35 +02004918
paul94f2b392005-06-28 12:44:16 +00004919static void
paul718e3742002-12-13 20:15:29 +00004920bgp_config_write_filter (struct vty *vty, struct peer *peer,
4921 afi_t afi, safi_t safi)
4922{
4923 struct bgp_filter *filter;
4924 struct bgp_filter *gfilter = NULL;
4925 char *addr;
4926 int in = FILTER_IN;
4927 int out = FILTER_OUT;
4928
4929 addr = peer->host;
4930 filter = &peer->filter[afi][safi];
4931 if (peer->af_group[afi][safi])
4932 gfilter = &peer->group->conf->filter[afi][safi];
4933
4934 /* distribute-list. */
4935 if (filter->dlist[in].name)
4936 if (! gfilter || ! gfilter->dlist[in].name
4937 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4938 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4939 filter->dlist[in].name, VTY_NEWLINE);
4940 if (filter->dlist[out].name && ! gfilter)
4941 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4942 filter->dlist[out].name, VTY_NEWLINE);
4943
4944 /* prefix-list. */
4945 if (filter->plist[in].name)
4946 if (! gfilter || ! gfilter->plist[in].name
4947 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4948 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4949 filter->plist[in].name, VTY_NEWLINE);
4950 if (filter->plist[out].name && ! gfilter)
4951 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4952 filter->plist[out].name, VTY_NEWLINE);
4953
4954 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004955 if (filter->map[RMAP_IN].name)
4956 if (! gfilter || ! gfilter->map[RMAP_IN].name
4957 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004958 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004959 filter->map[RMAP_IN].name, VTY_NEWLINE);
4960 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004961 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004962 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4963 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4964 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4965 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4966 if (filter->map[RMAP_EXPORT].name)
4967 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4968 || strcmp (filter->map[RMAP_EXPORT].name,
4969 gfilter->map[RMAP_EXPORT].name) != 0)
4970 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4971 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004972
4973 /* unsuppress-map */
4974 if (filter->usmap.name && ! gfilter)
4975 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4976 filter->usmap.name, VTY_NEWLINE);
4977
4978 /* filter-list. */
4979 if (filter->aslist[in].name)
4980 if (! gfilter || ! gfilter->aslist[in].name
4981 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4982 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4983 filter->aslist[in].name, VTY_NEWLINE);
4984 if (filter->aslist[out].name && ! gfilter)
4985 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4986 filter->aslist[out].name, VTY_NEWLINE);
4987}
4988
4989/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004990static void
paul718e3742002-12-13 20:15:29 +00004991bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4992 struct peer *peer, afi_t afi, safi_t safi)
4993{
paul718e3742002-12-13 20:15:29 +00004994 struct peer *g_peer = NULL;
4995 char buf[SU_ADDRSTRLEN];
4996 char *addr;
4997
paul718e3742002-12-13 20:15:29 +00004998 addr = peer->host;
4999 if (peer_group_active (peer))
5000 g_peer = peer->group->conf;
5001
5002 /************************************
5003 ****** Global to the neighbor ******
5004 ************************************/
5005 if (afi == AFI_IP && safi == SAFI_UNICAST)
5006 {
5007 /* remote-as. */
5008 if (! peer_group_active (peer))
5009 {
5010 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5011 vty_out (vty, " neighbor %s peer-group%s", addr,
5012 VTY_NEWLINE);
5013 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005014 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00005015 VTY_NEWLINE);
5016 }
5017 else
5018 {
5019 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005020 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00005021 VTY_NEWLINE);
5022 if (peer->af_group[AFI_IP][SAFI_UNICAST])
5023 vty_out (vty, " neighbor %s peer-group %s%s", addr,
5024 peer->group->name, VTY_NEWLINE);
5025 }
5026
5027 /* local-as. */
5028 if (peer->change_local_as)
5029 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00005030 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00005031 peer->change_local_as,
5032 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00005033 " no-prepend" : "",
5034 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
5035 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005036
5037 /* Description. */
5038 if (peer->desc)
5039 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
5040 VTY_NEWLINE);
5041
5042 /* Shutdown. */
5043 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
5044 if (! peer_group_active (peer) ||
5045 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
5046 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
5047
Paul Jakma0df7c912008-07-21 21:02:49 +00005048 /* Password. */
5049 if (peer->password)
5050 if (!peer_group_active (peer)
5051 || ! g_peer->password
5052 || strcmp (peer->password, g_peer->password) != 0)
5053 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
5054 VTY_NEWLINE);
5055
paul718e3742002-12-13 20:15:29 +00005056 /* BGP port. */
5057 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00005058 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00005059 VTY_NEWLINE);
5060
5061 /* Local interface name. */
5062 if (peer->ifname)
5063 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
5064 VTY_NEWLINE);
5065
5066 /* Passive. */
5067 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
5068 if (! peer_group_active (peer) ||
5069 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
5070 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
5071
5072 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00005073 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00005074 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00005075 if (! peer_group_active (peer) ||
5076 g_peer->ttl != peer->ttl)
5077 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
5078 VTY_NEWLINE);
5079
Nick Hilliardfa411a22011-03-23 15:33:17 +00005080 /* ttl-security hops */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00005081 if (peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00005082 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00005083 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00005084 peer->gtsm_hops, VTY_NEWLINE);
5085
hasso6ffd2072005-02-02 14:50:11 +00005086 /* disable-connected-check. */
5087 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00005088 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00005089 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
5090 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005091
5092 /* Update-source. */
5093 if (peer->update_if)
5094 if (! peer_group_active (peer) || ! g_peer->update_if
5095 || strcmp (g_peer->update_if, peer->update_if) != 0)
5096 vty_out (vty, " neighbor %s update-source %s%s", addr,
5097 peer->update_if, VTY_NEWLINE);
5098 if (peer->update_source)
5099 if (! peer_group_active (peer) || ! g_peer->update_source
5100 || sockunion_cmp (g_peer->update_source,
5101 peer->update_source) != 0)
5102 vty_out (vty, " neighbor %s update-source %s%s", addr,
5103 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
5104 VTY_NEWLINE);
5105
paul718e3742002-12-13 20:15:29 +00005106 /* advertisement-interval */
Daniel Walton0d7435f2015-10-22 11:35:20 +03005107 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV) &&
5108 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00005109 vty_out (vty, " neighbor %s advertisement-interval %d%s",
5110 addr, peer->v_routeadv, VTY_NEWLINE);
5111
5112 /* timers. */
5113 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
5114 && ! peer_group_active (peer))
5115 vty_out (vty, " neighbor %s timers %d %d%s", addr,
5116 peer->keepalive, peer->holdtime, VTY_NEWLINE);
5117
Daniel Walton0d7435f2015-10-22 11:35:20 +03005118 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT) &&
5119 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00005120 vty_out (vty, " neighbor %s timers connect %d%s", addr,
5121 peer->connect, VTY_NEWLINE);
5122
5123 /* Default weight. */
5124 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
5125 if (! peer_group_active (peer) ||
5126 g_peer->weight != peer->weight)
5127 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
5128 VTY_NEWLINE);
5129
paul718e3742002-12-13 20:15:29 +00005130 /* Dynamic capability. */
5131 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5132 if (! peer_group_active (peer) ||
5133 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5134 vty_out (vty, " neighbor %s capability dynamic%s", addr,
5135 VTY_NEWLINE);
5136
5137 /* dont capability negotiation. */
5138 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
5139 if (! peer_group_active (peer) ||
5140 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
5141 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
5142 VTY_NEWLINE);
5143
5144 /* override capability negotiation. */
5145 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5146 if (! peer_group_active (peer) ||
5147 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5148 vty_out (vty, " neighbor %s override-capability%s", addr,
5149 VTY_NEWLINE);
5150
5151 /* strict capability negotiation. */
5152 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5153 if (! peer_group_active (peer) ||
5154 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5155 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
5156 VTY_NEWLINE);
5157
Christian Franke15c71342012-11-19 11:17:31 +00005158 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
paul718e3742002-12-13 20:15:29 +00005159 {
5160 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5161 {
5162 if (peer->afc[AFI_IP][SAFI_UNICAST])
5163 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5164 }
5165 else
5166 {
5167 if (! peer->afc[AFI_IP][SAFI_UNICAST])
5168 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
5169 }
5170 }
5171 }
5172
5173
5174 /************************************
5175 ****** Per AF to the neighbor ******
5176 ************************************/
5177
5178 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
5179 {
5180 if (peer->af_group[afi][safi])
5181 vty_out (vty, " neighbor %s peer-group %s%s", addr,
5182 peer->group->name, VTY_NEWLINE);
5183 else
5184 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5185 }
5186
5187 /* ORF capability. */
5188 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5189 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5190 if (! peer->af_group[afi][safi])
5191 {
5192 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
5193
5194 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5195 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5196 vty_out (vty, " both");
5197 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
5198 vty_out (vty, " send");
5199 else
5200 vty_out (vty, " receive");
5201 vty_out (vty, "%s", VTY_NEWLINE);
5202 }
5203
5204 /* Route reflector client. */
5205 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
5206 && ! peer->af_group[afi][safi])
5207 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
5208 VTY_NEWLINE);
5209
5210 /* Nexthop self. */
5211 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
5212 && ! peer->af_group[afi][safi])
Timo Teräs9e7a53c2014-04-24 10:22:37 +03005213 vty_out (vty, " neighbor %s next-hop-self%s%s", addr,
5214 peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ?
5215 " all" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005216
5217 /* Remove private AS. */
5218 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
5219 && ! peer->af_group[afi][safi])
5220 vty_out (vty, " neighbor %s remove-private-AS%s",
5221 addr, VTY_NEWLINE);
5222
5223 /* send-community print. */
5224 if (! peer->af_group[afi][safi])
5225 {
5226 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5227 {
5228 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5229 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5230 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
5231 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5232 vty_out (vty, " neighbor %s send-community extended%s",
5233 addr, VTY_NEWLINE);
5234 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5235 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
5236 }
5237 else
5238 {
5239 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5240 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5241 vty_out (vty, " no neighbor %s send-community both%s",
5242 addr, VTY_NEWLINE);
5243 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5244 vty_out (vty, " no neighbor %s send-community extended%s",
5245 addr, VTY_NEWLINE);
5246 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5247 vty_out (vty, " no neighbor %s send-community%s",
5248 addr, VTY_NEWLINE);
5249 }
5250 }
5251
5252 /* Default information */
5253 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5254 && ! peer->af_group[afi][safi])
5255 {
5256 vty_out (vty, " neighbor %s default-originate", addr);
5257 if (peer->default_rmap[afi][safi].name)
5258 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5259 vty_out (vty, "%s", VTY_NEWLINE);
5260 }
5261
5262 /* Soft reconfiguration inbound. */
5263 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5264 if (! peer->af_group[afi][safi] ||
5265 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5266 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5267 VTY_NEWLINE);
5268
5269 /* maximum-prefix. */
5270 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5271 if (! peer->af_group[afi][safi]
5272 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005273 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005274 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5275 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005276 {
hasso0a486e52005-02-01 20:57:17 +00005277 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5278 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5279 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5280 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5281 vty_out (vty, " warning-only");
5282 if (peer->pmax_restart[afi][safi])
5283 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5284 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005285 }
paul718e3742002-12-13 20:15:29 +00005286
5287 /* Route server client. */
5288 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5289 && ! peer->af_group[afi][safi])
5290 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5291
Dylan Hall3cf12882011-10-27 15:28:17 +04005292 /* Nexthop-local unchanged. */
5293 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5294 && ! peer->af_group[afi][safi])
5295 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5296
paul718e3742002-12-13 20:15:29 +00005297 /* Allow AS in. */
5298 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5299 if (! peer_group_active (peer)
5300 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5301 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5302 {
5303 if (peer->allowas_in[afi][safi] == 3)
5304 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5305 else
5306 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5307 peer->allowas_in[afi][safi], VTY_NEWLINE);
5308 }
5309
5310 /* Filter. */
5311 bgp_config_write_filter (vty, peer, afi, safi);
5312
5313 /* atribute-unchanged. */
5314 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5315 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5316 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5317 && ! peer->af_group[afi][safi])
5318 {
5319 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5320 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5321 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5322 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5323 else
5324 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5325 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5326 " as-path" : "",
5327 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5328 " next-hop" : "",
5329 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5330 " med" : "", VTY_NEWLINE);
5331 }
5332}
5333
5334/* Display "address-family" configuration header. */
5335void
5336bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5337 int *write)
5338{
5339 if (*write)
5340 return;
5341
5342 if (afi == AFI_IP && safi == SAFI_UNICAST)
5343 return;
5344
5345 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5346
5347 if (afi == AFI_IP)
5348 {
5349 if (safi == SAFI_MULTICAST)
5350 vty_out (vty, "ipv4 multicast");
5351 else if (safi == SAFI_MPLS_VPN)
Lou Bergera3fda882016-01-12 13:42:04 -05005352 vty_out (vty, "vpnv4");
5353 else if (safi == SAFI_ENCAP)
5354 vty_out (vty, "encap");
paul718e3742002-12-13 20:15:29 +00005355 }
5356 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005357 {
Lou Berger13c378d2016-01-12 13:41:56 -05005358 if (safi == SAFI_MPLS_VPN)
5359 vty_out (vty, "vpnv6");
Lou Bergera3fda882016-01-12 13:42:04 -05005360 else if (safi == SAFI_ENCAP)
5361 vty_out (vty, "encapv6");
Lou Berger13c378d2016-01-12 13:41:56 -05005362 else
5363 {
5364 vty_out (vty, "ipv6");
5365 if (safi == SAFI_MULTICAST)
5366 vty_out (vty, " multicast");
5367 }
Paul Jakma37a217a2007-04-10 19:20:29 +00005368 }
paul718e3742002-12-13 20:15:29 +00005369
5370 vty_out (vty, "%s", VTY_NEWLINE);
5371
5372 *write = 1;
5373}
5374
5375/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005376static int
paul718e3742002-12-13 20:15:29 +00005377bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5378 safi_t safi)
5379{
5380 int write = 0;
5381 struct peer *peer;
5382 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005383 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005384
5385 bgp_config_write_network (vty, bgp, afi, safi, &write);
5386
5387 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5388
paul1eb8ef22005-04-07 07:30:20 +00005389 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005390 {
5391 if (group->conf->afc[afi][safi])
5392 {
5393 bgp_config_write_family_header (vty, afi, safi, &write);
5394 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5395 }
5396 }
paul1eb8ef22005-04-07 07:30:20 +00005397 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005398 {
5399 if (peer->afc[afi][safi])
5400 {
5401 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5402 {
5403 bgp_config_write_family_header (vty, afi, safi, &write);
5404 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5405 }
5406 }
5407 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005408
5409 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5410
Roman Hoog Antink6184c392014-03-17 14:01:42 +01005411 bgp_config_write_distance (vty, bgp, afi, safi, &write);
5412
paul718e3742002-12-13 20:15:29 +00005413 if (write)
5414 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5415
5416 return write;
5417}
5418
5419int
5420bgp_config_write (struct vty *vty)
5421{
5422 int write = 0;
5423 struct bgp *bgp;
5424 struct peer_group *group;
5425 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005426 struct listnode *node, *nnode;
5427 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005428
5429 /* BGP Multiple instance. */
5430 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5431 {
5432 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5433 write++;
5434 }
5435
5436 /* BGP Config type. */
5437 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5438 {
5439 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5440 write++;
5441 }
5442
5443 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005444 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005445 {
5446 if (write)
5447 vty_out (vty, "!%s", VTY_NEWLINE);
5448
5449 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005450 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005451
5452 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5453 {
5454 if (bgp->name)
5455 vty_out (vty, " view %s", bgp->name);
5456 }
5457 vty_out (vty, "%s", VTY_NEWLINE);
5458
5459 /* No Synchronization */
5460 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5461 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5462
5463 /* BGP fast-external-failover. */
5464 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5465 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5466
5467 /* BGP router ID. */
5468 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5469 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5470 VTY_NEWLINE);
5471
paul848973c2003-08-13 00:32:49 +00005472 /* BGP log-neighbor-changes. */
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07005473 if (!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5474 vty_out (vty, " no bgp log-neighbor-changes%s", VTY_NEWLINE);
paul848973c2003-08-13 00:32:49 +00005475
paul718e3742002-12-13 20:15:29 +00005476 /* BGP configuration. */
5477 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5478 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5479
5480 /* BGP default ipv4-unicast. */
5481 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5482 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5483
5484 /* BGP default local-preference. */
5485 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5486 vty_out (vty, " bgp default local-preference %d%s",
5487 bgp->default_local_pref, VTY_NEWLINE);
5488
5489 /* BGP client-to-client reflection. */
5490 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5491 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5492
5493 /* BGP cluster ID. */
5494 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5495 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5496 VTY_NEWLINE);
5497
hassoe0701b72004-05-20 09:19:34 +00005498 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005499 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005500 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5501 VTY_NEWLINE);
5502
5503 /* Confederation peer */
5504 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005505 {
hassoe0701b72004-05-20 09:19:34 +00005506 int i;
paul718e3742002-12-13 20:15:29 +00005507
hassoe0701b72004-05-20 09:19:34 +00005508 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005509
hassoe0701b72004-05-20 09:19:34 +00005510 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005511 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005512
hassoe0701b72004-05-20 09:19:34 +00005513 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005514 }
5515
5516 /* BGP enforce-first-as. */
5517 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5518 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5519
5520 /* BGP deterministic-med. */
5521 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5522 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005523
5524 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005525 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5526 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5527 bgp->stalepath_time, VTY_NEWLINE);
Philippe Guibert4afa3dd2016-05-24 16:52:02 +02005528 if (bgp->restart_time != BGP_DEFAULT_RESTART_TIME)
5529 vty_out (vty, " bgp graceful-restart restart-time %d%s",
5530 bgp->restart_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005531 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5532 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5533
paul718e3742002-12-13 20:15:29 +00005534 /* BGP bestpath method. */
5535 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5536 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005537 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5538 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
Pradosh Mohapatra2fdd4552013-09-07 07:02:36 +00005539 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
5540 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
5541 }
Dinesh Dutt083e5e22015-11-09 20:21:54 -05005542 if (bgp_flag_check (bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
5543 vty_out (vty, " bgp route-reflector allow-outbound-policy%s",
5544 VTY_NEWLINE);
5545 }
paul718e3742002-12-13 20:15:29 +00005546 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5547 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5548 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5549 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5550 {
5551 vty_out (vty, " bgp bestpath med");
5552 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5553 vty_out (vty, " confed");
5554 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5555 vty_out (vty, " missing-as-worst");
5556 vty_out (vty, "%s", VTY_NEWLINE);
5557 }
5558
5559 /* BGP network import check. */
5560 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5561 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5562
5563 /* BGP scan interval. */
5564 bgp_config_write_scan_time (vty);
5565
5566 /* BGP flag dampening. */
5567 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5568 BGP_CONFIG_DAMPENING))
5569 bgp_config_write_damp (vty);
5570
5571 /* BGP static route configuration. */
5572 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5573
5574 /* BGP redistribute configuration. */
5575 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5576
5577 /* BGP timers configuration. */
5578 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5579 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5580 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5581 bgp->default_holdtime, VTY_NEWLINE);
5582
5583 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005584 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005585 {
5586 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5587 }
5588
5589 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005590 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005591 {
5592 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5593 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5594 }
5595
Josh Bailey165b5ff2011-07-20 20:43:22 -07005596 /* maximum-paths */
5597 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5598
paul718e3742002-12-13 20:15:29 +00005599 /* Distance configuration. */
Roman Hoog Antink6184c392014-03-17 14:01:42 +01005600 bgp_config_write_distance (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
paul718e3742002-12-13 20:15:29 +00005601
5602 /* No auto-summary */
5603 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5604 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5605
5606 /* IPv4 multicast configuration. */
5607 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5608
5609 /* IPv4 VPN configuration. */
5610 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5611
Lou Bergera3fda882016-01-12 13:42:04 -05005612 /* ENCAPv4 configuration. */
5613 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_ENCAP);
5614
paul718e3742002-12-13 20:15:29 +00005615 /* IPv6 unicast configuration. */
5616 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5617
Paul Jakma37a217a2007-04-10 19:20:29 +00005618 /* IPv6 multicast configuration. */
5619 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5620
Lou Berger13c378d2016-01-12 13:41:56 -05005621 /* IPv6 VPN configuration. */
5622 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MPLS_VPN);
5623
Lou Bergera3fda882016-01-12 13:42:04 -05005624 /* ENCAPv6 configuration. */
5625 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_ENCAP);
5626
5627 vty_out (vty, " exit%s", VTY_NEWLINE);
5628
paul718e3742002-12-13 20:15:29 +00005629 write++;
5630 }
5631 return write;
5632}
5633
5634void
paul94f2b392005-06-28 12:44:16 +00005635bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005636{
5637 memset (&bgp_master, 0, sizeof (struct bgp_master));
5638
5639 bm = &bgp_master;
5640 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005641 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005642 bm->port = BGP_PORT_DEFAULT;
5643 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005644 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005645}
paul200df112005-06-01 11:17:05 +00005646
David Lamparter6b0655a2014-06-04 06:53:35 +02005647
paul718e3742002-12-13 20:15:29 +00005648void
paul94f2b392005-06-28 12:44:16 +00005649bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005650{
paul718e3742002-12-13 20:15:29 +00005651 /* BGP VTY commands installation. */
5652 bgp_vty_init ();
5653
paul718e3742002-12-13 20:15:29 +00005654 /* Init zebra. */
Donald Sharp774914f2015-10-14 08:50:39 -04005655 bgp_zebra_init (bm->master);
paul718e3742002-12-13 20:15:29 +00005656
5657 /* BGP inits. */
5658 bgp_attr_init ();
5659 bgp_debug_init ();
5660 bgp_dump_init ();
5661 bgp_route_init ();
5662 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005663 bgp_address_init ();
paul718e3742002-12-13 20:15:29 +00005664 bgp_scan_init ();
5665 bgp_mplsvpn_init ();
Lou Berger298cc2f2016-01-12 13:42:02 -05005666 bgp_encap_init ();
paul718e3742002-12-13 20:15:29 +00005667
5668 /* Access list initialize. */
5669 access_list_init ();
5670 access_list_add_hook (peer_distribute_update);
5671 access_list_delete_hook (peer_distribute_update);
5672
5673 /* Filter list initialize. */
5674 bgp_filter_init ();
5675 as_list_add_hook (peer_aslist_update);
5676 as_list_delete_hook (peer_aslist_update);
5677
5678 /* Prefix list initialize.*/
5679 prefix_list_init ();
5680 prefix_list_add_hook (peer_prefix_list_update);
5681 prefix_list_delete_hook (peer_prefix_list_update);
5682
5683 /* Community list initialize. */
5684 bgp_clist = community_list_init ();
5685
5686#ifdef HAVE_SNMP
5687 bgp_snmp_init ();
5688#endif /* HAVE_SNMP */
5689}
paul545acaf2004-04-20 15:13:15 +00005690
5691void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005692bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005693{
paul545acaf2004-04-20 15:13:15 +00005694 struct bgp *bgp;
5695 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005696 struct listnode *node, *nnode;
5697 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005698
paul1eb8ef22005-04-07 07:30:20 +00005699 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5700 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005701 if (peer->status == Established)
5702 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5703 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005704
paul545acaf2004-04-20 15:13:15 +00005705 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005706
paule210cf92005-06-15 19:15:35 +00005707 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005708 {
5709 work_queue_free (bm->process_main_queue);
5710 bm->process_main_queue = NULL;
5711 }
paule210cf92005-06-15 19:15:35 +00005712 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005713 {
5714 work_queue_free (bm->process_rsclient_queue);
5715 bm->process_rsclient_queue = NULL;
5716 }
paul545acaf2004-04-20 15:13:15 +00005717}