blob: 636f56934c06be67924049babe67fef89feccd34 [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"
paul718e3742002-12-13 20:15:29 +000039
40#include "bgpd/bgpd.h"
41#include "bgpd/bgp_table.h"
42#include "bgpd/bgp_aspath.h"
43#include "bgpd/bgp_route.h"
44#include "bgpd/bgp_dump.h"
45#include "bgpd/bgp_debug.h"
46#include "bgpd/bgp_community.h"
47#include "bgpd/bgp_attr.h"
48#include "bgpd/bgp_regex.h"
49#include "bgpd/bgp_clist.h"
50#include "bgpd/bgp_fsm.h"
51#include "bgpd/bgp_packet.h"
52#include "bgpd/bgp_zebra.h"
53#include "bgpd/bgp_open.h"
54#include "bgpd/bgp_filter.h"
55#include "bgpd/bgp_nexthop.h"
56#include "bgpd/bgp_damp.h"
57#include "bgpd/bgp_mplsvpn.h"
58#include "bgpd/bgp_advertise.h"
59#include "bgpd/bgp_network.h"
60#include "bgpd/bgp_vty.h"
Josh Bailey165b5ff2011-07-20 20:43:22 -070061#include "bgpd/bgp_mpath.h"
paul718e3742002-12-13 20:15:29 +000062#ifdef HAVE_SNMP
63#include "bgpd/bgp_snmp.h"
64#endif /* HAVE_SNMP */
David Lamparter6b0655a2014-06-04 06:53:35 +020065
paul718e3742002-12-13 20:15:29 +000066/* BGP process wide configuration. */
67static struct bgp_master bgp_master;
68
hasso18a6dce2004-10-03 18:18:34 +000069extern struct in_addr router_id_zebra;
70
paul718e3742002-12-13 20:15:29 +000071/* BGP process wide configuration pointer to export. */
72struct bgp_master *bm;
73
74/* BGP community-list. */
75struct community_list_handler *bgp_clist;
David Lamparter6b0655a2014-06-04 06:53:35 +020076
paul718e3742002-12-13 20:15:29 +000077/* BGP global flag manipulation. */
78int
79bgp_option_set (int flag)
80{
81 switch (flag)
82 {
83 case BGP_OPT_NO_FIB:
84 case BGP_OPT_MULTIPLE_INSTANCE:
85 case BGP_OPT_CONFIG_CISCO:
Paul Jakmacccbc012012-06-14 10:40:26 +010086 case BGP_OPT_NO_LISTEN:
paul718e3742002-12-13 20:15:29 +000087 SET_FLAG (bm->options, flag);
88 break;
89 default:
90 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +000091 }
92 return 0;
93}
94
95int
96bgp_option_unset (int flag)
97{
98 switch (flag)
99 {
100 case BGP_OPT_MULTIPLE_INSTANCE:
101 if (listcount (bm->bgp) > 1)
102 return BGP_ERR_MULTIPLE_INSTANCE_USED;
103 /* Fall through. */
104 case BGP_OPT_NO_FIB:
105 case BGP_OPT_CONFIG_CISCO:
106 UNSET_FLAG (bm->options, flag);
107 break;
108 default:
109 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +0000110 }
111 return 0;
112}
113
114int
115bgp_option_check (int flag)
116{
117 return CHECK_FLAG (bm->options, flag);
118}
David Lamparter6b0655a2014-06-04 06:53:35 +0200119
paul718e3742002-12-13 20:15:29 +0000120/* BGP flag manipulation. */
121int
122bgp_flag_set (struct bgp *bgp, int flag)
123{
124 SET_FLAG (bgp->flags, flag);
125 return 0;
126}
127
128int
129bgp_flag_unset (struct bgp *bgp, int flag)
130{
131 UNSET_FLAG (bgp->flags, flag);
132 return 0;
133}
134
135int
136bgp_flag_check (struct bgp *bgp, int flag)
137{
138 return CHECK_FLAG (bgp->flags, flag);
139}
David Lamparter6b0655a2014-06-04 06:53:35 +0200140
paul718e3742002-12-13 20:15:29 +0000141/* Internal function to set BGP structure configureation flag. */
142static void
143bgp_config_set (struct bgp *bgp, int config)
144{
145 SET_FLAG (bgp->config, config);
146}
147
148static void
149bgp_config_unset (struct bgp *bgp, int config)
150{
151 UNSET_FLAG (bgp->config, config);
152}
153
154static int
155bgp_config_check (struct bgp *bgp, int config)
156{
157 return CHECK_FLAG (bgp->config, config);
158}
David Lamparter6b0655a2014-06-04 06:53:35 +0200159
paul718e3742002-12-13 20:15:29 +0000160/* Set BGP router identifier. */
161int
162bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
163{
164 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000165 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000166
167 if (bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID)
168 && IPV4_ADDR_SAME (&bgp->router_id, id))
169 return 0;
170
171 IPV4_ADDR_COPY (&bgp->router_id, id);
172 bgp_config_set (bgp, BGP_CONFIG_ROUTER_ID);
173
174 /* Set all peer's local identifier with this value. */
paul1eb8ef22005-04-07 07:30:20 +0000175 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000176 {
177 IPV4_ADDR_COPY (&peer->local_id, id);
178
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000179 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000180 {
181 peer->last_reset = PEER_DOWN_RID_CHANGE;
182 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
183 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
184 }
paul718e3742002-12-13 20:15:29 +0000185 }
186 return 0;
187}
188
paul718e3742002-12-13 20:15:29 +0000189/* BGP's cluster-id control. */
190int
191bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
192{
193 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000194 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000195
196 if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)
197 && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id))
198 return 0;
199
200 IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id);
201 bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID);
202
203 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000204 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000205 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000206 if (peer->sort != BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +0000207 continue;
208
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000209 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000210 {
211 peer->last_reset = PEER_DOWN_CLID_CHANGE;
212 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
213 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
214 }
paul718e3742002-12-13 20:15:29 +0000215 }
216 return 0;
217}
218
219int
220bgp_cluster_id_unset (struct bgp *bgp)
221{
222 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000223 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000224
225 if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID))
226 return 0;
227
228 bgp->cluster_id.s_addr = 0;
229 bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID);
230
231 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000232 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000233 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000234 if (peer->sort != BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +0000235 continue;
236
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000237 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000238 {
239 peer->last_reset = PEER_DOWN_CLID_CHANGE;
240 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
241 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
242 }
paul718e3742002-12-13 20:15:29 +0000243 }
244 return 0;
245}
David Lamparter6b0655a2014-06-04 06:53:35 +0200246
Stephen Hemminger65957882010-01-15 16:22:10 +0300247/* time_t value that is monotonicly increasing
248 * and uneffected by adjustments to system clock
249 */
250time_t bgp_clock (void)
251{
252 struct timeval tv;
253
254 quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv);
255 return tv.tv_sec;
256}
257
paul718e3742002-12-13 20:15:29 +0000258/* BGP timer configuration. */
259int
260bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
261{
262 bgp->default_keepalive = (keepalive < holdtime / 3
263 ? keepalive : holdtime / 3);
264 bgp->default_holdtime = holdtime;
265
266 return 0;
267}
268
269int
270bgp_timers_unset (struct bgp *bgp)
271{
272 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
273 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
274
275 return 0;
276}
David Lamparter6b0655a2014-06-04 06:53:35 +0200277
paul718e3742002-12-13 20:15:29 +0000278/* BGP confederation configuration. */
279int
280bgp_confederation_id_set (struct bgp *bgp, as_t as)
281{
282 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000283 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000284 int already_confed;
285
286 if (as == 0)
287 return BGP_ERR_INVALID_AS;
288
289 /* Remember - were we doing confederation before? */
290 already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);
291 bgp->confed_id = as;
292 bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);
293
294 /* If we were doing confederation already, this is just an external
295 AS change. Just Reset EBGP sessions, not CONFED sessions. If we
296 were not doing confederation before, reset all EBGP sessions. */
paul1eb8ef22005-04-07 07:30:20 +0000297 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000298 {
299 /* We're looking for peers who's AS is not local or part of our
300 confederation. */
301 if (already_confed)
302 {
303 if (peer_sort (peer) == BGP_PEER_EBGP)
304 {
305 peer->local_as = as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000306 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000307 {
308 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
309 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
310 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
311 }
312
paul718e3742002-12-13 20:15:29 +0000313 else
314 BGP_EVENT_ADD (peer, BGP_Stop);
315 }
316 }
317 else
318 {
319 /* Not doign confederation before, so reset every non-local
320 session */
321 if (peer_sort (peer) != BGP_PEER_IBGP)
322 {
323 /* Reset the local_as to be our EBGP one */
324 if (peer_sort (peer) == BGP_PEER_EBGP)
325 peer->local_as = as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000326 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000327 {
328 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
329 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
330 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
331 }
paul718e3742002-12-13 20:15:29 +0000332 else
333 BGP_EVENT_ADD (peer, BGP_Stop);
334 }
335 }
336 }
337 return 0;
338}
339
340int
341bgp_confederation_id_unset (struct bgp *bgp)
342{
343 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000344 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000345
346 bgp->confed_id = 0;
347 bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
348
paul1eb8ef22005-04-07 07:30:20 +0000349 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000350 {
351 /* We're looking for peers who's AS is not local */
352 if (peer_sort (peer) != BGP_PEER_IBGP)
353 {
354 peer->local_as = bgp->as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000355 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000356 {
357 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
358 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
359 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
360 }
361
paul718e3742002-12-13 20:15:29 +0000362 else
363 BGP_EVENT_ADD (peer, BGP_Stop);
364 }
365 }
366 return 0;
367}
368
369/* Is an AS part of the confed or not? */
370int
371bgp_confederation_peers_check (struct bgp *bgp, as_t as)
372{
373 int i;
374
375 if (! bgp)
376 return 0;
377
378 for (i = 0; i < bgp->confed_peers_cnt; i++)
379 if (bgp->confed_peers[i] == as)
380 return 1;
381
382 return 0;
383}
384
385/* Add an AS to the confederation set. */
386int
387bgp_confederation_peers_add (struct bgp *bgp, as_t as)
388{
389 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000390 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000391
392 if (! bgp)
393 return BGP_ERR_INVALID_BGP;
394
395 if (bgp->as == as)
396 return BGP_ERR_INVALID_AS;
397
398 if (bgp_confederation_peers_check (bgp, as))
399 return -1;
400
401 if (bgp->confed_peers)
402 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
403 bgp->confed_peers,
404 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
405 else
406 bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST,
407 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
408
409 bgp->confed_peers[bgp->confed_peers_cnt] = as;
410 bgp->confed_peers_cnt++;
411
412 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
413 {
paul1eb8ef22005-04-07 07:30:20 +0000414 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000415 {
416 if (peer->as == as)
417 {
418 peer->local_as = bgp->as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000419 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000420 {
421 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
422 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
423 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
424 }
paul718e3742002-12-13 20:15:29 +0000425 else
426 BGP_EVENT_ADD (peer, BGP_Stop);
427 }
428 }
429 }
430 return 0;
431}
432
433/* Delete an AS from the confederation set. */
434int
435bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
436{
437 int i;
438 int j;
439 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000440 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000441
442 if (! bgp)
443 return -1;
444
445 if (! bgp_confederation_peers_check (bgp, as))
446 return -1;
447
448 for (i = 0; i < bgp->confed_peers_cnt; i++)
449 if (bgp->confed_peers[i] == as)
450 for(j = i + 1; j < bgp->confed_peers_cnt; j++)
451 bgp->confed_peers[j - 1] = bgp->confed_peers[j];
452
453 bgp->confed_peers_cnt--;
454
455 if (bgp->confed_peers_cnt == 0)
456 {
457 if (bgp->confed_peers)
458 XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
459 bgp->confed_peers = NULL;
460 }
461 else
462 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
463 bgp->confed_peers,
464 bgp->confed_peers_cnt * sizeof (as_t));
465
466 /* Now reset any peer who's remote AS has just been removed from the
467 CONFED */
468 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
469 {
paul1eb8ef22005-04-07 07:30:20 +0000470 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000471 {
472 if (peer->as == as)
473 {
474 peer->local_as = bgp->confed_id;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000475 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000476 {
477 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
478 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
479 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
480 }
paul718e3742002-12-13 20:15:29 +0000481 else
482 BGP_EVENT_ADD (peer, BGP_Stop);
483 }
484 }
485 }
486
487 return 0;
488}
David Lamparter6b0655a2014-06-04 06:53:35 +0200489
paul718e3742002-12-13 20:15:29 +0000490/* Local preference configuration. */
491int
492bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
493{
494 if (! bgp)
495 return -1;
496
paul718e3742002-12-13 20:15:29 +0000497 bgp->default_local_pref = local_pref;
498
499 return 0;
500}
501
502int
503bgp_default_local_preference_unset (struct bgp *bgp)
504{
505 if (! bgp)
506 return -1;
507
paul718e3742002-12-13 20:15:29 +0000508 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
509
510 return 0;
511}
David Lamparter6b0655a2014-06-04 06:53:35 +0200512
paulfee0f4c2004-09-13 05:12:46 +0000513/* If peer is RSERVER_CLIENT in at least one address family and is not member
514 of a peer_group for that family, return 1.
515 Used to check wether the peer is included in list bgp->rsclient. */
516int
517peer_rsclient_active (struct peer *peer)
518{
519 int i;
520 int j;
521
522 for (i=AFI_IP; i < AFI_MAX; i++)
523 for (j=SAFI_UNICAST; j < SAFI_MAX; j++)
524 if (CHECK_FLAG(peer->af_flags[i][j], PEER_FLAG_RSERVER_CLIENT)
525 && ! peer->af_group[i][j])
526 return 1;
527 return 0;
528}
529
pauleb821182004-05-01 08:44:08 +0000530/* Peer comparison function for sorting. */
paul718e3742002-12-13 20:15:29 +0000531static int
532peer_cmp (struct peer *p1, struct peer *p2)
533{
pauleb821182004-05-01 08:44:08 +0000534 return sockunion_cmp (&p1->su, &p2->su);
paul718e3742002-12-13 20:15:29 +0000535}
536
537int
538peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
539{
540 return CHECK_FLAG (peer->af_flags[afi][safi], flag);
541}
542
543/* Reset all address family specific configuration. */
544static void
545peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
546{
547 int i;
548 struct bgp_filter *filter;
549 char orf_name[BUFSIZ];
550
551 filter = &peer->filter[afi][safi];
552
553 /* Clear neighbor filter and route-map */
554 for (i = FILTER_IN; i < FILTER_MAX; i++)
555 {
556 if (filter->dlist[i].name)
557 {
558 free (filter->dlist[i].name);
559 filter->dlist[i].name = NULL;
560 }
561 if (filter->plist[i].name)
562 {
563 free (filter->plist[i].name);
564 filter->plist[i].name = NULL;
565 }
566 if (filter->aslist[i].name)
567 {
568 free (filter->aslist[i].name);
569 filter->aslist[i].name = NULL;
570 }
paulfee0f4c2004-09-13 05:12:46 +0000571 }
572 for (i = RMAP_IN; i < RMAP_MAX; i++)
573 {
paul718e3742002-12-13 20:15:29 +0000574 if (filter->map[i].name)
575 {
576 free (filter->map[i].name);
577 filter->map[i].name = NULL;
578 }
579 }
580
581 /* Clear unsuppress map. */
582 if (filter->usmap.name)
583 free (filter->usmap.name);
584 filter->usmap.name = NULL;
585 filter->usmap.map = NULL;
586
587 /* Clear neighbor's all address family flags. */
588 peer->af_flags[afi][safi] = 0;
589
590 /* Clear neighbor's all address family sflags. */
591 peer->af_sflags[afi][safi] = 0;
592
593 /* Clear neighbor's all address family capabilities. */
594 peer->af_cap[afi][safi] = 0;
595
596 /* Clear ORF info */
597 peer->orf_plist[afi][safi] = NULL;
598 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
David Lamparterc9c06d02015-04-13 10:21:35 +0200599 prefix_bgp_orf_remove_all (afi, orf_name);
paul718e3742002-12-13 20:15:29 +0000600
601 /* Set default neighbor send-community. */
602 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
603 {
604 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
605 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
606 }
607
608 /* Clear neighbor default_originate_rmap */
609 if (peer->default_rmap[afi][safi].name)
610 free (peer->default_rmap[afi][safi].name);
611 peer->default_rmap[afi][safi].name = NULL;
612 peer->default_rmap[afi][safi].map = NULL;
613
614 /* Clear neighbor maximum-prefix */
615 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +0000616 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000617}
618
619/* peer global config reset */
paul94f2b392005-06-28 12:44:16 +0000620static void
paul718e3742002-12-13 20:15:29 +0000621peer_global_config_reset (struct peer *peer)
622{
623 peer->weight = 0;
624 peer->change_local_as = 0;
625 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
626 if (peer->update_source)
627 {
628 sockunion_free (peer->update_source);
629 peer->update_source = NULL;
630 }
631 if (peer->update_if)
632 {
633 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
634 peer->update_if = NULL;
635 }
636
637 if (peer_sort (peer) == BGP_PEER_IBGP)
638 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
639 else
640 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
641
642 peer->flags = 0;
643 peer->config = 0;
644 peer->holdtime = 0;
645 peer->keepalive = 0;
646 peer->connect = 0;
647 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
648}
649
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000650/* Check peer's AS number and determines if this peer is IBGP or EBGP */
651static bgp_peer_sort_t
652peer_calc_sort (struct peer *peer)
paul718e3742002-12-13 20:15:29 +0000653{
654 struct bgp *bgp;
655
656 bgp = peer->bgp;
657
658 /* Peer-group */
659 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
660 {
661 if (peer->as)
662 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
663 else
664 {
665 struct peer *peer1;
666 peer1 = listnode_head (peer->group->peer);
667 if (peer1)
668 return (peer1->local_as == peer1->as
669 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
670 }
671 return BGP_PEER_INTERNAL;
672 }
673
674 /* Normal peer */
675 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
676 {
677 if (peer->local_as == 0)
678 return BGP_PEER_INTERNAL;
679
680 if (peer->local_as == peer->as)
681 {
682 if (peer->local_as == bgp->confed_id)
683 return BGP_PEER_EBGP;
684 else
685 return BGP_PEER_IBGP;
686 }
687
688 if (bgp_confederation_peers_check (bgp, peer->as))
689 return BGP_PEER_CONFED;
690
691 return BGP_PEER_EBGP;
692 }
693 else
694 {
695 return (peer->local_as == 0
696 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
697 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
698 }
699}
700
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000701/* Calculate and cache the peer "sort" */
702bgp_peer_sort_t
703peer_sort (struct peer *peer)
704{
705 peer->sort = peer_calc_sort (peer);
706 return peer->sort;
707}
708
Paul Jakmaf63f06d2011-04-08 12:44:43 +0100709static void
paul200df112005-06-01 11:17:05 +0000710peer_free (struct peer *peer)
711{
Paul Jakmaca058a32006-09-14 02:58:49 +0000712 assert (peer->status == Deleted);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700713
714 bgp_unlock(peer->bgp);
715
Paul Jakmaca058a32006-09-14 02:58:49 +0000716 /* this /ought/ to have been done already through bgp_stop earlier,
717 * but just to be sure..
718 */
719 bgp_timer_set (peer);
720 BGP_READ_OFF (peer->t_read);
721 BGP_WRITE_OFF (peer->t_write);
Paul Jakma9fde6622006-09-14 03:02:02 +0000722 BGP_EVENT_FLUSH (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +0000723
paul200df112005-06-01 11:17:05 +0000724 if (peer->desc)
Daniel Walton363c9032015-10-21 06:42:54 -0700725 {
726 XFREE (MTYPE_PEER_DESC, peer->desc);
727 peer->desc = NULL;
728 }
paul200df112005-06-01 11:17:05 +0000729
730 /* Free allocated host character. */
731 if (peer->host)
Daniel Walton363c9032015-10-21 06:42:54 -0700732 {
733 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
734 peer->host = NULL;
735 }
736
paul200df112005-06-01 11:17:05 +0000737 /* Update source configuration. */
738 if (peer->update_source)
Daniel Walton363c9032015-10-21 06:42:54 -0700739 {
740 sockunion_free (peer->update_source);
741 peer->update_source = NULL;
742 }
paul200df112005-06-01 11:17:05 +0000743
744 if (peer->update_if)
Daniel Walton363c9032015-10-21 06:42:54 -0700745 {
746 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
747 peer->update_if = NULL;
748 }
Paul Jakmaa625ca32006-03-30 14:12:38 +0000749
750 if (peer->clear_node_queue)
Daniel Walton363c9032015-10-21 06:42:54 -0700751 {
752 work_queue_free(peer->clear_node_queue);
753 peer->clear_node_queue = NULL;
754 }
Paul Jakmaa625ca32006-03-30 14:12:38 +0000755
Lou Berger056f3762013-04-10 12:30:04 -0700756 if (peer->notify.data)
757 XFREE(MTYPE_TMP, peer->notify.data);
758
Paul Jakmaca058a32006-09-14 02:58:49 +0000759 bgp_sync_delete (peer);
paul200df112005-06-01 11:17:05 +0000760 memset (peer, 0, sizeof (struct peer));
761
762 XFREE (MTYPE_BGP_PEER, peer);
763}
764
765/* increase reference count on a struct peer */
766struct peer *
Donald Sharp104576d2015-09-16 13:17:55 -0400767peer_lock_with_caller (const char *name, struct peer *peer)
paul200df112005-06-01 11:17:05 +0000768{
769 assert (peer && (peer->lock >= 0));
Donald Sharp104576d2015-09-16 13:17:55 -0400770
771#if 0
772 zlog_debug("%s peer_lock %p %d", name, peer, peer->lock);
773#endif
774
paul200df112005-06-01 11:17:05 +0000775 peer->lock++;
776
777 return peer;
778}
779
780/* decrease reference count on a struct peer
781 * struct peer is freed and NULL returned if last reference
782 */
783struct peer *
Donald Sharp104576d2015-09-16 13:17:55 -0400784peer_unlock_with_caller (const char *name, struct peer *peer)
paul200df112005-06-01 11:17:05 +0000785{
786 assert (peer && (peer->lock > 0));
Donald Sharp104576d2015-09-16 13:17:55 -0400787
788#if 0
789 zlog_debug("%s peer_unlock %p %d", name, peer, peer->lock);
790#endif
791
paul200df112005-06-01 11:17:05 +0000792 peer->lock--;
793
794 if (peer->lock == 0)
795 {
paul200df112005-06-01 11:17:05 +0000796 peer_free (peer);
797 return NULL;
798 }
799
paul200df112005-06-01 11:17:05 +0000800 return peer;
801}
802
803/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000804static struct peer *
Paul Jakma6f585442006-10-22 19:13:07 +0000805peer_new (struct bgp *bgp)
paul718e3742002-12-13 20:15:29 +0000806{
807 afi_t afi;
808 safi_t safi;
809 struct peer *peer;
810 struct servent *sp;
Paul Jakma6f585442006-10-22 19:13:07 +0000811
812 /* bgp argument is absolutely required */
813 assert (bgp);
814 if (!bgp)
815 return NULL;
816
paul718e3742002-12-13 20:15:29 +0000817 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000818 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000819
820 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000821 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000822 peer->v_start = BGP_INIT_START_TIMER;
823 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
paul718e3742002-12-13 20:15:29 +0000824 peer->status = Idle;
825 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000826 peer->weight = 0;
Paul Jakma0df7c912008-07-21 21:02:49 +0000827 peer->password = NULL;
Paul Jakma6f585442006-10-22 19:13:07 +0000828 peer->bgp = bgp;
Paul Jakmaca058a32006-09-14 02:58:49 +0000829 peer = peer_lock (peer); /* initial reference */
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700830 bgp_lock (bgp);
paul718e3742002-12-13 20:15:29 +0000831
832 /* Set default flags. */
833 for (afi = AFI_IP; afi < AFI_MAX; afi++)
834 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
835 {
836 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
837 {
838 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
839 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
840 }
841 peer->orf_plist[afi][safi] = NULL;
842 }
843 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
844
845 /* Create buffers. */
846 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
847 peer->obuf = stream_fifo_new ();
848 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000849 peer->scratch = stream_new (BGP_MAX_PACKET_SIZE);
paul718e3742002-12-13 20:15:29 +0000850
851 bgp_sync_init (peer);
852
853 /* Get service port number. */
854 sp = getservbyname ("bgp", "tcp");
855 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
856
857 return peer;
858}
859
860/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000861static struct peer *
paul718e3742002-12-13 20:15:29 +0000862peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
863 as_t remote_as, afi_t afi, safi_t safi)
864{
865 int active;
866 struct peer *peer;
867 char buf[SU_ADDRSTRLEN];
868
Paul Jakma6f585442006-10-22 19:13:07 +0000869 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000870 peer->su = *su;
871 peer->local_as = local_as;
872 peer->as = remote_as;
873 peer->local_id = bgp->router_id;
874 peer->v_holdtime = bgp->default_holdtime;
875 peer->v_keepalive = bgp->default_keepalive;
876 if (peer_sort (peer) == BGP_PEER_IBGP)
877 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
878 else
879 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000880
881 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000882 listnode_add_sort (bgp->peer, peer);
883
884 active = peer_active (peer);
885
886 if (afi && safi)
887 peer->afc[afi][safi] = 1;
888
Stephen Hemminger65957882010-01-15 16:22:10 +0300889 /* Last read and reset time set */
890 peer->readtime = peer->resettime = bgp_clock ();
paul848973c2003-08-13 00:32:49 +0000891
paul718e3742002-12-13 20:15:29 +0000892 /* Default TTL set. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000893 peer->ttl = (peer->sort == BGP_PEER_IBGP) ? 255 : 1;
paul718e3742002-12-13 20:15:29 +0000894
895 /* Make peer's address string. */
896 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000897 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000898
899 /* Set up peer's events and timers. */
900 if (! active && peer_active (peer))
901 bgp_timer_set (peer);
902
903 return peer;
904}
905
pauleb821182004-05-01 08:44:08 +0000906/* Make accept BGP peer. Called from bgp_accept (). */
907struct peer *
908peer_create_accept (struct bgp *bgp)
909{
910 struct peer *peer;
911
Paul Jakma6f585442006-10-22 19:13:07 +0000912 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000913
914 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000915 listnode_add_sort (bgp->peer, peer);
916
917 return peer;
918}
919
paul718e3742002-12-13 20:15:29 +0000920/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000921static void
paul718e3742002-12-13 20:15:29 +0000922peer_as_change (struct peer *peer, as_t as)
923{
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000924 bgp_peer_sort_t type;
Daniel Walton0d7435f2015-10-22 11:35:20 +0300925 struct peer *conf;
paul718e3742002-12-13 20:15:29 +0000926
927 /* Stop peer. */
928 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
929 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000930 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000931 {
932 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
933 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
934 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
935 }
paul718e3742002-12-13 20:15:29 +0000936 else
937 BGP_EVENT_ADD (peer, BGP_Stop);
938 }
939 type = peer_sort (peer);
940 peer->as = as;
941
paul848973c2003-08-13 00:32:49 +0000942 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
943 && ! bgp_confederation_peers_check (peer->bgp, as)
944 && peer->bgp->as != as)
945 peer->local_as = peer->bgp->confed_id;
946 else
947 peer->local_as = peer->bgp->as;
948
paul718e3742002-12-13 20:15:29 +0000949 /* Advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +0300950 conf = NULL;
951 if (peer->group)
952 conf = peer->group->conf;
953
954 if (conf && CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
955 peer->v_routeadv = conf->routeadv;
paul718e3742002-12-13 20:15:29 +0000956 else
Daniel Walton0d7435f2015-10-22 11:35:20 +0300957 if (peer_sort (peer) == BGP_PEER_IBGP)
958 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
959 else
960 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul718e3742002-12-13 20:15:29 +0000961
962 /* TTL reset */
963 if (peer_sort (peer) == BGP_PEER_IBGP)
964 peer->ttl = 255;
965 else if (type == BGP_PEER_IBGP)
966 peer->ttl = 1;
967
968 /* reflector-client reset */
969 if (peer_sort (peer) != BGP_PEER_IBGP)
970 {
971 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
972 PEER_FLAG_REFLECTOR_CLIENT);
973 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
974 PEER_FLAG_REFLECTOR_CLIENT);
975 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
976 PEER_FLAG_REFLECTOR_CLIENT);
977 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
978 PEER_FLAG_REFLECTOR_CLIENT);
979 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
980 PEER_FLAG_REFLECTOR_CLIENT);
Lou Berger9da04bc2016-01-12 13:41:55 -0500981 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MPLS_VPN],
982 PEER_FLAG_REFLECTOR_CLIENT);
paul718e3742002-12-13 20:15:29 +0000983 }
984
985 /* local-as reset */
986 if (peer_sort (peer) != BGP_PEER_EBGP)
987 {
988 peer->change_local_as = 0;
989 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +0000990 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +0000991 }
992}
993
994/* If peer does not exist, create new one. If peer already exists,
995 set AS number to the peer. */
996int
997peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
998 afi_t afi, safi_t safi)
999{
1000 struct peer *peer;
1001 as_t local_as;
1002
1003 peer = peer_lookup (bgp, su);
1004
1005 if (peer)
1006 {
1007 /* When this peer is a member of peer-group. */
1008 if (peer->group)
1009 {
1010 if (peer->group->conf->as)
1011 {
1012 /* Return peer group's AS number. */
1013 *as = peer->group->conf->as;
1014 return BGP_ERR_PEER_GROUP_MEMBER;
1015 }
1016 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
1017 {
1018 if (bgp->as != *as)
1019 {
1020 *as = peer->as;
1021 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1022 }
1023 }
1024 else
1025 {
1026 if (bgp->as == *as)
1027 {
1028 *as = peer->as;
1029 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1030 }
1031 }
1032 }
1033
1034 /* Existing peer's AS number change. */
1035 if (peer->as != *as)
1036 peer_as_change (peer, *as);
1037 }
1038 else
1039 {
1040
1041 /* If the peer is not part of our confederation, and its not an
1042 iBGP peer then spoof the source AS */
1043 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1044 && ! bgp_confederation_peers_check (bgp, *as)
1045 && bgp->as != *as)
1046 local_as = bgp->confed_id;
1047 else
1048 local_as = bgp->as;
1049
1050 /* If this is IPv4 unicast configuration and "no bgp default
1051 ipv4-unicast" is specified. */
1052
1053 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1054 && afi == AFI_IP && safi == SAFI_UNICAST)
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001055 peer_create (su, bgp, local_as, *as, 0, 0);
paul718e3742002-12-13 20:15:29 +00001056 else
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001057 peer_create (su, bgp, local_as, *as, afi, safi);
paul718e3742002-12-13 20:15:29 +00001058 }
1059
1060 return 0;
1061}
1062
1063/* Activate the peer or peer group for specified AFI and SAFI. */
1064int
1065peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1066{
1067 int active;
1068
1069 if (peer->afc[afi][safi])
1070 return 0;
1071
1072 /* Activate the address family configuration. */
1073 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1074 peer->afc[afi][safi] = 1;
1075 else
1076 {
1077 active = peer_active (peer);
1078
1079 peer->afc[afi][safi] = 1;
1080
1081 if (! active && peer_active (peer))
1082 bgp_timer_set (peer);
1083 else
1084 {
1085 if (peer->status == Established)
1086 {
1087 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1088 {
1089 peer->afc_adv[afi][safi] = 1;
1090 bgp_capability_send (peer, afi, safi,
1091 CAPABILITY_CODE_MP,
1092 CAPABILITY_ACTION_SET);
1093 if (peer->afc_recv[afi][safi])
1094 {
1095 peer->afc_nego[afi][safi] = 1;
1096 bgp_announce_route (peer, afi, safi);
1097 }
1098 }
1099 else
hassoe0701b72004-05-20 09:19:34 +00001100 {
1101 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1102 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1103 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1104 }
paul718e3742002-12-13 20:15:29 +00001105 }
1106 }
1107 }
1108 return 0;
1109}
1110
1111int
1112peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1113{
1114 struct peer_group *group;
1115 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001116 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001117
1118 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1119 {
1120 group = peer->group;
1121
paul1eb8ef22005-04-07 07:30:20 +00001122 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001123 {
1124 if (peer1->af_group[afi][safi])
1125 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1126 }
1127 }
1128 else
1129 {
1130 if (peer->af_group[afi][safi])
1131 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1132 }
1133
1134 if (! peer->afc[afi][safi])
1135 return 0;
1136
1137 /* De-activate the address family configuration. */
1138 peer->afc[afi][safi] = 0;
1139 peer_af_flag_reset (peer, afi, safi);
1140
1141 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1142 {
1143 if (peer->status == Established)
1144 {
1145 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1146 {
1147 peer->afc_adv[afi][safi] = 0;
1148 peer->afc_nego[afi][safi] = 0;
1149
1150 if (peer_active_nego (peer))
1151 {
1152 bgp_capability_send (peer, afi, safi,
1153 CAPABILITY_CODE_MP,
1154 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001155 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001156 peer->pcount[afi][safi] = 0;
1157 }
1158 else
hassoe0701b72004-05-20 09:19:34 +00001159 {
1160 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1161 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1162 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1163 }
paul718e3742002-12-13 20:15:29 +00001164 }
1165 else
hassoe0701b72004-05-20 09:19:34 +00001166 {
1167 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1168 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1169 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1170 }
paul718e3742002-12-13 20:15:29 +00001171 }
1172 }
1173 return 0;
1174}
1175
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001176static void
hasso93406d82005-02-02 14:40:33 +00001177peer_nsf_stop (struct peer *peer)
1178{
1179 afi_t afi;
1180 safi_t safi;
1181
1182 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1183 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1184
1185 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +04001186 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +00001187 peer->nsf[afi][safi] = 0;
1188
1189 if (peer->t_gr_restart)
1190 {
1191 BGP_TIMER_OFF (peer->t_gr_restart);
1192 if (BGP_DEBUG (events, EVENTS))
1193 zlog_debug ("%s graceful restart timer stopped", peer->host);
1194 }
1195 if (peer->t_gr_stale)
1196 {
1197 BGP_TIMER_OFF (peer->t_gr_stale);
1198 if (BGP_DEBUG (events, EVENTS))
1199 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1200 }
1201 bgp_clear_route_all (peer);
1202}
1203
Paul Jakmaca058a32006-09-14 02:58:49 +00001204/* Delete peer from confguration.
1205 *
1206 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1207 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1208 *
1209 * This function /should/ take care to be idempotent, to guard against
1210 * it being called multiple times through stray events that come in
1211 * that happen to result in this function being called again. That
1212 * said, getting here for a "Deleted" peer is a bug in the neighbour
1213 * FSM.
1214 */
paul718e3742002-12-13 20:15:29 +00001215int
1216peer_delete (struct peer *peer)
1217{
1218 int i;
1219 afi_t afi;
1220 safi_t safi;
1221 struct bgp *bgp;
1222 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001223 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001224
Paul Jakmaca058a32006-09-14 02:58:49 +00001225 assert (peer->status != Deleted);
1226
paul718e3742002-12-13 20:15:29 +00001227 bgp = peer->bgp;
1228
hasso93406d82005-02-02 14:40:33 +00001229 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1230 peer_nsf_stop (peer);
1231
Chris Caputo228da422009-07-18 05:44:03 +00001232 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001233 relationship. */
1234 if (peer->group)
1235 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001236 if ((pn = listnode_lookup (peer->group->peer, peer)))
1237 {
1238 peer = peer_unlock (peer); /* group->peer list reference */
1239 list_delete_node (peer->group->peer, pn);
1240 }
paul718e3742002-12-13 20:15:29 +00001241 peer->group = NULL;
1242 }
paul200df112005-06-01 11:17:05 +00001243
paul718e3742002-12-13 20:15:29 +00001244 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001245 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1246 * executed after peer structure is deleted.
1247 */
hassoe0701b72004-05-20 09:19:34 +00001248 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001249 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001250 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001251
1252 /* Password configuration */
1253 if (peer->password)
1254 {
1255 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1256 peer->password = NULL;
1257
1258 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1259 bgp_md5_set (peer);
1260 }
1261
Paul Jakmaca058a32006-09-14 02:58:49 +00001262 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001263
paul718e3742002-12-13 20:15:29 +00001264 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001265 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1266 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001267 {
Chris Caputo228da422009-07-18 05:44:03 +00001268 peer_unlock (peer); /* bgp peer list reference */
1269 list_delete_node (bgp->peer, pn);
1270 }
paul200df112005-06-01 11:17:05 +00001271
Chris Caputo228da422009-07-18 05:44:03 +00001272 if (peer_rsclient_active (peer)
1273 && (pn = listnode_lookup (bgp->rsclient, peer)))
1274 {
1275 peer_unlock (peer); /* rsclient list reference */
1276 list_delete_node (bgp->rsclient, pn);
1277
1278 /* Clear our own rsclient ribs. */
1279 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1280 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1281 if (CHECK_FLAG(peer->af_flags[afi][safi],
1282 PEER_FLAG_RSERVER_CLIENT))
1283 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001284 }
1285
1286 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1287 member of a peer_group. */
1288 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1289 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1290 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001291 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001292
paul200df112005-06-01 11:17:05 +00001293 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001294 if (peer->ibuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001295 {
1296 stream_free (peer->ibuf);
1297 peer->ibuf = NULL;
1298 }
1299
paul718e3742002-12-13 20:15:29 +00001300 if (peer->obuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001301 {
1302 stream_fifo_free (peer->obuf);
1303 peer->obuf = NULL;
1304 }
1305
paul718e3742002-12-13 20:15:29 +00001306 if (peer->work)
Daniel Walton363c9032015-10-21 06:42:54 -07001307 {
1308 stream_free (peer->work);
1309 peer->work = NULL;
1310 }
1311
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00001312 if (peer->scratch)
Daniel Walton363c9032015-10-21 06:42:54 -07001313 {
1314 stream_free(peer->scratch);
1315 peer->scratch = NULL;
1316 }
Paul Jakma18937402006-07-27 19:05:12 +00001317
paul718e3742002-12-13 20:15:29 +00001318 /* Local and remote addresses. */
1319 if (peer->su_local)
Daniel Walton363c9032015-10-21 06:42:54 -07001320 {
1321 sockunion_free (peer->su_local);
1322 peer->su_local = NULL;
1323 }
1324
paul718e3742002-12-13 20:15:29 +00001325 if (peer->su_remote)
Daniel Walton363c9032015-10-21 06:42:54 -07001326 {
1327 sockunion_free (peer->su_remote);
1328 peer->su_remote = NULL;
1329 }
paul200df112005-06-01 11:17:05 +00001330
paul718e3742002-12-13 20:15:29 +00001331 /* Free filter related memory. */
1332 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1333 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1334 {
1335 filter = &peer->filter[afi][safi];
1336
1337 for (i = FILTER_IN; i < FILTER_MAX; i++)
1338 {
1339 if (filter->dlist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001340 {
1341 free(filter->dlist[i].name);
1342 filter->dlist[i].name = NULL;
1343 }
1344
paul718e3742002-12-13 20:15:29 +00001345 if (filter->plist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001346 {
1347 free(filter->plist[i].name);
1348 filter->plist[i].name = NULL;
1349 }
1350
paul718e3742002-12-13 20:15:29 +00001351 if (filter->aslist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001352 {
1353 free(filter->aslist[i].name);
1354 filter->aslist[i].name = NULL;
1355 }
paul200df112005-06-01 11:17:05 +00001356 }
Daniel Walton363c9032015-10-21 06:42:54 -07001357
paul200df112005-06-01 11:17:05 +00001358 for (i = RMAP_IN; i < RMAP_MAX; i++)
1359 {
paul718e3742002-12-13 20:15:29 +00001360 if (filter->map[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001361 {
1362 free (filter->map[i].name);
1363 filter->map[i].name = NULL;
1364 }
paul718e3742002-12-13 20:15:29 +00001365 }
1366
1367 if (filter->usmap.name)
Daniel Walton363c9032015-10-21 06:42:54 -07001368 {
1369 free (filter->usmap.name);
1370 filter->usmap.name = NULL;
1371 }
paul718e3742002-12-13 20:15:29 +00001372
1373 if (peer->default_rmap[afi][safi].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001374 {
1375 free (peer->default_rmap[afi][safi].name);
1376 peer->default_rmap[afi][safi].name = NULL;
1377 }
paul718e3742002-12-13 20:15:29 +00001378 }
paul200df112005-06-01 11:17:05 +00001379
Lou Berger82dd7072016-01-12 13:41:57 -05001380 if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETING))
1381 bgp_peer_clear_node_queue_drain_immediate(peer);
1382
paul200df112005-06-01 11:17:05 +00001383 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001384
1385 return 0;
1386}
David Lamparter6b0655a2014-06-04 06:53:35 +02001387
paul94f2b392005-06-28 12:44:16 +00001388static int
paul718e3742002-12-13 20:15:29 +00001389peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1390{
1391 return strcmp (g1->name, g2->name);
1392}
1393
1394/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001395static int
paul718e3742002-12-13 20:15:29 +00001396peer_group_active (struct peer *peer)
1397{
1398 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1399 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1400 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1401 || peer->af_group[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05001402 || peer->af_group[AFI_IP6][SAFI_MULTICAST]
1403 || peer->af_group[AFI_IP6][SAFI_MPLS_VPN])
paul718e3742002-12-13 20:15:29 +00001404 return 1;
1405 return 0;
1406}
1407
1408/* Peer group cofiguration. */
1409static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001410peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001411{
1412 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1413 sizeof (struct peer_group));
1414}
1415
paul94f2b392005-06-28 12:44:16 +00001416static void
paul718e3742002-12-13 20:15:29 +00001417peer_group_free (struct peer_group *group)
1418{
1419 XFREE (MTYPE_PEER_GROUP, group);
1420}
1421
1422struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001423peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001424{
1425 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001426 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001427
paul1eb8ef22005-04-07 07:30:20 +00001428 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001429 {
1430 if (strcmp (group->name, name) == 0)
1431 return group;
1432 }
1433 return NULL;
1434}
1435
1436struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001437peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001438{
1439 struct peer_group *group;
1440
1441 group = peer_group_lookup (bgp, name);
1442 if (group)
1443 return group;
1444
1445 group = peer_group_new ();
1446 group->bgp = bgp;
1447 group->name = strdup (name);
1448 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001449 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001450 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1451 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001452 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001453 group->conf->group = group;
1454 group->conf->as = 0;
1455 group->conf->ttl = 1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001456 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001457 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1458 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1459 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1460 group->conf->keepalive = 0;
1461 group->conf->holdtime = 0;
1462 group->conf->connect = 0;
1463 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1464 listnode_add_sort (bgp->group, group);
1465
1466 return 0;
1467}
1468
paul94f2b392005-06-28 12:44:16 +00001469static void
paul718e3742002-12-13 20:15:29 +00001470peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1471 afi_t afi, safi_t safi)
1472{
1473 int in = FILTER_IN;
1474 int out = FILTER_OUT;
1475 struct peer *conf;
1476 struct bgp_filter *pfilter;
1477 struct bgp_filter *gfilter;
1478
1479 conf = group->conf;
1480 pfilter = &peer->filter[afi][safi];
1481 gfilter = &conf->filter[afi][safi];
1482
1483 /* remote-as */
1484 if (conf->as)
1485 peer->as = conf->as;
1486
1487 /* remote-as */
1488 if (conf->change_local_as)
1489 peer->change_local_as = conf->change_local_as;
1490
1491 /* TTL */
1492 peer->ttl = conf->ttl;
1493
Nick Hilliardfa411a22011-03-23 15:33:17 +00001494 /* GTSM hops */
1495 peer->gtsm_hops = conf->gtsm_hops;
1496
paul718e3742002-12-13 20:15:29 +00001497 /* Weight */
1498 peer->weight = conf->weight;
1499
1500 /* peer flags apply */
1501 peer->flags = conf->flags;
1502 /* peer af_flags apply */
1503 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1504 /* peer config apply */
1505 peer->config = conf->config;
1506
1507 /* peer timers apply */
1508 peer->holdtime = conf->holdtime;
1509 peer->keepalive = conf->keepalive;
1510 peer->connect = conf->connect;
1511 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1512 peer->v_connect = conf->connect;
1513 else
1514 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1515
1516 /* advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +03001517 if (CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
1518 peer->v_routeadv = conf->routeadv;
paul718e3742002-12-13 20:15:29 +00001519 else
Daniel Walton0d7435f2015-10-22 11:35:20 +03001520 if (peer_sort (peer) == BGP_PEER_IBGP)
1521 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1522 else
1523 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul718e3742002-12-13 20:15:29 +00001524
Paul Jakma0df7c912008-07-21 21:02:49 +00001525 /* password apply */
Roman Hoog Antink0e4303d2013-01-18 13:52:03 +01001526 if (conf->password && !peer->password)
Paul Jakma0df7c912008-07-21 21:02:49 +00001527 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
Paul Jakma0df7c912008-07-21 21:02:49 +00001528
1529 bgp_md5_set (peer);
1530
paul718e3742002-12-13 20:15:29 +00001531 /* maximum-prefix */
1532 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001533 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001534 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001535
1536 /* allowas-in */
1537 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1538
paulfee0f4c2004-09-13 05:12:46 +00001539 /* route-server-client */
1540 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1541 {
1542 /* Make peer's RIB point to group's RIB. */
1543 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1544
1545 /* Import policy. */
1546 if (pfilter->map[RMAP_IMPORT].name)
1547 free (pfilter->map[RMAP_IMPORT].name);
1548 if (gfilter->map[RMAP_IMPORT].name)
1549 {
1550 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1551 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1552 }
1553 else
1554 {
1555 pfilter->map[RMAP_IMPORT].name = NULL;
1556 pfilter->map[RMAP_IMPORT].map = NULL;
1557 }
1558
1559 /* Export policy. */
1560 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1561 {
1562 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1563 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1564 }
1565 }
1566
paul718e3742002-12-13 20:15:29 +00001567 /* default-originate route-map */
1568 if (conf->default_rmap[afi][safi].name)
1569 {
1570 if (peer->default_rmap[afi][safi].name)
1571 free (peer->default_rmap[afi][safi].name);
1572 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1573 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1574 }
1575
1576 /* update-source apply */
1577 if (conf->update_source)
1578 {
1579 if (peer->update_source)
1580 sockunion_free (peer->update_source);
1581 if (peer->update_if)
1582 {
1583 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1584 peer->update_if = NULL;
1585 }
1586 peer->update_source = sockunion_dup (conf->update_source);
1587 }
1588 else if (conf->update_if)
1589 {
1590 if (peer->update_if)
1591 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1592 if (peer->update_source)
1593 {
1594 sockunion_free (peer->update_source);
1595 peer->update_source = NULL;
1596 }
1597 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1598 }
1599
1600 /* inbound filter apply */
1601 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1602 {
1603 if (pfilter->dlist[in].name)
1604 free (pfilter->dlist[in].name);
1605 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1606 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1607 }
1608 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1609 {
1610 if (pfilter->plist[in].name)
1611 free (pfilter->plist[in].name);
1612 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1613 pfilter->plist[in].plist = gfilter->plist[in].plist;
1614 }
1615 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1616 {
1617 if (pfilter->aslist[in].name)
1618 free (pfilter->aslist[in].name);
1619 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1620 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1621 }
paulfee0f4c2004-09-13 05:12:46 +00001622 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001623 {
paulfee0f4c2004-09-13 05:12:46 +00001624 if (pfilter->map[RMAP_IN].name)
1625 free (pfilter->map[RMAP_IN].name);
1626 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1627 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001628 }
1629
1630 /* outbound filter apply */
1631 if (gfilter->dlist[out].name)
1632 {
1633 if (pfilter->dlist[out].name)
1634 free (pfilter->dlist[out].name);
1635 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1636 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1637 }
1638 else
1639 {
1640 if (pfilter->dlist[out].name)
1641 free (pfilter->dlist[out].name);
1642 pfilter->dlist[out].name = NULL;
1643 pfilter->dlist[out].alist = NULL;
1644 }
1645 if (gfilter->plist[out].name)
1646 {
1647 if (pfilter->plist[out].name)
1648 free (pfilter->plist[out].name);
1649 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1650 pfilter->plist[out].plist = gfilter->plist[out].plist;
1651 }
1652 else
1653 {
1654 if (pfilter->plist[out].name)
1655 free (pfilter->plist[out].name);
1656 pfilter->plist[out].name = NULL;
1657 pfilter->plist[out].plist = NULL;
1658 }
1659 if (gfilter->aslist[out].name)
1660 {
1661 if (pfilter->aslist[out].name)
1662 free (pfilter->aslist[out].name);
1663 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1664 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1665 }
1666 else
1667 {
1668 if (pfilter->aslist[out].name)
1669 free (pfilter->aslist[out].name);
1670 pfilter->aslist[out].name = NULL;
1671 pfilter->aslist[out].aslist = NULL;
1672 }
paulfee0f4c2004-09-13 05:12:46 +00001673 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001674 {
paulfee0f4c2004-09-13 05:12:46 +00001675 if (pfilter->map[RMAP_OUT].name)
1676 free (pfilter->map[RMAP_OUT].name);
1677 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1678 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001679 }
1680 else
1681 {
paulfee0f4c2004-09-13 05:12:46 +00001682 if (pfilter->map[RMAP_OUT].name)
1683 free (pfilter->map[RMAP_OUT].name);
1684 pfilter->map[RMAP_OUT].name = NULL;
1685 pfilter->map[RMAP_OUT].map = NULL;
1686 }
1687
1688 /* RS-client's import/export route-maps. */
1689 if (gfilter->map[RMAP_IMPORT].name)
1690 {
1691 if (pfilter->map[RMAP_IMPORT].name)
1692 free (pfilter->map[RMAP_IMPORT].name);
1693 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1694 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1695 }
1696 else
1697 {
1698 if (pfilter->map[RMAP_IMPORT].name)
1699 free (pfilter->map[RMAP_IMPORT].name);
1700 pfilter->map[RMAP_IMPORT].name = NULL;
1701 pfilter->map[RMAP_IMPORT].map = NULL;
1702 }
1703 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1704 {
1705 if (pfilter->map[RMAP_EXPORT].name)
1706 free (pfilter->map[RMAP_EXPORT].name);
1707 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1708 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001709 }
1710
1711 if (gfilter->usmap.name)
1712 {
1713 if (pfilter->usmap.name)
1714 free (pfilter->usmap.name);
1715 pfilter->usmap.name = strdup (gfilter->usmap.name);
1716 pfilter->usmap.map = gfilter->usmap.map;
1717 }
1718 else
1719 {
1720 if (pfilter->usmap.name)
1721 free (pfilter->usmap.name);
1722 pfilter->usmap.name = NULL;
1723 pfilter->usmap.map = NULL;
1724 }
1725}
1726
1727/* Peer group's remote AS configuration. */
1728int
paulfd79ac92004-10-13 05:06:08 +00001729peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001730{
1731 struct peer_group *group;
1732 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001733 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001734
1735 group = peer_group_lookup (bgp, group_name);
1736 if (! group)
1737 return -1;
1738
1739 if (group->conf->as == *as)
1740 return 0;
1741
1742 /* When we setup peer-group AS number all peer group member's AS
1743 number must be updated to same number. */
1744 peer_as_change (group->conf, *as);
1745
paul1eb8ef22005-04-07 07:30:20 +00001746 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001747 {
1748 if (peer->as != *as)
1749 peer_as_change (peer, *as);
1750 }
1751
1752 return 0;
1753}
1754
1755int
1756peer_group_delete (struct peer_group *group)
1757{
1758 struct bgp *bgp;
1759 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001760 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001761
1762 bgp = group->bgp;
1763
paul1eb8ef22005-04-07 07:30:20 +00001764 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001765 {
paul718e3742002-12-13 20:15:29 +00001766 peer_delete (peer);
1767 }
1768 list_delete (group->peer);
1769
1770 free (group->name);
1771 group->name = NULL;
1772
1773 group->conf->group = NULL;
1774 peer_delete (group->conf);
1775
1776 /* Delete from all peer_group list. */
1777 listnode_delete (bgp->group, group);
1778
1779 peer_group_free (group);
1780
1781 return 0;
1782}
1783
1784int
1785peer_group_remote_as_delete (struct peer_group *group)
1786{
1787 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001788 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001789
1790 if (! group->conf->as)
1791 return 0;
1792
paul1eb8ef22005-04-07 07:30:20 +00001793 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001794 {
paul718e3742002-12-13 20:15:29 +00001795 peer_delete (peer);
1796 }
1797 list_delete_all_node (group->peer);
1798
1799 group->conf->as = 0;
1800
1801 return 0;
1802}
1803
1804/* Bind specified peer to peer group. */
1805int
1806peer_group_bind (struct bgp *bgp, union sockunion *su,
1807 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1808{
1809 struct peer *peer;
1810 int first_member = 0;
1811
1812 /* Check peer group's address family. */
1813 if (! group->conf->afc[afi][safi])
1814 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1815
1816 /* Lookup the peer. */
1817 peer = peer_lookup (bgp, su);
1818
1819 /* Create a new peer. */
1820 if (! peer)
1821 {
1822 if (! group->conf->as)
1823 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1824
1825 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1826 peer->group = group;
1827 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001828
Paul Jakmaca058a32006-09-14 02:58:49 +00001829 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001830 listnode_add (group->peer, peer);
1831 peer_group2peer_config_copy (group, peer, afi, safi);
1832
1833 return 0;
1834 }
1835
1836 /* When the peer already belongs to peer group, check the consistency. */
1837 if (peer->af_group[afi][safi])
1838 {
1839 if (strcmp (peer->group->name, group->name) != 0)
1840 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1841
1842 return 0;
1843 }
1844
1845 /* Check current peer group configuration. */
1846 if (peer_group_active (peer)
1847 && strcmp (peer->group->name, group->name) != 0)
1848 return BGP_ERR_PEER_GROUP_MISMATCH;
1849
1850 if (! group->conf->as)
1851 {
1852 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1853 && peer_sort (group->conf) != peer_sort (peer))
1854 {
1855 if (as)
1856 *as = peer->as;
1857 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1858 }
1859
1860 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1861 first_member = 1;
1862 }
1863
1864 peer->af_group[afi][safi] = 1;
1865 peer->afc[afi][safi] = 1;
1866 if (! peer->group)
1867 {
1868 peer->group = group;
paul200df112005-06-01 11:17:05 +00001869
Paul Jakmaca058a32006-09-14 02:58:49 +00001870 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001871 listnode_add (group->peer, peer);
1872 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001873 else
1874 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001875
1876 if (first_member)
1877 {
1878 /* Advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +03001879 if (! CHECK_FLAG (group->conf->config, PEER_CONFIG_ROUTEADV))
1880 {
1881 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1882 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1883 else
1884 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1885 }
paul718e3742002-12-13 20:15:29 +00001886
1887 /* ebgp-multihop reset */
1888 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1889 group->conf->ttl = 255;
1890
1891 /* local-as reset */
1892 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1893 {
1894 group->conf->change_local_as = 0;
1895 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001896 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001897 }
1898 }
paulfee0f4c2004-09-13 05:12:46 +00001899
1900 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1901 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001902 struct listnode *pn;
1903
paulfee0f4c2004-09-13 05:12:46 +00001904 /* If it's not configured as RSERVER_CLIENT in any other address
1905 family, without being member of a peer_group, remove it from
1906 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001907 if (! peer_rsclient_active (peer)
1908 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001909 {
1910 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001911 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001912
1913 /* Clear our own rsclient rib for this afi/safi. */
1914 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001915 }
paulfee0f4c2004-09-13 05:12:46 +00001916
Paul Jakmab608d5b2008-07-02 02:12:07 +00001917 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001918
1919 /* Import policy. */
1920 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1921 {
1922 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1923 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1924 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1925 }
1926
1927 /* Export policy. */
1928 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1929 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1930 {
1931 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1932 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1933 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1934 }
1935 }
1936
paul718e3742002-12-13 20:15:29 +00001937 peer_group2peer_config_copy (group, peer, afi, safi);
1938
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001939 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001940 {
1941 peer->last_reset = PEER_DOWN_RMAP_BIND;
1942 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1943 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1944 }
paul718e3742002-12-13 20:15:29 +00001945 else
1946 BGP_EVENT_ADD (peer, BGP_Stop);
1947
1948 return 0;
1949}
1950
1951int
1952peer_group_unbind (struct bgp *bgp, struct peer *peer,
1953 struct peer_group *group, afi_t afi, safi_t safi)
1954{
1955 if (! peer->af_group[afi][safi])
1956 return 0;
1957
1958 if (group != peer->group)
1959 return BGP_ERR_PEER_GROUP_MISMATCH;
1960
1961 peer->af_group[afi][safi] = 0;
1962 peer->afc[afi][safi] = 0;
1963 peer_af_flag_reset (peer, afi, safi);
1964
paulfee0f4c2004-09-13 05:12:46 +00001965 if (peer->rib[afi][safi])
1966 peer->rib[afi][safi] = NULL;
1967
paul718e3742002-12-13 20:15:29 +00001968 if (! peer_group_active (peer))
1969 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001970 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001971 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001972 listnode_delete (group->peer, peer);
1973 peer->group = NULL;
1974 if (group->conf->as)
1975 {
1976 peer_delete (peer);
1977 return 0;
1978 }
1979 peer_global_config_reset (peer);
1980 }
1981
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001982 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001983 {
1984 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1985 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1986 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1987 }
paul718e3742002-12-13 20:15:29 +00001988 else
1989 BGP_EVENT_ADD (peer, BGP_Stop);
1990
1991 return 0;
1992}
David Lamparter6b0655a2014-06-04 06:53:35 +02001993
Vipin Kumardd49eb12014-09-30 14:36:38 -07001994
1995static int
1996bgp_startup_timer_expire (struct thread *thread)
1997{
1998 struct bgp *bgp;
1999
2000 bgp = THREAD_ARG (thread);
2001 bgp->t_startup = NULL;
2002
2003 return 0;
2004}
2005
paul718e3742002-12-13 20:15:29 +00002006/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00002007static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002008bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002009{
2010 struct bgp *bgp;
2011 afi_t afi;
2012 safi_t safi;
2013
paul200df112005-06-01 11:17:05 +00002014 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
2015 return NULL;
2016
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002017 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00002018 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00002019 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00002020
2021 bgp->peer = list_new ();
2022 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
2023
2024 bgp->group = list_new ();
2025 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
2026
paulfee0f4c2004-09-13 05:12:46 +00002027 bgp->rsclient = list_new ();
2028 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
2029
paul718e3742002-12-13 20:15:29 +00002030 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2031 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2032 {
Paul Jakma64e580a2006-02-21 01:09:01 +00002033 bgp->route[afi][safi] = bgp_table_init (afi, safi);
2034 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
2035 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07002036 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
2037 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00002038 }
2039
2040 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
2041 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
2042 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00002043 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
2044 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07002045 bgp_flag_set (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES);
paul718e3742002-12-13 20:15:29 +00002046
2047 bgp->as = *as;
2048
2049 if (name)
2050 bgp->name = strdup (name);
2051
Donald Sharp774914f2015-10-14 08:50:39 -04002052 THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire,
Vipin Kumardd49eb12014-09-30 14:36:38 -07002053 bgp, bgp->restart_time);
2054
paul718e3742002-12-13 20:15:29 +00002055 return bgp;
2056}
2057
2058/* Return first entry of BGP. */
2059struct bgp *
paul94f2b392005-06-28 12:44:16 +00002060bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00002061{
Lou Berger056f3762013-04-10 12:30:04 -07002062 if (bm && bm->bgp && bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00002063 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00002064 return NULL;
2065}
2066
2067/* Lookup BGP entry. */
2068struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002069bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00002070{
2071 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002072 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002073
paul1eb8ef22005-04-07 07:30:20 +00002074 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002075 if (bgp->as == as
2076 && ((bgp->name == NULL && name == NULL)
2077 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
2078 return bgp;
2079 return NULL;
2080}
2081
2082/* Lookup BGP structure by view name. */
2083struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002084bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002085{
2086 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002087 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002088
paul1eb8ef22005-04-07 07:30:20 +00002089 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002090 if ((bgp->name == NULL && name == NULL)
2091 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2092 return bgp;
2093 return NULL;
2094}
2095
2096/* Called from VTY commands. */
2097int
paulfd79ac92004-10-13 05:06:08 +00002098bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002099{
2100 struct bgp *bgp;
2101
2102 /* Multiple instance check. */
2103 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2104 {
2105 if (name)
2106 bgp = bgp_lookup_by_name (name);
2107 else
2108 bgp = bgp_get_default ();
2109
2110 /* Already exists. */
2111 if (bgp)
2112 {
2113 if (bgp->as != *as)
2114 {
2115 *as = bgp->as;
2116 return BGP_ERR_INSTANCE_MISMATCH;
2117 }
2118 *bgp_val = bgp;
2119 return 0;
2120 }
2121 }
2122 else
2123 {
2124 /* BGP instance name can not be specified for single instance. */
2125 if (name)
2126 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2127
2128 /* Get default BGP structure if exists. */
2129 bgp = bgp_get_default ();
2130
2131 if (bgp)
2132 {
2133 if (bgp->as != *as)
2134 {
2135 *as = bgp->as;
2136 return BGP_ERR_AS_MISMATCH;
2137 }
2138 *bgp_val = bgp;
2139 return 0;
2140 }
2141 }
2142
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002143 bgp = bgp_create (as, name);
2144 bgp_router_id_set(bgp, &router_id_zebra);
2145 *bgp_val = bgp;
2146
Paul Jakmaad12dde2012-06-13 22:50:07 +01002147 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002148 if (list_isempty(bm->bgp)
2149 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002150 {
2151 if (bgp_socket (bm->port, bm->address) < 0)
2152 return BGP_ERR_INVALID_VALUE;
2153 }
2154
paul718e3742002-12-13 20:15:29 +00002155 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002156
2157 return 0;
2158}
2159
2160/* Delete BGP instance. */
2161int
2162bgp_delete (struct bgp *bgp)
2163{
2164 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002165 struct peer_group *group;
Denil Vira57cd5e72015-08-10 12:46:14 -07002166 struct listnode *node, *pnode;
2167 struct listnode *next, *pnext;
paul718e3742002-12-13 20:15:29 +00002168 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002169 int i;
2170
Lou Berger82dd7072016-01-12 13:41:57 -05002171 SET_FLAG(bgp->flags, BGP_FLAG_DELETING);
2172
David Lampartercffe7802014-12-07 03:27:13 +01002173 THREAD_OFF (bgp->t_startup);
2174
paul718e3742002-12-13 20:15:29 +00002175 /* Delete static route. */
2176 bgp_static_delete (bgp);
2177
2178 /* Unset redistribution. */
2179 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2180 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2181 if (i != ZEBRA_ROUTE_BGP)
2182 bgp_redistribute_unset (bgp, afi, i);
2183
paul1eb8ef22005-04-07 07:30:20 +00002184 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002185 {
2186 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2187 {
2188 /* Send notify to remote peer. */
2189 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2190 }
2191
2192 peer_delete (peer);
2193 }
paul718e3742002-12-13 20:15:29 +00002194
Chris Caputo228da422009-07-18 05:44:03 +00002195 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002196 {
Denil Vira57cd5e72015-08-10 12:46:14 -07002197 for (ALL_LIST_ELEMENTS (group->peer, pnode, pnext, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002198 {
2199 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2200 {
2201 /* Send notify to remote peer. */
2202 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2203 }
2204 }
2205 peer_group_delete (group);
2206 }
Chris Caputo228da422009-07-18 05:44:03 +00002207
2208 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002209
2210 if (bgp->peer_self) {
2211 peer_delete(bgp->peer_self);
2212 bgp->peer_self = NULL;
2213 }
Lou Berger82dd7072016-01-12 13:41:57 -05002214
2215 /*
2216 * Free pending deleted routes. Unfortunately, it also has to process
2217 * all the pending activity for other instances of struct bgp.
2218 *
2219 * This call was added to achieve clean memory allocation at exit,
2220 * for the sake of valgrind.
2221 */
2222 bgp_process_queues_drain_immediate();
2223
2224 bgp_zebra_destroy();
2225 bgp_scan_destroy();
2226 bgp_address_destroy();
Paul Jakmafd35b942009-07-16 19:27:32 +01002227
Lou Berger82dd7072016-01-12 13:41:57 -05002228
Paul Jakmafd35b942009-07-16 19:27:32 +01002229 /* Remove visibility via the master list - there may however still be
2230 * routes to be processed still referencing the struct bgp.
2231 */
2232 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002233 if (list_isempty(bm->bgp))
2234 bgp_close ();
2235
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002236 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002237
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002238 return 0;
2239}
2240
2241static void bgp_free (struct bgp *);
2242
2243void
2244bgp_lock (struct bgp *bgp)
2245{
2246 ++bgp->lock;
2247}
2248
2249void
2250bgp_unlock(struct bgp *bgp)
2251{
Chris Caputo228da422009-07-18 05:44:03 +00002252 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002253 if (--bgp->lock == 0)
2254 bgp_free (bgp);
2255}
2256
2257static void
2258bgp_free (struct bgp *bgp)
2259{
2260 afi_t afi;
2261 safi_t safi;
2262
2263 list_delete (bgp->group);
2264 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002265 list_delete (bgp->rsclient);
2266
paul718e3742002-12-13 20:15:29 +00002267 if (bgp->name)
2268 free (bgp->name);
2269
2270 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2271 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2272 {
2273 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002274 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002275 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002276 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002277 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002278 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002279 }
2280 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002281}
David Lamparter6b0655a2014-06-04 06:53:35 +02002282
paul718e3742002-12-13 20:15:29 +00002283struct peer *
2284peer_lookup (struct bgp *bgp, union sockunion *su)
2285{
2286 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002287 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002288
Steve Hillfc4dc592009-07-28 17:54:35 +01002289 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002290 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002291 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2292 if (sockunion_same (&peer->su, su)
2293 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2294 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002295 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002296 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002297 {
2298 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002299
Paul Jakma2158ad22009-07-28 18:10:55 +01002300 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2301 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2302 if (sockunion_same (&peer->su, su)
2303 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2304 return peer;
paul718e3742002-12-13 20:15:29 +00002305 }
2306 return NULL;
2307}
2308
2309struct peer *
2310peer_lookup_with_open (union sockunion *su, as_t remote_as,
2311 struct in_addr *remote_id, int *as)
2312{
2313 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002314 struct listnode *node;
2315 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002316 struct bgp *bgp;
2317
Steve Hillfc4dc592009-07-28 17:54:35 +01002318 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002319 return NULL;
2320
Paul Jakma9d878772009-08-05 16:25:16 +01002321 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002322 {
Paul Jakma9d878772009-08-05 16:25:16 +01002323 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2324 {
2325 if (sockunion_same (&peer->su, su)
2326 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2327 {
2328 if (peer->as == remote_as
2329 && peer->remote_id.s_addr == remote_id->s_addr)
2330 return peer;
2331 if (peer->as == remote_as)
2332 *as = 1;
2333 }
2334 }
2335
2336 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2337 {
2338 if (sockunion_same (&peer->su, su)
2339 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2340 {
2341 if (peer->as == remote_as
2342 && peer->remote_id.s_addr == 0)
2343 return peer;
2344 if (peer->as == remote_as)
2345 *as = 1;
2346 }
2347 }
paul718e3742002-12-13 20:15:29 +00002348 }
2349 return NULL;
2350}
David Lamparter6b0655a2014-06-04 06:53:35 +02002351
paul718e3742002-12-13 20:15:29 +00002352/* If peer is configured at least one address family return 1. */
2353int
2354peer_active (struct peer *peer)
2355{
2356 if (peer->afc[AFI_IP][SAFI_UNICAST]
2357 || peer->afc[AFI_IP][SAFI_MULTICAST]
2358 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2359 || peer->afc[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05002360 || peer->afc[AFI_IP6][SAFI_MULTICAST]
2361 || peer->afc[AFI_IP6][SAFI_MPLS_VPN])
paul718e3742002-12-13 20:15:29 +00002362 return 1;
2363 return 0;
2364}
2365
2366/* If peer is negotiated at least one address family return 1. */
2367int
2368peer_active_nego (struct peer *peer)
2369{
2370 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2371 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2372 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2373 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05002374 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
2375 || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN])
paul718e3742002-12-13 20:15:29 +00002376 return 1;
2377 return 0;
2378}
David Lamparter6b0655a2014-06-04 06:53:35 +02002379
paul718e3742002-12-13 20:15:29 +00002380/* peer_flag_change_type. */
2381enum peer_change_type
2382{
2383 peer_change_none,
2384 peer_change_reset,
2385 peer_change_reset_in,
2386 peer_change_reset_out,
2387};
2388
paul94f2b392005-06-28 12:44:16 +00002389static void
paul718e3742002-12-13 20:15:29 +00002390peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2391 enum peer_change_type type)
2392{
2393 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2394 return;
2395
Stephen Hemmingerd9d4ae52010-01-13 00:32:39 +00002396 if (peer->status != Established)
2397 return;
2398
paul718e3742002-12-13 20:15:29 +00002399 if (type == peer_change_reset)
2400 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2401 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2402 else if (type == peer_change_reset_in)
2403 {
2404 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2405 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2406 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2407 else
2408 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2409 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2410 }
2411 else if (type == peer_change_reset_out)
2412 bgp_announce_route (peer, afi, safi);
2413}
2414
2415struct peer_flag_action
2416{
2417 /* Peer's flag. */
2418 u_int32_t flag;
2419
2420 /* This flag can be set for peer-group member. */
2421 u_char not_for_member;
2422
2423 /* Action when the flag is changed. */
2424 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002425
2426 /* Peer down cause */
2427 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002428};
2429
Stephen Hemminger03621952009-07-21 16:27:20 -07002430static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002431 {
2432 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2433 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2434 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2435 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2436 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002437 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002438 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002439 { 0, 0, 0 }
2440 };
2441
Stephen Hemminger03621952009-07-21 16:27:20 -07002442static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002443 {
2444 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2445 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2446 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2447 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2448 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2449 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2450 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2451 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2452 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2453 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2454 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2455 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2456 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002457 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
Timo Teräs9e7a53c2014-04-24 10:22:37 +03002458 { PEER_FLAG_NEXTHOP_SELF_ALL, 1, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002459 { 0, 0, 0 }
2460 };
2461
2462/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002463static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002464peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002465 struct peer_flag_action *action, u_int32_t flag)
2466{
2467 int i;
2468 int found = 0;
2469 int reset_in = 0;
2470 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002471 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002472
2473 /* Check peer's frag action. */
2474 for (i = 0; i < size; i++)
2475 {
2476 match = &action_list[i];
2477
2478 if (match->flag == 0)
2479 break;
2480
2481 if (match->flag & flag)
2482 {
2483 found = 1;
2484
2485 if (match->type == peer_change_reset_in)
2486 reset_in = 1;
2487 if (match->type == peer_change_reset_out)
2488 reset_out = 1;
2489 if (match->type == peer_change_reset)
2490 {
2491 reset_in = 1;
2492 reset_out = 1;
2493 }
2494 if (match->not_for_member)
2495 action->not_for_member = 1;
2496 }
2497 }
2498
2499 /* Set peer clear type. */
2500 if (reset_in && reset_out)
2501 action->type = peer_change_reset;
2502 else if (reset_in)
2503 action->type = peer_change_reset_in;
2504 else if (reset_out)
2505 action->type = peer_change_reset_out;
2506 else
2507 action->type = peer_change_none;
2508
2509 return found;
2510}
2511
paul94f2b392005-06-28 12:44:16 +00002512static void
paul718e3742002-12-13 20:15:29 +00002513peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2514{
2515 if (flag == PEER_FLAG_SHUTDOWN)
2516 {
2517 if (CHECK_FLAG (peer->flags, flag))
2518 {
hasso93406d82005-02-02 14:40:33 +00002519 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2520 peer_nsf_stop (peer);
2521
hasso0a486e52005-02-01 20:57:17 +00002522 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2523 if (peer->t_pmax_restart)
2524 {
2525 BGP_TIMER_OFF (peer->t_pmax_restart);
2526 if (BGP_DEBUG (events, EVENTS))
2527 zlog_debug ("%s Maximum-prefix restart timer canceled",
2528 peer->host);
2529 }
2530
hasso93406d82005-02-02 14:40:33 +00002531 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2532 peer_nsf_stop (peer);
2533
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002534 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002535 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2536 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2537 else
2538 BGP_EVENT_ADD (peer, BGP_Stop);
2539 }
2540 else
2541 {
2542 peer->v_start = BGP_INIT_START_TIMER;
2543 BGP_EVENT_ADD (peer, BGP_Stop);
2544 }
2545 }
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002546 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002547 {
hassoc9502432005-02-01 22:01:48 +00002548 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2549 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2550 else if (flag == PEER_FLAG_PASSIVE)
2551 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002552 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002553 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002554
hassoc9502432005-02-01 22:01:48 +00002555 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2556 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002557 }
2558 else
2559 BGP_EVENT_ADD (peer, BGP_Stop);
2560}
2561
2562/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002563static int
paul718e3742002-12-13 20:15:29 +00002564peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2565{
2566 int found;
2567 int size;
2568 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002569 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002570 struct peer_flag_action action;
2571
2572 memset (&action, 0, sizeof (struct peer_flag_action));
2573 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2574
2575 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2576
2577 /* No flag action is found. */
2578 if (! found)
2579 return BGP_ERR_INVALID_FLAG;
2580
2581 /* Not for peer-group member. */
2582 if (action.not_for_member && peer_group_active (peer))
2583 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2584
2585 /* When unset the peer-group member's flag we have to check
2586 peer-group configuration. */
2587 if (! set && peer_group_active (peer))
2588 if (CHECK_FLAG (peer->group->conf->flags, flag))
2589 {
2590 if (flag == PEER_FLAG_SHUTDOWN)
2591 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2592 else
2593 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2594 }
2595
2596 /* Flag conflict check. */
2597 if (set
2598 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2599 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2600 return BGP_ERR_PEER_FLAG_CONFLICT;
2601
2602 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2603 {
2604 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2605 return 0;
2606 if (! set && ! CHECK_FLAG (peer->flags, flag))
2607 return 0;
2608 }
2609
2610 if (set)
2611 SET_FLAG (peer->flags, flag);
2612 else
2613 UNSET_FLAG (peer->flags, flag);
2614
2615 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2616 {
2617 if (action.type == peer_change_reset)
2618 peer_flag_modify_action (peer, flag);
2619
2620 return 0;
2621 }
2622
2623 /* peer-group member updates. */
2624 group = peer->group;
2625
paul1eb8ef22005-04-07 07:30:20 +00002626 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002627 {
2628 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2629 continue;
2630
2631 if (! set && ! CHECK_FLAG (peer->flags, flag))
2632 continue;
2633
2634 if (set)
2635 SET_FLAG (peer->flags, flag);
2636 else
2637 UNSET_FLAG (peer->flags, flag);
2638
2639 if (action.type == peer_change_reset)
2640 peer_flag_modify_action (peer, flag);
2641 }
2642 return 0;
2643}
2644
2645int
2646peer_flag_set (struct peer *peer, u_int32_t flag)
2647{
2648 return peer_flag_modify (peer, flag, 1);
2649}
2650
2651int
2652peer_flag_unset (struct peer *peer, u_int32_t flag)
2653{
2654 return peer_flag_modify (peer, flag, 0);
2655}
2656
paul94f2b392005-06-28 12:44:16 +00002657static int
paul718e3742002-12-13 20:15:29 +00002658peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2659{
2660 if (peer->af_group[afi][safi])
2661 return 1;
2662 return 0;
2663}
2664
paul94f2b392005-06-28 12:44:16 +00002665static int
paul718e3742002-12-13 20:15:29 +00002666peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2667 int set)
2668{
2669 int found;
2670 int size;
paul1eb8ef22005-04-07 07:30:20 +00002671 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002672 struct peer_group *group;
2673 struct peer_flag_action action;
2674
2675 memset (&action, 0, sizeof (struct peer_flag_action));
2676 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2677
2678 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2679
2680 /* No flag action is found. */
2681 if (! found)
2682 return BGP_ERR_INVALID_FLAG;
2683
2684 /* Adress family must be activated. */
2685 if (! peer->afc[afi][safi])
2686 return BGP_ERR_PEER_INACTIVE;
2687
2688 /* Not for peer-group member. */
2689 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2690 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2691
2692 /* Spcecial check for reflector client. */
2693 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2694 && peer_sort (peer) != BGP_PEER_IBGP)
2695 return BGP_ERR_NOT_INTERNAL_PEER;
2696
2697 /* Spcecial check for remove-private-AS. */
2698 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2699 && peer_sort (peer) == BGP_PEER_IBGP)
2700 return BGP_ERR_REMOVE_PRIVATE_AS;
2701
2702 /* When unset the peer-group member's flag we have to check
2703 peer-group configuration. */
2704 if (! set && peer->af_group[afi][safi])
2705 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2706 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2707
2708 /* When current flag configuration is same as requested one. */
2709 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2710 {
2711 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2712 return 0;
2713 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2714 return 0;
2715 }
2716
2717 if (set)
2718 SET_FLAG (peer->af_flags[afi][safi], flag);
2719 else
2720 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2721
2722 /* Execute action when peer is established. */
2723 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2724 && peer->status == Established)
2725 {
2726 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2727 bgp_clear_adj_in (peer, afi, safi);
2728 else
hassoe0701b72004-05-20 09:19:34 +00002729 {
2730 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2731 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2732 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2733 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2734 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2735 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2736 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2737 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2738
2739 peer_change_action (peer, afi, safi, action.type);
2740 }
2741
paul718e3742002-12-13 20:15:29 +00002742 }
2743
2744 /* Peer group member updates. */
2745 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2746 {
2747 group = peer->group;
2748
paul1eb8ef22005-04-07 07:30:20 +00002749 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002750 {
2751 if (! peer->af_group[afi][safi])
2752 continue;
2753
2754 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2755 continue;
2756
2757 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2758 continue;
2759
2760 if (set)
2761 SET_FLAG (peer->af_flags[afi][safi], flag);
2762 else
2763 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2764
2765 if (peer->status == Established)
2766 {
2767 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2768 bgp_clear_adj_in (peer, afi, safi);
2769 else
hassoe0701b72004-05-20 09:19:34 +00002770 {
2771 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2772 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2773 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2774 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2775 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2776 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2777 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2778 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2779
2780 peer_change_action (peer, afi, safi, action.type);
2781 }
paul718e3742002-12-13 20:15:29 +00002782 }
2783 }
2784 }
2785 return 0;
2786}
2787
2788int
2789peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2790{
2791 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2792}
2793
2794int
2795peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2796{
2797 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2798}
David Lamparter6b0655a2014-06-04 06:53:35 +02002799
paul718e3742002-12-13 20:15:29 +00002800/* EBGP multihop configuration. */
2801int
2802peer_ebgp_multihop_set (struct peer *peer, int ttl)
2803{
2804 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002805 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002806 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002807
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002808 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002809 return 0;
2810
Nick Hilliardfa411a22011-03-23 15:33:17 +00002811 /* see comment in peer_ttl_security_hops_set() */
2812 if (ttl != MAXTTL)
2813 {
2814 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2815 {
2816 group = peer->group;
2817 if (group->conf->gtsm_hops != 0)
2818 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2819
2820 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2821 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002822 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002823 continue;
2824
2825 if (peer1->gtsm_hops != 0)
2826 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2827 }
2828 }
2829 else
2830 {
2831 if (peer->gtsm_hops != 0)
2832 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2833 }
2834 }
2835
paul718e3742002-12-13 20:15:29 +00002836 peer->ttl = ttl;
2837
2838 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2839 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002840 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002841 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002842 }
2843 else
2844 {
2845 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002846 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002847 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002848 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002849 continue;
paul718e3742002-12-13 20:15:29 +00002850
pauleb821182004-05-01 08:44:08 +00002851 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002852
pauleb821182004-05-01 08:44:08 +00002853 if (peer->fd >= 0)
2854 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2855 }
paul718e3742002-12-13 20:15:29 +00002856 }
2857 return 0;
2858}
2859
2860int
2861peer_ebgp_multihop_unset (struct peer *peer)
2862{
2863 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002864 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002865
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002866 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002867 return 0;
2868
Nick Hilliardfa411a22011-03-23 15:33:17 +00002869 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2870 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2871
paul718e3742002-12-13 20:15:29 +00002872 if (peer_group_active (peer))
2873 peer->ttl = peer->group->conf->ttl;
2874 else
2875 peer->ttl = 1;
2876
2877 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2878 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002879 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002880 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002881 }
2882 else
2883 {
2884 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002885 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002886 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002887 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002888 continue;
paul718e3742002-12-13 20:15:29 +00002889
pauleb821182004-05-01 08:44:08 +00002890 peer->ttl = 1;
2891
2892 if (peer->fd >= 0)
2893 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2894 }
paul718e3742002-12-13 20:15:29 +00002895 }
2896 return 0;
2897}
David Lamparter6b0655a2014-06-04 06:53:35 +02002898
paul718e3742002-12-13 20:15:29 +00002899/* Neighbor description. */
2900int
2901peer_description_set (struct peer *peer, char *desc)
2902{
2903 if (peer->desc)
2904 XFREE (MTYPE_PEER_DESC, peer->desc);
2905
2906 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2907
2908 return 0;
2909}
2910
2911int
2912peer_description_unset (struct peer *peer)
2913{
2914 if (peer->desc)
2915 XFREE (MTYPE_PEER_DESC, peer->desc);
2916
2917 peer->desc = NULL;
2918
2919 return 0;
2920}
David Lamparter6b0655a2014-06-04 06:53:35 +02002921
paul718e3742002-12-13 20:15:29 +00002922/* Neighbor update-source. */
2923int
paulfd79ac92004-10-13 05:06:08 +00002924peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002925{
2926 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002927 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002928
2929 if (peer->update_if)
2930 {
2931 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2932 && strcmp (peer->update_if, ifname) == 0)
2933 return 0;
2934
2935 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2936 peer->update_if = NULL;
2937 }
2938
2939 if (peer->update_source)
2940 {
2941 sockunion_free (peer->update_source);
2942 peer->update_source = NULL;
2943 }
2944
2945 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2946
2947 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2948 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002949 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002950 {
2951 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2952 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2953 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2954 }
paul718e3742002-12-13 20:15:29 +00002955 else
2956 BGP_EVENT_ADD (peer, BGP_Stop);
2957 return 0;
2958 }
2959
2960 /* peer-group member updates. */
2961 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002962 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002963 {
2964 if (peer->update_if)
2965 {
2966 if (strcmp (peer->update_if, ifname) == 0)
2967 continue;
2968
2969 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2970 peer->update_if = NULL;
2971 }
2972
2973 if (peer->update_source)
2974 {
2975 sockunion_free (peer->update_source);
2976 peer->update_source = NULL;
2977 }
2978
2979 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2980
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002981 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002982 {
2983 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2984 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2985 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2986 }
paul718e3742002-12-13 20:15:29 +00002987 else
2988 BGP_EVENT_ADD (peer, BGP_Stop);
2989 }
2990 return 0;
2991}
2992
2993int
2994peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2995{
2996 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002997 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002998
2999 if (peer->update_source)
3000 {
3001 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3002 && sockunion_cmp (peer->update_source, su) == 0)
3003 return 0;
3004 sockunion_free (peer->update_source);
3005 peer->update_source = NULL;
3006 }
3007
3008 if (peer->update_if)
3009 {
3010 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3011 peer->update_if = NULL;
3012 }
3013
3014 peer->update_source = sockunion_dup (su);
3015
3016 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
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 return 0;
3027 }
3028
3029 /* peer-group member updates. */
3030 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003031 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003032 {
3033 if (peer->update_source)
3034 {
3035 if (sockunion_cmp (peer->update_source, su) == 0)
3036 continue;
3037 sockunion_free (peer->update_source);
3038 peer->update_source = NULL;
3039 }
3040
3041 if (peer->update_if)
3042 {
3043 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3044 peer->update_if = NULL;
3045 }
3046
3047 peer->update_source = sockunion_dup (su);
3048
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003049 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003050 {
3051 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3052 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3053 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3054 }
paul718e3742002-12-13 20:15:29 +00003055 else
3056 BGP_EVENT_ADD (peer, BGP_Stop);
3057 }
3058 return 0;
3059}
3060
3061int
3062peer_update_source_unset (struct peer *peer)
3063{
3064 union sockunion *su;
3065 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003066 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003067
3068 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3069 && ! peer->update_source
3070 && ! peer->update_if)
3071 return 0;
3072
3073 if (peer->update_source)
3074 {
3075 sockunion_free (peer->update_source);
3076 peer->update_source = NULL;
3077 }
3078 if (peer->update_if)
3079 {
3080 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3081 peer->update_if = NULL;
3082 }
3083
3084 if (peer_group_active (peer))
3085 {
3086 group = peer->group;
3087
3088 if (group->conf->update_source)
3089 {
3090 su = sockunion_dup (group->conf->update_source);
3091 peer->update_source = su;
3092 }
3093 else if (group->conf->update_if)
3094 peer->update_if =
3095 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
3096 }
3097
3098 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3099 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003100 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003101 {
3102 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3103 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3104 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3105 }
paul718e3742002-12-13 20:15:29 +00003106 else
3107 BGP_EVENT_ADD (peer, BGP_Stop);
3108 return 0;
3109 }
3110
3111 /* peer-group member updates. */
3112 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003113 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003114 {
3115 if (! peer->update_source && ! peer->update_if)
3116 continue;
3117
3118 if (peer->update_source)
3119 {
3120 sockunion_free (peer->update_source);
3121 peer->update_source = NULL;
3122 }
3123
3124 if (peer->update_if)
3125 {
3126 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3127 peer->update_if = NULL;
3128 }
3129
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003130 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003131 {
3132 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3133 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3134 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3135 }
paul718e3742002-12-13 20:15:29 +00003136 else
3137 BGP_EVENT_ADD (peer, BGP_Stop);
3138 }
3139 return 0;
3140}
David Lamparter6b0655a2014-06-04 06:53:35 +02003141
paul718e3742002-12-13 20:15:29 +00003142int
3143peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003144 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003145{
3146 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003147 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003148
3149 /* Adress family must be activated. */
3150 if (! peer->afc[afi][safi])
3151 return BGP_ERR_PEER_INACTIVE;
3152
3153 /* Default originate can't be used for peer group memeber. */
3154 if (peer_is_group_member (peer, afi, safi))
3155 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3156
3157 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3158 || (rmap && ! peer->default_rmap[afi][safi].name)
3159 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3160 {
3161 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3162
3163 if (rmap)
3164 {
3165 if (peer->default_rmap[afi][safi].name)
3166 free (peer->default_rmap[afi][safi].name);
3167 peer->default_rmap[afi][safi].name = strdup (rmap);
3168 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3169 }
3170 }
3171
3172 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3173 {
3174 if (peer->status == Established && peer->afc_nego[afi][safi])
3175 bgp_default_originate (peer, afi, safi, 0);
3176 return 0;
3177 }
3178
3179 /* peer-group member updates. */
3180 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003181 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003182 {
3183 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3184
3185 if (rmap)
3186 {
3187 if (peer->default_rmap[afi][safi].name)
3188 free (peer->default_rmap[afi][safi].name);
3189 peer->default_rmap[afi][safi].name = strdup (rmap);
3190 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3191 }
3192
3193 if (peer->status == Established && peer->afc_nego[afi][safi])
3194 bgp_default_originate (peer, afi, safi, 0);
3195 }
3196 return 0;
3197}
3198
3199int
3200peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3201{
3202 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003203 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003204
3205 /* Adress family must be activated. */
3206 if (! peer->afc[afi][safi])
3207 return BGP_ERR_PEER_INACTIVE;
3208
3209 /* Default originate can't be used for peer group memeber. */
3210 if (peer_is_group_member (peer, afi, safi))
3211 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3212
3213 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3214 {
3215 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3216
3217 if (peer->default_rmap[afi][safi].name)
3218 free (peer->default_rmap[afi][safi].name);
3219 peer->default_rmap[afi][safi].name = NULL;
3220 peer->default_rmap[afi][safi].map = NULL;
3221 }
3222
3223 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3224 {
3225 if (peer->status == Established && peer->afc_nego[afi][safi])
3226 bgp_default_originate (peer, afi, safi, 1);
3227 return 0;
3228 }
3229
3230 /* peer-group member updates. */
3231 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003232 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003233 {
3234 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3235
3236 if (peer->default_rmap[afi][safi].name)
3237 free (peer->default_rmap[afi][safi].name);
3238 peer->default_rmap[afi][safi].name = NULL;
3239 peer->default_rmap[afi][safi].map = NULL;
3240
3241 if (peer->status == Established && peer->afc_nego[afi][safi])
3242 bgp_default_originate (peer, afi, safi, 1);
3243 }
3244 return 0;
3245}
David Lamparter6b0655a2014-06-04 06:53:35 +02003246
paul718e3742002-12-13 20:15:29 +00003247int
3248peer_port_set (struct peer *peer, u_int16_t port)
3249{
3250 peer->port = port;
3251 return 0;
3252}
3253
3254int
3255peer_port_unset (struct peer *peer)
3256{
3257 peer->port = BGP_PORT_DEFAULT;
3258 return 0;
3259}
David Lamparter6b0655a2014-06-04 06:53:35 +02003260
paul718e3742002-12-13 20:15:29 +00003261/* neighbor weight. */
3262int
3263peer_weight_set (struct peer *peer, u_int16_t weight)
3264{
3265 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003266 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003267
3268 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3269 peer->weight = weight;
3270
3271 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3272 return 0;
3273
3274 /* peer-group member updates. */
3275 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003276 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003277 {
3278 peer->weight = group->conf->weight;
3279 }
3280 return 0;
3281}
3282
3283int
3284peer_weight_unset (struct peer *peer)
3285{
3286 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003287 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003288
3289 /* Set default weight. */
3290 if (peer_group_active (peer))
3291 peer->weight = peer->group->conf->weight;
3292 else
3293 peer->weight = 0;
3294
3295 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3296
3297 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3298 return 0;
3299
3300 /* peer-group member updates. */
3301 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003302 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003303 {
3304 peer->weight = 0;
3305 }
3306 return 0;
3307}
David Lamparter6b0655a2014-06-04 06:53:35 +02003308
paul718e3742002-12-13 20:15:29 +00003309int
3310peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3311{
3312 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003313 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003314
3315 /* Not for peer group memeber. */
3316 if (peer_group_active (peer))
3317 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3318
3319 /* keepalive value check. */
3320 if (keepalive > 65535)
3321 return BGP_ERR_INVALID_VALUE;
3322
3323 /* Holdtime value check. */
3324 if (holdtime > 65535)
3325 return BGP_ERR_INVALID_VALUE;
3326
3327 /* Holdtime value must be either 0 or greater than 3. */
3328 if (holdtime < 3 && holdtime != 0)
3329 return BGP_ERR_INVALID_VALUE;
3330
3331 /* Set value to the configuration. */
3332 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3333 peer->holdtime = holdtime;
3334 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3335
3336 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3337 return 0;
3338
3339 /* peer-group member updates. */
3340 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003341 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003342 {
3343 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3344 peer->holdtime = group->conf->holdtime;
3345 peer->keepalive = group->conf->keepalive;
3346 }
3347 return 0;
3348}
3349
3350int
3351peer_timers_unset (struct peer *peer)
3352{
3353 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003354 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003355
3356 if (peer_group_active (peer))
3357 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3358
3359 /* Clear configuration. */
3360 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3361 peer->keepalive = 0;
3362 peer->holdtime = 0;
3363
3364 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3365 return 0;
3366
3367 /* peer-group member updates. */
3368 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003369 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003370 {
3371 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3372 peer->holdtime = 0;
3373 peer->keepalive = 0;
3374 }
3375
3376 return 0;
3377}
David Lamparter6b0655a2014-06-04 06:53:35 +02003378
paul718e3742002-12-13 20:15:29 +00003379int
3380peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3381{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003382 struct peer_group *group;
3383 struct listnode *node, *nnode;
3384
paul718e3742002-12-13 20:15:29 +00003385 if (peer_group_active (peer))
3386 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3387
3388 if (connect > 65535)
3389 return BGP_ERR_INVALID_VALUE;
3390
3391 /* Set value to the configuration. */
3392 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3393 peer->connect = connect;
3394
3395 /* Set value to timer setting. */
3396 peer->v_connect = connect;
3397
Daniel Walton0d7435f2015-10-22 11:35:20 +03003398 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3399 return 0;
3400
3401 /* peer-group member updates. */
3402 group = peer->group;
3403 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3404 {
3405 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3406 peer->connect = connect;
3407 peer->v_connect = connect;
3408 }
paul718e3742002-12-13 20:15:29 +00003409 return 0;
3410}
3411
3412int
3413peer_timers_connect_unset (struct peer *peer)
3414{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003415 struct peer_group *group;
3416 struct listnode *node, *nnode;
3417
paul718e3742002-12-13 20:15:29 +00003418 if (peer_group_active (peer))
3419 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3420
3421 /* Clear configuration. */
3422 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3423 peer->connect = 0;
3424
3425 /* Set timer setting to default value. */
3426 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3427
Daniel Walton0d7435f2015-10-22 11:35:20 +03003428 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3429 return 0;
3430
3431 /* peer-group member updates. */
3432 group = peer->group;
3433 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3434 {
3435 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3436 peer->connect = 0;
3437 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3438 }
3439 return 0;
paul718e3742002-12-13 20:15:29 +00003440}
David Lamparter6b0655a2014-06-04 06:53:35 +02003441
paul718e3742002-12-13 20:15:29 +00003442int
3443peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3444{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003445 struct peer_group *group;
3446 struct listnode *node, *nnode;
3447
paul718e3742002-12-13 20:15:29 +00003448 if (peer_group_active (peer))
3449 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3450
3451 if (routeadv > 600)
3452 return BGP_ERR_INVALID_VALUE;
3453
3454 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3455 peer->routeadv = routeadv;
3456 peer->v_routeadv = routeadv;
3457
Daniel Walton0d7435f2015-10-22 11:35:20 +03003458 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3459 return 0;
3460
3461 /* peer-group member updates. */
3462 group = peer->group;
3463 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3464 {
3465 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3466 peer->routeadv = routeadv;
3467 peer->v_routeadv = routeadv;
3468 }
3469
paul718e3742002-12-13 20:15:29 +00003470 return 0;
3471}
3472
3473int
3474peer_advertise_interval_unset (struct peer *peer)
3475{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003476 struct peer_group *group;
3477 struct listnode *node, *nnode;
3478
paul718e3742002-12-13 20:15:29 +00003479 if (peer_group_active (peer))
3480 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3481
3482 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3483 peer->routeadv = 0;
3484
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003485 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003486 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3487 else
3488 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
Daniel Walton0d7435f2015-10-22 11:35:20 +03003489
3490 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3491 return 0;
3492
3493 /* peer-group member updates. */
3494 group = peer->group;
3495 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3496 {
3497 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3498 peer->routeadv = 0;
3499
3500 if (peer->sort == BGP_PEER_IBGP)
3501 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3502 else
3503 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3504 }
paul718e3742002-12-13 20:15:29 +00003505
3506 return 0;
3507}
David Lamparter6b0655a2014-06-04 06:53:35 +02003508
paul718e3742002-12-13 20:15:29 +00003509/* neighbor interface */
3510int
paulfd79ac92004-10-13 05:06:08 +00003511peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003512{
3513 if (peer->ifname)
3514 free (peer->ifname);
3515 peer->ifname = strdup (str);
3516
3517 return 0;
3518}
3519
3520int
3521peer_interface_unset (struct peer *peer)
3522{
3523 if (peer->ifname)
3524 free (peer->ifname);
3525 peer->ifname = NULL;
3526
3527 return 0;
3528}
David Lamparter6b0655a2014-06-04 06:53:35 +02003529
paul718e3742002-12-13 20:15:29 +00003530/* Allow-as in. */
3531int
3532peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3533{
3534 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003535 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003536
3537 if (allow_num < 1 || allow_num > 10)
3538 return BGP_ERR_INVALID_VALUE;
3539
3540 if (peer->allowas_in[afi][safi] != allow_num)
3541 {
3542 peer->allowas_in[afi][safi] = allow_num;
3543 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3544 peer_change_action (peer, afi, safi, peer_change_reset_in);
3545 }
3546
3547 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3548 return 0;
3549
3550 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003551 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003552 {
3553 if (peer->allowas_in[afi][safi] != allow_num)
3554 {
3555 peer->allowas_in[afi][safi] = allow_num;
3556 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3557 peer_change_action (peer, afi, safi, peer_change_reset_in);
3558 }
3559
3560 }
3561 return 0;
3562}
3563
3564int
3565peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3566{
3567 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003568 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003569
3570 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3571 {
3572 peer->allowas_in[afi][safi] = 0;
3573 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3574 }
3575
3576 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3577 return 0;
3578
3579 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003580 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003581 {
3582 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3583 {
3584 peer->allowas_in[afi][safi] = 0;
3585 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3586 }
3587 }
3588 return 0;
3589}
David Lamparter6b0655a2014-06-04 06:53:35 +02003590
paul718e3742002-12-13 20:15:29 +00003591int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003592peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003593{
3594 struct bgp *bgp = peer->bgp;
3595 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003596 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003597
3598 if (peer_sort (peer) != BGP_PEER_EBGP
3599 && peer_sort (peer) != BGP_PEER_INTERNAL)
3600 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3601
3602 if (bgp->as == as)
3603 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3604
3605 if (peer_group_active (peer))
3606 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3607
Andrew Certain9d3f9702012-11-07 23:50:07 +00003608 if (peer->as == as)
3609 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3610
paul718e3742002-12-13 20:15:29 +00003611 if (peer->change_local_as == as &&
3612 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003613 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3614 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3615 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003616 return 0;
3617
3618 peer->change_local_as = as;
3619 if (no_prepend)
3620 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3621 else
3622 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3623
Andrew Certain9d3f9702012-11-07 23:50:07 +00003624 if (replace_as)
3625 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3626 else
3627 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3628
paul718e3742002-12-13 20:15:29 +00003629 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3630 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003631 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003632 {
3633 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3634 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3635 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3636 }
paul718e3742002-12-13 20:15:29 +00003637 else
3638 BGP_EVENT_ADD (peer, BGP_Stop);
3639
3640 return 0;
3641 }
3642
3643 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003644 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003645 {
3646 peer->change_local_as = as;
3647 if (no_prepend)
3648 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3649 else
3650 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3651
Andrew Certain9d3f9702012-11-07 23:50:07 +00003652 if (replace_as)
3653 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3654 else
3655 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3656
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003657 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003658 {
3659 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3660 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3661 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3662 }
paul718e3742002-12-13 20:15:29 +00003663 else
3664 BGP_EVENT_ADD (peer, BGP_Stop);
3665 }
3666
3667 return 0;
3668}
3669
3670int
3671peer_local_as_unset (struct peer *peer)
3672{
3673 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003674 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003675
3676 if (peer_group_active (peer))
3677 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3678
3679 if (! peer->change_local_as)
3680 return 0;
3681
3682 peer->change_local_as = 0;
3683 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003684 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003685
3686 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3687 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003688 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003689 {
3690 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3691 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3692 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3693 }
paul718e3742002-12-13 20:15:29 +00003694 else
3695 BGP_EVENT_ADD (peer, BGP_Stop);
3696
3697 return 0;
3698 }
3699
3700 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003701 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003702 {
3703 peer->change_local_as = 0;
3704 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003705 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003706
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003707 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003708 {
3709 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3710 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3711 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3712 }
paul718e3742002-12-13 20:15:29 +00003713 else
3714 BGP_EVENT_ADD (peer, BGP_Stop);
3715 }
3716 return 0;
3717}
David Lamparter6b0655a2014-06-04 06:53:35 +02003718
Paul Jakma0df7c912008-07-21 21:02:49 +00003719/* Set password for authenticating with the peer. */
3720int
3721peer_password_set (struct peer *peer, const char *password)
3722{
3723 struct listnode *nn, *nnode;
3724 int len = password ? strlen(password) : 0;
3725 int ret = BGP_SUCCESS;
3726
3727 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3728 return BGP_ERR_INVALID_VALUE;
3729
3730 if (peer->password && strcmp (peer->password, password) == 0
3731 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3732 return 0;
3733
3734 if (peer->password)
3735 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3736
3737 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3738
3739 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3740 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003741 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3742 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
Paul Jakma0df7c912008-07-21 21:02:49 +00003743 else
3744 BGP_EVENT_ADD (peer, BGP_Stop);
3745
3746 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3747 }
3748
3749 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3750 {
3751 if (peer->password && strcmp (peer->password, password) == 0)
3752 continue;
3753
3754 if (peer->password)
3755 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3756
3757 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3758
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003759 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003760 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3761 else
3762 BGP_EVENT_ADD (peer, BGP_Stop);
3763
3764 if (bgp_md5_set (peer) < 0)
3765 ret = BGP_ERR_TCPSIG_FAILED;
3766 }
3767
3768 return ret;
3769}
3770
3771int
3772peer_password_unset (struct peer *peer)
3773{
3774 struct listnode *nn, *nnode;
3775
3776 if (!peer->password
3777 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3778 return 0;
3779
3780 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3781 {
3782 if (peer_group_active (peer)
3783 && peer->group->conf->password
3784 && strcmp (peer->group->conf->password, peer->password) == 0)
3785 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3786
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003787 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003788 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3789 else
3790 BGP_EVENT_ADD (peer, BGP_Stop);
3791
3792 if (peer->password)
3793 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3794
3795 peer->password = NULL;
3796
3797 bgp_md5_set (peer);
3798
3799 return 0;
3800 }
3801
3802 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3803 peer->password = NULL;
3804
3805 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3806 {
3807 if (!peer->password)
3808 continue;
3809
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003810 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003811 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3812 else
3813 BGP_EVENT_ADD (peer, BGP_Stop);
3814
3815 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3816 peer->password = NULL;
3817
3818 bgp_md5_set (peer);
3819 }
3820
3821 return 0;
3822}
David Lamparter6b0655a2014-06-04 06:53:35 +02003823
paul718e3742002-12-13 20:15:29 +00003824/* Set distribute list to the peer. */
3825int
3826peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003827 const char *name)
paul718e3742002-12-13 20:15:29 +00003828{
3829 struct bgp_filter *filter;
3830 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003831 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003832
3833 if (! peer->afc[afi][safi])
3834 return BGP_ERR_PEER_INACTIVE;
3835
3836 if (direct != FILTER_IN && direct != FILTER_OUT)
3837 return BGP_ERR_INVALID_VALUE;
3838
3839 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3840 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3841
3842 filter = &peer->filter[afi][safi];
3843
3844 if (filter->plist[direct].name)
3845 return BGP_ERR_PEER_FILTER_CONFLICT;
3846
3847 if (filter->dlist[direct].name)
3848 free (filter->dlist[direct].name);
3849 filter->dlist[direct].name = strdup (name);
3850 filter->dlist[direct].alist = access_list_lookup (afi, name);
3851
3852 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3853 return 0;
3854
3855 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003856 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003857 {
3858 filter = &peer->filter[afi][safi];
3859
3860 if (! peer->af_group[afi][safi])
3861 continue;
3862
3863 if (filter->dlist[direct].name)
3864 free (filter->dlist[direct].name);
3865 filter->dlist[direct].name = strdup (name);
3866 filter->dlist[direct].alist = access_list_lookup (afi, name);
3867 }
3868
3869 return 0;
3870}
3871
3872int
3873peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3874{
3875 struct bgp_filter *filter;
3876 struct bgp_filter *gfilter;
3877 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003878 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003879
3880 if (! peer->afc[afi][safi])
3881 return BGP_ERR_PEER_INACTIVE;
3882
3883 if (direct != FILTER_IN && direct != FILTER_OUT)
3884 return BGP_ERR_INVALID_VALUE;
3885
3886 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3887 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3888
3889 filter = &peer->filter[afi][safi];
3890
3891 /* apply peer-group filter */
3892 if (peer->af_group[afi][safi])
3893 {
3894 gfilter = &peer->group->conf->filter[afi][safi];
3895
3896 if (gfilter->dlist[direct].name)
3897 {
3898 if (filter->dlist[direct].name)
3899 free (filter->dlist[direct].name);
3900 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3901 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3902 return 0;
3903 }
3904 }
3905
3906 if (filter->dlist[direct].name)
3907 free (filter->dlist[direct].name);
3908 filter->dlist[direct].name = NULL;
3909 filter->dlist[direct].alist = NULL;
3910
3911 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3912 return 0;
3913
3914 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003915 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003916 {
3917 filter = &peer->filter[afi][safi];
3918
3919 if (! peer->af_group[afi][safi])
3920 continue;
3921
3922 if (filter->dlist[direct].name)
3923 free (filter->dlist[direct].name);
3924 filter->dlist[direct].name = NULL;
3925 filter->dlist[direct].alist = NULL;
3926 }
3927
3928 return 0;
3929}
3930
3931/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003932static void
paul718e3742002-12-13 20:15:29 +00003933peer_distribute_update (struct access_list *access)
3934{
3935 afi_t afi;
3936 safi_t safi;
3937 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003938 struct listnode *mnode, *mnnode;
3939 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003940 struct bgp *bgp;
3941 struct peer *peer;
3942 struct peer_group *group;
3943 struct bgp_filter *filter;
3944
paul1eb8ef22005-04-07 07:30:20 +00003945 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003946 {
paul1eb8ef22005-04-07 07:30:20 +00003947 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003948 {
3949 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3950 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3951 {
3952 filter = &peer->filter[afi][safi];
3953
3954 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3955 {
3956 if (filter->dlist[direct].name)
3957 filter->dlist[direct].alist =
3958 access_list_lookup (afi, filter->dlist[direct].name);
3959 else
3960 filter->dlist[direct].alist = NULL;
3961 }
3962 }
3963 }
paul1eb8ef22005-04-07 07:30:20 +00003964 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003965 {
3966 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3967 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3968 {
3969 filter = &group->conf->filter[afi][safi];
3970
3971 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3972 {
3973 if (filter->dlist[direct].name)
3974 filter->dlist[direct].alist =
3975 access_list_lookup (afi, filter->dlist[direct].name);
3976 else
3977 filter->dlist[direct].alist = NULL;
3978 }
3979 }
3980 }
3981 }
3982}
David Lamparter6b0655a2014-06-04 06:53:35 +02003983
paul718e3742002-12-13 20:15:29 +00003984/* Set prefix list to the peer. */
3985int
3986peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003987 const char *name)
paul718e3742002-12-13 20:15:29 +00003988{
3989 struct bgp_filter *filter;
3990 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003991 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003992
3993 if (! peer->afc[afi][safi])
3994 return BGP_ERR_PEER_INACTIVE;
3995
3996 if (direct != FILTER_IN && direct != FILTER_OUT)
3997 return BGP_ERR_INVALID_VALUE;
3998
3999 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4000 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4001
4002 filter = &peer->filter[afi][safi];
4003
4004 if (filter->dlist[direct].name)
4005 return BGP_ERR_PEER_FILTER_CONFLICT;
4006
4007 if (filter->plist[direct].name)
4008 free (filter->plist[direct].name);
4009 filter->plist[direct].name = strdup (name);
4010 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4011
4012 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4013 return 0;
4014
4015 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004016 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004017 {
4018 filter = &peer->filter[afi][safi];
4019
4020 if (! peer->af_group[afi][safi])
4021 continue;
4022
4023 if (filter->plist[direct].name)
4024 free (filter->plist[direct].name);
4025 filter->plist[direct].name = strdup (name);
4026 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4027 }
4028 return 0;
4029}
4030
4031int
4032peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4033{
4034 struct bgp_filter *filter;
4035 struct bgp_filter *gfilter;
4036 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004037 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004038
4039 if (! peer->afc[afi][safi])
4040 return BGP_ERR_PEER_INACTIVE;
4041
4042 if (direct != FILTER_IN && direct != FILTER_OUT)
4043 return BGP_ERR_INVALID_VALUE;
4044
4045 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4046 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4047
4048 filter = &peer->filter[afi][safi];
4049
4050 /* apply peer-group filter */
4051 if (peer->af_group[afi][safi])
4052 {
4053 gfilter = &peer->group->conf->filter[afi][safi];
4054
4055 if (gfilter->plist[direct].name)
4056 {
4057 if (filter->plist[direct].name)
4058 free (filter->plist[direct].name);
4059 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
4060 filter->plist[direct].plist = gfilter->plist[direct].plist;
4061 return 0;
4062 }
4063 }
4064
4065 if (filter->plist[direct].name)
4066 free (filter->plist[direct].name);
4067 filter->plist[direct].name = NULL;
4068 filter->plist[direct].plist = NULL;
4069
4070 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4071 return 0;
4072
4073 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004074 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004075 {
4076 filter = &peer->filter[afi][safi];
4077
4078 if (! peer->af_group[afi][safi])
4079 continue;
4080
4081 if (filter->plist[direct].name)
4082 free (filter->plist[direct].name);
4083 filter->plist[direct].name = NULL;
4084 filter->plist[direct].plist = NULL;
4085 }
4086
4087 return 0;
4088}
4089
4090/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00004091static void
paul718e3742002-12-13 20:15:29 +00004092peer_prefix_list_update (struct prefix_list *plist)
4093{
paul1eb8ef22005-04-07 07:30:20 +00004094 struct listnode *mnode, *mnnode;
4095 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004096 struct bgp *bgp;
4097 struct peer *peer;
4098 struct peer_group *group;
4099 struct bgp_filter *filter;
4100 afi_t afi;
4101 safi_t safi;
4102 int direct;
4103
paul1eb8ef22005-04-07 07:30:20 +00004104 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004105 {
paul1eb8ef22005-04-07 07:30:20 +00004106 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004107 {
4108 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4109 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4110 {
4111 filter = &peer->filter[afi][safi];
4112
4113 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4114 {
4115 if (filter->plist[direct].name)
4116 filter->plist[direct].plist =
4117 prefix_list_lookup (afi, filter->plist[direct].name);
4118 else
4119 filter->plist[direct].plist = NULL;
4120 }
4121 }
4122 }
paul1eb8ef22005-04-07 07:30:20 +00004123 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004124 {
4125 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4126 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4127 {
4128 filter = &group->conf->filter[afi][safi];
4129
4130 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4131 {
4132 if (filter->plist[direct].name)
4133 filter->plist[direct].plist =
4134 prefix_list_lookup (afi, filter->plist[direct].name);
4135 else
4136 filter->plist[direct].plist = NULL;
4137 }
4138 }
4139 }
4140 }
4141}
David Lamparter6b0655a2014-06-04 06:53:35 +02004142
paul718e3742002-12-13 20:15:29 +00004143int
4144peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004145 const char *name)
paul718e3742002-12-13 20:15:29 +00004146{
4147 struct bgp_filter *filter;
4148 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004149 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004150
4151 if (! peer->afc[afi][safi])
4152 return BGP_ERR_PEER_INACTIVE;
4153
4154 if (direct != FILTER_IN && direct != FILTER_OUT)
4155 return BGP_ERR_INVALID_VALUE;
4156
4157 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4158 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4159
4160 filter = &peer->filter[afi][safi];
4161
4162 if (filter->aslist[direct].name)
4163 free (filter->aslist[direct].name);
4164 filter->aslist[direct].name = strdup (name);
4165 filter->aslist[direct].aslist = as_list_lookup (name);
4166
4167 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4168 return 0;
4169
4170 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004171 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004172 {
4173 filter = &peer->filter[afi][safi];
4174
4175 if (! peer->af_group[afi][safi])
4176 continue;
4177
4178 if (filter->aslist[direct].name)
4179 free (filter->aslist[direct].name);
4180 filter->aslist[direct].name = strdup (name);
4181 filter->aslist[direct].aslist = as_list_lookup (name);
4182 }
4183 return 0;
4184}
4185
4186int
4187peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4188{
4189 struct bgp_filter *filter;
4190 struct bgp_filter *gfilter;
4191 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004192 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004193
4194 if (! peer->afc[afi][safi])
4195 return BGP_ERR_PEER_INACTIVE;
4196
hassob5f29602005-05-25 21:00:28 +00004197 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004198 return BGP_ERR_INVALID_VALUE;
4199
hassob5f29602005-05-25 21:00:28 +00004200 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004201 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4202
4203 filter = &peer->filter[afi][safi];
4204
4205 /* apply peer-group filter */
4206 if (peer->af_group[afi][safi])
4207 {
4208 gfilter = &peer->group->conf->filter[afi][safi];
4209
4210 if (gfilter->aslist[direct].name)
4211 {
4212 if (filter->aslist[direct].name)
4213 free (filter->aslist[direct].name);
4214 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4215 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4216 return 0;
4217 }
4218 }
4219
4220 if (filter->aslist[direct].name)
4221 free (filter->aslist[direct].name);
4222 filter->aslist[direct].name = NULL;
4223 filter->aslist[direct].aslist = NULL;
4224
4225 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4226 return 0;
4227
4228 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004229 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004230 {
4231 filter = &peer->filter[afi][safi];
4232
4233 if (! peer->af_group[afi][safi])
4234 continue;
4235
4236 if (filter->aslist[direct].name)
4237 free (filter->aslist[direct].name);
4238 filter->aslist[direct].name = NULL;
4239 filter->aslist[direct].aslist = NULL;
4240 }
4241
4242 return 0;
4243}
4244
paul94f2b392005-06-28 12:44:16 +00004245static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004246peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004247{
4248 afi_t afi;
4249 safi_t safi;
4250 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004251 struct listnode *mnode, *mnnode;
4252 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004253 struct bgp *bgp;
4254 struct peer *peer;
4255 struct peer_group *group;
4256 struct bgp_filter *filter;
4257
paul1eb8ef22005-04-07 07:30:20 +00004258 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004259 {
paul1eb8ef22005-04-07 07:30:20 +00004260 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004261 {
4262 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4263 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4264 {
4265 filter = &peer->filter[afi][safi];
4266
4267 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4268 {
4269 if (filter->aslist[direct].name)
4270 filter->aslist[direct].aslist =
4271 as_list_lookup (filter->aslist[direct].name);
4272 else
4273 filter->aslist[direct].aslist = NULL;
4274 }
4275 }
4276 }
paul1eb8ef22005-04-07 07:30:20 +00004277 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004278 {
4279 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4280 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4281 {
4282 filter = &group->conf->filter[afi][safi];
4283
4284 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4285 {
4286 if (filter->aslist[direct].name)
4287 filter->aslist[direct].aslist =
4288 as_list_lookup (filter->aslist[direct].name);
4289 else
4290 filter->aslist[direct].aslist = NULL;
4291 }
4292 }
4293 }
4294 }
4295}
David Lamparter6b0655a2014-06-04 06:53:35 +02004296
paul718e3742002-12-13 20:15:29 +00004297/* Set route-map to the peer. */
4298int
4299peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004300 const char *name)
paul718e3742002-12-13 20:15:29 +00004301{
4302 struct bgp_filter *filter;
4303 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004304 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004305
4306 if (! peer->afc[afi][safi])
4307 return BGP_ERR_PEER_INACTIVE;
4308
paulfee0f4c2004-09-13 05:12:46 +00004309 if (direct != RMAP_IN && direct != RMAP_OUT &&
4310 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004311 return BGP_ERR_INVALID_VALUE;
4312
paulfee0f4c2004-09-13 05:12:46 +00004313 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4314 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004315 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4316
4317 filter = &peer->filter[afi][safi];
4318
4319 if (filter->map[direct].name)
4320 free (filter->map[direct].name);
4321
4322 filter->map[direct].name = strdup (name);
4323 filter->map[direct].map = route_map_lookup_by_name (name);
4324
4325 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4326 return 0;
4327
4328 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004329 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004330 {
4331 filter = &peer->filter[afi][safi];
4332
4333 if (! peer->af_group[afi][safi])
4334 continue;
4335
4336 if (filter->map[direct].name)
4337 free (filter->map[direct].name);
4338 filter->map[direct].name = strdup (name);
4339 filter->map[direct].map = route_map_lookup_by_name (name);
4340 }
4341 return 0;
4342}
4343
4344/* Unset route-map from the peer. */
4345int
4346peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4347{
4348 struct bgp_filter *filter;
4349 struct bgp_filter *gfilter;
4350 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004351 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004352
4353 if (! peer->afc[afi][safi])
4354 return BGP_ERR_PEER_INACTIVE;
4355
hassob5f29602005-05-25 21:00:28 +00004356 if (direct != RMAP_IN && direct != RMAP_OUT &&
4357 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004358 return BGP_ERR_INVALID_VALUE;
4359
hassob5f29602005-05-25 21:00:28 +00004360 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4361 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004362 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4363
4364 filter = &peer->filter[afi][safi];
4365
4366 /* apply peer-group filter */
4367 if (peer->af_group[afi][safi])
4368 {
4369 gfilter = &peer->group->conf->filter[afi][safi];
4370
4371 if (gfilter->map[direct].name)
4372 {
4373 if (filter->map[direct].name)
4374 free (filter->map[direct].name);
4375 filter->map[direct].name = strdup (gfilter->map[direct].name);
4376 filter->map[direct].map = gfilter->map[direct].map;
4377 return 0;
4378 }
4379 }
4380
4381 if (filter->map[direct].name)
4382 free (filter->map[direct].name);
4383 filter->map[direct].name = NULL;
4384 filter->map[direct].map = NULL;
4385
4386 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4387 return 0;
4388
4389 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004390 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004391 {
4392 filter = &peer->filter[afi][safi];
4393
4394 if (! peer->af_group[afi][safi])
4395 continue;
4396
4397 if (filter->map[direct].name)
4398 free (filter->map[direct].name);
4399 filter->map[direct].name = NULL;
4400 filter->map[direct].map = NULL;
4401 }
4402 return 0;
4403}
David Lamparter6b0655a2014-06-04 06:53:35 +02004404
paul718e3742002-12-13 20:15:29 +00004405/* Set unsuppress-map to the peer. */
4406int
paulfd79ac92004-10-13 05:06:08 +00004407peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4408 const char *name)
paul718e3742002-12-13 20:15:29 +00004409{
4410 struct bgp_filter *filter;
4411 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004412 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004413
4414 if (! peer->afc[afi][safi])
4415 return BGP_ERR_PEER_INACTIVE;
4416
4417 if (peer_is_group_member (peer, afi, safi))
4418 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4419
4420 filter = &peer->filter[afi][safi];
4421
4422 if (filter->usmap.name)
4423 free (filter->usmap.name);
4424
4425 filter->usmap.name = strdup (name);
4426 filter->usmap.map = route_map_lookup_by_name (name);
4427
4428 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4429 return 0;
4430
4431 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004432 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004433 {
4434 filter = &peer->filter[afi][safi];
4435
4436 if (! peer->af_group[afi][safi])
4437 continue;
4438
4439 if (filter->usmap.name)
4440 free (filter->usmap.name);
4441 filter->usmap.name = strdup (name);
4442 filter->usmap.map = route_map_lookup_by_name (name);
4443 }
4444 return 0;
4445}
4446
4447/* Unset route-map from the peer. */
4448int
4449peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4450{
4451 struct bgp_filter *filter;
4452 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004453 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004454
4455 if (! peer->afc[afi][safi])
4456 return BGP_ERR_PEER_INACTIVE;
4457
4458 if (peer_is_group_member (peer, afi, safi))
4459 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4460
4461 filter = &peer->filter[afi][safi];
4462
4463 if (filter->usmap.name)
4464 free (filter->usmap.name);
4465 filter->usmap.name = NULL;
4466 filter->usmap.map = NULL;
4467
4468 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4469 return 0;
4470
4471 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004472 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004473 {
4474 filter = &peer->filter[afi][safi];
4475
4476 if (! peer->af_group[afi][safi])
4477 continue;
4478
4479 if (filter->usmap.name)
4480 free (filter->usmap.name);
4481 filter->usmap.name = NULL;
4482 filter->usmap.map = NULL;
4483 }
4484 return 0;
4485}
David Lamparter6b0655a2014-06-04 06:53:35 +02004486
paul718e3742002-12-13 20:15:29 +00004487int
4488peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004489 u_int32_t max, u_char threshold,
4490 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004491{
4492 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004493 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004494
4495 if (! peer->afc[afi][safi])
4496 return BGP_ERR_PEER_INACTIVE;
4497
4498 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4499 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004500 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004501 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004502 if (warning)
4503 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4504 else
4505 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4506
4507 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4508 return 0;
4509
4510 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004511 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004512 {
4513 if (! peer->af_group[afi][safi])
4514 continue;
4515
4516 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4517 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004518 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004519 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004520 if (warning)
4521 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4522 else
4523 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4524 }
4525 return 0;
4526}
4527
4528int
4529peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4530{
4531 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004532 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004533
4534 if (! peer->afc[afi][safi])
4535 return BGP_ERR_PEER_INACTIVE;
4536
4537 /* apply peer-group config */
4538 if (peer->af_group[afi][safi])
4539 {
4540 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4541 PEER_FLAG_MAX_PREFIX))
4542 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4543 else
4544 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4545
4546 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4547 PEER_FLAG_MAX_PREFIX_WARNING))
4548 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4549 else
4550 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4551
4552 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004553 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004554 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004555 return 0;
4556 }
4557
4558 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4559 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4560 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004561 peer->pmax_threshold[afi][safi] = 0;
4562 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004563
4564 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4565 return 0;
4566
4567 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004568 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004569 {
4570 if (! peer->af_group[afi][safi])
4571 continue;
4572
4573 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4574 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4575 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004576 peer->pmax_threshold[afi][safi] = 0;
4577 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004578 }
4579 return 0;
4580}
David Lamparter5f9adb52014-05-19 23:15:02 +02004581
4582static int is_ebgp_multihop_configured (struct peer *peer)
4583{
4584 struct peer_group *group;
4585 struct listnode *node, *nnode;
4586 struct peer *peer1;
4587
4588 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4589 {
4590 group = peer->group;
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004591 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4592 (group->conf->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004593 return 1;
4594
4595 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4596 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004597 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
4598 (peer1->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004599 return 1;
4600 }
4601 }
4602 else
4603 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004604 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4605 (peer->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004606 return 1;
4607 }
4608 return 0;
4609}
4610
Nick Hilliardfa411a22011-03-23 15:33:17 +00004611/* Set # of hops between us and BGP peer. */
4612int
4613peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4614{
4615 struct peer_group *group;
4616 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004617 int ret;
4618
4619 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4620
Nick Hilliardfa411a22011-03-23 15:33:17 +00004621 /* We cannot configure ttl-security hops when ebgp-multihop is already
4622 set. For non peer-groups, the check is simple. For peer-groups, it's
4623 slightly messy, because we need to check both the peer-group structure
4624 and all peer-group members for any trace of ebgp-multihop configuration
4625 before actually applying the ttl-security rules. Cisco really made a
4626 mess of this configuration parameter, and OpenBGPD got it right.
4627 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004628
David Lamparter5f9adb52014-05-19 23:15:02 +02004629 if (peer->gtsm_hops == 0)
4630 {
4631 if (is_ebgp_multihop_configured (peer))
4632 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004633
David Lamparter5f9adb52014-05-19 23:15:02 +02004634 /* specify MAXTTL on outgoing packets */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004635 /* Routine handles iBGP peers correctly */
David Lamparter5f9adb52014-05-19 23:15:02 +02004636 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4637 if (ret != 0)
4638 return ret;
4639 }
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004640
Nick Hilliardfa411a22011-03-23 15:33:17 +00004641 peer->gtsm_hops = gtsm_hops;
4642
Nick Hilliardfa411a22011-03-23 15:33:17 +00004643 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4644 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004645 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004646 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4647 }
4648 else
4649 {
4650 group = peer->group;
4651 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4652 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004653 peer->gtsm_hops = group->conf->gtsm_hops;
4654
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004655 /* Change setting of existing peer
4656 * established then change value (may break connectivity)
4657 * not established yet (teardown session and restart)
4658 * no session then do nothing (will get handled by next connection)
4659 */
4660 if (peer->status == Established)
4661 {
4662 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4663 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4664 MAXTTL + 1 - peer->gtsm_hops);
4665 }
4666 else if (peer->status < Established)
4667 {
4668 if (BGP_DEBUG (events, EVENTS))
4669 zlog_debug ("%s Min-ttl changed", peer->host);
4670 BGP_EVENT_ADD (peer, BGP_Stop);
4671 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004672 }
4673 }
4674
4675 return 0;
4676}
4677
4678int
4679peer_ttl_security_hops_unset (struct peer *peer)
4680{
4681 struct peer_group *group;
4682 struct listnode *node, *nnode;
4683 struct peer *opeer;
4684
4685 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4686
Nick Hilliardfa411a22011-03-23 15:33:17 +00004687 /* if a peer-group member, then reset to peer-group default rather than 0 */
4688 if (peer_group_active (peer))
4689 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4690 else
4691 peer->gtsm_hops = 0;
4692
4693 opeer = peer;
4694 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4695 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004696 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004697 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4698 }
4699 else
4700 {
4701 group = peer->group;
4702 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4703 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004704 peer->gtsm_hops = 0;
4705
4706 if (peer->fd >= 0)
4707 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4708 }
4709 }
4710
4711 return peer_ebgp_multihop_unset (opeer);
4712}
David Lamparter6b0655a2014-06-04 06:53:35 +02004713
paul718e3742002-12-13 20:15:29 +00004714int
4715peer_clear (struct peer *peer)
4716{
4717 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4718 {
hasso0a486e52005-02-01 20:57:17 +00004719 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4720 {
4721 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4722 if (peer->t_pmax_restart)
4723 {
4724 BGP_TIMER_OFF (peer->t_pmax_restart);
4725 if (BGP_DEBUG (events, EVENTS))
4726 zlog_debug ("%s Maximum-prefix restart timer canceled",
4727 peer->host);
4728 }
4729 BGP_EVENT_ADD (peer, BGP_Start);
4730 return 0;
4731 }
4732
paul718e3742002-12-13 20:15:29 +00004733 peer->v_start = BGP_INIT_START_TIMER;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00004734 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00004735 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4736 BGP_NOTIFY_CEASE_ADMIN_RESET);
4737 else
4738 BGP_EVENT_ADD (peer, BGP_Stop);
4739 }
4740 return 0;
4741}
4742
4743int
4744peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4745 enum bgp_clear_type stype)
4746{
4747 if (peer->status != Established)
4748 return 0;
4749
4750 if (! peer->afc[afi][safi])
4751 return BGP_ERR_AF_UNCONFIGURED;
4752
Timo Teräs5a2a1ec2015-10-22 11:35:18 +03004753 peer->rtt = sockopt_tcp_rtt (peer->fd);
4754
paulfee0f4c2004-09-13 05:12:46 +00004755 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4756 {
4757 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4758 return 0;
4759 bgp_check_local_routes_rsclient (peer, afi, safi);
4760 bgp_soft_reconfig_rsclient (peer, afi, safi);
4761 }
4762
paul718e3742002-12-13 20:15:29 +00004763 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4764 bgp_announce_route (peer, afi, safi);
4765
4766 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4767 {
4768 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4769 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4770 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4771 {
4772 struct bgp_filter *filter = &peer->filter[afi][safi];
4773 u_char prefix_type;
4774
4775 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4776 prefix_type = ORF_TYPE_PREFIX;
4777 else
4778 prefix_type = ORF_TYPE_PREFIX_OLD;
4779
4780 if (filter->plist[FILTER_IN].plist)
4781 {
4782 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4783 bgp_route_refresh_send (peer, afi, safi,
4784 prefix_type, REFRESH_DEFER, 1);
4785 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4786 REFRESH_IMMEDIATE, 0);
4787 }
4788 else
4789 {
4790 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4791 bgp_route_refresh_send (peer, afi, safi,
4792 prefix_type, REFRESH_IMMEDIATE, 1);
4793 else
4794 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4795 }
4796 return 0;
4797 }
4798 }
4799
4800 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4801 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4802 {
4803 /* If neighbor has soft reconfiguration inbound flag.
4804 Use Adj-RIB-In database. */
4805 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4806 bgp_soft_reconfig_in (peer, afi, safi);
4807 else
4808 {
4809 /* If neighbor has route refresh capability, send route refresh
4810 message to the peer. */
4811 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4812 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4813 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4814 else
4815 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4816 }
4817 }
4818 return 0;
4819}
David Lamparter6b0655a2014-06-04 06:53:35 +02004820
paulfd79ac92004-10-13 05:06:08 +00004821/* Display peer uptime.*/
4822/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004823char *
4824peer_uptime (time_t uptime2, char *buf, size_t len)
4825{
4826 time_t uptime1;
4827 struct tm *tm;
4828
4829 /* Check buffer length. */
4830 if (len < BGP_UPTIME_LEN)
4831 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004832 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004833 /* XXX: should return status instead of buf... */
4834 snprintf (buf, len, "<error> ");
4835 return buf;
paul718e3742002-12-13 20:15:29 +00004836 }
4837
4838 /* If there is no connection has been done before print `never'. */
4839 if (uptime2 == 0)
4840 {
4841 snprintf (buf, len, "never ");
4842 return buf;
4843 }
4844
4845 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004846 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004847 uptime1 -= uptime2;
4848 tm = gmtime (&uptime1);
Paul Jakma84c38402015-05-26 15:19:38 +01004849
paul718e3742002-12-13 20:15:29 +00004850 /* Making formatted timer strings. */
4851#define ONE_DAY_SECOND 60*60*24
Paul Jakma84c38402015-05-26 15:19:38 +01004852#define ONE_WEEK_SECOND ONE_DAY_SECOND*7
4853#define ONE_YEAR_SECOND ONE_DAY_SECOND*365
paul718e3742002-12-13 20:15:29 +00004854
4855 if (uptime1 < ONE_DAY_SECOND)
4856 snprintf (buf, len, "%02d:%02d:%02d",
4857 tm->tm_hour, tm->tm_min, tm->tm_sec);
4858 else if (uptime1 < ONE_WEEK_SECOND)
4859 snprintf (buf, len, "%dd%02dh%02dm",
4860 tm->tm_yday, tm->tm_hour, tm->tm_min);
Paul Jakma84c38402015-05-26 15:19:38 +01004861 else if (uptime1 < ONE_YEAR_SECOND)
paul718e3742002-12-13 20:15:29 +00004862 snprintf (buf, len, "%02dw%dd%02dh",
4863 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
Paul Jakma84c38402015-05-26 15:19:38 +01004864 else
4865 snprintf (buf, len, "%02dy%02dw%dd",
4866 tm->tm_year - 70, tm->tm_yday/7,
4867 tm->tm_yday - ((tm->tm_yday/7) * 7));
paul718e3742002-12-13 20:15:29 +00004868 return buf;
4869}
David Lamparter6b0655a2014-06-04 06:53:35 +02004870
paul94f2b392005-06-28 12:44:16 +00004871static void
paul718e3742002-12-13 20:15:29 +00004872bgp_config_write_filter (struct vty *vty, struct peer *peer,
4873 afi_t afi, safi_t safi)
4874{
4875 struct bgp_filter *filter;
4876 struct bgp_filter *gfilter = NULL;
4877 char *addr;
4878 int in = FILTER_IN;
4879 int out = FILTER_OUT;
4880
4881 addr = peer->host;
4882 filter = &peer->filter[afi][safi];
4883 if (peer->af_group[afi][safi])
4884 gfilter = &peer->group->conf->filter[afi][safi];
4885
4886 /* distribute-list. */
4887 if (filter->dlist[in].name)
4888 if (! gfilter || ! gfilter->dlist[in].name
4889 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4890 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4891 filter->dlist[in].name, VTY_NEWLINE);
4892 if (filter->dlist[out].name && ! gfilter)
4893 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4894 filter->dlist[out].name, VTY_NEWLINE);
4895
4896 /* prefix-list. */
4897 if (filter->plist[in].name)
4898 if (! gfilter || ! gfilter->plist[in].name
4899 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4900 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4901 filter->plist[in].name, VTY_NEWLINE);
4902 if (filter->plist[out].name && ! gfilter)
4903 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4904 filter->plist[out].name, VTY_NEWLINE);
4905
4906 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004907 if (filter->map[RMAP_IN].name)
4908 if (! gfilter || ! gfilter->map[RMAP_IN].name
4909 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004910 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004911 filter->map[RMAP_IN].name, VTY_NEWLINE);
4912 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004913 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004914 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4915 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4916 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4917 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4918 if (filter->map[RMAP_EXPORT].name)
4919 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4920 || strcmp (filter->map[RMAP_EXPORT].name,
4921 gfilter->map[RMAP_EXPORT].name) != 0)
4922 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4923 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004924
4925 /* unsuppress-map */
4926 if (filter->usmap.name && ! gfilter)
4927 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4928 filter->usmap.name, VTY_NEWLINE);
4929
4930 /* filter-list. */
4931 if (filter->aslist[in].name)
4932 if (! gfilter || ! gfilter->aslist[in].name
4933 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4934 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4935 filter->aslist[in].name, VTY_NEWLINE);
4936 if (filter->aslist[out].name && ! gfilter)
4937 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4938 filter->aslist[out].name, VTY_NEWLINE);
4939}
4940
4941/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004942static void
paul718e3742002-12-13 20:15:29 +00004943bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4944 struct peer *peer, afi_t afi, safi_t safi)
4945{
paul718e3742002-12-13 20:15:29 +00004946 struct peer *g_peer = NULL;
4947 char buf[SU_ADDRSTRLEN];
4948 char *addr;
4949
paul718e3742002-12-13 20:15:29 +00004950 addr = peer->host;
4951 if (peer_group_active (peer))
4952 g_peer = peer->group->conf;
4953
4954 /************************************
4955 ****** Global to the neighbor ******
4956 ************************************/
4957 if (afi == AFI_IP && safi == SAFI_UNICAST)
4958 {
4959 /* remote-as. */
4960 if (! peer_group_active (peer))
4961 {
4962 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4963 vty_out (vty, " neighbor %s peer-group%s", addr,
4964 VTY_NEWLINE);
4965 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004966 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004967 VTY_NEWLINE);
4968 }
4969 else
4970 {
4971 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004972 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004973 VTY_NEWLINE);
4974 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4975 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4976 peer->group->name, VTY_NEWLINE);
4977 }
4978
4979 /* local-as. */
4980 if (peer->change_local_as)
4981 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00004982 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004983 peer->change_local_as,
4984 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00004985 " no-prepend" : "",
4986 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
4987 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004988
4989 /* Description. */
4990 if (peer->desc)
4991 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4992 VTY_NEWLINE);
4993
4994 /* Shutdown. */
4995 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4996 if (! peer_group_active (peer) ||
4997 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4998 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4999
Paul Jakma0df7c912008-07-21 21:02:49 +00005000 /* Password. */
5001 if (peer->password)
5002 if (!peer_group_active (peer)
5003 || ! g_peer->password
5004 || strcmp (peer->password, g_peer->password) != 0)
5005 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
5006 VTY_NEWLINE);
5007
paul718e3742002-12-13 20:15:29 +00005008 /* BGP port. */
5009 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00005010 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00005011 VTY_NEWLINE);
5012
5013 /* Local interface name. */
5014 if (peer->ifname)
5015 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
5016 VTY_NEWLINE);
5017
5018 /* Passive. */
5019 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
5020 if (! peer_group_active (peer) ||
5021 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
5022 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
5023
5024 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00005025 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00005026 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00005027 if (! peer_group_active (peer) ||
5028 g_peer->ttl != peer->ttl)
5029 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
5030 VTY_NEWLINE);
5031
Nick Hilliardfa411a22011-03-23 15:33:17 +00005032 /* ttl-security hops */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00005033 if (peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00005034 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00005035 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00005036 peer->gtsm_hops, VTY_NEWLINE);
5037
hasso6ffd2072005-02-02 14:50:11 +00005038 /* disable-connected-check. */
5039 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00005040 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00005041 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
5042 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005043
5044 /* Update-source. */
5045 if (peer->update_if)
5046 if (! peer_group_active (peer) || ! g_peer->update_if
5047 || strcmp (g_peer->update_if, peer->update_if) != 0)
5048 vty_out (vty, " neighbor %s update-source %s%s", addr,
5049 peer->update_if, VTY_NEWLINE);
5050 if (peer->update_source)
5051 if (! peer_group_active (peer) || ! g_peer->update_source
5052 || sockunion_cmp (g_peer->update_source,
5053 peer->update_source) != 0)
5054 vty_out (vty, " neighbor %s update-source %s%s", addr,
5055 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
5056 VTY_NEWLINE);
5057
paul718e3742002-12-13 20:15:29 +00005058 /* advertisement-interval */
Daniel Walton0d7435f2015-10-22 11:35:20 +03005059 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV) &&
5060 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00005061 vty_out (vty, " neighbor %s advertisement-interval %d%s",
5062 addr, peer->v_routeadv, VTY_NEWLINE);
5063
5064 /* timers. */
5065 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
5066 && ! peer_group_active (peer))
5067 vty_out (vty, " neighbor %s timers %d %d%s", addr,
5068 peer->keepalive, peer->holdtime, VTY_NEWLINE);
5069
Daniel Walton0d7435f2015-10-22 11:35:20 +03005070 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT) &&
5071 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00005072 vty_out (vty, " neighbor %s timers connect %d%s", addr,
5073 peer->connect, VTY_NEWLINE);
5074
5075 /* Default weight. */
5076 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
5077 if (! peer_group_active (peer) ||
5078 g_peer->weight != peer->weight)
5079 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
5080 VTY_NEWLINE);
5081
paul718e3742002-12-13 20:15:29 +00005082 /* Dynamic capability. */
5083 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5084 if (! peer_group_active (peer) ||
5085 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5086 vty_out (vty, " neighbor %s capability dynamic%s", addr,
5087 VTY_NEWLINE);
5088
5089 /* dont capability negotiation. */
5090 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
5091 if (! peer_group_active (peer) ||
5092 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
5093 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
5094 VTY_NEWLINE);
5095
5096 /* override capability negotiation. */
5097 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5098 if (! peer_group_active (peer) ||
5099 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5100 vty_out (vty, " neighbor %s override-capability%s", addr,
5101 VTY_NEWLINE);
5102
5103 /* strict capability negotiation. */
5104 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5105 if (! peer_group_active (peer) ||
5106 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5107 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
5108 VTY_NEWLINE);
5109
Christian Franke15c71342012-11-19 11:17:31 +00005110 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
paul718e3742002-12-13 20:15:29 +00005111 {
5112 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5113 {
5114 if (peer->afc[AFI_IP][SAFI_UNICAST])
5115 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5116 }
5117 else
5118 {
5119 if (! peer->afc[AFI_IP][SAFI_UNICAST])
5120 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
5121 }
5122 }
5123 }
5124
5125
5126 /************************************
5127 ****** Per AF to the neighbor ******
5128 ************************************/
5129
5130 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
5131 {
5132 if (peer->af_group[afi][safi])
5133 vty_out (vty, " neighbor %s peer-group %s%s", addr,
5134 peer->group->name, VTY_NEWLINE);
5135 else
5136 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5137 }
5138
5139 /* ORF capability. */
5140 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5141 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5142 if (! peer->af_group[afi][safi])
5143 {
5144 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
5145
5146 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5147 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5148 vty_out (vty, " both");
5149 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
5150 vty_out (vty, " send");
5151 else
5152 vty_out (vty, " receive");
5153 vty_out (vty, "%s", VTY_NEWLINE);
5154 }
5155
5156 /* Route reflector client. */
5157 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
5158 && ! peer->af_group[afi][safi])
5159 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
5160 VTY_NEWLINE);
5161
5162 /* Nexthop self. */
5163 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
5164 && ! peer->af_group[afi][safi])
Timo Teräs9e7a53c2014-04-24 10:22:37 +03005165 vty_out (vty, " neighbor %s next-hop-self%s%s", addr,
5166 peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ?
5167 " all" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005168
5169 /* Remove private AS. */
5170 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
5171 && ! peer->af_group[afi][safi])
5172 vty_out (vty, " neighbor %s remove-private-AS%s",
5173 addr, VTY_NEWLINE);
5174
5175 /* send-community print. */
5176 if (! peer->af_group[afi][safi])
5177 {
5178 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5179 {
5180 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5181 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5182 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
5183 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5184 vty_out (vty, " neighbor %s send-community extended%s",
5185 addr, VTY_NEWLINE);
5186 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5187 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
5188 }
5189 else
5190 {
5191 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5192 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5193 vty_out (vty, " no neighbor %s send-community both%s",
5194 addr, VTY_NEWLINE);
5195 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5196 vty_out (vty, " no neighbor %s send-community extended%s",
5197 addr, VTY_NEWLINE);
5198 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5199 vty_out (vty, " no neighbor %s send-community%s",
5200 addr, VTY_NEWLINE);
5201 }
5202 }
5203
5204 /* Default information */
5205 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5206 && ! peer->af_group[afi][safi])
5207 {
5208 vty_out (vty, " neighbor %s default-originate", addr);
5209 if (peer->default_rmap[afi][safi].name)
5210 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5211 vty_out (vty, "%s", VTY_NEWLINE);
5212 }
5213
5214 /* Soft reconfiguration inbound. */
5215 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5216 if (! peer->af_group[afi][safi] ||
5217 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5218 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5219 VTY_NEWLINE);
5220
5221 /* maximum-prefix. */
5222 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5223 if (! peer->af_group[afi][safi]
5224 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005225 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005226 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5227 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005228 {
hasso0a486e52005-02-01 20:57:17 +00005229 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5230 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5231 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5232 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5233 vty_out (vty, " warning-only");
5234 if (peer->pmax_restart[afi][safi])
5235 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5236 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005237 }
paul718e3742002-12-13 20:15:29 +00005238
5239 /* Route server client. */
5240 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5241 && ! peer->af_group[afi][safi])
5242 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5243
Dylan Hall3cf12882011-10-27 15:28:17 +04005244 /* Nexthop-local unchanged. */
5245 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5246 && ! peer->af_group[afi][safi])
5247 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5248
paul718e3742002-12-13 20:15:29 +00005249 /* Allow AS in. */
5250 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5251 if (! peer_group_active (peer)
5252 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5253 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5254 {
5255 if (peer->allowas_in[afi][safi] == 3)
5256 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5257 else
5258 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5259 peer->allowas_in[afi][safi], VTY_NEWLINE);
5260 }
5261
5262 /* Filter. */
5263 bgp_config_write_filter (vty, peer, afi, safi);
5264
5265 /* atribute-unchanged. */
5266 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5267 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5268 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5269 && ! peer->af_group[afi][safi])
5270 {
5271 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5272 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5273 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5274 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5275 else
5276 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5277 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5278 " as-path" : "",
5279 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5280 " next-hop" : "",
5281 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5282 " med" : "", VTY_NEWLINE);
5283 }
5284}
5285
5286/* Display "address-family" configuration header. */
5287void
5288bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5289 int *write)
5290{
5291 if (*write)
5292 return;
5293
5294 if (afi == AFI_IP && safi == SAFI_UNICAST)
5295 return;
5296
5297 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5298
5299 if (afi == AFI_IP)
5300 {
5301 if (safi == SAFI_MULTICAST)
5302 vty_out (vty, "ipv4 multicast");
5303 else if (safi == SAFI_MPLS_VPN)
5304 vty_out (vty, "vpnv4 unicast");
5305 }
5306 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005307 {
Lou Berger13c378d2016-01-12 13:41:56 -05005308 if (safi == SAFI_MPLS_VPN)
5309 vty_out (vty, "vpnv6");
5310 else
5311 {
5312 vty_out (vty, "ipv6");
5313 if (safi == SAFI_MULTICAST)
5314 vty_out (vty, " multicast");
5315 }
Paul Jakma37a217a2007-04-10 19:20:29 +00005316 }
paul718e3742002-12-13 20:15:29 +00005317
5318 vty_out (vty, "%s", VTY_NEWLINE);
5319
5320 *write = 1;
5321}
5322
5323/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005324static int
paul718e3742002-12-13 20:15:29 +00005325bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5326 safi_t safi)
5327{
5328 int write = 0;
5329 struct peer *peer;
5330 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005331 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005332
5333 bgp_config_write_network (vty, bgp, afi, safi, &write);
5334
5335 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5336
paul1eb8ef22005-04-07 07:30:20 +00005337 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005338 {
5339 if (group->conf->afc[afi][safi])
5340 {
5341 bgp_config_write_family_header (vty, afi, safi, &write);
5342 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5343 }
5344 }
paul1eb8ef22005-04-07 07:30:20 +00005345 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005346 {
5347 if (peer->afc[afi][safi])
5348 {
5349 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5350 {
5351 bgp_config_write_family_header (vty, afi, safi, &write);
5352 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5353 }
5354 }
5355 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005356
5357 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5358
paul718e3742002-12-13 20:15:29 +00005359 if (write)
5360 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5361
5362 return write;
5363}
5364
5365int
5366bgp_config_write (struct vty *vty)
5367{
5368 int write = 0;
5369 struct bgp *bgp;
5370 struct peer_group *group;
5371 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005372 struct listnode *node, *nnode;
5373 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005374
5375 /* BGP Multiple instance. */
5376 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5377 {
5378 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5379 write++;
5380 }
5381
5382 /* BGP Config type. */
5383 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5384 {
5385 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5386 write++;
5387 }
5388
5389 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005390 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005391 {
5392 if (write)
5393 vty_out (vty, "!%s", VTY_NEWLINE);
5394
5395 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005396 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005397
5398 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5399 {
5400 if (bgp->name)
5401 vty_out (vty, " view %s", bgp->name);
5402 }
5403 vty_out (vty, "%s", VTY_NEWLINE);
5404
5405 /* No Synchronization */
5406 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5407 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5408
5409 /* BGP fast-external-failover. */
5410 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5411 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5412
5413 /* BGP router ID. */
5414 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5415 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5416 VTY_NEWLINE);
5417
paul848973c2003-08-13 00:32:49 +00005418 /* BGP log-neighbor-changes. */
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07005419 if (!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5420 vty_out (vty, " no bgp log-neighbor-changes%s", VTY_NEWLINE);
paul848973c2003-08-13 00:32:49 +00005421
paul718e3742002-12-13 20:15:29 +00005422 /* BGP configuration. */
5423 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5424 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5425
5426 /* BGP default ipv4-unicast. */
5427 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5428 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5429
5430 /* BGP default local-preference. */
5431 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5432 vty_out (vty, " bgp default local-preference %d%s",
5433 bgp->default_local_pref, VTY_NEWLINE);
5434
5435 /* BGP client-to-client reflection. */
5436 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5437 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5438
5439 /* BGP cluster ID. */
5440 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5441 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5442 VTY_NEWLINE);
5443
hassoe0701b72004-05-20 09:19:34 +00005444 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005445 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005446 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5447 VTY_NEWLINE);
5448
5449 /* Confederation peer */
5450 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005451 {
hassoe0701b72004-05-20 09:19:34 +00005452 int i;
paul718e3742002-12-13 20:15:29 +00005453
hassoe0701b72004-05-20 09:19:34 +00005454 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005455
hassoe0701b72004-05-20 09:19:34 +00005456 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005457 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005458
hassoe0701b72004-05-20 09:19:34 +00005459 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005460 }
5461
5462 /* BGP enforce-first-as. */
5463 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5464 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5465
5466 /* BGP deterministic-med. */
5467 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5468 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005469
5470 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005471 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5472 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5473 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005474 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5475 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5476
paul718e3742002-12-13 20:15:29 +00005477 /* BGP bestpath method. */
5478 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5479 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005480 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5481 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
Pradosh Mohapatra2fdd4552013-09-07 07:02:36 +00005482 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
5483 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
5484 }
paul718e3742002-12-13 20:15:29 +00005485 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5486 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5487 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5488 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5489 {
5490 vty_out (vty, " bgp bestpath med");
5491 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5492 vty_out (vty, " confed");
5493 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5494 vty_out (vty, " missing-as-worst");
5495 vty_out (vty, "%s", VTY_NEWLINE);
5496 }
5497
5498 /* BGP network import check. */
5499 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5500 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5501
5502 /* BGP scan interval. */
5503 bgp_config_write_scan_time (vty);
5504
5505 /* BGP flag dampening. */
5506 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5507 BGP_CONFIG_DAMPENING))
5508 bgp_config_write_damp (vty);
5509
5510 /* BGP static route configuration. */
5511 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5512
5513 /* BGP redistribute configuration. */
5514 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5515
5516 /* BGP timers configuration. */
5517 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5518 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5519 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5520 bgp->default_holdtime, VTY_NEWLINE);
5521
5522 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005523 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005524 {
5525 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5526 }
5527
5528 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005529 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005530 {
5531 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5532 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5533 }
5534
Josh Bailey165b5ff2011-07-20 20:43:22 -07005535 /* maximum-paths */
5536 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5537
paul718e3742002-12-13 20:15:29 +00005538 /* Distance configuration. */
5539 bgp_config_write_distance (vty, bgp);
5540
5541 /* No auto-summary */
5542 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5543 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5544
5545 /* IPv4 multicast configuration. */
5546 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5547
5548 /* IPv4 VPN configuration. */
5549 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5550
5551 /* IPv6 unicast configuration. */
5552 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5553
Paul Jakma37a217a2007-04-10 19:20:29 +00005554 /* IPv6 multicast configuration. */
5555 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5556
Lou Berger13c378d2016-01-12 13:41:56 -05005557 /* IPv6 VPN configuration. */
5558 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MPLS_VPN);
5559
paul718e3742002-12-13 20:15:29 +00005560 write++;
5561 }
5562 return write;
5563}
5564
5565void
paul94f2b392005-06-28 12:44:16 +00005566bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005567{
5568 memset (&bgp_master, 0, sizeof (struct bgp_master));
5569
5570 bm = &bgp_master;
5571 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005572 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005573 bm->port = BGP_PORT_DEFAULT;
5574 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005575 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005576}
paul200df112005-06-01 11:17:05 +00005577
David Lamparter6b0655a2014-06-04 06:53:35 +02005578
paul718e3742002-12-13 20:15:29 +00005579void
paul94f2b392005-06-28 12:44:16 +00005580bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005581{
paul718e3742002-12-13 20:15:29 +00005582 /* BGP VTY commands installation. */
5583 bgp_vty_init ();
5584
paul718e3742002-12-13 20:15:29 +00005585 /* Init zebra. */
Donald Sharp774914f2015-10-14 08:50:39 -04005586 bgp_zebra_init (bm->master);
paul718e3742002-12-13 20:15:29 +00005587
5588 /* BGP inits. */
5589 bgp_attr_init ();
5590 bgp_debug_init ();
5591 bgp_dump_init ();
5592 bgp_route_init ();
5593 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005594 bgp_address_init ();
paul718e3742002-12-13 20:15:29 +00005595 bgp_scan_init ();
5596 bgp_mplsvpn_init ();
5597
5598 /* Access list initialize. */
5599 access_list_init ();
5600 access_list_add_hook (peer_distribute_update);
5601 access_list_delete_hook (peer_distribute_update);
5602
5603 /* Filter list initialize. */
5604 bgp_filter_init ();
5605 as_list_add_hook (peer_aslist_update);
5606 as_list_delete_hook (peer_aslist_update);
5607
5608 /* Prefix list initialize.*/
5609 prefix_list_init ();
5610 prefix_list_add_hook (peer_prefix_list_update);
5611 prefix_list_delete_hook (peer_prefix_list_update);
5612
5613 /* Community list initialize. */
5614 bgp_clist = community_list_init ();
5615
5616#ifdef HAVE_SNMP
5617 bgp_snmp_init ();
5618#endif /* HAVE_SNMP */
5619}
paul545acaf2004-04-20 15:13:15 +00005620
5621void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005622bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005623{
paul545acaf2004-04-20 15:13:15 +00005624 struct bgp *bgp;
5625 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005626 struct listnode *node, *nnode;
5627 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005628
paul1eb8ef22005-04-07 07:30:20 +00005629 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5630 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005631 if (peer->status == Established)
5632 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5633 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005634
paul545acaf2004-04-20 15:13:15 +00005635 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005636
paule210cf92005-06-15 19:15:35 +00005637 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005638 {
5639 work_queue_free (bm->process_main_queue);
5640 bm->process_main_queue = NULL;
5641 }
paule210cf92005-06-15 19:15:35 +00005642 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005643 {
5644 work_queue_free (bm->process_rsclient_queue);
5645 bm->process_rsclient_queue = NULL;
5646 }
paul545acaf2004-04-20 15:13:15 +00005647}