blob: 010e224e7935caa24edfcc265683e5327bcddc85 [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 ();
Daniel Walton5bcd7542015-05-19 17:58:10 -0700871
872 /* We use a larger buffer for peer->work in the event that:
873 * - We RX a BGP_UPDATE where the attributes alone are just
874 * under BGP_MAX_PACKET_SIZE
875 * - The user configures an outbound route-map that does many as-path
876 * prepends or adds many communities. At most they can have CMD_ARGC_MAX
877 * args in a route-map so there is a finite limit on how large they can
878 * make the attributes.
879 *
880 * Having a buffer with BGP_MAX_PACKET_SIZE_OVERFLOW allows us to avoid bounds
881 * checking for every single attribute as we construct an UPDATE.
882 */
883 peer->work = stream_new (BGP_MAX_PACKET_SIZE + BGP_MAX_PACKET_SIZE_OVERFLOW);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000884 peer->scratch = stream_new (BGP_MAX_PACKET_SIZE);
paul718e3742002-12-13 20:15:29 +0000885
886 bgp_sync_init (peer);
887
888 /* Get service port number. */
889 sp = getservbyname ("bgp", "tcp");
890 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
891
892 return peer;
893}
894
895/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000896static struct peer *
paul718e3742002-12-13 20:15:29 +0000897peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
898 as_t remote_as, afi_t afi, safi_t safi)
899{
900 int active;
901 struct peer *peer;
902 char buf[SU_ADDRSTRLEN];
903
Paul Jakma6f585442006-10-22 19:13:07 +0000904 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000905 peer->su = *su;
906 peer->local_as = local_as;
907 peer->as = remote_as;
908 peer->local_id = bgp->router_id;
909 peer->v_holdtime = bgp->default_holdtime;
910 peer->v_keepalive = bgp->default_keepalive;
911 if (peer_sort (peer) == BGP_PEER_IBGP)
912 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
913 else
914 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000915
916 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000917 listnode_add_sort (bgp->peer, peer);
918
919 active = peer_active (peer);
920
921 if (afi && safi)
922 peer->afc[afi][safi] = 1;
923
Stephen Hemminger65957882010-01-15 16:22:10 +0300924 /* Last read and reset time set */
925 peer->readtime = peer->resettime = bgp_clock ();
paul848973c2003-08-13 00:32:49 +0000926
paul718e3742002-12-13 20:15:29 +0000927 /* Default TTL set. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000928 peer->ttl = (peer->sort == BGP_PEER_IBGP) ? 255 : 1;
paul718e3742002-12-13 20:15:29 +0000929
930 /* Make peer's address string. */
931 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000932 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000933
934 /* Set up peer's events and timers. */
935 if (! active && peer_active (peer))
936 bgp_timer_set (peer);
937
938 return peer;
939}
940
pauleb821182004-05-01 08:44:08 +0000941/* Make accept BGP peer. Called from bgp_accept (). */
942struct peer *
943peer_create_accept (struct bgp *bgp)
944{
945 struct peer *peer;
946
Paul Jakma6f585442006-10-22 19:13:07 +0000947 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000948
949 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000950 listnode_add_sort (bgp->peer, peer);
951
952 return peer;
953}
954
paul718e3742002-12-13 20:15:29 +0000955/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000956static void
paul718e3742002-12-13 20:15:29 +0000957peer_as_change (struct peer *peer, as_t as)
958{
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000959 bgp_peer_sort_t type;
Daniel Walton0d7435f2015-10-22 11:35:20 +0300960 struct peer *conf;
paul718e3742002-12-13 20:15:29 +0000961
962 /* Stop peer. */
963 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
964 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000965 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000966 {
967 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
968 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
969 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
970 }
paul718e3742002-12-13 20:15:29 +0000971 else
972 BGP_EVENT_ADD (peer, BGP_Stop);
973 }
974 type = peer_sort (peer);
975 peer->as = as;
976
paul848973c2003-08-13 00:32:49 +0000977 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
978 && ! bgp_confederation_peers_check (peer->bgp, as)
979 && peer->bgp->as != as)
980 peer->local_as = peer->bgp->confed_id;
981 else
982 peer->local_as = peer->bgp->as;
983
paul718e3742002-12-13 20:15:29 +0000984 /* Advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +0300985 conf = NULL;
986 if (peer->group)
987 conf = peer->group->conf;
988
989 if (conf && CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
990 peer->v_routeadv = conf->routeadv;
paul718e3742002-12-13 20:15:29 +0000991 else
Daniel Walton0d7435f2015-10-22 11:35:20 +0300992 if (peer_sort (peer) == BGP_PEER_IBGP)
993 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
994 else
995 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul718e3742002-12-13 20:15:29 +0000996
997 /* TTL reset */
998 if (peer_sort (peer) == BGP_PEER_IBGP)
999 peer->ttl = 255;
1000 else if (type == BGP_PEER_IBGP)
1001 peer->ttl = 1;
1002
1003 /* reflector-client reset */
1004 if (peer_sort (peer) != BGP_PEER_IBGP)
1005 {
1006 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
1007 PEER_FLAG_REFLECTOR_CLIENT);
1008 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
1009 PEER_FLAG_REFLECTOR_CLIENT);
1010 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
1011 PEER_FLAG_REFLECTOR_CLIENT);
Lou Berger298cc2f2016-01-12 13:42:02 -05001012 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_ENCAP],
1013 PEER_FLAG_REFLECTOR_CLIENT);
paul718e3742002-12-13 20:15:29 +00001014 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
1015 PEER_FLAG_REFLECTOR_CLIENT);
1016 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
1017 PEER_FLAG_REFLECTOR_CLIENT);
Lou Berger9da04bc2016-01-12 13:41:55 -05001018 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MPLS_VPN],
1019 PEER_FLAG_REFLECTOR_CLIENT);
Lou Berger298cc2f2016-01-12 13:42:02 -05001020 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_ENCAP],
1021 PEER_FLAG_REFLECTOR_CLIENT);
paul718e3742002-12-13 20:15:29 +00001022 }
1023
1024 /* local-as reset */
1025 if (peer_sort (peer) != BGP_PEER_EBGP)
1026 {
1027 peer->change_local_as = 0;
1028 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001029 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001030 }
1031}
1032
1033/* If peer does not exist, create new one. If peer already exists,
1034 set AS number to the peer. */
1035int
1036peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
1037 afi_t afi, safi_t safi)
1038{
1039 struct peer *peer;
1040 as_t local_as;
1041
1042 peer = peer_lookup (bgp, su);
1043
1044 if (peer)
1045 {
1046 /* When this peer is a member of peer-group. */
1047 if (peer->group)
1048 {
1049 if (peer->group->conf->as)
1050 {
1051 /* Return peer group's AS number. */
1052 *as = peer->group->conf->as;
1053 return BGP_ERR_PEER_GROUP_MEMBER;
1054 }
1055 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
1056 {
1057 if (bgp->as != *as)
1058 {
1059 *as = peer->as;
1060 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1061 }
1062 }
1063 else
1064 {
1065 if (bgp->as == *as)
1066 {
1067 *as = peer->as;
1068 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1069 }
1070 }
1071 }
1072
1073 /* Existing peer's AS number change. */
1074 if (peer->as != *as)
1075 peer_as_change (peer, *as);
1076 }
1077 else
1078 {
1079
1080 /* If the peer is not part of our confederation, and its not an
1081 iBGP peer then spoof the source AS */
1082 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1083 && ! bgp_confederation_peers_check (bgp, *as)
1084 && bgp->as != *as)
1085 local_as = bgp->confed_id;
1086 else
1087 local_as = bgp->as;
1088
1089 /* If this is IPv4 unicast configuration and "no bgp default
1090 ipv4-unicast" is specified. */
1091
1092 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1093 && afi == AFI_IP && safi == SAFI_UNICAST)
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001094 peer_create (su, bgp, local_as, *as, 0, 0);
paul718e3742002-12-13 20:15:29 +00001095 else
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001096 peer_create (su, bgp, local_as, *as, afi, safi);
paul718e3742002-12-13 20:15:29 +00001097 }
1098
1099 return 0;
1100}
1101
1102/* Activate the peer or peer group for specified AFI and SAFI. */
1103int
1104peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1105{
1106 int active;
1107
1108 if (peer->afc[afi][safi])
1109 return 0;
1110
1111 /* Activate the address family configuration. */
1112 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1113 peer->afc[afi][safi] = 1;
1114 else
1115 {
1116 active = peer_active (peer);
1117
1118 peer->afc[afi][safi] = 1;
1119
1120 if (! active && peer_active (peer))
1121 bgp_timer_set (peer);
1122 else
1123 {
1124 if (peer->status == Established)
1125 {
1126 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1127 {
1128 peer->afc_adv[afi][safi] = 1;
1129 bgp_capability_send (peer, afi, safi,
1130 CAPABILITY_CODE_MP,
1131 CAPABILITY_ACTION_SET);
1132 if (peer->afc_recv[afi][safi])
1133 {
1134 peer->afc_nego[afi][safi] = 1;
1135 bgp_announce_route (peer, afi, safi);
1136 }
1137 }
1138 else
hassoe0701b72004-05-20 09:19:34 +00001139 {
1140 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1141 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1142 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1143 }
paul718e3742002-12-13 20:15:29 +00001144 }
1145 }
1146 }
1147 return 0;
1148}
1149
1150int
1151peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1152{
1153 struct peer_group *group;
1154 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001155 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001156
1157 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1158 {
1159 group = peer->group;
1160
paul1eb8ef22005-04-07 07:30:20 +00001161 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001162 {
1163 if (peer1->af_group[afi][safi])
1164 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1165 }
1166 }
1167 else
1168 {
1169 if (peer->af_group[afi][safi])
1170 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1171 }
1172
1173 if (! peer->afc[afi][safi])
1174 return 0;
1175
1176 /* De-activate the address family configuration. */
1177 peer->afc[afi][safi] = 0;
1178 peer_af_flag_reset (peer, afi, safi);
1179
1180 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1181 {
1182 if (peer->status == Established)
1183 {
1184 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1185 {
1186 peer->afc_adv[afi][safi] = 0;
1187 peer->afc_nego[afi][safi] = 0;
1188
1189 if (peer_active_nego (peer))
1190 {
1191 bgp_capability_send (peer, afi, safi,
1192 CAPABILITY_CODE_MP,
1193 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001194 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001195 peer->pcount[afi][safi] = 0;
1196 }
1197 else
hassoe0701b72004-05-20 09:19:34 +00001198 {
1199 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1200 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1201 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1202 }
paul718e3742002-12-13 20:15:29 +00001203 }
1204 else
hassoe0701b72004-05-20 09:19:34 +00001205 {
1206 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1207 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1208 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1209 }
paul718e3742002-12-13 20:15:29 +00001210 }
1211 }
1212 return 0;
1213}
1214
David Lamparterdfb9bd72016-05-24 18:58:07 +02001215int
1216peer_afc_set (struct peer *peer, afi_t afi, safi_t safi, int enable)
1217{
1218 if (enable)
1219 return peer_activate (peer, afi, safi);
1220 else
1221 return peer_deactivate (peer, afi, safi);
1222}
1223
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001224static void
hasso93406d82005-02-02 14:40:33 +00001225peer_nsf_stop (struct peer *peer)
1226{
1227 afi_t afi;
1228 safi_t safi;
1229
1230 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1231 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1232
1233 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +04001234 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +00001235 peer->nsf[afi][safi] = 0;
1236
1237 if (peer->t_gr_restart)
1238 {
1239 BGP_TIMER_OFF (peer->t_gr_restart);
1240 if (BGP_DEBUG (events, EVENTS))
1241 zlog_debug ("%s graceful restart timer stopped", peer->host);
1242 }
1243 if (peer->t_gr_stale)
1244 {
1245 BGP_TIMER_OFF (peer->t_gr_stale);
1246 if (BGP_DEBUG (events, EVENTS))
1247 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1248 }
1249 bgp_clear_route_all (peer);
1250}
1251
Paul Jakmaca058a32006-09-14 02:58:49 +00001252/* Delete peer from confguration.
1253 *
1254 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1255 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1256 *
1257 * This function /should/ take care to be idempotent, to guard against
1258 * it being called multiple times through stray events that come in
1259 * that happen to result in this function being called again. That
1260 * said, getting here for a "Deleted" peer is a bug in the neighbour
1261 * FSM.
1262 */
paul718e3742002-12-13 20:15:29 +00001263int
1264peer_delete (struct peer *peer)
1265{
1266 int i;
1267 afi_t afi;
1268 safi_t safi;
1269 struct bgp *bgp;
1270 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001271 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001272
Paul Jakmaca058a32006-09-14 02:58:49 +00001273 assert (peer->status != Deleted);
1274
paul718e3742002-12-13 20:15:29 +00001275 bgp = peer->bgp;
1276
hasso93406d82005-02-02 14:40:33 +00001277 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1278 peer_nsf_stop (peer);
1279
Chris Caputo228da422009-07-18 05:44:03 +00001280 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001281 relationship. */
1282 if (peer->group)
1283 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001284 if ((pn = listnode_lookup (peer->group->peer, peer)))
1285 {
1286 peer = peer_unlock (peer); /* group->peer list reference */
1287 list_delete_node (peer->group->peer, pn);
1288 }
paul718e3742002-12-13 20:15:29 +00001289 peer->group = NULL;
1290 }
paul200df112005-06-01 11:17:05 +00001291
paul718e3742002-12-13 20:15:29 +00001292 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001293 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1294 * executed after peer structure is deleted.
1295 */
hassoe0701b72004-05-20 09:19:34 +00001296 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001297 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001298 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001299
1300 /* Password configuration */
1301 if (peer->password)
1302 {
1303 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1304 peer->password = NULL;
1305
1306 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1307 bgp_md5_set (peer);
1308 }
1309
Paul Jakmaca058a32006-09-14 02:58:49 +00001310 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001311
paul718e3742002-12-13 20:15:29 +00001312 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001313 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1314 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001315 {
Chris Caputo228da422009-07-18 05:44:03 +00001316 peer_unlock (peer); /* bgp peer list reference */
1317 list_delete_node (bgp->peer, pn);
1318 }
paul200df112005-06-01 11:17:05 +00001319
Chris Caputo228da422009-07-18 05:44:03 +00001320 if (peer_rsclient_active (peer)
1321 && (pn = listnode_lookup (bgp->rsclient, peer)))
1322 {
1323 peer_unlock (peer); /* rsclient list reference */
1324 list_delete_node (bgp->rsclient, pn);
1325
1326 /* Clear our own rsclient ribs. */
1327 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1328 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1329 if (CHECK_FLAG(peer->af_flags[afi][safi],
1330 PEER_FLAG_RSERVER_CLIENT))
1331 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001332 }
1333
1334 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1335 member of a peer_group. */
1336 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1337 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1338 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001339 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001340
paul200df112005-06-01 11:17:05 +00001341 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001342 if (peer->ibuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001343 {
1344 stream_free (peer->ibuf);
1345 peer->ibuf = NULL;
1346 }
1347
paul718e3742002-12-13 20:15:29 +00001348 if (peer->obuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001349 {
1350 stream_fifo_free (peer->obuf);
1351 peer->obuf = NULL;
1352 }
1353
paul718e3742002-12-13 20:15:29 +00001354 if (peer->work)
Daniel Walton363c9032015-10-21 06:42:54 -07001355 {
1356 stream_free (peer->work);
1357 peer->work = NULL;
1358 }
1359
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00001360 if (peer->scratch)
Daniel Walton363c9032015-10-21 06:42:54 -07001361 {
1362 stream_free(peer->scratch);
1363 peer->scratch = NULL;
1364 }
Paul Jakma18937402006-07-27 19:05:12 +00001365
paul718e3742002-12-13 20:15:29 +00001366 /* Local and remote addresses. */
1367 if (peer->su_local)
Daniel Walton363c9032015-10-21 06:42:54 -07001368 {
1369 sockunion_free (peer->su_local);
1370 peer->su_local = NULL;
1371 }
1372
paul718e3742002-12-13 20:15:29 +00001373 if (peer->su_remote)
Daniel Walton363c9032015-10-21 06:42:54 -07001374 {
1375 sockunion_free (peer->su_remote);
1376 peer->su_remote = NULL;
1377 }
paul200df112005-06-01 11:17:05 +00001378
paul718e3742002-12-13 20:15:29 +00001379 /* Free filter related memory. */
1380 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1381 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1382 {
1383 filter = &peer->filter[afi][safi];
1384
1385 for (i = FILTER_IN; i < FILTER_MAX; i++)
1386 {
1387 if (filter->dlist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001388 {
1389 free(filter->dlist[i].name);
1390 filter->dlist[i].name = NULL;
1391 }
1392
paul718e3742002-12-13 20:15:29 +00001393 if (filter->plist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001394 {
1395 free(filter->plist[i].name);
1396 filter->plist[i].name = NULL;
1397 }
1398
paul718e3742002-12-13 20:15:29 +00001399 if (filter->aslist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001400 {
1401 free(filter->aslist[i].name);
1402 filter->aslist[i].name = NULL;
1403 }
paul200df112005-06-01 11:17:05 +00001404 }
Daniel Walton363c9032015-10-21 06:42:54 -07001405
paul200df112005-06-01 11:17:05 +00001406 for (i = RMAP_IN; i < RMAP_MAX; i++)
1407 {
paul718e3742002-12-13 20:15:29 +00001408 if (filter->map[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001409 {
1410 free (filter->map[i].name);
1411 filter->map[i].name = NULL;
1412 }
paul718e3742002-12-13 20:15:29 +00001413 }
1414
1415 if (filter->usmap.name)
Daniel Walton363c9032015-10-21 06:42:54 -07001416 {
1417 free (filter->usmap.name);
1418 filter->usmap.name = NULL;
1419 }
paul718e3742002-12-13 20:15:29 +00001420
1421 if (peer->default_rmap[afi][safi].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001422 {
1423 free (peer->default_rmap[afi][safi].name);
1424 peer->default_rmap[afi][safi].name = NULL;
1425 }
paul718e3742002-12-13 20:15:29 +00001426 }
paul200df112005-06-01 11:17:05 +00001427
Lou Berger82dd7072016-01-12 13:41:57 -05001428 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETING))
1429 bgp_peer_clear_node_queue_drain_immediate(peer);
1430
paul200df112005-06-01 11:17:05 +00001431 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001432
1433 return 0;
1434}
David Lamparter6b0655a2014-06-04 06:53:35 +02001435
paul94f2b392005-06-28 12:44:16 +00001436static int
paul718e3742002-12-13 20:15:29 +00001437peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1438{
1439 return strcmp (g1->name, g2->name);
1440}
1441
1442/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001443static int
paul718e3742002-12-13 20:15:29 +00001444peer_group_active (struct peer *peer)
1445{
1446 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1447 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1448 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05001449 || peer->af_group[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00001450 || peer->af_group[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05001451 || peer->af_group[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05001452 || peer->af_group[AFI_IP6][SAFI_MPLS_VPN]
1453 || peer->af_group[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00001454 return 1;
1455 return 0;
1456}
1457
1458/* Peer group cofiguration. */
1459static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001460peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001461{
1462 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1463 sizeof (struct peer_group));
1464}
1465
paul94f2b392005-06-28 12:44:16 +00001466static void
paul718e3742002-12-13 20:15:29 +00001467peer_group_free (struct peer_group *group)
1468{
1469 XFREE (MTYPE_PEER_GROUP, group);
1470}
1471
1472struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001473peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001474{
1475 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001476 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001477
paul1eb8ef22005-04-07 07:30:20 +00001478 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001479 {
1480 if (strcmp (group->name, name) == 0)
1481 return group;
1482 }
1483 return NULL;
1484}
1485
1486struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001487peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001488{
1489 struct peer_group *group;
1490
1491 group = peer_group_lookup (bgp, name);
1492 if (group)
1493 return group;
1494
1495 group = peer_group_new ();
1496 group->bgp = bgp;
1497 group->name = strdup (name);
1498 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001499 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001500 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1501 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001502 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001503 group->conf->group = group;
1504 group->conf->as = 0;
1505 group->conf->ttl = 1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001506 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001507 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1508 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1509 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1510 group->conf->keepalive = 0;
1511 group->conf->holdtime = 0;
1512 group->conf->connect = 0;
1513 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1514 listnode_add_sort (bgp->group, group);
1515
1516 return 0;
1517}
1518
paul94f2b392005-06-28 12:44:16 +00001519static void
paul718e3742002-12-13 20:15:29 +00001520peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1521 afi_t afi, safi_t safi)
1522{
1523 int in = FILTER_IN;
1524 int out = FILTER_OUT;
1525 struct peer *conf;
1526 struct bgp_filter *pfilter;
1527 struct bgp_filter *gfilter;
1528
1529 conf = group->conf;
1530 pfilter = &peer->filter[afi][safi];
1531 gfilter = &conf->filter[afi][safi];
1532
1533 /* remote-as */
1534 if (conf->as)
1535 peer->as = conf->as;
1536
1537 /* remote-as */
1538 if (conf->change_local_as)
1539 peer->change_local_as = conf->change_local_as;
1540
1541 /* TTL */
1542 peer->ttl = conf->ttl;
1543
Nick Hilliardfa411a22011-03-23 15:33:17 +00001544 /* GTSM hops */
1545 peer->gtsm_hops = conf->gtsm_hops;
1546
paul718e3742002-12-13 20:15:29 +00001547 /* Weight */
1548 peer->weight = conf->weight;
1549
1550 /* peer flags apply */
1551 peer->flags = conf->flags;
1552 /* peer af_flags apply */
1553 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1554 /* peer config apply */
1555 peer->config = conf->config;
1556
1557 /* peer timers apply */
1558 peer->holdtime = conf->holdtime;
1559 peer->keepalive = conf->keepalive;
1560 peer->connect = conf->connect;
1561 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1562 peer->v_connect = conf->connect;
1563 else
1564 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1565
1566 /* advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +03001567 if (CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
1568 peer->v_routeadv = conf->routeadv;
paul718e3742002-12-13 20:15:29 +00001569 else
Daniel Walton0d7435f2015-10-22 11:35:20 +03001570 if (peer_sort (peer) == BGP_PEER_IBGP)
1571 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1572 else
1573 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul718e3742002-12-13 20:15:29 +00001574
Paul Jakma0df7c912008-07-21 21:02:49 +00001575 /* password apply */
Roman Hoog Antink0e4303d2013-01-18 13:52:03 +01001576 if (conf->password && !peer->password)
Paul Jakma0df7c912008-07-21 21:02:49 +00001577 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
Paul Jakma0df7c912008-07-21 21:02:49 +00001578
1579 bgp_md5_set (peer);
1580
paul718e3742002-12-13 20:15:29 +00001581 /* maximum-prefix */
1582 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001583 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001584 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001585
1586 /* allowas-in */
1587 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1588
paulfee0f4c2004-09-13 05:12:46 +00001589 /* route-server-client */
1590 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1591 {
1592 /* Make peer's RIB point to group's RIB. */
1593 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1594
1595 /* Import policy. */
1596 if (pfilter->map[RMAP_IMPORT].name)
1597 free (pfilter->map[RMAP_IMPORT].name);
1598 if (gfilter->map[RMAP_IMPORT].name)
1599 {
1600 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1601 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1602 }
1603 else
1604 {
1605 pfilter->map[RMAP_IMPORT].name = NULL;
1606 pfilter->map[RMAP_IMPORT].map = NULL;
1607 }
1608
1609 /* Export policy. */
1610 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1611 {
1612 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1613 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1614 }
1615 }
1616
paul718e3742002-12-13 20:15:29 +00001617 /* default-originate route-map */
1618 if (conf->default_rmap[afi][safi].name)
1619 {
1620 if (peer->default_rmap[afi][safi].name)
1621 free (peer->default_rmap[afi][safi].name);
1622 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1623 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1624 }
1625
1626 /* update-source apply */
1627 if (conf->update_source)
1628 {
1629 if (peer->update_source)
1630 sockunion_free (peer->update_source);
1631 if (peer->update_if)
1632 {
1633 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1634 peer->update_if = NULL;
1635 }
1636 peer->update_source = sockunion_dup (conf->update_source);
1637 }
1638 else if (conf->update_if)
1639 {
1640 if (peer->update_if)
1641 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1642 if (peer->update_source)
1643 {
1644 sockunion_free (peer->update_source);
1645 peer->update_source = NULL;
1646 }
1647 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1648 }
1649
1650 /* inbound filter apply */
1651 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1652 {
1653 if (pfilter->dlist[in].name)
1654 free (pfilter->dlist[in].name);
1655 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1656 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1657 }
1658 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1659 {
1660 if (pfilter->plist[in].name)
1661 free (pfilter->plist[in].name);
1662 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1663 pfilter->plist[in].plist = gfilter->plist[in].plist;
1664 }
1665 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1666 {
1667 if (pfilter->aslist[in].name)
1668 free (pfilter->aslist[in].name);
1669 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1670 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1671 }
paulfee0f4c2004-09-13 05:12:46 +00001672 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001673 {
paulfee0f4c2004-09-13 05:12:46 +00001674 if (pfilter->map[RMAP_IN].name)
1675 free (pfilter->map[RMAP_IN].name);
1676 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1677 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001678 }
1679
1680 /* outbound filter apply */
1681 if (gfilter->dlist[out].name)
1682 {
1683 if (pfilter->dlist[out].name)
1684 free (pfilter->dlist[out].name);
1685 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1686 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1687 }
1688 else
1689 {
1690 if (pfilter->dlist[out].name)
1691 free (pfilter->dlist[out].name);
1692 pfilter->dlist[out].name = NULL;
1693 pfilter->dlist[out].alist = NULL;
1694 }
1695 if (gfilter->plist[out].name)
1696 {
1697 if (pfilter->plist[out].name)
1698 free (pfilter->plist[out].name);
1699 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1700 pfilter->plist[out].plist = gfilter->plist[out].plist;
1701 }
1702 else
1703 {
1704 if (pfilter->plist[out].name)
1705 free (pfilter->plist[out].name);
1706 pfilter->plist[out].name = NULL;
1707 pfilter->plist[out].plist = NULL;
1708 }
1709 if (gfilter->aslist[out].name)
1710 {
1711 if (pfilter->aslist[out].name)
1712 free (pfilter->aslist[out].name);
1713 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1714 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1715 }
1716 else
1717 {
1718 if (pfilter->aslist[out].name)
1719 free (pfilter->aslist[out].name);
1720 pfilter->aslist[out].name = NULL;
1721 pfilter->aslist[out].aslist = NULL;
1722 }
paulfee0f4c2004-09-13 05:12:46 +00001723 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001724 {
paulfee0f4c2004-09-13 05:12:46 +00001725 if (pfilter->map[RMAP_OUT].name)
1726 free (pfilter->map[RMAP_OUT].name);
1727 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1728 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001729 }
1730 else
1731 {
paulfee0f4c2004-09-13 05:12:46 +00001732 if (pfilter->map[RMAP_OUT].name)
1733 free (pfilter->map[RMAP_OUT].name);
1734 pfilter->map[RMAP_OUT].name = NULL;
1735 pfilter->map[RMAP_OUT].map = NULL;
1736 }
1737
1738 /* RS-client's import/export route-maps. */
1739 if (gfilter->map[RMAP_IMPORT].name)
1740 {
1741 if (pfilter->map[RMAP_IMPORT].name)
1742 free (pfilter->map[RMAP_IMPORT].name);
1743 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1744 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1745 }
1746 else
1747 {
1748 if (pfilter->map[RMAP_IMPORT].name)
1749 free (pfilter->map[RMAP_IMPORT].name);
1750 pfilter->map[RMAP_IMPORT].name = NULL;
1751 pfilter->map[RMAP_IMPORT].map = NULL;
1752 }
1753 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1754 {
1755 if (pfilter->map[RMAP_EXPORT].name)
1756 free (pfilter->map[RMAP_EXPORT].name);
1757 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1758 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001759 }
1760
1761 if (gfilter->usmap.name)
1762 {
1763 if (pfilter->usmap.name)
1764 free (pfilter->usmap.name);
1765 pfilter->usmap.name = strdup (gfilter->usmap.name);
1766 pfilter->usmap.map = gfilter->usmap.map;
1767 }
1768 else
1769 {
1770 if (pfilter->usmap.name)
1771 free (pfilter->usmap.name);
1772 pfilter->usmap.name = NULL;
1773 pfilter->usmap.map = NULL;
1774 }
1775}
1776
1777/* Peer group's remote AS configuration. */
1778int
paulfd79ac92004-10-13 05:06:08 +00001779peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001780{
1781 struct peer_group *group;
1782 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001783 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001784
1785 group = peer_group_lookup (bgp, group_name);
1786 if (! group)
1787 return -1;
1788
1789 if (group->conf->as == *as)
1790 return 0;
1791
1792 /* When we setup peer-group AS number all peer group member's AS
1793 number must be updated to same number. */
1794 peer_as_change (group->conf, *as);
1795
paul1eb8ef22005-04-07 07:30:20 +00001796 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001797 {
1798 if (peer->as != *as)
1799 peer_as_change (peer, *as);
1800 }
1801
1802 return 0;
1803}
1804
1805int
1806peer_group_delete (struct peer_group *group)
1807{
1808 struct bgp *bgp;
1809 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001810 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001811
1812 bgp = group->bgp;
1813
paul1eb8ef22005-04-07 07:30:20 +00001814 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001815 {
paul718e3742002-12-13 20:15:29 +00001816 peer_delete (peer);
1817 }
1818 list_delete (group->peer);
1819
1820 free (group->name);
1821 group->name = NULL;
1822
1823 group->conf->group = NULL;
1824 peer_delete (group->conf);
1825
1826 /* Delete from all peer_group list. */
1827 listnode_delete (bgp->group, group);
1828
1829 peer_group_free (group);
1830
1831 return 0;
1832}
1833
1834int
1835peer_group_remote_as_delete (struct peer_group *group)
1836{
1837 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001838 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001839
1840 if (! group->conf->as)
1841 return 0;
1842
paul1eb8ef22005-04-07 07:30:20 +00001843 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001844 {
paul718e3742002-12-13 20:15:29 +00001845 peer_delete (peer);
1846 }
1847 list_delete_all_node (group->peer);
1848
1849 group->conf->as = 0;
1850
1851 return 0;
1852}
1853
1854/* Bind specified peer to peer group. */
1855int
1856peer_group_bind (struct bgp *bgp, union sockunion *su,
1857 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1858{
1859 struct peer *peer;
1860 int first_member = 0;
1861
1862 /* Check peer group's address family. */
1863 if (! group->conf->afc[afi][safi])
1864 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1865
1866 /* Lookup the peer. */
1867 peer = peer_lookup (bgp, su);
1868
1869 /* Create a new peer. */
1870 if (! peer)
1871 {
1872 if (! group->conf->as)
1873 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1874
1875 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1876 peer->group = group;
1877 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001878
Paul Jakmaca058a32006-09-14 02:58:49 +00001879 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001880 listnode_add (group->peer, peer);
1881 peer_group2peer_config_copy (group, peer, afi, safi);
1882
1883 return 0;
1884 }
1885
1886 /* When the peer already belongs to peer group, check the consistency. */
1887 if (peer->af_group[afi][safi])
1888 {
1889 if (strcmp (peer->group->name, group->name) != 0)
1890 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1891
1892 return 0;
1893 }
1894
1895 /* Check current peer group configuration. */
1896 if (peer_group_active (peer)
1897 && strcmp (peer->group->name, group->name) != 0)
1898 return BGP_ERR_PEER_GROUP_MISMATCH;
1899
1900 if (! group->conf->as)
1901 {
1902 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1903 && peer_sort (group->conf) != peer_sort (peer))
1904 {
1905 if (as)
1906 *as = peer->as;
1907 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1908 }
1909
1910 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1911 first_member = 1;
1912 }
1913
1914 peer->af_group[afi][safi] = 1;
1915 peer->afc[afi][safi] = 1;
1916 if (! peer->group)
1917 {
1918 peer->group = group;
paul200df112005-06-01 11:17:05 +00001919
Paul Jakmaca058a32006-09-14 02:58:49 +00001920 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001921 listnode_add (group->peer, peer);
1922 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001923 else
1924 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001925
1926 if (first_member)
1927 {
1928 /* Advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +03001929 if (! CHECK_FLAG (group->conf->config, PEER_CONFIG_ROUTEADV))
1930 {
1931 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1932 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1933 else
1934 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1935 }
paul718e3742002-12-13 20:15:29 +00001936
1937 /* ebgp-multihop reset */
1938 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1939 group->conf->ttl = 255;
1940
1941 /* local-as reset */
1942 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1943 {
1944 group->conf->change_local_as = 0;
1945 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001946 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001947 }
1948 }
paulfee0f4c2004-09-13 05:12:46 +00001949
1950 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1951 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001952 struct listnode *pn;
1953
paulfee0f4c2004-09-13 05:12:46 +00001954 /* If it's not configured as RSERVER_CLIENT in any other address
1955 family, without being member of a peer_group, remove it from
1956 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001957 if (! peer_rsclient_active (peer)
1958 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001959 {
1960 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001961 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001962
1963 /* Clear our own rsclient rib for this afi/safi. */
1964 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001965 }
paulfee0f4c2004-09-13 05:12:46 +00001966
Paul Jakmab608d5b2008-07-02 02:12:07 +00001967 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001968
1969 /* Import policy. */
1970 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1971 {
1972 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1973 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1974 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1975 }
1976
1977 /* Export policy. */
1978 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1979 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1980 {
1981 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1982 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1983 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1984 }
1985 }
1986
paul718e3742002-12-13 20:15:29 +00001987 peer_group2peer_config_copy (group, peer, afi, safi);
1988
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001989 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001990 {
1991 peer->last_reset = PEER_DOWN_RMAP_BIND;
1992 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1993 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1994 }
paul718e3742002-12-13 20:15:29 +00001995 else
1996 BGP_EVENT_ADD (peer, BGP_Stop);
1997
1998 return 0;
1999}
2000
2001int
2002peer_group_unbind (struct bgp *bgp, struct peer *peer,
2003 struct peer_group *group, afi_t afi, safi_t safi)
2004{
2005 if (! peer->af_group[afi][safi])
2006 return 0;
2007
2008 if (group != peer->group)
2009 return BGP_ERR_PEER_GROUP_MISMATCH;
2010
2011 peer->af_group[afi][safi] = 0;
2012 peer->afc[afi][safi] = 0;
2013 peer_af_flag_reset (peer, afi, safi);
2014
paulfee0f4c2004-09-13 05:12:46 +00002015 if (peer->rib[afi][safi])
2016 peer->rib[afi][safi] = NULL;
2017
paul718e3742002-12-13 20:15:29 +00002018 if (! peer_group_active (peer))
2019 {
Paul Jakmaca058a32006-09-14 02:58:49 +00002020 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00002021 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00002022 listnode_delete (group->peer, peer);
2023 peer->group = NULL;
2024 if (group->conf->as)
2025 {
2026 peer_delete (peer);
2027 return 0;
2028 }
2029 peer_global_config_reset (peer);
2030 }
2031
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002032 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002033 {
2034 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
2035 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2036 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2037 }
paul718e3742002-12-13 20:15:29 +00002038 else
2039 BGP_EVENT_ADD (peer, BGP_Stop);
2040
2041 return 0;
2042}
David Lamparter6b0655a2014-06-04 06:53:35 +02002043
Vipin Kumardd49eb12014-09-30 14:36:38 -07002044
2045static int
2046bgp_startup_timer_expire (struct thread *thread)
2047{
2048 struct bgp *bgp;
2049
2050 bgp = THREAD_ARG (thread);
2051 bgp->t_startup = NULL;
2052
2053 return 0;
2054}
2055
paul718e3742002-12-13 20:15:29 +00002056/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00002057static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002058bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002059{
2060 struct bgp *bgp;
2061 afi_t afi;
2062 safi_t safi;
2063
paul200df112005-06-01 11:17:05 +00002064 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
2065 return NULL;
2066
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002067 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00002068 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00002069 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00002070
2071 bgp->peer = list_new ();
2072 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
2073
2074 bgp->group = list_new ();
2075 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
2076
paulfee0f4c2004-09-13 05:12:46 +00002077 bgp->rsclient = list_new ();
2078 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
2079
paul718e3742002-12-13 20:15:29 +00002080 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2081 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2082 {
Paul Jakma64e580a2006-02-21 01:09:01 +00002083 bgp->route[afi][safi] = bgp_table_init (afi, safi);
2084 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
2085 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07002086 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
2087 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00002088 }
2089
2090 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
2091 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
2092 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00002093 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
2094 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07002095 bgp_flag_set (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES);
paul718e3742002-12-13 20:15:29 +00002096
2097 bgp->as = *as;
2098
2099 if (name)
2100 bgp->name = strdup (name);
2101
Donald Sharp774914f2015-10-14 08:50:39 -04002102 THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire,
Vipin Kumardd49eb12014-09-30 14:36:38 -07002103 bgp, bgp->restart_time);
2104
paul718e3742002-12-13 20:15:29 +00002105 return bgp;
2106}
2107
2108/* Return first entry of BGP. */
2109struct bgp *
paul94f2b392005-06-28 12:44:16 +00002110bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00002111{
Lou Berger056f3762013-04-10 12:30:04 -07002112 if (bm && bm->bgp && bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00002113 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00002114 return NULL;
2115}
2116
2117/* Lookup BGP entry. */
2118struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002119bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00002120{
2121 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002122 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002123
paul1eb8ef22005-04-07 07:30:20 +00002124 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002125 if (bgp->as == as
2126 && ((bgp->name == NULL && name == NULL)
2127 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
2128 return bgp;
2129 return NULL;
2130}
2131
2132/* Lookup BGP structure by view name. */
2133struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002134bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002135{
2136 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002137 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002138
paul1eb8ef22005-04-07 07:30:20 +00002139 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002140 if ((bgp->name == NULL && name == NULL)
2141 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2142 return bgp;
2143 return NULL;
2144}
2145
2146/* Called from VTY commands. */
2147int
paulfd79ac92004-10-13 05:06:08 +00002148bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002149{
2150 struct bgp *bgp;
2151
2152 /* Multiple instance check. */
2153 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2154 {
2155 if (name)
2156 bgp = bgp_lookup_by_name (name);
2157 else
2158 bgp = bgp_get_default ();
2159
2160 /* Already exists. */
2161 if (bgp)
2162 {
2163 if (bgp->as != *as)
2164 {
2165 *as = bgp->as;
2166 return BGP_ERR_INSTANCE_MISMATCH;
2167 }
2168 *bgp_val = bgp;
2169 return 0;
2170 }
2171 }
2172 else
2173 {
2174 /* BGP instance name can not be specified for single instance. */
2175 if (name)
2176 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2177
2178 /* Get default BGP structure if exists. */
2179 bgp = bgp_get_default ();
2180
2181 if (bgp)
2182 {
2183 if (bgp->as != *as)
2184 {
2185 *as = bgp->as;
2186 return BGP_ERR_AS_MISMATCH;
2187 }
2188 *bgp_val = bgp;
2189 return 0;
2190 }
2191 }
2192
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002193 bgp = bgp_create (as, name);
2194 bgp_router_id_set(bgp, &router_id_zebra);
2195 *bgp_val = bgp;
2196
Paul Jakmaad12dde2012-06-13 22:50:07 +01002197 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002198 if (list_isempty(bm->bgp)
2199 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002200 {
2201 if (bgp_socket (bm->port, bm->address) < 0)
2202 return BGP_ERR_INVALID_VALUE;
2203 }
2204
paul718e3742002-12-13 20:15:29 +00002205 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002206
2207 return 0;
2208}
2209
2210/* Delete BGP instance. */
2211int
2212bgp_delete (struct bgp *bgp)
2213{
2214 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002215 struct peer_group *group;
Denil Vira57cd5e72015-08-10 12:46:14 -07002216 struct listnode *node, *pnode;
2217 struct listnode *next, *pnext;
paul718e3742002-12-13 20:15:29 +00002218 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002219 int i;
2220
Lou Berger82dd7072016-01-12 13:41:57 -05002221 SET_FLAG(bgp->flags, BGP_FLAG_DELETING);
2222
David Lampartercffe7802014-12-07 03:27:13 +01002223 THREAD_OFF (bgp->t_startup);
2224
Daniel Walton9e518dd2015-05-19 17:47:26 -07002225 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2226 {
2227 if (peer->status == Established ||
2228 peer->status == OpenSent ||
2229 peer->status == OpenConfirm)
2230 {
2231 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2232 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
2233 }
2234 }
2235
paul718e3742002-12-13 20:15:29 +00002236 /* Delete static route. */
2237 bgp_static_delete (bgp);
2238
2239 /* Unset redistribution. */
2240 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2241 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2242 if (i != ZEBRA_ROUTE_BGP)
2243 bgp_redistribute_unset (bgp, afi, i);
2244
paul1eb8ef22005-04-07 07:30:20 +00002245 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002246 {
2247 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2248 {
2249 /* Send notify to remote peer. */
2250 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2251 }
2252
2253 peer_delete (peer);
2254 }
paul718e3742002-12-13 20:15:29 +00002255
Chris Caputo228da422009-07-18 05:44:03 +00002256 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002257 {
Denil Vira57cd5e72015-08-10 12:46:14 -07002258 for (ALL_LIST_ELEMENTS (group->peer, pnode, pnext, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002259 {
2260 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2261 {
2262 /* Send notify to remote peer. */
2263 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2264 }
2265 }
2266 peer_group_delete (group);
2267 }
Chris Caputo228da422009-07-18 05:44:03 +00002268
2269 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002270
2271 if (bgp->peer_self) {
2272 peer_delete(bgp->peer_self);
2273 bgp->peer_self = NULL;
2274 }
Lou Berger82dd7072016-01-12 13:41:57 -05002275
2276 /*
2277 * Free pending deleted routes. Unfortunately, it also has to process
2278 * all the pending activity for other instances of struct bgp.
2279 *
2280 * This call was added to achieve clean memory allocation at exit,
2281 * for the sake of valgrind.
2282 */
2283 bgp_process_queues_drain_immediate();
2284
Paul Jakmafd35b942009-07-16 19:27:32 +01002285 /* Remove visibility via the master list - there may however still be
2286 * routes to be processed still referencing the struct bgp.
2287 */
2288 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002289 if (list_isempty(bm->bgp))
2290 bgp_close ();
2291
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002292 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002293
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002294 return 0;
2295}
2296
2297static void bgp_free (struct bgp *);
2298
2299void
2300bgp_lock (struct bgp *bgp)
2301{
2302 ++bgp->lock;
2303}
2304
2305void
2306bgp_unlock(struct bgp *bgp)
2307{
Chris Caputo228da422009-07-18 05:44:03 +00002308 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002309 if (--bgp->lock == 0)
2310 bgp_free (bgp);
2311}
2312
2313static void
2314bgp_free (struct bgp *bgp)
2315{
2316 afi_t afi;
2317 safi_t safi;
2318
2319 list_delete (bgp->group);
2320 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002321 list_delete (bgp->rsclient);
2322
paul718e3742002-12-13 20:15:29 +00002323 if (bgp->name)
2324 free (bgp->name);
2325
2326 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2327 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2328 {
2329 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002330 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002331 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002332 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002333 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002334 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002335 }
2336 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002337}
David Lamparter6b0655a2014-06-04 06:53:35 +02002338
paul718e3742002-12-13 20:15:29 +00002339struct peer *
2340peer_lookup (struct bgp *bgp, union sockunion *su)
2341{
2342 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002343 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002344
Steve Hillfc4dc592009-07-28 17:54:35 +01002345 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002346 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002347 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2348 if (sockunion_same (&peer->su, su)
2349 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2350 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002351 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002352 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002353 {
2354 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002355
Paul Jakma2158ad22009-07-28 18:10:55 +01002356 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2357 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2358 if (sockunion_same (&peer->su, su)
2359 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2360 return peer;
paul718e3742002-12-13 20:15:29 +00002361 }
2362 return NULL;
2363}
2364
2365struct peer *
2366peer_lookup_with_open (union sockunion *su, as_t remote_as,
2367 struct in_addr *remote_id, int *as)
2368{
2369 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002370 struct listnode *node;
2371 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002372 struct bgp *bgp;
2373
Steve Hillfc4dc592009-07-28 17:54:35 +01002374 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002375 return NULL;
2376
Paul Jakma9d878772009-08-05 16:25:16 +01002377 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002378 {
Paul Jakma9d878772009-08-05 16:25:16 +01002379 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2380 {
2381 if (sockunion_same (&peer->su, su)
2382 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2383 {
2384 if (peer->as == remote_as
2385 && peer->remote_id.s_addr == remote_id->s_addr)
2386 return peer;
2387 if (peer->as == remote_as)
2388 *as = 1;
2389 }
2390 }
2391
2392 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2393 {
2394 if (sockunion_same (&peer->su, su)
2395 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2396 {
2397 if (peer->as == remote_as
2398 && peer->remote_id.s_addr == 0)
2399 return peer;
2400 if (peer->as == remote_as)
2401 *as = 1;
2402 }
2403 }
paul718e3742002-12-13 20:15:29 +00002404 }
2405 return NULL;
2406}
David Lamparter6b0655a2014-06-04 06:53:35 +02002407
paul718e3742002-12-13 20:15:29 +00002408/* If peer is configured at least one address family return 1. */
2409int
2410peer_active (struct peer *peer)
2411{
2412 if (peer->afc[AFI_IP][SAFI_UNICAST]
2413 || peer->afc[AFI_IP][SAFI_MULTICAST]
2414 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05002415 || peer->afc[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00002416 || peer->afc[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05002417 || peer->afc[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05002418 || peer->afc[AFI_IP6][SAFI_MPLS_VPN]
2419 || peer->afc[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00002420 return 1;
2421 return 0;
2422}
2423
2424/* If peer is negotiated at least one address family return 1. */
2425int
2426peer_active_nego (struct peer *peer)
2427{
2428 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2429 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2430 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05002431 || peer->afc_nego[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00002432 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05002433 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05002434 || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
2435 || peer->afc_nego[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00002436 return 1;
2437 return 0;
2438}
David Lamparter6b0655a2014-06-04 06:53:35 +02002439
paul718e3742002-12-13 20:15:29 +00002440/* peer_flag_change_type. */
2441enum peer_change_type
2442{
2443 peer_change_none,
2444 peer_change_reset,
2445 peer_change_reset_in,
2446 peer_change_reset_out,
2447};
2448
paul94f2b392005-06-28 12:44:16 +00002449static void
paul718e3742002-12-13 20:15:29 +00002450peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2451 enum peer_change_type type)
2452{
2453 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2454 return;
2455
Stephen Hemmingerd9d4ae52010-01-13 00:32:39 +00002456 if (peer->status != Established)
2457 return;
2458
paul718e3742002-12-13 20:15:29 +00002459 if (type == peer_change_reset)
2460 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2461 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2462 else if (type == peer_change_reset_in)
2463 {
2464 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2465 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2466 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2467 else
2468 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2469 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2470 }
2471 else if (type == peer_change_reset_out)
2472 bgp_announce_route (peer, afi, safi);
2473}
2474
2475struct peer_flag_action
2476{
2477 /* Peer's flag. */
2478 u_int32_t flag;
2479
2480 /* This flag can be set for peer-group member. */
2481 u_char not_for_member;
2482
2483 /* Action when the flag is changed. */
2484 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002485
2486 /* Peer down cause */
2487 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002488};
2489
Stephen Hemminger03621952009-07-21 16:27:20 -07002490static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002491 {
2492 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2493 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2494 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2495 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2496 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002497 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002498 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002499 { 0, 0, 0 }
2500 };
2501
Stephen Hemminger03621952009-07-21 16:27:20 -07002502static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002503 {
2504 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2505 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2506 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2507 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2508 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2509 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2510 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2511 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2512 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2513 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2514 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2515 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2516 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002517 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
Timo Teräs9e7a53c2014-04-24 10:22:37 +03002518 { PEER_FLAG_NEXTHOP_SELF_ALL, 1, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002519 { 0, 0, 0 }
2520 };
2521
2522/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002523static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002524peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002525 struct peer_flag_action *action, u_int32_t flag)
2526{
2527 int i;
2528 int found = 0;
2529 int reset_in = 0;
2530 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002531 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002532
2533 /* Check peer's frag action. */
2534 for (i = 0; i < size; i++)
2535 {
2536 match = &action_list[i];
2537
2538 if (match->flag == 0)
2539 break;
2540
2541 if (match->flag & flag)
2542 {
2543 found = 1;
2544
2545 if (match->type == peer_change_reset_in)
2546 reset_in = 1;
2547 if (match->type == peer_change_reset_out)
2548 reset_out = 1;
2549 if (match->type == peer_change_reset)
2550 {
2551 reset_in = 1;
2552 reset_out = 1;
2553 }
2554 if (match->not_for_member)
2555 action->not_for_member = 1;
2556 }
2557 }
2558
2559 /* Set peer clear type. */
2560 if (reset_in && reset_out)
2561 action->type = peer_change_reset;
2562 else if (reset_in)
2563 action->type = peer_change_reset_in;
2564 else if (reset_out)
2565 action->type = peer_change_reset_out;
2566 else
2567 action->type = peer_change_none;
2568
2569 return found;
2570}
2571
paul94f2b392005-06-28 12:44:16 +00002572static void
paul718e3742002-12-13 20:15:29 +00002573peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2574{
2575 if (flag == PEER_FLAG_SHUTDOWN)
2576 {
2577 if (CHECK_FLAG (peer->flags, flag))
2578 {
hasso93406d82005-02-02 14:40:33 +00002579 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2580 peer_nsf_stop (peer);
2581
hasso0a486e52005-02-01 20:57:17 +00002582 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2583 if (peer->t_pmax_restart)
2584 {
2585 BGP_TIMER_OFF (peer->t_pmax_restart);
2586 if (BGP_DEBUG (events, EVENTS))
2587 zlog_debug ("%s Maximum-prefix restart timer canceled",
2588 peer->host);
2589 }
2590
hasso93406d82005-02-02 14:40:33 +00002591 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2592 peer_nsf_stop (peer);
2593
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002594 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002595 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2596 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2597 else
2598 BGP_EVENT_ADD (peer, BGP_Stop);
2599 }
2600 else
2601 {
2602 peer->v_start = BGP_INIT_START_TIMER;
2603 BGP_EVENT_ADD (peer, BGP_Stop);
2604 }
2605 }
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002606 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002607 {
hassoc9502432005-02-01 22:01:48 +00002608 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2609 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2610 else if (flag == PEER_FLAG_PASSIVE)
2611 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002612 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002613 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002614
hassoc9502432005-02-01 22:01:48 +00002615 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2616 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002617 }
2618 else
2619 BGP_EVENT_ADD (peer, BGP_Stop);
2620}
2621
2622/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002623static int
paul718e3742002-12-13 20:15:29 +00002624peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2625{
2626 int found;
2627 int size;
2628 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002629 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002630 struct peer_flag_action action;
2631
2632 memset (&action, 0, sizeof (struct peer_flag_action));
2633 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2634
2635 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2636
2637 /* No flag action is found. */
2638 if (! found)
2639 return BGP_ERR_INVALID_FLAG;
2640
2641 /* Not for peer-group member. */
2642 if (action.not_for_member && peer_group_active (peer))
2643 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2644
2645 /* When unset the peer-group member's flag we have to check
2646 peer-group configuration. */
2647 if (! set && peer_group_active (peer))
2648 if (CHECK_FLAG (peer->group->conf->flags, flag))
2649 {
2650 if (flag == PEER_FLAG_SHUTDOWN)
2651 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2652 else
2653 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2654 }
2655
2656 /* Flag conflict check. */
2657 if (set
2658 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2659 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2660 return BGP_ERR_PEER_FLAG_CONFLICT;
2661
2662 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2663 {
2664 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2665 return 0;
2666 if (! set && ! CHECK_FLAG (peer->flags, flag))
2667 return 0;
2668 }
2669
2670 if (set)
2671 SET_FLAG (peer->flags, flag);
2672 else
2673 UNSET_FLAG (peer->flags, flag);
2674
2675 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2676 {
2677 if (action.type == peer_change_reset)
2678 peer_flag_modify_action (peer, flag);
2679
2680 return 0;
2681 }
2682
2683 /* peer-group member updates. */
2684 group = peer->group;
2685
paul1eb8ef22005-04-07 07:30:20 +00002686 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002687 {
2688 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2689 continue;
2690
2691 if (! set && ! CHECK_FLAG (peer->flags, flag))
2692 continue;
2693
2694 if (set)
2695 SET_FLAG (peer->flags, flag);
2696 else
2697 UNSET_FLAG (peer->flags, flag);
2698
2699 if (action.type == peer_change_reset)
2700 peer_flag_modify_action (peer, flag);
2701 }
2702 return 0;
2703}
2704
2705int
2706peer_flag_set (struct peer *peer, u_int32_t flag)
2707{
2708 return peer_flag_modify (peer, flag, 1);
2709}
2710
2711int
2712peer_flag_unset (struct peer *peer, u_int32_t flag)
2713{
2714 return peer_flag_modify (peer, flag, 0);
2715}
2716
paul94f2b392005-06-28 12:44:16 +00002717static int
paul718e3742002-12-13 20:15:29 +00002718peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2719{
2720 if (peer->af_group[afi][safi])
2721 return 1;
2722 return 0;
2723}
2724
paul94f2b392005-06-28 12:44:16 +00002725static int
paul718e3742002-12-13 20:15:29 +00002726peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2727 int set)
2728{
2729 int found;
2730 int size;
paul1eb8ef22005-04-07 07:30:20 +00002731 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002732 struct peer_group *group;
2733 struct peer_flag_action action;
2734
2735 memset (&action, 0, sizeof (struct peer_flag_action));
2736 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2737
2738 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2739
2740 /* No flag action is found. */
2741 if (! found)
2742 return BGP_ERR_INVALID_FLAG;
2743
2744 /* Adress family must be activated. */
2745 if (! peer->afc[afi][safi])
2746 return BGP_ERR_PEER_INACTIVE;
2747
2748 /* Not for peer-group member. */
2749 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2750 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2751
2752 /* Spcecial check for reflector client. */
2753 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2754 && peer_sort (peer) != BGP_PEER_IBGP)
2755 return BGP_ERR_NOT_INTERNAL_PEER;
2756
2757 /* Spcecial check for remove-private-AS. */
2758 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2759 && peer_sort (peer) == BGP_PEER_IBGP)
2760 return BGP_ERR_REMOVE_PRIVATE_AS;
2761
2762 /* When unset the peer-group member's flag we have to check
2763 peer-group configuration. */
2764 if (! set && peer->af_group[afi][safi])
2765 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2766 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2767
2768 /* When current flag configuration is same as requested one. */
2769 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2770 {
2771 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2772 return 0;
2773 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2774 return 0;
2775 }
2776
2777 if (set)
2778 SET_FLAG (peer->af_flags[afi][safi], flag);
2779 else
2780 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2781
2782 /* Execute action when peer is established. */
2783 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2784 && peer->status == Established)
2785 {
2786 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2787 bgp_clear_adj_in (peer, afi, safi);
2788 else
hassoe0701b72004-05-20 09:19:34 +00002789 {
2790 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2791 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2792 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2793 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2794 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2795 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2796 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2797 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2798
2799 peer_change_action (peer, afi, safi, action.type);
2800 }
2801
paul718e3742002-12-13 20:15:29 +00002802 }
2803
2804 /* Peer group member updates. */
2805 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2806 {
2807 group = peer->group;
2808
paul1eb8ef22005-04-07 07:30:20 +00002809 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002810 {
2811 if (! peer->af_group[afi][safi])
2812 continue;
2813
2814 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2815 continue;
2816
2817 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2818 continue;
2819
2820 if (set)
2821 SET_FLAG (peer->af_flags[afi][safi], flag);
2822 else
2823 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2824
2825 if (peer->status == Established)
2826 {
2827 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2828 bgp_clear_adj_in (peer, afi, safi);
2829 else
hassoe0701b72004-05-20 09:19:34 +00002830 {
2831 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2832 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2833 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2834 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2835 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2836 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2837 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2838 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2839
2840 peer_change_action (peer, afi, safi, action.type);
2841 }
paul718e3742002-12-13 20:15:29 +00002842 }
2843 }
2844 }
2845 return 0;
2846}
2847
2848int
2849peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2850{
2851 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2852}
2853
2854int
2855peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2856{
2857 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2858}
David Lamparter6b0655a2014-06-04 06:53:35 +02002859
paul718e3742002-12-13 20:15:29 +00002860/* EBGP multihop configuration. */
2861int
2862peer_ebgp_multihop_set (struct peer *peer, int ttl)
2863{
2864 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002865 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002866 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002867
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002868 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002869 return 0;
2870
Nick Hilliardfa411a22011-03-23 15:33:17 +00002871 /* see comment in peer_ttl_security_hops_set() */
2872 if (ttl != MAXTTL)
2873 {
2874 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2875 {
2876 group = peer->group;
2877 if (group->conf->gtsm_hops != 0)
2878 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2879
2880 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2881 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002882 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002883 continue;
2884
2885 if (peer1->gtsm_hops != 0)
2886 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2887 }
2888 }
2889 else
2890 {
2891 if (peer->gtsm_hops != 0)
2892 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2893 }
2894 }
2895
paul718e3742002-12-13 20:15:29 +00002896 peer->ttl = ttl;
2897
2898 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2899 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002900 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002901 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002902 }
2903 else
2904 {
2905 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002906 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002907 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002908 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002909 continue;
paul718e3742002-12-13 20:15:29 +00002910
pauleb821182004-05-01 08:44:08 +00002911 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002912
pauleb821182004-05-01 08:44:08 +00002913 if (peer->fd >= 0)
2914 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2915 }
paul718e3742002-12-13 20:15:29 +00002916 }
2917 return 0;
2918}
2919
2920int
2921peer_ebgp_multihop_unset (struct peer *peer)
2922{
2923 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002924 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002925
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002926 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002927 return 0;
2928
Nick Hilliardfa411a22011-03-23 15:33:17 +00002929 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2930 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2931
paul718e3742002-12-13 20:15:29 +00002932 if (peer_group_active (peer))
2933 peer->ttl = peer->group->conf->ttl;
2934 else
2935 peer->ttl = 1;
2936
2937 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2938 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002939 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002940 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002941 }
2942 else
2943 {
2944 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002945 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002946 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002947 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002948 continue;
paul718e3742002-12-13 20:15:29 +00002949
pauleb821182004-05-01 08:44:08 +00002950 peer->ttl = 1;
2951
2952 if (peer->fd >= 0)
2953 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2954 }
paul718e3742002-12-13 20:15:29 +00002955 }
2956 return 0;
2957}
David Lamparter6b0655a2014-06-04 06:53:35 +02002958
paul718e3742002-12-13 20:15:29 +00002959/* Neighbor description. */
2960int
David Lamparterdfb9bd72016-05-24 18:58:07 +02002961peer_description_set (struct peer *peer, const char *desc)
paul718e3742002-12-13 20:15:29 +00002962{
2963 if (peer->desc)
2964 XFREE (MTYPE_PEER_DESC, peer->desc);
2965
2966 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2967
2968 return 0;
2969}
2970
2971int
2972peer_description_unset (struct peer *peer)
2973{
2974 if (peer->desc)
2975 XFREE (MTYPE_PEER_DESC, peer->desc);
2976
2977 peer->desc = NULL;
2978
2979 return 0;
2980}
David Lamparter6b0655a2014-06-04 06:53:35 +02002981
paul718e3742002-12-13 20:15:29 +00002982/* Neighbor update-source. */
2983int
paulfd79ac92004-10-13 05:06:08 +00002984peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002985{
2986 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002987 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002988
2989 if (peer->update_if)
2990 {
2991 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2992 && strcmp (peer->update_if, ifname) == 0)
2993 return 0;
2994
2995 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2996 peer->update_if = NULL;
2997 }
2998
2999 if (peer->update_source)
3000 {
3001 sockunion_free (peer->update_source);
3002 peer->update_source = NULL;
3003 }
3004
3005 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
3006
3007 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3008 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003009 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003010 {
3011 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3012 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3013 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3014 }
paul718e3742002-12-13 20:15:29 +00003015 else
3016 BGP_EVENT_ADD (peer, BGP_Stop);
3017 return 0;
3018 }
3019
3020 /* peer-group member updates. */
3021 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003022 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003023 {
3024 if (peer->update_if)
3025 {
3026 if (strcmp (peer->update_if, ifname) == 0)
3027 continue;
3028
3029 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3030 peer->update_if = NULL;
3031 }
3032
3033 if (peer->update_source)
3034 {
3035 sockunion_free (peer->update_source);
3036 peer->update_source = NULL;
3037 }
3038
3039 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
3040
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003041 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003042 {
3043 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3044 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3045 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3046 }
paul718e3742002-12-13 20:15:29 +00003047 else
3048 BGP_EVENT_ADD (peer, BGP_Stop);
3049 }
3050 return 0;
3051}
3052
3053int
David Lamparterdfb9bd72016-05-24 18:58:07 +02003054peer_update_source_addr_set (struct peer *peer, const union sockunion *su)
paul718e3742002-12-13 20:15:29 +00003055{
3056 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003057 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003058
3059 if (peer->update_source)
3060 {
3061 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3062 && sockunion_cmp (peer->update_source, su) == 0)
3063 return 0;
3064 sockunion_free (peer->update_source);
3065 peer->update_source = NULL;
3066 }
3067
3068 if (peer->update_if)
3069 {
3070 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3071 peer->update_if = NULL;
3072 }
3073
3074 peer->update_source = sockunion_dup (su);
3075
3076 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3077 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003078 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003079 {
3080 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3081 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3082 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3083 }
paul718e3742002-12-13 20:15:29 +00003084 else
3085 BGP_EVENT_ADD (peer, BGP_Stop);
3086 return 0;
3087 }
3088
3089 /* peer-group member updates. */
3090 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003091 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003092 {
3093 if (peer->update_source)
3094 {
3095 if (sockunion_cmp (peer->update_source, su) == 0)
3096 continue;
3097 sockunion_free (peer->update_source);
3098 peer->update_source = NULL;
3099 }
3100
3101 if (peer->update_if)
3102 {
3103 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3104 peer->update_if = NULL;
3105 }
3106
3107 peer->update_source = sockunion_dup (su);
3108
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003109 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003110 {
3111 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3112 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3113 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3114 }
paul718e3742002-12-13 20:15:29 +00003115 else
3116 BGP_EVENT_ADD (peer, BGP_Stop);
3117 }
3118 return 0;
3119}
3120
3121int
3122peer_update_source_unset (struct peer *peer)
3123{
3124 union sockunion *su;
3125 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003126 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003127
3128 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3129 && ! peer->update_source
3130 && ! peer->update_if)
3131 return 0;
3132
3133 if (peer->update_source)
3134 {
3135 sockunion_free (peer->update_source);
3136 peer->update_source = NULL;
3137 }
3138 if (peer->update_if)
3139 {
3140 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3141 peer->update_if = NULL;
3142 }
3143
3144 if (peer_group_active (peer))
3145 {
3146 group = peer->group;
3147
3148 if (group->conf->update_source)
3149 {
3150 su = sockunion_dup (group->conf->update_source);
3151 peer->update_source = su;
3152 }
3153 else if (group->conf->update_if)
3154 peer->update_if =
3155 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
3156 }
3157
3158 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3159 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003160 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003161 {
3162 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3163 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3164 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3165 }
paul718e3742002-12-13 20:15:29 +00003166 else
3167 BGP_EVENT_ADD (peer, BGP_Stop);
3168 return 0;
3169 }
3170
3171 /* peer-group member updates. */
3172 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003173 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003174 {
3175 if (! peer->update_source && ! peer->update_if)
3176 continue;
3177
3178 if (peer->update_source)
3179 {
3180 sockunion_free (peer->update_source);
3181 peer->update_source = NULL;
3182 }
3183
3184 if (peer->update_if)
3185 {
3186 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3187 peer->update_if = NULL;
3188 }
3189
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003190 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003191 {
3192 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3193 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3194 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3195 }
paul718e3742002-12-13 20:15:29 +00003196 else
3197 BGP_EVENT_ADD (peer, BGP_Stop);
3198 }
3199 return 0;
3200}
David Lamparter6b0655a2014-06-04 06:53:35 +02003201
paul718e3742002-12-13 20:15:29 +00003202int
3203peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003204 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003205{
3206 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003207 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003208
3209 /* Adress family must be activated. */
3210 if (! peer->afc[afi][safi])
3211 return BGP_ERR_PEER_INACTIVE;
3212
3213 /* Default originate can't be used for peer group memeber. */
3214 if (peer_is_group_member (peer, afi, safi))
3215 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3216
3217 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3218 || (rmap && ! peer->default_rmap[afi][safi].name)
3219 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3220 {
3221 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3222
3223 if (rmap)
3224 {
3225 if (peer->default_rmap[afi][safi].name)
3226 free (peer->default_rmap[afi][safi].name);
3227 peer->default_rmap[afi][safi].name = strdup (rmap);
3228 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3229 }
3230 }
3231
3232 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3233 {
3234 if (peer->status == Established && peer->afc_nego[afi][safi])
3235 bgp_default_originate (peer, afi, safi, 0);
3236 return 0;
3237 }
3238
3239 /* peer-group member updates. */
3240 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003241 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003242 {
3243 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3244
3245 if (rmap)
3246 {
3247 if (peer->default_rmap[afi][safi].name)
3248 free (peer->default_rmap[afi][safi].name);
3249 peer->default_rmap[afi][safi].name = strdup (rmap);
3250 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3251 }
3252
3253 if (peer->status == Established && peer->afc_nego[afi][safi])
3254 bgp_default_originate (peer, afi, safi, 0);
3255 }
3256 return 0;
3257}
3258
3259int
3260peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3261{
3262 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003263 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003264
3265 /* Adress family must be activated. */
3266 if (! peer->afc[afi][safi])
3267 return BGP_ERR_PEER_INACTIVE;
3268
3269 /* Default originate can't be used for peer group memeber. */
3270 if (peer_is_group_member (peer, afi, safi))
3271 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3272
3273 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3274 {
3275 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3276
3277 if (peer->default_rmap[afi][safi].name)
3278 free (peer->default_rmap[afi][safi].name);
3279 peer->default_rmap[afi][safi].name = NULL;
3280 peer->default_rmap[afi][safi].map = NULL;
3281 }
3282
3283 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3284 {
3285 if (peer->status == Established && peer->afc_nego[afi][safi])
3286 bgp_default_originate (peer, afi, safi, 1);
3287 return 0;
3288 }
3289
3290 /* peer-group member updates. */
3291 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003292 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003293 {
3294 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3295
3296 if (peer->default_rmap[afi][safi].name)
3297 free (peer->default_rmap[afi][safi].name);
3298 peer->default_rmap[afi][safi].name = NULL;
3299 peer->default_rmap[afi][safi].map = NULL;
3300
3301 if (peer->status == Established && peer->afc_nego[afi][safi])
3302 bgp_default_originate (peer, afi, safi, 1);
3303 }
3304 return 0;
3305}
David Lamparter6b0655a2014-06-04 06:53:35 +02003306
paul718e3742002-12-13 20:15:29 +00003307int
3308peer_port_set (struct peer *peer, u_int16_t port)
3309{
3310 peer->port = port;
3311 return 0;
3312}
3313
3314int
3315peer_port_unset (struct peer *peer)
3316{
3317 peer->port = BGP_PORT_DEFAULT;
3318 return 0;
3319}
David Lamparter6b0655a2014-06-04 06:53:35 +02003320
paul718e3742002-12-13 20:15:29 +00003321/* neighbor weight. */
3322int
3323peer_weight_set (struct peer *peer, u_int16_t weight)
3324{
3325 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003326 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003327
3328 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3329 peer->weight = weight;
3330
3331 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3332 return 0;
3333
3334 /* peer-group member updates. */
3335 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003336 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003337 {
3338 peer->weight = group->conf->weight;
3339 }
3340 return 0;
3341}
3342
3343int
3344peer_weight_unset (struct peer *peer)
3345{
3346 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003347 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003348
3349 /* Set default weight. */
3350 if (peer_group_active (peer))
3351 peer->weight = peer->group->conf->weight;
3352 else
3353 peer->weight = 0;
3354
3355 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3356
3357 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3358 return 0;
3359
3360 /* peer-group member updates. */
3361 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003362 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003363 {
3364 peer->weight = 0;
3365 }
3366 return 0;
3367}
David Lamparter6b0655a2014-06-04 06:53:35 +02003368
paul718e3742002-12-13 20:15:29 +00003369int
3370peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3371{
3372 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003373 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003374
3375 /* Not for peer group memeber. */
3376 if (peer_group_active (peer))
3377 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3378
3379 /* keepalive value check. */
3380 if (keepalive > 65535)
3381 return BGP_ERR_INVALID_VALUE;
3382
3383 /* Holdtime value check. */
3384 if (holdtime > 65535)
3385 return BGP_ERR_INVALID_VALUE;
3386
3387 /* Holdtime value must be either 0 or greater than 3. */
3388 if (holdtime < 3 && holdtime != 0)
3389 return BGP_ERR_INVALID_VALUE;
3390
3391 /* Set value to the configuration. */
3392 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3393 peer->holdtime = holdtime;
3394 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3395
3396 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3397 return 0;
3398
3399 /* peer-group member updates. */
3400 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003401 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003402 {
3403 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3404 peer->holdtime = group->conf->holdtime;
3405 peer->keepalive = group->conf->keepalive;
3406 }
3407 return 0;
3408}
3409
3410int
3411peer_timers_unset (struct peer *peer)
3412{
3413 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003414 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003415
3416 if (peer_group_active (peer))
3417 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3418
3419 /* Clear configuration. */
3420 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3421 peer->keepalive = 0;
3422 peer->holdtime = 0;
3423
3424 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3425 return 0;
3426
3427 /* peer-group member updates. */
3428 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003429 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003430 {
3431 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3432 peer->holdtime = 0;
3433 peer->keepalive = 0;
3434 }
3435
3436 return 0;
3437}
David Lamparter6b0655a2014-06-04 06:53:35 +02003438
paul718e3742002-12-13 20:15:29 +00003439int
3440peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3441{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003442 struct peer_group *group;
3443 struct listnode *node, *nnode;
3444
paul718e3742002-12-13 20:15:29 +00003445 if (peer_group_active (peer))
3446 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3447
3448 if (connect > 65535)
3449 return BGP_ERR_INVALID_VALUE;
3450
3451 /* Set value to the configuration. */
3452 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3453 peer->connect = connect;
3454
3455 /* Set value to timer setting. */
3456 peer->v_connect = connect;
3457
Daniel Walton0d7435f2015-10-22 11:35:20 +03003458 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3459 return 0;
3460
3461 /* peer-group member updates. */
3462 group = peer->group;
3463 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3464 {
3465 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3466 peer->connect = connect;
3467 peer->v_connect = connect;
3468 }
paul718e3742002-12-13 20:15:29 +00003469 return 0;
3470}
3471
3472int
3473peer_timers_connect_unset (struct peer *peer)
3474{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003475 struct peer_group *group;
3476 struct listnode *node, *nnode;
3477
paul718e3742002-12-13 20:15:29 +00003478 if (peer_group_active (peer))
3479 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3480
3481 /* Clear configuration. */
3482 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3483 peer->connect = 0;
3484
3485 /* Set timer setting to default value. */
3486 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3487
Daniel Walton0d7435f2015-10-22 11:35:20 +03003488 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3489 return 0;
3490
3491 /* peer-group member updates. */
3492 group = peer->group;
3493 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3494 {
3495 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3496 peer->connect = 0;
3497 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3498 }
3499 return 0;
paul718e3742002-12-13 20:15:29 +00003500}
David Lamparter6b0655a2014-06-04 06:53:35 +02003501
paul718e3742002-12-13 20:15:29 +00003502int
3503peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3504{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003505 struct peer_group *group;
3506 struct listnode *node, *nnode;
3507
paul718e3742002-12-13 20:15:29 +00003508 if (peer_group_active (peer))
3509 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3510
3511 if (routeadv > 600)
3512 return BGP_ERR_INVALID_VALUE;
3513
3514 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3515 peer->routeadv = routeadv;
3516 peer->v_routeadv = routeadv;
3517
Daniel Walton0d7435f2015-10-22 11:35:20 +03003518 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3519 return 0;
3520
3521 /* peer-group member updates. */
3522 group = peer->group;
3523 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3524 {
3525 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3526 peer->routeadv = routeadv;
3527 peer->v_routeadv = routeadv;
3528 }
3529
paul718e3742002-12-13 20:15:29 +00003530 return 0;
3531}
3532
3533int
3534peer_advertise_interval_unset (struct peer *peer)
3535{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003536 struct peer_group *group;
3537 struct listnode *node, *nnode;
3538
paul718e3742002-12-13 20:15:29 +00003539 if (peer_group_active (peer))
3540 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3541
3542 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3543 peer->routeadv = 0;
3544
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003545 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003546 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3547 else
3548 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
Daniel Walton0d7435f2015-10-22 11:35:20 +03003549
3550 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3551 return 0;
3552
3553 /* peer-group member updates. */
3554 group = peer->group;
3555 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3556 {
3557 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3558 peer->routeadv = 0;
3559
3560 if (peer->sort == BGP_PEER_IBGP)
3561 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3562 else
3563 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3564 }
paul718e3742002-12-13 20:15:29 +00003565
3566 return 0;
3567}
David Lamparter6b0655a2014-06-04 06:53:35 +02003568
paul718e3742002-12-13 20:15:29 +00003569/* neighbor interface */
3570int
paulfd79ac92004-10-13 05:06:08 +00003571peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003572{
3573 if (peer->ifname)
3574 free (peer->ifname);
3575 peer->ifname = strdup (str);
3576
3577 return 0;
3578}
3579
3580int
3581peer_interface_unset (struct peer *peer)
3582{
3583 if (peer->ifname)
3584 free (peer->ifname);
3585 peer->ifname = NULL;
3586
3587 return 0;
3588}
David Lamparter6b0655a2014-06-04 06:53:35 +02003589
paul718e3742002-12-13 20:15:29 +00003590/* Allow-as in. */
3591int
3592peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3593{
3594 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003595 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003596
3597 if (allow_num < 1 || allow_num > 10)
3598 return BGP_ERR_INVALID_VALUE;
3599
3600 if (peer->allowas_in[afi][safi] != allow_num)
3601 {
3602 peer->allowas_in[afi][safi] = allow_num;
3603 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3604 peer_change_action (peer, afi, safi, peer_change_reset_in);
3605 }
3606
3607 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3608 return 0;
3609
3610 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003611 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003612 {
3613 if (peer->allowas_in[afi][safi] != allow_num)
3614 {
3615 peer->allowas_in[afi][safi] = allow_num;
3616 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3617 peer_change_action (peer, afi, safi, peer_change_reset_in);
3618 }
3619
3620 }
3621 return 0;
3622}
3623
3624int
3625peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3626{
3627 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003628 struct listnode *node, *nnode;
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 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3637 return 0;
3638
3639 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003640 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003641 {
3642 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3643 {
3644 peer->allowas_in[afi][safi] = 0;
3645 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3646 }
3647 }
3648 return 0;
3649}
David Lamparter6b0655a2014-06-04 06:53:35 +02003650
paul718e3742002-12-13 20:15:29 +00003651int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003652peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003653{
3654 struct bgp *bgp = peer->bgp;
3655 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003656 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003657
3658 if (peer_sort (peer) != BGP_PEER_EBGP
3659 && peer_sort (peer) != BGP_PEER_INTERNAL)
3660 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3661
3662 if (bgp->as == as)
3663 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3664
3665 if (peer_group_active (peer))
3666 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3667
Andrew Certain9d3f9702012-11-07 23:50:07 +00003668 if (peer->as == as)
3669 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3670
paul718e3742002-12-13 20:15:29 +00003671 if (peer->change_local_as == as &&
3672 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003673 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3674 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3675 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003676 return 0;
3677
3678 peer->change_local_as = as;
3679 if (no_prepend)
3680 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3681 else
3682 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3683
Andrew Certain9d3f9702012-11-07 23:50:07 +00003684 if (replace_as)
3685 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3686 else
3687 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3688
paul718e3742002-12-13 20:15:29 +00003689 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3690 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003691 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003692 {
3693 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3694 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3695 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3696 }
paul718e3742002-12-13 20:15:29 +00003697 else
3698 BGP_EVENT_ADD (peer, BGP_Stop);
3699
3700 return 0;
3701 }
3702
3703 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003704 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003705 {
3706 peer->change_local_as = as;
3707 if (no_prepend)
3708 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3709 else
3710 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3711
Andrew Certain9d3f9702012-11-07 23:50:07 +00003712 if (replace_as)
3713 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3714 else
3715 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3716
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003717 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003718 {
3719 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3720 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3721 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3722 }
paul718e3742002-12-13 20:15:29 +00003723 else
3724 BGP_EVENT_ADD (peer, BGP_Stop);
3725 }
3726
3727 return 0;
3728}
3729
3730int
3731peer_local_as_unset (struct peer *peer)
3732{
3733 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003734 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003735
3736 if (peer_group_active (peer))
3737 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3738
3739 if (! peer->change_local_as)
3740 return 0;
3741
3742 peer->change_local_as = 0;
3743 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003744 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003745
3746 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3747 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003748 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003749 {
3750 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3751 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3752 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3753 }
paul718e3742002-12-13 20:15:29 +00003754 else
3755 BGP_EVENT_ADD (peer, BGP_Stop);
3756
3757 return 0;
3758 }
3759
3760 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003761 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003762 {
3763 peer->change_local_as = 0;
3764 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003765 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003766
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003767 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003768 {
3769 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3770 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3771 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3772 }
paul718e3742002-12-13 20:15:29 +00003773 else
3774 BGP_EVENT_ADD (peer, BGP_Stop);
3775 }
3776 return 0;
3777}
David Lamparter6b0655a2014-06-04 06:53:35 +02003778
Paul Jakma0df7c912008-07-21 21:02:49 +00003779/* Set password for authenticating with the peer. */
3780int
3781peer_password_set (struct peer *peer, const char *password)
3782{
3783 struct listnode *nn, *nnode;
3784 int len = password ? strlen(password) : 0;
3785 int ret = BGP_SUCCESS;
3786
3787 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3788 return BGP_ERR_INVALID_VALUE;
3789
3790 if (peer->password && strcmp (peer->password, password) == 0
3791 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3792 return 0;
3793
3794 if (peer->password)
3795 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3796
3797 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3798
3799 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3800 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003801 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3802 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
Paul Jakma0df7c912008-07-21 21:02:49 +00003803 else
3804 BGP_EVENT_ADD (peer, BGP_Stop);
3805
3806 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3807 }
3808
3809 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3810 {
3811 if (peer->password && strcmp (peer->password, password) == 0)
3812 continue;
3813
3814 if (peer->password)
3815 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3816
3817 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3818
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003819 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003820 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3821 else
3822 BGP_EVENT_ADD (peer, BGP_Stop);
3823
3824 if (bgp_md5_set (peer) < 0)
3825 ret = BGP_ERR_TCPSIG_FAILED;
3826 }
3827
3828 return ret;
3829}
3830
3831int
3832peer_password_unset (struct peer *peer)
3833{
3834 struct listnode *nn, *nnode;
3835
3836 if (!peer->password
3837 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3838 return 0;
3839
3840 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3841 {
3842 if (peer_group_active (peer)
3843 && peer->group->conf->password
3844 && strcmp (peer->group->conf->password, peer->password) == 0)
3845 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3846
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003847 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003848 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3849 else
3850 BGP_EVENT_ADD (peer, BGP_Stop);
3851
3852 if (peer->password)
3853 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3854
3855 peer->password = NULL;
3856
3857 bgp_md5_set (peer);
3858
3859 return 0;
3860 }
3861
3862 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3863 peer->password = NULL;
3864
3865 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3866 {
3867 if (!peer->password)
3868 continue;
3869
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003870 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003871 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3872 else
3873 BGP_EVENT_ADD (peer, BGP_Stop);
3874
3875 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3876 peer->password = NULL;
3877
3878 bgp_md5_set (peer);
3879 }
3880
3881 return 0;
3882}
David Lamparter6b0655a2014-06-04 06:53:35 +02003883
paul718e3742002-12-13 20:15:29 +00003884/* Set distribute list to the peer. */
3885int
3886peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003887 const char *name)
paul718e3742002-12-13 20:15:29 +00003888{
3889 struct bgp_filter *filter;
3890 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003891 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003892
3893 if (! peer->afc[afi][safi])
3894 return BGP_ERR_PEER_INACTIVE;
3895
3896 if (direct != FILTER_IN && direct != FILTER_OUT)
3897 return BGP_ERR_INVALID_VALUE;
3898
3899 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3900 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3901
3902 filter = &peer->filter[afi][safi];
3903
3904 if (filter->plist[direct].name)
3905 return BGP_ERR_PEER_FILTER_CONFLICT;
3906
3907 if (filter->dlist[direct].name)
3908 free (filter->dlist[direct].name);
3909 filter->dlist[direct].name = strdup (name);
3910 filter->dlist[direct].alist = access_list_lookup (afi, name);
3911
3912 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3913 return 0;
3914
3915 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003916 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003917 {
3918 filter = &peer->filter[afi][safi];
3919
3920 if (! peer->af_group[afi][safi])
3921 continue;
3922
3923 if (filter->dlist[direct].name)
3924 free (filter->dlist[direct].name);
3925 filter->dlist[direct].name = strdup (name);
3926 filter->dlist[direct].alist = access_list_lookup (afi, name);
3927 }
3928
3929 return 0;
3930}
3931
3932int
3933peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3934{
3935 struct bgp_filter *filter;
3936 struct bgp_filter *gfilter;
3937 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003938 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003939
3940 if (! peer->afc[afi][safi])
3941 return BGP_ERR_PEER_INACTIVE;
3942
3943 if (direct != FILTER_IN && direct != FILTER_OUT)
3944 return BGP_ERR_INVALID_VALUE;
3945
3946 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3947 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3948
3949 filter = &peer->filter[afi][safi];
3950
3951 /* apply peer-group filter */
3952 if (peer->af_group[afi][safi])
3953 {
3954 gfilter = &peer->group->conf->filter[afi][safi];
3955
3956 if (gfilter->dlist[direct].name)
3957 {
3958 if (filter->dlist[direct].name)
3959 free (filter->dlist[direct].name);
3960 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3961 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3962 return 0;
3963 }
3964 }
3965
3966 if (filter->dlist[direct].name)
3967 free (filter->dlist[direct].name);
3968 filter->dlist[direct].name = NULL;
3969 filter->dlist[direct].alist = NULL;
3970
3971 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3972 return 0;
3973
3974 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003975 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003976 {
3977 filter = &peer->filter[afi][safi];
3978
3979 if (! peer->af_group[afi][safi])
3980 continue;
3981
3982 if (filter->dlist[direct].name)
3983 free (filter->dlist[direct].name);
3984 filter->dlist[direct].name = NULL;
3985 filter->dlist[direct].alist = NULL;
3986 }
3987
3988 return 0;
3989}
3990
3991/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003992static void
paul718e3742002-12-13 20:15:29 +00003993peer_distribute_update (struct access_list *access)
3994{
3995 afi_t afi;
3996 safi_t safi;
3997 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003998 struct listnode *mnode, *mnnode;
3999 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004000 struct bgp *bgp;
4001 struct peer *peer;
4002 struct peer_group *group;
4003 struct bgp_filter *filter;
4004
paul1eb8ef22005-04-07 07:30:20 +00004005 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004006 {
paul1eb8ef22005-04-07 07:30:20 +00004007 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004008 {
4009 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4010 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4011 {
4012 filter = &peer->filter[afi][safi];
4013
4014 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4015 {
4016 if (filter->dlist[direct].name)
4017 filter->dlist[direct].alist =
4018 access_list_lookup (afi, filter->dlist[direct].name);
4019 else
4020 filter->dlist[direct].alist = NULL;
4021 }
4022 }
4023 }
paul1eb8ef22005-04-07 07:30:20 +00004024 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004025 {
4026 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4027 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4028 {
4029 filter = &group->conf->filter[afi][safi];
4030
4031 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4032 {
4033 if (filter->dlist[direct].name)
4034 filter->dlist[direct].alist =
4035 access_list_lookup (afi, filter->dlist[direct].name);
4036 else
4037 filter->dlist[direct].alist = NULL;
4038 }
4039 }
4040 }
4041 }
4042}
David Lamparter6b0655a2014-06-04 06:53:35 +02004043
paul718e3742002-12-13 20:15:29 +00004044/* Set prefix list to the peer. */
4045int
4046peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004047 const char *name)
paul718e3742002-12-13 20:15:29 +00004048{
4049 struct bgp_filter *filter;
4050 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004051 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004052
4053 if (! peer->afc[afi][safi])
4054 return BGP_ERR_PEER_INACTIVE;
4055
4056 if (direct != FILTER_IN && direct != FILTER_OUT)
4057 return BGP_ERR_INVALID_VALUE;
4058
4059 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4060 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4061
4062 filter = &peer->filter[afi][safi];
4063
4064 if (filter->dlist[direct].name)
4065 return BGP_ERR_PEER_FILTER_CONFLICT;
4066
4067 if (filter->plist[direct].name)
4068 free (filter->plist[direct].name);
4069 filter->plist[direct].name = strdup (name);
4070 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4071
4072 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4073 return 0;
4074
4075 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004076 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004077 {
4078 filter = &peer->filter[afi][safi];
4079
4080 if (! peer->af_group[afi][safi])
4081 continue;
4082
4083 if (filter->plist[direct].name)
4084 free (filter->plist[direct].name);
4085 filter->plist[direct].name = strdup (name);
4086 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4087 }
4088 return 0;
4089}
4090
4091int
4092peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4093{
4094 struct bgp_filter *filter;
4095 struct bgp_filter *gfilter;
4096 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004097 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004098
4099 if (! peer->afc[afi][safi])
4100 return BGP_ERR_PEER_INACTIVE;
4101
4102 if (direct != FILTER_IN && direct != FILTER_OUT)
4103 return BGP_ERR_INVALID_VALUE;
4104
4105 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4106 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4107
4108 filter = &peer->filter[afi][safi];
4109
4110 /* apply peer-group filter */
4111 if (peer->af_group[afi][safi])
4112 {
4113 gfilter = &peer->group->conf->filter[afi][safi];
4114
4115 if (gfilter->plist[direct].name)
4116 {
4117 if (filter->plist[direct].name)
4118 free (filter->plist[direct].name);
4119 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
4120 filter->plist[direct].plist = gfilter->plist[direct].plist;
4121 return 0;
4122 }
4123 }
4124
4125 if (filter->plist[direct].name)
4126 free (filter->plist[direct].name);
4127 filter->plist[direct].name = NULL;
4128 filter->plist[direct].plist = NULL;
4129
4130 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4131 return 0;
4132
4133 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004134 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004135 {
4136 filter = &peer->filter[afi][safi];
4137
4138 if (! peer->af_group[afi][safi])
4139 continue;
4140
4141 if (filter->plist[direct].name)
4142 free (filter->plist[direct].name);
4143 filter->plist[direct].name = NULL;
4144 filter->plist[direct].plist = NULL;
4145 }
4146
4147 return 0;
4148}
4149
4150/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00004151static void
paul718e3742002-12-13 20:15:29 +00004152peer_prefix_list_update (struct prefix_list *plist)
4153{
paul1eb8ef22005-04-07 07:30:20 +00004154 struct listnode *mnode, *mnnode;
4155 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004156 struct bgp *bgp;
4157 struct peer *peer;
4158 struct peer_group *group;
4159 struct bgp_filter *filter;
4160 afi_t afi;
4161 safi_t safi;
4162 int direct;
4163
paul1eb8ef22005-04-07 07:30:20 +00004164 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004165 {
paul1eb8ef22005-04-07 07:30:20 +00004166 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004167 {
4168 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4169 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4170 {
4171 filter = &peer->filter[afi][safi];
4172
4173 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4174 {
4175 if (filter->plist[direct].name)
4176 filter->plist[direct].plist =
4177 prefix_list_lookup (afi, filter->plist[direct].name);
4178 else
4179 filter->plist[direct].plist = NULL;
4180 }
4181 }
4182 }
paul1eb8ef22005-04-07 07:30:20 +00004183 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004184 {
4185 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4186 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4187 {
4188 filter = &group->conf->filter[afi][safi];
4189
4190 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4191 {
4192 if (filter->plist[direct].name)
4193 filter->plist[direct].plist =
4194 prefix_list_lookup (afi, filter->plist[direct].name);
4195 else
4196 filter->plist[direct].plist = NULL;
4197 }
4198 }
4199 }
4200 }
4201}
David Lamparter6b0655a2014-06-04 06:53:35 +02004202
paul718e3742002-12-13 20:15:29 +00004203int
4204peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004205 const char *name)
paul718e3742002-12-13 20:15:29 +00004206{
4207 struct bgp_filter *filter;
4208 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004209 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004210
4211 if (! peer->afc[afi][safi])
4212 return BGP_ERR_PEER_INACTIVE;
4213
4214 if (direct != FILTER_IN && direct != FILTER_OUT)
4215 return BGP_ERR_INVALID_VALUE;
4216
4217 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4218 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4219
4220 filter = &peer->filter[afi][safi];
4221
4222 if (filter->aslist[direct].name)
4223 free (filter->aslist[direct].name);
4224 filter->aslist[direct].name = strdup (name);
4225 filter->aslist[direct].aslist = as_list_lookup (name);
4226
4227 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4228 return 0;
4229
4230 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004231 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004232 {
4233 filter = &peer->filter[afi][safi];
4234
4235 if (! peer->af_group[afi][safi])
4236 continue;
4237
4238 if (filter->aslist[direct].name)
4239 free (filter->aslist[direct].name);
4240 filter->aslist[direct].name = strdup (name);
4241 filter->aslist[direct].aslist = as_list_lookup (name);
4242 }
4243 return 0;
4244}
4245
4246int
4247peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4248{
4249 struct bgp_filter *filter;
4250 struct bgp_filter *gfilter;
4251 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004252 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004253
4254 if (! peer->afc[afi][safi])
4255 return BGP_ERR_PEER_INACTIVE;
4256
hassob5f29602005-05-25 21:00:28 +00004257 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004258 return BGP_ERR_INVALID_VALUE;
4259
hassob5f29602005-05-25 21:00:28 +00004260 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004261 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4262
4263 filter = &peer->filter[afi][safi];
4264
4265 /* apply peer-group filter */
4266 if (peer->af_group[afi][safi])
4267 {
4268 gfilter = &peer->group->conf->filter[afi][safi];
4269
4270 if (gfilter->aslist[direct].name)
4271 {
4272 if (filter->aslist[direct].name)
4273 free (filter->aslist[direct].name);
4274 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4275 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4276 return 0;
4277 }
4278 }
4279
4280 if (filter->aslist[direct].name)
4281 free (filter->aslist[direct].name);
4282 filter->aslist[direct].name = NULL;
4283 filter->aslist[direct].aslist = NULL;
4284
4285 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4286 return 0;
4287
4288 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004289 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004290 {
4291 filter = &peer->filter[afi][safi];
4292
4293 if (! peer->af_group[afi][safi])
4294 continue;
4295
4296 if (filter->aslist[direct].name)
4297 free (filter->aslist[direct].name);
4298 filter->aslist[direct].name = NULL;
4299 filter->aslist[direct].aslist = NULL;
4300 }
4301
4302 return 0;
4303}
4304
paul94f2b392005-06-28 12:44:16 +00004305static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004306peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004307{
4308 afi_t afi;
4309 safi_t safi;
4310 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004311 struct listnode *mnode, *mnnode;
4312 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004313 struct bgp *bgp;
4314 struct peer *peer;
4315 struct peer_group *group;
4316 struct bgp_filter *filter;
4317
paul1eb8ef22005-04-07 07:30:20 +00004318 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004319 {
paul1eb8ef22005-04-07 07:30:20 +00004320 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004321 {
4322 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4323 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4324 {
4325 filter = &peer->filter[afi][safi];
4326
4327 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4328 {
4329 if (filter->aslist[direct].name)
4330 filter->aslist[direct].aslist =
4331 as_list_lookup (filter->aslist[direct].name);
4332 else
4333 filter->aslist[direct].aslist = NULL;
4334 }
4335 }
4336 }
paul1eb8ef22005-04-07 07:30:20 +00004337 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004338 {
4339 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4340 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4341 {
4342 filter = &group->conf->filter[afi][safi];
4343
4344 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4345 {
4346 if (filter->aslist[direct].name)
4347 filter->aslist[direct].aslist =
4348 as_list_lookup (filter->aslist[direct].name);
4349 else
4350 filter->aslist[direct].aslist = NULL;
4351 }
4352 }
4353 }
4354 }
4355}
David Lamparter6b0655a2014-06-04 06:53:35 +02004356
paul718e3742002-12-13 20:15:29 +00004357/* Set route-map to the peer. */
4358int
4359peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004360 const char *name)
paul718e3742002-12-13 20:15:29 +00004361{
4362 struct bgp_filter *filter;
4363 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004364 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004365
4366 if (! peer->afc[afi][safi])
4367 return BGP_ERR_PEER_INACTIVE;
4368
paulfee0f4c2004-09-13 05:12:46 +00004369 if (direct != RMAP_IN && direct != RMAP_OUT &&
4370 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004371 return BGP_ERR_INVALID_VALUE;
4372
paulfee0f4c2004-09-13 05:12:46 +00004373 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4374 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004375 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4376
4377 filter = &peer->filter[afi][safi];
4378
4379 if (filter->map[direct].name)
4380 free (filter->map[direct].name);
4381
4382 filter->map[direct].name = strdup (name);
4383 filter->map[direct].map = route_map_lookup_by_name (name);
4384
4385 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4386 return 0;
4387
4388 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004389 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004390 {
4391 filter = &peer->filter[afi][safi];
4392
4393 if (! peer->af_group[afi][safi])
4394 continue;
4395
4396 if (filter->map[direct].name)
4397 free (filter->map[direct].name);
4398 filter->map[direct].name = strdup (name);
4399 filter->map[direct].map = route_map_lookup_by_name (name);
4400 }
4401 return 0;
4402}
4403
4404/* Unset route-map from the peer. */
4405int
4406peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4407{
4408 struct bgp_filter *filter;
4409 struct bgp_filter *gfilter;
4410 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004411 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004412
4413 if (! peer->afc[afi][safi])
4414 return BGP_ERR_PEER_INACTIVE;
4415
hassob5f29602005-05-25 21:00:28 +00004416 if (direct != RMAP_IN && direct != RMAP_OUT &&
4417 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004418 return BGP_ERR_INVALID_VALUE;
4419
hassob5f29602005-05-25 21:00:28 +00004420 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4421 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004422 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4423
4424 filter = &peer->filter[afi][safi];
4425
4426 /* apply peer-group filter */
4427 if (peer->af_group[afi][safi])
4428 {
4429 gfilter = &peer->group->conf->filter[afi][safi];
4430
4431 if (gfilter->map[direct].name)
4432 {
4433 if (filter->map[direct].name)
4434 free (filter->map[direct].name);
4435 filter->map[direct].name = strdup (gfilter->map[direct].name);
4436 filter->map[direct].map = gfilter->map[direct].map;
4437 return 0;
4438 }
4439 }
4440
4441 if (filter->map[direct].name)
4442 free (filter->map[direct].name);
4443 filter->map[direct].name = NULL;
4444 filter->map[direct].map = NULL;
4445
4446 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4447 return 0;
4448
4449 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004450 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004451 {
4452 filter = &peer->filter[afi][safi];
4453
4454 if (! peer->af_group[afi][safi])
4455 continue;
4456
4457 if (filter->map[direct].name)
4458 free (filter->map[direct].name);
4459 filter->map[direct].name = NULL;
4460 filter->map[direct].map = NULL;
4461 }
4462 return 0;
4463}
David Lamparter6b0655a2014-06-04 06:53:35 +02004464
paul718e3742002-12-13 20:15:29 +00004465/* Set unsuppress-map to the peer. */
4466int
paulfd79ac92004-10-13 05:06:08 +00004467peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4468 const char *name)
paul718e3742002-12-13 20:15:29 +00004469{
4470 struct bgp_filter *filter;
4471 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004472 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004473
4474 if (! peer->afc[afi][safi])
4475 return BGP_ERR_PEER_INACTIVE;
4476
4477 if (peer_is_group_member (peer, afi, safi))
4478 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4479
4480 filter = &peer->filter[afi][safi];
4481
4482 if (filter->usmap.name)
4483 free (filter->usmap.name);
4484
4485 filter->usmap.name = strdup (name);
4486 filter->usmap.map = route_map_lookup_by_name (name);
4487
4488 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4489 return 0;
4490
4491 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004492 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004493 {
4494 filter = &peer->filter[afi][safi];
4495
4496 if (! peer->af_group[afi][safi])
4497 continue;
4498
4499 if (filter->usmap.name)
4500 free (filter->usmap.name);
4501 filter->usmap.name = strdup (name);
4502 filter->usmap.map = route_map_lookup_by_name (name);
4503 }
4504 return 0;
4505}
4506
4507/* Unset route-map from the peer. */
4508int
4509peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4510{
4511 struct bgp_filter *filter;
4512 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004513 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004514
4515 if (! peer->afc[afi][safi])
4516 return BGP_ERR_PEER_INACTIVE;
4517
4518 if (peer_is_group_member (peer, afi, safi))
4519 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4520
4521 filter = &peer->filter[afi][safi];
4522
4523 if (filter->usmap.name)
4524 free (filter->usmap.name);
4525 filter->usmap.name = NULL;
4526 filter->usmap.map = NULL;
4527
4528 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4529 return 0;
4530
4531 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004532 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004533 {
4534 filter = &peer->filter[afi][safi];
4535
4536 if (! peer->af_group[afi][safi])
4537 continue;
4538
4539 if (filter->usmap.name)
4540 free (filter->usmap.name);
4541 filter->usmap.name = NULL;
4542 filter->usmap.map = NULL;
4543 }
4544 return 0;
4545}
David Lamparter6b0655a2014-06-04 06:53:35 +02004546
paul718e3742002-12-13 20:15:29 +00004547int
4548peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004549 u_int32_t max, u_char threshold,
4550 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004551{
4552 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004553 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004554
4555 if (! peer->afc[afi][safi])
4556 return BGP_ERR_PEER_INACTIVE;
4557
4558 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4559 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004560 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004561 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004562 if (warning)
4563 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4564 else
4565 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4566
4567 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4568 return 0;
4569
4570 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004571 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004572 {
4573 if (! peer->af_group[afi][safi])
4574 continue;
4575
4576 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4577 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004578 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004579 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004580 if (warning)
4581 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4582 else
4583 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4584 }
4585 return 0;
4586}
4587
4588int
4589peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4590{
4591 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004592 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004593
4594 if (! peer->afc[afi][safi])
4595 return BGP_ERR_PEER_INACTIVE;
4596
4597 /* apply peer-group config */
4598 if (peer->af_group[afi][safi])
4599 {
4600 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4601 PEER_FLAG_MAX_PREFIX))
4602 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4603 else
4604 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4605
4606 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4607 PEER_FLAG_MAX_PREFIX_WARNING))
4608 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4609 else
4610 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4611
4612 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004613 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004614 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004615 return 0;
4616 }
4617
4618 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4619 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4620 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004621 peer->pmax_threshold[afi][safi] = 0;
4622 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004623
4624 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4625 return 0;
4626
4627 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004628 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004629 {
4630 if (! peer->af_group[afi][safi])
4631 continue;
4632
4633 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4634 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4635 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004636 peer->pmax_threshold[afi][safi] = 0;
4637 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004638 }
4639 return 0;
4640}
David Lamparter5f9adb52014-05-19 23:15:02 +02004641
4642static int is_ebgp_multihop_configured (struct peer *peer)
4643{
4644 struct peer_group *group;
4645 struct listnode *node, *nnode;
4646 struct peer *peer1;
4647
4648 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4649 {
4650 group = peer->group;
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004651 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4652 (group->conf->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004653 return 1;
4654
4655 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4656 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004657 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
4658 (peer1->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004659 return 1;
4660 }
4661 }
4662 else
4663 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004664 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4665 (peer->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004666 return 1;
4667 }
4668 return 0;
4669}
4670
Nick Hilliardfa411a22011-03-23 15:33:17 +00004671/* Set # of hops between us and BGP peer. */
4672int
4673peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4674{
4675 struct peer_group *group;
4676 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004677 int ret;
4678
4679 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4680
Nick Hilliardfa411a22011-03-23 15:33:17 +00004681 /* We cannot configure ttl-security hops when ebgp-multihop is already
4682 set. For non peer-groups, the check is simple. For peer-groups, it's
4683 slightly messy, because we need to check both the peer-group structure
4684 and all peer-group members for any trace of ebgp-multihop configuration
4685 before actually applying the ttl-security rules. Cisco really made a
4686 mess of this configuration parameter, and OpenBGPD got it right.
4687 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004688
David Lamparter5f9adb52014-05-19 23:15:02 +02004689 if (peer->gtsm_hops == 0)
4690 {
4691 if (is_ebgp_multihop_configured (peer))
4692 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004693
David Lamparter5f9adb52014-05-19 23:15:02 +02004694 /* specify MAXTTL on outgoing packets */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004695 /* Routine handles iBGP peers correctly */
David Lamparter5f9adb52014-05-19 23:15:02 +02004696 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4697 if (ret != 0)
4698 return ret;
4699 }
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004700
Nick Hilliardfa411a22011-03-23 15:33:17 +00004701 peer->gtsm_hops = gtsm_hops;
4702
Nick Hilliardfa411a22011-03-23 15:33:17 +00004703 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4704 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004705 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004706 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4707 }
4708 else
4709 {
4710 group = peer->group;
4711 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4712 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004713 peer->gtsm_hops = group->conf->gtsm_hops;
4714
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004715 /* Change setting of existing peer
4716 * established then change value (may break connectivity)
4717 * not established yet (teardown session and restart)
4718 * no session then do nothing (will get handled by next connection)
4719 */
4720 if (peer->status == Established)
4721 {
4722 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4723 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4724 MAXTTL + 1 - peer->gtsm_hops);
4725 }
4726 else if (peer->status < Established)
4727 {
4728 if (BGP_DEBUG (events, EVENTS))
4729 zlog_debug ("%s Min-ttl changed", peer->host);
4730 BGP_EVENT_ADD (peer, BGP_Stop);
4731 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004732 }
4733 }
4734
4735 return 0;
4736}
4737
4738int
4739peer_ttl_security_hops_unset (struct peer *peer)
4740{
4741 struct peer_group *group;
4742 struct listnode *node, *nnode;
4743 struct peer *opeer;
4744
4745 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4746
Nick Hilliardfa411a22011-03-23 15:33:17 +00004747 /* if a peer-group member, then reset to peer-group default rather than 0 */
4748 if (peer_group_active (peer))
4749 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4750 else
4751 peer->gtsm_hops = 0;
4752
4753 opeer = peer;
4754 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4755 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004756 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004757 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4758 }
4759 else
4760 {
4761 group = peer->group;
4762 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4763 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004764 peer->gtsm_hops = 0;
4765
4766 if (peer->fd >= 0)
4767 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4768 }
4769 }
4770
4771 return peer_ebgp_multihop_unset (opeer);
4772}
David Lamparter6b0655a2014-06-04 06:53:35 +02004773
paul718e3742002-12-13 20:15:29 +00004774int
4775peer_clear (struct peer *peer)
4776{
4777 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4778 {
hasso0a486e52005-02-01 20:57:17 +00004779 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4780 {
4781 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4782 if (peer->t_pmax_restart)
4783 {
4784 BGP_TIMER_OFF (peer->t_pmax_restart);
4785 if (BGP_DEBUG (events, EVENTS))
4786 zlog_debug ("%s Maximum-prefix restart timer canceled",
4787 peer->host);
4788 }
4789 BGP_EVENT_ADD (peer, BGP_Start);
4790 return 0;
4791 }
4792
paul718e3742002-12-13 20:15:29 +00004793 peer->v_start = BGP_INIT_START_TIMER;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00004794 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00004795 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4796 BGP_NOTIFY_CEASE_ADMIN_RESET);
4797 else
4798 BGP_EVENT_ADD (peer, BGP_Stop);
4799 }
4800 return 0;
4801}
4802
4803int
4804peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4805 enum bgp_clear_type stype)
4806{
4807 if (peer->status != Established)
4808 return 0;
4809
4810 if (! peer->afc[afi][safi])
4811 return BGP_ERR_AF_UNCONFIGURED;
4812
Timo Teräs5a2a1ec2015-10-22 11:35:18 +03004813 peer->rtt = sockopt_tcp_rtt (peer->fd);
4814
paulfee0f4c2004-09-13 05:12:46 +00004815 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4816 {
4817 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4818 return 0;
4819 bgp_check_local_routes_rsclient (peer, afi, safi);
4820 bgp_soft_reconfig_rsclient (peer, afi, safi);
4821 }
4822
paul718e3742002-12-13 20:15:29 +00004823 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4824 bgp_announce_route (peer, afi, safi);
4825
4826 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4827 {
4828 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4829 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4830 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4831 {
4832 struct bgp_filter *filter = &peer->filter[afi][safi];
4833 u_char prefix_type;
4834
4835 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4836 prefix_type = ORF_TYPE_PREFIX;
4837 else
4838 prefix_type = ORF_TYPE_PREFIX_OLD;
4839
4840 if (filter->plist[FILTER_IN].plist)
4841 {
4842 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4843 bgp_route_refresh_send (peer, afi, safi,
4844 prefix_type, REFRESH_DEFER, 1);
4845 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4846 REFRESH_IMMEDIATE, 0);
4847 }
4848 else
4849 {
4850 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4851 bgp_route_refresh_send (peer, afi, safi,
4852 prefix_type, REFRESH_IMMEDIATE, 1);
4853 else
4854 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4855 }
4856 return 0;
4857 }
4858 }
4859
4860 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4861 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4862 {
4863 /* If neighbor has soft reconfiguration inbound flag.
4864 Use Adj-RIB-In database. */
4865 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4866 bgp_soft_reconfig_in (peer, afi, safi);
4867 else
4868 {
4869 /* If neighbor has route refresh capability, send route refresh
4870 message to the peer. */
4871 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4872 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4873 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4874 else
4875 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4876 }
4877 }
4878 return 0;
4879}
David Lamparter6b0655a2014-06-04 06:53:35 +02004880
paulfd79ac92004-10-13 05:06:08 +00004881/* Display peer uptime.*/
4882/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004883char *
4884peer_uptime (time_t uptime2, char *buf, size_t len)
4885{
4886 time_t uptime1;
4887 struct tm *tm;
4888
4889 /* Check buffer length. */
4890 if (len < BGP_UPTIME_LEN)
4891 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004892 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004893 /* XXX: should return status instead of buf... */
4894 snprintf (buf, len, "<error> ");
4895 return buf;
paul718e3742002-12-13 20:15:29 +00004896 }
4897
4898 /* If there is no connection has been done before print `never'. */
4899 if (uptime2 == 0)
4900 {
4901 snprintf (buf, len, "never ");
4902 return buf;
4903 }
4904
4905 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004906 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004907 uptime1 -= uptime2;
4908 tm = gmtime (&uptime1);
Paul Jakma84c38402015-05-26 15:19:38 +01004909
paul718e3742002-12-13 20:15:29 +00004910 /* Making formatted timer strings. */
4911#define ONE_DAY_SECOND 60*60*24
Paul Jakma84c38402015-05-26 15:19:38 +01004912#define ONE_WEEK_SECOND ONE_DAY_SECOND*7
4913#define ONE_YEAR_SECOND ONE_DAY_SECOND*365
paul718e3742002-12-13 20:15:29 +00004914
4915 if (uptime1 < ONE_DAY_SECOND)
4916 snprintf (buf, len, "%02d:%02d:%02d",
4917 tm->tm_hour, tm->tm_min, tm->tm_sec);
4918 else if (uptime1 < ONE_WEEK_SECOND)
4919 snprintf (buf, len, "%dd%02dh%02dm",
4920 tm->tm_yday, tm->tm_hour, tm->tm_min);
Paul Jakma84c38402015-05-26 15:19:38 +01004921 else if (uptime1 < ONE_YEAR_SECOND)
paul718e3742002-12-13 20:15:29 +00004922 snprintf (buf, len, "%02dw%dd%02dh",
4923 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
Paul Jakma84c38402015-05-26 15:19:38 +01004924 else
4925 snprintf (buf, len, "%02dy%02dw%dd",
4926 tm->tm_year - 70, tm->tm_yday/7,
4927 tm->tm_yday - ((tm->tm_yday/7) * 7));
paul718e3742002-12-13 20:15:29 +00004928 return buf;
4929}
David Lamparter6b0655a2014-06-04 06:53:35 +02004930
paul94f2b392005-06-28 12:44:16 +00004931static void
paul718e3742002-12-13 20:15:29 +00004932bgp_config_write_filter (struct vty *vty, struct peer *peer,
4933 afi_t afi, safi_t safi)
4934{
4935 struct bgp_filter *filter;
4936 struct bgp_filter *gfilter = NULL;
4937 char *addr;
4938 int in = FILTER_IN;
4939 int out = FILTER_OUT;
4940
4941 addr = peer->host;
4942 filter = &peer->filter[afi][safi];
4943 if (peer->af_group[afi][safi])
4944 gfilter = &peer->group->conf->filter[afi][safi];
4945
4946 /* distribute-list. */
4947 if (filter->dlist[in].name)
4948 if (! gfilter || ! gfilter->dlist[in].name
4949 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4950 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4951 filter->dlist[in].name, VTY_NEWLINE);
4952 if (filter->dlist[out].name && ! gfilter)
4953 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4954 filter->dlist[out].name, VTY_NEWLINE);
4955
4956 /* prefix-list. */
4957 if (filter->plist[in].name)
4958 if (! gfilter || ! gfilter->plist[in].name
4959 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4960 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4961 filter->plist[in].name, VTY_NEWLINE);
4962 if (filter->plist[out].name && ! gfilter)
4963 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4964 filter->plist[out].name, VTY_NEWLINE);
4965
4966 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004967 if (filter->map[RMAP_IN].name)
4968 if (! gfilter || ! gfilter->map[RMAP_IN].name
4969 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004970 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004971 filter->map[RMAP_IN].name, VTY_NEWLINE);
4972 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004973 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004974 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4975 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4976 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4977 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4978 if (filter->map[RMAP_EXPORT].name)
4979 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4980 || strcmp (filter->map[RMAP_EXPORT].name,
4981 gfilter->map[RMAP_EXPORT].name) != 0)
4982 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4983 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004984
4985 /* unsuppress-map */
4986 if (filter->usmap.name && ! gfilter)
4987 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4988 filter->usmap.name, VTY_NEWLINE);
4989
4990 /* filter-list. */
4991 if (filter->aslist[in].name)
4992 if (! gfilter || ! gfilter->aslist[in].name
4993 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4994 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4995 filter->aslist[in].name, VTY_NEWLINE);
4996 if (filter->aslist[out].name && ! gfilter)
4997 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4998 filter->aslist[out].name, VTY_NEWLINE);
4999}
5000
5001/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00005002static void
paul718e3742002-12-13 20:15:29 +00005003bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
5004 struct peer *peer, afi_t afi, safi_t safi)
5005{
paul718e3742002-12-13 20:15:29 +00005006 struct peer *g_peer = NULL;
5007 char buf[SU_ADDRSTRLEN];
5008 char *addr;
5009
paul718e3742002-12-13 20:15:29 +00005010 addr = peer->host;
5011 if (peer_group_active (peer))
5012 g_peer = peer->group->conf;
5013
5014 /************************************
5015 ****** Global to the neighbor ******
5016 ************************************/
5017 if (afi == AFI_IP && safi == SAFI_UNICAST)
5018 {
5019 /* remote-as. */
5020 if (! peer_group_active (peer))
5021 {
5022 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5023 vty_out (vty, " neighbor %s peer-group%s", addr,
5024 VTY_NEWLINE);
5025 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005026 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00005027 VTY_NEWLINE);
5028 }
5029 else
5030 {
5031 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005032 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00005033 VTY_NEWLINE);
5034 if (peer->af_group[AFI_IP][SAFI_UNICAST])
5035 vty_out (vty, " neighbor %s peer-group %s%s", addr,
5036 peer->group->name, VTY_NEWLINE);
5037 }
5038
5039 /* local-as. */
5040 if (peer->change_local_as)
5041 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00005042 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00005043 peer->change_local_as,
5044 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00005045 " no-prepend" : "",
5046 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
5047 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005048
5049 /* Description. */
5050 if (peer->desc)
5051 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
5052 VTY_NEWLINE);
5053
5054 /* Shutdown. */
5055 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
5056 if (! peer_group_active (peer) ||
5057 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
5058 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
5059
Paul Jakma0df7c912008-07-21 21:02:49 +00005060 /* Password. */
5061 if (peer->password)
5062 if (!peer_group_active (peer)
5063 || ! g_peer->password
5064 || strcmp (peer->password, g_peer->password) != 0)
5065 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
5066 VTY_NEWLINE);
5067
paul718e3742002-12-13 20:15:29 +00005068 /* BGP port. */
5069 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00005070 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00005071 VTY_NEWLINE);
5072
5073 /* Local interface name. */
5074 if (peer->ifname)
5075 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
5076 VTY_NEWLINE);
5077
5078 /* Passive. */
5079 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
5080 if (! peer_group_active (peer) ||
5081 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
5082 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
5083
5084 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00005085 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00005086 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00005087 if (! peer_group_active (peer) ||
5088 g_peer->ttl != peer->ttl)
5089 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
5090 VTY_NEWLINE);
5091
Nick Hilliardfa411a22011-03-23 15:33:17 +00005092 /* ttl-security hops */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00005093 if (peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00005094 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00005095 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00005096 peer->gtsm_hops, VTY_NEWLINE);
5097
hasso6ffd2072005-02-02 14:50:11 +00005098 /* disable-connected-check. */
5099 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00005100 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00005101 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
5102 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005103
5104 /* Update-source. */
5105 if (peer->update_if)
5106 if (! peer_group_active (peer) || ! g_peer->update_if
5107 || strcmp (g_peer->update_if, peer->update_if) != 0)
5108 vty_out (vty, " neighbor %s update-source %s%s", addr,
5109 peer->update_if, VTY_NEWLINE);
5110 if (peer->update_source)
5111 if (! peer_group_active (peer) || ! g_peer->update_source
5112 || sockunion_cmp (g_peer->update_source,
5113 peer->update_source) != 0)
5114 vty_out (vty, " neighbor %s update-source %s%s", addr,
5115 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
5116 VTY_NEWLINE);
5117
paul718e3742002-12-13 20:15:29 +00005118 /* advertisement-interval */
Daniel Walton0d7435f2015-10-22 11:35:20 +03005119 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV) &&
5120 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00005121 vty_out (vty, " neighbor %s advertisement-interval %d%s",
5122 addr, peer->v_routeadv, VTY_NEWLINE);
5123
5124 /* timers. */
5125 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
5126 && ! peer_group_active (peer))
5127 vty_out (vty, " neighbor %s timers %d %d%s", addr,
5128 peer->keepalive, peer->holdtime, VTY_NEWLINE);
5129
Daniel Walton0d7435f2015-10-22 11:35:20 +03005130 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT) &&
5131 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00005132 vty_out (vty, " neighbor %s timers connect %d%s", addr,
5133 peer->connect, VTY_NEWLINE);
5134
5135 /* Default weight. */
5136 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
5137 if (! peer_group_active (peer) ||
5138 g_peer->weight != peer->weight)
5139 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
5140 VTY_NEWLINE);
5141
paul718e3742002-12-13 20:15:29 +00005142 /* Dynamic capability. */
5143 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5144 if (! peer_group_active (peer) ||
5145 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5146 vty_out (vty, " neighbor %s capability dynamic%s", addr,
5147 VTY_NEWLINE);
5148
5149 /* dont capability negotiation. */
5150 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
5151 if (! peer_group_active (peer) ||
5152 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
5153 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
5154 VTY_NEWLINE);
5155
5156 /* override capability negotiation. */
5157 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5158 if (! peer_group_active (peer) ||
5159 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5160 vty_out (vty, " neighbor %s override-capability%s", addr,
5161 VTY_NEWLINE);
5162
5163 /* strict capability negotiation. */
5164 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5165 if (! peer_group_active (peer) ||
5166 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5167 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
5168 VTY_NEWLINE);
5169
Christian Franke15c71342012-11-19 11:17:31 +00005170 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
paul718e3742002-12-13 20:15:29 +00005171 {
5172 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5173 {
5174 if (peer->afc[AFI_IP][SAFI_UNICAST])
5175 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5176 }
5177 else
5178 {
5179 if (! peer->afc[AFI_IP][SAFI_UNICAST])
5180 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
5181 }
5182 }
5183 }
5184
5185
5186 /************************************
5187 ****** Per AF to the neighbor ******
5188 ************************************/
5189
5190 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
5191 {
5192 if (peer->af_group[afi][safi])
5193 vty_out (vty, " neighbor %s peer-group %s%s", addr,
5194 peer->group->name, VTY_NEWLINE);
5195 else
5196 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5197 }
5198
5199 /* ORF capability. */
5200 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5201 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5202 if (! peer->af_group[afi][safi])
5203 {
5204 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
5205
5206 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5207 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5208 vty_out (vty, " both");
5209 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
5210 vty_out (vty, " send");
5211 else
5212 vty_out (vty, " receive");
5213 vty_out (vty, "%s", VTY_NEWLINE);
5214 }
5215
5216 /* Route reflector client. */
5217 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
5218 && ! peer->af_group[afi][safi])
5219 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
5220 VTY_NEWLINE);
5221
5222 /* Nexthop self. */
5223 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
5224 && ! peer->af_group[afi][safi])
Timo Teräs9e7a53c2014-04-24 10:22:37 +03005225 vty_out (vty, " neighbor %s next-hop-self%s%s", addr,
5226 peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ?
5227 " all" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005228
5229 /* Remove private AS. */
5230 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
5231 && ! peer->af_group[afi][safi])
5232 vty_out (vty, " neighbor %s remove-private-AS%s",
5233 addr, VTY_NEWLINE);
5234
5235 /* send-community print. */
5236 if (! peer->af_group[afi][safi])
5237 {
5238 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5239 {
5240 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5241 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5242 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
5243 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5244 vty_out (vty, " 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, " neighbor %s send-community%s", addr, VTY_NEWLINE);
5248 }
5249 else
5250 {
5251 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5252 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5253 vty_out (vty, " no neighbor %s send-community both%s",
5254 addr, VTY_NEWLINE);
5255 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5256 vty_out (vty, " no neighbor %s send-community extended%s",
5257 addr, VTY_NEWLINE);
5258 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5259 vty_out (vty, " no neighbor %s send-community%s",
5260 addr, VTY_NEWLINE);
5261 }
5262 }
5263
5264 /* Default information */
5265 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5266 && ! peer->af_group[afi][safi])
5267 {
5268 vty_out (vty, " neighbor %s default-originate", addr);
5269 if (peer->default_rmap[afi][safi].name)
5270 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5271 vty_out (vty, "%s", VTY_NEWLINE);
5272 }
5273
5274 /* Soft reconfiguration inbound. */
5275 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5276 if (! peer->af_group[afi][safi] ||
5277 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5278 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5279 VTY_NEWLINE);
5280
5281 /* maximum-prefix. */
5282 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5283 if (! peer->af_group[afi][safi]
5284 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005285 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005286 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5287 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005288 {
hasso0a486e52005-02-01 20:57:17 +00005289 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5290 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5291 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5292 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5293 vty_out (vty, " warning-only");
5294 if (peer->pmax_restart[afi][safi])
5295 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5296 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005297 }
paul718e3742002-12-13 20:15:29 +00005298
5299 /* Route server client. */
5300 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5301 && ! peer->af_group[afi][safi])
5302 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5303
Dylan Hall3cf12882011-10-27 15:28:17 +04005304 /* Nexthop-local unchanged. */
5305 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5306 && ! peer->af_group[afi][safi])
5307 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5308
paul718e3742002-12-13 20:15:29 +00005309 /* Allow AS in. */
5310 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5311 if (! peer_group_active (peer)
5312 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5313 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5314 {
5315 if (peer->allowas_in[afi][safi] == 3)
5316 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5317 else
5318 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5319 peer->allowas_in[afi][safi], VTY_NEWLINE);
5320 }
5321
5322 /* Filter. */
5323 bgp_config_write_filter (vty, peer, afi, safi);
5324
5325 /* atribute-unchanged. */
5326 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5327 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5328 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5329 && ! peer->af_group[afi][safi])
5330 {
5331 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5332 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5333 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5334 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5335 else
5336 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5337 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5338 " as-path" : "",
5339 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5340 " next-hop" : "",
5341 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5342 " med" : "", VTY_NEWLINE);
5343 }
5344}
5345
5346/* Display "address-family" configuration header. */
5347void
5348bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5349 int *write)
5350{
5351 if (*write)
5352 return;
5353
5354 if (afi == AFI_IP && safi == SAFI_UNICAST)
5355 return;
5356
5357 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5358
5359 if (afi == AFI_IP)
5360 {
5361 if (safi == SAFI_MULTICAST)
5362 vty_out (vty, "ipv4 multicast");
5363 else if (safi == SAFI_MPLS_VPN)
Lou Bergera3fda882016-01-12 13:42:04 -05005364 vty_out (vty, "vpnv4");
5365 else if (safi == SAFI_ENCAP)
5366 vty_out (vty, "encap");
paul718e3742002-12-13 20:15:29 +00005367 }
5368 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005369 {
Lou Berger13c378d2016-01-12 13:41:56 -05005370 if (safi == SAFI_MPLS_VPN)
5371 vty_out (vty, "vpnv6");
Lou Bergera3fda882016-01-12 13:42:04 -05005372 else if (safi == SAFI_ENCAP)
5373 vty_out (vty, "encapv6");
Lou Berger13c378d2016-01-12 13:41:56 -05005374 else
5375 {
5376 vty_out (vty, "ipv6");
5377 if (safi == SAFI_MULTICAST)
5378 vty_out (vty, " multicast");
5379 }
Paul Jakma37a217a2007-04-10 19:20:29 +00005380 }
paul718e3742002-12-13 20:15:29 +00005381
5382 vty_out (vty, "%s", VTY_NEWLINE);
5383
5384 *write = 1;
5385}
5386
5387/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005388static int
paul718e3742002-12-13 20:15:29 +00005389bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5390 safi_t safi)
5391{
5392 int write = 0;
5393 struct peer *peer;
5394 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005395 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005396
5397 bgp_config_write_network (vty, bgp, afi, safi, &write);
5398
5399 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5400
paul1eb8ef22005-04-07 07:30:20 +00005401 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005402 {
5403 if (group->conf->afc[afi][safi])
5404 {
5405 bgp_config_write_family_header (vty, afi, safi, &write);
5406 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5407 }
5408 }
paul1eb8ef22005-04-07 07:30:20 +00005409 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005410 {
5411 if (peer->afc[afi][safi])
5412 {
5413 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5414 {
5415 bgp_config_write_family_header (vty, afi, safi, &write);
5416 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5417 }
5418 }
5419 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005420
5421 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5422
Roman Hoog Antink6184c392014-03-17 14:01:42 +01005423 bgp_config_write_distance (vty, bgp, afi, safi, &write);
5424
paul718e3742002-12-13 20:15:29 +00005425 if (write)
5426 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5427
5428 return write;
5429}
5430
5431int
5432bgp_config_write (struct vty *vty)
5433{
5434 int write = 0;
5435 struct bgp *bgp;
5436 struct peer_group *group;
5437 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005438 struct listnode *node, *nnode;
5439 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005440
5441 /* BGP Multiple instance. */
5442 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5443 {
5444 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5445 write++;
5446 }
5447
5448 /* BGP Config type. */
5449 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5450 {
5451 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5452 write++;
5453 }
5454
5455 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005456 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005457 {
5458 if (write)
5459 vty_out (vty, "!%s", VTY_NEWLINE);
5460
5461 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005462 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005463
5464 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5465 {
5466 if (bgp->name)
5467 vty_out (vty, " view %s", bgp->name);
5468 }
5469 vty_out (vty, "%s", VTY_NEWLINE);
5470
5471 /* No Synchronization */
5472 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5473 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5474
5475 /* BGP fast-external-failover. */
5476 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5477 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5478
5479 /* BGP router ID. */
5480 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5481 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5482 VTY_NEWLINE);
5483
paul848973c2003-08-13 00:32:49 +00005484 /* BGP log-neighbor-changes. */
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07005485 if (!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5486 vty_out (vty, " no bgp log-neighbor-changes%s", VTY_NEWLINE);
paul848973c2003-08-13 00:32:49 +00005487
paul718e3742002-12-13 20:15:29 +00005488 /* BGP configuration. */
5489 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5490 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5491
5492 /* BGP default ipv4-unicast. */
5493 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5494 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5495
5496 /* BGP default local-preference. */
5497 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5498 vty_out (vty, " bgp default local-preference %d%s",
5499 bgp->default_local_pref, VTY_NEWLINE);
5500
5501 /* BGP client-to-client reflection. */
5502 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5503 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5504
5505 /* BGP cluster ID. */
5506 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5507 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5508 VTY_NEWLINE);
5509
hassoe0701b72004-05-20 09:19:34 +00005510 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005511 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005512 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5513 VTY_NEWLINE);
5514
5515 /* Confederation peer */
5516 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005517 {
hassoe0701b72004-05-20 09:19:34 +00005518 int i;
paul718e3742002-12-13 20:15:29 +00005519
hassoe0701b72004-05-20 09:19:34 +00005520 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005521
hassoe0701b72004-05-20 09:19:34 +00005522 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005523 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005524
hassoe0701b72004-05-20 09:19:34 +00005525 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005526 }
5527
5528 /* BGP enforce-first-as. */
5529 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5530 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5531
5532 /* BGP deterministic-med. */
5533 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5534 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005535
5536 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005537 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5538 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5539 bgp->stalepath_time, VTY_NEWLINE);
Philippe Guibert4afa3dd2016-05-24 16:52:02 +02005540 if (bgp->restart_time != BGP_DEFAULT_RESTART_TIME)
5541 vty_out (vty, " bgp graceful-restart restart-time %d%s",
5542 bgp->restart_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005543 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5544 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5545
paul718e3742002-12-13 20:15:29 +00005546 /* BGP bestpath method. */
5547 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5548 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005549 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5550 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
Pradosh Mohapatra2fdd4552013-09-07 07:02:36 +00005551 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
5552 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
5553 }
Dinesh Dutt083e5e22015-11-09 20:21:54 -05005554 if (bgp_flag_check (bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) {
5555 vty_out (vty, " bgp route-reflector allow-outbound-policy%s",
5556 VTY_NEWLINE);
5557 }
paul718e3742002-12-13 20:15:29 +00005558 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5559 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5560 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5561 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5562 {
5563 vty_out (vty, " bgp bestpath med");
5564 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5565 vty_out (vty, " confed");
5566 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5567 vty_out (vty, " missing-as-worst");
5568 vty_out (vty, "%s", VTY_NEWLINE);
5569 }
5570
5571 /* BGP network import check. */
5572 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5573 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5574
5575 /* BGP scan interval. */
5576 bgp_config_write_scan_time (vty);
5577
5578 /* BGP flag dampening. */
5579 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5580 BGP_CONFIG_DAMPENING))
5581 bgp_config_write_damp (vty);
5582
5583 /* BGP static route configuration. */
5584 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5585
5586 /* BGP redistribute configuration. */
5587 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5588
5589 /* BGP timers configuration. */
5590 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5591 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5592 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5593 bgp->default_holdtime, VTY_NEWLINE);
5594
5595 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005596 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005597 {
5598 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5599 }
5600
5601 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005602 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005603 {
5604 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5605 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5606 }
5607
Josh Bailey165b5ff2011-07-20 20:43:22 -07005608 /* maximum-paths */
5609 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5610
paul718e3742002-12-13 20:15:29 +00005611 /* Distance configuration. */
Roman Hoog Antink6184c392014-03-17 14:01:42 +01005612 bgp_config_write_distance (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
paul718e3742002-12-13 20:15:29 +00005613
5614 /* No auto-summary */
5615 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5616 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5617
5618 /* IPv4 multicast configuration. */
5619 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5620
5621 /* IPv4 VPN configuration. */
5622 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5623
Lou Bergera3fda882016-01-12 13:42:04 -05005624 /* ENCAPv4 configuration. */
5625 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_ENCAP);
5626
paul718e3742002-12-13 20:15:29 +00005627 /* IPv6 unicast configuration. */
5628 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5629
Paul Jakma37a217a2007-04-10 19:20:29 +00005630 /* IPv6 multicast configuration. */
5631 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5632
Lou Berger13c378d2016-01-12 13:41:56 -05005633 /* IPv6 VPN configuration. */
5634 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MPLS_VPN);
5635
Lou Bergera3fda882016-01-12 13:42:04 -05005636 /* ENCAPv6 configuration. */
5637 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_ENCAP);
5638
5639 vty_out (vty, " exit%s", VTY_NEWLINE);
5640
paul718e3742002-12-13 20:15:29 +00005641 write++;
5642 }
5643 return write;
5644}
5645
5646void
paul94f2b392005-06-28 12:44:16 +00005647bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005648{
5649 memset (&bgp_master, 0, sizeof (struct bgp_master));
5650
5651 bm = &bgp_master;
5652 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005653 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005654 bm->port = BGP_PORT_DEFAULT;
5655 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005656 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005657}
paul200df112005-06-01 11:17:05 +00005658
David Lamparter6b0655a2014-06-04 06:53:35 +02005659
paul718e3742002-12-13 20:15:29 +00005660void
paul94f2b392005-06-28 12:44:16 +00005661bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005662{
paul718e3742002-12-13 20:15:29 +00005663 /* BGP VTY commands installation. */
5664 bgp_vty_init ();
5665
paul718e3742002-12-13 20:15:29 +00005666 /* Init zebra. */
Donald Sharp774914f2015-10-14 08:50:39 -04005667 bgp_zebra_init (bm->master);
paul718e3742002-12-13 20:15:29 +00005668
5669 /* BGP inits. */
5670 bgp_attr_init ();
5671 bgp_debug_init ();
5672 bgp_dump_init ();
5673 bgp_route_init ();
5674 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005675 bgp_address_init ();
paul718e3742002-12-13 20:15:29 +00005676 bgp_scan_init ();
5677 bgp_mplsvpn_init ();
Lou Berger298cc2f2016-01-12 13:42:02 -05005678 bgp_encap_init ();
paul718e3742002-12-13 20:15:29 +00005679
5680 /* Access list initialize. */
5681 access_list_init ();
5682 access_list_add_hook (peer_distribute_update);
5683 access_list_delete_hook (peer_distribute_update);
5684
5685 /* Filter list initialize. */
5686 bgp_filter_init ();
5687 as_list_add_hook (peer_aslist_update);
5688 as_list_delete_hook (peer_aslist_update);
5689
5690 /* Prefix list initialize.*/
5691 prefix_list_init ();
5692 prefix_list_add_hook (peer_prefix_list_update);
5693 prefix_list_delete_hook (peer_prefix_list_update);
5694
5695 /* Community list initialize. */
5696 bgp_clist = community_list_init ();
5697
5698#ifdef HAVE_SNMP
5699 bgp_snmp_init ();
5700#endif /* HAVE_SNMP */
5701}
paul545acaf2004-04-20 15:13:15 +00005702
5703void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005704bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005705{
paul545acaf2004-04-20 15:13:15 +00005706 struct bgp *bgp;
5707 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005708 struct listnode *node, *nnode;
5709 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005710
paul1eb8ef22005-04-07 07:30:20 +00005711 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5712 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005713 if (peer->status == Established)
5714 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5715 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005716
paul545acaf2004-04-20 15:13:15 +00005717 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005718
paule210cf92005-06-15 19:15:35 +00005719 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005720 {
5721 work_queue_free (bm->process_main_queue);
5722 bm->process_main_queue = NULL;
5723 }
paule210cf92005-06-15 19:15:35 +00005724 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005725 {
5726 work_queue_free (bm->process_rsclient_queue);
5727 bm->process_rsclient_queue = NULL;
5728 }
paul545acaf2004-04-20 15:13:15 +00005729}