blob: c3c0dba3fe2ed3e449d51ba7f1cc71d35030d7cf [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
1380 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001381
1382 return 0;
1383}
David Lamparter6b0655a2014-06-04 06:53:35 +02001384
paul94f2b392005-06-28 12:44:16 +00001385static int
paul718e3742002-12-13 20:15:29 +00001386peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1387{
1388 return strcmp (g1->name, g2->name);
1389}
1390
1391/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001392static int
paul718e3742002-12-13 20:15:29 +00001393peer_group_active (struct peer *peer)
1394{
1395 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1396 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1397 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1398 || peer->af_group[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05001399 || peer->af_group[AFI_IP6][SAFI_MULTICAST]
1400 || peer->af_group[AFI_IP6][SAFI_MPLS_VPN])
paul718e3742002-12-13 20:15:29 +00001401 return 1;
1402 return 0;
1403}
1404
1405/* Peer group cofiguration. */
1406static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001407peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001408{
1409 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1410 sizeof (struct peer_group));
1411}
1412
paul94f2b392005-06-28 12:44:16 +00001413static void
paul718e3742002-12-13 20:15:29 +00001414peer_group_free (struct peer_group *group)
1415{
1416 XFREE (MTYPE_PEER_GROUP, group);
1417}
1418
1419struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001420peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001421{
1422 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001423 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001424
paul1eb8ef22005-04-07 07:30:20 +00001425 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001426 {
1427 if (strcmp (group->name, name) == 0)
1428 return group;
1429 }
1430 return NULL;
1431}
1432
1433struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001434peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001435{
1436 struct peer_group *group;
1437
1438 group = peer_group_lookup (bgp, name);
1439 if (group)
1440 return group;
1441
1442 group = peer_group_new ();
1443 group->bgp = bgp;
1444 group->name = strdup (name);
1445 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001446 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001447 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1448 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001449 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001450 group->conf->group = group;
1451 group->conf->as = 0;
1452 group->conf->ttl = 1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001453 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001454 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1455 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1456 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1457 group->conf->keepalive = 0;
1458 group->conf->holdtime = 0;
1459 group->conf->connect = 0;
1460 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1461 listnode_add_sort (bgp->group, group);
1462
1463 return 0;
1464}
1465
paul94f2b392005-06-28 12:44:16 +00001466static void
paul718e3742002-12-13 20:15:29 +00001467peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1468 afi_t afi, safi_t safi)
1469{
1470 int in = FILTER_IN;
1471 int out = FILTER_OUT;
1472 struct peer *conf;
1473 struct bgp_filter *pfilter;
1474 struct bgp_filter *gfilter;
1475
1476 conf = group->conf;
1477 pfilter = &peer->filter[afi][safi];
1478 gfilter = &conf->filter[afi][safi];
1479
1480 /* remote-as */
1481 if (conf->as)
1482 peer->as = conf->as;
1483
1484 /* remote-as */
1485 if (conf->change_local_as)
1486 peer->change_local_as = conf->change_local_as;
1487
1488 /* TTL */
1489 peer->ttl = conf->ttl;
1490
Nick Hilliardfa411a22011-03-23 15:33:17 +00001491 /* GTSM hops */
1492 peer->gtsm_hops = conf->gtsm_hops;
1493
paul718e3742002-12-13 20:15:29 +00001494 /* Weight */
1495 peer->weight = conf->weight;
1496
1497 /* peer flags apply */
1498 peer->flags = conf->flags;
1499 /* peer af_flags apply */
1500 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1501 /* peer config apply */
1502 peer->config = conf->config;
1503
1504 /* peer timers apply */
1505 peer->holdtime = conf->holdtime;
1506 peer->keepalive = conf->keepalive;
1507 peer->connect = conf->connect;
1508 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1509 peer->v_connect = conf->connect;
1510 else
1511 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1512
1513 /* advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +03001514 if (CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
1515 peer->v_routeadv = conf->routeadv;
paul718e3742002-12-13 20:15:29 +00001516 else
Daniel Walton0d7435f2015-10-22 11:35:20 +03001517 if (peer_sort (peer) == BGP_PEER_IBGP)
1518 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1519 else
1520 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul718e3742002-12-13 20:15:29 +00001521
Paul Jakma0df7c912008-07-21 21:02:49 +00001522 /* password apply */
Roman Hoog Antink0e4303d2013-01-18 13:52:03 +01001523 if (conf->password && !peer->password)
Paul Jakma0df7c912008-07-21 21:02:49 +00001524 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
Paul Jakma0df7c912008-07-21 21:02:49 +00001525
1526 bgp_md5_set (peer);
1527
paul718e3742002-12-13 20:15:29 +00001528 /* maximum-prefix */
1529 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001530 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001531 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001532
1533 /* allowas-in */
1534 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1535
paulfee0f4c2004-09-13 05:12:46 +00001536 /* route-server-client */
1537 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1538 {
1539 /* Make peer's RIB point to group's RIB. */
1540 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1541
1542 /* Import policy. */
1543 if (pfilter->map[RMAP_IMPORT].name)
1544 free (pfilter->map[RMAP_IMPORT].name);
1545 if (gfilter->map[RMAP_IMPORT].name)
1546 {
1547 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1548 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1549 }
1550 else
1551 {
1552 pfilter->map[RMAP_IMPORT].name = NULL;
1553 pfilter->map[RMAP_IMPORT].map = NULL;
1554 }
1555
1556 /* Export policy. */
1557 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1558 {
1559 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1560 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1561 }
1562 }
1563
paul718e3742002-12-13 20:15:29 +00001564 /* default-originate route-map */
1565 if (conf->default_rmap[afi][safi].name)
1566 {
1567 if (peer->default_rmap[afi][safi].name)
1568 free (peer->default_rmap[afi][safi].name);
1569 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1570 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1571 }
1572
1573 /* update-source apply */
1574 if (conf->update_source)
1575 {
1576 if (peer->update_source)
1577 sockunion_free (peer->update_source);
1578 if (peer->update_if)
1579 {
1580 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1581 peer->update_if = NULL;
1582 }
1583 peer->update_source = sockunion_dup (conf->update_source);
1584 }
1585 else if (conf->update_if)
1586 {
1587 if (peer->update_if)
1588 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1589 if (peer->update_source)
1590 {
1591 sockunion_free (peer->update_source);
1592 peer->update_source = NULL;
1593 }
1594 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1595 }
1596
1597 /* inbound filter apply */
1598 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1599 {
1600 if (pfilter->dlist[in].name)
1601 free (pfilter->dlist[in].name);
1602 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1603 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1604 }
1605 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1606 {
1607 if (pfilter->plist[in].name)
1608 free (pfilter->plist[in].name);
1609 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1610 pfilter->plist[in].plist = gfilter->plist[in].plist;
1611 }
1612 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1613 {
1614 if (pfilter->aslist[in].name)
1615 free (pfilter->aslist[in].name);
1616 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1617 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1618 }
paulfee0f4c2004-09-13 05:12:46 +00001619 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001620 {
paulfee0f4c2004-09-13 05:12:46 +00001621 if (pfilter->map[RMAP_IN].name)
1622 free (pfilter->map[RMAP_IN].name);
1623 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1624 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001625 }
1626
1627 /* outbound filter apply */
1628 if (gfilter->dlist[out].name)
1629 {
1630 if (pfilter->dlist[out].name)
1631 free (pfilter->dlist[out].name);
1632 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1633 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1634 }
1635 else
1636 {
1637 if (pfilter->dlist[out].name)
1638 free (pfilter->dlist[out].name);
1639 pfilter->dlist[out].name = NULL;
1640 pfilter->dlist[out].alist = NULL;
1641 }
1642 if (gfilter->plist[out].name)
1643 {
1644 if (pfilter->plist[out].name)
1645 free (pfilter->plist[out].name);
1646 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1647 pfilter->plist[out].plist = gfilter->plist[out].plist;
1648 }
1649 else
1650 {
1651 if (pfilter->plist[out].name)
1652 free (pfilter->plist[out].name);
1653 pfilter->plist[out].name = NULL;
1654 pfilter->plist[out].plist = NULL;
1655 }
1656 if (gfilter->aslist[out].name)
1657 {
1658 if (pfilter->aslist[out].name)
1659 free (pfilter->aslist[out].name);
1660 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1661 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1662 }
1663 else
1664 {
1665 if (pfilter->aslist[out].name)
1666 free (pfilter->aslist[out].name);
1667 pfilter->aslist[out].name = NULL;
1668 pfilter->aslist[out].aslist = NULL;
1669 }
paulfee0f4c2004-09-13 05:12:46 +00001670 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001671 {
paulfee0f4c2004-09-13 05:12:46 +00001672 if (pfilter->map[RMAP_OUT].name)
1673 free (pfilter->map[RMAP_OUT].name);
1674 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1675 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001676 }
1677 else
1678 {
paulfee0f4c2004-09-13 05:12:46 +00001679 if (pfilter->map[RMAP_OUT].name)
1680 free (pfilter->map[RMAP_OUT].name);
1681 pfilter->map[RMAP_OUT].name = NULL;
1682 pfilter->map[RMAP_OUT].map = NULL;
1683 }
1684
1685 /* RS-client's import/export route-maps. */
1686 if (gfilter->map[RMAP_IMPORT].name)
1687 {
1688 if (pfilter->map[RMAP_IMPORT].name)
1689 free (pfilter->map[RMAP_IMPORT].name);
1690 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1691 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1692 }
1693 else
1694 {
1695 if (pfilter->map[RMAP_IMPORT].name)
1696 free (pfilter->map[RMAP_IMPORT].name);
1697 pfilter->map[RMAP_IMPORT].name = NULL;
1698 pfilter->map[RMAP_IMPORT].map = NULL;
1699 }
1700 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1701 {
1702 if (pfilter->map[RMAP_EXPORT].name)
1703 free (pfilter->map[RMAP_EXPORT].name);
1704 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1705 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001706 }
1707
1708 if (gfilter->usmap.name)
1709 {
1710 if (pfilter->usmap.name)
1711 free (pfilter->usmap.name);
1712 pfilter->usmap.name = strdup (gfilter->usmap.name);
1713 pfilter->usmap.map = gfilter->usmap.map;
1714 }
1715 else
1716 {
1717 if (pfilter->usmap.name)
1718 free (pfilter->usmap.name);
1719 pfilter->usmap.name = NULL;
1720 pfilter->usmap.map = NULL;
1721 }
1722}
1723
1724/* Peer group's remote AS configuration. */
1725int
paulfd79ac92004-10-13 05:06:08 +00001726peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001727{
1728 struct peer_group *group;
1729 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001730 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001731
1732 group = peer_group_lookup (bgp, group_name);
1733 if (! group)
1734 return -1;
1735
1736 if (group->conf->as == *as)
1737 return 0;
1738
1739 /* When we setup peer-group AS number all peer group member's AS
1740 number must be updated to same number. */
1741 peer_as_change (group->conf, *as);
1742
paul1eb8ef22005-04-07 07:30:20 +00001743 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001744 {
1745 if (peer->as != *as)
1746 peer_as_change (peer, *as);
1747 }
1748
1749 return 0;
1750}
1751
1752int
1753peer_group_delete (struct peer_group *group)
1754{
1755 struct bgp *bgp;
1756 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001757 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001758
1759 bgp = group->bgp;
1760
paul1eb8ef22005-04-07 07:30:20 +00001761 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001762 {
paul718e3742002-12-13 20:15:29 +00001763 peer_delete (peer);
1764 }
1765 list_delete (group->peer);
1766
1767 free (group->name);
1768 group->name = NULL;
1769
1770 group->conf->group = NULL;
1771 peer_delete (group->conf);
1772
1773 /* Delete from all peer_group list. */
1774 listnode_delete (bgp->group, group);
1775
1776 peer_group_free (group);
1777
1778 return 0;
1779}
1780
1781int
1782peer_group_remote_as_delete (struct peer_group *group)
1783{
1784 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001785 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001786
1787 if (! group->conf->as)
1788 return 0;
1789
paul1eb8ef22005-04-07 07:30:20 +00001790 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001791 {
paul718e3742002-12-13 20:15:29 +00001792 peer_delete (peer);
1793 }
1794 list_delete_all_node (group->peer);
1795
1796 group->conf->as = 0;
1797
1798 return 0;
1799}
1800
1801/* Bind specified peer to peer group. */
1802int
1803peer_group_bind (struct bgp *bgp, union sockunion *su,
1804 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1805{
1806 struct peer *peer;
1807 int first_member = 0;
1808
1809 /* Check peer group's address family. */
1810 if (! group->conf->afc[afi][safi])
1811 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1812
1813 /* Lookup the peer. */
1814 peer = peer_lookup (bgp, su);
1815
1816 /* Create a new peer. */
1817 if (! peer)
1818 {
1819 if (! group->conf->as)
1820 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1821
1822 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1823 peer->group = group;
1824 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001825
Paul Jakmaca058a32006-09-14 02:58:49 +00001826 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001827 listnode_add (group->peer, peer);
1828 peer_group2peer_config_copy (group, peer, afi, safi);
1829
1830 return 0;
1831 }
1832
1833 /* When the peer already belongs to peer group, check the consistency. */
1834 if (peer->af_group[afi][safi])
1835 {
1836 if (strcmp (peer->group->name, group->name) != 0)
1837 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1838
1839 return 0;
1840 }
1841
1842 /* Check current peer group configuration. */
1843 if (peer_group_active (peer)
1844 && strcmp (peer->group->name, group->name) != 0)
1845 return BGP_ERR_PEER_GROUP_MISMATCH;
1846
1847 if (! group->conf->as)
1848 {
1849 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1850 && peer_sort (group->conf) != peer_sort (peer))
1851 {
1852 if (as)
1853 *as = peer->as;
1854 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1855 }
1856
1857 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1858 first_member = 1;
1859 }
1860
1861 peer->af_group[afi][safi] = 1;
1862 peer->afc[afi][safi] = 1;
1863 if (! peer->group)
1864 {
1865 peer->group = group;
paul200df112005-06-01 11:17:05 +00001866
Paul Jakmaca058a32006-09-14 02:58:49 +00001867 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001868 listnode_add (group->peer, peer);
1869 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001870 else
1871 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001872
1873 if (first_member)
1874 {
1875 /* Advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +03001876 if (! CHECK_FLAG (group->conf->config, PEER_CONFIG_ROUTEADV))
1877 {
1878 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1879 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1880 else
1881 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1882 }
paul718e3742002-12-13 20:15:29 +00001883
1884 /* ebgp-multihop reset */
1885 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1886 group->conf->ttl = 255;
1887
1888 /* local-as reset */
1889 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1890 {
1891 group->conf->change_local_as = 0;
1892 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001893 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001894 }
1895 }
paulfee0f4c2004-09-13 05:12:46 +00001896
1897 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1898 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001899 struct listnode *pn;
1900
paulfee0f4c2004-09-13 05:12:46 +00001901 /* If it's not configured as RSERVER_CLIENT in any other address
1902 family, without being member of a peer_group, remove it from
1903 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001904 if (! peer_rsclient_active (peer)
1905 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001906 {
1907 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001908 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001909
1910 /* Clear our own rsclient rib for this afi/safi. */
1911 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001912 }
paulfee0f4c2004-09-13 05:12:46 +00001913
Paul Jakmab608d5b2008-07-02 02:12:07 +00001914 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001915
1916 /* Import policy. */
1917 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1918 {
1919 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1920 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1921 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1922 }
1923
1924 /* Export policy. */
1925 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1926 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1927 {
1928 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1929 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1930 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1931 }
1932 }
1933
paul718e3742002-12-13 20:15:29 +00001934 peer_group2peer_config_copy (group, peer, afi, safi);
1935
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001936 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001937 {
1938 peer->last_reset = PEER_DOWN_RMAP_BIND;
1939 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1940 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1941 }
paul718e3742002-12-13 20:15:29 +00001942 else
1943 BGP_EVENT_ADD (peer, BGP_Stop);
1944
1945 return 0;
1946}
1947
1948int
1949peer_group_unbind (struct bgp *bgp, struct peer *peer,
1950 struct peer_group *group, afi_t afi, safi_t safi)
1951{
1952 if (! peer->af_group[afi][safi])
1953 return 0;
1954
1955 if (group != peer->group)
1956 return BGP_ERR_PEER_GROUP_MISMATCH;
1957
1958 peer->af_group[afi][safi] = 0;
1959 peer->afc[afi][safi] = 0;
1960 peer_af_flag_reset (peer, afi, safi);
1961
paulfee0f4c2004-09-13 05:12:46 +00001962 if (peer->rib[afi][safi])
1963 peer->rib[afi][safi] = NULL;
1964
paul718e3742002-12-13 20:15:29 +00001965 if (! peer_group_active (peer))
1966 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001967 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001968 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001969 listnode_delete (group->peer, peer);
1970 peer->group = NULL;
1971 if (group->conf->as)
1972 {
1973 peer_delete (peer);
1974 return 0;
1975 }
1976 peer_global_config_reset (peer);
1977 }
1978
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001979 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001980 {
1981 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1982 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1983 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1984 }
paul718e3742002-12-13 20:15:29 +00001985 else
1986 BGP_EVENT_ADD (peer, BGP_Stop);
1987
1988 return 0;
1989}
David Lamparter6b0655a2014-06-04 06:53:35 +02001990
Vipin Kumardd49eb12014-09-30 14:36:38 -07001991
1992static int
1993bgp_startup_timer_expire (struct thread *thread)
1994{
1995 struct bgp *bgp;
1996
1997 bgp = THREAD_ARG (thread);
1998 bgp->t_startup = NULL;
1999
2000 return 0;
2001}
2002
paul718e3742002-12-13 20:15:29 +00002003/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00002004static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002005bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002006{
2007 struct bgp *bgp;
2008 afi_t afi;
2009 safi_t safi;
2010
paul200df112005-06-01 11:17:05 +00002011 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
2012 return NULL;
2013
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002014 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00002015 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00002016 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00002017
2018 bgp->peer = list_new ();
2019 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
2020
2021 bgp->group = list_new ();
2022 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
2023
paulfee0f4c2004-09-13 05:12:46 +00002024 bgp->rsclient = list_new ();
2025 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
2026
paul718e3742002-12-13 20:15:29 +00002027 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2028 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2029 {
Paul Jakma64e580a2006-02-21 01:09:01 +00002030 bgp->route[afi][safi] = bgp_table_init (afi, safi);
2031 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
2032 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07002033 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
2034 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00002035 }
2036
2037 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
2038 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
2039 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00002040 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
2041 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07002042 bgp_flag_set (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES);
paul718e3742002-12-13 20:15:29 +00002043
2044 bgp->as = *as;
2045
2046 if (name)
2047 bgp->name = strdup (name);
2048
Donald Sharp774914f2015-10-14 08:50:39 -04002049 THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire,
Vipin Kumardd49eb12014-09-30 14:36:38 -07002050 bgp, bgp->restart_time);
2051
paul718e3742002-12-13 20:15:29 +00002052 return bgp;
2053}
2054
2055/* Return first entry of BGP. */
2056struct bgp *
paul94f2b392005-06-28 12:44:16 +00002057bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00002058{
Lou Berger056f3762013-04-10 12:30:04 -07002059 if (bm && bm->bgp && bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00002060 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00002061 return NULL;
2062}
2063
2064/* Lookup BGP entry. */
2065struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002066bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00002067{
2068 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002069 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002070
paul1eb8ef22005-04-07 07:30:20 +00002071 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002072 if (bgp->as == as
2073 && ((bgp->name == NULL && name == NULL)
2074 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
2075 return bgp;
2076 return NULL;
2077}
2078
2079/* Lookup BGP structure by view name. */
2080struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002081bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002082{
2083 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002084 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002085
paul1eb8ef22005-04-07 07:30:20 +00002086 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002087 if ((bgp->name == NULL && name == NULL)
2088 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2089 return bgp;
2090 return NULL;
2091}
2092
2093/* Called from VTY commands. */
2094int
paulfd79ac92004-10-13 05:06:08 +00002095bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002096{
2097 struct bgp *bgp;
2098
2099 /* Multiple instance check. */
2100 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2101 {
2102 if (name)
2103 bgp = bgp_lookup_by_name (name);
2104 else
2105 bgp = bgp_get_default ();
2106
2107 /* Already exists. */
2108 if (bgp)
2109 {
2110 if (bgp->as != *as)
2111 {
2112 *as = bgp->as;
2113 return BGP_ERR_INSTANCE_MISMATCH;
2114 }
2115 *bgp_val = bgp;
2116 return 0;
2117 }
2118 }
2119 else
2120 {
2121 /* BGP instance name can not be specified for single instance. */
2122 if (name)
2123 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2124
2125 /* Get default BGP structure if exists. */
2126 bgp = bgp_get_default ();
2127
2128 if (bgp)
2129 {
2130 if (bgp->as != *as)
2131 {
2132 *as = bgp->as;
2133 return BGP_ERR_AS_MISMATCH;
2134 }
2135 *bgp_val = bgp;
2136 return 0;
2137 }
2138 }
2139
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002140 bgp = bgp_create (as, name);
2141 bgp_router_id_set(bgp, &router_id_zebra);
2142 *bgp_val = bgp;
2143
Paul Jakmaad12dde2012-06-13 22:50:07 +01002144 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002145 if (list_isempty(bm->bgp)
2146 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002147 {
2148 if (bgp_socket (bm->port, bm->address) < 0)
2149 return BGP_ERR_INVALID_VALUE;
2150 }
2151
paul718e3742002-12-13 20:15:29 +00002152 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002153
2154 return 0;
2155}
2156
2157/* Delete BGP instance. */
2158int
2159bgp_delete (struct bgp *bgp)
2160{
2161 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002162 struct peer_group *group;
Denil Vira57cd5e72015-08-10 12:46:14 -07002163 struct listnode *node, *pnode;
2164 struct listnode *next, *pnext;
paul718e3742002-12-13 20:15:29 +00002165 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002166 int i;
2167
David Lampartercffe7802014-12-07 03:27:13 +01002168 THREAD_OFF (bgp->t_startup);
2169
paul718e3742002-12-13 20:15:29 +00002170 /* Delete static route. */
2171 bgp_static_delete (bgp);
2172
2173 /* Unset redistribution. */
2174 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2175 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2176 if (i != ZEBRA_ROUTE_BGP)
2177 bgp_redistribute_unset (bgp, afi, i);
2178
paul1eb8ef22005-04-07 07:30:20 +00002179 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002180 {
2181 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2182 {
2183 /* Send notify to remote peer. */
2184 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2185 }
2186
2187 peer_delete (peer);
2188 }
paul718e3742002-12-13 20:15:29 +00002189
Chris Caputo228da422009-07-18 05:44:03 +00002190 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002191 {
Denil Vira57cd5e72015-08-10 12:46:14 -07002192 for (ALL_LIST_ELEMENTS (group->peer, pnode, pnext, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002193 {
2194 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2195 {
2196 /* Send notify to remote peer. */
2197 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2198 }
2199 }
2200 peer_group_delete (group);
2201 }
Chris Caputo228da422009-07-18 05:44:03 +00002202
2203 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002204
2205 if (bgp->peer_self) {
2206 peer_delete(bgp->peer_self);
2207 bgp->peer_self = NULL;
2208 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002209
2210 /* Remove visibility via the master list - there may however still be
2211 * routes to be processed still referencing the struct bgp.
2212 */
2213 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002214 if (list_isempty(bm->bgp))
2215 bgp_close ();
2216
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002217 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002218
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002219 return 0;
2220}
2221
2222static void bgp_free (struct bgp *);
2223
2224void
2225bgp_lock (struct bgp *bgp)
2226{
2227 ++bgp->lock;
2228}
2229
2230void
2231bgp_unlock(struct bgp *bgp)
2232{
Chris Caputo228da422009-07-18 05:44:03 +00002233 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002234 if (--bgp->lock == 0)
2235 bgp_free (bgp);
2236}
2237
2238static void
2239bgp_free (struct bgp *bgp)
2240{
2241 afi_t afi;
2242 safi_t safi;
2243
2244 list_delete (bgp->group);
2245 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002246 list_delete (bgp->rsclient);
2247
paul718e3742002-12-13 20:15:29 +00002248 if (bgp->name)
2249 free (bgp->name);
2250
2251 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2252 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2253 {
2254 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002255 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002256 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002257 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002258 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002259 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002260 }
2261 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002262}
David Lamparter6b0655a2014-06-04 06:53:35 +02002263
paul718e3742002-12-13 20:15:29 +00002264struct peer *
2265peer_lookup (struct bgp *bgp, union sockunion *su)
2266{
2267 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002268 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002269
Steve Hillfc4dc592009-07-28 17:54:35 +01002270 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002271 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002272 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2273 if (sockunion_same (&peer->su, su)
2274 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2275 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002276 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002277 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002278 {
2279 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002280
Paul Jakma2158ad22009-07-28 18:10:55 +01002281 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2282 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2283 if (sockunion_same (&peer->su, su)
2284 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2285 return peer;
paul718e3742002-12-13 20:15:29 +00002286 }
2287 return NULL;
2288}
2289
2290struct peer *
2291peer_lookup_with_open (union sockunion *su, as_t remote_as,
2292 struct in_addr *remote_id, int *as)
2293{
2294 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002295 struct listnode *node;
2296 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002297 struct bgp *bgp;
2298
Steve Hillfc4dc592009-07-28 17:54:35 +01002299 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002300 return NULL;
2301
Paul Jakma9d878772009-08-05 16:25:16 +01002302 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002303 {
Paul Jakma9d878772009-08-05 16:25:16 +01002304 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2305 {
2306 if (sockunion_same (&peer->su, su)
2307 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2308 {
2309 if (peer->as == remote_as
2310 && peer->remote_id.s_addr == remote_id->s_addr)
2311 return peer;
2312 if (peer->as == remote_as)
2313 *as = 1;
2314 }
2315 }
2316
2317 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2318 {
2319 if (sockunion_same (&peer->su, su)
2320 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2321 {
2322 if (peer->as == remote_as
2323 && peer->remote_id.s_addr == 0)
2324 return peer;
2325 if (peer->as == remote_as)
2326 *as = 1;
2327 }
2328 }
paul718e3742002-12-13 20:15:29 +00002329 }
2330 return NULL;
2331}
David Lamparter6b0655a2014-06-04 06:53:35 +02002332
paul718e3742002-12-13 20:15:29 +00002333/* If peer is configured at least one address family return 1. */
2334int
2335peer_active (struct peer *peer)
2336{
2337 if (peer->afc[AFI_IP][SAFI_UNICAST]
2338 || peer->afc[AFI_IP][SAFI_MULTICAST]
2339 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2340 || peer->afc[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05002341 || peer->afc[AFI_IP6][SAFI_MULTICAST]
2342 || peer->afc[AFI_IP6][SAFI_MPLS_VPN])
paul718e3742002-12-13 20:15:29 +00002343 return 1;
2344 return 0;
2345}
2346
2347/* If peer is negotiated at least one address family return 1. */
2348int
2349peer_active_nego (struct peer *peer)
2350{
2351 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2352 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2353 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2354 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
Lou Berger9da04bc2016-01-12 13:41:55 -05002355 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
2356 || peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN])
paul718e3742002-12-13 20:15:29 +00002357 return 1;
2358 return 0;
2359}
David Lamparter6b0655a2014-06-04 06:53:35 +02002360
paul718e3742002-12-13 20:15:29 +00002361/* peer_flag_change_type. */
2362enum peer_change_type
2363{
2364 peer_change_none,
2365 peer_change_reset,
2366 peer_change_reset_in,
2367 peer_change_reset_out,
2368};
2369
paul94f2b392005-06-28 12:44:16 +00002370static void
paul718e3742002-12-13 20:15:29 +00002371peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2372 enum peer_change_type type)
2373{
2374 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2375 return;
2376
Stephen Hemmingerd9d4ae52010-01-13 00:32:39 +00002377 if (peer->status != Established)
2378 return;
2379
paul718e3742002-12-13 20:15:29 +00002380 if (type == peer_change_reset)
2381 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2382 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2383 else if (type == peer_change_reset_in)
2384 {
2385 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2386 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2387 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2388 else
2389 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2390 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2391 }
2392 else if (type == peer_change_reset_out)
2393 bgp_announce_route (peer, afi, safi);
2394}
2395
2396struct peer_flag_action
2397{
2398 /* Peer's flag. */
2399 u_int32_t flag;
2400
2401 /* This flag can be set for peer-group member. */
2402 u_char not_for_member;
2403
2404 /* Action when the flag is changed. */
2405 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002406
2407 /* Peer down cause */
2408 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002409};
2410
Stephen Hemminger03621952009-07-21 16:27:20 -07002411static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002412 {
2413 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2414 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2415 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2416 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2417 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002418 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002419 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002420 { 0, 0, 0 }
2421 };
2422
Stephen Hemminger03621952009-07-21 16:27:20 -07002423static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002424 {
2425 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2426 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2427 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2428 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2429 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2430 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2431 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2432 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2433 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2434 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2435 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2436 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2437 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002438 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
Timo Teräs9e7a53c2014-04-24 10:22:37 +03002439 { PEER_FLAG_NEXTHOP_SELF_ALL, 1, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002440 { 0, 0, 0 }
2441 };
2442
2443/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002444static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002445peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002446 struct peer_flag_action *action, u_int32_t flag)
2447{
2448 int i;
2449 int found = 0;
2450 int reset_in = 0;
2451 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002452 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002453
2454 /* Check peer's frag action. */
2455 for (i = 0; i < size; i++)
2456 {
2457 match = &action_list[i];
2458
2459 if (match->flag == 0)
2460 break;
2461
2462 if (match->flag & flag)
2463 {
2464 found = 1;
2465
2466 if (match->type == peer_change_reset_in)
2467 reset_in = 1;
2468 if (match->type == peer_change_reset_out)
2469 reset_out = 1;
2470 if (match->type == peer_change_reset)
2471 {
2472 reset_in = 1;
2473 reset_out = 1;
2474 }
2475 if (match->not_for_member)
2476 action->not_for_member = 1;
2477 }
2478 }
2479
2480 /* Set peer clear type. */
2481 if (reset_in && reset_out)
2482 action->type = peer_change_reset;
2483 else if (reset_in)
2484 action->type = peer_change_reset_in;
2485 else if (reset_out)
2486 action->type = peer_change_reset_out;
2487 else
2488 action->type = peer_change_none;
2489
2490 return found;
2491}
2492
paul94f2b392005-06-28 12:44:16 +00002493static void
paul718e3742002-12-13 20:15:29 +00002494peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2495{
2496 if (flag == PEER_FLAG_SHUTDOWN)
2497 {
2498 if (CHECK_FLAG (peer->flags, flag))
2499 {
hasso93406d82005-02-02 14:40:33 +00002500 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2501 peer_nsf_stop (peer);
2502
hasso0a486e52005-02-01 20:57:17 +00002503 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2504 if (peer->t_pmax_restart)
2505 {
2506 BGP_TIMER_OFF (peer->t_pmax_restart);
2507 if (BGP_DEBUG (events, EVENTS))
2508 zlog_debug ("%s Maximum-prefix restart timer canceled",
2509 peer->host);
2510 }
2511
hasso93406d82005-02-02 14:40:33 +00002512 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2513 peer_nsf_stop (peer);
2514
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002515 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002516 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2517 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2518 else
2519 BGP_EVENT_ADD (peer, BGP_Stop);
2520 }
2521 else
2522 {
2523 peer->v_start = BGP_INIT_START_TIMER;
2524 BGP_EVENT_ADD (peer, BGP_Stop);
2525 }
2526 }
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002527 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002528 {
hassoc9502432005-02-01 22:01:48 +00002529 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2530 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2531 else if (flag == PEER_FLAG_PASSIVE)
2532 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002533 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002534 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002535
hassoc9502432005-02-01 22:01:48 +00002536 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2537 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002538 }
2539 else
2540 BGP_EVENT_ADD (peer, BGP_Stop);
2541}
2542
2543/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002544static int
paul718e3742002-12-13 20:15:29 +00002545peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2546{
2547 int found;
2548 int size;
2549 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002550 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002551 struct peer_flag_action action;
2552
2553 memset (&action, 0, sizeof (struct peer_flag_action));
2554 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2555
2556 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2557
2558 /* No flag action is found. */
2559 if (! found)
2560 return BGP_ERR_INVALID_FLAG;
2561
2562 /* Not for peer-group member. */
2563 if (action.not_for_member && peer_group_active (peer))
2564 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2565
2566 /* When unset the peer-group member's flag we have to check
2567 peer-group configuration. */
2568 if (! set && peer_group_active (peer))
2569 if (CHECK_FLAG (peer->group->conf->flags, flag))
2570 {
2571 if (flag == PEER_FLAG_SHUTDOWN)
2572 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2573 else
2574 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2575 }
2576
2577 /* Flag conflict check. */
2578 if (set
2579 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2580 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2581 return BGP_ERR_PEER_FLAG_CONFLICT;
2582
2583 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2584 {
2585 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2586 return 0;
2587 if (! set && ! CHECK_FLAG (peer->flags, flag))
2588 return 0;
2589 }
2590
2591 if (set)
2592 SET_FLAG (peer->flags, flag);
2593 else
2594 UNSET_FLAG (peer->flags, flag);
2595
2596 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2597 {
2598 if (action.type == peer_change_reset)
2599 peer_flag_modify_action (peer, flag);
2600
2601 return 0;
2602 }
2603
2604 /* peer-group member updates. */
2605 group = peer->group;
2606
paul1eb8ef22005-04-07 07:30:20 +00002607 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002608 {
2609 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2610 continue;
2611
2612 if (! set && ! CHECK_FLAG (peer->flags, flag))
2613 continue;
2614
2615 if (set)
2616 SET_FLAG (peer->flags, flag);
2617 else
2618 UNSET_FLAG (peer->flags, flag);
2619
2620 if (action.type == peer_change_reset)
2621 peer_flag_modify_action (peer, flag);
2622 }
2623 return 0;
2624}
2625
2626int
2627peer_flag_set (struct peer *peer, u_int32_t flag)
2628{
2629 return peer_flag_modify (peer, flag, 1);
2630}
2631
2632int
2633peer_flag_unset (struct peer *peer, u_int32_t flag)
2634{
2635 return peer_flag_modify (peer, flag, 0);
2636}
2637
paul94f2b392005-06-28 12:44:16 +00002638static int
paul718e3742002-12-13 20:15:29 +00002639peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2640{
2641 if (peer->af_group[afi][safi])
2642 return 1;
2643 return 0;
2644}
2645
paul94f2b392005-06-28 12:44:16 +00002646static int
paul718e3742002-12-13 20:15:29 +00002647peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2648 int set)
2649{
2650 int found;
2651 int size;
paul1eb8ef22005-04-07 07:30:20 +00002652 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002653 struct peer_group *group;
2654 struct peer_flag_action action;
2655
2656 memset (&action, 0, sizeof (struct peer_flag_action));
2657 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2658
2659 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2660
2661 /* No flag action is found. */
2662 if (! found)
2663 return BGP_ERR_INVALID_FLAG;
2664
2665 /* Adress family must be activated. */
2666 if (! peer->afc[afi][safi])
2667 return BGP_ERR_PEER_INACTIVE;
2668
2669 /* Not for peer-group member. */
2670 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2671 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2672
2673 /* Spcecial check for reflector client. */
2674 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2675 && peer_sort (peer) != BGP_PEER_IBGP)
2676 return BGP_ERR_NOT_INTERNAL_PEER;
2677
2678 /* Spcecial check for remove-private-AS. */
2679 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2680 && peer_sort (peer) == BGP_PEER_IBGP)
2681 return BGP_ERR_REMOVE_PRIVATE_AS;
2682
2683 /* When unset the peer-group member's flag we have to check
2684 peer-group configuration. */
2685 if (! set && peer->af_group[afi][safi])
2686 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2687 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2688
2689 /* When current flag configuration is same as requested one. */
2690 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2691 {
2692 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2693 return 0;
2694 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2695 return 0;
2696 }
2697
2698 if (set)
2699 SET_FLAG (peer->af_flags[afi][safi], flag);
2700 else
2701 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2702
2703 /* Execute action when peer is established. */
2704 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2705 && peer->status == Established)
2706 {
2707 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2708 bgp_clear_adj_in (peer, afi, safi);
2709 else
hassoe0701b72004-05-20 09:19:34 +00002710 {
2711 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2712 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2713 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2714 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2715 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2716 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2717 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2718 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2719
2720 peer_change_action (peer, afi, safi, action.type);
2721 }
2722
paul718e3742002-12-13 20:15:29 +00002723 }
2724
2725 /* Peer group member updates. */
2726 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2727 {
2728 group = peer->group;
2729
paul1eb8ef22005-04-07 07:30:20 +00002730 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002731 {
2732 if (! peer->af_group[afi][safi])
2733 continue;
2734
2735 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2736 continue;
2737
2738 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2739 continue;
2740
2741 if (set)
2742 SET_FLAG (peer->af_flags[afi][safi], flag);
2743 else
2744 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2745
2746 if (peer->status == Established)
2747 {
2748 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2749 bgp_clear_adj_in (peer, afi, safi);
2750 else
hassoe0701b72004-05-20 09:19:34 +00002751 {
2752 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2753 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2754 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2755 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2756 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2757 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2758 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2759 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2760
2761 peer_change_action (peer, afi, safi, action.type);
2762 }
paul718e3742002-12-13 20:15:29 +00002763 }
2764 }
2765 }
2766 return 0;
2767}
2768
2769int
2770peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2771{
2772 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2773}
2774
2775int
2776peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2777{
2778 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2779}
David Lamparter6b0655a2014-06-04 06:53:35 +02002780
paul718e3742002-12-13 20:15:29 +00002781/* EBGP multihop configuration. */
2782int
2783peer_ebgp_multihop_set (struct peer *peer, int ttl)
2784{
2785 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002786 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002787 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002788
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002789 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002790 return 0;
2791
Nick Hilliardfa411a22011-03-23 15:33:17 +00002792 /* see comment in peer_ttl_security_hops_set() */
2793 if (ttl != MAXTTL)
2794 {
2795 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2796 {
2797 group = peer->group;
2798 if (group->conf->gtsm_hops != 0)
2799 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2800
2801 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2802 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002803 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002804 continue;
2805
2806 if (peer1->gtsm_hops != 0)
2807 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2808 }
2809 }
2810 else
2811 {
2812 if (peer->gtsm_hops != 0)
2813 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2814 }
2815 }
2816
paul718e3742002-12-13 20:15:29 +00002817 peer->ttl = ttl;
2818
2819 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2820 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002821 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002822 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002823 }
2824 else
2825 {
2826 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002827 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002828 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002829 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002830 continue;
paul718e3742002-12-13 20:15:29 +00002831
pauleb821182004-05-01 08:44:08 +00002832 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002833
pauleb821182004-05-01 08:44:08 +00002834 if (peer->fd >= 0)
2835 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2836 }
paul718e3742002-12-13 20:15:29 +00002837 }
2838 return 0;
2839}
2840
2841int
2842peer_ebgp_multihop_unset (struct peer *peer)
2843{
2844 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002845 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002846
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002847 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002848 return 0;
2849
Nick Hilliardfa411a22011-03-23 15:33:17 +00002850 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2851 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2852
paul718e3742002-12-13 20:15:29 +00002853 if (peer_group_active (peer))
2854 peer->ttl = peer->group->conf->ttl;
2855 else
2856 peer->ttl = 1;
2857
2858 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2859 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002860 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002861 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002862 }
2863 else
2864 {
2865 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002866 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002867 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002868 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002869 continue;
paul718e3742002-12-13 20:15:29 +00002870
pauleb821182004-05-01 08:44:08 +00002871 peer->ttl = 1;
2872
2873 if (peer->fd >= 0)
2874 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2875 }
paul718e3742002-12-13 20:15:29 +00002876 }
2877 return 0;
2878}
David Lamparter6b0655a2014-06-04 06:53:35 +02002879
paul718e3742002-12-13 20:15:29 +00002880/* Neighbor description. */
2881int
2882peer_description_set (struct peer *peer, char *desc)
2883{
2884 if (peer->desc)
2885 XFREE (MTYPE_PEER_DESC, peer->desc);
2886
2887 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2888
2889 return 0;
2890}
2891
2892int
2893peer_description_unset (struct peer *peer)
2894{
2895 if (peer->desc)
2896 XFREE (MTYPE_PEER_DESC, peer->desc);
2897
2898 peer->desc = NULL;
2899
2900 return 0;
2901}
David Lamparter6b0655a2014-06-04 06:53:35 +02002902
paul718e3742002-12-13 20:15:29 +00002903/* Neighbor update-source. */
2904int
paulfd79ac92004-10-13 05:06:08 +00002905peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002906{
2907 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002908 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002909
2910 if (peer->update_if)
2911 {
2912 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2913 && strcmp (peer->update_if, ifname) == 0)
2914 return 0;
2915
2916 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2917 peer->update_if = NULL;
2918 }
2919
2920 if (peer->update_source)
2921 {
2922 sockunion_free (peer->update_source);
2923 peer->update_source = NULL;
2924 }
2925
2926 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2927
2928 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2929 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002930 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002931 {
2932 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2933 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2934 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2935 }
paul718e3742002-12-13 20:15:29 +00002936 else
2937 BGP_EVENT_ADD (peer, BGP_Stop);
2938 return 0;
2939 }
2940
2941 /* peer-group member updates. */
2942 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002943 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002944 {
2945 if (peer->update_if)
2946 {
2947 if (strcmp (peer->update_if, ifname) == 0)
2948 continue;
2949
2950 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2951 peer->update_if = NULL;
2952 }
2953
2954 if (peer->update_source)
2955 {
2956 sockunion_free (peer->update_source);
2957 peer->update_source = NULL;
2958 }
2959
2960 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2961
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002962 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002963 {
2964 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2965 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2966 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2967 }
paul718e3742002-12-13 20:15:29 +00002968 else
2969 BGP_EVENT_ADD (peer, BGP_Stop);
2970 }
2971 return 0;
2972}
2973
2974int
2975peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2976{
2977 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002978 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002979
2980 if (peer->update_source)
2981 {
2982 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2983 && sockunion_cmp (peer->update_source, su) == 0)
2984 return 0;
2985 sockunion_free (peer->update_source);
2986 peer->update_source = NULL;
2987 }
2988
2989 if (peer->update_if)
2990 {
2991 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2992 peer->update_if = NULL;
2993 }
2994
2995 peer->update_source = sockunion_dup (su);
2996
2997 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2998 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002999 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003000 {
3001 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3002 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3003 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3004 }
paul718e3742002-12-13 20:15:29 +00003005 else
3006 BGP_EVENT_ADD (peer, BGP_Stop);
3007 return 0;
3008 }
3009
3010 /* peer-group member updates. */
3011 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003012 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003013 {
3014 if (peer->update_source)
3015 {
3016 if (sockunion_cmp (peer->update_source, su) == 0)
3017 continue;
3018 sockunion_free (peer->update_source);
3019 peer->update_source = NULL;
3020 }
3021
3022 if (peer->update_if)
3023 {
3024 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3025 peer->update_if = NULL;
3026 }
3027
3028 peer->update_source = sockunion_dup (su);
3029
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003030 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003031 {
3032 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3033 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3034 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3035 }
paul718e3742002-12-13 20:15:29 +00003036 else
3037 BGP_EVENT_ADD (peer, BGP_Stop);
3038 }
3039 return 0;
3040}
3041
3042int
3043peer_update_source_unset (struct peer *peer)
3044{
3045 union sockunion *su;
3046 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003047 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003048
3049 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3050 && ! peer->update_source
3051 && ! peer->update_if)
3052 return 0;
3053
3054 if (peer->update_source)
3055 {
3056 sockunion_free (peer->update_source);
3057 peer->update_source = NULL;
3058 }
3059 if (peer->update_if)
3060 {
3061 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3062 peer->update_if = NULL;
3063 }
3064
3065 if (peer_group_active (peer))
3066 {
3067 group = peer->group;
3068
3069 if (group->conf->update_source)
3070 {
3071 su = sockunion_dup (group->conf->update_source);
3072 peer->update_source = su;
3073 }
3074 else if (group->conf->update_if)
3075 peer->update_if =
3076 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
3077 }
3078
3079 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3080 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003081 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003082 {
3083 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3084 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3085 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3086 }
paul718e3742002-12-13 20:15:29 +00003087 else
3088 BGP_EVENT_ADD (peer, BGP_Stop);
3089 return 0;
3090 }
3091
3092 /* peer-group member updates. */
3093 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003094 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003095 {
3096 if (! peer->update_source && ! peer->update_if)
3097 continue;
3098
3099 if (peer->update_source)
3100 {
3101 sockunion_free (peer->update_source);
3102 peer->update_source = NULL;
3103 }
3104
3105 if (peer->update_if)
3106 {
3107 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3108 peer->update_if = NULL;
3109 }
3110
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003111 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003112 {
3113 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3114 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3115 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3116 }
paul718e3742002-12-13 20:15:29 +00003117 else
3118 BGP_EVENT_ADD (peer, BGP_Stop);
3119 }
3120 return 0;
3121}
David Lamparter6b0655a2014-06-04 06:53:35 +02003122
paul718e3742002-12-13 20:15:29 +00003123int
3124peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003125 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003126{
3127 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003128 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003129
3130 /* Adress family must be activated. */
3131 if (! peer->afc[afi][safi])
3132 return BGP_ERR_PEER_INACTIVE;
3133
3134 /* Default originate can't be used for peer group memeber. */
3135 if (peer_is_group_member (peer, afi, safi))
3136 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3137
3138 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3139 || (rmap && ! peer->default_rmap[afi][safi].name)
3140 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3141 {
3142 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3143
3144 if (rmap)
3145 {
3146 if (peer->default_rmap[afi][safi].name)
3147 free (peer->default_rmap[afi][safi].name);
3148 peer->default_rmap[afi][safi].name = strdup (rmap);
3149 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3150 }
3151 }
3152
3153 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3154 {
3155 if (peer->status == Established && peer->afc_nego[afi][safi])
3156 bgp_default_originate (peer, afi, safi, 0);
3157 return 0;
3158 }
3159
3160 /* peer-group member updates. */
3161 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003162 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003163 {
3164 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3165
3166 if (rmap)
3167 {
3168 if (peer->default_rmap[afi][safi].name)
3169 free (peer->default_rmap[afi][safi].name);
3170 peer->default_rmap[afi][safi].name = strdup (rmap);
3171 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3172 }
3173
3174 if (peer->status == Established && peer->afc_nego[afi][safi])
3175 bgp_default_originate (peer, afi, safi, 0);
3176 }
3177 return 0;
3178}
3179
3180int
3181peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3182{
3183 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003184 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003185
3186 /* Adress family must be activated. */
3187 if (! peer->afc[afi][safi])
3188 return BGP_ERR_PEER_INACTIVE;
3189
3190 /* Default originate can't be used for peer group memeber. */
3191 if (peer_is_group_member (peer, afi, safi))
3192 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3193
3194 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3195 {
3196 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3197
3198 if (peer->default_rmap[afi][safi].name)
3199 free (peer->default_rmap[afi][safi].name);
3200 peer->default_rmap[afi][safi].name = NULL;
3201 peer->default_rmap[afi][safi].map = NULL;
3202 }
3203
3204 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3205 {
3206 if (peer->status == Established && peer->afc_nego[afi][safi])
3207 bgp_default_originate (peer, afi, safi, 1);
3208 return 0;
3209 }
3210
3211 /* peer-group member updates. */
3212 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003213 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003214 {
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 if (peer->status == Established && peer->afc_nego[afi][safi])
3223 bgp_default_originate (peer, afi, safi, 1);
3224 }
3225 return 0;
3226}
David Lamparter6b0655a2014-06-04 06:53:35 +02003227
paul718e3742002-12-13 20:15:29 +00003228int
3229peer_port_set (struct peer *peer, u_int16_t port)
3230{
3231 peer->port = port;
3232 return 0;
3233}
3234
3235int
3236peer_port_unset (struct peer *peer)
3237{
3238 peer->port = BGP_PORT_DEFAULT;
3239 return 0;
3240}
David Lamparter6b0655a2014-06-04 06:53:35 +02003241
paul718e3742002-12-13 20:15:29 +00003242/* neighbor weight. */
3243int
3244peer_weight_set (struct peer *peer, u_int16_t weight)
3245{
3246 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003247 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003248
3249 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3250 peer->weight = weight;
3251
3252 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3253 return 0;
3254
3255 /* peer-group member updates. */
3256 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003257 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003258 {
3259 peer->weight = group->conf->weight;
3260 }
3261 return 0;
3262}
3263
3264int
3265peer_weight_unset (struct peer *peer)
3266{
3267 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003268 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003269
3270 /* Set default weight. */
3271 if (peer_group_active (peer))
3272 peer->weight = peer->group->conf->weight;
3273 else
3274 peer->weight = 0;
3275
3276 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3277
3278 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3279 return 0;
3280
3281 /* peer-group member updates. */
3282 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003283 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003284 {
3285 peer->weight = 0;
3286 }
3287 return 0;
3288}
David Lamparter6b0655a2014-06-04 06:53:35 +02003289
paul718e3742002-12-13 20:15:29 +00003290int
3291peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3292{
3293 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003294 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003295
3296 /* Not for peer group memeber. */
3297 if (peer_group_active (peer))
3298 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3299
3300 /* keepalive value check. */
3301 if (keepalive > 65535)
3302 return BGP_ERR_INVALID_VALUE;
3303
3304 /* Holdtime value check. */
3305 if (holdtime > 65535)
3306 return BGP_ERR_INVALID_VALUE;
3307
3308 /* Holdtime value must be either 0 or greater than 3. */
3309 if (holdtime < 3 && holdtime != 0)
3310 return BGP_ERR_INVALID_VALUE;
3311
3312 /* Set value to the configuration. */
3313 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3314 peer->holdtime = holdtime;
3315 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3316
3317 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3318 return 0;
3319
3320 /* peer-group member updates. */
3321 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003322 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003323 {
3324 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3325 peer->holdtime = group->conf->holdtime;
3326 peer->keepalive = group->conf->keepalive;
3327 }
3328 return 0;
3329}
3330
3331int
3332peer_timers_unset (struct peer *peer)
3333{
3334 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003335 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003336
3337 if (peer_group_active (peer))
3338 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3339
3340 /* Clear configuration. */
3341 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3342 peer->keepalive = 0;
3343 peer->holdtime = 0;
3344
3345 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3346 return 0;
3347
3348 /* peer-group member updates. */
3349 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003350 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003351 {
3352 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3353 peer->holdtime = 0;
3354 peer->keepalive = 0;
3355 }
3356
3357 return 0;
3358}
David Lamparter6b0655a2014-06-04 06:53:35 +02003359
paul718e3742002-12-13 20:15:29 +00003360int
3361peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3362{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003363 struct peer_group *group;
3364 struct listnode *node, *nnode;
3365
paul718e3742002-12-13 20:15:29 +00003366 if (peer_group_active (peer))
3367 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3368
3369 if (connect > 65535)
3370 return BGP_ERR_INVALID_VALUE;
3371
3372 /* Set value to the configuration. */
3373 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3374 peer->connect = connect;
3375
3376 /* Set value to timer setting. */
3377 peer->v_connect = connect;
3378
Daniel Walton0d7435f2015-10-22 11:35:20 +03003379 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3380 return 0;
3381
3382 /* peer-group member updates. */
3383 group = peer->group;
3384 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3385 {
3386 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3387 peer->connect = connect;
3388 peer->v_connect = connect;
3389 }
paul718e3742002-12-13 20:15:29 +00003390 return 0;
3391}
3392
3393int
3394peer_timers_connect_unset (struct peer *peer)
3395{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003396 struct peer_group *group;
3397 struct listnode *node, *nnode;
3398
paul718e3742002-12-13 20:15:29 +00003399 if (peer_group_active (peer))
3400 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3401
3402 /* Clear configuration. */
3403 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3404 peer->connect = 0;
3405
3406 /* Set timer setting to default value. */
3407 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3408
Daniel Walton0d7435f2015-10-22 11:35:20 +03003409 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3410 return 0;
3411
3412 /* peer-group member updates. */
3413 group = peer->group;
3414 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3415 {
3416 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3417 peer->connect = 0;
3418 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3419 }
3420 return 0;
paul718e3742002-12-13 20:15:29 +00003421}
David Lamparter6b0655a2014-06-04 06:53:35 +02003422
paul718e3742002-12-13 20:15:29 +00003423int
3424peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3425{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003426 struct peer_group *group;
3427 struct listnode *node, *nnode;
3428
paul718e3742002-12-13 20:15:29 +00003429 if (peer_group_active (peer))
3430 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3431
3432 if (routeadv > 600)
3433 return BGP_ERR_INVALID_VALUE;
3434
3435 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3436 peer->routeadv = routeadv;
3437 peer->v_routeadv = routeadv;
3438
Daniel Walton0d7435f2015-10-22 11:35:20 +03003439 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3440 return 0;
3441
3442 /* peer-group member updates. */
3443 group = peer->group;
3444 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3445 {
3446 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3447 peer->routeadv = routeadv;
3448 peer->v_routeadv = routeadv;
3449 }
3450
paul718e3742002-12-13 20:15:29 +00003451 return 0;
3452}
3453
3454int
3455peer_advertise_interval_unset (struct peer *peer)
3456{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003457 struct peer_group *group;
3458 struct listnode *node, *nnode;
3459
paul718e3742002-12-13 20:15:29 +00003460 if (peer_group_active (peer))
3461 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3462
3463 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3464 peer->routeadv = 0;
3465
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003466 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003467 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3468 else
3469 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
Daniel Walton0d7435f2015-10-22 11:35:20 +03003470
3471 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3472 return 0;
3473
3474 /* peer-group member updates. */
3475 group = peer->group;
3476 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3477 {
3478 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3479 peer->routeadv = 0;
3480
3481 if (peer->sort == BGP_PEER_IBGP)
3482 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3483 else
3484 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3485 }
paul718e3742002-12-13 20:15:29 +00003486
3487 return 0;
3488}
David Lamparter6b0655a2014-06-04 06:53:35 +02003489
paul718e3742002-12-13 20:15:29 +00003490/* neighbor interface */
3491int
paulfd79ac92004-10-13 05:06:08 +00003492peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003493{
3494 if (peer->ifname)
3495 free (peer->ifname);
3496 peer->ifname = strdup (str);
3497
3498 return 0;
3499}
3500
3501int
3502peer_interface_unset (struct peer *peer)
3503{
3504 if (peer->ifname)
3505 free (peer->ifname);
3506 peer->ifname = NULL;
3507
3508 return 0;
3509}
David Lamparter6b0655a2014-06-04 06:53:35 +02003510
paul718e3742002-12-13 20:15:29 +00003511/* Allow-as in. */
3512int
3513peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3514{
3515 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003516 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003517
3518 if (allow_num < 1 || allow_num > 10)
3519 return BGP_ERR_INVALID_VALUE;
3520
3521 if (peer->allowas_in[afi][safi] != allow_num)
3522 {
3523 peer->allowas_in[afi][safi] = allow_num;
3524 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3525 peer_change_action (peer, afi, safi, peer_change_reset_in);
3526 }
3527
3528 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3529 return 0;
3530
3531 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003532 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003533 {
3534 if (peer->allowas_in[afi][safi] != allow_num)
3535 {
3536 peer->allowas_in[afi][safi] = allow_num;
3537 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3538 peer_change_action (peer, afi, safi, peer_change_reset_in);
3539 }
3540
3541 }
3542 return 0;
3543}
3544
3545int
3546peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3547{
3548 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003549 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003550
3551 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3552 {
3553 peer->allowas_in[afi][safi] = 0;
3554 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3555 }
3556
3557 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3558 return 0;
3559
3560 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003561 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003562 {
3563 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3564 {
3565 peer->allowas_in[afi][safi] = 0;
3566 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3567 }
3568 }
3569 return 0;
3570}
David Lamparter6b0655a2014-06-04 06:53:35 +02003571
paul718e3742002-12-13 20:15:29 +00003572int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003573peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003574{
3575 struct bgp *bgp = peer->bgp;
3576 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003577 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003578
3579 if (peer_sort (peer) != BGP_PEER_EBGP
3580 && peer_sort (peer) != BGP_PEER_INTERNAL)
3581 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3582
3583 if (bgp->as == as)
3584 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3585
3586 if (peer_group_active (peer))
3587 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3588
Andrew Certain9d3f9702012-11-07 23:50:07 +00003589 if (peer->as == as)
3590 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3591
paul718e3742002-12-13 20:15:29 +00003592 if (peer->change_local_as == as &&
3593 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003594 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3595 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3596 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003597 return 0;
3598
3599 peer->change_local_as = as;
3600 if (no_prepend)
3601 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3602 else
3603 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3604
Andrew Certain9d3f9702012-11-07 23:50:07 +00003605 if (replace_as)
3606 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3607 else
3608 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3609
paul718e3742002-12-13 20:15:29 +00003610 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3611 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003612 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003613 {
3614 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3615 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3616 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3617 }
paul718e3742002-12-13 20:15:29 +00003618 else
3619 BGP_EVENT_ADD (peer, BGP_Stop);
3620
3621 return 0;
3622 }
3623
3624 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003625 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003626 {
3627 peer->change_local_as = as;
3628 if (no_prepend)
3629 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3630 else
3631 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3632
Andrew Certain9d3f9702012-11-07 23:50:07 +00003633 if (replace_as)
3634 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3635 else
3636 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3637
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003638 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003639 {
3640 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3641 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3642 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3643 }
paul718e3742002-12-13 20:15:29 +00003644 else
3645 BGP_EVENT_ADD (peer, BGP_Stop);
3646 }
3647
3648 return 0;
3649}
3650
3651int
3652peer_local_as_unset (struct peer *peer)
3653{
3654 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003655 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003656
3657 if (peer_group_active (peer))
3658 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3659
3660 if (! peer->change_local_as)
3661 return 0;
3662
3663 peer->change_local_as = 0;
3664 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003665 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003666
3667 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3668 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003669 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003670 {
3671 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3672 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3673 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3674 }
paul718e3742002-12-13 20:15:29 +00003675 else
3676 BGP_EVENT_ADD (peer, BGP_Stop);
3677
3678 return 0;
3679 }
3680
3681 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003682 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003683 {
3684 peer->change_local_as = 0;
3685 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003686 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003687
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}
David Lamparter6b0655a2014-06-04 06:53:35 +02003699
Paul Jakma0df7c912008-07-21 21:02:49 +00003700/* Set password for authenticating with the peer. */
3701int
3702peer_password_set (struct peer *peer, const char *password)
3703{
3704 struct listnode *nn, *nnode;
3705 int len = password ? strlen(password) : 0;
3706 int ret = BGP_SUCCESS;
3707
3708 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3709 return BGP_ERR_INVALID_VALUE;
3710
3711 if (peer->password && strcmp (peer->password, password) == 0
3712 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3713 return 0;
3714
3715 if (peer->password)
3716 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3717
3718 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3719
3720 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3721 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003722 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3723 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
Paul Jakma0df7c912008-07-21 21:02:49 +00003724 else
3725 BGP_EVENT_ADD (peer, BGP_Stop);
3726
3727 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3728 }
3729
3730 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3731 {
3732 if (peer->password && strcmp (peer->password, password) == 0)
3733 continue;
3734
3735 if (peer->password)
3736 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3737
3738 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3739
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003740 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003741 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3742 else
3743 BGP_EVENT_ADD (peer, BGP_Stop);
3744
3745 if (bgp_md5_set (peer) < 0)
3746 ret = BGP_ERR_TCPSIG_FAILED;
3747 }
3748
3749 return ret;
3750}
3751
3752int
3753peer_password_unset (struct peer *peer)
3754{
3755 struct listnode *nn, *nnode;
3756
3757 if (!peer->password
3758 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3759 return 0;
3760
3761 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3762 {
3763 if (peer_group_active (peer)
3764 && peer->group->conf->password
3765 && strcmp (peer->group->conf->password, peer->password) == 0)
3766 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3767
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003768 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003769 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3770 else
3771 BGP_EVENT_ADD (peer, BGP_Stop);
3772
3773 if (peer->password)
3774 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3775
3776 peer->password = NULL;
3777
3778 bgp_md5_set (peer);
3779
3780 return 0;
3781 }
3782
3783 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3784 peer->password = NULL;
3785
3786 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3787 {
3788 if (!peer->password)
3789 continue;
3790
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003791 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003792 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3793 else
3794 BGP_EVENT_ADD (peer, BGP_Stop);
3795
3796 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3797 peer->password = NULL;
3798
3799 bgp_md5_set (peer);
3800 }
3801
3802 return 0;
3803}
David Lamparter6b0655a2014-06-04 06:53:35 +02003804
paul718e3742002-12-13 20:15:29 +00003805/* Set distribute list to the peer. */
3806int
3807peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003808 const char *name)
paul718e3742002-12-13 20:15:29 +00003809{
3810 struct bgp_filter *filter;
3811 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003812 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003813
3814 if (! peer->afc[afi][safi])
3815 return BGP_ERR_PEER_INACTIVE;
3816
3817 if (direct != FILTER_IN && direct != FILTER_OUT)
3818 return BGP_ERR_INVALID_VALUE;
3819
3820 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3821 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3822
3823 filter = &peer->filter[afi][safi];
3824
3825 if (filter->plist[direct].name)
3826 return BGP_ERR_PEER_FILTER_CONFLICT;
3827
3828 if (filter->dlist[direct].name)
3829 free (filter->dlist[direct].name);
3830 filter->dlist[direct].name = strdup (name);
3831 filter->dlist[direct].alist = access_list_lookup (afi, name);
3832
3833 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3834 return 0;
3835
3836 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003837 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003838 {
3839 filter = &peer->filter[afi][safi];
3840
3841 if (! peer->af_group[afi][safi])
3842 continue;
3843
3844 if (filter->dlist[direct].name)
3845 free (filter->dlist[direct].name);
3846 filter->dlist[direct].name = strdup (name);
3847 filter->dlist[direct].alist = access_list_lookup (afi, name);
3848 }
3849
3850 return 0;
3851}
3852
3853int
3854peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3855{
3856 struct bgp_filter *filter;
3857 struct bgp_filter *gfilter;
3858 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003859 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003860
3861 if (! peer->afc[afi][safi])
3862 return BGP_ERR_PEER_INACTIVE;
3863
3864 if (direct != FILTER_IN && direct != FILTER_OUT)
3865 return BGP_ERR_INVALID_VALUE;
3866
3867 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3868 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3869
3870 filter = &peer->filter[afi][safi];
3871
3872 /* apply peer-group filter */
3873 if (peer->af_group[afi][safi])
3874 {
3875 gfilter = &peer->group->conf->filter[afi][safi];
3876
3877 if (gfilter->dlist[direct].name)
3878 {
3879 if (filter->dlist[direct].name)
3880 free (filter->dlist[direct].name);
3881 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3882 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3883 return 0;
3884 }
3885 }
3886
3887 if (filter->dlist[direct].name)
3888 free (filter->dlist[direct].name);
3889 filter->dlist[direct].name = NULL;
3890 filter->dlist[direct].alist = NULL;
3891
3892 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3893 return 0;
3894
3895 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003896 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003897 {
3898 filter = &peer->filter[afi][safi];
3899
3900 if (! peer->af_group[afi][safi])
3901 continue;
3902
3903 if (filter->dlist[direct].name)
3904 free (filter->dlist[direct].name);
3905 filter->dlist[direct].name = NULL;
3906 filter->dlist[direct].alist = NULL;
3907 }
3908
3909 return 0;
3910}
3911
3912/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003913static void
paul718e3742002-12-13 20:15:29 +00003914peer_distribute_update (struct access_list *access)
3915{
3916 afi_t afi;
3917 safi_t safi;
3918 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003919 struct listnode *mnode, *mnnode;
3920 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003921 struct bgp *bgp;
3922 struct peer *peer;
3923 struct peer_group *group;
3924 struct bgp_filter *filter;
3925
paul1eb8ef22005-04-07 07:30:20 +00003926 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003927 {
paul1eb8ef22005-04-07 07:30:20 +00003928 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003929 {
3930 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3931 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3932 {
3933 filter = &peer->filter[afi][safi];
3934
3935 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3936 {
3937 if (filter->dlist[direct].name)
3938 filter->dlist[direct].alist =
3939 access_list_lookup (afi, filter->dlist[direct].name);
3940 else
3941 filter->dlist[direct].alist = NULL;
3942 }
3943 }
3944 }
paul1eb8ef22005-04-07 07:30:20 +00003945 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003946 {
3947 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3948 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3949 {
3950 filter = &group->conf->filter[afi][safi];
3951
3952 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3953 {
3954 if (filter->dlist[direct].name)
3955 filter->dlist[direct].alist =
3956 access_list_lookup (afi, filter->dlist[direct].name);
3957 else
3958 filter->dlist[direct].alist = NULL;
3959 }
3960 }
3961 }
3962 }
3963}
David Lamparter6b0655a2014-06-04 06:53:35 +02003964
paul718e3742002-12-13 20:15:29 +00003965/* Set prefix list to the peer. */
3966int
3967peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003968 const char *name)
paul718e3742002-12-13 20:15:29 +00003969{
3970 struct bgp_filter *filter;
3971 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003972 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003973
3974 if (! peer->afc[afi][safi])
3975 return BGP_ERR_PEER_INACTIVE;
3976
3977 if (direct != FILTER_IN && direct != FILTER_OUT)
3978 return BGP_ERR_INVALID_VALUE;
3979
3980 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3981 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3982
3983 filter = &peer->filter[afi][safi];
3984
3985 if (filter->dlist[direct].name)
3986 return BGP_ERR_PEER_FILTER_CONFLICT;
3987
3988 if (filter->plist[direct].name)
3989 free (filter->plist[direct].name);
3990 filter->plist[direct].name = strdup (name);
3991 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3992
3993 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3994 return 0;
3995
3996 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003997 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003998 {
3999 filter = &peer->filter[afi][safi];
4000
4001 if (! peer->af_group[afi][safi])
4002 continue;
4003
4004 if (filter->plist[direct].name)
4005 free (filter->plist[direct].name);
4006 filter->plist[direct].name = strdup (name);
4007 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4008 }
4009 return 0;
4010}
4011
4012int
4013peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4014{
4015 struct bgp_filter *filter;
4016 struct bgp_filter *gfilter;
4017 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004018 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004019
4020 if (! peer->afc[afi][safi])
4021 return BGP_ERR_PEER_INACTIVE;
4022
4023 if (direct != FILTER_IN && direct != FILTER_OUT)
4024 return BGP_ERR_INVALID_VALUE;
4025
4026 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4027 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4028
4029 filter = &peer->filter[afi][safi];
4030
4031 /* apply peer-group filter */
4032 if (peer->af_group[afi][safi])
4033 {
4034 gfilter = &peer->group->conf->filter[afi][safi];
4035
4036 if (gfilter->plist[direct].name)
4037 {
4038 if (filter->plist[direct].name)
4039 free (filter->plist[direct].name);
4040 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
4041 filter->plist[direct].plist = gfilter->plist[direct].plist;
4042 return 0;
4043 }
4044 }
4045
4046 if (filter->plist[direct].name)
4047 free (filter->plist[direct].name);
4048 filter->plist[direct].name = NULL;
4049 filter->plist[direct].plist = NULL;
4050
4051 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4052 return 0;
4053
4054 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004055 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004056 {
4057 filter = &peer->filter[afi][safi];
4058
4059 if (! peer->af_group[afi][safi])
4060 continue;
4061
4062 if (filter->plist[direct].name)
4063 free (filter->plist[direct].name);
4064 filter->plist[direct].name = NULL;
4065 filter->plist[direct].plist = NULL;
4066 }
4067
4068 return 0;
4069}
4070
4071/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00004072static void
paul718e3742002-12-13 20:15:29 +00004073peer_prefix_list_update (struct prefix_list *plist)
4074{
paul1eb8ef22005-04-07 07:30:20 +00004075 struct listnode *mnode, *mnnode;
4076 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004077 struct bgp *bgp;
4078 struct peer *peer;
4079 struct peer_group *group;
4080 struct bgp_filter *filter;
4081 afi_t afi;
4082 safi_t safi;
4083 int direct;
4084
paul1eb8ef22005-04-07 07:30:20 +00004085 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004086 {
paul1eb8ef22005-04-07 07:30:20 +00004087 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004088 {
4089 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4090 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4091 {
4092 filter = &peer->filter[afi][safi];
4093
4094 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4095 {
4096 if (filter->plist[direct].name)
4097 filter->plist[direct].plist =
4098 prefix_list_lookup (afi, filter->plist[direct].name);
4099 else
4100 filter->plist[direct].plist = NULL;
4101 }
4102 }
4103 }
paul1eb8ef22005-04-07 07:30:20 +00004104 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004105 {
4106 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4107 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4108 {
4109 filter = &group->conf->filter[afi][safi];
4110
4111 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4112 {
4113 if (filter->plist[direct].name)
4114 filter->plist[direct].plist =
4115 prefix_list_lookup (afi, filter->plist[direct].name);
4116 else
4117 filter->plist[direct].plist = NULL;
4118 }
4119 }
4120 }
4121 }
4122}
David Lamparter6b0655a2014-06-04 06:53:35 +02004123
paul718e3742002-12-13 20:15:29 +00004124int
4125peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004126 const char *name)
paul718e3742002-12-13 20:15:29 +00004127{
4128 struct bgp_filter *filter;
4129 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004130 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004131
4132 if (! peer->afc[afi][safi])
4133 return BGP_ERR_PEER_INACTIVE;
4134
4135 if (direct != FILTER_IN && direct != FILTER_OUT)
4136 return BGP_ERR_INVALID_VALUE;
4137
4138 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4139 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4140
4141 filter = &peer->filter[afi][safi];
4142
4143 if (filter->aslist[direct].name)
4144 free (filter->aslist[direct].name);
4145 filter->aslist[direct].name = strdup (name);
4146 filter->aslist[direct].aslist = as_list_lookup (name);
4147
4148 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4149 return 0;
4150
4151 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004152 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004153 {
4154 filter = &peer->filter[afi][safi];
4155
4156 if (! peer->af_group[afi][safi])
4157 continue;
4158
4159 if (filter->aslist[direct].name)
4160 free (filter->aslist[direct].name);
4161 filter->aslist[direct].name = strdup (name);
4162 filter->aslist[direct].aslist = as_list_lookup (name);
4163 }
4164 return 0;
4165}
4166
4167int
4168peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4169{
4170 struct bgp_filter *filter;
4171 struct bgp_filter *gfilter;
4172 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004173 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004174
4175 if (! peer->afc[afi][safi])
4176 return BGP_ERR_PEER_INACTIVE;
4177
hassob5f29602005-05-25 21:00:28 +00004178 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004179 return BGP_ERR_INVALID_VALUE;
4180
hassob5f29602005-05-25 21:00:28 +00004181 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004182 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4183
4184 filter = &peer->filter[afi][safi];
4185
4186 /* apply peer-group filter */
4187 if (peer->af_group[afi][safi])
4188 {
4189 gfilter = &peer->group->conf->filter[afi][safi];
4190
4191 if (gfilter->aslist[direct].name)
4192 {
4193 if (filter->aslist[direct].name)
4194 free (filter->aslist[direct].name);
4195 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4196 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4197 return 0;
4198 }
4199 }
4200
4201 if (filter->aslist[direct].name)
4202 free (filter->aslist[direct].name);
4203 filter->aslist[direct].name = NULL;
4204 filter->aslist[direct].aslist = NULL;
4205
4206 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4207 return 0;
4208
4209 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004210 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004211 {
4212 filter = &peer->filter[afi][safi];
4213
4214 if (! peer->af_group[afi][safi])
4215 continue;
4216
4217 if (filter->aslist[direct].name)
4218 free (filter->aslist[direct].name);
4219 filter->aslist[direct].name = NULL;
4220 filter->aslist[direct].aslist = NULL;
4221 }
4222
4223 return 0;
4224}
4225
paul94f2b392005-06-28 12:44:16 +00004226static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004227peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004228{
4229 afi_t afi;
4230 safi_t safi;
4231 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004232 struct listnode *mnode, *mnnode;
4233 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004234 struct bgp *bgp;
4235 struct peer *peer;
4236 struct peer_group *group;
4237 struct bgp_filter *filter;
4238
paul1eb8ef22005-04-07 07:30:20 +00004239 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004240 {
paul1eb8ef22005-04-07 07:30:20 +00004241 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004242 {
4243 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4244 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4245 {
4246 filter = &peer->filter[afi][safi];
4247
4248 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4249 {
4250 if (filter->aslist[direct].name)
4251 filter->aslist[direct].aslist =
4252 as_list_lookup (filter->aslist[direct].name);
4253 else
4254 filter->aslist[direct].aslist = NULL;
4255 }
4256 }
4257 }
paul1eb8ef22005-04-07 07:30:20 +00004258 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004259 {
4260 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4261 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4262 {
4263 filter = &group->conf->filter[afi][safi];
4264
4265 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4266 {
4267 if (filter->aslist[direct].name)
4268 filter->aslist[direct].aslist =
4269 as_list_lookup (filter->aslist[direct].name);
4270 else
4271 filter->aslist[direct].aslist = NULL;
4272 }
4273 }
4274 }
4275 }
4276}
David Lamparter6b0655a2014-06-04 06:53:35 +02004277
paul718e3742002-12-13 20:15:29 +00004278/* Set route-map to the peer. */
4279int
4280peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004281 const char *name)
paul718e3742002-12-13 20:15:29 +00004282{
4283 struct bgp_filter *filter;
4284 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004285 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004286
4287 if (! peer->afc[afi][safi])
4288 return BGP_ERR_PEER_INACTIVE;
4289
paulfee0f4c2004-09-13 05:12:46 +00004290 if (direct != RMAP_IN && direct != RMAP_OUT &&
4291 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004292 return BGP_ERR_INVALID_VALUE;
4293
paulfee0f4c2004-09-13 05:12:46 +00004294 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4295 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004296 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4297
4298 filter = &peer->filter[afi][safi];
4299
4300 if (filter->map[direct].name)
4301 free (filter->map[direct].name);
4302
4303 filter->map[direct].name = strdup (name);
4304 filter->map[direct].map = route_map_lookup_by_name (name);
4305
4306 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4307 return 0;
4308
4309 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004310 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004311 {
4312 filter = &peer->filter[afi][safi];
4313
4314 if (! peer->af_group[afi][safi])
4315 continue;
4316
4317 if (filter->map[direct].name)
4318 free (filter->map[direct].name);
4319 filter->map[direct].name = strdup (name);
4320 filter->map[direct].map = route_map_lookup_by_name (name);
4321 }
4322 return 0;
4323}
4324
4325/* Unset route-map from the peer. */
4326int
4327peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4328{
4329 struct bgp_filter *filter;
4330 struct bgp_filter *gfilter;
4331 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004332 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004333
4334 if (! peer->afc[afi][safi])
4335 return BGP_ERR_PEER_INACTIVE;
4336
hassob5f29602005-05-25 21:00:28 +00004337 if (direct != RMAP_IN && direct != RMAP_OUT &&
4338 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004339 return BGP_ERR_INVALID_VALUE;
4340
hassob5f29602005-05-25 21:00:28 +00004341 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4342 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004343 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4344
4345 filter = &peer->filter[afi][safi];
4346
4347 /* apply peer-group filter */
4348 if (peer->af_group[afi][safi])
4349 {
4350 gfilter = &peer->group->conf->filter[afi][safi];
4351
4352 if (gfilter->map[direct].name)
4353 {
4354 if (filter->map[direct].name)
4355 free (filter->map[direct].name);
4356 filter->map[direct].name = strdup (gfilter->map[direct].name);
4357 filter->map[direct].map = gfilter->map[direct].map;
4358 return 0;
4359 }
4360 }
4361
4362 if (filter->map[direct].name)
4363 free (filter->map[direct].name);
4364 filter->map[direct].name = NULL;
4365 filter->map[direct].map = NULL;
4366
4367 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4368 return 0;
4369
4370 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004371 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004372 {
4373 filter = &peer->filter[afi][safi];
4374
4375 if (! peer->af_group[afi][safi])
4376 continue;
4377
4378 if (filter->map[direct].name)
4379 free (filter->map[direct].name);
4380 filter->map[direct].name = NULL;
4381 filter->map[direct].map = NULL;
4382 }
4383 return 0;
4384}
David Lamparter6b0655a2014-06-04 06:53:35 +02004385
paul718e3742002-12-13 20:15:29 +00004386/* Set unsuppress-map to the peer. */
4387int
paulfd79ac92004-10-13 05:06:08 +00004388peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4389 const char *name)
paul718e3742002-12-13 20:15:29 +00004390{
4391 struct bgp_filter *filter;
4392 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004393 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004394
4395 if (! peer->afc[afi][safi])
4396 return BGP_ERR_PEER_INACTIVE;
4397
4398 if (peer_is_group_member (peer, afi, safi))
4399 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4400
4401 filter = &peer->filter[afi][safi];
4402
4403 if (filter->usmap.name)
4404 free (filter->usmap.name);
4405
4406 filter->usmap.name = strdup (name);
4407 filter->usmap.map = route_map_lookup_by_name (name);
4408
4409 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4410 return 0;
4411
4412 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004413 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004414 {
4415 filter = &peer->filter[afi][safi];
4416
4417 if (! peer->af_group[afi][safi])
4418 continue;
4419
4420 if (filter->usmap.name)
4421 free (filter->usmap.name);
4422 filter->usmap.name = strdup (name);
4423 filter->usmap.map = route_map_lookup_by_name (name);
4424 }
4425 return 0;
4426}
4427
4428/* Unset route-map from the peer. */
4429int
4430peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4431{
4432 struct bgp_filter *filter;
4433 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004434 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004435
4436 if (! peer->afc[afi][safi])
4437 return BGP_ERR_PEER_INACTIVE;
4438
4439 if (peer_is_group_member (peer, afi, safi))
4440 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4441
4442 filter = &peer->filter[afi][safi];
4443
4444 if (filter->usmap.name)
4445 free (filter->usmap.name);
4446 filter->usmap.name = NULL;
4447 filter->usmap.map = NULL;
4448
4449 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4450 return 0;
4451
4452 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004453 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004454 {
4455 filter = &peer->filter[afi][safi];
4456
4457 if (! peer->af_group[afi][safi])
4458 continue;
4459
4460 if (filter->usmap.name)
4461 free (filter->usmap.name);
4462 filter->usmap.name = NULL;
4463 filter->usmap.map = NULL;
4464 }
4465 return 0;
4466}
David Lamparter6b0655a2014-06-04 06:53:35 +02004467
paul718e3742002-12-13 20:15:29 +00004468int
4469peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004470 u_int32_t max, u_char threshold,
4471 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004472{
4473 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004474 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004475
4476 if (! peer->afc[afi][safi])
4477 return BGP_ERR_PEER_INACTIVE;
4478
4479 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4480 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004481 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004482 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004483 if (warning)
4484 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4485 else
4486 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4487
4488 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4489 return 0;
4490
4491 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004492 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004493 {
4494 if (! peer->af_group[afi][safi])
4495 continue;
4496
4497 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4498 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004499 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004500 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004501 if (warning)
4502 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4503 else
4504 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4505 }
4506 return 0;
4507}
4508
4509int
4510peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4511{
4512 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004513 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004514
4515 if (! peer->afc[afi][safi])
4516 return BGP_ERR_PEER_INACTIVE;
4517
4518 /* apply peer-group config */
4519 if (peer->af_group[afi][safi])
4520 {
4521 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4522 PEER_FLAG_MAX_PREFIX))
4523 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4524 else
4525 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4526
4527 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4528 PEER_FLAG_MAX_PREFIX_WARNING))
4529 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4530 else
4531 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4532
4533 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004534 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004535 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004536 return 0;
4537 }
4538
4539 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4540 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4541 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004542 peer->pmax_threshold[afi][safi] = 0;
4543 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004544
4545 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4546 return 0;
4547
4548 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004549 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004550 {
4551 if (! peer->af_group[afi][safi])
4552 continue;
4553
4554 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4555 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4556 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004557 peer->pmax_threshold[afi][safi] = 0;
4558 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004559 }
4560 return 0;
4561}
David Lamparter5f9adb52014-05-19 23:15:02 +02004562
4563static int is_ebgp_multihop_configured (struct peer *peer)
4564{
4565 struct peer_group *group;
4566 struct listnode *node, *nnode;
4567 struct peer *peer1;
4568
4569 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4570 {
4571 group = peer->group;
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004572 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4573 (group->conf->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004574 return 1;
4575
4576 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4577 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004578 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
4579 (peer1->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004580 return 1;
4581 }
4582 }
4583 else
4584 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004585 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4586 (peer->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004587 return 1;
4588 }
4589 return 0;
4590}
4591
Nick Hilliardfa411a22011-03-23 15:33:17 +00004592/* Set # of hops between us and BGP peer. */
4593int
4594peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4595{
4596 struct peer_group *group;
4597 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004598 int ret;
4599
4600 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4601
Nick Hilliardfa411a22011-03-23 15:33:17 +00004602 /* We cannot configure ttl-security hops when ebgp-multihop is already
4603 set. For non peer-groups, the check is simple. For peer-groups, it's
4604 slightly messy, because we need to check both the peer-group structure
4605 and all peer-group members for any trace of ebgp-multihop configuration
4606 before actually applying the ttl-security rules. Cisco really made a
4607 mess of this configuration parameter, and OpenBGPD got it right.
4608 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004609
David Lamparter5f9adb52014-05-19 23:15:02 +02004610 if (peer->gtsm_hops == 0)
4611 {
4612 if (is_ebgp_multihop_configured (peer))
4613 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004614
David Lamparter5f9adb52014-05-19 23:15:02 +02004615 /* specify MAXTTL on outgoing packets */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004616 /* Routine handles iBGP peers correctly */
David Lamparter5f9adb52014-05-19 23:15:02 +02004617 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4618 if (ret != 0)
4619 return ret;
4620 }
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004621
Nick Hilliardfa411a22011-03-23 15:33:17 +00004622 peer->gtsm_hops = gtsm_hops;
4623
Nick Hilliardfa411a22011-03-23 15:33:17 +00004624 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4625 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004626 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004627 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4628 }
4629 else
4630 {
4631 group = peer->group;
4632 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4633 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004634 peer->gtsm_hops = group->conf->gtsm_hops;
4635
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004636 /* Change setting of existing peer
4637 * established then change value (may break connectivity)
4638 * not established yet (teardown session and restart)
4639 * no session then do nothing (will get handled by next connection)
4640 */
4641 if (peer->status == Established)
4642 {
4643 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4644 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4645 MAXTTL + 1 - peer->gtsm_hops);
4646 }
4647 else if (peer->status < Established)
4648 {
4649 if (BGP_DEBUG (events, EVENTS))
4650 zlog_debug ("%s Min-ttl changed", peer->host);
4651 BGP_EVENT_ADD (peer, BGP_Stop);
4652 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004653 }
4654 }
4655
4656 return 0;
4657}
4658
4659int
4660peer_ttl_security_hops_unset (struct peer *peer)
4661{
4662 struct peer_group *group;
4663 struct listnode *node, *nnode;
4664 struct peer *opeer;
4665
4666 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4667
Nick Hilliardfa411a22011-03-23 15:33:17 +00004668 /* if a peer-group member, then reset to peer-group default rather than 0 */
4669 if (peer_group_active (peer))
4670 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4671 else
4672 peer->gtsm_hops = 0;
4673
4674 opeer = peer;
4675 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4676 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004677 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004678 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4679 }
4680 else
4681 {
4682 group = peer->group;
4683 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4684 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004685 peer->gtsm_hops = 0;
4686
4687 if (peer->fd >= 0)
4688 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4689 }
4690 }
4691
4692 return peer_ebgp_multihop_unset (opeer);
4693}
David Lamparter6b0655a2014-06-04 06:53:35 +02004694
paul718e3742002-12-13 20:15:29 +00004695int
4696peer_clear (struct peer *peer)
4697{
4698 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4699 {
hasso0a486e52005-02-01 20:57:17 +00004700 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4701 {
4702 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4703 if (peer->t_pmax_restart)
4704 {
4705 BGP_TIMER_OFF (peer->t_pmax_restart);
4706 if (BGP_DEBUG (events, EVENTS))
4707 zlog_debug ("%s Maximum-prefix restart timer canceled",
4708 peer->host);
4709 }
4710 BGP_EVENT_ADD (peer, BGP_Start);
4711 return 0;
4712 }
4713
paul718e3742002-12-13 20:15:29 +00004714 peer->v_start = BGP_INIT_START_TIMER;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00004715 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00004716 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4717 BGP_NOTIFY_CEASE_ADMIN_RESET);
4718 else
4719 BGP_EVENT_ADD (peer, BGP_Stop);
4720 }
4721 return 0;
4722}
4723
4724int
4725peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4726 enum bgp_clear_type stype)
4727{
4728 if (peer->status != Established)
4729 return 0;
4730
4731 if (! peer->afc[afi][safi])
4732 return BGP_ERR_AF_UNCONFIGURED;
4733
Timo Teräs5a2a1ec2015-10-22 11:35:18 +03004734 peer->rtt = sockopt_tcp_rtt (peer->fd);
4735
paulfee0f4c2004-09-13 05:12:46 +00004736 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4737 {
4738 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4739 return 0;
4740 bgp_check_local_routes_rsclient (peer, afi, safi);
4741 bgp_soft_reconfig_rsclient (peer, afi, safi);
4742 }
4743
paul718e3742002-12-13 20:15:29 +00004744 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4745 bgp_announce_route (peer, afi, safi);
4746
4747 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4748 {
4749 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4750 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4751 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4752 {
4753 struct bgp_filter *filter = &peer->filter[afi][safi];
4754 u_char prefix_type;
4755
4756 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4757 prefix_type = ORF_TYPE_PREFIX;
4758 else
4759 prefix_type = ORF_TYPE_PREFIX_OLD;
4760
4761 if (filter->plist[FILTER_IN].plist)
4762 {
4763 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4764 bgp_route_refresh_send (peer, afi, safi,
4765 prefix_type, REFRESH_DEFER, 1);
4766 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4767 REFRESH_IMMEDIATE, 0);
4768 }
4769 else
4770 {
4771 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4772 bgp_route_refresh_send (peer, afi, safi,
4773 prefix_type, REFRESH_IMMEDIATE, 1);
4774 else
4775 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4776 }
4777 return 0;
4778 }
4779 }
4780
4781 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4782 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4783 {
4784 /* If neighbor has soft reconfiguration inbound flag.
4785 Use Adj-RIB-In database. */
4786 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4787 bgp_soft_reconfig_in (peer, afi, safi);
4788 else
4789 {
4790 /* If neighbor has route refresh capability, send route refresh
4791 message to the peer. */
4792 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4793 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4794 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4795 else
4796 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4797 }
4798 }
4799 return 0;
4800}
David Lamparter6b0655a2014-06-04 06:53:35 +02004801
paulfd79ac92004-10-13 05:06:08 +00004802/* Display peer uptime.*/
4803/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004804char *
4805peer_uptime (time_t uptime2, char *buf, size_t len)
4806{
4807 time_t uptime1;
4808 struct tm *tm;
4809
4810 /* Check buffer length. */
4811 if (len < BGP_UPTIME_LEN)
4812 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004813 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004814 /* XXX: should return status instead of buf... */
4815 snprintf (buf, len, "<error> ");
4816 return buf;
paul718e3742002-12-13 20:15:29 +00004817 }
4818
4819 /* If there is no connection has been done before print `never'. */
4820 if (uptime2 == 0)
4821 {
4822 snprintf (buf, len, "never ");
4823 return buf;
4824 }
4825
4826 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004827 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004828 uptime1 -= uptime2;
4829 tm = gmtime (&uptime1);
Paul Jakma84c38402015-05-26 15:19:38 +01004830
paul718e3742002-12-13 20:15:29 +00004831 /* Making formatted timer strings. */
4832#define ONE_DAY_SECOND 60*60*24
Paul Jakma84c38402015-05-26 15:19:38 +01004833#define ONE_WEEK_SECOND ONE_DAY_SECOND*7
4834#define ONE_YEAR_SECOND ONE_DAY_SECOND*365
paul718e3742002-12-13 20:15:29 +00004835
4836 if (uptime1 < ONE_DAY_SECOND)
4837 snprintf (buf, len, "%02d:%02d:%02d",
4838 tm->tm_hour, tm->tm_min, tm->tm_sec);
4839 else if (uptime1 < ONE_WEEK_SECOND)
4840 snprintf (buf, len, "%dd%02dh%02dm",
4841 tm->tm_yday, tm->tm_hour, tm->tm_min);
Paul Jakma84c38402015-05-26 15:19:38 +01004842 else if (uptime1 < ONE_YEAR_SECOND)
paul718e3742002-12-13 20:15:29 +00004843 snprintf (buf, len, "%02dw%dd%02dh",
4844 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
Paul Jakma84c38402015-05-26 15:19:38 +01004845 else
4846 snprintf (buf, len, "%02dy%02dw%dd",
4847 tm->tm_year - 70, tm->tm_yday/7,
4848 tm->tm_yday - ((tm->tm_yday/7) * 7));
paul718e3742002-12-13 20:15:29 +00004849 return buf;
4850}
David Lamparter6b0655a2014-06-04 06:53:35 +02004851
paul94f2b392005-06-28 12:44:16 +00004852static void
paul718e3742002-12-13 20:15:29 +00004853bgp_config_write_filter (struct vty *vty, struct peer *peer,
4854 afi_t afi, safi_t safi)
4855{
4856 struct bgp_filter *filter;
4857 struct bgp_filter *gfilter = NULL;
4858 char *addr;
4859 int in = FILTER_IN;
4860 int out = FILTER_OUT;
4861
4862 addr = peer->host;
4863 filter = &peer->filter[afi][safi];
4864 if (peer->af_group[afi][safi])
4865 gfilter = &peer->group->conf->filter[afi][safi];
4866
4867 /* distribute-list. */
4868 if (filter->dlist[in].name)
4869 if (! gfilter || ! gfilter->dlist[in].name
4870 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4871 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4872 filter->dlist[in].name, VTY_NEWLINE);
4873 if (filter->dlist[out].name && ! gfilter)
4874 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4875 filter->dlist[out].name, VTY_NEWLINE);
4876
4877 /* prefix-list. */
4878 if (filter->plist[in].name)
4879 if (! gfilter || ! gfilter->plist[in].name
4880 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4881 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4882 filter->plist[in].name, VTY_NEWLINE);
4883 if (filter->plist[out].name && ! gfilter)
4884 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4885 filter->plist[out].name, VTY_NEWLINE);
4886
4887 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004888 if (filter->map[RMAP_IN].name)
4889 if (! gfilter || ! gfilter->map[RMAP_IN].name
4890 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004891 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004892 filter->map[RMAP_IN].name, VTY_NEWLINE);
4893 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004894 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004895 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4896 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4897 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4898 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4899 if (filter->map[RMAP_EXPORT].name)
4900 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4901 || strcmp (filter->map[RMAP_EXPORT].name,
4902 gfilter->map[RMAP_EXPORT].name) != 0)
4903 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4904 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004905
4906 /* unsuppress-map */
4907 if (filter->usmap.name && ! gfilter)
4908 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4909 filter->usmap.name, VTY_NEWLINE);
4910
4911 /* filter-list. */
4912 if (filter->aslist[in].name)
4913 if (! gfilter || ! gfilter->aslist[in].name
4914 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4915 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4916 filter->aslist[in].name, VTY_NEWLINE);
4917 if (filter->aslist[out].name && ! gfilter)
4918 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4919 filter->aslist[out].name, VTY_NEWLINE);
4920}
4921
4922/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004923static void
paul718e3742002-12-13 20:15:29 +00004924bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4925 struct peer *peer, afi_t afi, safi_t safi)
4926{
paul718e3742002-12-13 20:15:29 +00004927 struct peer *g_peer = NULL;
4928 char buf[SU_ADDRSTRLEN];
4929 char *addr;
4930
paul718e3742002-12-13 20:15:29 +00004931 addr = peer->host;
4932 if (peer_group_active (peer))
4933 g_peer = peer->group->conf;
4934
4935 /************************************
4936 ****** Global to the neighbor ******
4937 ************************************/
4938 if (afi == AFI_IP && safi == SAFI_UNICAST)
4939 {
4940 /* remote-as. */
4941 if (! peer_group_active (peer))
4942 {
4943 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4944 vty_out (vty, " neighbor %s peer-group%s", addr,
4945 VTY_NEWLINE);
4946 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004947 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004948 VTY_NEWLINE);
4949 }
4950 else
4951 {
4952 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004953 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004954 VTY_NEWLINE);
4955 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4956 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4957 peer->group->name, VTY_NEWLINE);
4958 }
4959
4960 /* local-as. */
4961 if (peer->change_local_as)
4962 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00004963 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004964 peer->change_local_as,
4965 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00004966 " no-prepend" : "",
4967 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
4968 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004969
4970 /* Description. */
4971 if (peer->desc)
4972 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4973 VTY_NEWLINE);
4974
4975 /* Shutdown. */
4976 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4977 if (! peer_group_active (peer) ||
4978 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4979 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4980
Paul Jakma0df7c912008-07-21 21:02:49 +00004981 /* Password. */
4982 if (peer->password)
4983 if (!peer_group_active (peer)
4984 || ! g_peer->password
4985 || strcmp (peer->password, g_peer->password) != 0)
4986 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4987 VTY_NEWLINE);
4988
paul718e3742002-12-13 20:15:29 +00004989 /* BGP port. */
4990 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004991 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004992 VTY_NEWLINE);
4993
4994 /* Local interface name. */
4995 if (peer->ifname)
4996 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4997 VTY_NEWLINE);
4998
4999 /* Passive. */
5000 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
5001 if (! peer_group_active (peer) ||
5002 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
5003 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
5004
5005 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00005006 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00005007 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00005008 if (! peer_group_active (peer) ||
5009 g_peer->ttl != peer->ttl)
5010 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
5011 VTY_NEWLINE);
5012
Nick Hilliardfa411a22011-03-23 15:33:17 +00005013 /* ttl-security hops */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00005014 if (peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00005015 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00005016 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00005017 peer->gtsm_hops, VTY_NEWLINE);
5018
hasso6ffd2072005-02-02 14:50:11 +00005019 /* disable-connected-check. */
5020 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00005021 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00005022 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
5023 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005024
5025 /* Update-source. */
5026 if (peer->update_if)
5027 if (! peer_group_active (peer) || ! g_peer->update_if
5028 || strcmp (g_peer->update_if, peer->update_if) != 0)
5029 vty_out (vty, " neighbor %s update-source %s%s", addr,
5030 peer->update_if, VTY_NEWLINE);
5031 if (peer->update_source)
5032 if (! peer_group_active (peer) || ! g_peer->update_source
5033 || sockunion_cmp (g_peer->update_source,
5034 peer->update_source) != 0)
5035 vty_out (vty, " neighbor %s update-source %s%s", addr,
5036 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
5037 VTY_NEWLINE);
5038
paul718e3742002-12-13 20:15:29 +00005039 /* advertisement-interval */
Daniel Walton0d7435f2015-10-22 11:35:20 +03005040 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV) &&
5041 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00005042 vty_out (vty, " neighbor %s advertisement-interval %d%s",
5043 addr, peer->v_routeadv, VTY_NEWLINE);
5044
5045 /* timers. */
5046 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
5047 && ! peer_group_active (peer))
5048 vty_out (vty, " neighbor %s timers %d %d%s", addr,
5049 peer->keepalive, peer->holdtime, VTY_NEWLINE);
5050
Daniel Walton0d7435f2015-10-22 11:35:20 +03005051 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT) &&
5052 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00005053 vty_out (vty, " neighbor %s timers connect %d%s", addr,
5054 peer->connect, VTY_NEWLINE);
5055
5056 /* Default weight. */
5057 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
5058 if (! peer_group_active (peer) ||
5059 g_peer->weight != peer->weight)
5060 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
5061 VTY_NEWLINE);
5062
paul718e3742002-12-13 20:15:29 +00005063 /* Dynamic capability. */
5064 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5065 if (! peer_group_active (peer) ||
5066 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5067 vty_out (vty, " neighbor %s capability dynamic%s", addr,
5068 VTY_NEWLINE);
5069
5070 /* dont capability negotiation. */
5071 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
5072 if (! peer_group_active (peer) ||
5073 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
5074 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
5075 VTY_NEWLINE);
5076
5077 /* override capability negotiation. */
5078 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5079 if (! peer_group_active (peer) ||
5080 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5081 vty_out (vty, " neighbor %s override-capability%s", addr,
5082 VTY_NEWLINE);
5083
5084 /* strict capability negotiation. */
5085 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5086 if (! peer_group_active (peer) ||
5087 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5088 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
5089 VTY_NEWLINE);
5090
Christian Franke15c71342012-11-19 11:17:31 +00005091 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
paul718e3742002-12-13 20:15:29 +00005092 {
5093 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5094 {
5095 if (peer->afc[AFI_IP][SAFI_UNICAST])
5096 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5097 }
5098 else
5099 {
5100 if (! peer->afc[AFI_IP][SAFI_UNICAST])
5101 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
5102 }
5103 }
5104 }
5105
5106
5107 /************************************
5108 ****** Per AF to the neighbor ******
5109 ************************************/
5110
5111 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
5112 {
5113 if (peer->af_group[afi][safi])
5114 vty_out (vty, " neighbor %s peer-group %s%s", addr,
5115 peer->group->name, VTY_NEWLINE);
5116 else
5117 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5118 }
5119
5120 /* ORF capability. */
5121 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5122 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5123 if (! peer->af_group[afi][safi])
5124 {
5125 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
5126
5127 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5128 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5129 vty_out (vty, " both");
5130 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
5131 vty_out (vty, " send");
5132 else
5133 vty_out (vty, " receive");
5134 vty_out (vty, "%s", VTY_NEWLINE);
5135 }
5136
5137 /* Route reflector client. */
5138 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
5139 && ! peer->af_group[afi][safi])
5140 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
5141 VTY_NEWLINE);
5142
5143 /* Nexthop self. */
5144 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
5145 && ! peer->af_group[afi][safi])
Timo Teräs9e7a53c2014-04-24 10:22:37 +03005146 vty_out (vty, " neighbor %s next-hop-self%s%s", addr,
5147 peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ?
5148 " all" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005149
5150 /* Remove private AS. */
5151 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
5152 && ! peer->af_group[afi][safi])
5153 vty_out (vty, " neighbor %s remove-private-AS%s",
5154 addr, VTY_NEWLINE);
5155
5156 /* send-community print. */
5157 if (! peer->af_group[afi][safi])
5158 {
5159 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5160 {
5161 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5162 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5163 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
5164 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5165 vty_out (vty, " neighbor %s send-community extended%s",
5166 addr, VTY_NEWLINE);
5167 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5168 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
5169 }
5170 else
5171 {
5172 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5173 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5174 vty_out (vty, " no neighbor %s send-community both%s",
5175 addr, VTY_NEWLINE);
5176 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5177 vty_out (vty, " no neighbor %s send-community extended%s",
5178 addr, VTY_NEWLINE);
5179 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5180 vty_out (vty, " no neighbor %s send-community%s",
5181 addr, VTY_NEWLINE);
5182 }
5183 }
5184
5185 /* Default information */
5186 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5187 && ! peer->af_group[afi][safi])
5188 {
5189 vty_out (vty, " neighbor %s default-originate", addr);
5190 if (peer->default_rmap[afi][safi].name)
5191 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5192 vty_out (vty, "%s", VTY_NEWLINE);
5193 }
5194
5195 /* Soft reconfiguration inbound. */
5196 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5197 if (! peer->af_group[afi][safi] ||
5198 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5199 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5200 VTY_NEWLINE);
5201
5202 /* maximum-prefix. */
5203 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5204 if (! peer->af_group[afi][safi]
5205 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005206 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005207 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5208 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005209 {
hasso0a486e52005-02-01 20:57:17 +00005210 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5211 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5212 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5213 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5214 vty_out (vty, " warning-only");
5215 if (peer->pmax_restart[afi][safi])
5216 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5217 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005218 }
paul718e3742002-12-13 20:15:29 +00005219
5220 /* Route server client. */
5221 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5222 && ! peer->af_group[afi][safi])
5223 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5224
Dylan Hall3cf12882011-10-27 15:28:17 +04005225 /* Nexthop-local unchanged. */
5226 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5227 && ! peer->af_group[afi][safi])
5228 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5229
paul718e3742002-12-13 20:15:29 +00005230 /* Allow AS in. */
5231 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5232 if (! peer_group_active (peer)
5233 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5234 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5235 {
5236 if (peer->allowas_in[afi][safi] == 3)
5237 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5238 else
5239 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5240 peer->allowas_in[afi][safi], VTY_NEWLINE);
5241 }
5242
5243 /* Filter. */
5244 bgp_config_write_filter (vty, peer, afi, safi);
5245
5246 /* atribute-unchanged. */
5247 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5248 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5249 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5250 && ! peer->af_group[afi][safi])
5251 {
5252 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5253 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5254 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5255 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5256 else
5257 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5258 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5259 " as-path" : "",
5260 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5261 " next-hop" : "",
5262 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5263 " med" : "", VTY_NEWLINE);
5264 }
5265}
5266
5267/* Display "address-family" configuration header. */
5268void
5269bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5270 int *write)
5271{
5272 if (*write)
5273 return;
5274
5275 if (afi == AFI_IP && safi == SAFI_UNICAST)
5276 return;
5277
5278 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5279
5280 if (afi == AFI_IP)
5281 {
5282 if (safi == SAFI_MULTICAST)
5283 vty_out (vty, "ipv4 multicast");
5284 else if (safi == SAFI_MPLS_VPN)
5285 vty_out (vty, "vpnv4 unicast");
5286 }
5287 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005288 {
5289 vty_out (vty, "ipv6");
5290
5291 if (safi == SAFI_MULTICAST)
5292 vty_out (vty, " multicast");
5293 }
paul718e3742002-12-13 20:15:29 +00005294
5295 vty_out (vty, "%s", VTY_NEWLINE);
5296
5297 *write = 1;
5298}
5299
5300/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005301static int
paul718e3742002-12-13 20:15:29 +00005302bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5303 safi_t safi)
5304{
5305 int write = 0;
5306 struct peer *peer;
5307 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005308 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005309
5310 bgp_config_write_network (vty, bgp, afi, safi, &write);
5311
5312 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5313
paul1eb8ef22005-04-07 07:30:20 +00005314 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005315 {
5316 if (group->conf->afc[afi][safi])
5317 {
5318 bgp_config_write_family_header (vty, afi, safi, &write);
5319 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5320 }
5321 }
paul1eb8ef22005-04-07 07:30:20 +00005322 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005323 {
5324 if (peer->afc[afi][safi])
5325 {
5326 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5327 {
5328 bgp_config_write_family_header (vty, afi, safi, &write);
5329 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5330 }
5331 }
5332 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005333
5334 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5335
paul718e3742002-12-13 20:15:29 +00005336 if (write)
5337 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5338
5339 return write;
5340}
5341
5342int
5343bgp_config_write (struct vty *vty)
5344{
5345 int write = 0;
5346 struct bgp *bgp;
5347 struct peer_group *group;
5348 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005349 struct listnode *node, *nnode;
5350 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005351
5352 /* BGP Multiple instance. */
5353 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5354 {
5355 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5356 write++;
5357 }
5358
5359 /* BGP Config type. */
5360 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5361 {
5362 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5363 write++;
5364 }
5365
5366 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005367 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005368 {
5369 if (write)
5370 vty_out (vty, "!%s", VTY_NEWLINE);
5371
5372 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005373 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005374
5375 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5376 {
5377 if (bgp->name)
5378 vty_out (vty, " view %s", bgp->name);
5379 }
5380 vty_out (vty, "%s", VTY_NEWLINE);
5381
5382 /* No Synchronization */
5383 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5384 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5385
5386 /* BGP fast-external-failover. */
5387 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5388 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5389
5390 /* BGP router ID. */
5391 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5392 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5393 VTY_NEWLINE);
5394
paul848973c2003-08-13 00:32:49 +00005395 /* BGP log-neighbor-changes. */
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07005396 if (!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5397 vty_out (vty, " no bgp log-neighbor-changes%s", VTY_NEWLINE);
paul848973c2003-08-13 00:32:49 +00005398
paul718e3742002-12-13 20:15:29 +00005399 /* BGP configuration. */
5400 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5401 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5402
5403 /* BGP default ipv4-unicast. */
5404 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5405 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5406
5407 /* BGP default local-preference. */
5408 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5409 vty_out (vty, " bgp default local-preference %d%s",
5410 bgp->default_local_pref, VTY_NEWLINE);
5411
5412 /* BGP client-to-client reflection. */
5413 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5414 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5415
5416 /* BGP cluster ID. */
5417 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5418 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5419 VTY_NEWLINE);
5420
hassoe0701b72004-05-20 09:19:34 +00005421 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005422 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005423 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5424 VTY_NEWLINE);
5425
5426 /* Confederation peer */
5427 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005428 {
hassoe0701b72004-05-20 09:19:34 +00005429 int i;
paul718e3742002-12-13 20:15:29 +00005430
hassoe0701b72004-05-20 09:19:34 +00005431 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005432
hassoe0701b72004-05-20 09:19:34 +00005433 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005434 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005435
hassoe0701b72004-05-20 09:19:34 +00005436 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005437 }
5438
5439 /* BGP enforce-first-as. */
5440 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5441 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5442
5443 /* BGP deterministic-med. */
5444 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5445 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005446
5447 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005448 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5449 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5450 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005451 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5452 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5453
paul718e3742002-12-13 20:15:29 +00005454 /* BGP bestpath method. */
5455 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5456 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005457 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5458 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
Pradosh Mohapatra2fdd4552013-09-07 07:02:36 +00005459 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
5460 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
5461 }
paul718e3742002-12-13 20:15:29 +00005462 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5463 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5464 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5465 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5466 {
5467 vty_out (vty, " bgp bestpath med");
5468 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5469 vty_out (vty, " confed");
5470 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5471 vty_out (vty, " missing-as-worst");
5472 vty_out (vty, "%s", VTY_NEWLINE);
5473 }
5474
5475 /* BGP network import check. */
5476 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5477 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5478
5479 /* BGP scan interval. */
5480 bgp_config_write_scan_time (vty);
5481
5482 /* BGP flag dampening. */
5483 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5484 BGP_CONFIG_DAMPENING))
5485 bgp_config_write_damp (vty);
5486
5487 /* BGP static route configuration. */
5488 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5489
5490 /* BGP redistribute configuration. */
5491 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5492
5493 /* BGP timers configuration. */
5494 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5495 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5496 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5497 bgp->default_holdtime, VTY_NEWLINE);
5498
5499 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005500 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005501 {
5502 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5503 }
5504
5505 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005506 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005507 {
5508 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5509 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5510 }
5511
Josh Bailey165b5ff2011-07-20 20:43:22 -07005512 /* maximum-paths */
5513 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5514
paul718e3742002-12-13 20:15:29 +00005515 /* Distance configuration. */
5516 bgp_config_write_distance (vty, bgp);
5517
5518 /* No auto-summary */
5519 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5520 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5521
5522 /* IPv4 multicast configuration. */
5523 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5524
5525 /* IPv4 VPN configuration. */
5526 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5527
5528 /* IPv6 unicast configuration. */
5529 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5530
Paul Jakma37a217a2007-04-10 19:20:29 +00005531 /* IPv6 multicast configuration. */
5532 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5533
paul718e3742002-12-13 20:15:29 +00005534 write++;
5535 }
5536 return write;
5537}
5538
5539void
paul94f2b392005-06-28 12:44:16 +00005540bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005541{
5542 memset (&bgp_master, 0, sizeof (struct bgp_master));
5543
5544 bm = &bgp_master;
5545 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005546 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005547 bm->port = BGP_PORT_DEFAULT;
5548 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005549 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005550}
paul200df112005-06-01 11:17:05 +00005551
David Lamparter6b0655a2014-06-04 06:53:35 +02005552
paul718e3742002-12-13 20:15:29 +00005553void
paul94f2b392005-06-28 12:44:16 +00005554bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005555{
paul718e3742002-12-13 20:15:29 +00005556 /* BGP VTY commands installation. */
5557 bgp_vty_init ();
5558
paul718e3742002-12-13 20:15:29 +00005559 /* Init zebra. */
Donald Sharp774914f2015-10-14 08:50:39 -04005560 bgp_zebra_init (bm->master);
paul718e3742002-12-13 20:15:29 +00005561
5562 /* BGP inits. */
5563 bgp_attr_init ();
5564 bgp_debug_init ();
5565 bgp_dump_init ();
5566 bgp_route_init ();
5567 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005568 bgp_address_init ();
paul718e3742002-12-13 20:15:29 +00005569 bgp_scan_init ();
5570 bgp_mplsvpn_init ();
5571
5572 /* Access list initialize. */
5573 access_list_init ();
5574 access_list_add_hook (peer_distribute_update);
5575 access_list_delete_hook (peer_distribute_update);
5576
5577 /* Filter list initialize. */
5578 bgp_filter_init ();
5579 as_list_add_hook (peer_aslist_update);
5580 as_list_delete_hook (peer_aslist_update);
5581
5582 /* Prefix list initialize.*/
5583 prefix_list_init ();
5584 prefix_list_add_hook (peer_prefix_list_update);
5585 prefix_list_delete_hook (peer_prefix_list_update);
5586
5587 /* Community list initialize. */
5588 bgp_clist = community_list_init ();
5589
5590#ifdef HAVE_SNMP
5591 bgp_snmp_init ();
5592#endif /* HAVE_SNMP */
5593}
paul545acaf2004-04-20 15:13:15 +00005594
5595void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005596bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005597{
paul545acaf2004-04-20 15:13:15 +00005598 struct bgp *bgp;
5599 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005600 struct listnode *node, *nnode;
5601 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005602
paul1eb8ef22005-04-07 07:30:20 +00005603 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5604 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005605 if (peer->status == Established)
5606 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5607 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005608
paul545acaf2004-04-20 15:13:15 +00005609 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005610
paule210cf92005-06-15 19:15:35 +00005611 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005612 {
5613 work_queue_free (bm->process_main_queue);
5614 bm->process_main_queue = NULL;
5615 }
paule210cf92005-06-15 19:15:35 +00005616 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005617 {
5618 work_queue_free (bm->process_rsclient_queue);
5619 bm->process_rsclient_queue = NULL;
5620 }
paul545acaf2004-04-20 15:13:15 +00005621}