blob: db952c7fc1b0ae107e1f50406f3ac1d370b55825 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* BGP-4, BGP-4+ daemon program
2 Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "prefix.h"
24#include "thread.h"
25#include "buffer.h"
26#include "stream.h"
27#include "command.h"
28#include "sockunion.h"
Timo Teräs5a2a1ec2015-10-22 11:35:18 +030029#include "sockopt.h"
paul718e3742002-12-13 20:15:29 +000030#include "network.h"
31#include "memory.h"
32#include "filter.h"
33#include "routemap.h"
34#include "str.h"
35#include "log.h"
36#include "plist.h"
37#include "linklist.h"
paul200df112005-06-01 11:17:05 +000038#include "workqueue.h"
Lou Berger298cc2f2016-01-12 13:42:02 -050039#include "table.h"
paul718e3742002-12-13 20:15:29 +000040
41#include "bgpd/bgpd.h"
42#include "bgpd/bgp_table.h"
43#include "bgpd/bgp_aspath.h"
44#include "bgpd/bgp_route.h"
45#include "bgpd/bgp_dump.h"
46#include "bgpd/bgp_debug.h"
47#include "bgpd/bgp_community.h"
48#include "bgpd/bgp_attr.h"
49#include "bgpd/bgp_regex.h"
50#include "bgpd/bgp_clist.h"
51#include "bgpd/bgp_fsm.h"
52#include "bgpd/bgp_packet.h"
53#include "bgpd/bgp_zebra.h"
54#include "bgpd/bgp_open.h"
55#include "bgpd/bgp_filter.h"
56#include "bgpd/bgp_nexthop.h"
57#include "bgpd/bgp_damp.h"
58#include "bgpd/bgp_mplsvpn.h"
Lou Berger298cc2f2016-01-12 13:42:02 -050059#include "bgpd/bgp_encap.h"
paul718e3742002-12-13 20:15:29 +000060#include "bgpd/bgp_advertise.h"
61#include "bgpd/bgp_network.h"
62#include "bgpd/bgp_vty.h"
Josh Bailey165b5ff2011-07-20 20:43:22 -070063#include "bgpd/bgp_mpath.h"
paul718e3742002-12-13 20:15:29 +000064#ifdef HAVE_SNMP
65#include "bgpd/bgp_snmp.h"
66#endif /* HAVE_SNMP */
David Lamparter6b0655a2014-06-04 06:53:35 +020067
paul718e3742002-12-13 20:15:29 +000068/* BGP process wide configuration. */
69static struct bgp_master bgp_master;
70
hasso18a6dce2004-10-03 18:18:34 +000071extern struct in_addr router_id_zebra;
72
paul718e3742002-12-13 20:15:29 +000073/* BGP process wide configuration pointer to export. */
74struct bgp_master *bm;
75
76/* BGP community-list. */
77struct community_list_handler *bgp_clist;
David Lamparter6b0655a2014-06-04 06:53:35 +020078
paul718e3742002-12-13 20:15:29 +000079/* BGP global flag manipulation. */
80int
81bgp_option_set (int flag)
82{
83 switch (flag)
84 {
85 case BGP_OPT_NO_FIB:
86 case BGP_OPT_MULTIPLE_INSTANCE:
87 case BGP_OPT_CONFIG_CISCO:
Paul Jakmacccbc012012-06-14 10:40:26 +010088 case BGP_OPT_NO_LISTEN:
paul718e3742002-12-13 20:15:29 +000089 SET_FLAG (bm->options, flag);
90 break;
91 default:
92 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +000093 }
94 return 0;
95}
96
97int
98bgp_option_unset (int flag)
99{
100 switch (flag)
101 {
102 case BGP_OPT_MULTIPLE_INSTANCE:
103 if (listcount (bm->bgp) > 1)
104 return BGP_ERR_MULTIPLE_INSTANCE_USED;
105 /* Fall through. */
106 case BGP_OPT_NO_FIB:
107 case BGP_OPT_CONFIG_CISCO:
108 UNSET_FLAG (bm->options, flag);
109 break;
110 default:
111 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +0000112 }
113 return 0;
114}
115
116int
117bgp_option_check (int flag)
118{
119 return CHECK_FLAG (bm->options, flag);
120}
David Lamparter6b0655a2014-06-04 06:53:35 +0200121
paul718e3742002-12-13 20:15:29 +0000122/* BGP flag manipulation. */
123int
124bgp_flag_set (struct bgp *bgp, int flag)
125{
126 SET_FLAG (bgp->flags, flag);
127 return 0;
128}
129
130int
131bgp_flag_unset (struct bgp *bgp, int flag)
132{
133 UNSET_FLAG (bgp->flags, flag);
134 return 0;
135}
136
137int
138bgp_flag_check (struct bgp *bgp, int flag)
139{
140 return CHECK_FLAG (bgp->flags, flag);
141}
David Lamparter6b0655a2014-06-04 06:53:35 +0200142
paul718e3742002-12-13 20:15:29 +0000143/* Internal function to set BGP structure configureation flag. */
144static void
145bgp_config_set (struct bgp *bgp, int config)
146{
147 SET_FLAG (bgp->config, config);
148}
149
150static void
151bgp_config_unset (struct bgp *bgp, int config)
152{
153 UNSET_FLAG (bgp->config, config);
154}
155
156static int
157bgp_config_check (struct bgp *bgp, int config)
158{
159 return CHECK_FLAG (bgp->config, config);
160}
David Lamparter6b0655a2014-06-04 06:53:35 +0200161
paul718e3742002-12-13 20:15:29 +0000162/* Set BGP router identifier. */
David Lamparter584083d2016-05-24 18:58:08 +0200163static int
paul718e3742002-12-13 20:15:29 +0000164bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
165{
166 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000167 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000168
169 if (bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID)
170 && IPV4_ADDR_SAME (&bgp->router_id, id))
171 return 0;
172
173 IPV4_ADDR_COPY (&bgp->router_id, id);
174 bgp_config_set (bgp, BGP_CONFIG_ROUTER_ID);
175
176 /* Set all peer's local identifier with this value. */
paul1eb8ef22005-04-07 07:30:20 +0000177 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000178 {
179 IPV4_ADDR_COPY (&peer->local_id, id);
180
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000181 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000182 {
183 peer->last_reset = PEER_DOWN_RID_CHANGE;
184 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
185 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
186 }
paul718e3742002-12-13 20:15:29 +0000187 }
188 return 0;
189}
190
David Lamparter584083d2016-05-24 18:58:08 +0200191void
192bgp_router_id_zebra_bump (void)
193{
194 struct listnode *node, *nnode;
195 struct bgp *bgp;
196
197 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
198 {
199 if (!bgp->router_id_static.s_addr)
200 bgp_router_id_set (bgp, &router_id_zebra);
201 }
202}
203
204int
205bgp_router_id_static_set (struct bgp *bgp, struct in_addr id)
206{
207 bgp->router_id_static = id;
208 bgp_router_id_set (bgp, id.s_addr ? &id : &router_id_zebra);
209 return 0;
210}
211
paul718e3742002-12-13 20:15:29 +0000212/* BGP's cluster-id control. */
213int
214bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
215{
216 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000217 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000218
219 if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)
220 && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id))
221 return 0;
222
223 IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id);
224 bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID);
225
226 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000227 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000228 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000229 if (peer->sort != BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +0000230 continue;
231
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000232 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000233 {
234 peer->last_reset = PEER_DOWN_CLID_CHANGE;
235 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
236 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
237 }
paul718e3742002-12-13 20:15:29 +0000238 }
239 return 0;
240}
241
242int
243bgp_cluster_id_unset (struct bgp *bgp)
244{
245 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000246 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000247
248 if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID))
249 return 0;
250
251 bgp->cluster_id.s_addr = 0;
252 bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID);
253
254 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000255 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000256 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000257 if (peer->sort != BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +0000258 continue;
259
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000260 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000261 {
262 peer->last_reset = PEER_DOWN_CLID_CHANGE;
263 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
264 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
265 }
paul718e3742002-12-13 20:15:29 +0000266 }
267 return 0;
268}
David Lamparter6b0655a2014-06-04 06:53:35 +0200269
Stephen Hemminger65957882010-01-15 16:22:10 +0300270/* time_t value that is monotonicly increasing
271 * and uneffected by adjustments to system clock
272 */
273time_t bgp_clock (void)
274{
275 struct timeval tv;
276
277 quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv);
278 return tv.tv_sec;
279}
280
paul718e3742002-12-13 20:15:29 +0000281/* BGP timer configuration. */
282int
283bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
284{
285 bgp->default_keepalive = (keepalive < holdtime / 3
286 ? keepalive : holdtime / 3);
287 bgp->default_holdtime = holdtime;
288
289 return 0;
290}
291
292int
293bgp_timers_unset (struct bgp *bgp)
294{
295 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
296 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
297
298 return 0;
299}
David Lamparter6b0655a2014-06-04 06:53:35 +0200300
paul718e3742002-12-13 20:15:29 +0000301/* BGP confederation configuration. */
302int
303bgp_confederation_id_set (struct bgp *bgp, as_t as)
304{
305 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000306 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000307 int already_confed;
308
309 if (as == 0)
310 return BGP_ERR_INVALID_AS;
311
312 /* Remember - were we doing confederation before? */
313 already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);
314 bgp->confed_id = as;
315 bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);
316
317 /* If we were doing confederation already, this is just an external
318 AS change. Just Reset EBGP sessions, not CONFED sessions. If we
319 were not doing confederation before, reset all EBGP sessions. */
paul1eb8ef22005-04-07 07:30:20 +0000320 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000321 {
322 /* We're looking for peers who's AS is not local or part of our
323 confederation. */
324 if (already_confed)
325 {
326 if (peer_sort (peer) == BGP_PEER_EBGP)
327 {
328 peer->local_as = as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000329 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000330 {
331 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
332 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
333 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
334 }
335
paul718e3742002-12-13 20:15:29 +0000336 else
337 BGP_EVENT_ADD (peer, BGP_Stop);
338 }
339 }
340 else
341 {
342 /* Not doign confederation before, so reset every non-local
343 session */
344 if (peer_sort (peer) != BGP_PEER_IBGP)
345 {
346 /* Reset the local_as to be our EBGP one */
347 if (peer_sort (peer) == BGP_PEER_EBGP)
348 peer->local_as = as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000349 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000350 {
351 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
352 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
353 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
354 }
paul718e3742002-12-13 20:15:29 +0000355 else
356 BGP_EVENT_ADD (peer, BGP_Stop);
357 }
358 }
359 }
360 return 0;
361}
362
363int
364bgp_confederation_id_unset (struct bgp *bgp)
365{
366 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000367 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000368
369 bgp->confed_id = 0;
370 bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
371
paul1eb8ef22005-04-07 07:30:20 +0000372 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000373 {
374 /* We're looking for peers who's AS is not local */
375 if (peer_sort (peer) != BGP_PEER_IBGP)
376 {
377 peer->local_as = bgp->as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000378 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000379 {
380 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
381 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
382 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
383 }
384
paul718e3742002-12-13 20:15:29 +0000385 else
386 BGP_EVENT_ADD (peer, BGP_Stop);
387 }
388 }
389 return 0;
390}
391
392/* Is an AS part of the confed or not? */
393int
394bgp_confederation_peers_check (struct bgp *bgp, as_t as)
395{
396 int i;
397
398 if (! bgp)
399 return 0;
400
401 for (i = 0; i < bgp->confed_peers_cnt; i++)
402 if (bgp->confed_peers[i] == as)
403 return 1;
404
405 return 0;
406}
407
408/* Add an AS to the confederation set. */
409int
410bgp_confederation_peers_add (struct bgp *bgp, as_t as)
411{
412 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000413 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000414
415 if (! bgp)
416 return BGP_ERR_INVALID_BGP;
417
418 if (bgp->as == as)
419 return BGP_ERR_INVALID_AS;
420
421 if (bgp_confederation_peers_check (bgp, as))
422 return -1;
423
424 if (bgp->confed_peers)
425 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
426 bgp->confed_peers,
427 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
428 else
429 bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST,
430 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
431
432 bgp->confed_peers[bgp->confed_peers_cnt] = as;
433 bgp->confed_peers_cnt++;
434
435 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
436 {
paul1eb8ef22005-04-07 07:30:20 +0000437 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000438 {
439 if (peer->as == as)
440 {
441 peer->local_as = bgp->as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000442 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000443 {
444 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
445 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
446 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
447 }
paul718e3742002-12-13 20:15:29 +0000448 else
449 BGP_EVENT_ADD (peer, BGP_Stop);
450 }
451 }
452 }
453 return 0;
454}
455
456/* Delete an AS from the confederation set. */
457int
458bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
459{
460 int i;
461 int j;
462 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000463 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000464
465 if (! bgp)
466 return -1;
467
468 if (! bgp_confederation_peers_check (bgp, as))
469 return -1;
470
471 for (i = 0; i < bgp->confed_peers_cnt; i++)
472 if (bgp->confed_peers[i] == as)
473 for(j = i + 1; j < bgp->confed_peers_cnt; j++)
474 bgp->confed_peers[j - 1] = bgp->confed_peers[j];
475
476 bgp->confed_peers_cnt--;
477
478 if (bgp->confed_peers_cnt == 0)
479 {
480 if (bgp->confed_peers)
481 XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
482 bgp->confed_peers = NULL;
483 }
484 else
485 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
486 bgp->confed_peers,
487 bgp->confed_peers_cnt * sizeof (as_t));
488
489 /* Now reset any peer who's remote AS has just been removed from the
490 CONFED */
491 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
492 {
paul1eb8ef22005-04-07 07:30:20 +0000493 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000494 {
495 if (peer->as == as)
496 {
497 peer->local_as = bgp->confed_id;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000498 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000499 {
500 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
501 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
502 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
503 }
paul718e3742002-12-13 20:15:29 +0000504 else
505 BGP_EVENT_ADD (peer, BGP_Stop);
506 }
507 }
508 }
509
510 return 0;
511}
David Lamparter6b0655a2014-06-04 06:53:35 +0200512
paul718e3742002-12-13 20:15:29 +0000513/* Local preference configuration. */
514int
515bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
516{
517 if (! bgp)
518 return -1;
519
paul718e3742002-12-13 20:15:29 +0000520 bgp->default_local_pref = local_pref;
521
522 return 0;
523}
524
525int
526bgp_default_local_preference_unset (struct bgp *bgp)
527{
528 if (! bgp)
529 return -1;
530
paul718e3742002-12-13 20:15:29 +0000531 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
532
533 return 0;
534}
David Lamparter6b0655a2014-06-04 06:53:35 +0200535
paulfee0f4c2004-09-13 05:12:46 +0000536/* If peer is RSERVER_CLIENT in at least one address family and is not member
537 of a peer_group for that family, return 1.
538 Used to check wether the peer is included in list bgp->rsclient. */
539int
540peer_rsclient_active (struct peer *peer)
541{
542 int i;
543 int j;
544
545 for (i=AFI_IP; i < AFI_MAX; i++)
546 for (j=SAFI_UNICAST; j < SAFI_MAX; j++)
547 if (CHECK_FLAG(peer->af_flags[i][j], PEER_FLAG_RSERVER_CLIENT)
548 && ! peer->af_group[i][j])
549 return 1;
550 return 0;
551}
552
pauleb821182004-05-01 08:44:08 +0000553/* Peer comparison function for sorting. */
paul718e3742002-12-13 20:15:29 +0000554static int
555peer_cmp (struct peer *p1, struct peer *p2)
556{
pauleb821182004-05-01 08:44:08 +0000557 return sockunion_cmp (&p1->su, &p2->su);
paul718e3742002-12-13 20:15:29 +0000558}
559
560int
561peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
562{
563 return CHECK_FLAG (peer->af_flags[afi][safi], flag);
564}
565
566/* Reset all address family specific configuration. */
567static void
568peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
569{
570 int i;
571 struct bgp_filter *filter;
572 char orf_name[BUFSIZ];
573
574 filter = &peer->filter[afi][safi];
575
576 /* Clear neighbor filter and route-map */
577 for (i = FILTER_IN; i < FILTER_MAX; i++)
578 {
579 if (filter->dlist[i].name)
580 {
581 free (filter->dlist[i].name);
582 filter->dlist[i].name = NULL;
583 }
584 if (filter->plist[i].name)
585 {
586 free (filter->plist[i].name);
587 filter->plist[i].name = NULL;
588 }
589 if (filter->aslist[i].name)
590 {
591 free (filter->aslist[i].name);
592 filter->aslist[i].name = NULL;
593 }
paulfee0f4c2004-09-13 05:12:46 +0000594 }
595 for (i = RMAP_IN; i < RMAP_MAX; i++)
596 {
paul718e3742002-12-13 20:15:29 +0000597 if (filter->map[i].name)
598 {
599 free (filter->map[i].name);
600 filter->map[i].name = NULL;
601 }
602 }
603
604 /* Clear unsuppress map. */
605 if (filter->usmap.name)
606 free (filter->usmap.name);
607 filter->usmap.name = NULL;
608 filter->usmap.map = NULL;
609
610 /* Clear neighbor's all address family flags. */
611 peer->af_flags[afi][safi] = 0;
612
613 /* Clear neighbor's all address family sflags. */
614 peer->af_sflags[afi][safi] = 0;
615
616 /* Clear neighbor's all address family capabilities. */
617 peer->af_cap[afi][safi] = 0;
618
619 /* Clear ORF info */
620 peer->orf_plist[afi][safi] = NULL;
621 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
David Lamparterc9c06d02015-04-13 10:21:35 +0200622 prefix_bgp_orf_remove_all (afi, orf_name);
paul718e3742002-12-13 20:15:29 +0000623
624 /* Set default neighbor send-community. */
625 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
626 {
627 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
628 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
629 }
630
631 /* Clear neighbor default_originate_rmap */
632 if (peer->default_rmap[afi][safi].name)
633 free (peer->default_rmap[afi][safi].name);
634 peer->default_rmap[afi][safi].name = NULL;
635 peer->default_rmap[afi][safi].map = NULL;
636
637 /* Clear neighbor maximum-prefix */
638 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +0000639 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000640}
641
642/* peer global config reset */
paul94f2b392005-06-28 12:44:16 +0000643static void
paul718e3742002-12-13 20:15:29 +0000644peer_global_config_reset (struct peer *peer)
645{
646 peer->weight = 0;
647 peer->change_local_as = 0;
648 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
649 if (peer->update_source)
650 {
651 sockunion_free (peer->update_source);
652 peer->update_source = NULL;
653 }
654 if (peer->update_if)
655 {
656 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
657 peer->update_if = NULL;
658 }
659
660 if (peer_sort (peer) == BGP_PEER_IBGP)
661 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
662 else
663 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
664
665 peer->flags = 0;
666 peer->config = 0;
667 peer->holdtime = 0;
668 peer->keepalive = 0;
669 peer->connect = 0;
670 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
671}
672
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000673/* Check peer's AS number and determines if this peer is IBGP or EBGP */
674static bgp_peer_sort_t
675peer_calc_sort (struct peer *peer)
paul718e3742002-12-13 20:15:29 +0000676{
677 struct bgp *bgp;
678
679 bgp = peer->bgp;
680
681 /* Peer-group */
682 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
683 {
684 if (peer->as)
685 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
686 else
687 {
688 struct peer *peer1;
689 peer1 = listnode_head (peer->group->peer);
690 if (peer1)
691 return (peer1->local_as == peer1->as
692 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
693 }
694 return BGP_PEER_INTERNAL;
695 }
696
697 /* Normal peer */
698 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
699 {
700 if (peer->local_as == 0)
701 return BGP_PEER_INTERNAL;
702
703 if (peer->local_as == peer->as)
704 {
705 if (peer->local_as == bgp->confed_id)
706 return BGP_PEER_EBGP;
707 else
708 return BGP_PEER_IBGP;
709 }
710
711 if (bgp_confederation_peers_check (bgp, peer->as))
712 return BGP_PEER_CONFED;
713
714 return BGP_PEER_EBGP;
715 }
716 else
717 {
718 return (peer->local_as == 0
719 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
720 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
721 }
722}
723
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000724/* Calculate and cache the peer "sort" */
725bgp_peer_sort_t
726peer_sort (struct peer *peer)
727{
728 peer->sort = peer_calc_sort (peer);
729 return peer->sort;
730}
731
Paul Jakmaf63f06d2011-04-08 12:44:43 +0100732static void
paul200df112005-06-01 11:17:05 +0000733peer_free (struct peer *peer)
734{
Paul Jakmaca058a32006-09-14 02:58:49 +0000735 assert (peer->status == Deleted);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700736
737 bgp_unlock(peer->bgp);
738
Paul Jakmaca058a32006-09-14 02:58:49 +0000739 /* this /ought/ to have been done already through bgp_stop earlier,
740 * but just to be sure..
741 */
742 bgp_timer_set (peer);
743 BGP_READ_OFF (peer->t_read);
744 BGP_WRITE_OFF (peer->t_write);
Paul Jakma9fde6622006-09-14 03:02:02 +0000745 BGP_EVENT_FLUSH (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +0000746
paul200df112005-06-01 11:17:05 +0000747 if (peer->desc)
Daniel Walton363c9032015-10-21 06:42:54 -0700748 {
749 XFREE (MTYPE_PEER_DESC, peer->desc);
750 peer->desc = NULL;
751 }
paul200df112005-06-01 11:17:05 +0000752
753 /* Free allocated host character. */
754 if (peer->host)
Daniel Walton363c9032015-10-21 06:42:54 -0700755 {
756 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
757 peer->host = NULL;
758 }
759
paul200df112005-06-01 11:17:05 +0000760 /* Update source configuration. */
761 if (peer->update_source)
Daniel Walton363c9032015-10-21 06:42:54 -0700762 {
763 sockunion_free (peer->update_source);
764 peer->update_source = NULL;
765 }
paul200df112005-06-01 11:17:05 +0000766
767 if (peer->update_if)
Daniel Walton363c9032015-10-21 06:42:54 -0700768 {
769 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
770 peer->update_if = NULL;
771 }
Paul Jakmaa625ca32006-03-30 14:12:38 +0000772
773 if (peer->clear_node_queue)
Daniel Walton363c9032015-10-21 06:42:54 -0700774 {
775 work_queue_free(peer->clear_node_queue);
776 peer->clear_node_queue = NULL;
777 }
Paul Jakmaa625ca32006-03-30 14:12:38 +0000778
Lou Berger056f3762013-04-10 12:30:04 -0700779 if (peer->notify.data)
780 XFREE(MTYPE_TMP, peer->notify.data);
781
Paul Jakmaca058a32006-09-14 02:58:49 +0000782 bgp_sync_delete (peer);
paul200df112005-06-01 11:17:05 +0000783 memset (peer, 0, sizeof (struct peer));
784
785 XFREE (MTYPE_BGP_PEER, peer);
786}
787
788/* increase reference count on a struct peer */
789struct peer *
Donald Sharp104576d2015-09-16 13:17:55 -0400790peer_lock_with_caller (const char *name, struct peer *peer)
paul200df112005-06-01 11:17:05 +0000791{
792 assert (peer && (peer->lock >= 0));
Donald Sharp104576d2015-09-16 13:17:55 -0400793
794#if 0
795 zlog_debug("%s peer_lock %p %d", name, peer, peer->lock);
796#endif
797
paul200df112005-06-01 11:17:05 +0000798 peer->lock++;
799
800 return peer;
801}
802
803/* decrease reference count on a struct peer
804 * struct peer is freed and NULL returned if last reference
805 */
806struct peer *
Donald Sharp104576d2015-09-16 13:17:55 -0400807peer_unlock_with_caller (const char *name, struct peer *peer)
paul200df112005-06-01 11:17:05 +0000808{
809 assert (peer && (peer->lock > 0));
Donald Sharp104576d2015-09-16 13:17:55 -0400810
811#if 0
812 zlog_debug("%s peer_unlock %p %d", name, peer, peer->lock);
813#endif
814
paul200df112005-06-01 11:17:05 +0000815 peer->lock--;
816
817 if (peer->lock == 0)
818 {
paul200df112005-06-01 11:17:05 +0000819 peer_free (peer);
820 return NULL;
821 }
822
paul200df112005-06-01 11:17:05 +0000823 return peer;
824}
825
826/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000827static struct peer *
Paul Jakma6f585442006-10-22 19:13:07 +0000828peer_new (struct bgp *bgp)
paul718e3742002-12-13 20:15:29 +0000829{
830 afi_t afi;
831 safi_t safi;
832 struct peer *peer;
833 struct servent *sp;
Paul Jakma6f585442006-10-22 19:13:07 +0000834
835 /* bgp argument is absolutely required */
836 assert (bgp);
837 if (!bgp)
838 return NULL;
839
paul718e3742002-12-13 20:15:29 +0000840 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000841 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000842
843 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000844 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000845 peer->v_start = BGP_INIT_START_TIMER;
846 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
paul718e3742002-12-13 20:15:29 +0000847 peer->status = Idle;
848 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000849 peer->weight = 0;
Paul Jakma0df7c912008-07-21 21:02:49 +0000850 peer->password = NULL;
Paul Jakma6f585442006-10-22 19:13:07 +0000851 peer->bgp = bgp;
Paul Jakmaca058a32006-09-14 02:58:49 +0000852 peer = peer_lock (peer); /* initial reference */
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700853 bgp_lock (bgp);
paul718e3742002-12-13 20:15:29 +0000854
855 /* Set default flags. */
856 for (afi = AFI_IP; afi < AFI_MAX; afi++)
857 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
858 {
859 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
860 {
861 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
862 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
863 }
864 peer->orf_plist[afi][safi] = NULL;
865 }
866 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
867
868 /* Create buffers. */
869 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
870 peer->obuf = stream_fifo_new ();
871 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000872 peer->scratch = stream_new (BGP_MAX_PACKET_SIZE);
paul718e3742002-12-13 20:15:29 +0000873
874 bgp_sync_init (peer);
875
876 /* Get service port number. */
877 sp = getservbyname ("bgp", "tcp");
878 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
879
880 return peer;
881}
882
883/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000884static struct peer *
paul718e3742002-12-13 20:15:29 +0000885peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
886 as_t remote_as, afi_t afi, safi_t safi)
887{
888 int active;
889 struct peer *peer;
890 char buf[SU_ADDRSTRLEN];
891
Paul Jakma6f585442006-10-22 19:13:07 +0000892 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000893 peer->su = *su;
894 peer->local_as = local_as;
895 peer->as = remote_as;
896 peer->local_id = bgp->router_id;
897 peer->v_holdtime = bgp->default_holdtime;
898 peer->v_keepalive = bgp->default_keepalive;
899 if (peer_sort (peer) == BGP_PEER_IBGP)
900 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
901 else
902 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000903
904 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000905 listnode_add_sort (bgp->peer, peer);
906
907 active = peer_active (peer);
908
909 if (afi && safi)
910 peer->afc[afi][safi] = 1;
911
Stephen Hemminger65957882010-01-15 16:22:10 +0300912 /* Last read and reset time set */
913 peer->readtime = peer->resettime = bgp_clock ();
paul848973c2003-08-13 00:32:49 +0000914
paul718e3742002-12-13 20:15:29 +0000915 /* Default TTL set. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000916 peer->ttl = (peer->sort == BGP_PEER_IBGP) ? 255 : 1;
paul718e3742002-12-13 20:15:29 +0000917
918 /* Make peer's address string. */
919 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000920 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000921
922 /* Set up peer's events and timers. */
923 if (! active && peer_active (peer))
924 bgp_timer_set (peer);
925
926 return peer;
927}
928
pauleb821182004-05-01 08:44:08 +0000929/* Make accept BGP peer. Called from bgp_accept (). */
930struct peer *
931peer_create_accept (struct bgp *bgp)
932{
933 struct peer *peer;
934
Paul Jakma6f585442006-10-22 19:13:07 +0000935 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000936
937 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000938 listnode_add_sort (bgp->peer, peer);
939
940 return peer;
941}
942
paul718e3742002-12-13 20:15:29 +0000943/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000944static void
paul718e3742002-12-13 20:15:29 +0000945peer_as_change (struct peer *peer, as_t as)
946{
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000947 bgp_peer_sort_t type;
Daniel Walton0d7435f2015-10-22 11:35:20 +0300948 struct peer *conf;
paul718e3742002-12-13 20:15:29 +0000949
950 /* Stop peer. */
951 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
952 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000953 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000954 {
955 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
956 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
957 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
958 }
paul718e3742002-12-13 20:15:29 +0000959 else
960 BGP_EVENT_ADD (peer, BGP_Stop);
961 }
962 type = peer_sort (peer);
963 peer->as = as;
964
paul848973c2003-08-13 00:32:49 +0000965 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
966 && ! bgp_confederation_peers_check (peer->bgp, as)
967 && peer->bgp->as != as)
968 peer->local_as = peer->bgp->confed_id;
969 else
970 peer->local_as = peer->bgp->as;
971
paul718e3742002-12-13 20:15:29 +0000972 /* Advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +0300973 conf = NULL;
974 if (peer->group)
975 conf = peer->group->conf;
976
977 if (conf && CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
978 peer->v_routeadv = conf->routeadv;
paul718e3742002-12-13 20:15:29 +0000979 else
Daniel Walton0d7435f2015-10-22 11:35:20 +0300980 if (peer_sort (peer) == BGP_PEER_IBGP)
981 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
982 else
983 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul718e3742002-12-13 20:15:29 +0000984
985 /* TTL reset */
986 if (peer_sort (peer) == BGP_PEER_IBGP)
987 peer->ttl = 255;
988 else if (type == BGP_PEER_IBGP)
989 peer->ttl = 1;
990
991 /* reflector-client reset */
992 if (peer_sort (peer) != BGP_PEER_IBGP)
993 {
994 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
995 PEER_FLAG_REFLECTOR_CLIENT);
996 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
997 PEER_FLAG_REFLECTOR_CLIENT);
998 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
999 PEER_FLAG_REFLECTOR_CLIENT);
Lou Berger298cc2f2016-01-12 13:42:02 -05001000 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_ENCAP],
1001 PEER_FLAG_REFLECTOR_CLIENT);
paul718e3742002-12-13 20:15:29 +00001002 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
1003 PEER_FLAG_REFLECTOR_CLIENT);
1004 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
1005 PEER_FLAG_REFLECTOR_CLIENT);
Lou Berger9da04bc2016-01-12 13:41:55 -05001006 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MPLS_VPN],
1007 PEER_FLAG_REFLECTOR_CLIENT);
Lou Berger298cc2f2016-01-12 13:42:02 -05001008 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_ENCAP],
1009 PEER_FLAG_REFLECTOR_CLIENT);
paul718e3742002-12-13 20:15:29 +00001010 }
1011
1012 /* local-as reset */
1013 if (peer_sort (peer) != BGP_PEER_EBGP)
1014 {
1015 peer->change_local_as = 0;
1016 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001017 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001018 }
1019}
1020
1021/* If peer does not exist, create new one. If peer already exists,
1022 set AS number to the peer. */
1023int
1024peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
1025 afi_t afi, safi_t safi)
1026{
1027 struct peer *peer;
1028 as_t local_as;
1029
1030 peer = peer_lookup (bgp, su);
1031
1032 if (peer)
1033 {
1034 /* When this peer is a member of peer-group. */
1035 if (peer->group)
1036 {
1037 if (peer->group->conf->as)
1038 {
1039 /* Return peer group's AS number. */
1040 *as = peer->group->conf->as;
1041 return BGP_ERR_PEER_GROUP_MEMBER;
1042 }
1043 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
1044 {
1045 if (bgp->as != *as)
1046 {
1047 *as = peer->as;
1048 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1049 }
1050 }
1051 else
1052 {
1053 if (bgp->as == *as)
1054 {
1055 *as = peer->as;
1056 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1057 }
1058 }
1059 }
1060
1061 /* Existing peer's AS number change. */
1062 if (peer->as != *as)
1063 peer_as_change (peer, *as);
1064 }
1065 else
1066 {
1067
1068 /* If the peer is not part of our confederation, and its not an
1069 iBGP peer then spoof the source AS */
1070 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1071 && ! bgp_confederation_peers_check (bgp, *as)
1072 && bgp->as != *as)
1073 local_as = bgp->confed_id;
1074 else
1075 local_as = bgp->as;
1076
1077 /* If this is IPv4 unicast configuration and "no bgp default
1078 ipv4-unicast" is specified. */
1079
1080 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1081 && afi == AFI_IP && safi == SAFI_UNICAST)
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001082 peer_create (su, bgp, local_as, *as, 0, 0);
paul718e3742002-12-13 20:15:29 +00001083 else
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001084 peer_create (su, bgp, local_as, *as, afi, safi);
paul718e3742002-12-13 20:15:29 +00001085 }
1086
1087 return 0;
1088}
1089
1090/* Activate the peer or peer group for specified AFI and SAFI. */
1091int
1092peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1093{
1094 int active;
1095
1096 if (peer->afc[afi][safi])
1097 return 0;
1098
1099 /* Activate the address family configuration. */
1100 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1101 peer->afc[afi][safi] = 1;
1102 else
1103 {
1104 active = peer_active (peer);
1105
1106 peer->afc[afi][safi] = 1;
1107
1108 if (! active && peer_active (peer))
1109 bgp_timer_set (peer);
1110 else
1111 {
1112 if (peer->status == Established)
1113 {
1114 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1115 {
1116 peer->afc_adv[afi][safi] = 1;
1117 bgp_capability_send (peer, afi, safi,
1118 CAPABILITY_CODE_MP,
1119 CAPABILITY_ACTION_SET);
1120 if (peer->afc_recv[afi][safi])
1121 {
1122 peer->afc_nego[afi][safi] = 1;
1123 bgp_announce_route (peer, afi, safi);
1124 }
1125 }
1126 else
hassoe0701b72004-05-20 09:19:34 +00001127 {
1128 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1129 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1130 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1131 }
paul718e3742002-12-13 20:15:29 +00001132 }
1133 }
1134 }
1135 return 0;
1136}
1137
1138int
1139peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1140{
1141 struct peer_group *group;
1142 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001143 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001144
1145 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1146 {
1147 group = peer->group;
1148
paul1eb8ef22005-04-07 07:30:20 +00001149 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001150 {
1151 if (peer1->af_group[afi][safi])
1152 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1153 }
1154 }
1155 else
1156 {
1157 if (peer->af_group[afi][safi])
1158 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1159 }
1160
1161 if (! peer->afc[afi][safi])
1162 return 0;
1163
1164 /* De-activate the address family configuration. */
1165 peer->afc[afi][safi] = 0;
1166 peer_af_flag_reset (peer, afi, safi);
1167
1168 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1169 {
1170 if (peer->status == Established)
1171 {
1172 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1173 {
1174 peer->afc_adv[afi][safi] = 0;
1175 peer->afc_nego[afi][safi] = 0;
1176
1177 if (peer_active_nego (peer))
1178 {
1179 bgp_capability_send (peer, afi, safi,
1180 CAPABILITY_CODE_MP,
1181 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001182 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001183 peer->pcount[afi][safi] = 0;
1184 }
1185 else
hassoe0701b72004-05-20 09:19:34 +00001186 {
1187 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1188 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1189 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1190 }
paul718e3742002-12-13 20:15:29 +00001191 }
1192 else
hassoe0701b72004-05-20 09:19:34 +00001193 {
1194 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1195 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1196 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1197 }
paul718e3742002-12-13 20:15:29 +00001198 }
1199 }
1200 return 0;
1201}
1202
David Lamparterdfb9bd72016-05-24 18:58:07 +02001203int
1204peer_afc_set (struct peer *peer, afi_t afi, safi_t safi, int enable)
1205{
1206 if (enable)
1207 return peer_activate (peer, afi, safi);
1208 else
1209 return peer_deactivate (peer, afi, safi);
1210}
1211
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001212static void
hasso93406d82005-02-02 14:40:33 +00001213peer_nsf_stop (struct peer *peer)
1214{
1215 afi_t afi;
1216 safi_t safi;
1217
1218 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1219 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1220
1221 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +04001222 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +00001223 peer->nsf[afi][safi] = 0;
1224
1225 if (peer->t_gr_restart)
1226 {
1227 BGP_TIMER_OFF (peer->t_gr_restart);
1228 if (BGP_DEBUG (events, EVENTS))
1229 zlog_debug ("%s graceful restart timer stopped", peer->host);
1230 }
1231 if (peer->t_gr_stale)
1232 {
1233 BGP_TIMER_OFF (peer->t_gr_stale);
1234 if (BGP_DEBUG (events, EVENTS))
1235 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1236 }
1237 bgp_clear_route_all (peer);
1238}
1239
Paul Jakmaca058a32006-09-14 02:58:49 +00001240/* Delete peer from confguration.
1241 *
1242 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1243 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1244 *
1245 * This function /should/ take care to be idempotent, to guard against
1246 * it being called multiple times through stray events that come in
1247 * that happen to result in this function being called again. That
1248 * said, getting here for a "Deleted" peer is a bug in the neighbour
1249 * FSM.
1250 */
paul718e3742002-12-13 20:15:29 +00001251int
1252peer_delete (struct peer *peer)
1253{
1254 int i;
1255 afi_t afi;
1256 safi_t safi;
1257 struct bgp *bgp;
1258 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001259 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001260
Paul Jakmaca058a32006-09-14 02:58:49 +00001261 assert (peer->status != Deleted);
1262
paul718e3742002-12-13 20:15:29 +00001263 bgp = peer->bgp;
1264
hasso93406d82005-02-02 14:40:33 +00001265 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1266 peer_nsf_stop (peer);
1267
Chris Caputo228da422009-07-18 05:44:03 +00001268 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001269 relationship. */
1270 if (peer->group)
1271 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001272 if ((pn = listnode_lookup (peer->group->peer, peer)))
1273 {
1274 peer = peer_unlock (peer); /* group->peer list reference */
1275 list_delete_node (peer->group->peer, pn);
1276 }
paul718e3742002-12-13 20:15:29 +00001277 peer->group = NULL;
1278 }
paul200df112005-06-01 11:17:05 +00001279
paul718e3742002-12-13 20:15:29 +00001280 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001281 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1282 * executed after peer structure is deleted.
1283 */
hassoe0701b72004-05-20 09:19:34 +00001284 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001285 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001286 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001287
1288 /* Password configuration */
1289 if (peer->password)
1290 {
1291 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1292 peer->password = NULL;
1293
1294 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1295 bgp_md5_set (peer);
1296 }
1297
Paul Jakmaca058a32006-09-14 02:58:49 +00001298 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001299
paul718e3742002-12-13 20:15:29 +00001300 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001301 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1302 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001303 {
Chris Caputo228da422009-07-18 05:44:03 +00001304 peer_unlock (peer); /* bgp peer list reference */
1305 list_delete_node (bgp->peer, pn);
1306 }
paul200df112005-06-01 11:17:05 +00001307
Chris Caputo228da422009-07-18 05:44:03 +00001308 if (peer_rsclient_active (peer)
1309 && (pn = listnode_lookup (bgp->rsclient, peer)))
1310 {
1311 peer_unlock (peer); /* rsclient list reference */
1312 list_delete_node (bgp->rsclient, pn);
1313
1314 /* Clear our own rsclient ribs. */
1315 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1316 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1317 if (CHECK_FLAG(peer->af_flags[afi][safi],
1318 PEER_FLAG_RSERVER_CLIENT))
1319 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001320 }
1321
1322 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1323 member of a peer_group. */
1324 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1325 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1326 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001327 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001328
paul200df112005-06-01 11:17:05 +00001329 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001330 if (peer->ibuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001331 {
1332 stream_free (peer->ibuf);
1333 peer->ibuf = NULL;
1334 }
1335
paul718e3742002-12-13 20:15:29 +00001336 if (peer->obuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001337 {
1338 stream_fifo_free (peer->obuf);
1339 peer->obuf = NULL;
1340 }
1341
paul718e3742002-12-13 20:15:29 +00001342 if (peer->work)
Daniel Walton363c9032015-10-21 06:42:54 -07001343 {
1344 stream_free (peer->work);
1345 peer->work = NULL;
1346 }
1347
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00001348 if (peer->scratch)
Daniel Walton363c9032015-10-21 06:42:54 -07001349 {
1350 stream_free(peer->scratch);
1351 peer->scratch = NULL;
1352 }
Paul Jakma18937402006-07-27 19:05:12 +00001353
paul718e3742002-12-13 20:15:29 +00001354 /* Local and remote addresses. */
1355 if (peer->su_local)
Daniel Walton363c9032015-10-21 06:42:54 -07001356 {
1357 sockunion_free (peer->su_local);
1358 peer->su_local = NULL;
1359 }
1360
paul718e3742002-12-13 20:15:29 +00001361 if (peer->su_remote)
Daniel Walton363c9032015-10-21 06:42:54 -07001362 {
1363 sockunion_free (peer->su_remote);
1364 peer->su_remote = NULL;
1365 }
paul200df112005-06-01 11:17:05 +00001366
paul718e3742002-12-13 20:15:29 +00001367 /* Free filter related memory. */
1368 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1369 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1370 {
1371 filter = &peer->filter[afi][safi];
1372
1373 for (i = FILTER_IN; i < FILTER_MAX; i++)
1374 {
1375 if (filter->dlist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001376 {
1377 free(filter->dlist[i].name);
1378 filter->dlist[i].name = NULL;
1379 }
1380
paul718e3742002-12-13 20:15:29 +00001381 if (filter->plist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001382 {
1383 free(filter->plist[i].name);
1384 filter->plist[i].name = NULL;
1385 }
1386
paul718e3742002-12-13 20:15:29 +00001387 if (filter->aslist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001388 {
1389 free(filter->aslist[i].name);
1390 filter->aslist[i].name = NULL;
1391 }
paul200df112005-06-01 11:17:05 +00001392 }
Daniel Walton363c9032015-10-21 06:42:54 -07001393
paul200df112005-06-01 11:17:05 +00001394 for (i = RMAP_IN; i < RMAP_MAX; i++)
1395 {
paul718e3742002-12-13 20:15:29 +00001396 if (filter->map[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001397 {
1398 free (filter->map[i].name);
1399 filter->map[i].name = NULL;
1400 }
paul718e3742002-12-13 20:15:29 +00001401 }
1402
1403 if (filter->usmap.name)
Daniel Walton363c9032015-10-21 06:42:54 -07001404 {
1405 free (filter->usmap.name);
1406 filter->usmap.name = NULL;
1407 }
paul718e3742002-12-13 20:15:29 +00001408
1409 if (peer->default_rmap[afi][safi].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001410 {
1411 free (peer->default_rmap[afi][safi].name);
1412 peer->default_rmap[afi][safi].name = NULL;
1413 }
paul718e3742002-12-13 20:15:29 +00001414 }
paul200df112005-06-01 11:17:05 +00001415
Lou Berger82dd7072016-01-12 13:41:57 -05001416 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETING))
1417 bgp_peer_clear_node_queue_drain_immediate(peer);
1418
paul200df112005-06-01 11:17:05 +00001419 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001420
1421 return 0;
1422}
David Lamparter6b0655a2014-06-04 06:53:35 +02001423
paul94f2b392005-06-28 12:44:16 +00001424static int
paul718e3742002-12-13 20:15:29 +00001425peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1426{
1427 return strcmp (g1->name, g2->name);
1428}
1429
1430/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001431static int
paul718e3742002-12-13 20:15:29 +00001432peer_group_active (struct peer *peer)
1433{
1434 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1435 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1436 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05001437 || peer->af_group[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00001438 || peer->af_group[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05001439 || peer->af_group[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05001440 || peer->af_group[AFI_IP6][SAFI_MPLS_VPN]
1441 || peer->af_group[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00001442 return 1;
1443 return 0;
1444}
1445
1446/* Peer group cofiguration. */
1447static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001448peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001449{
1450 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1451 sizeof (struct peer_group));
1452}
1453
paul94f2b392005-06-28 12:44:16 +00001454static void
paul718e3742002-12-13 20:15:29 +00001455peer_group_free (struct peer_group *group)
1456{
1457 XFREE (MTYPE_PEER_GROUP, group);
1458}
1459
1460struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001461peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001462{
1463 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001464 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001465
paul1eb8ef22005-04-07 07:30:20 +00001466 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001467 {
1468 if (strcmp (group->name, name) == 0)
1469 return group;
1470 }
1471 return NULL;
1472}
1473
1474struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001475peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001476{
1477 struct peer_group *group;
1478
1479 group = peer_group_lookup (bgp, name);
1480 if (group)
1481 return group;
1482
1483 group = peer_group_new ();
1484 group->bgp = bgp;
1485 group->name = strdup (name);
1486 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001487 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001488 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1489 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001490 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001491 group->conf->group = group;
1492 group->conf->as = 0;
1493 group->conf->ttl = 1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001494 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001495 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1496 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1497 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1498 group->conf->keepalive = 0;
1499 group->conf->holdtime = 0;
1500 group->conf->connect = 0;
1501 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1502 listnode_add_sort (bgp->group, group);
1503
1504 return 0;
1505}
1506
paul94f2b392005-06-28 12:44:16 +00001507static void
paul718e3742002-12-13 20:15:29 +00001508peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1509 afi_t afi, safi_t safi)
1510{
1511 int in = FILTER_IN;
1512 int out = FILTER_OUT;
1513 struct peer *conf;
1514 struct bgp_filter *pfilter;
1515 struct bgp_filter *gfilter;
1516
1517 conf = group->conf;
1518 pfilter = &peer->filter[afi][safi];
1519 gfilter = &conf->filter[afi][safi];
1520
1521 /* remote-as */
1522 if (conf->as)
1523 peer->as = conf->as;
1524
1525 /* remote-as */
1526 if (conf->change_local_as)
1527 peer->change_local_as = conf->change_local_as;
1528
1529 /* TTL */
1530 peer->ttl = conf->ttl;
1531
Nick Hilliardfa411a22011-03-23 15:33:17 +00001532 /* GTSM hops */
1533 peer->gtsm_hops = conf->gtsm_hops;
1534
paul718e3742002-12-13 20:15:29 +00001535 /* Weight */
1536 peer->weight = conf->weight;
1537
1538 /* peer flags apply */
1539 peer->flags = conf->flags;
1540 /* peer af_flags apply */
1541 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1542 /* peer config apply */
1543 peer->config = conf->config;
1544
1545 /* peer timers apply */
1546 peer->holdtime = conf->holdtime;
1547 peer->keepalive = conf->keepalive;
1548 peer->connect = conf->connect;
1549 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1550 peer->v_connect = conf->connect;
1551 else
1552 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1553
1554 /* advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +03001555 if (CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
1556 peer->v_routeadv = conf->routeadv;
paul718e3742002-12-13 20:15:29 +00001557 else
Daniel Walton0d7435f2015-10-22 11:35:20 +03001558 if (peer_sort (peer) == BGP_PEER_IBGP)
1559 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1560 else
1561 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul718e3742002-12-13 20:15:29 +00001562
Paul Jakma0df7c912008-07-21 21:02:49 +00001563 /* password apply */
Roman Hoog Antink0e4303d2013-01-18 13:52:03 +01001564 if (conf->password && !peer->password)
Paul Jakma0df7c912008-07-21 21:02:49 +00001565 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
Paul Jakma0df7c912008-07-21 21:02:49 +00001566
1567 bgp_md5_set (peer);
1568
paul718e3742002-12-13 20:15:29 +00001569 /* maximum-prefix */
1570 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001571 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001572 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001573
1574 /* allowas-in */
1575 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1576
paulfee0f4c2004-09-13 05:12:46 +00001577 /* route-server-client */
1578 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1579 {
1580 /* Make peer's RIB point to group's RIB. */
1581 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1582
1583 /* Import policy. */
1584 if (pfilter->map[RMAP_IMPORT].name)
1585 free (pfilter->map[RMAP_IMPORT].name);
1586 if (gfilter->map[RMAP_IMPORT].name)
1587 {
1588 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1589 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1590 }
1591 else
1592 {
1593 pfilter->map[RMAP_IMPORT].name = NULL;
1594 pfilter->map[RMAP_IMPORT].map = NULL;
1595 }
1596
1597 /* Export policy. */
1598 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1599 {
1600 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1601 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1602 }
1603 }
1604
paul718e3742002-12-13 20:15:29 +00001605 /* default-originate route-map */
1606 if (conf->default_rmap[afi][safi].name)
1607 {
1608 if (peer->default_rmap[afi][safi].name)
1609 free (peer->default_rmap[afi][safi].name);
1610 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1611 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1612 }
1613
1614 /* update-source apply */
1615 if (conf->update_source)
1616 {
1617 if (peer->update_source)
1618 sockunion_free (peer->update_source);
1619 if (peer->update_if)
1620 {
1621 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1622 peer->update_if = NULL;
1623 }
1624 peer->update_source = sockunion_dup (conf->update_source);
1625 }
1626 else if (conf->update_if)
1627 {
1628 if (peer->update_if)
1629 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1630 if (peer->update_source)
1631 {
1632 sockunion_free (peer->update_source);
1633 peer->update_source = NULL;
1634 }
1635 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1636 }
1637
1638 /* inbound filter apply */
1639 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1640 {
1641 if (pfilter->dlist[in].name)
1642 free (pfilter->dlist[in].name);
1643 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1644 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1645 }
1646 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1647 {
1648 if (pfilter->plist[in].name)
1649 free (pfilter->plist[in].name);
1650 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1651 pfilter->plist[in].plist = gfilter->plist[in].plist;
1652 }
1653 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1654 {
1655 if (pfilter->aslist[in].name)
1656 free (pfilter->aslist[in].name);
1657 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1658 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1659 }
paulfee0f4c2004-09-13 05:12:46 +00001660 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001661 {
paulfee0f4c2004-09-13 05:12:46 +00001662 if (pfilter->map[RMAP_IN].name)
1663 free (pfilter->map[RMAP_IN].name);
1664 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1665 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001666 }
1667
1668 /* outbound filter apply */
1669 if (gfilter->dlist[out].name)
1670 {
1671 if (pfilter->dlist[out].name)
1672 free (pfilter->dlist[out].name);
1673 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1674 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1675 }
1676 else
1677 {
1678 if (pfilter->dlist[out].name)
1679 free (pfilter->dlist[out].name);
1680 pfilter->dlist[out].name = NULL;
1681 pfilter->dlist[out].alist = NULL;
1682 }
1683 if (gfilter->plist[out].name)
1684 {
1685 if (pfilter->plist[out].name)
1686 free (pfilter->plist[out].name);
1687 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1688 pfilter->plist[out].plist = gfilter->plist[out].plist;
1689 }
1690 else
1691 {
1692 if (pfilter->plist[out].name)
1693 free (pfilter->plist[out].name);
1694 pfilter->plist[out].name = NULL;
1695 pfilter->plist[out].plist = NULL;
1696 }
1697 if (gfilter->aslist[out].name)
1698 {
1699 if (pfilter->aslist[out].name)
1700 free (pfilter->aslist[out].name);
1701 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1702 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1703 }
1704 else
1705 {
1706 if (pfilter->aslist[out].name)
1707 free (pfilter->aslist[out].name);
1708 pfilter->aslist[out].name = NULL;
1709 pfilter->aslist[out].aslist = NULL;
1710 }
paulfee0f4c2004-09-13 05:12:46 +00001711 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001712 {
paulfee0f4c2004-09-13 05:12:46 +00001713 if (pfilter->map[RMAP_OUT].name)
1714 free (pfilter->map[RMAP_OUT].name);
1715 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1716 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001717 }
1718 else
1719 {
paulfee0f4c2004-09-13 05:12:46 +00001720 if (pfilter->map[RMAP_OUT].name)
1721 free (pfilter->map[RMAP_OUT].name);
1722 pfilter->map[RMAP_OUT].name = NULL;
1723 pfilter->map[RMAP_OUT].map = NULL;
1724 }
1725
1726 /* RS-client's import/export route-maps. */
1727 if (gfilter->map[RMAP_IMPORT].name)
1728 {
1729 if (pfilter->map[RMAP_IMPORT].name)
1730 free (pfilter->map[RMAP_IMPORT].name);
1731 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1732 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1733 }
1734 else
1735 {
1736 if (pfilter->map[RMAP_IMPORT].name)
1737 free (pfilter->map[RMAP_IMPORT].name);
1738 pfilter->map[RMAP_IMPORT].name = NULL;
1739 pfilter->map[RMAP_IMPORT].map = NULL;
1740 }
1741 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1742 {
1743 if (pfilter->map[RMAP_EXPORT].name)
1744 free (pfilter->map[RMAP_EXPORT].name);
1745 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1746 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001747 }
1748
1749 if (gfilter->usmap.name)
1750 {
1751 if (pfilter->usmap.name)
1752 free (pfilter->usmap.name);
1753 pfilter->usmap.name = strdup (gfilter->usmap.name);
1754 pfilter->usmap.map = gfilter->usmap.map;
1755 }
1756 else
1757 {
1758 if (pfilter->usmap.name)
1759 free (pfilter->usmap.name);
1760 pfilter->usmap.name = NULL;
1761 pfilter->usmap.map = NULL;
1762 }
1763}
1764
1765/* Peer group's remote AS configuration. */
1766int
paulfd79ac92004-10-13 05:06:08 +00001767peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001768{
1769 struct peer_group *group;
1770 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001771 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001772
1773 group = peer_group_lookup (bgp, group_name);
1774 if (! group)
1775 return -1;
1776
1777 if (group->conf->as == *as)
1778 return 0;
1779
1780 /* When we setup peer-group AS number all peer group member's AS
1781 number must be updated to same number. */
1782 peer_as_change (group->conf, *as);
1783
paul1eb8ef22005-04-07 07:30:20 +00001784 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001785 {
1786 if (peer->as != *as)
1787 peer_as_change (peer, *as);
1788 }
1789
1790 return 0;
1791}
1792
1793int
1794peer_group_delete (struct peer_group *group)
1795{
1796 struct bgp *bgp;
1797 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001798 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001799
1800 bgp = group->bgp;
1801
paul1eb8ef22005-04-07 07:30:20 +00001802 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001803 {
paul718e3742002-12-13 20:15:29 +00001804 peer_delete (peer);
1805 }
1806 list_delete (group->peer);
1807
1808 free (group->name);
1809 group->name = NULL;
1810
1811 group->conf->group = NULL;
1812 peer_delete (group->conf);
1813
1814 /* Delete from all peer_group list. */
1815 listnode_delete (bgp->group, group);
1816
1817 peer_group_free (group);
1818
1819 return 0;
1820}
1821
1822int
1823peer_group_remote_as_delete (struct peer_group *group)
1824{
1825 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001826 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001827
1828 if (! group->conf->as)
1829 return 0;
1830
paul1eb8ef22005-04-07 07:30:20 +00001831 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001832 {
paul718e3742002-12-13 20:15:29 +00001833 peer_delete (peer);
1834 }
1835 list_delete_all_node (group->peer);
1836
1837 group->conf->as = 0;
1838
1839 return 0;
1840}
1841
1842/* Bind specified peer to peer group. */
1843int
1844peer_group_bind (struct bgp *bgp, union sockunion *su,
1845 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1846{
1847 struct peer *peer;
1848 int first_member = 0;
1849
1850 /* Check peer group's address family. */
1851 if (! group->conf->afc[afi][safi])
1852 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1853
1854 /* Lookup the peer. */
1855 peer = peer_lookup (bgp, su);
1856
1857 /* Create a new peer. */
1858 if (! peer)
1859 {
1860 if (! group->conf->as)
1861 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1862
1863 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1864 peer->group = group;
1865 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001866
Paul Jakmaca058a32006-09-14 02:58:49 +00001867 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001868 listnode_add (group->peer, peer);
1869 peer_group2peer_config_copy (group, peer, afi, safi);
1870
1871 return 0;
1872 }
1873
1874 /* When the peer already belongs to peer group, check the consistency. */
1875 if (peer->af_group[afi][safi])
1876 {
1877 if (strcmp (peer->group->name, group->name) != 0)
1878 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1879
1880 return 0;
1881 }
1882
1883 /* Check current peer group configuration. */
1884 if (peer_group_active (peer)
1885 && strcmp (peer->group->name, group->name) != 0)
1886 return BGP_ERR_PEER_GROUP_MISMATCH;
1887
1888 if (! group->conf->as)
1889 {
1890 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1891 && peer_sort (group->conf) != peer_sort (peer))
1892 {
1893 if (as)
1894 *as = peer->as;
1895 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1896 }
1897
1898 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1899 first_member = 1;
1900 }
1901
1902 peer->af_group[afi][safi] = 1;
1903 peer->afc[afi][safi] = 1;
1904 if (! peer->group)
1905 {
1906 peer->group = group;
paul200df112005-06-01 11:17:05 +00001907
Paul Jakmaca058a32006-09-14 02:58:49 +00001908 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001909 listnode_add (group->peer, peer);
1910 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001911 else
1912 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001913
1914 if (first_member)
1915 {
1916 /* Advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +03001917 if (! CHECK_FLAG (group->conf->config, PEER_CONFIG_ROUTEADV))
1918 {
1919 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1920 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1921 else
1922 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1923 }
paul718e3742002-12-13 20:15:29 +00001924
1925 /* ebgp-multihop reset */
1926 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1927 group->conf->ttl = 255;
1928
1929 /* local-as reset */
1930 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1931 {
1932 group->conf->change_local_as = 0;
1933 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001934 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001935 }
1936 }
paulfee0f4c2004-09-13 05:12:46 +00001937
1938 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1939 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001940 struct listnode *pn;
1941
paulfee0f4c2004-09-13 05:12:46 +00001942 /* If it's not configured as RSERVER_CLIENT in any other address
1943 family, without being member of a peer_group, remove it from
1944 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001945 if (! peer_rsclient_active (peer)
1946 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001947 {
1948 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001949 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001950
1951 /* Clear our own rsclient rib for this afi/safi. */
1952 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001953 }
paulfee0f4c2004-09-13 05:12:46 +00001954
Paul Jakmab608d5b2008-07-02 02:12:07 +00001955 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001956
1957 /* Import policy. */
1958 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1959 {
1960 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1961 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1962 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1963 }
1964
1965 /* Export policy. */
1966 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1967 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1968 {
1969 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1970 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1971 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1972 }
1973 }
1974
paul718e3742002-12-13 20:15:29 +00001975 peer_group2peer_config_copy (group, peer, afi, safi);
1976
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001977 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001978 {
1979 peer->last_reset = PEER_DOWN_RMAP_BIND;
1980 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1981 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1982 }
paul718e3742002-12-13 20:15:29 +00001983 else
1984 BGP_EVENT_ADD (peer, BGP_Stop);
1985
1986 return 0;
1987}
1988
1989int
1990peer_group_unbind (struct bgp *bgp, struct peer *peer,
1991 struct peer_group *group, afi_t afi, safi_t safi)
1992{
1993 if (! peer->af_group[afi][safi])
1994 return 0;
1995
1996 if (group != peer->group)
1997 return BGP_ERR_PEER_GROUP_MISMATCH;
1998
1999 peer->af_group[afi][safi] = 0;
2000 peer->afc[afi][safi] = 0;
2001 peer_af_flag_reset (peer, afi, safi);
2002
paulfee0f4c2004-09-13 05:12:46 +00002003 if (peer->rib[afi][safi])
2004 peer->rib[afi][safi] = NULL;
2005
paul718e3742002-12-13 20:15:29 +00002006 if (! peer_group_active (peer))
2007 {
Paul Jakmaca058a32006-09-14 02:58:49 +00002008 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00002009 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00002010 listnode_delete (group->peer, peer);
2011 peer->group = NULL;
2012 if (group->conf->as)
2013 {
2014 peer_delete (peer);
2015 return 0;
2016 }
2017 peer_global_config_reset (peer);
2018 }
2019
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002020 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002021 {
2022 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
2023 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2024 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2025 }
paul718e3742002-12-13 20:15:29 +00002026 else
2027 BGP_EVENT_ADD (peer, BGP_Stop);
2028
2029 return 0;
2030}
David Lamparter6b0655a2014-06-04 06:53:35 +02002031
Vipin Kumardd49eb12014-09-30 14:36:38 -07002032
2033static int
2034bgp_startup_timer_expire (struct thread *thread)
2035{
2036 struct bgp *bgp;
2037
2038 bgp = THREAD_ARG (thread);
2039 bgp->t_startup = NULL;
2040
2041 return 0;
2042}
2043
paul718e3742002-12-13 20:15:29 +00002044/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00002045static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002046bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002047{
2048 struct bgp *bgp;
2049 afi_t afi;
2050 safi_t safi;
2051
paul200df112005-06-01 11:17:05 +00002052 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
2053 return NULL;
2054
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002055 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00002056 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00002057 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00002058
2059 bgp->peer = list_new ();
2060 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
2061
2062 bgp->group = list_new ();
2063 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
2064
paulfee0f4c2004-09-13 05:12:46 +00002065 bgp->rsclient = list_new ();
2066 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
2067
paul718e3742002-12-13 20:15:29 +00002068 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2069 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2070 {
Paul Jakma64e580a2006-02-21 01:09:01 +00002071 bgp->route[afi][safi] = bgp_table_init (afi, safi);
2072 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
2073 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07002074 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
2075 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00002076 }
2077
2078 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
2079 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
2080 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00002081 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
2082 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07002083 bgp_flag_set (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES);
paul718e3742002-12-13 20:15:29 +00002084
2085 bgp->as = *as;
2086
2087 if (name)
2088 bgp->name = strdup (name);
2089
Donald Sharp774914f2015-10-14 08:50:39 -04002090 THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire,
Vipin Kumardd49eb12014-09-30 14:36:38 -07002091 bgp, bgp->restart_time);
2092
paul718e3742002-12-13 20:15:29 +00002093 return bgp;
2094}
2095
2096/* Return first entry of BGP. */
2097struct bgp *
paul94f2b392005-06-28 12:44:16 +00002098bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00002099{
Lou Berger056f3762013-04-10 12:30:04 -07002100 if (bm && bm->bgp && bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00002101 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00002102 return NULL;
2103}
2104
2105/* Lookup BGP entry. */
2106struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002107bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00002108{
2109 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002110 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002111
paul1eb8ef22005-04-07 07:30:20 +00002112 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002113 if (bgp->as == as
2114 && ((bgp->name == NULL && name == NULL)
2115 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
2116 return bgp;
2117 return NULL;
2118}
2119
2120/* Lookup BGP structure by view name. */
2121struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002122bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002123{
2124 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002125 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002126
paul1eb8ef22005-04-07 07:30:20 +00002127 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002128 if ((bgp->name == NULL && name == NULL)
2129 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2130 return bgp;
2131 return NULL;
2132}
2133
2134/* Called from VTY commands. */
2135int
paulfd79ac92004-10-13 05:06:08 +00002136bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002137{
2138 struct bgp *bgp;
2139
2140 /* Multiple instance check. */
2141 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2142 {
2143 if (name)
2144 bgp = bgp_lookup_by_name (name);
2145 else
2146 bgp = bgp_get_default ();
2147
2148 /* Already exists. */
2149 if (bgp)
2150 {
2151 if (bgp->as != *as)
2152 {
2153 *as = bgp->as;
2154 return BGP_ERR_INSTANCE_MISMATCH;
2155 }
2156 *bgp_val = bgp;
2157 return 0;
2158 }
2159 }
2160 else
2161 {
2162 /* BGP instance name can not be specified for single instance. */
2163 if (name)
2164 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2165
2166 /* Get default BGP structure if exists. */
2167 bgp = bgp_get_default ();
2168
2169 if (bgp)
2170 {
2171 if (bgp->as != *as)
2172 {
2173 *as = bgp->as;
2174 return BGP_ERR_AS_MISMATCH;
2175 }
2176 *bgp_val = bgp;
2177 return 0;
2178 }
2179 }
2180
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002181 bgp = bgp_create (as, name);
2182 bgp_router_id_set(bgp, &router_id_zebra);
2183 *bgp_val = bgp;
2184
Paul Jakmaad12dde2012-06-13 22:50:07 +01002185 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002186 if (list_isempty(bm->bgp)
2187 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002188 {
2189 if (bgp_socket (bm->port, bm->address) < 0)
2190 return BGP_ERR_INVALID_VALUE;
2191 }
2192
paul718e3742002-12-13 20:15:29 +00002193 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002194
2195 return 0;
2196}
2197
2198/* Delete BGP instance. */
2199int
2200bgp_delete (struct bgp *bgp)
2201{
2202 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002203 struct peer_group *group;
Denil Vira57cd5e72015-08-10 12:46:14 -07002204 struct listnode *node, *pnode;
2205 struct listnode *next, *pnext;
paul718e3742002-12-13 20:15:29 +00002206 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002207 int i;
2208
Lou Berger82dd7072016-01-12 13:41:57 -05002209 SET_FLAG(bgp->flags, BGP_FLAG_DELETING);
2210
David Lampartercffe7802014-12-07 03:27:13 +01002211 THREAD_OFF (bgp->t_startup);
2212
paul718e3742002-12-13 20:15:29 +00002213 /* Delete static route. */
2214 bgp_static_delete (bgp);
2215
2216 /* Unset redistribution. */
2217 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2218 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2219 if (i != ZEBRA_ROUTE_BGP)
2220 bgp_redistribute_unset (bgp, afi, i);
2221
paul1eb8ef22005-04-07 07:30:20 +00002222 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002223 {
2224 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2225 {
2226 /* Send notify to remote peer. */
2227 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2228 }
2229
2230 peer_delete (peer);
2231 }
paul718e3742002-12-13 20:15:29 +00002232
Chris Caputo228da422009-07-18 05:44:03 +00002233 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002234 {
Denil Vira57cd5e72015-08-10 12:46:14 -07002235 for (ALL_LIST_ELEMENTS (group->peer, pnode, pnext, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002236 {
2237 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2238 {
2239 /* Send notify to remote peer. */
2240 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2241 }
2242 }
2243 peer_group_delete (group);
2244 }
Chris Caputo228da422009-07-18 05:44:03 +00002245
2246 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002247
2248 if (bgp->peer_self) {
2249 peer_delete(bgp->peer_self);
2250 bgp->peer_self = NULL;
2251 }
Lou Berger82dd7072016-01-12 13:41:57 -05002252
2253 /*
2254 * Free pending deleted routes. Unfortunately, it also has to process
2255 * all the pending activity for other instances of struct bgp.
2256 *
2257 * This call was added to achieve clean memory allocation at exit,
2258 * for the sake of valgrind.
2259 */
2260 bgp_process_queues_drain_immediate();
2261
Paul Jakmafd35b942009-07-16 19:27:32 +01002262 /* Remove visibility via the master list - there may however still be
2263 * routes to be processed still referencing the struct bgp.
2264 */
2265 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002266 if (list_isempty(bm->bgp))
2267 bgp_close ();
2268
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002269 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002270
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002271 return 0;
2272}
2273
2274static void bgp_free (struct bgp *);
2275
2276void
2277bgp_lock (struct bgp *bgp)
2278{
2279 ++bgp->lock;
2280}
2281
2282void
2283bgp_unlock(struct bgp *bgp)
2284{
Chris Caputo228da422009-07-18 05:44:03 +00002285 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002286 if (--bgp->lock == 0)
2287 bgp_free (bgp);
2288}
2289
2290static void
2291bgp_free (struct bgp *bgp)
2292{
2293 afi_t afi;
2294 safi_t safi;
2295
2296 list_delete (bgp->group);
2297 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002298 list_delete (bgp->rsclient);
2299
paul718e3742002-12-13 20:15:29 +00002300 if (bgp->name)
2301 free (bgp->name);
2302
2303 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2304 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2305 {
2306 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002307 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002308 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002309 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002310 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002311 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002312 }
2313 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002314}
David Lamparter6b0655a2014-06-04 06:53:35 +02002315
paul718e3742002-12-13 20:15:29 +00002316struct peer *
2317peer_lookup (struct bgp *bgp, union sockunion *su)
2318{
2319 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002320 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002321
Steve Hillfc4dc592009-07-28 17:54:35 +01002322 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002323 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002324 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2325 if (sockunion_same (&peer->su, su)
2326 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2327 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002328 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002329 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002330 {
2331 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002332
Paul Jakma2158ad22009-07-28 18:10:55 +01002333 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2334 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2335 if (sockunion_same (&peer->su, su)
2336 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2337 return peer;
paul718e3742002-12-13 20:15:29 +00002338 }
2339 return NULL;
2340}
2341
2342struct peer *
2343peer_lookup_with_open (union sockunion *su, as_t remote_as,
2344 struct in_addr *remote_id, int *as)
2345{
2346 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002347 struct listnode *node;
2348 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002349 struct bgp *bgp;
2350
Steve Hillfc4dc592009-07-28 17:54:35 +01002351 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002352 return NULL;
2353
Paul Jakma9d878772009-08-05 16:25:16 +01002354 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002355 {
Paul Jakma9d878772009-08-05 16:25:16 +01002356 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2357 {
2358 if (sockunion_same (&peer->su, su)
2359 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2360 {
2361 if (peer->as == remote_as
2362 && peer->remote_id.s_addr == remote_id->s_addr)
2363 return peer;
2364 if (peer->as == remote_as)
2365 *as = 1;
2366 }
2367 }
2368
2369 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2370 {
2371 if (sockunion_same (&peer->su, su)
2372 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2373 {
2374 if (peer->as == remote_as
2375 && peer->remote_id.s_addr == 0)
2376 return peer;
2377 if (peer->as == remote_as)
2378 *as = 1;
2379 }
2380 }
paul718e3742002-12-13 20:15:29 +00002381 }
2382 return NULL;
2383}
David Lamparter6b0655a2014-06-04 06:53:35 +02002384
paul718e3742002-12-13 20:15:29 +00002385/* If peer is configured at least one address family return 1. */
2386int
2387peer_active (struct peer *peer)
2388{
2389 if (peer->afc[AFI_IP][SAFI_UNICAST]
2390 || peer->afc[AFI_IP][SAFI_MULTICAST]
2391 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05002392 || peer->afc[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00002393 || peer->afc[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05002394 || peer->afc[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05002395 || peer->afc[AFI_IP6][SAFI_MPLS_VPN]
2396 || peer->afc[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00002397 return 1;
2398 return 0;
2399}
2400
2401/* If peer is negotiated at least one address family return 1. */
2402int
2403peer_active_nego (struct peer *peer)
2404{
2405 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2406 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2407 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
Lou Berger298cc2f2016-01-12 13:42:02 -05002408 || peer->afc_nego[AFI_IP][SAFI_ENCAP]
paul718e3742002-12-13 20:15:29 +00002409 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05002410 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
Lou Berger298cc2f2016-01-12 13:42:02 -05002411 || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
2412 || peer->afc_nego[AFI_IP6][SAFI_ENCAP])
paul718e3742002-12-13 20:15:29 +00002413 return 1;
2414 return 0;
2415}
David Lamparter6b0655a2014-06-04 06:53:35 +02002416
paul718e3742002-12-13 20:15:29 +00002417/* peer_flag_change_type. */
2418enum peer_change_type
2419{
2420 peer_change_none,
2421 peer_change_reset,
2422 peer_change_reset_in,
2423 peer_change_reset_out,
2424};
2425
paul94f2b392005-06-28 12:44:16 +00002426static void
paul718e3742002-12-13 20:15:29 +00002427peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2428 enum peer_change_type type)
2429{
2430 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2431 return;
2432
Stephen Hemmingerd9d4ae52010-01-13 00:32:39 +00002433 if (peer->status != Established)
2434 return;
2435
paul718e3742002-12-13 20:15:29 +00002436 if (type == peer_change_reset)
2437 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2438 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2439 else if (type == peer_change_reset_in)
2440 {
2441 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2442 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2443 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2444 else
2445 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2446 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2447 }
2448 else if (type == peer_change_reset_out)
2449 bgp_announce_route (peer, afi, safi);
2450}
2451
2452struct peer_flag_action
2453{
2454 /* Peer's flag. */
2455 u_int32_t flag;
2456
2457 /* This flag can be set for peer-group member. */
2458 u_char not_for_member;
2459
2460 /* Action when the flag is changed. */
2461 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002462
2463 /* Peer down cause */
2464 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002465};
2466
Stephen Hemminger03621952009-07-21 16:27:20 -07002467static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002468 {
2469 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2470 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2471 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2472 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2473 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002474 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002475 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002476 { 0, 0, 0 }
2477 };
2478
Stephen Hemminger03621952009-07-21 16:27:20 -07002479static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002480 {
2481 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2482 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2483 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2484 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2485 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2486 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2487 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2488 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2489 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2490 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2491 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2492 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2493 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002494 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
Timo Teräs9e7a53c2014-04-24 10:22:37 +03002495 { PEER_FLAG_NEXTHOP_SELF_ALL, 1, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002496 { 0, 0, 0 }
2497 };
2498
2499/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002500static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002501peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002502 struct peer_flag_action *action, u_int32_t flag)
2503{
2504 int i;
2505 int found = 0;
2506 int reset_in = 0;
2507 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002508 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002509
2510 /* Check peer's frag action. */
2511 for (i = 0; i < size; i++)
2512 {
2513 match = &action_list[i];
2514
2515 if (match->flag == 0)
2516 break;
2517
2518 if (match->flag & flag)
2519 {
2520 found = 1;
2521
2522 if (match->type == peer_change_reset_in)
2523 reset_in = 1;
2524 if (match->type == peer_change_reset_out)
2525 reset_out = 1;
2526 if (match->type == peer_change_reset)
2527 {
2528 reset_in = 1;
2529 reset_out = 1;
2530 }
2531 if (match->not_for_member)
2532 action->not_for_member = 1;
2533 }
2534 }
2535
2536 /* Set peer clear type. */
2537 if (reset_in && reset_out)
2538 action->type = peer_change_reset;
2539 else if (reset_in)
2540 action->type = peer_change_reset_in;
2541 else if (reset_out)
2542 action->type = peer_change_reset_out;
2543 else
2544 action->type = peer_change_none;
2545
2546 return found;
2547}
2548
paul94f2b392005-06-28 12:44:16 +00002549static void
paul718e3742002-12-13 20:15:29 +00002550peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2551{
2552 if (flag == PEER_FLAG_SHUTDOWN)
2553 {
2554 if (CHECK_FLAG (peer->flags, flag))
2555 {
hasso93406d82005-02-02 14:40:33 +00002556 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2557 peer_nsf_stop (peer);
2558
hasso0a486e52005-02-01 20:57:17 +00002559 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2560 if (peer->t_pmax_restart)
2561 {
2562 BGP_TIMER_OFF (peer->t_pmax_restart);
2563 if (BGP_DEBUG (events, EVENTS))
2564 zlog_debug ("%s Maximum-prefix restart timer canceled",
2565 peer->host);
2566 }
2567
hasso93406d82005-02-02 14:40:33 +00002568 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2569 peer_nsf_stop (peer);
2570
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002571 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002572 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2573 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2574 else
2575 BGP_EVENT_ADD (peer, BGP_Stop);
2576 }
2577 else
2578 {
2579 peer->v_start = BGP_INIT_START_TIMER;
2580 BGP_EVENT_ADD (peer, BGP_Stop);
2581 }
2582 }
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002583 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002584 {
hassoc9502432005-02-01 22:01:48 +00002585 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2586 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2587 else if (flag == PEER_FLAG_PASSIVE)
2588 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002589 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002590 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002591
hassoc9502432005-02-01 22:01:48 +00002592 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2593 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002594 }
2595 else
2596 BGP_EVENT_ADD (peer, BGP_Stop);
2597}
2598
2599/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002600static int
paul718e3742002-12-13 20:15:29 +00002601peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2602{
2603 int found;
2604 int size;
2605 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002606 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002607 struct peer_flag_action action;
2608
2609 memset (&action, 0, sizeof (struct peer_flag_action));
2610 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2611
2612 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2613
2614 /* No flag action is found. */
2615 if (! found)
2616 return BGP_ERR_INVALID_FLAG;
2617
2618 /* Not for peer-group member. */
2619 if (action.not_for_member && peer_group_active (peer))
2620 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2621
2622 /* When unset the peer-group member's flag we have to check
2623 peer-group configuration. */
2624 if (! set && peer_group_active (peer))
2625 if (CHECK_FLAG (peer->group->conf->flags, flag))
2626 {
2627 if (flag == PEER_FLAG_SHUTDOWN)
2628 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2629 else
2630 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2631 }
2632
2633 /* Flag conflict check. */
2634 if (set
2635 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2636 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2637 return BGP_ERR_PEER_FLAG_CONFLICT;
2638
2639 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2640 {
2641 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2642 return 0;
2643 if (! set && ! CHECK_FLAG (peer->flags, flag))
2644 return 0;
2645 }
2646
2647 if (set)
2648 SET_FLAG (peer->flags, flag);
2649 else
2650 UNSET_FLAG (peer->flags, flag);
2651
2652 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2653 {
2654 if (action.type == peer_change_reset)
2655 peer_flag_modify_action (peer, flag);
2656
2657 return 0;
2658 }
2659
2660 /* peer-group member updates. */
2661 group = peer->group;
2662
paul1eb8ef22005-04-07 07:30:20 +00002663 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002664 {
2665 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2666 continue;
2667
2668 if (! set && ! CHECK_FLAG (peer->flags, flag))
2669 continue;
2670
2671 if (set)
2672 SET_FLAG (peer->flags, flag);
2673 else
2674 UNSET_FLAG (peer->flags, flag);
2675
2676 if (action.type == peer_change_reset)
2677 peer_flag_modify_action (peer, flag);
2678 }
2679 return 0;
2680}
2681
2682int
2683peer_flag_set (struct peer *peer, u_int32_t flag)
2684{
2685 return peer_flag_modify (peer, flag, 1);
2686}
2687
2688int
2689peer_flag_unset (struct peer *peer, u_int32_t flag)
2690{
2691 return peer_flag_modify (peer, flag, 0);
2692}
2693
paul94f2b392005-06-28 12:44:16 +00002694static int
paul718e3742002-12-13 20:15:29 +00002695peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2696{
2697 if (peer->af_group[afi][safi])
2698 return 1;
2699 return 0;
2700}
2701
paul94f2b392005-06-28 12:44:16 +00002702static int
paul718e3742002-12-13 20:15:29 +00002703peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2704 int set)
2705{
2706 int found;
2707 int size;
paul1eb8ef22005-04-07 07:30:20 +00002708 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002709 struct peer_group *group;
2710 struct peer_flag_action action;
2711
2712 memset (&action, 0, sizeof (struct peer_flag_action));
2713 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2714
2715 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2716
2717 /* No flag action is found. */
2718 if (! found)
2719 return BGP_ERR_INVALID_FLAG;
2720
2721 /* Adress family must be activated. */
2722 if (! peer->afc[afi][safi])
2723 return BGP_ERR_PEER_INACTIVE;
2724
2725 /* Not for peer-group member. */
2726 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2727 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2728
2729 /* Spcecial check for reflector client. */
2730 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2731 && peer_sort (peer) != BGP_PEER_IBGP)
2732 return BGP_ERR_NOT_INTERNAL_PEER;
2733
2734 /* Spcecial check for remove-private-AS. */
2735 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2736 && peer_sort (peer) == BGP_PEER_IBGP)
2737 return BGP_ERR_REMOVE_PRIVATE_AS;
2738
2739 /* When unset the peer-group member's flag we have to check
2740 peer-group configuration. */
2741 if (! set && peer->af_group[afi][safi])
2742 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2743 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2744
2745 /* When current flag configuration is same as requested one. */
2746 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2747 {
2748 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2749 return 0;
2750 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2751 return 0;
2752 }
2753
2754 if (set)
2755 SET_FLAG (peer->af_flags[afi][safi], flag);
2756 else
2757 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2758
2759 /* Execute action when peer is established. */
2760 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2761 && peer->status == Established)
2762 {
2763 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2764 bgp_clear_adj_in (peer, afi, safi);
2765 else
hassoe0701b72004-05-20 09:19:34 +00002766 {
2767 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2768 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2769 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2770 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2771 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2772 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2773 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2774 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2775
2776 peer_change_action (peer, afi, safi, action.type);
2777 }
2778
paul718e3742002-12-13 20:15:29 +00002779 }
2780
2781 /* Peer group member updates. */
2782 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2783 {
2784 group = peer->group;
2785
paul1eb8ef22005-04-07 07:30:20 +00002786 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002787 {
2788 if (! peer->af_group[afi][safi])
2789 continue;
2790
2791 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2792 continue;
2793
2794 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2795 continue;
2796
2797 if (set)
2798 SET_FLAG (peer->af_flags[afi][safi], flag);
2799 else
2800 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2801
2802 if (peer->status == Established)
2803 {
2804 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2805 bgp_clear_adj_in (peer, afi, safi);
2806 else
hassoe0701b72004-05-20 09:19:34 +00002807 {
2808 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2809 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2810 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2811 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2812 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2813 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2814 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2815 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2816
2817 peer_change_action (peer, afi, safi, action.type);
2818 }
paul718e3742002-12-13 20:15:29 +00002819 }
2820 }
2821 }
2822 return 0;
2823}
2824
2825int
2826peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2827{
2828 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2829}
2830
2831int
2832peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2833{
2834 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2835}
David Lamparter6b0655a2014-06-04 06:53:35 +02002836
paul718e3742002-12-13 20:15:29 +00002837/* EBGP multihop configuration. */
2838int
2839peer_ebgp_multihop_set (struct peer *peer, int ttl)
2840{
2841 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002842 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002843 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002844
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002845 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002846 return 0;
2847
Nick Hilliardfa411a22011-03-23 15:33:17 +00002848 /* see comment in peer_ttl_security_hops_set() */
2849 if (ttl != MAXTTL)
2850 {
2851 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2852 {
2853 group = peer->group;
2854 if (group->conf->gtsm_hops != 0)
2855 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2856
2857 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2858 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002859 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002860 continue;
2861
2862 if (peer1->gtsm_hops != 0)
2863 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2864 }
2865 }
2866 else
2867 {
2868 if (peer->gtsm_hops != 0)
2869 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2870 }
2871 }
2872
paul718e3742002-12-13 20:15:29 +00002873 peer->ttl = ttl;
2874
2875 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2876 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002877 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002878 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002879 }
2880 else
2881 {
2882 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002883 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002884 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002885 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002886 continue;
paul718e3742002-12-13 20:15:29 +00002887
pauleb821182004-05-01 08:44:08 +00002888 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002889
pauleb821182004-05-01 08:44:08 +00002890 if (peer->fd >= 0)
2891 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2892 }
paul718e3742002-12-13 20:15:29 +00002893 }
2894 return 0;
2895}
2896
2897int
2898peer_ebgp_multihop_unset (struct peer *peer)
2899{
2900 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002901 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002902
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002903 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002904 return 0;
2905
Nick Hilliardfa411a22011-03-23 15:33:17 +00002906 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2907 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2908
paul718e3742002-12-13 20:15:29 +00002909 if (peer_group_active (peer))
2910 peer->ttl = peer->group->conf->ttl;
2911 else
2912 peer->ttl = 1;
2913
2914 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2915 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002916 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002917 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002918 }
2919 else
2920 {
2921 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002922 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002923 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002924 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002925 continue;
paul718e3742002-12-13 20:15:29 +00002926
pauleb821182004-05-01 08:44:08 +00002927 peer->ttl = 1;
2928
2929 if (peer->fd >= 0)
2930 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2931 }
paul718e3742002-12-13 20:15:29 +00002932 }
2933 return 0;
2934}
David Lamparter6b0655a2014-06-04 06:53:35 +02002935
paul718e3742002-12-13 20:15:29 +00002936/* Neighbor description. */
2937int
David Lamparterdfb9bd72016-05-24 18:58:07 +02002938peer_description_set (struct peer *peer, const char *desc)
paul718e3742002-12-13 20:15:29 +00002939{
2940 if (peer->desc)
2941 XFREE (MTYPE_PEER_DESC, peer->desc);
2942
2943 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2944
2945 return 0;
2946}
2947
2948int
2949peer_description_unset (struct peer *peer)
2950{
2951 if (peer->desc)
2952 XFREE (MTYPE_PEER_DESC, peer->desc);
2953
2954 peer->desc = NULL;
2955
2956 return 0;
2957}
David Lamparter6b0655a2014-06-04 06:53:35 +02002958
paul718e3742002-12-13 20:15:29 +00002959/* Neighbor update-source. */
2960int
paulfd79ac92004-10-13 05:06:08 +00002961peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002962{
2963 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002964 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002965
2966 if (peer->update_if)
2967 {
2968 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2969 && strcmp (peer->update_if, ifname) == 0)
2970 return 0;
2971
2972 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2973 peer->update_if = NULL;
2974 }
2975
2976 if (peer->update_source)
2977 {
2978 sockunion_free (peer->update_source);
2979 peer->update_source = NULL;
2980 }
2981
2982 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2983
2984 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2985 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002986 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002987 {
2988 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2989 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2990 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2991 }
paul718e3742002-12-13 20:15:29 +00002992 else
2993 BGP_EVENT_ADD (peer, BGP_Stop);
2994 return 0;
2995 }
2996
2997 /* peer-group member updates. */
2998 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002999 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003000 {
3001 if (peer->update_if)
3002 {
3003 if (strcmp (peer->update_if, ifname) == 0)
3004 continue;
3005
3006 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3007 peer->update_if = NULL;
3008 }
3009
3010 if (peer->update_source)
3011 {
3012 sockunion_free (peer->update_source);
3013 peer->update_source = NULL;
3014 }
3015
3016 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
3017
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003018 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003019 {
3020 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3021 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3022 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3023 }
paul718e3742002-12-13 20:15:29 +00003024 else
3025 BGP_EVENT_ADD (peer, BGP_Stop);
3026 }
3027 return 0;
3028}
3029
3030int
David Lamparterdfb9bd72016-05-24 18:58:07 +02003031peer_update_source_addr_set (struct peer *peer, const union sockunion *su)
paul718e3742002-12-13 20:15:29 +00003032{
3033 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003034 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003035
3036 if (peer->update_source)
3037 {
3038 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3039 && sockunion_cmp (peer->update_source, su) == 0)
3040 return 0;
3041 sockunion_free (peer->update_source);
3042 peer->update_source = NULL;
3043 }
3044
3045 if (peer->update_if)
3046 {
3047 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3048 peer->update_if = NULL;
3049 }
3050
3051 peer->update_source = sockunion_dup (su);
3052
3053 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3054 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003055 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003056 {
3057 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3058 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3059 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3060 }
paul718e3742002-12-13 20:15:29 +00003061 else
3062 BGP_EVENT_ADD (peer, BGP_Stop);
3063 return 0;
3064 }
3065
3066 /* peer-group member updates. */
3067 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003068 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003069 {
3070 if (peer->update_source)
3071 {
3072 if (sockunion_cmp (peer->update_source, su) == 0)
3073 continue;
3074 sockunion_free (peer->update_source);
3075 peer->update_source = NULL;
3076 }
3077
3078 if (peer->update_if)
3079 {
3080 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3081 peer->update_if = NULL;
3082 }
3083
3084 peer->update_source = sockunion_dup (su);
3085
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003086 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003087 {
3088 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3089 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3090 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3091 }
paul718e3742002-12-13 20:15:29 +00003092 else
3093 BGP_EVENT_ADD (peer, BGP_Stop);
3094 }
3095 return 0;
3096}
3097
3098int
3099peer_update_source_unset (struct peer *peer)
3100{
3101 union sockunion *su;
3102 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003103 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003104
3105 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3106 && ! peer->update_source
3107 && ! peer->update_if)
3108 return 0;
3109
3110 if (peer->update_source)
3111 {
3112 sockunion_free (peer->update_source);
3113 peer->update_source = NULL;
3114 }
3115 if (peer->update_if)
3116 {
3117 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3118 peer->update_if = NULL;
3119 }
3120
3121 if (peer_group_active (peer))
3122 {
3123 group = peer->group;
3124
3125 if (group->conf->update_source)
3126 {
3127 su = sockunion_dup (group->conf->update_source);
3128 peer->update_source = su;
3129 }
3130 else if (group->conf->update_if)
3131 peer->update_if =
3132 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
3133 }
3134
3135 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3136 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003137 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003138 {
3139 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3140 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3141 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3142 }
paul718e3742002-12-13 20:15:29 +00003143 else
3144 BGP_EVENT_ADD (peer, BGP_Stop);
3145 return 0;
3146 }
3147
3148 /* peer-group member updates. */
3149 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003150 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003151 {
3152 if (! peer->update_source && ! peer->update_if)
3153 continue;
3154
3155 if (peer->update_source)
3156 {
3157 sockunion_free (peer->update_source);
3158 peer->update_source = NULL;
3159 }
3160
3161 if (peer->update_if)
3162 {
3163 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3164 peer->update_if = NULL;
3165 }
3166
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003167 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003168 {
3169 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3170 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3171 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3172 }
paul718e3742002-12-13 20:15:29 +00003173 else
3174 BGP_EVENT_ADD (peer, BGP_Stop);
3175 }
3176 return 0;
3177}
David Lamparter6b0655a2014-06-04 06:53:35 +02003178
paul718e3742002-12-13 20:15:29 +00003179int
3180peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003181 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003182{
3183 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003184 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003185
3186 /* Adress family must be activated. */
3187 if (! peer->afc[afi][safi])
3188 return BGP_ERR_PEER_INACTIVE;
3189
3190 /* Default originate can't be used for peer group memeber. */
3191 if (peer_is_group_member (peer, afi, safi))
3192 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3193
3194 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3195 || (rmap && ! peer->default_rmap[afi][safi].name)
3196 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3197 {
3198 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3199
3200 if (rmap)
3201 {
3202 if (peer->default_rmap[afi][safi].name)
3203 free (peer->default_rmap[afi][safi].name);
3204 peer->default_rmap[afi][safi].name = strdup (rmap);
3205 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3206 }
3207 }
3208
3209 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3210 {
3211 if (peer->status == Established && peer->afc_nego[afi][safi])
3212 bgp_default_originate (peer, afi, safi, 0);
3213 return 0;
3214 }
3215
3216 /* peer-group member updates. */
3217 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003218 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003219 {
3220 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3221
3222 if (rmap)
3223 {
3224 if (peer->default_rmap[afi][safi].name)
3225 free (peer->default_rmap[afi][safi].name);
3226 peer->default_rmap[afi][safi].name = strdup (rmap);
3227 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3228 }
3229
3230 if (peer->status == Established && peer->afc_nego[afi][safi])
3231 bgp_default_originate (peer, afi, safi, 0);
3232 }
3233 return 0;
3234}
3235
3236int
3237peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3238{
3239 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003240 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003241
3242 /* Adress family must be activated. */
3243 if (! peer->afc[afi][safi])
3244 return BGP_ERR_PEER_INACTIVE;
3245
3246 /* Default originate can't be used for peer group memeber. */
3247 if (peer_is_group_member (peer, afi, safi))
3248 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3249
3250 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3251 {
3252 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3253
3254 if (peer->default_rmap[afi][safi].name)
3255 free (peer->default_rmap[afi][safi].name);
3256 peer->default_rmap[afi][safi].name = NULL;
3257 peer->default_rmap[afi][safi].map = NULL;
3258 }
3259
3260 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3261 {
3262 if (peer->status == Established && peer->afc_nego[afi][safi])
3263 bgp_default_originate (peer, afi, safi, 1);
3264 return 0;
3265 }
3266
3267 /* peer-group member updates. */
3268 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003269 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003270 {
3271 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3272
3273 if (peer->default_rmap[afi][safi].name)
3274 free (peer->default_rmap[afi][safi].name);
3275 peer->default_rmap[afi][safi].name = NULL;
3276 peer->default_rmap[afi][safi].map = NULL;
3277
3278 if (peer->status == Established && peer->afc_nego[afi][safi])
3279 bgp_default_originate (peer, afi, safi, 1);
3280 }
3281 return 0;
3282}
David Lamparter6b0655a2014-06-04 06:53:35 +02003283
paul718e3742002-12-13 20:15:29 +00003284int
3285peer_port_set (struct peer *peer, u_int16_t port)
3286{
3287 peer->port = port;
3288 return 0;
3289}
3290
3291int
3292peer_port_unset (struct peer *peer)
3293{
3294 peer->port = BGP_PORT_DEFAULT;
3295 return 0;
3296}
David Lamparter6b0655a2014-06-04 06:53:35 +02003297
paul718e3742002-12-13 20:15:29 +00003298/* neighbor weight. */
3299int
3300peer_weight_set (struct peer *peer, u_int16_t weight)
3301{
3302 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003303 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003304
3305 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3306 peer->weight = weight;
3307
3308 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3309 return 0;
3310
3311 /* peer-group member updates. */
3312 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003313 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003314 {
3315 peer->weight = group->conf->weight;
3316 }
3317 return 0;
3318}
3319
3320int
3321peer_weight_unset (struct peer *peer)
3322{
3323 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003324 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003325
3326 /* Set default weight. */
3327 if (peer_group_active (peer))
3328 peer->weight = peer->group->conf->weight;
3329 else
3330 peer->weight = 0;
3331
3332 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3333
3334 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3335 return 0;
3336
3337 /* peer-group member updates. */
3338 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003339 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003340 {
3341 peer->weight = 0;
3342 }
3343 return 0;
3344}
David Lamparter6b0655a2014-06-04 06:53:35 +02003345
paul718e3742002-12-13 20:15:29 +00003346int
3347peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3348{
3349 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003350 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003351
3352 /* Not for peer group memeber. */
3353 if (peer_group_active (peer))
3354 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3355
3356 /* keepalive value check. */
3357 if (keepalive > 65535)
3358 return BGP_ERR_INVALID_VALUE;
3359
3360 /* Holdtime value check. */
3361 if (holdtime > 65535)
3362 return BGP_ERR_INVALID_VALUE;
3363
3364 /* Holdtime value must be either 0 or greater than 3. */
3365 if (holdtime < 3 && holdtime != 0)
3366 return BGP_ERR_INVALID_VALUE;
3367
3368 /* Set value to the configuration. */
3369 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3370 peer->holdtime = holdtime;
3371 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3372
3373 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3374 return 0;
3375
3376 /* peer-group member updates. */
3377 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003378 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003379 {
3380 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3381 peer->holdtime = group->conf->holdtime;
3382 peer->keepalive = group->conf->keepalive;
3383 }
3384 return 0;
3385}
3386
3387int
3388peer_timers_unset (struct peer *peer)
3389{
3390 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003391 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003392
3393 if (peer_group_active (peer))
3394 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3395
3396 /* Clear configuration. */
3397 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3398 peer->keepalive = 0;
3399 peer->holdtime = 0;
3400
3401 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3402 return 0;
3403
3404 /* peer-group member updates. */
3405 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003406 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003407 {
3408 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3409 peer->holdtime = 0;
3410 peer->keepalive = 0;
3411 }
3412
3413 return 0;
3414}
David Lamparter6b0655a2014-06-04 06:53:35 +02003415
paul718e3742002-12-13 20:15:29 +00003416int
3417peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3418{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003419 struct peer_group *group;
3420 struct listnode *node, *nnode;
3421
paul718e3742002-12-13 20:15:29 +00003422 if (peer_group_active (peer))
3423 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3424
3425 if (connect > 65535)
3426 return BGP_ERR_INVALID_VALUE;
3427
3428 /* Set value to the configuration. */
3429 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3430 peer->connect = connect;
3431
3432 /* Set value to timer setting. */
3433 peer->v_connect = connect;
3434
Daniel Walton0d7435f2015-10-22 11:35:20 +03003435 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3436 return 0;
3437
3438 /* peer-group member updates. */
3439 group = peer->group;
3440 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3441 {
3442 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3443 peer->connect = connect;
3444 peer->v_connect = connect;
3445 }
paul718e3742002-12-13 20:15:29 +00003446 return 0;
3447}
3448
3449int
3450peer_timers_connect_unset (struct peer *peer)
3451{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003452 struct peer_group *group;
3453 struct listnode *node, *nnode;
3454
paul718e3742002-12-13 20:15:29 +00003455 if (peer_group_active (peer))
3456 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3457
3458 /* Clear configuration. */
3459 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3460 peer->connect = 0;
3461
3462 /* Set timer setting to default value. */
3463 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3464
Daniel Walton0d7435f2015-10-22 11:35:20 +03003465 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3466 return 0;
3467
3468 /* peer-group member updates. */
3469 group = peer->group;
3470 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3471 {
3472 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3473 peer->connect = 0;
3474 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3475 }
3476 return 0;
paul718e3742002-12-13 20:15:29 +00003477}
David Lamparter6b0655a2014-06-04 06:53:35 +02003478
paul718e3742002-12-13 20:15:29 +00003479int
3480peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3481{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003482 struct peer_group *group;
3483 struct listnode *node, *nnode;
3484
paul718e3742002-12-13 20:15:29 +00003485 if (peer_group_active (peer))
3486 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3487
3488 if (routeadv > 600)
3489 return BGP_ERR_INVALID_VALUE;
3490
3491 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3492 peer->routeadv = routeadv;
3493 peer->v_routeadv = routeadv;
3494
Daniel Walton0d7435f2015-10-22 11:35:20 +03003495 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3496 return 0;
3497
3498 /* peer-group member updates. */
3499 group = peer->group;
3500 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3501 {
3502 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3503 peer->routeadv = routeadv;
3504 peer->v_routeadv = routeadv;
3505 }
3506
paul718e3742002-12-13 20:15:29 +00003507 return 0;
3508}
3509
3510int
3511peer_advertise_interval_unset (struct peer *peer)
3512{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003513 struct peer_group *group;
3514 struct listnode *node, *nnode;
3515
paul718e3742002-12-13 20:15:29 +00003516 if (peer_group_active (peer))
3517 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3518
3519 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3520 peer->routeadv = 0;
3521
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003522 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003523 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3524 else
3525 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
Daniel Walton0d7435f2015-10-22 11:35:20 +03003526
3527 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3528 return 0;
3529
3530 /* peer-group member updates. */
3531 group = peer->group;
3532 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3533 {
3534 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3535 peer->routeadv = 0;
3536
3537 if (peer->sort == BGP_PEER_IBGP)
3538 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3539 else
3540 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3541 }
paul718e3742002-12-13 20:15:29 +00003542
3543 return 0;
3544}
David Lamparter6b0655a2014-06-04 06:53:35 +02003545
paul718e3742002-12-13 20:15:29 +00003546/* neighbor interface */
3547int
paulfd79ac92004-10-13 05:06:08 +00003548peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003549{
3550 if (peer->ifname)
3551 free (peer->ifname);
3552 peer->ifname = strdup (str);
3553
3554 return 0;
3555}
3556
3557int
3558peer_interface_unset (struct peer *peer)
3559{
3560 if (peer->ifname)
3561 free (peer->ifname);
3562 peer->ifname = NULL;
3563
3564 return 0;
3565}
David Lamparter6b0655a2014-06-04 06:53:35 +02003566
paul718e3742002-12-13 20:15:29 +00003567/* Allow-as in. */
3568int
3569peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3570{
3571 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003572 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003573
3574 if (allow_num < 1 || allow_num > 10)
3575 return BGP_ERR_INVALID_VALUE;
3576
3577 if (peer->allowas_in[afi][safi] != allow_num)
3578 {
3579 peer->allowas_in[afi][safi] = allow_num;
3580 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3581 peer_change_action (peer, afi, safi, peer_change_reset_in);
3582 }
3583
3584 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3585 return 0;
3586
3587 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003588 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003589 {
3590 if (peer->allowas_in[afi][safi] != allow_num)
3591 {
3592 peer->allowas_in[afi][safi] = allow_num;
3593 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3594 peer_change_action (peer, afi, safi, peer_change_reset_in);
3595 }
3596
3597 }
3598 return 0;
3599}
3600
3601int
3602peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3603{
3604 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003605 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003606
3607 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3608 {
3609 peer->allowas_in[afi][safi] = 0;
3610 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3611 }
3612
3613 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3614 return 0;
3615
3616 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003617 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003618 {
3619 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3620 {
3621 peer->allowas_in[afi][safi] = 0;
3622 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3623 }
3624 }
3625 return 0;
3626}
David Lamparter6b0655a2014-06-04 06:53:35 +02003627
paul718e3742002-12-13 20:15:29 +00003628int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003629peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003630{
3631 struct bgp *bgp = peer->bgp;
3632 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003633 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003634
3635 if (peer_sort (peer) != BGP_PEER_EBGP
3636 && peer_sort (peer) != BGP_PEER_INTERNAL)
3637 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3638
3639 if (bgp->as == as)
3640 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3641
3642 if (peer_group_active (peer))
3643 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3644
Andrew Certain9d3f9702012-11-07 23:50:07 +00003645 if (peer->as == as)
3646 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3647
paul718e3742002-12-13 20:15:29 +00003648 if (peer->change_local_as == as &&
3649 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003650 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3651 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3652 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003653 return 0;
3654
3655 peer->change_local_as = as;
3656 if (no_prepend)
3657 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3658 else
3659 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3660
Andrew Certain9d3f9702012-11-07 23:50:07 +00003661 if (replace_as)
3662 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3663 else
3664 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3665
paul718e3742002-12-13 20:15:29 +00003666 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3667 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003668 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003669 {
3670 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3671 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3672 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3673 }
paul718e3742002-12-13 20:15:29 +00003674 else
3675 BGP_EVENT_ADD (peer, BGP_Stop);
3676
3677 return 0;
3678 }
3679
3680 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003681 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003682 {
3683 peer->change_local_as = as;
3684 if (no_prepend)
3685 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3686 else
3687 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3688
Andrew Certain9d3f9702012-11-07 23:50:07 +00003689 if (replace_as)
3690 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3691 else
3692 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3693
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003694 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003695 {
3696 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3697 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3698 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3699 }
paul718e3742002-12-13 20:15:29 +00003700 else
3701 BGP_EVENT_ADD (peer, BGP_Stop);
3702 }
3703
3704 return 0;
3705}
3706
3707int
3708peer_local_as_unset (struct peer *peer)
3709{
3710 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003711 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003712
3713 if (peer_group_active (peer))
3714 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3715
3716 if (! peer->change_local_as)
3717 return 0;
3718
3719 peer->change_local_as = 0;
3720 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003721 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003722
3723 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3724 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003725 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003726 {
3727 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3728 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3729 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3730 }
paul718e3742002-12-13 20:15:29 +00003731 else
3732 BGP_EVENT_ADD (peer, BGP_Stop);
3733
3734 return 0;
3735 }
3736
3737 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003738 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003739 {
3740 peer->change_local_as = 0;
3741 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003742 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003743
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003744 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003745 {
3746 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3747 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3748 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3749 }
paul718e3742002-12-13 20:15:29 +00003750 else
3751 BGP_EVENT_ADD (peer, BGP_Stop);
3752 }
3753 return 0;
3754}
David Lamparter6b0655a2014-06-04 06:53:35 +02003755
Paul Jakma0df7c912008-07-21 21:02:49 +00003756/* Set password for authenticating with the peer. */
3757int
3758peer_password_set (struct peer *peer, const char *password)
3759{
3760 struct listnode *nn, *nnode;
3761 int len = password ? strlen(password) : 0;
3762 int ret = BGP_SUCCESS;
3763
3764 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3765 return BGP_ERR_INVALID_VALUE;
3766
3767 if (peer->password && strcmp (peer->password, password) == 0
3768 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3769 return 0;
3770
3771 if (peer->password)
3772 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3773
3774 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3775
3776 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3777 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003778 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3779 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
Paul Jakma0df7c912008-07-21 21:02:49 +00003780 else
3781 BGP_EVENT_ADD (peer, BGP_Stop);
3782
3783 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3784 }
3785
3786 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3787 {
3788 if (peer->password && strcmp (peer->password, password) == 0)
3789 continue;
3790
3791 if (peer->password)
3792 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3793
3794 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3795
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003796 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003797 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3798 else
3799 BGP_EVENT_ADD (peer, BGP_Stop);
3800
3801 if (bgp_md5_set (peer) < 0)
3802 ret = BGP_ERR_TCPSIG_FAILED;
3803 }
3804
3805 return ret;
3806}
3807
3808int
3809peer_password_unset (struct peer *peer)
3810{
3811 struct listnode *nn, *nnode;
3812
3813 if (!peer->password
3814 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3815 return 0;
3816
3817 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3818 {
3819 if (peer_group_active (peer)
3820 && peer->group->conf->password
3821 && strcmp (peer->group->conf->password, peer->password) == 0)
3822 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3823
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003824 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003825 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3826 else
3827 BGP_EVENT_ADD (peer, BGP_Stop);
3828
3829 if (peer->password)
3830 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3831
3832 peer->password = NULL;
3833
3834 bgp_md5_set (peer);
3835
3836 return 0;
3837 }
3838
3839 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3840 peer->password = NULL;
3841
3842 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3843 {
3844 if (!peer->password)
3845 continue;
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 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3853 peer->password = NULL;
3854
3855 bgp_md5_set (peer);
3856 }
3857
3858 return 0;
3859}
David Lamparter6b0655a2014-06-04 06:53:35 +02003860
paul718e3742002-12-13 20:15:29 +00003861/* Set distribute list to the peer. */
3862int
3863peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003864 const char *name)
paul718e3742002-12-13 20:15:29 +00003865{
3866 struct bgp_filter *filter;
3867 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003868 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003869
3870 if (! peer->afc[afi][safi])
3871 return BGP_ERR_PEER_INACTIVE;
3872
3873 if (direct != FILTER_IN && direct != FILTER_OUT)
3874 return BGP_ERR_INVALID_VALUE;
3875
3876 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3877 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3878
3879 filter = &peer->filter[afi][safi];
3880
3881 if (filter->plist[direct].name)
3882 return BGP_ERR_PEER_FILTER_CONFLICT;
3883
3884 if (filter->dlist[direct].name)
3885 free (filter->dlist[direct].name);
3886 filter->dlist[direct].name = strdup (name);
3887 filter->dlist[direct].alist = access_list_lookup (afi, name);
3888
3889 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3890 return 0;
3891
3892 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003893 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003894 {
3895 filter = &peer->filter[afi][safi];
3896
3897 if (! peer->af_group[afi][safi])
3898 continue;
3899
3900 if (filter->dlist[direct].name)
3901 free (filter->dlist[direct].name);
3902 filter->dlist[direct].name = strdup (name);
3903 filter->dlist[direct].alist = access_list_lookup (afi, name);
3904 }
3905
3906 return 0;
3907}
3908
3909int
3910peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3911{
3912 struct bgp_filter *filter;
3913 struct bgp_filter *gfilter;
3914 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003915 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003916
3917 if (! peer->afc[afi][safi])
3918 return BGP_ERR_PEER_INACTIVE;
3919
3920 if (direct != FILTER_IN && direct != FILTER_OUT)
3921 return BGP_ERR_INVALID_VALUE;
3922
3923 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3924 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3925
3926 filter = &peer->filter[afi][safi];
3927
3928 /* apply peer-group filter */
3929 if (peer->af_group[afi][safi])
3930 {
3931 gfilter = &peer->group->conf->filter[afi][safi];
3932
3933 if (gfilter->dlist[direct].name)
3934 {
3935 if (filter->dlist[direct].name)
3936 free (filter->dlist[direct].name);
3937 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3938 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3939 return 0;
3940 }
3941 }
3942
3943 if (filter->dlist[direct].name)
3944 free (filter->dlist[direct].name);
3945 filter->dlist[direct].name = NULL;
3946 filter->dlist[direct].alist = NULL;
3947
3948 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3949 return 0;
3950
3951 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003952 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003953 {
3954 filter = &peer->filter[afi][safi];
3955
3956 if (! peer->af_group[afi][safi])
3957 continue;
3958
3959 if (filter->dlist[direct].name)
3960 free (filter->dlist[direct].name);
3961 filter->dlist[direct].name = NULL;
3962 filter->dlist[direct].alist = NULL;
3963 }
3964
3965 return 0;
3966}
3967
3968/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003969static void
paul718e3742002-12-13 20:15:29 +00003970peer_distribute_update (struct access_list *access)
3971{
3972 afi_t afi;
3973 safi_t safi;
3974 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003975 struct listnode *mnode, *mnnode;
3976 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003977 struct bgp *bgp;
3978 struct peer *peer;
3979 struct peer_group *group;
3980 struct bgp_filter *filter;
3981
paul1eb8ef22005-04-07 07:30:20 +00003982 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003983 {
paul1eb8ef22005-04-07 07:30:20 +00003984 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003985 {
3986 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3987 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3988 {
3989 filter = &peer->filter[afi][safi];
3990
3991 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3992 {
3993 if (filter->dlist[direct].name)
3994 filter->dlist[direct].alist =
3995 access_list_lookup (afi, filter->dlist[direct].name);
3996 else
3997 filter->dlist[direct].alist = NULL;
3998 }
3999 }
4000 }
paul1eb8ef22005-04-07 07:30:20 +00004001 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004002 {
4003 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4004 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4005 {
4006 filter = &group->conf->filter[afi][safi];
4007
4008 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4009 {
4010 if (filter->dlist[direct].name)
4011 filter->dlist[direct].alist =
4012 access_list_lookup (afi, filter->dlist[direct].name);
4013 else
4014 filter->dlist[direct].alist = NULL;
4015 }
4016 }
4017 }
4018 }
4019}
David Lamparter6b0655a2014-06-04 06:53:35 +02004020
paul718e3742002-12-13 20:15:29 +00004021/* Set prefix list to the peer. */
4022int
4023peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004024 const char *name)
paul718e3742002-12-13 20:15:29 +00004025{
4026 struct bgp_filter *filter;
4027 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004028 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004029
4030 if (! peer->afc[afi][safi])
4031 return BGP_ERR_PEER_INACTIVE;
4032
4033 if (direct != FILTER_IN && direct != FILTER_OUT)
4034 return BGP_ERR_INVALID_VALUE;
4035
4036 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4037 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4038
4039 filter = &peer->filter[afi][safi];
4040
4041 if (filter->dlist[direct].name)
4042 return BGP_ERR_PEER_FILTER_CONFLICT;
4043
4044 if (filter->plist[direct].name)
4045 free (filter->plist[direct].name);
4046 filter->plist[direct].name = strdup (name);
4047 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4048
4049 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4050 return 0;
4051
4052 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004053 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004054 {
4055 filter = &peer->filter[afi][safi];
4056
4057 if (! peer->af_group[afi][safi])
4058 continue;
4059
4060 if (filter->plist[direct].name)
4061 free (filter->plist[direct].name);
4062 filter->plist[direct].name = strdup (name);
4063 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4064 }
4065 return 0;
4066}
4067
4068int
4069peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4070{
4071 struct bgp_filter *filter;
4072 struct bgp_filter *gfilter;
4073 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004074 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004075
4076 if (! peer->afc[afi][safi])
4077 return BGP_ERR_PEER_INACTIVE;
4078
4079 if (direct != FILTER_IN && direct != FILTER_OUT)
4080 return BGP_ERR_INVALID_VALUE;
4081
4082 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4083 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4084
4085 filter = &peer->filter[afi][safi];
4086
4087 /* apply peer-group filter */
4088 if (peer->af_group[afi][safi])
4089 {
4090 gfilter = &peer->group->conf->filter[afi][safi];
4091
4092 if (gfilter->plist[direct].name)
4093 {
4094 if (filter->plist[direct].name)
4095 free (filter->plist[direct].name);
4096 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
4097 filter->plist[direct].plist = gfilter->plist[direct].plist;
4098 return 0;
4099 }
4100 }
4101
4102 if (filter->plist[direct].name)
4103 free (filter->plist[direct].name);
4104 filter->plist[direct].name = NULL;
4105 filter->plist[direct].plist = NULL;
4106
4107 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4108 return 0;
4109
4110 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004111 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004112 {
4113 filter = &peer->filter[afi][safi];
4114
4115 if (! peer->af_group[afi][safi])
4116 continue;
4117
4118 if (filter->plist[direct].name)
4119 free (filter->plist[direct].name);
4120 filter->plist[direct].name = NULL;
4121 filter->plist[direct].plist = NULL;
4122 }
4123
4124 return 0;
4125}
4126
4127/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00004128static void
paul718e3742002-12-13 20:15:29 +00004129peer_prefix_list_update (struct prefix_list *plist)
4130{
paul1eb8ef22005-04-07 07:30:20 +00004131 struct listnode *mnode, *mnnode;
4132 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004133 struct bgp *bgp;
4134 struct peer *peer;
4135 struct peer_group *group;
4136 struct bgp_filter *filter;
4137 afi_t afi;
4138 safi_t safi;
4139 int direct;
4140
paul1eb8ef22005-04-07 07:30:20 +00004141 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004142 {
paul1eb8ef22005-04-07 07:30:20 +00004143 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004144 {
4145 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4146 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4147 {
4148 filter = &peer->filter[afi][safi];
4149
4150 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4151 {
4152 if (filter->plist[direct].name)
4153 filter->plist[direct].plist =
4154 prefix_list_lookup (afi, filter->plist[direct].name);
4155 else
4156 filter->plist[direct].plist = NULL;
4157 }
4158 }
4159 }
paul1eb8ef22005-04-07 07:30:20 +00004160 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004161 {
4162 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4163 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4164 {
4165 filter = &group->conf->filter[afi][safi];
4166
4167 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4168 {
4169 if (filter->plist[direct].name)
4170 filter->plist[direct].plist =
4171 prefix_list_lookup (afi, filter->plist[direct].name);
4172 else
4173 filter->plist[direct].plist = NULL;
4174 }
4175 }
4176 }
4177 }
4178}
David Lamparter6b0655a2014-06-04 06:53:35 +02004179
paul718e3742002-12-13 20:15:29 +00004180int
4181peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004182 const char *name)
paul718e3742002-12-13 20:15:29 +00004183{
4184 struct bgp_filter *filter;
4185 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004186 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004187
4188 if (! peer->afc[afi][safi])
4189 return BGP_ERR_PEER_INACTIVE;
4190
4191 if (direct != FILTER_IN && direct != FILTER_OUT)
4192 return BGP_ERR_INVALID_VALUE;
4193
4194 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4195 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4196
4197 filter = &peer->filter[afi][safi];
4198
4199 if (filter->aslist[direct].name)
4200 free (filter->aslist[direct].name);
4201 filter->aslist[direct].name = strdup (name);
4202 filter->aslist[direct].aslist = as_list_lookup (name);
4203
4204 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4205 return 0;
4206
4207 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004208 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004209 {
4210 filter = &peer->filter[afi][safi];
4211
4212 if (! peer->af_group[afi][safi])
4213 continue;
4214
4215 if (filter->aslist[direct].name)
4216 free (filter->aslist[direct].name);
4217 filter->aslist[direct].name = strdup (name);
4218 filter->aslist[direct].aslist = as_list_lookup (name);
4219 }
4220 return 0;
4221}
4222
4223int
4224peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4225{
4226 struct bgp_filter *filter;
4227 struct bgp_filter *gfilter;
4228 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004229 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004230
4231 if (! peer->afc[afi][safi])
4232 return BGP_ERR_PEER_INACTIVE;
4233
hassob5f29602005-05-25 21:00:28 +00004234 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004235 return BGP_ERR_INVALID_VALUE;
4236
hassob5f29602005-05-25 21:00:28 +00004237 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004238 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4239
4240 filter = &peer->filter[afi][safi];
4241
4242 /* apply peer-group filter */
4243 if (peer->af_group[afi][safi])
4244 {
4245 gfilter = &peer->group->conf->filter[afi][safi];
4246
4247 if (gfilter->aslist[direct].name)
4248 {
4249 if (filter->aslist[direct].name)
4250 free (filter->aslist[direct].name);
4251 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4252 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4253 return 0;
4254 }
4255 }
4256
4257 if (filter->aslist[direct].name)
4258 free (filter->aslist[direct].name);
4259 filter->aslist[direct].name = NULL;
4260 filter->aslist[direct].aslist = NULL;
4261
4262 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4263 return 0;
4264
4265 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004266 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004267 {
4268 filter = &peer->filter[afi][safi];
4269
4270 if (! peer->af_group[afi][safi])
4271 continue;
4272
4273 if (filter->aslist[direct].name)
4274 free (filter->aslist[direct].name);
4275 filter->aslist[direct].name = NULL;
4276 filter->aslist[direct].aslist = NULL;
4277 }
4278
4279 return 0;
4280}
4281
paul94f2b392005-06-28 12:44:16 +00004282static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004283peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004284{
4285 afi_t afi;
4286 safi_t safi;
4287 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004288 struct listnode *mnode, *mnnode;
4289 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004290 struct bgp *bgp;
4291 struct peer *peer;
4292 struct peer_group *group;
4293 struct bgp_filter *filter;
4294
paul1eb8ef22005-04-07 07:30:20 +00004295 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004296 {
paul1eb8ef22005-04-07 07:30:20 +00004297 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004298 {
4299 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4300 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4301 {
4302 filter = &peer->filter[afi][safi];
4303
4304 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4305 {
4306 if (filter->aslist[direct].name)
4307 filter->aslist[direct].aslist =
4308 as_list_lookup (filter->aslist[direct].name);
4309 else
4310 filter->aslist[direct].aslist = NULL;
4311 }
4312 }
4313 }
paul1eb8ef22005-04-07 07:30:20 +00004314 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004315 {
4316 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4317 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4318 {
4319 filter = &group->conf->filter[afi][safi];
4320
4321 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4322 {
4323 if (filter->aslist[direct].name)
4324 filter->aslist[direct].aslist =
4325 as_list_lookup (filter->aslist[direct].name);
4326 else
4327 filter->aslist[direct].aslist = NULL;
4328 }
4329 }
4330 }
4331 }
4332}
David Lamparter6b0655a2014-06-04 06:53:35 +02004333
paul718e3742002-12-13 20:15:29 +00004334/* Set route-map to the peer. */
4335int
4336peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004337 const char *name)
paul718e3742002-12-13 20:15:29 +00004338{
4339 struct bgp_filter *filter;
4340 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004341 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004342
4343 if (! peer->afc[afi][safi])
4344 return BGP_ERR_PEER_INACTIVE;
4345
paulfee0f4c2004-09-13 05:12:46 +00004346 if (direct != RMAP_IN && direct != RMAP_OUT &&
4347 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004348 return BGP_ERR_INVALID_VALUE;
4349
paulfee0f4c2004-09-13 05:12:46 +00004350 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4351 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004352 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4353
4354 filter = &peer->filter[afi][safi];
4355
4356 if (filter->map[direct].name)
4357 free (filter->map[direct].name);
4358
4359 filter->map[direct].name = strdup (name);
4360 filter->map[direct].map = route_map_lookup_by_name (name);
4361
4362 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4363 return 0;
4364
4365 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004366 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004367 {
4368 filter = &peer->filter[afi][safi];
4369
4370 if (! peer->af_group[afi][safi])
4371 continue;
4372
4373 if (filter->map[direct].name)
4374 free (filter->map[direct].name);
4375 filter->map[direct].name = strdup (name);
4376 filter->map[direct].map = route_map_lookup_by_name (name);
4377 }
4378 return 0;
4379}
4380
4381/* Unset route-map from the peer. */
4382int
4383peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4384{
4385 struct bgp_filter *filter;
4386 struct bgp_filter *gfilter;
4387 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004388 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004389
4390 if (! peer->afc[afi][safi])
4391 return BGP_ERR_PEER_INACTIVE;
4392
hassob5f29602005-05-25 21:00:28 +00004393 if (direct != RMAP_IN && direct != RMAP_OUT &&
4394 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004395 return BGP_ERR_INVALID_VALUE;
4396
hassob5f29602005-05-25 21:00:28 +00004397 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4398 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004399 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4400
4401 filter = &peer->filter[afi][safi];
4402
4403 /* apply peer-group filter */
4404 if (peer->af_group[afi][safi])
4405 {
4406 gfilter = &peer->group->conf->filter[afi][safi];
4407
4408 if (gfilter->map[direct].name)
4409 {
4410 if (filter->map[direct].name)
4411 free (filter->map[direct].name);
4412 filter->map[direct].name = strdup (gfilter->map[direct].name);
4413 filter->map[direct].map = gfilter->map[direct].map;
4414 return 0;
4415 }
4416 }
4417
4418 if (filter->map[direct].name)
4419 free (filter->map[direct].name);
4420 filter->map[direct].name = NULL;
4421 filter->map[direct].map = NULL;
4422
4423 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4424 return 0;
4425
4426 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004427 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004428 {
4429 filter = &peer->filter[afi][safi];
4430
4431 if (! peer->af_group[afi][safi])
4432 continue;
4433
4434 if (filter->map[direct].name)
4435 free (filter->map[direct].name);
4436 filter->map[direct].name = NULL;
4437 filter->map[direct].map = NULL;
4438 }
4439 return 0;
4440}
David Lamparter6b0655a2014-06-04 06:53:35 +02004441
paul718e3742002-12-13 20:15:29 +00004442/* Set unsuppress-map to the peer. */
4443int
paulfd79ac92004-10-13 05:06:08 +00004444peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4445 const char *name)
paul718e3742002-12-13 20:15:29 +00004446{
4447 struct bgp_filter *filter;
4448 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004449 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004450
4451 if (! peer->afc[afi][safi])
4452 return BGP_ERR_PEER_INACTIVE;
4453
4454 if (peer_is_group_member (peer, afi, safi))
4455 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4456
4457 filter = &peer->filter[afi][safi];
4458
4459 if (filter->usmap.name)
4460 free (filter->usmap.name);
4461
4462 filter->usmap.name = strdup (name);
4463 filter->usmap.map = route_map_lookup_by_name (name);
4464
4465 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4466 return 0;
4467
4468 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004469 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004470 {
4471 filter = &peer->filter[afi][safi];
4472
4473 if (! peer->af_group[afi][safi])
4474 continue;
4475
4476 if (filter->usmap.name)
4477 free (filter->usmap.name);
4478 filter->usmap.name = strdup (name);
4479 filter->usmap.map = route_map_lookup_by_name (name);
4480 }
4481 return 0;
4482}
4483
4484/* Unset route-map from the peer. */
4485int
4486peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4487{
4488 struct bgp_filter *filter;
4489 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004490 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004491
4492 if (! peer->afc[afi][safi])
4493 return BGP_ERR_PEER_INACTIVE;
4494
4495 if (peer_is_group_member (peer, afi, safi))
4496 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4497
4498 filter = &peer->filter[afi][safi];
4499
4500 if (filter->usmap.name)
4501 free (filter->usmap.name);
4502 filter->usmap.name = NULL;
4503 filter->usmap.map = NULL;
4504
4505 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4506 return 0;
4507
4508 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004509 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004510 {
4511 filter = &peer->filter[afi][safi];
4512
4513 if (! peer->af_group[afi][safi])
4514 continue;
4515
4516 if (filter->usmap.name)
4517 free (filter->usmap.name);
4518 filter->usmap.name = NULL;
4519 filter->usmap.map = NULL;
4520 }
4521 return 0;
4522}
David Lamparter6b0655a2014-06-04 06:53:35 +02004523
paul718e3742002-12-13 20:15:29 +00004524int
4525peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004526 u_int32_t max, u_char threshold,
4527 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004528{
4529 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004530 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004531
4532 if (! peer->afc[afi][safi])
4533 return BGP_ERR_PEER_INACTIVE;
4534
4535 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4536 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004537 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004538 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004539 if (warning)
4540 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4541 else
4542 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4543
4544 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4545 return 0;
4546
4547 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004548 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004549 {
4550 if (! peer->af_group[afi][safi])
4551 continue;
4552
4553 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4554 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004555 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004556 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004557 if (warning)
4558 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4559 else
4560 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4561 }
4562 return 0;
4563}
4564
4565int
4566peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4567{
4568 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004569 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004570
4571 if (! peer->afc[afi][safi])
4572 return BGP_ERR_PEER_INACTIVE;
4573
4574 /* apply peer-group config */
4575 if (peer->af_group[afi][safi])
4576 {
4577 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4578 PEER_FLAG_MAX_PREFIX))
4579 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4580 else
4581 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4582
4583 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4584 PEER_FLAG_MAX_PREFIX_WARNING))
4585 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4586 else
4587 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4588
4589 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004590 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004591 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004592 return 0;
4593 }
4594
4595 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4596 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4597 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004598 peer->pmax_threshold[afi][safi] = 0;
4599 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004600
4601 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4602 return 0;
4603
4604 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004605 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004606 {
4607 if (! peer->af_group[afi][safi])
4608 continue;
4609
4610 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4611 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4612 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004613 peer->pmax_threshold[afi][safi] = 0;
4614 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004615 }
4616 return 0;
4617}
David Lamparter5f9adb52014-05-19 23:15:02 +02004618
4619static int is_ebgp_multihop_configured (struct peer *peer)
4620{
4621 struct peer_group *group;
4622 struct listnode *node, *nnode;
4623 struct peer *peer1;
4624
4625 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4626 {
4627 group = peer->group;
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004628 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4629 (group->conf->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004630 return 1;
4631
4632 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4633 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004634 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
4635 (peer1->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004636 return 1;
4637 }
4638 }
4639 else
4640 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004641 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4642 (peer->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004643 return 1;
4644 }
4645 return 0;
4646}
4647
Nick Hilliardfa411a22011-03-23 15:33:17 +00004648/* Set # of hops between us and BGP peer. */
4649int
4650peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4651{
4652 struct peer_group *group;
4653 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004654 int ret;
4655
4656 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4657
Nick Hilliardfa411a22011-03-23 15:33:17 +00004658 /* We cannot configure ttl-security hops when ebgp-multihop is already
4659 set. For non peer-groups, the check is simple. For peer-groups, it's
4660 slightly messy, because we need to check both the peer-group structure
4661 and all peer-group members for any trace of ebgp-multihop configuration
4662 before actually applying the ttl-security rules. Cisco really made a
4663 mess of this configuration parameter, and OpenBGPD got it right.
4664 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004665
David Lamparter5f9adb52014-05-19 23:15:02 +02004666 if (peer->gtsm_hops == 0)
4667 {
4668 if (is_ebgp_multihop_configured (peer))
4669 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004670
David Lamparter5f9adb52014-05-19 23:15:02 +02004671 /* specify MAXTTL on outgoing packets */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004672 /* Routine handles iBGP peers correctly */
David Lamparter5f9adb52014-05-19 23:15:02 +02004673 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4674 if (ret != 0)
4675 return ret;
4676 }
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004677
Nick Hilliardfa411a22011-03-23 15:33:17 +00004678 peer->gtsm_hops = gtsm_hops;
4679
Nick Hilliardfa411a22011-03-23 15:33:17 +00004680 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4681 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004682 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004683 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4684 }
4685 else
4686 {
4687 group = peer->group;
4688 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4689 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004690 peer->gtsm_hops = group->conf->gtsm_hops;
4691
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004692 /* Change setting of existing peer
4693 * established then change value (may break connectivity)
4694 * not established yet (teardown session and restart)
4695 * no session then do nothing (will get handled by next connection)
4696 */
4697 if (peer->status == Established)
4698 {
4699 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4700 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4701 MAXTTL + 1 - peer->gtsm_hops);
4702 }
4703 else if (peer->status < Established)
4704 {
4705 if (BGP_DEBUG (events, EVENTS))
4706 zlog_debug ("%s Min-ttl changed", peer->host);
4707 BGP_EVENT_ADD (peer, BGP_Stop);
4708 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004709 }
4710 }
4711
4712 return 0;
4713}
4714
4715int
4716peer_ttl_security_hops_unset (struct peer *peer)
4717{
4718 struct peer_group *group;
4719 struct listnode *node, *nnode;
4720 struct peer *opeer;
4721
4722 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4723
Nick Hilliardfa411a22011-03-23 15:33:17 +00004724 /* if a peer-group member, then reset to peer-group default rather than 0 */
4725 if (peer_group_active (peer))
4726 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4727 else
4728 peer->gtsm_hops = 0;
4729
4730 opeer = peer;
4731 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4732 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004733 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004734 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4735 }
4736 else
4737 {
4738 group = peer->group;
4739 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4740 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004741 peer->gtsm_hops = 0;
4742
4743 if (peer->fd >= 0)
4744 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4745 }
4746 }
4747
4748 return peer_ebgp_multihop_unset (opeer);
4749}
David Lamparter6b0655a2014-06-04 06:53:35 +02004750
paul718e3742002-12-13 20:15:29 +00004751int
4752peer_clear (struct peer *peer)
4753{
4754 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4755 {
hasso0a486e52005-02-01 20:57:17 +00004756 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4757 {
4758 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4759 if (peer->t_pmax_restart)
4760 {
4761 BGP_TIMER_OFF (peer->t_pmax_restart);
4762 if (BGP_DEBUG (events, EVENTS))
4763 zlog_debug ("%s Maximum-prefix restart timer canceled",
4764 peer->host);
4765 }
4766 BGP_EVENT_ADD (peer, BGP_Start);
4767 return 0;
4768 }
4769
paul718e3742002-12-13 20:15:29 +00004770 peer->v_start = BGP_INIT_START_TIMER;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00004771 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00004772 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4773 BGP_NOTIFY_CEASE_ADMIN_RESET);
4774 else
4775 BGP_EVENT_ADD (peer, BGP_Stop);
4776 }
4777 return 0;
4778}
4779
4780int
4781peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4782 enum bgp_clear_type stype)
4783{
4784 if (peer->status != Established)
4785 return 0;
4786
4787 if (! peer->afc[afi][safi])
4788 return BGP_ERR_AF_UNCONFIGURED;
4789
Timo Teräs5a2a1ec2015-10-22 11:35:18 +03004790 peer->rtt = sockopt_tcp_rtt (peer->fd);
4791
paulfee0f4c2004-09-13 05:12:46 +00004792 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4793 {
4794 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4795 return 0;
4796 bgp_check_local_routes_rsclient (peer, afi, safi);
4797 bgp_soft_reconfig_rsclient (peer, afi, safi);
4798 }
4799
paul718e3742002-12-13 20:15:29 +00004800 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4801 bgp_announce_route (peer, afi, safi);
4802
4803 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4804 {
4805 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4806 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4807 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4808 {
4809 struct bgp_filter *filter = &peer->filter[afi][safi];
4810 u_char prefix_type;
4811
4812 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4813 prefix_type = ORF_TYPE_PREFIX;
4814 else
4815 prefix_type = ORF_TYPE_PREFIX_OLD;
4816
4817 if (filter->plist[FILTER_IN].plist)
4818 {
4819 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4820 bgp_route_refresh_send (peer, afi, safi,
4821 prefix_type, REFRESH_DEFER, 1);
4822 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4823 REFRESH_IMMEDIATE, 0);
4824 }
4825 else
4826 {
4827 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4828 bgp_route_refresh_send (peer, afi, safi,
4829 prefix_type, REFRESH_IMMEDIATE, 1);
4830 else
4831 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4832 }
4833 return 0;
4834 }
4835 }
4836
4837 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4838 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4839 {
4840 /* If neighbor has soft reconfiguration inbound flag.
4841 Use Adj-RIB-In database. */
4842 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4843 bgp_soft_reconfig_in (peer, afi, safi);
4844 else
4845 {
4846 /* If neighbor has route refresh capability, send route refresh
4847 message to the peer. */
4848 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4849 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4850 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4851 else
4852 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4853 }
4854 }
4855 return 0;
4856}
David Lamparter6b0655a2014-06-04 06:53:35 +02004857
paulfd79ac92004-10-13 05:06:08 +00004858/* Display peer uptime.*/
4859/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004860char *
4861peer_uptime (time_t uptime2, char *buf, size_t len)
4862{
4863 time_t uptime1;
4864 struct tm *tm;
4865
4866 /* Check buffer length. */
4867 if (len < BGP_UPTIME_LEN)
4868 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004869 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004870 /* XXX: should return status instead of buf... */
4871 snprintf (buf, len, "<error> ");
4872 return buf;
paul718e3742002-12-13 20:15:29 +00004873 }
4874
4875 /* If there is no connection has been done before print `never'. */
4876 if (uptime2 == 0)
4877 {
4878 snprintf (buf, len, "never ");
4879 return buf;
4880 }
4881
4882 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004883 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004884 uptime1 -= uptime2;
4885 tm = gmtime (&uptime1);
Paul Jakma84c38402015-05-26 15:19:38 +01004886
paul718e3742002-12-13 20:15:29 +00004887 /* Making formatted timer strings. */
4888#define ONE_DAY_SECOND 60*60*24
Paul Jakma84c38402015-05-26 15:19:38 +01004889#define ONE_WEEK_SECOND ONE_DAY_SECOND*7
4890#define ONE_YEAR_SECOND ONE_DAY_SECOND*365
paul718e3742002-12-13 20:15:29 +00004891
4892 if (uptime1 < ONE_DAY_SECOND)
4893 snprintf (buf, len, "%02d:%02d:%02d",
4894 tm->tm_hour, tm->tm_min, tm->tm_sec);
4895 else if (uptime1 < ONE_WEEK_SECOND)
4896 snprintf (buf, len, "%dd%02dh%02dm",
4897 tm->tm_yday, tm->tm_hour, tm->tm_min);
Paul Jakma84c38402015-05-26 15:19:38 +01004898 else if (uptime1 < ONE_YEAR_SECOND)
paul718e3742002-12-13 20:15:29 +00004899 snprintf (buf, len, "%02dw%dd%02dh",
4900 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
Paul Jakma84c38402015-05-26 15:19:38 +01004901 else
4902 snprintf (buf, len, "%02dy%02dw%dd",
4903 tm->tm_year - 70, tm->tm_yday/7,
4904 tm->tm_yday - ((tm->tm_yday/7) * 7));
paul718e3742002-12-13 20:15:29 +00004905 return buf;
4906}
David Lamparter6b0655a2014-06-04 06:53:35 +02004907
paul94f2b392005-06-28 12:44:16 +00004908static void
paul718e3742002-12-13 20:15:29 +00004909bgp_config_write_filter (struct vty *vty, struct peer *peer,
4910 afi_t afi, safi_t safi)
4911{
4912 struct bgp_filter *filter;
4913 struct bgp_filter *gfilter = NULL;
4914 char *addr;
4915 int in = FILTER_IN;
4916 int out = FILTER_OUT;
4917
4918 addr = peer->host;
4919 filter = &peer->filter[afi][safi];
4920 if (peer->af_group[afi][safi])
4921 gfilter = &peer->group->conf->filter[afi][safi];
4922
4923 /* distribute-list. */
4924 if (filter->dlist[in].name)
4925 if (! gfilter || ! gfilter->dlist[in].name
4926 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4927 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4928 filter->dlist[in].name, VTY_NEWLINE);
4929 if (filter->dlist[out].name && ! gfilter)
4930 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4931 filter->dlist[out].name, VTY_NEWLINE);
4932
4933 /* prefix-list. */
4934 if (filter->plist[in].name)
4935 if (! gfilter || ! gfilter->plist[in].name
4936 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4937 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4938 filter->plist[in].name, VTY_NEWLINE);
4939 if (filter->plist[out].name && ! gfilter)
4940 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4941 filter->plist[out].name, VTY_NEWLINE);
4942
4943 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004944 if (filter->map[RMAP_IN].name)
4945 if (! gfilter || ! gfilter->map[RMAP_IN].name
4946 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004947 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004948 filter->map[RMAP_IN].name, VTY_NEWLINE);
4949 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004950 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004951 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4952 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4953 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4954 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4955 if (filter->map[RMAP_EXPORT].name)
4956 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4957 || strcmp (filter->map[RMAP_EXPORT].name,
4958 gfilter->map[RMAP_EXPORT].name) != 0)
4959 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4960 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004961
4962 /* unsuppress-map */
4963 if (filter->usmap.name && ! gfilter)
4964 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4965 filter->usmap.name, VTY_NEWLINE);
4966
4967 /* filter-list. */
4968 if (filter->aslist[in].name)
4969 if (! gfilter || ! gfilter->aslist[in].name
4970 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4971 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4972 filter->aslist[in].name, VTY_NEWLINE);
4973 if (filter->aslist[out].name && ! gfilter)
4974 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4975 filter->aslist[out].name, VTY_NEWLINE);
4976}
4977
4978/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004979static void
paul718e3742002-12-13 20:15:29 +00004980bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4981 struct peer *peer, afi_t afi, safi_t safi)
4982{
paul718e3742002-12-13 20:15:29 +00004983 struct peer *g_peer = NULL;
4984 char buf[SU_ADDRSTRLEN];
4985 char *addr;
4986
paul718e3742002-12-13 20:15:29 +00004987 addr = peer->host;
4988 if (peer_group_active (peer))
4989 g_peer = peer->group->conf;
4990
4991 /************************************
4992 ****** Global to the neighbor ******
4993 ************************************/
4994 if (afi == AFI_IP && safi == SAFI_UNICAST)
4995 {
4996 /* remote-as. */
4997 if (! peer_group_active (peer))
4998 {
4999 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
5000 vty_out (vty, " neighbor %s peer-group%s", addr,
5001 VTY_NEWLINE);
5002 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005003 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00005004 VTY_NEWLINE);
5005 }
5006 else
5007 {
5008 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005009 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00005010 VTY_NEWLINE);
5011 if (peer->af_group[AFI_IP][SAFI_UNICAST])
5012 vty_out (vty, " neighbor %s peer-group %s%s", addr,
5013 peer->group->name, VTY_NEWLINE);
5014 }
5015
5016 /* local-as. */
5017 if (peer->change_local_as)
5018 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00005019 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00005020 peer->change_local_as,
5021 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00005022 " no-prepend" : "",
5023 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
5024 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005025
5026 /* Description. */
5027 if (peer->desc)
5028 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
5029 VTY_NEWLINE);
5030
5031 /* Shutdown. */
5032 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
5033 if (! peer_group_active (peer) ||
5034 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
5035 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
5036
Paul Jakma0df7c912008-07-21 21:02:49 +00005037 /* Password. */
5038 if (peer->password)
5039 if (!peer_group_active (peer)
5040 || ! g_peer->password
5041 || strcmp (peer->password, g_peer->password) != 0)
5042 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
5043 VTY_NEWLINE);
5044
paul718e3742002-12-13 20:15:29 +00005045 /* BGP port. */
5046 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00005047 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00005048 VTY_NEWLINE);
5049
5050 /* Local interface name. */
5051 if (peer->ifname)
5052 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
5053 VTY_NEWLINE);
5054
5055 /* Passive. */
5056 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
5057 if (! peer_group_active (peer) ||
5058 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
5059 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
5060
5061 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00005062 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00005063 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00005064 if (! peer_group_active (peer) ||
5065 g_peer->ttl != peer->ttl)
5066 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
5067 VTY_NEWLINE);
5068
Nick Hilliardfa411a22011-03-23 15:33:17 +00005069 /* ttl-security hops */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00005070 if (peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00005071 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00005072 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00005073 peer->gtsm_hops, VTY_NEWLINE);
5074
hasso6ffd2072005-02-02 14:50:11 +00005075 /* disable-connected-check. */
5076 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00005077 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00005078 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
5079 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005080
5081 /* Update-source. */
5082 if (peer->update_if)
5083 if (! peer_group_active (peer) || ! g_peer->update_if
5084 || strcmp (g_peer->update_if, peer->update_if) != 0)
5085 vty_out (vty, " neighbor %s update-source %s%s", addr,
5086 peer->update_if, VTY_NEWLINE);
5087 if (peer->update_source)
5088 if (! peer_group_active (peer) || ! g_peer->update_source
5089 || sockunion_cmp (g_peer->update_source,
5090 peer->update_source) != 0)
5091 vty_out (vty, " neighbor %s update-source %s%s", addr,
5092 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
5093 VTY_NEWLINE);
5094
paul718e3742002-12-13 20:15:29 +00005095 /* advertisement-interval */
Daniel Walton0d7435f2015-10-22 11:35:20 +03005096 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV) &&
5097 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00005098 vty_out (vty, " neighbor %s advertisement-interval %d%s",
5099 addr, peer->v_routeadv, VTY_NEWLINE);
5100
5101 /* timers. */
5102 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
5103 && ! peer_group_active (peer))
5104 vty_out (vty, " neighbor %s timers %d %d%s", addr,
5105 peer->keepalive, peer->holdtime, VTY_NEWLINE);
5106
Daniel Walton0d7435f2015-10-22 11:35:20 +03005107 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT) &&
5108 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00005109 vty_out (vty, " neighbor %s timers connect %d%s", addr,
5110 peer->connect, VTY_NEWLINE);
5111
5112 /* Default weight. */
5113 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
5114 if (! peer_group_active (peer) ||
5115 g_peer->weight != peer->weight)
5116 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
5117 VTY_NEWLINE);
5118
paul718e3742002-12-13 20:15:29 +00005119 /* Dynamic capability. */
5120 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5121 if (! peer_group_active (peer) ||
5122 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5123 vty_out (vty, " neighbor %s capability dynamic%s", addr,
5124 VTY_NEWLINE);
5125
5126 /* dont capability negotiation. */
5127 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
5128 if (! peer_group_active (peer) ||
5129 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
5130 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
5131 VTY_NEWLINE);
5132
5133 /* override capability negotiation. */
5134 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5135 if (! peer_group_active (peer) ||
5136 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5137 vty_out (vty, " neighbor %s override-capability%s", addr,
5138 VTY_NEWLINE);
5139
5140 /* strict capability negotiation. */
5141 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5142 if (! peer_group_active (peer) ||
5143 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5144 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
5145 VTY_NEWLINE);
5146
Christian Franke15c71342012-11-19 11:17:31 +00005147 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
paul718e3742002-12-13 20:15:29 +00005148 {
5149 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5150 {
5151 if (peer->afc[AFI_IP][SAFI_UNICAST])
5152 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5153 }
5154 else
5155 {
5156 if (! peer->afc[AFI_IP][SAFI_UNICAST])
5157 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
5158 }
5159 }
5160 }
5161
5162
5163 /************************************
5164 ****** Per AF to the neighbor ******
5165 ************************************/
5166
5167 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
5168 {
5169 if (peer->af_group[afi][safi])
5170 vty_out (vty, " neighbor %s peer-group %s%s", addr,
5171 peer->group->name, VTY_NEWLINE);
5172 else
5173 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5174 }
5175
5176 /* ORF capability. */
5177 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5178 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5179 if (! peer->af_group[afi][safi])
5180 {
5181 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
5182
5183 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5184 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5185 vty_out (vty, " both");
5186 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
5187 vty_out (vty, " send");
5188 else
5189 vty_out (vty, " receive");
5190 vty_out (vty, "%s", VTY_NEWLINE);
5191 }
5192
5193 /* Route reflector client. */
5194 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
5195 && ! peer->af_group[afi][safi])
5196 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
5197 VTY_NEWLINE);
5198
5199 /* Nexthop self. */
5200 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
5201 && ! peer->af_group[afi][safi])
Timo Teräs9e7a53c2014-04-24 10:22:37 +03005202 vty_out (vty, " neighbor %s next-hop-self%s%s", addr,
5203 peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ?
5204 " all" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005205
5206 /* Remove private AS. */
5207 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
5208 && ! peer->af_group[afi][safi])
5209 vty_out (vty, " neighbor %s remove-private-AS%s",
5210 addr, VTY_NEWLINE);
5211
5212 /* send-community print. */
5213 if (! peer->af_group[afi][safi])
5214 {
5215 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5216 {
5217 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5218 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5219 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
5220 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5221 vty_out (vty, " neighbor %s send-community extended%s",
5222 addr, VTY_NEWLINE);
5223 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5224 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
5225 }
5226 else
5227 {
5228 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5229 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5230 vty_out (vty, " no neighbor %s send-community both%s",
5231 addr, VTY_NEWLINE);
5232 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5233 vty_out (vty, " no neighbor %s send-community extended%s",
5234 addr, VTY_NEWLINE);
5235 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5236 vty_out (vty, " no neighbor %s send-community%s",
5237 addr, VTY_NEWLINE);
5238 }
5239 }
5240
5241 /* Default information */
5242 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5243 && ! peer->af_group[afi][safi])
5244 {
5245 vty_out (vty, " neighbor %s default-originate", addr);
5246 if (peer->default_rmap[afi][safi].name)
5247 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5248 vty_out (vty, "%s", VTY_NEWLINE);
5249 }
5250
5251 /* Soft reconfiguration inbound. */
5252 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5253 if (! peer->af_group[afi][safi] ||
5254 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5255 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5256 VTY_NEWLINE);
5257
5258 /* maximum-prefix. */
5259 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5260 if (! peer->af_group[afi][safi]
5261 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005262 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005263 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5264 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005265 {
hasso0a486e52005-02-01 20:57:17 +00005266 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5267 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5268 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5269 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5270 vty_out (vty, " warning-only");
5271 if (peer->pmax_restart[afi][safi])
5272 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5273 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005274 }
paul718e3742002-12-13 20:15:29 +00005275
5276 /* Route server client. */
5277 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5278 && ! peer->af_group[afi][safi])
5279 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5280
Dylan Hall3cf12882011-10-27 15:28:17 +04005281 /* Nexthop-local unchanged. */
5282 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5283 && ! peer->af_group[afi][safi])
5284 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5285
paul718e3742002-12-13 20:15:29 +00005286 /* Allow AS in. */
5287 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5288 if (! peer_group_active (peer)
5289 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5290 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5291 {
5292 if (peer->allowas_in[afi][safi] == 3)
5293 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5294 else
5295 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5296 peer->allowas_in[afi][safi], VTY_NEWLINE);
5297 }
5298
5299 /* Filter. */
5300 bgp_config_write_filter (vty, peer, afi, safi);
5301
5302 /* atribute-unchanged. */
5303 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5304 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5305 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5306 && ! peer->af_group[afi][safi])
5307 {
5308 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5309 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5310 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5311 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5312 else
5313 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5314 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5315 " as-path" : "",
5316 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5317 " next-hop" : "",
5318 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5319 " med" : "", VTY_NEWLINE);
5320 }
5321}
5322
5323/* Display "address-family" configuration header. */
5324void
5325bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5326 int *write)
5327{
5328 if (*write)
5329 return;
5330
5331 if (afi == AFI_IP && safi == SAFI_UNICAST)
5332 return;
5333
5334 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5335
5336 if (afi == AFI_IP)
5337 {
5338 if (safi == SAFI_MULTICAST)
5339 vty_out (vty, "ipv4 multicast");
5340 else if (safi == SAFI_MPLS_VPN)
Lou Bergera3fda882016-01-12 13:42:04 -05005341 vty_out (vty, "vpnv4");
5342 else if (safi == SAFI_ENCAP)
5343 vty_out (vty, "encap");
paul718e3742002-12-13 20:15:29 +00005344 }
5345 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005346 {
Lou Berger13c378d2016-01-12 13:41:56 -05005347 if (safi == SAFI_MPLS_VPN)
5348 vty_out (vty, "vpnv6");
Lou Bergera3fda882016-01-12 13:42:04 -05005349 else if (safi == SAFI_ENCAP)
5350 vty_out (vty, "encapv6");
Lou Berger13c378d2016-01-12 13:41:56 -05005351 else
5352 {
5353 vty_out (vty, "ipv6");
5354 if (safi == SAFI_MULTICAST)
5355 vty_out (vty, " multicast");
5356 }
Paul Jakma37a217a2007-04-10 19:20:29 +00005357 }
paul718e3742002-12-13 20:15:29 +00005358
5359 vty_out (vty, "%s", VTY_NEWLINE);
5360
5361 *write = 1;
5362}
5363
5364/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005365static int
paul718e3742002-12-13 20:15:29 +00005366bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5367 safi_t safi)
5368{
5369 int write = 0;
5370 struct peer *peer;
5371 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005372 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005373
5374 bgp_config_write_network (vty, bgp, afi, safi, &write);
5375
5376 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5377
paul1eb8ef22005-04-07 07:30:20 +00005378 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005379 {
5380 if (group->conf->afc[afi][safi])
5381 {
5382 bgp_config_write_family_header (vty, afi, safi, &write);
5383 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5384 }
5385 }
paul1eb8ef22005-04-07 07:30:20 +00005386 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005387 {
5388 if (peer->afc[afi][safi])
5389 {
5390 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5391 {
5392 bgp_config_write_family_header (vty, afi, safi, &write);
5393 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5394 }
5395 }
5396 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005397
5398 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5399
Roman Hoog Antink6184c392014-03-17 14:01:42 +01005400 bgp_config_write_distance (vty, bgp, afi, safi, &write);
5401
paul718e3742002-12-13 20:15:29 +00005402 if (write)
5403 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5404
5405 return write;
5406}
5407
5408int
5409bgp_config_write (struct vty *vty)
5410{
5411 int write = 0;
5412 struct bgp *bgp;
5413 struct peer_group *group;
5414 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005415 struct listnode *node, *nnode;
5416 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005417
5418 /* BGP Multiple instance. */
5419 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5420 {
5421 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5422 write++;
5423 }
5424
5425 /* BGP Config type. */
5426 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5427 {
5428 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5429 write++;
5430 }
5431
5432 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005433 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005434 {
5435 if (write)
5436 vty_out (vty, "!%s", VTY_NEWLINE);
5437
5438 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005439 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005440
5441 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5442 {
5443 if (bgp->name)
5444 vty_out (vty, " view %s", bgp->name);
5445 }
5446 vty_out (vty, "%s", VTY_NEWLINE);
5447
5448 /* No Synchronization */
5449 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5450 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5451
5452 /* BGP fast-external-failover. */
5453 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5454 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5455
5456 /* BGP router ID. */
5457 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5458 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5459 VTY_NEWLINE);
5460
paul848973c2003-08-13 00:32:49 +00005461 /* BGP log-neighbor-changes. */
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07005462 if (!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5463 vty_out (vty, " no bgp log-neighbor-changes%s", VTY_NEWLINE);
paul848973c2003-08-13 00:32:49 +00005464
paul718e3742002-12-13 20:15:29 +00005465 /* BGP configuration. */
5466 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5467 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5468
5469 /* BGP default ipv4-unicast. */
5470 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5471 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5472
5473 /* BGP default local-preference. */
5474 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5475 vty_out (vty, " bgp default local-preference %d%s",
5476 bgp->default_local_pref, VTY_NEWLINE);
5477
5478 /* BGP client-to-client reflection. */
5479 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5480 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5481
5482 /* BGP cluster ID. */
5483 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5484 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5485 VTY_NEWLINE);
5486
hassoe0701b72004-05-20 09:19:34 +00005487 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005488 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005489 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5490 VTY_NEWLINE);
5491
5492 /* Confederation peer */
5493 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005494 {
hassoe0701b72004-05-20 09:19:34 +00005495 int i;
paul718e3742002-12-13 20:15:29 +00005496
hassoe0701b72004-05-20 09:19:34 +00005497 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005498
hassoe0701b72004-05-20 09:19:34 +00005499 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005500 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005501
hassoe0701b72004-05-20 09:19:34 +00005502 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005503 }
5504
5505 /* BGP enforce-first-as. */
5506 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5507 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5508
5509 /* BGP deterministic-med. */
5510 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5511 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005512
5513 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005514 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5515 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5516 bgp->stalepath_time, VTY_NEWLINE);
Philippe Guibert4afa3dd2016-05-24 16:52:02 +02005517 if (bgp->restart_time != BGP_DEFAULT_RESTART_TIME)
5518 vty_out (vty, " bgp graceful-restart restart-time %d%s",
5519 bgp->restart_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005520 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5521 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5522
paul718e3742002-12-13 20:15:29 +00005523 /* BGP bestpath method. */
5524 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5525 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005526 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5527 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
Pradosh Mohapatra2fdd4552013-09-07 07:02:36 +00005528 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
5529 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
5530 }
paul718e3742002-12-13 20:15:29 +00005531 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5532 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5533 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5534 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5535 {
5536 vty_out (vty, " bgp bestpath med");
5537 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5538 vty_out (vty, " confed");
5539 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5540 vty_out (vty, " missing-as-worst");
5541 vty_out (vty, "%s", VTY_NEWLINE);
5542 }
5543
5544 /* BGP network import check. */
5545 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5546 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5547
5548 /* BGP scan interval. */
5549 bgp_config_write_scan_time (vty);
5550
5551 /* BGP flag dampening. */
5552 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5553 BGP_CONFIG_DAMPENING))
5554 bgp_config_write_damp (vty);
5555
5556 /* BGP static route configuration. */
5557 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5558
5559 /* BGP redistribute configuration. */
5560 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5561
5562 /* BGP timers configuration. */
5563 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5564 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5565 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5566 bgp->default_holdtime, VTY_NEWLINE);
5567
5568 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005569 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005570 {
5571 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5572 }
5573
5574 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005575 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005576 {
5577 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5578 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5579 }
5580
Josh Bailey165b5ff2011-07-20 20:43:22 -07005581 /* maximum-paths */
5582 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5583
paul718e3742002-12-13 20:15:29 +00005584 /* Distance configuration. */
Roman Hoog Antink6184c392014-03-17 14:01:42 +01005585 bgp_config_write_distance (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
paul718e3742002-12-13 20:15:29 +00005586
5587 /* No auto-summary */
5588 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5589 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5590
5591 /* IPv4 multicast configuration. */
5592 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5593
5594 /* IPv4 VPN configuration. */
5595 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5596
Lou Bergera3fda882016-01-12 13:42:04 -05005597 /* ENCAPv4 configuration. */
5598 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_ENCAP);
5599
paul718e3742002-12-13 20:15:29 +00005600 /* IPv6 unicast configuration. */
5601 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5602
Paul Jakma37a217a2007-04-10 19:20:29 +00005603 /* IPv6 multicast configuration. */
5604 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5605
Lou Berger13c378d2016-01-12 13:41:56 -05005606 /* IPv6 VPN configuration. */
5607 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MPLS_VPN);
5608
Lou Bergera3fda882016-01-12 13:42:04 -05005609 /* ENCAPv6 configuration. */
5610 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_ENCAP);
5611
5612 vty_out (vty, " exit%s", VTY_NEWLINE);
5613
paul718e3742002-12-13 20:15:29 +00005614 write++;
5615 }
5616 return write;
5617}
5618
5619void
paul94f2b392005-06-28 12:44:16 +00005620bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005621{
5622 memset (&bgp_master, 0, sizeof (struct bgp_master));
5623
5624 bm = &bgp_master;
5625 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005626 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005627 bm->port = BGP_PORT_DEFAULT;
5628 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005629 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005630}
paul200df112005-06-01 11:17:05 +00005631
David Lamparter6b0655a2014-06-04 06:53:35 +02005632
paul718e3742002-12-13 20:15:29 +00005633void
paul94f2b392005-06-28 12:44:16 +00005634bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005635{
paul718e3742002-12-13 20:15:29 +00005636 /* BGP VTY commands installation. */
5637 bgp_vty_init ();
5638
paul718e3742002-12-13 20:15:29 +00005639 /* Init zebra. */
Donald Sharp774914f2015-10-14 08:50:39 -04005640 bgp_zebra_init (bm->master);
paul718e3742002-12-13 20:15:29 +00005641
5642 /* BGP inits. */
5643 bgp_attr_init ();
5644 bgp_debug_init ();
5645 bgp_dump_init ();
5646 bgp_route_init ();
5647 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005648 bgp_address_init ();
paul718e3742002-12-13 20:15:29 +00005649 bgp_scan_init ();
5650 bgp_mplsvpn_init ();
Lou Berger298cc2f2016-01-12 13:42:02 -05005651 bgp_encap_init ();
paul718e3742002-12-13 20:15:29 +00005652
5653 /* Access list initialize. */
5654 access_list_init ();
5655 access_list_add_hook (peer_distribute_update);
5656 access_list_delete_hook (peer_distribute_update);
5657
5658 /* Filter list initialize. */
5659 bgp_filter_init ();
5660 as_list_add_hook (peer_aslist_update);
5661 as_list_delete_hook (peer_aslist_update);
5662
5663 /* Prefix list initialize.*/
5664 prefix_list_init ();
5665 prefix_list_add_hook (peer_prefix_list_update);
5666 prefix_list_delete_hook (peer_prefix_list_update);
5667
5668 /* Community list initialize. */
5669 bgp_clist = community_list_init ();
5670
5671#ifdef HAVE_SNMP
5672 bgp_snmp_init ();
5673#endif /* HAVE_SNMP */
5674}
paul545acaf2004-04-20 15:13:15 +00005675
5676void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005677bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005678{
paul545acaf2004-04-20 15:13:15 +00005679 struct bgp *bgp;
5680 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005681 struct listnode *node, *nnode;
5682 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005683
paul1eb8ef22005-04-07 07:30:20 +00005684 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5685 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005686 if (peer->status == Established)
5687 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5688 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005689
paul545acaf2004-04-20 15:13:15 +00005690 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005691
paule210cf92005-06-15 19:15:35 +00005692 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005693 {
5694 work_queue_free (bm->process_main_queue);
5695 bm->process_main_queue = NULL;
5696 }
paule210cf92005-06-15 19:15:35 +00005697 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005698 {
5699 work_queue_free (bm->process_rsclient_queue);
5700 bm->process_rsclient_queue = NULL;
5701 }
paul545acaf2004-04-20 15:13:15 +00005702}