blob: 2325f07c8d02feacf0eaa73757a4d4f81c041fb9 [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);
981 }
982
983 /* local-as reset */
984 if (peer_sort (peer) != BGP_PEER_EBGP)
985 {
986 peer->change_local_as = 0;
987 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +0000988 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +0000989 }
990}
991
992/* If peer does not exist, create new one. If peer already exists,
993 set AS number to the peer. */
994int
995peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
996 afi_t afi, safi_t safi)
997{
998 struct peer *peer;
999 as_t local_as;
1000
1001 peer = peer_lookup (bgp, su);
1002
1003 if (peer)
1004 {
1005 /* When this peer is a member of peer-group. */
1006 if (peer->group)
1007 {
1008 if (peer->group->conf->as)
1009 {
1010 /* Return peer group's AS number. */
1011 *as = peer->group->conf->as;
1012 return BGP_ERR_PEER_GROUP_MEMBER;
1013 }
1014 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
1015 {
1016 if (bgp->as != *as)
1017 {
1018 *as = peer->as;
1019 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1020 }
1021 }
1022 else
1023 {
1024 if (bgp->as == *as)
1025 {
1026 *as = peer->as;
1027 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1028 }
1029 }
1030 }
1031
1032 /* Existing peer's AS number change. */
1033 if (peer->as != *as)
1034 peer_as_change (peer, *as);
1035 }
1036 else
1037 {
1038
1039 /* If the peer is not part of our confederation, and its not an
1040 iBGP peer then spoof the source AS */
1041 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1042 && ! bgp_confederation_peers_check (bgp, *as)
1043 && bgp->as != *as)
1044 local_as = bgp->confed_id;
1045 else
1046 local_as = bgp->as;
1047
1048 /* If this is IPv4 unicast configuration and "no bgp default
1049 ipv4-unicast" is specified. */
1050
1051 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1052 && afi == AFI_IP && safi == SAFI_UNICAST)
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001053 peer_create (su, bgp, local_as, *as, 0, 0);
paul718e3742002-12-13 20:15:29 +00001054 else
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001055 peer_create (su, bgp, local_as, *as, afi, safi);
paul718e3742002-12-13 20:15:29 +00001056 }
1057
1058 return 0;
1059}
1060
1061/* Activate the peer or peer group for specified AFI and SAFI. */
1062int
1063peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1064{
1065 int active;
1066
1067 if (peer->afc[afi][safi])
1068 return 0;
1069
1070 /* Activate the address family configuration. */
1071 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1072 peer->afc[afi][safi] = 1;
1073 else
1074 {
1075 active = peer_active (peer);
1076
1077 peer->afc[afi][safi] = 1;
1078
1079 if (! active && peer_active (peer))
1080 bgp_timer_set (peer);
1081 else
1082 {
1083 if (peer->status == Established)
1084 {
1085 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1086 {
1087 peer->afc_adv[afi][safi] = 1;
1088 bgp_capability_send (peer, afi, safi,
1089 CAPABILITY_CODE_MP,
1090 CAPABILITY_ACTION_SET);
1091 if (peer->afc_recv[afi][safi])
1092 {
1093 peer->afc_nego[afi][safi] = 1;
1094 bgp_announce_route (peer, afi, safi);
1095 }
1096 }
1097 else
hassoe0701b72004-05-20 09:19:34 +00001098 {
1099 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1100 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1101 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1102 }
paul718e3742002-12-13 20:15:29 +00001103 }
1104 }
1105 }
1106 return 0;
1107}
1108
1109int
1110peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1111{
1112 struct peer_group *group;
1113 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001114 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001115
1116 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1117 {
1118 group = peer->group;
1119
paul1eb8ef22005-04-07 07:30:20 +00001120 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001121 {
1122 if (peer1->af_group[afi][safi])
1123 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1124 }
1125 }
1126 else
1127 {
1128 if (peer->af_group[afi][safi])
1129 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1130 }
1131
1132 if (! peer->afc[afi][safi])
1133 return 0;
1134
1135 /* De-activate the address family configuration. */
1136 peer->afc[afi][safi] = 0;
1137 peer_af_flag_reset (peer, afi, safi);
1138
1139 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1140 {
1141 if (peer->status == Established)
1142 {
1143 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1144 {
1145 peer->afc_adv[afi][safi] = 0;
1146 peer->afc_nego[afi][safi] = 0;
1147
1148 if (peer_active_nego (peer))
1149 {
1150 bgp_capability_send (peer, afi, safi,
1151 CAPABILITY_CODE_MP,
1152 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001153 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001154 peer->pcount[afi][safi] = 0;
1155 }
1156 else
hassoe0701b72004-05-20 09:19:34 +00001157 {
1158 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1159 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1160 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1161 }
paul718e3742002-12-13 20:15:29 +00001162 }
1163 else
hassoe0701b72004-05-20 09:19:34 +00001164 {
1165 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1166 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1167 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1168 }
paul718e3742002-12-13 20:15:29 +00001169 }
1170 }
1171 return 0;
1172}
1173
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001174static void
hasso93406d82005-02-02 14:40:33 +00001175peer_nsf_stop (struct peer *peer)
1176{
1177 afi_t afi;
1178 safi_t safi;
1179
1180 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1181 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1182
1183 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +04001184 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +00001185 peer->nsf[afi][safi] = 0;
1186
1187 if (peer->t_gr_restart)
1188 {
1189 BGP_TIMER_OFF (peer->t_gr_restart);
1190 if (BGP_DEBUG (events, EVENTS))
1191 zlog_debug ("%s graceful restart timer stopped", peer->host);
1192 }
1193 if (peer->t_gr_stale)
1194 {
1195 BGP_TIMER_OFF (peer->t_gr_stale);
1196 if (BGP_DEBUG (events, EVENTS))
1197 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1198 }
1199 bgp_clear_route_all (peer);
1200}
1201
Paul Jakmaca058a32006-09-14 02:58:49 +00001202/* Delete peer from confguration.
1203 *
1204 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1205 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1206 *
1207 * This function /should/ take care to be idempotent, to guard against
1208 * it being called multiple times through stray events that come in
1209 * that happen to result in this function being called again. That
1210 * said, getting here for a "Deleted" peer is a bug in the neighbour
1211 * FSM.
1212 */
paul718e3742002-12-13 20:15:29 +00001213int
1214peer_delete (struct peer *peer)
1215{
1216 int i;
1217 afi_t afi;
1218 safi_t safi;
1219 struct bgp *bgp;
1220 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001221 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001222
Paul Jakmaca058a32006-09-14 02:58:49 +00001223 assert (peer->status != Deleted);
1224
paul718e3742002-12-13 20:15:29 +00001225 bgp = peer->bgp;
1226
hasso93406d82005-02-02 14:40:33 +00001227 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1228 peer_nsf_stop (peer);
1229
Chris Caputo228da422009-07-18 05:44:03 +00001230 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001231 relationship. */
1232 if (peer->group)
1233 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001234 if ((pn = listnode_lookup (peer->group->peer, peer)))
1235 {
1236 peer = peer_unlock (peer); /* group->peer list reference */
1237 list_delete_node (peer->group->peer, pn);
1238 }
paul718e3742002-12-13 20:15:29 +00001239 peer->group = NULL;
1240 }
paul200df112005-06-01 11:17:05 +00001241
paul718e3742002-12-13 20:15:29 +00001242 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001243 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1244 * executed after peer structure is deleted.
1245 */
hassoe0701b72004-05-20 09:19:34 +00001246 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001247 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001248 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001249
1250 /* Password configuration */
1251 if (peer->password)
1252 {
1253 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1254 peer->password = NULL;
1255
1256 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1257 bgp_md5_set (peer);
1258 }
1259
Paul Jakmaca058a32006-09-14 02:58:49 +00001260 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001261
paul718e3742002-12-13 20:15:29 +00001262 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001263 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1264 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001265 {
Chris Caputo228da422009-07-18 05:44:03 +00001266 peer_unlock (peer); /* bgp peer list reference */
1267 list_delete_node (bgp->peer, pn);
1268 }
paul200df112005-06-01 11:17:05 +00001269
Chris Caputo228da422009-07-18 05:44:03 +00001270 if (peer_rsclient_active (peer)
1271 && (pn = listnode_lookup (bgp->rsclient, peer)))
1272 {
1273 peer_unlock (peer); /* rsclient list reference */
1274 list_delete_node (bgp->rsclient, pn);
1275
1276 /* Clear our own rsclient ribs. */
1277 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1278 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1279 if (CHECK_FLAG(peer->af_flags[afi][safi],
1280 PEER_FLAG_RSERVER_CLIENT))
1281 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001282 }
1283
1284 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1285 member of a peer_group. */
1286 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1287 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1288 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001289 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001290
paul200df112005-06-01 11:17:05 +00001291 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001292 if (peer->ibuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001293 {
1294 stream_free (peer->ibuf);
1295 peer->ibuf = NULL;
1296 }
1297
paul718e3742002-12-13 20:15:29 +00001298 if (peer->obuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001299 {
1300 stream_fifo_free (peer->obuf);
1301 peer->obuf = NULL;
1302 }
1303
paul718e3742002-12-13 20:15:29 +00001304 if (peer->work)
Daniel Walton363c9032015-10-21 06:42:54 -07001305 {
1306 stream_free (peer->work);
1307 peer->work = NULL;
1308 }
1309
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00001310 if (peer->scratch)
Daniel Walton363c9032015-10-21 06:42:54 -07001311 {
1312 stream_free(peer->scratch);
1313 peer->scratch = NULL;
1314 }
Paul Jakma18937402006-07-27 19:05:12 +00001315
paul718e3742002-12-13 20:15:29 +00001316 /* Local and remote addresses. */
1317 if (peer->su_local)
Daniel Walton363c9032015-10-21 06:42:54 -07001318 {
1319 sockunion_free (peer->su_local);
1320 peer->su_local = NULL;
1321 }
1322
paul718e3742002-12-13 20:15:29 +00001323 if (peer->su_remote)
Daniel Walton363c9032015-10-21 06:42:54 -07001324 {
1325 sockunion_free (peer->su_remote);
1326 peer->su_remote = NULL;
1327 }
paul200df112005-06-01 11:17:05 +00001328
paul718e3742002-12-13 20:15:29 +00001329 /* Free filter related memory. */
1330 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1331 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1332 {
1333 filter = &peer->filter[afi][safi];
1334
1335 for (i = FILTER_IN; i < FILTER_MAX; i++)
1336 {
1337 if (filter->dlist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001338 {
1339 free(filter->dlist[i].name);
1340 filter->dlist[i].name = NULL;
1341 }
1342
paul718e3742002-12-13 20:15:29 +00001343 if (filter->plist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001344 {
1345 free(filter->plist[i].name);
1346 filter->plist[i].name = NULL;
1347 }
1348
paul718e3742002-12-13 20:15:29 +00001349 if (filter->aslist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001350 {
1351 free(filter->aslist[i].name);
1352 filter->aslist[i].name = NULL;
1353 }
paul200df112005-06-01 11:17:05 +00001354 }
Daniel Walton363c9032015-10-21 06:42:54 -07001355
paul200df112005-06-01 11:17:05 +00001356 for (i = RMAP_IN; i < RMAP_MAX; i++)
1357 {
paul718e3742002-12-13 20:15:29 +00001358 if (filter->map[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001359 {
1360 free (filter->map[i].name);
1361 filter->map[i].name = NULL;
1362 }
paul718e3742002-12-13 20:15:29 +00001363 }
1364
1365 if (filter->usmap.name)
Daniel Walton363c9032015-10-21 06:42:54 -07001366 {
1367 free (filter->usmap.name);
1368 filter->usmap.name = NULL;
1369 }
paul718e3742002-12-13 20:15:29 +00001370
1371 if (peer->default_rmap[afi][safi].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001372 {
1373 free (peer->default_rmap[afi][safi].name);
1374 peer->default_rmap[afi][safi].name = NULL;
1375 }
paul718e3742002-12-13 20:15:29 +00001376 }
paul200df112005-06-01 11:17:05 +00001377
1378 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001379
1380 return 0;
1381}
David Lamparter6b0655a2014-06-04 06:53:35 +02001382
paul94f2b392005-06-28 12:44:16 +00001383static int
paul718e3742002-12-13 20:15:29 +00001384peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1385{
1386 return strcmp (g1->name, g2->name);
1387}
1388
1389/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001390static int
paul718e3742002-12-13 20:15:29 +00001391peer_group_active (struct peer *peer)
1392{
1393 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1394 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1395 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1396 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1397 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1398 return 1;
1399 return 0;
1400}
1401
1402/* Peer group cofiguration. */
1403static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001404peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001405{
1406 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1407 sizeof (struct peer_group));
1408}
1409
paul94f2b392005-06-28 12:44:16 +00001410static void
paul718e3742002-12-13 20:15:29 +00001411peer_group_free (struct peer_group *group)
1412{
1413 XFREE (MTYPE_PEER_GROUP, group);
1414}
1415
1416struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001417peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001418{
1419 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001420 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001421
paul1eb8ef22005-04-07 07:30:20 +00001422 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001423 {
1424 if (strcmp (group->name, name) == 0)
1425 return group;
1426 }
1427 return NULL;
1428}
1429
1430struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001431peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001432{
1433 struct peer_group *group;
1434
1435 group = peer_group_lookup (bgp, name);
1436 if (group)
1437 return group;
1438
1439 group = peer_group_new ();
1440 group->bgp = bgp;
1441 group->name = strdup (name);
1442 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001443 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001444 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1445 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001446 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001447 group->conf->group = group;
1448 group->conf->as = 0;
1449 group->conf->ttl = 1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001450 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001451 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1452 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1453 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1454 group->conf->keepalive = 0;
1455 group->conf->holdtime = 0;
1456 group->conf->connect = 0;
1457 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1458 listnode_add_sort (bgp->group, group);
1459
1460 return 0;
1461}
1462
paul94f2b392005-06-28 12:44:16 +00001463static void
paul718e3742002-12-13 20:15:29 +00001464peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1465 afi_t afi, safi_t safi)
1466{
1467 int in = FILTER_IN;
1468 int out = FILTER_OUT;
1469 struct peer *conf;
1470 struct bgp_filter *pfilter;
1471 struct bgp_filter *gfilter;
1472
1473 conf = group->conf;
1474 pfilter = &peer->filter[afi][safi];
1475 gfilter = &conf->filter[afi][safi];
1476
1477 /* remote-as */
1478 if (conf->as)
1479 peer->as = conf->as;
1480
1481 /* remote-as */
1482 if (conf->change_local_as)
1483 peer->change_local_as = conf->change_local_as;
1484
1485 /* TTL */
1486 peer->ttl = conf->ttl;
1487
Nick Hilliardfa411a22011-03-23 15:33:17 +00001488 /* GTSM hops */
1489 peer->gtsm_hops = conf->gtsm_hops;
1490
paul718e3742002-12-13 20:15:29 +00001491 /* Weight */
1492 peer->weight = conf->weight;
1493
1494 /* peer flags apply */
1495 peer->flags = conf->flags;
1496 /* peer af_flags apply */
1497 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1498 /* peer config apply */
1499 peer->config = conf->config;
1500
1501 /* peer timers apply */
1502 peer->holdtime = conf->holdtime;
1503 peer->keepalive = conf->keepalive;
1504 peer->connect = conf->connect;
1505 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1506 peer->v_connect = conf->connect;
1507 else
1508 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1509
1510 /* advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +03001511 if (CHECK_FLAG (conf->config, PEER_CONFIG_ROUTEADV))
1512 peer->v_routeadv = conf->routeadv;
paul718e3742002-12-13 20:15:29 +00001513 else
Daniel Walton0d7435f2015-10-22 11:35:20 +03001514 if (peer_sort (peer) == BGP_PEER_IBGP)
1515 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1516 else
1517 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul718e3742002-12-13 20:15:29 +00001518
Paul Jakma0df7c912008-07-21 21:02:49 +00001519 /* password apply */
Roman Hoog Antink0e4303d2013-01-18 13:52:03 +01001520 if (conf->password && !peer->password)
Paul Jakma0df7c912008-07-21 21:02:49 +00001521 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
Paul Jakma0df7c912008-07-21 21:02:49 +00001522
1523 bgp_md5_set (peer);
1524
paul718e3742002-12-13 20:15:29 +00001525 /* maximum-prefix */
1526 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001527 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001528 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001529
1530 /* allowas-in */
1531 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1532
paulfee0f4c2004-09-13 05:12:46 +00001533 /* route-server-client */
1534 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1535 {
1536 /* Make peer's RIB point to group's RIB. */
1537 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1538
1539 /* Import policy. */
1540 if (pfilter->map[RMAP_IMPORT].name)
1541 free (pfilter->map[RMAP_IMPORT].name);
1542 if (gfilter->map[RMAP_IMPORT].name)
1543 {
1544 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1545 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1546 }
1547 else
1548 {
1549 pfilter->map[RMAP_IMPORT].name = NULL;
1550 pfilter->map[RMAP_IMPORT].map = NULL;
1551 }
1552
1553 /* Export policy. */
1554 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1555 {
1556 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1557 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1558 }
1559 }
1560
paul718e3742002-12-13 20:15:29 +00001561 /* default-originate route-map */
1562 if (conf->default_rmap[afi][safi].name)
1563 {
1564 if (peer->default_rmap[afi][safi].name)
1565 free (peer->default_rmap[afi][safi].name);
1566 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1567 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1568 }
1569
1570 /* update-source apply */
1571 if (conf->update_source)
1572 {
1573 if (peer->update_source)
1574 sockunion_free (peer->update_source);
1575 if (peer->update_if)
1576 {
1577 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1578 peer->update_if = NULL;
1579 }
1580 peer->update_source = sockunion_dup (conf->update_source);
1581 }
1582 else if (conf->update_if)
1583 {
1584 if (peer->update_if)
1585 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1586 if (peer->update_source)
1587 {
1588 sockunion_free (peer->update_source);
1589 peer->update_source = NULL;
1590 }
1591 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1592 }
1593
1594 /* inbound filter apply */
1595 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1596 {
1597 if (pfilter->dlist[in].name)
1598 free (pfilter->dlist[in].name);
1599 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1600 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1601 }
1602 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1603 {
1604 if (pfilter->plist[in].name)
1605 free (pfilter->plist[in].name);
1606 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1607 pfilter->plist[in].plist = gfilter->plist[in].plist;
1608 }
1609 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1610 {
1611 if (pfilter->aslist[in].name)
1612 free (pfilter->aslist[in].name);
1613 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1614 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1615 }
paulfee0f4c2004-09-13 05:12:46 +00001616 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001617 {
paulfee0f4c2004-09-13 05:12:46 +00001618 if (pfilter->map[RMAP_IN].name)
1619 free (pfilter->map[RMAP_IN].name);
1620 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1621 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001622 }
1623
1624 /* outbound filter apply */
1625 if (gfilter->dlist[out].name)
1626 {
1627 if (pfilter->dlist[out].name)
1628 free (pfilter->dlist[out].name);
1629 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1630 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1631 }
1632 else
1633 {
1634 if (pfilter->dlist[out].name)
1635 free (pfilter->dlist[out].name);
1636 pfilter->dlist[out].name = NULL;
1637 pfilter->dlist[out].alist = NULL;
1638 }
1639 if (gfilter->plist[out].name)
1640 {
1641 if (pfilter->plist[out].name)
1642 free (pfilter->plist[out].name);
1643 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1644 pfilter->plist[out].plist = gfilter->plist[out].plist;
1645 }
1646 else
1647 {
1648 if (pfilter->plist[out].name)
1649 free (pfilter->plist[out].name);
1650 pfilter->plist[out].name = NULL;
1651 pfilter->plist[out].plist = NULL;
1652 }
1653 if (gfilter->aslist[out].name)
1654 {
1655 if (pfilter->aslist[out].name)
1656 free (pfilter->aslist[out].name);
1657 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1658 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1659 }
1660 else
1661 {
1662 if (pfilter->aslist[out].name)
1663 free (pfilter->aslist[out].name);
1664 pfilter->aslist[out].name = NULL;
1665 pfilter->aslist[out].aslist = NULL;
1666 }
paulfee0f4c2004-09-13 05:12:46 +00001667 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001668 {
paulfee0f4c2004-09-13 05:12:46 +00001669 if (pfilter->map[RMAP_OUT].name)
1670 free (pfilter->map[RMAP_OUT].name);
1671 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1672 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001673 }
1674 else
1675 {
paulfee0f4c2004-09-13 05:12:46 +00001676 if (pfilter->map[RMAP_OUT].name)
1677 free (pfilter->map[RMAP_OUT].name);
1678 pfilter->map[RMAP_OUT].name = NULL;
1679 pfilter->map[RMAP_OUT].map = NULL;
1680 }
1681
1682 /* RS-client's import/export route-maps. */
1683 if (gfilter->map[RMAP_IMPORT].name)
1684 {
1685 if (pfilter->map[RMAP_IMPORT].name)
1686 free (pfilter->map[RMAP_IMPORT].name);
1687 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1688 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1689 }
1690 else
1691 {
1692 if (pfilter->map[RMAP_IMPORT].name)
1693 free (pfilter->map[RMAP_IMPORT].name);
1694 pfilter->map[RMAP_IMPORT].name = NULL;
1695 pfilter->map[RMAP_IMPORT].map = NULL;
1696 }
1697 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1698 {
1699 if (pfilter->map[RMAP_EXPORT].name)
1700 free (pfilter->map[RMAP_EXPORT].name);
1701 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1702 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001703 }
1704
1705 if (gfilter->usmap.name)
1706 {
1707 if (pfilter->usmap.name)
1708 free (pfilter->usmap.name);
1709 pfilter->usmap.name = strdup (gfilter->usmap.name);
1710 pfilter->usmap.map = gfilter->usmap.map;
1711 }
1712 else
1713 {
1714 if (pfilter->usmap.name)
1715 free (pfilter->usmap.name);
1716 pfilter->usmap.name = NULL;
1717 pfilter->usmap.map = NULL;
1718 }
1719}
1720
1721/* Peer group's remote AS configuration. */
1722int
paulfd79ac92004-10-13 05:06:08 +00001723peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001724{
1725 struct peer_group *group;
1726 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001727 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001728
1729 group = peer_group_lookup (bgp, group_name);
1730 if (! group)
1731 return -1;
1732
1733 if (group->conf->as == *as)
1734 return 0;
1735
1736 /* When we setup peer-group AS number all peer group member's AS
1737 number must be updated to same number. */
1738 peer_as_change (group->conf, *as);
1739
paul1eb8ef22005-04-07 07:30:20 +00001740 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001741 {
1742 if (peer->as != *as)
1743 peer_as_change (peer, *as);
1744 }
1745
1746 return 0;
1747}
1748
1749int
1750peer_group_delete (struct peer_group *group)
1751{
1752 struct bgp *bgp;
1753 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001754 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001755
1756 bgp = group->bgp;
1757
paul1eb8ef22005-04-07 07:30:20 +00001758 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001759 {
paul718e3742002-12-13 20:15:29 +00001760 peer_delete (peer);
1761 }
1762 list_delete (group->peer);
1763
1764 free (group->name);
1765 group->name = NULL;
1766
1767 group->conf->group = NULL;
1768 peer_delete (group->conf);
1769
1770 /* Delete from all peer_group list. */
1771 listnode_delete (bgp->group, group);
1772
1773 peer_group_free (group);
1774
1775 return 0;
1776}
1777
1778int
1779peer_group_remote_as_delete (struct peer_group *group)
1780{
1781 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001782 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001783
1784 if (! group->conf->as)
1785 return 0;
1786
paul1eb8ef22005-04-07 07:30:20 +00001787 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001788 {
paul718e3742002-12-13 20:15:29 +00001789 peer_delete (peer);
1790 }
1791 list_delete_all_node (group->peer);
1792
1793 group->conf->as = 0;
1794
1795 return 0;
1796}
1797
1798/* Bind specified peer to peer group. */
1799int
1800peer_group_bind (struct bgp *bgp, union sockunion *su,
1801 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1802{
1803 struct peer *peer;
1804 int first_member = 0;
1805
1806 /* Check peer group's address family. */
1807 if (! group->conf->afc[afi][safi])
1808 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1809
1810 /* Lookup the peer. */
1811 peer = peer_lookup (bgp, su);
1812
1813 /* Create a new peer. */
1814 if (! peer)
1815 {
1816 if (! group->conf->as)
1817 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1818
1819 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1820 peer->group = group;
1821 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001822
Paul Jakmaca058a32006-09-14 02:58:49 +00001823 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001824 listnode_add (group->peer, peer);
1825 peer_group2peer_config_copy (group, peer, afi, safi);
1826
1827 return 0;
1828 }
1829
1830 /* When the peer already belongs to peer group, check the consistency. */
1831 if (peer->af_group[afi][safi])
1832 {
1833 if (strcmp (peer->group->name, group->name) != 0)
1834 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1835
1836 return 0;
1837 }
1838
1839 /* Check current peer group configuration. */
1840 if (peer_group_active (peer)
1841 && strcmp (peer->group->name, group->name) != 0)
1842 return BGP_ERR_PEER_GROUP_MISMATCH;
1843
1844 if (! group->conf->as)
1845 {
1846 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1847 && peer_sort (group->conf) != peer_sort (peer))
1848 {
1849 if (as)
1850 *as = peer->as;
1851 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1852 }
1853
1854 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1855 first_member = 1;
1856 }
1857
1858 peer->af_group[afi][safi] = 1;
1859 peer->afc[afi][safi] = 1;
1860 if (! peer->group)
1861 {
1862 peer->group = group;
paul200df112005-06-01 11:17:05 +00001863
Paul Jakmaca058a32006-09-14 02:58:49 +00001864 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001865 listnode_add (group->peer, peer);
1866 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001867 else
1868 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001869
1870 if (first_member)
1871 {
1872 /* Advertisement-interval reset */
Daniel Walton0d7435f2015-10-22 11:35:20 +03001873 if (! CHECK_FLAG (group->conf->config, PEER_CONFIG_ROUTEADV))
1874 {
1875 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1876 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1877 else
1878 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1879 }
paul718e3742002-12-13 20:15:29 +00001880
1881 /* ebgp-multihop reset */
1882 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1883 group->conf->ttl = 255;
1884
1885 /* local-as reset */
1886 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1887 {
1888 group->conf->change_local_as = 0;
1889 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001890 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001891 }
1892 }
paulfee0f4c2004-09-13 05:12:46 +00001893
1894 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1895 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001896 struct listnode *pn;
1897
paulfee0f4c2004-09-13 05:12:46 +00001898 /* If it's not configured as RSERVER_CLIENT in any other address
1899 family, without being member of a peer_group, remove it from
1900 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001901 if (! peer_rsclient_active (peer)
1902 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001903 {
1904 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001905 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001906
1907 /* Clear our own rsclient rib for this afi/safi. */
1908 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001909 }
paulfee0f4c2004-09-13 05:12:46 +00001910
Paul Jakmab608d5b2008-07-02 02:12:07 +00001911 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001912
1913 /* Import policy. */
1914 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1915 {
1916 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1917 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1918 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1919 }
1920
1921 /* Export policy. */
1922 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1923 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1924 {
1925 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1926 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1927 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1928 }
1929 }
1930
paul718e3742002-12-13 20:15:29 +00001931 peer_group2peer_config_copy (group, peer, afi, safi);
1932
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001933 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001934 {
1935 peer->last_reset = PEER_DOWN_RMAP_BIND;
1936 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1937 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1938 }
paul718e3742002-12-13 20:15:29 +00001939 else
1940 BGP_EVENT_ADD (peer, BGP_Stop);
1941
1942 return 0;
1943}
1944
1945int
1946peer_group_unbind (struct bgp *bgp, struct peer *peer,
1947 struct peer_group *group, afi_t afi, safi_t safi)
1948{
1949 if (! peer->af_group[afi][safi])
1950 return 0;
1951
1952 if (group != peer->group)
1953 return BGP_ERR_PEER_GROUP_MISMATCH;
1954
1955 peer->af_group[afi][safi] = 0;
1956 peer->afc[afi][safi] = 0;
1957 peer_af_flag_reset (peer, afi, safi);
1958
paulfee0f4c2004-09-13 05:12:46 +00001959 if (peer->rib[afi][safi])
1960 peer->rib[afi][safi] = NULL;
1961
paul718e3742002-12-13 20:15:29 +00001962 if (! peer_group_active (peer))
1963 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001964 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001965 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001966 listnode_delete (group->peer, peer);
1967 peer->group = NULL;
1968 if (group->conf->as)
1969 {
1970 peer_delete (peer);
1971 return 0;
1972 }
1973 peer_global_config_reset (peer);
1974 }
1975
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001976 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001977 {
1978 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1979 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1980 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1981 }
paul718e3742002-12-13 20:15:29 +00001982 else
1983 BGP_EVENT_ADD (peer, BGP_Stop);
1984
1985 return 0;
1986}
David Lamparter6b0655a2014-06-04 06:53:35 +02001987
Vipin Kumardd49eb12014-09-30 14:36:38 -07001988
1989static int
1990bgp_startup_timer_expire (struct thread *thread)
1991{
1992 struct bgp *bgp;
1993
1994 bgp = THREAD_ARG (thread);
1995 bgp->t_startup = NULL;
1996
1997 return 0;
1998}
1999
paul718e3742002-12-13 20:15:29 +00002000/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00002001static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002002bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002003{
2004 struct bgp *bgp;
2005 afi_t afi;
2006 safi_t safi;
2007
paul200df112005-06-01 11:17:05 +00002008 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
2009 return NULL;
2010
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002011 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00002012 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00002013 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00002014
2015 bgp->peer = list_new ();
2016 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
2017
2018 bgp->group = list_new ();
2019 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
2020
paulfee0f4c2004-09-13 05:12:46 +00002021 bgp->rsclient = list_new ();
2022 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
2023
paul718e3742002-12-13 20:15:29 +00002024 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2025 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2026 {
Paul Jakma64e580a2006-02-21 01:09:01 +00002027 bgp->route[afi][safi] = bgp_table_init (afi, safi);
2028 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
2029 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07002030 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
2031 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00002032 }
2033
2034 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
2035 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
2036 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00002037 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
2038 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07002039 bgp_flag_set (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES);
paul718e3742002-12-13 20:15:29 +00002040
2041 bgp->as = *as;
2042
2043 if (name)
2044 bgp->name = strdup (name);
2045
Donald Sharp774914f2015-10-14 08:50:39 -04002046 THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire,
Vipin Kumardd49eb12014-09-30 14:36:38 -07002047 bgp, bgp->restart_time);
2048
paul718e3742002-12-13 20:15:29 +00002049 return bgp;
2050}
2051
2052/* Return first entry of BGP. */
2053struct bgp *
paul94f2b392005-06-28 12:44:16 +00002054bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00002055{
Lou Berger056f3762013-04-10 12:30:04 -07002056 if (bm && bm->bgp && bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00002057 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00002058 return NULL;
2059}
2060
2061/* Lookup BGP entry. */
2062struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002063bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00002064{
2065 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002066 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002067
paul1eb8ef22005-04-07 07:30:20 +00002068 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002069 if (bgp->as == as
2070 && ((bgp->name == NULL && name == NULL)
2071 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
2072 return bgp;
2073 return NULL;
2074}
2075
2076/* Lookup BGP structure by view name. */
2077struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002078bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002079{
2080 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002081 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002082
paul1eb8ef22005-04-07 07:30:20 +00002083 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002084 if ((bgp->name == NULL && name == NULL)
2085 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2086 return bgp;
2087 return NULL;
2088}
2089
2090/* Called from VTY commands. */
2091int
paulfd79ac92004-10-13 05:06:08 +00002092bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002093{
2094 struct bgp *bgp;
2095
2096 /* Multiple instance check. */
2097 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2098 {
2099 if (name)
2100 bgp = bgp_lookup_by_name (name);
2101 else
2102 bgp = bgp_get_default ();
2103
2104 /* Already exists. */
2105 if (bgp)
2106 {
2107 if (bgp->as != *as)
2108 {
2109 *as = bgp->as;
2110 return BGP_ERR_INSTANCE_MISMATCH;
2111 }
2112 *bgp_val = bgp;
2113 return 0;
2114 }
2115 }
2116 else
2117 {
2118 /* BGP instance name can not be specified for single instance. */
2119 if (name)
2120 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2121
2122 /* Get default BGP structure if exists. */
2123 bgp = bgp_get_default ();
2124
2125 if (bgp)
2126 {
2127 if (bgp->as != *as)
2128 {
2129 *as = bgp->as;
2130 return BGP_ERR_AS_MISMATCH;
2131 }
2132 *bgp_val = bgp;
2133 return 0;
2134 }
2135 }
2136
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002137 bgp = bgp_create (as, name);
2138 bgp_router_id_set(bgp, &router_id_zebra);
2139 *bgp_val = bgp;
2140
Paul Jakmaad12dde2012-06-13 22:50:07 +01002141 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002142 if (list_isempty(bm->bgp)
2143 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002144 {
2145 if (bgp_socket (bm->port, bm->address) < 0)
2146 return BGP_ERR_INVALID_VALUE;
2147 }
2148
paul718e3742002-12-13 20:15:29 +00002149 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002150
2151 return 0;
2152}
2153
2154/* Delete BGP instance. */
2155int
2156bgp_delete (struct bgp *bgp)
2157{
2158 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002159 struct peer_group *group;
Denil Vira57cd5e72015-08-10 12:46:14 -07002160 struct listnode *node, *pnode;
2161 struct listnode *next, *pnext;
paul718e3742002-12-13 20:15:29 +00002162 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002163 int i;
2164
David Lampartercffe7802014-12-07 03:27:13 +01002165 THREAD_OFF (bgp->t_startup);
2166
paul718e3742002-12-13 20:15:29 +00002167 /* Delete static route. */
2168 bgp_static_delete (bgp);
2169
2170 /* Unset redistribution. */
2171 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2172 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2173 if (i != ZEBRA_ROUTE_BGP)
2174 bgp_redistribute_unset (bgp, afi, i);
2175
paul1eb8ef22005-04-07 07:30:20 +00002176 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002177 {
2178 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2179 {
2180 /* Send notify to remote peer. */
2181 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2182 }
2183
2184 peer_delete (peer);
2185 }
paul718e3742002-12-13 20:15:29 +00002186
Chris Caputo228da422009-07-18 05:44:03 +00002187 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002188 {
Denil Vira57cd5e72015-08-10 12:46:14 -07002189 for (ALL_LIST_ELEMENTS (group->peer, pnode, pnext, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002190 {
2191 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2192 {
2193 /* Send notify to remote peer. */
2194 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2195 }
2196 }
2197 peer_group_delete (group);
2198 }
Chris Caputo228da422009-07-18 05:44:03 +00002199
2200 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002201
2202 if (bgp->peer_self) {
2203 peer_delete(bgp->peer_self);
2204 bgp->peer_self = NULL;
2205 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002206
2207 /* Remove visibility via the master list - there may however still be
2208 * routes to be processed still referencing the struct bgp.
2209 */
2210 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002211 if (list_isempty(bm->bgp))
2212 bgp_close ();
2213
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002214 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002215
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002216 return 0;
2217}
2218
2219static void bgp_free (struct bgp *);
2220
2221void
2222bgp_lock (struct bgp *bgp)
2223{
2224 ++bgp->lock;
2225}
2226
2227void
2228bgp_unlock(struct bgp *bgp)
2229{
Chris Caputo228da422009-07-18 05:44:03 +00002230 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002231 if (--bgp->lock == 0)
2232 bgp_free (bgp);
2233}
2234
2235static void
2236bgp_free (struct bgp *bgp)
2237{
2238 afi_t afi;
2239 safi_t safi;
2240
2241 list_delete (bgp->group);
2242 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002243 list_delete (bgp->rsclient);
2244
paul718e3742002-12-13 20:15:29 +00002245 if (bgp->name)
2246 free (bgp->name);
2247
2248 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2249 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2250 {
2251 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002252 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002253 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002254 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002255 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002256 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002257 }
2258 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002259}
David Lamparter6b0655a2014-06-04 06:53:35 +02002260
paul718e3742002-12-13 20:15:29 +00002261struct peer *
2262peer_lookup (struct bgp *bgp, union sockunion *su)
2263{
2264 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002265 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002266
Steve Hillfc4dc592009-07-28 17:54:35 +01002267 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002268 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002269 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2270 if (sockunion_same (&peer->su, su)
2271 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2272 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002273 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002274 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002275 {
2276 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002277
Paul Jakma2158ad22009-07-28 18:10:55 +01002278 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2279 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2280 if (sockunion_same (&peer->su, su)
2281 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2282 return peer;
paul718e3742002-12-13 20:15:29 +00002283 }
2284 return NULL;
2285}
2286
2287struct peer *
2288peer_lookup_with_open (union sockunion *su, as_t remote_as,
2289 struct in_addr *remote_id, int *as)
2290{
2291 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002292 struct listnode *node;
2293 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002294 struct bgp *bgp;
2295
Steve Hillfc4dc592009-07-28 17:54:35 +01002296 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002297 return NULL;
2298
Paul Jakma9d878772009-08-05 16:25:16 +01002299 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002300 {
Paul Jakma9d878772009-08-05 16:25:16 +01002301 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2302 {
2303 if (sockunion_same (&peer->su, su)
2304 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2305 {
2306 if (peer->as == remote_as
2307 && peer->remote_id.s_addr == remote_id->s_addr)
2308 return peer;
2309 if (peer->as == remote_as)
2310 *as = 1;
2311 }
2312 }
2313
2314 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2315 {
2316 if (sockunion_same (&peer->su, su)
2317 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2318 {
2319 if (peer->as == remote_as
2320 && peer->remote_id.s_addr == 0)
2321 return peer;
2322 if (peer->as == remote_as)
2323 *as = 1;
2324 }
2325 }
paul718e3742002-12-13 20:15:29 +00002326 }
2327 return NULL;
2328}
David Lamparter6b0655a2014-06-04 06:53:35 +02002329
paul718e3742002-12-13 20:15:29 +00002330/* If peer is configured at least one address family return 1. */
2331int
2332peer_active (struct peer *peer)
2333{
2334 if (peer->afc[AFI_IP][SAFI_UNICAST]
2335 || peer->afc[AFI_IP][SAFI_MULTICAST]
2336 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2337 || peer->afc[AFI_IP6][SAFI_UNICAST]
2338 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2339 return 1;
2340 return 0;
2341}
2342
2343/* If peer is negotiated at least one address family return 1. */
2344int
2345peer_active_nego (struct peer *peer)
2346{
2347 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2348 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2349 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2350 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2351 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2352 return 1;
2353 return 0;
2354}
David Lamparter6b0655a2014-06-04 06:53:35 +02002355
paul718e3742002-12-13 20:15:29 +00002356/* peer_flag_change_type. */
2357enum peer_change_type
2358{
2359 peer_change_none,
2360 peer_change_reset,
2361 peer_change_reset_in,
2362 peer_change_reset_out,
2363};
2364
paul94f2b392005-06-28 12:44:16 +00002365static void
paul718e3742002-12-13 20:15:29 +00002366peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2367 enum peer_change_type type)
2368{
2369 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2370 return;
2371
Stephen Hemmingerd9d4ae52010-01-13 00:32:39 +00002372 if (peer->status != Established)
2373 return;
2374
paul718e3742002-12-13 20:15:29 +00002375 if (type == peer_change_reset)
2376 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2377 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2378 else if (type == peer_change_reset_in)
2379 {
2380 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2381 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2382 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2383 else
2384 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2385 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2386 }
2387 else if (type == peer_change_reset_out)
2388 bgp_announce_route (peer, afi, safi);
2389}
2390
2391struct peer_flag_action
2392{
2393 /* Peer's flag. */
2394 u_int32_t flag;
2395
2396 /* This flag can be set for peer-group member. */
2397 u_char not_for_member;
2398
2399 /* Action when the flag is changed. */
2400 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002401
2402 /* Peer down cause */
2403 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002404};
2405
Stephen Hemminger03621952009-07-21 16:27:20 -07002406static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002407 {
2408 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2409 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2410 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2411 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2412 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002413 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002414 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002415 { 0, 0, 0 }
2416 };
2417
Stephen Hemminger03621952009-07-21 16:27:20 -07002418static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002419 {
2420 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2421 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2422 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2423 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2424 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2425 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2426 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2427 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2428 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2429 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2430 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2431 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2432 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002433 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
Timo Teräs9e7a53c2014-04-24 10:22:37 +03002434 { PEER_FLAG_NEXTHOP_SELF_ALL, 1, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002435 { 0, 0, 0 }
2436 };
2437
2438/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002439static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002440peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002441 struct peer_flag_action *action, u_int32_t flag)
2442{
2443 int i;
2444 int found = 0;
2445 int reset_in = 0;
2446 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002447 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002448
2449 /* Check peer's frag action. */
2450 for (i = 0; i < size; i++)
2451 {
2452 match = &action_list[i];
2453
2454 if (match->flag == 0)
2455 break;
2456
2457 if (match->flag & flag)
2458 {
2459 found = 1;
2460
2461 if (match->type == peer_change_reset_in)
2462 reset_in = 1;
2463 if (match->type == peer_change_reset_out)
2464 reset_out = 1;
2465 if (match->type == peer_change_reset)
2466 {
2467 reset_in = 1;
2468 reset_out = 1;
2469 }
2470 if (match->not_for_member)
2471 action->not_for_member = 1;
2472 }
2473 }
2474
2475 /* Set peer clear type. */
2476 if (reset_in && reset_out)
2477 action->type = peer_change_reset;
2478 else if (reset_in)
2479 action->type = peer_change_reset_in;
2480 else if (reset_out)
2481 action->type = peer_change_reset_out;
2482 else
2483 action->type = peer_change_none;
2484
2485 return found;
2486}
2487
paul94f2b392005-06-28 12:44:16 +00002488static void
paul718e3742002-12-13 20:15:29 +00002489peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2490{
2491 if (flag == PEER_FLAG_SHUTDOWN)
2492 {
2493 if (CHECK_FLAG (peer->flags, flag))
2494 {
hasso93406d82005-02-02 14:40:33 +00002495 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2496 peer_nsf_stop (peer);
2497
hasso0a486e52005-02-01 20:57:17 +00002498 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2499 if (peer->t_pmax_restart)
2500 {
2501 BGP_TIMER_OFF (peer->t_pmax_restart);
2502 if (BGP_DEBUG (events, EVENTS))
2503 zlog_debug ("%s Maximum-prefix restart timer canceled",
2504 peer->host);
2505 }
2506
hasso93406d82005-02-02 14:40:33 +00002507 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2508 peer_nsf_stop (peer);
2509
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002510 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002511 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2512 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2513 else
2514 BGP_EVENT_ADD (peer, BGP_Stop);
2515 }
2516 else
2517 {
2518 peer->v_start = BGP_INIT_START_TIMER;
2519 BGP_EVENT_ADD (peer, BGP_Stop);
2520 }
2521 }
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002522 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002523 {
hassoc9502432005-02-01 22:01:48 +00002524 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2525 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2526 else if (flag == PEER_FLAG_PASSIVE)
2527 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002528 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002529 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002530
hassoc9502432005-02-01 22:01:48 +00002531 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2532 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002533 }
2534 else
2535 BGP_EVENT_ADD (peer, BGP_Stop);
2536}
2537
2538/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002539static int
paul718e3742002-12-13 20:15:29 +00002540peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2541{
2542 int found;
2543 int size;
2544 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002545 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002546 struct peer_flag_action action;
2547
2548 memset (&action, 0, sizeof (struct peer_flag_action));
2549 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2550
2551 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2552
2553 /* No flag action is found. */
2554 if (! found)
2555 return BGP_ERR_INVALID_FLAG;
2556
2557 /* Not for peer-group member. */
2558 if (action.not_for_member && peer_group_active (peer))
2559 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2560
2561 /* When unset the peer-group member's flag we have to check
2562 peer-group configuration. */
2563 if (! set && peer_group_active (peer))
2564 if (CHECK_FLAG (peer->group->conf->flags, flag))
2565 {
2566 if (flag == PEER_FLAG_SHUTDOWN)
2567 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2568 else
2569 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2570 }
2571
2572 /* Flag conflict check. */
2573 if (set
2574 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2575 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2576 return BGP_ERR_PEER_FLAG_CONFLICT;
2577
2578 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2579 {
2580 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2581 return 0;
2582 if (! set && ! CHECK_FLAG (peer->flags, flag))
2583 return 0;
2584 }
2585
2586 if (set)
2587 SET_FLAG (peer->flags, flag);
2588 else
2589 UNSET_FLAG (peer->flags, flag);
2590
2591 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2592 {
2593 if (action.type == peer_change_reset)
2594 peer_flag_modify_action (peer, flag);
2595
2596 return 0;
2597 }
2598
2599 /* peer-group member updates. */
2600 group = peer->group;
2601
paul1eb8ef22005-04-07 07:30:20 +00002602 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002603 {
2604 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2605 continue;
2606
2607 if (! set && ! CHECK_FLAG (peer->flags, flag))
2608 continue;
2609
2610 if (set)
2611 SET_FLAG (peer->flags, flag);
2612 else
2613 UNSET_FLAG (peer->flags, flag);
2614
2615 if (action.type == peer_change_reset)
2616 peer_flag_modify_action (peer, flag);
2617 }
2618 return 0;
2619}
2620
2621int
2622peer_flag_set (struct peer *peer, u_int32_t flag)
2623{
2624 return peer_flag_modify (peer, flag, 1);
2625}
2626
2627int
2628peer_flag_unset (struct peer *peer, u_int32_t flag)
2629{
2630 return peer_flag_modify (peer, flag, 0);
2631}
2632
paul94f2b392005-06-28 12:44:16 +00002633static int
paul718e3742002-12-13 20:15:29 +00002634peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2635{
2636 if (peer->af_group[afi][safi])
2637 return 1;
2638 return 0;
2639}
2640
paul94f2b392005-06-28 12:44:16 +00002641static int
paul718e3742002-12-13 20:15:29 +00002642peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2643 int set)
2644{
2645 int found;
2646 int size;
paul1eb8ef22005-04-07 07:30:20 +00002647 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002648 struct peer_group *group;
2649 struct peer_flag_action action;
2650
2651 memset (&action, 0, sizeof (struct peer_flag_action));
2652 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2653
2654 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2655
2656 /* No flag action is found. */
2657 if (! found)
2658 return BGP_ERR_INVALID_FLAG;
2659
2660 /* Adress family must be activated. */
2661 if (! peer->afc[afi][safi])
2662 return BGP_ERR_PEER_INACTIVE;
2663
2664 /* Not for peer-group member. */
2665 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2666 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2667
2668 /* Spcecial check for reflector client. */
2669 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2670 && peer_sort (peer) != BGP_PEER_IBGP)
2671 return BGP_ERR_NOT_INTERNAL_PEER;
2672
2673 /* Spcecial check for remove-private-AS. */
2674 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2675 && peer_sort (peer) == BGP_PEER_IBGP)
2676 return BGP_ERR_REMOVE_PRIVATE_AS;
2677
2678 /* When unset the peer-group member's flag we have to check
2679 peer-group configuration. */
2680 if (! set && peer->af_group[afi][safi])
2681 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2682 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2683
2684 /* When current flag configuration is same as requested one. */
2685 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2686 {
2687 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2688 return 0;
2689 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2690 return 0;
2691 }
2692
2693 if (set)
2694 SET_FLAG (peer->af_flags[afi][safi], flag);
2695 else
2696 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2697
2698 /* Execute action when peer is established. */
2699 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2700 && peer->status == Established)
2701 {
2702 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2703 bgp_clear_adj_in (peer, afi, safi);
2704 else
hassoe0701b72004-05-20 09:19:34 +00002705 {
2706 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2707 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2708 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2709 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2710 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2711 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2712 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2713 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2714
2715 peer_change_action (peer, afi, safi, action.type);
2716 }
2717
paul718e3742002-12-13 20:15:29 +00002718 }
2719
2720 /* Peer group member updates. */
2721 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2722 {
2723 group = peer->group;
2724
paul1eb8ef22005-04-07 07:30:20 +00002725 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002726 {
2727 if (! peer->af_group[afi][safi])
2728 continue;
2729
2730 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2731 continue;
2732
2733 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2734 continue;
2735
2736 if (set)
2737 SET_FLAG (peer->af_flags[afi][safi], flag);
2738 else
2739 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2740
2741 if (peer->status == Established)
2742 {
2743 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2744 bgp_clear_adj_in (peer, afi, safi);
2745 else
hassoe0701b72004-05-20 09:19:34 +00002746 {
2747 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2748 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2749 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2750 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2751 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2752 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2753 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2754 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2755
2756 peer_change_action (peer, afi, safi, action.type);
2757 }
paul718e3742002-12-13 20:15:29 +00002758 }
2759 }
2760 }
2761 return 0;
2762}
2763
2764int
2765peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2766{
2767 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2768}
2769
2770int
2771peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2772{
2773 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2774}
David Lamparter6b0655a2014-06-04 06:53:35 +02002775
paul718e3742002-12-13 20:15:29 +00002776/* EBGP multihop configuration. */
2777int
2778peer_ebgp_multihop_set (struct peer *peer, int ttl)
2779{
2780 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002781 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002782 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002783
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002784 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002785 return 0;
2786
Nick Hilliardfa411a22011-03-23 15:33:17 +00002787 /* see comment in peer_ttl_security_hops_set() */
2788 if (ttl != MAXTTL)
2789 {
2790 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2791 {
2792 group = peer->group;
2793 if (group->conf->gtsm_hops != 0)
2794 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2795
2796 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2797 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002798 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002799 continue;
2800
2801 if (peer1->gtsm_hops != 0)
2802 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2803 }
2804 }
2805 else
2806 {
2807 if (peer->gtsm_hops != 0)
2808 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2809 }
2810 }
2811
paul718e3742002-12-13 20:15:29 +00002812 peer->ttl = ttl;
2813
2814 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2815 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002816 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002817 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002818 }
2819 else
2820 {
2821 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002822 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002823 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002824 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002825 continue;
paul718e3742002-12-13 20:15:29 +00002826
pauleb821182004-05-01 08:44:08 +00002827 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002828
pauleb821182004-05-01 08:44:08 +00002829 if (peer->fd >= 0)
2830 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2831 }
paul718e3742002-12-13 20:15:29 +00002832 }
2833 return 0;
2834}
2835
2836int
2837peer_ebgp_multihop_unset (struct peer *peer)
2838{
2839 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002840 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002841
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002842 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002843 return 0;
2844
Nick Hilliardfa411a22011-03-23 15:33:17 +00002845 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2846 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2847
paul718e3742002-12-13 20:15:29 +00002848 if (peer_group_active (peer))
2849 peer->ttl = peer->group->conf->ttl;
2850 else
2851 peer->ttl = 1;
2852
2853 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2854 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002855 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002856 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002857 }
2858 else
2859 {
2860 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002861 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002862 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002863 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002864 continue;
paul718e3742002-12-13 20:15:29 +00002865
pauleb821182004-05-01 08:44:08 +00002866 peer->ttl = 1;
2867
2868 if (peer->fd >= 0)
2869 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2870 }
paul718e3742002-12-13 20:15:29 +00002871 }
2872 return 0;
2873}
David Lamparter6b0655a2014-06-04 06:53:35 +02002874
paul718e3742002-12-13 20:15:29 +00002875/* Neighbor description. */
2876int
2877peer_description_set (struct peer *peer, char *desc)
2878{
2879 if (peer->desc)
2880 XFREE (MTYPE_PEER_DESC, peer->desc);
2881
2882 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2883
2884 return 0;
2885}
2886
2887int
2888peer_description_unset (struct peer *peer)
2889{
2890 if (peer->desc)
2891 XFREE (MTYPE_PEER_DESC, peer->desc);
2892
2893 peer->desc = NULL;
2894
2895 return 0;
2896}
David Lamparter6b0655a2014-06-04 06:53:35 +02002897
paul718e3742002-12-13 20:15:29 +00002898/* Neighbor update-source. */
2899int
paulfd79ac92004-10-13 05:06:08 +00002900peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002901{
2902 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002903 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002904
2905 if (peer->update_if)
2906 {
2907 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2908 && strcmp (peer->update_if, ifname) == 0)
2909 return 0;
2910
2911 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2912 peer->update_if = NULL;
2913 }
2914
2915 if (peer->update_source)
2916 {
2917 sockunion_free (peer->update_source);
2918 peer->update_source = NULL;
2919 }
2920
2921 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2922
2923 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2924 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002925 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002926 {
2927 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2928 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2929 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2930 }
paul718e3742002-12-13 20:15:29 +00002931 else
2932 BGP_EVENT_ADD (peer, BGP_Stop);
2933 return 0;
2934 }
2935
2936 /* peer-group member updates. */
2937 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002938 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002939 {
2940 if (peer->update_if)
2941 {
2942 if (strcmp (peer->update_if, ifname) == 0)
2943 continue;
2944
2945 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2946 peer->update_if = NULL;
2947 }
2948
2949 if (peer->update_source)
2950 {
2951 sockunion_free (peer->update_source);
2952 peer->update_source = NULL;
2953 }
2954
2955 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2956
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002957 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002958 {
2959 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2960 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2961 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2962 }
paul718e3742002-12-13 20:15:29 +00002963 else
2964 BGP_EVENT_ADD (peer, BGP_Stop);
2965 }
2966 return 0;
2967}
2968
2969int
2970peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2971{
2972 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002973 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002974
2975 if (peer->update_source)
2976 {
2977 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2978 && sockunion_cmp (peer->update_source, su) == 0)
2979 return 0;
2980 sockunion_free (peer->update_source);
2981 peer->update_source = NULL;
2982 }
2983
2984 if (peer->update_if)
2985 {
2986 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2987 peer->update_if = NULL;
2988 }
2989
2990 peer->update_source = sockunion_dup (su);
2991
2992 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2993 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002994 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002995 {
2996 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2997 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2998 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2999 }
paul718e3742002-12-13 20:15:29 +00003000 else
3001 BGP_EVENT_ADD (peer, BGP_Stop);
3002 return 0;
3003 }
3004
3005 /* peer-group member updates. */
3006 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003007 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003008 {
3009 if (peer->update_source)
3010 {
3011 if (sockunion_cmp (peer->update_source, su) == 0)
3012 continue;
3013 sockunion_free (peer->update_source);
3014 peer->update_source = NULL;
3015 }
3016
3017 if (peer->update_if)
3018 {
3019 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3020 peer->update_if = NULL;
3021 }
3022
3023 peer->update_source = sockunion_dup (su);
3024
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003025 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003026 {
3027 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3028 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3029 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3030 }
paul718e3742002-12-13 20:15:29 +00003031 else
3032 BGP_EVENT_ADD (peer, BGP_Stop);
3033 }
3034 return 0;
3035}
3036
3037int
3038peer_update_source_unset (struct peer *peer)
3039{
3040 union sockunion *su;
3041 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003042 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003043
3044 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3045 && ! peer->update_source
3046 && ! peer->update_if)
3047 return 0;
3048
3049 if (peer->update_source)
3050 {
3051 sockunion_free (peer->update_source);
3052 peer->update_source = NULL;
3053 }
3054 if (peer->update_if)
3055 {
3056 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3057 peer->update_if = NULL;
3058 }
3059
3060 if (peer_group_active (peer))
3061 {
3062 group = peer->group;
3063
3064 if (group->conf->update_source)
3065 {
3066 su = sockunion_dup (group->conf->update_source);
3067 peer->update_source = su;
3068 }
3069 else if (group->conf->update_if)
3070 peer->update_if =
3071 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
3072 }
3073
3074 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3075 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003076 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003077 {
3078 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3079 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3080 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3081 }
paul718e3742002-12-13 20:15:29 +00003082 else
3083 BGP_EVENT_ADD (peer, BGP_Stop);
3084 return 0;
3085 }
3086
3087 /* peer-group member updates. */
3088 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003089 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003090 {
3091 if (! peer->update_source && ! peer->update_if)
3092 continue;
3093
3094 if (peer->update_source)
3095 {
3096 sockunion_free (peer->update_source);
3097 peer->update_source = NULL;
3098 }
3099
3100 if (peer->update_if)
3101 {
3102 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3103 peer->update_if = NULL;
3104 }
3105
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003106 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003107 {
3108 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3109 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3110 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3111 }
paul718e3742002-12-13 20:15:29 +00003112 else
3113 BGP_EVENT_ADD (peer, BGP_Stop);
3114 }
3115 return 0;
3116}
David Lamparter6b0655a2014-06-04 06:53:35 +02003117
paul718e3742002-12-13 20:15:29 +00003118int
3119peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003120 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003121{
3122 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003123 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003124
3125 /* Adress family must be activated. */
3126 if (! peer->afc[afi][safi])
3127 return BGP_ERR_PEER_INACTIVE;
3128
3129 /* Default originate can't be used for peer group memeber. */
3130 if (peer_is_group_member (peer, afi, safi))
3131 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3132
3133 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3134 || (rmap && ! peer->default_rmap[afi][safi].name)
3135 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3136 {
3137 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3138
3139 if (rmap)
3140 {
3141 if (peer->default_rmap[afi][safi].name)
3142 free (peer->default_rmap[afi][safi].name);
3143 peer->default_rmap[afi][safi].name = strdup (rmap);
3144 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3145 }
3146 }
3147
3148 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3149 {
3150 if (peer->status == Established && peer->afc_nego[afi][safi])
3151 bgp_default_originate (peer, afi, safi, 0);
3152 return 0;
3153 }
3154
3155 /* peer-group member updates. */
3156 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003157 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003158 {
3159 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3160
3161 if (rmap)
3162 {
3163 if (peer->default_rmap[afi][safi].name)
3164 free (peer->default_rmap[afi][safi].name);
3165 peer->default_rmap[afi][safi].name = strdup (rmap);
3166 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3167 }
3168
3169 if (peer->status == Established && peer->afc_nego[afi][safi])
3170 bgp_default_originate (peer, afi, safi, 0);
3171 }
3172 return 0;
3173}
3174
3175int
3176peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3177{
3178 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003179 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003180
3181 /* Adress family must be activated. */
3182 if (! peer->afc[afi][safi])
3183 return BGP_ERR_PEER_INACTIVE;
3184
3185 /* Default originate can't be used for peer group memeber. */
3186 if (peer_is_group_member (peer, afi, safi))
3187 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3188
3189 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3190 {
3191 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3192
3193 if (peer->default_rmap[afi][safi].name)
3194 free (peer->default_rmap[afi][safi].name);
3195 peer->default_rmap[afi][safi].name = NULL;
3196 peer->default_rmap[afi][safi].map = NULL;
3197 }
3198
3199 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3200 {
3201 if (peer->status == Established && peer->afc_nego[afi][safi])
3202 bgp_default_originate (peer, afi, safi, 1);
3203 return 0;
3204 }
3205
3206 /* peer-group member updates. */
3207 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003208 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003209 {
3210 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3211
3212 if (peer->default_rmap[afi][safi].name)
3213 free (peer->default_rmap[afi][safi].name);
3214 peer->default_rmap[afi][safi].name = NULL;
3215 peer->default_rmap[afi][safi].map = NULL;
3216
3217 if (peer->status == Established && peer->afc_nego[afi][safi])
3218 bgp_default_originate (peer, afi, safi, 1);
3219 }
3220 return 0;
3221}
David Lamparter6b0655a2014-06-04 06:53:35 +02003222
paul718e3742002-12-13 20:15:29 +00003223int
3224peer_port_set (struct peer *peer, u_int16_t port)
3225{
3226 peer->port = port;
3227 return 0;
3228}
3229
3230int
3231peer_port_unset (struct peer *peer)
3232{
3233 peer->port = BGP_PORT_DEFAULT;
3234 return 0;
3235}
David Lamparter6b0655a2014-06-04 06:53:35 +02003236
paul718e3742002-12-13 20:15:29 +00003237/* neighbor weight. */
3238int
3239peer_weight_set (struct peer *peer, u_int16_t weight)
3240{
3241 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003242 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003243
3244 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3245 peer->weight = weight;
3246
3247 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3248 return 0;
3249
3250 /* peer-group member updates. */
3251 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003252 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003253 {
3254 peer->weight = group->conf->weight;
3255 }
3256 return 0;
3257}
3258
3259int
3260peer_weight_unset (struct peer *peer)
3261{
3262 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003263 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003264
3265 /* Set default weight. */
3266 if (peer_group_active (peer))
3267 peer->weight = peer->group->conf->weight;
3268 else
3269 peer->weight = 0;
3270
3271 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3272
3273 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3274 return 0;
3275
3276 /* peer-group member updates. */
3277 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003278 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003279 {
3280 peer->weight = 0;
3281 }
3282 return 0;
3283}
David Lamparter6b0655a2014-06-04 06:53:35 +02003284
paul718e3742002-12-13 20:15:29 +00003285int
3286peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3287{
3288 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003289 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003290
3291 /* Not for peer group memeber. */
3292 if (peer_group_active (peer))
3293 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3294
3295 /* keepalive value check. */
3296 if (keepalive > 65535)
3297 return BGP_ERR_INVALID_VALUE;
3298
3299 /* Holdtime value check. */
3300 if (holdtime > 65535)
3301 return BGP_ERR_INVALID_VALUE;
3302
3303 /* Holdtime value must be either 0 or greater than 3. */
3304 if (holdtime < 3 && holdtime != 0)
3305 return BGP_ERR_INVALID_VALUE;
3306
3307 /* Set value to the configuration. */
3308 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3309 peer->holdtime = holdtime;
3310 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3311
3312 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3313 return 0;
3314
3315 /* peer-group member updates. */
3316 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003317 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003318 {
3319 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3320 peer->holdtime = group->conf->holdtime;
3321 peer->keepalive = group->conf->keepalive;
3322 }
3323 return 0;
3324}
3325
3326int
3327peer_timers_unset (struct peer *peer)
3328{
3329 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003330 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003331
3332 if (peer_group_active (peer))
3333 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3334
3335 /* Clear configuration. */
3336 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3337 peer->keepalive = 0;
3338 peer->holdtime = 0;
3339
3340 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3341 return 0;
3342
3343 /* peer-group member updates. */
3344 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003345 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003346 {
3347 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3348 peer->holdtime = 0;
3349 peer->keepalive = 0;
3350 }
3351
3352 return 0;
3353}
David Lamparter6b0655a2014-06-04 06:53:35 +02003354
paul718e3742002-12-13 20:15:29 +00003355int
3356peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3357{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003358 struct peer_group *group;
3359 struct listnode *node, *nnode;
3360
paul718e3742002-12-13 20:15:29 +00003361 if (peer_group_active (peer))
3362 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3363
3364 if (connect > 65535)
3365 return BGP_ERR_INVALID_VALUE;
3366
3367 /* Set value to the configuration. */
3368 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3369 peer->connect = connect;
3370
3371 /* Set value to timer setting. */
3372 peer->v_connect = connect;
3373
Daniel Walton0d7435f2015-10-22 11:35:20 +03003374 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3375 return 0;
3376
3377 /* peer-group member updates. */
3378 group = peer->group;
3379 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3380 {
3381 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3382 peer->connect = connect;
3383 peer->v_connect = connect;
3384 }
paul718e3742002-12-13 20:15:29 +00003385 return 0;
3386}
3387
3388int
3389peer_timers_connect_unset (struct peer *peer)
3390{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003391 struct peer_group *group;
3392 struct listnode *node, *nnode;
3393
paul718e3742002-12-13 20:15:29 +00003394 if (peer_group_active (peer))
3395 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3396
3397 /* Clear configuration. */
3398 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3399 peer->connect = 0;
3400
3401 /* Set timer setting to default value. */
3402 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3403
Daniel Walton0d7435f2015-10-22 11:35:20 +03003404 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3405 return 0;
3406
3407 /* peer-group member updates. */
3408 group = peer->group;
3409 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3410 {
3411 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3412 peer->connect = 0;
3413 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3414 }
3415 return 0;
paul718e3742002-12-13 20:15:29 +00003416}
David Lamparter6b0655a2014-06-04 06:53:35 +02003417
paul718e3742002-12-13 20:15:29 +00003418int
3419peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3420{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003421 struct peer_group *group;
3422 struct listnode *node, *nnode;
3423
paul718e3742002-12-13 20:15:29 +00003424 if (peer_group_active (peer))
3425 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3426
3427 if (routeadv > 600)
3428 return BGP_ERR_INVALID_VALUE;
3429
3430 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3431 peer->routeadv = routeadv;
3432 peer->v_routeadv = routeadv;
3433
Daniel Walton0d7435f2015-10-22 11:35:20 +03003434 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3435 return 0;
3436
3437 /* peer-group member updates. */
3438 group = peer->group;
3439 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3440 {
3441 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3442 peer->routeadv = routeadv;
3443 peer->v_routeadv = routeadv;
3444 }
3445
paul718e3742002-12-13 20:15:29 +00003446 return 0;
3447}
3448
3449int
3450peer_advertise_interval_unset (struct peer *peer)
3451{
Daniel Walton0d7435f2015-10-22 11:35:20 +03003452 struct peer_group *group;
3453 struct listnode *node, *nnode;
3454
paul718e3742002-12-13 20:15:29 +00003455 if (peer_group_active (peer))
3456 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3457
3458 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3459 peer->routeadv = 0;
3460
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003461 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003462 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3463 else
3464 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
Daniel Walton0d7435f2015-10-22 11:35:20 +03003465
3466 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3467 return 0;
3468
3469 /* peer-group member updates. */
3470 group = peer->group;
3471 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
3472 {
3473 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3474 peer->routeadv = 0;
3475
3476 if (peer->sort == BGP_PEER_IBGP)
3477 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3478 else
3479 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3480 }
paul718e3742002-12-13 20:15:29 +00003481
3482 return 0;
3483}
David Lamparter6b0655a2014-06-04 06:53:35 +02003484
paul718e3742002-12-13 20:15:29 +00003485/* neighbor interface */
3486int
paulfd79ac92004-10-13 05:06:08 +00003487peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003488{
3489 if (peer->ifname)
3490 free (peer->ifname);
3491 peer->ifname = strdup (str);
3492
3493 return 0;
3494}
3495
3496int
3497peer_interface_unset (struct peer *peer)
3498{
3499 if (peer->ifname)
3500 free (peer->ifname);
3501 peer->ifname = NULL;
3502
3503 return 0;
3504}
David Lamparter6b0655a2014-06-04 06:53:35 +02003505
paul718e3742002-12-13 20:15:29 +00003506/* Allow-as in. */
3507int
3508peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3509{
3510 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003511 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003512
3513 if (allow_num < 1 || allow_num > 10)
3514 return BGP_ERR_INVALID_VALUE;
3515
3516 if (peer->allowas_in[afi][safi] != allow_num)
3517 {
3518 peer->allowas_in[afi][safi] = allow_num;
3519 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3520 peer_change_action (peer, afi, safi, peer_change_reset_in);
3521 }
3522
3523 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3524 return 0;
3525
3526 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003527 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003528 {
3529 if (peer->allowas_in[afi][safi] != allow_num)
3530 {
3531 peer->allowas_in[afi][safi] = allow_num;
3532 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3533 peer_change_action (peer, afi, safi, peer_change_reset_in);
3534 }
3535
3536 }
3537 return 0;
3538}
3539
3540int
3541peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3542{
3543 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003544 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003545
3546 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3547 {
3548 peer->allowas_in[afi][safi] = 0;
3549 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3550 }
3551
3552 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3553 return 0;
3554
3555 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003556 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003557 {
3558 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3559 {
3560 peer->allowas_in[afi][safi] = 0;
3561 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3562 }
3563 }
3564 return 0;
3565}
David Lamparter6b0655a2014-06-04 06:53:35 +02003566
paul718e3742002-12-13 20:15:29 +00003567int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003568peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003569{
3570 struct bgp *bgp = peer->bgp;
3571 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003572 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003573
3574 if (peer_sort (peer) != BGP_PEER_EBGP
3575 && peer_sort (peer) != BGP_PEER_INTERNAL)
3576 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3577
3578 if (bgp->as == as)
3579 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3580
3581 if (peer_group_active (peer))
3582 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3583
Andrew Certain9d3f9702012-11-07 23:50:07 +00003584 if (peer->as == as)
3585 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3586
paul718e3742002-12-13 20:15:29 +00003587 if (peer->change_local_as == as &&
3588 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003589 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3590 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3591 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003592 return 0;
3593
3594 peer->change_local_as = as;
3595 if (no_prepend)
3596 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3597 else
3598 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3599
Andrew Certain9d3f9702012-11-07 23:50:07 +00003600 if (replace_as)
3601 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3602 else
3603 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3604
paul718e3742002-12-13 20:15:29 +00003605 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3606 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003607 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003608 {
3609 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3610 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3611 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3612 }
paul718e3742002-12-13 20:15:29 +00003613 else
3614 BGP_EVENT_ADD (peer, BGP_Stop);
3615
3616 return 0;
3617 }
3618
3619 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003620 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003621 {
3622 peer->change_local_as = as;
3623 if (no_prepend)
3624 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3625 else
3626 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3627
Andrew Certain9d3f9702012-11-07 23:50:07 +00003628 if (replace_as)
3629 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3630 else
3631 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3632
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003633 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003634 {
3635 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3636 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3637 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3638 }
paul718e3742002-12-13 20:15:29 +00003639 else
3640 BGP_EVENT_ADD (peer, BGP_Stop);
3641 }
3642
3643 return 0;
3644}
3645
3646int
3647peer_local_as_unset (struct peer *peer)
3648{
3649 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003650 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003651
3652 if (peer_group_active (peer))
3653 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3654
3655 if (! peer->change_local_as)
3656 return 0;
3657
3658 peer->change_local_as = 0;
3659 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003660 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003661
3662 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3663 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003664 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003665 {
3666 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3667 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3668 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3669 }
paul718e3742002-12-13 20:15:29 +00003670 else
3671 BGP_EVENT_ADD (peer, BGP_Stop);
3672
3673 return 0;
3674 }
3675
3676 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003677 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003678 {
3679 peer->change_local_as = 0;
3680 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003681 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003682
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003683 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003684 {
3685 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3686 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3687 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3688 }
paul718e3742002-12-13 20:15:29 +00003689 else
3690 BGP_EVENT_ADD (peer, BGP_Stop);
3691 }
3692 return 0;
3693}
David Lamparter6b0655a2014-06-04 06:53:35 +02003694
Paul Jakma0df7c912008-07-21 21:02:49 +00003695/* Set password for authenticating with the peer. */
3696int
3697peer_password_set (struct peer *peer, const char *password)
3698{
3699 struct listnode *nn, *nnode;
3700 int len = password ? strlen(password) : 0;
3701 int ret = BGP_SUCCESS;
3702
3703 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3704 return BGP_ERR_INVALID_VALUE;
3705
3706 if (peer->password && strcmp (peer->password, password) == 0
3707 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3708 return 0;
3709
3710 if (peer->password)
3711 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3712
3713 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3714
3715 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3716 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003717 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3718 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
Paul Jakma0df7c912008-07-21 21:02:49 +00003719 else
3720 BGP_EVENT_ADD (peer, BGP_Stop);
3721
3722 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3723 }
3724
3725 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3726 {
3727 if (peer->password && strcmp (peer->password, password) == 0)
3728 continue;
3729
3730 if (peer->password)
3731 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3732
3733 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3734
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003735 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003736 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3737 else
3738 BGP_EVENT_ADD (peer, BGP_Stop);
3739
3740 if (bgp_md5_set (peer) < 0)
3741 ret = BGP_ERR_TCPSIG_FAILED;
3742 }
3743
3744 return ret;
3745}
3746
3747int
3748peer_password_unset (struct peer *peer)
3749{
3750 struct listnode *nn, *nnode;
3751
3752 if (!peer->password
3753 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3754 return 0;
3755
3756 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3757 {
3758 if (peer_group_active (peer)
3759 && peer->group->conf->password
3760 && strcmp (peer->group->conf->password, peer->password) == 0)
3761 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3762
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003763 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003764 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3765 else
3766 BGP_EVENT_ADD (peer, BGP_Stop);
3767
3768 if (peer->password)
3769 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3770
3771 peer->password = NULL;
3772
3773 bgp_md5_set (peer);
3774
3775 return 0;
3776 }
3777
3778 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3779 peer->password = NULL;
3780
3781 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3782 {
3783 if (!peer->password)
3784 continue;
3785
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003786 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003787 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3788 else
3789 BGP_EVENT_ADD (peer, BGP_Stop);
3790
3791 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3792 peer->password = NULL;
3793
3794 bgp_md5_set (peer);
3795 }
3796
3797 return 0;
3798}
David Lamparter6b0655a2014-06-04 06:53:35 +02003799
paul718e3742002-12-13 20:15:29 +00003800/* Set distribute list to the peer. */
3801int
3802peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003803 const char *name)
paul718e3742002-12-13 20:15:29 +00003804{
3805 struct bgp_filter *filter;
3806 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003807 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003808
3809 if (! peer->afc[afi][safi])
3810 return BGP_ERR_PEER_INACTIVE;
3811
3812 if (direct != FILTER_IN && direct != FILTER_OUT)
3813 return BGP_ERR_INVALID_VALUE;
3814
3815 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3816 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3817
3818 filter = &peer->filter[afi][safi];
3819
3820 if (filter->plist[direct].name)
3821 return BGP_ERR_PEER_FILTER_CONFLICT;
3822
3823 if (filter->dlist[direct].name)
3824 free (filter->dlist[direct].name);
3825 filter->dlist[direct].name = strdup (name);
3826 filter->dlist[direct].alist = access_list_lookup (afi, name);
3827
3828 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3829 return 0;
3830
3831 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003832 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003833 {
3834 filter = &peer->filter[afi][safi];
3835
3836 if (! peer->af_group[afi][safi])
3837 continue;
3838
3839 if (filter->dlist[direct].name)
3840 free (filter->dlist[direct].name);
3841 filter->dlist[direct].name = strdup (name);
3842 filter->dlist[direct].alist = access_list_lookup (afi, name);
3843 }
3844
3845 return 0;
3846}
3847
3848int
3849peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3850{
3851 struct bgp_filter *filter;
3852 struct bgp_filter *gfilter;
3853 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003854 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003855
3856 if (! peer->afc[afi][safi])
3857 return BGP_ERR_PEER_INACTIVE;
3858
3859 if (direct != FILTER_IN && direct != FILTER_OUT)
3860 return BGP_ERR_INVALID_VALUE;
3861
3862 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3863 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3864
3865 filter = &peer->filter[afi][safi];
3866
3867 /* apply peer-group filter */
3868 if (peer->af_group[afi][safi])
3869 {
3870 gfilter = &peer->group->conf->filter[afi][safi];
3871
3872 if (gfilter->dlist[direct].name)
3873 {
3874 if (filter->dlist[direct].name)
3875 free (filter->dlist[direct].name);
3876 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3877 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3878 return 0;
3879 }
3880 }
3881
3882 if (filter->dlist[direct].name)
3883 free (filter->dlist[direct].name);
3884 filter->dlist[direct].name = NULL;
3885 filter->dlist[direct].alist = NULL;
3886
3887 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3888 return 0;
3889
3890 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003891 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003892 {
3893 filter = &peer->filter[afi][safi];
3894
3895 if (! peer->af_group[afi][safi])
3896 continue;
3897
3898 if (filter->dlist[direct].name)
3899 free (filter->dlist[direct].name);
3900 filter->dlist[direct].name = NULL;
3901 filter->dlist[direct].alist = NULL;
3902 }
3903
3904 return 0;
3905}
3906
3907/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003908static void
paul718e3742002-12-13 20:15:29 +00003909peer_distribute_update (struct access_list *access)
3910{
3911 afi_t afi;
3912 safi_t safi;
3913 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003914 struct listnode *mnode, *mnnode;
3915 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003916 struct bgp *bgp;
3917 struct peer *peer;
3918 struct peer_group *group;
3919 struct bgp_filter *filter;
3920
paul1eb8ef22005-04-07 07:30:20 +00003921 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003922 {
paul1eb8ef22005-04-07 07:30:20 +00003923 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003924 {
3925 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3926 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3927 {
3928 filter = &peer->filter[afi][safi];
3929
3930 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3931 {
3932 if (filter->dlist[direct].name)
3933 filter->dlist[direct].alist =
3934 access_list_lookup (afi, filter->dlist[direct].name);
3935 else
3936 filter->dlist[direct].alist = NULL;
3937 }
3938 }
3939 }
paul1eb8ef22005-04-07 07:30:20 +00003940 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003941 {
3942 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3943 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3944 {
3945 filter = &group->conf->filter[afi][safi];
3946
3947 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3948 {
3949 if (filter->dlist[direct].name)
3950 filter->dlist[direct].alist =
3951 access_list_lookup (afi, filter->dlist[direct].name);
3952 else
3953 filter->dlist[direct].alist = NULL;
3954 }
3955 }
3956 }
3957 }
3958}
David Lamparter6b0655a2014-06-04 06:53:35 +02003959
paul718e3742002-12-13 20:15:29 +00003960/* Set prefix list to the peer. */
3961int
3962peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003963 const char *name)
paul718e3742002-12-13 20:15:29 +00003964{
3965 struct bgp_filter *filter;
3966 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003967 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003968
3969 if (! peer->afc[afi][safi])
3970 return BGP_ERR_PEER_INACTIVE;
3971
3972 if (direct != FILTER_IN && direct != FILTER_OUT)
3973 return BGP_ERR_INVALID_VALUE;
3974
3975 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3976 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3977
3978 filter = &peer->filter[afi][safi];
3979
3980 if (filter->dlist[direct].name)
3981 return BGP_ERR_PEER_FILTER_CONFLICT;
3982
3983 if (filter->plist[direct].name)
3984 free (filter->plist[direct].name);
3985 filter->plist[direct].name = strdup (name);
3986 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3987
3988 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3989 return 0;
3990
3991 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003992 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003993 {
3994 filter = &peer->filter[afi][safi];
3995
3996 if (! peer->af_group[afi][safi])
3997 continue;
3998
3999 if (filter->plist[direct].name)
4000 free (filter->plist[direct].name);
4001 filter->plist[direct].name = strdup (name);
4002 filter->plist[direct].plist = prefix_list_lookup (afi, name);
4003 }
4004 return 0;
4005}
4006
4007int
4008peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4009{
4010 struct bgp_filter *filter;
4011 struct bgp_filter *gfilter;
4012 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004013 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004014
4015 if (! peer->afc[afi][safi])
4016 return BGP_ERR_PEER_INACTIVE;
4017
4018 if (direct != FILTER_IN && direct != FILTER_OUT)
4019 return BGP_ERR_INVALID_VALUE;
4020
4021 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4022 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4023
4024 filter = &peer->filter[afi][safi];
4025
4026 /* apply peer-group filter */
4027 if (peer->af_group[afi][safi])
4028 {
4029 gfilter = &peer->group->conf->filter[afi][safi];
4030
4031 if (gfilter->plist[direct].name)
4032 {
4033 if (filter->plist[direct].name)
4034 free (filter->plist[direct].name);
4035 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
4036 filter->plist[direct].plist = gfilter->plist[direct].plist;
4037 return 0;
4038 }
4039 }
4040
4041 if (filter->plist[direct].name)
4042 free (filter->plist[direct].name);
4043 filter->plist[direct].name = NULL;
4044 filter->plist[direct].plist = NULL;
4045
4046 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4047 return 0;
4048
4049 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004050 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004051 {
4052 filter = &peer->filter[afi][safi];
4053
4054 if (! peer->af_group[afi][safi])
4055 continue;
4056
4057 if (filter->plist[direct].name)
4058 free (filter->plist[direct].name);
4059 filter->plist[direct].name = NULL;
4060 filter->plist[direct].plist = NULL;
4061 }
4062
4063 return 0;
4064}
4065
4066/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00004067static void
paul718e3742002-12-13 20:15:29 +00004068peer_prefix_list_update (struct prefix_list *plist)
4069{
paul1eb8ef22005-04-07 07:30:20 +00004070 struct listnode *mnode, *mnnode;
4071 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004072 struct bgp *bgp;
4073 struct peer *peer;
4074 struct peer_group *group;
4075 struct bgp_filter *filter;
4076 afi_t afi;
4077 safi_t safi;
4078 int direct;
4079
paul1eb8ef22005-04-07 07:30:20 +00004080 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004081 {
paul1eb8ef22005-04-07 07:30:20 +00004082 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004083 {
4084 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4085 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4086 {
4087 filter = &peer->filter[afi][safi];
4088
4089 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4090 {
4091 if (filter->plist[direct].name)
4092 filter->plist[direct].plist =
4093 prefix_list_lookup (afi, filter->plist[direct].name);
4094 else
4095 filter->plist[direct].plist = NULL;
4096 }
4097 }
4098 }
paul1eb8ef22005-04-07 07:30:20 +00004099 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004100 {
4101 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4102 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4103 {
4104 filter = &group->conf->filter[afi][safi];
4105
4106 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4107 {
4108 if (filter->plist[direct].name)
4109 filter->plist[direct].plist =
4110 prefix_list_lookup (afi, filter->plist[direct].name);
4111 else
4112 filter->plist[direct].plist = NULL;
4113 }
4114 }
4115 }
4116 }
4117}
David Lamparter6b0655a2014-06-04 06:53:35 +02004118
paul718e3742002-12-13 20:15:29 +00004119int
4120peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004121 const char *name)
paul718e3742002-12-13 20:15:29 +00004122{
4123 struct bgp_filter *filter;
4124 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004125 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004126
4127 if (! peer->afc[afi][safi])
4128 return BGP_ERR_PEER_INACTIVE;
4129
4130 if (direct != FILTER_IN && direct != FILTER_OUT)
4131 return BGP_ERR_INVALID_VALUE;
4132
4133 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4134 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4135
4136 filter = &peer->filter[afi][safi];
4137
4138 if (filter->aslist[direct].name)
4139 free (filter->aslist[direct].name);
4140 filter->aslist[direct].name = strdup (name);
4141 filter->aslist[direct].aslist = as_list_lookup (name);
4142
4143 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4144 return 0;
4145
4146 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004147 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004148 {
4149 filter = &peer->filter[afi][safi];
4150
4151 if (! peer->af_group[afi][safi])
4152 continue;
4153
4154 if (filter->aslist[direct].name)
4155 free (filter->aslist[direct].name);
4156 filter->aslist[direct].name = strdup (name);
4157 filter->aslist[direct].aslist = as_list_lookup (name);
4158 }
4159 return 0;
4160}
4161
4162int
4163peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4164{
4165 struct bgp_filter *filter;
4166 struct bgp_filter *gfilter;
4167 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004168 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004169
4170 if (! peer->afc[afi][safi])
4171 return BGP_ERR_PEER_INACTIVE;
4172
hassob5f29602005-05-25 21:00:28 +00004173 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004174 return BGP_ERR_INVALID_VALUE;
4175
hassob5f29602005-05-25 21:00:28 +00004176 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004177 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4178
4179 filter = &peer->filter[afi][safi];
4180
4181 /* apply peer-group filter */
4182 if (peer->af_group[afi][safi])
4183 {
4184 gfilter = &peer->group->conf->filter[afi][safi];
4185
4186 if (gfilter->aslist[direct].name)
4187 {
4188 if (filter->aslist[direct].name)
4189 free (filter->aslist[direct].name);
4190 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4191 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4192 return 0;
4193 }
4194 }
4195
4196 if (filter->aslist[direct].name)
4197 free (filter->aslist[direct].name);
4198 filter->aslist[direct].name = NULL;
4199 filter->aslist[direct].aslist = NULL;
4200
4201 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4202 return 0;
4203
4204 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004205 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004206 {
4207 filter = &peer->filter[afi][safi];
4208
4209 if (! peer->af_group[afi][safi])
4210 continue;
4211
4212 if (filter->aslist[direct].name)
4213 free (filter->aslist[direct].name);
4214 filter->aslist[direct].name = NULL;
4215 filter->aslist[direct].aslist = NULL;
4216 }
4217
4218 return 0;
4219}
4220
paul94f2b392005-06-28 12:44:16 +00004221static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004222peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004223{
4224 afi_t afi;
4225 safi_t safi;
4226 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004227 struct listnode *mnode, *mnnode;
4228 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004229 struct bgp *bgp;
4230 struct peer *peer;
4231 struct peer_group *group;
4232 struct bgp_filter *filter;
4233
paul1eb8ef22005-04-07 07:30:20 +00004234 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004235 {
paul1eb8ef22005-04-07 07:30:20 +00004236 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004237 {
4238 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4239 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4240 {
4241 filter = &peer->filter[afi][safi];
4242
4243 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4244 {
4245 if (filter->aslist[direct].name)
4246 filter->aslist[direct].aslist =
4247 as_list_lookup (filter->aslist[direct].name);
4248 else
4249 filter->aslist[direct].aslist = NULL;
4250 }
4251 }
4252 }
paul1eb8ef22005-04-07 07:30:20 +00004253 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004254 {
4255 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4256 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4257 {
4258 filter = &group->conf->filter[afi][safi];
4259
4260 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4261 {
4262 if (filter->aslist[direct].name)
4263 filter->aslist[direct].aslist =
4264 as_list_lookup (filter->aslist[direct].name);
4265 else
4266 filter->aslist[direct].aslist = NULL;
4267 }
4268 }
4269 }
4270 }
4271}
David Lamparter6b0655a2014-06-04 06:53:35 +02004272
paul718e3742002-12-13 20:15:29 +00004273/* Set route-map to the peer. */
4274int
4275peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004276 const char *name)
paul718e3742002-12-13 20:15:29 +00004277{
4278 struct bgp_filter *filter;
4279 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004280 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004281
4282 if (! peer->afc[afi][safi])
4283 return BGP_ERR_PEER_INACTIVE;
4284
paulfee0f4c2004-09-13 05:12:46 +00004285 if (direct != RMAP_IN && direct != RMAP_OUT &&
4286 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004287 return BGP_ERR_INVALID_VALUE;
4288
paulfee0f4c2004-09-13 05:12:46 +00004289 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4290 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004291 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4292
4293 filter = &peer->filter[afi][safi];
4294
4295 if (filter->map[direct].name)
4296 free (filter->map[direct].name);
4297
4298 filter->map[direct].name = strdup (name);
4299 filter->map[direct].map = route_map_lookup_by_name (name);
4300
4301 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4302 return 0;
4303
4304 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004305 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004306 {
4307 filter = &peer->filter[afi][safi];
4308
4309 if (! peer->af_group[afi][safi])
4310 continue;
4311
4312 if (filter->map[direct].name)
4313 free (filter->map[direct].name);
4314 filter->map[direct].name = strdup (name);
4315 filter->map[direct].map = route_map_lookup_by_name (name);
4316 }
4317 return 0;
4318}
4319
4320/* Unset route-map from the peer. */
4321int
4322peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4323{
4324 struct bgp_filter *filter;
4325 struct bgp_filter *gfilter;
4326 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004327 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004328
4329 if (! peer->afc[afi][safi])
4330 return BGP_ERR_PEER_INACTIVE;
4331
hassob5f29602005-05-25 21:00:28 +00004332 if (direct != RMAP_IN && direct != RMAP_OUT &&
4333 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004334 return BGP_ERR_INVALID_VALUE;
4335
hassob5f29602005-05-25 21:00:28 +00004336 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4337 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004338 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4339
4340 filter = &peer->filter[afi][safi];
4341
4342 /* apply peer-group filter */
4343 if (peer->af_group[afi][safi])
4344 {
4345 gfilter = &peer->group->conf->filter[afi][safi];
4346
4347 if (gfilter->map[direct].name)
4348 {
4349 if (filter->map[direct].name)
4350 free (filter->map[direct].name);
4351 filter->map[direct].name = strdup (gfilter->map[direct].name);
4352 filter->map[direct].map = gfilter->map[direct].map;
4353 return 0;
4354 }
4355 }
4356
4357 if (filter->map[direct].name)
4358 free (filter->map[direct].name);
4359 filter->map[direct].name = NULL;
4360 filter->map[direct].map = NULL;
4361
4362 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4363 return 0;
4364
4365 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004366 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004367 {
4368 filter = &peer->filter[afi][safi];
4369
4370 if (! peer->af_group[afi][safi])
4371 continue;
4372
4373 if (filter->map[direct].name)
4374 free (filter->map[direct].name);
4375 filter->map[direct].name = NULL;
4376 filter->map[direct].map = NULL;
4377 }
4378 return 0;
4379}
David Lamparter6b0655a2014-06-04 06:53:35 +02004380
paul718e3742002-12-13 20:15:29 +00004381/* Set unsuppress-map to the peer. */
4382int
paulfd79ac92004-10-13 05:06:08 +00004383peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4384 const char *name)
paul718e3742002-12-13 20:15:29 +00004385{
4386 struct bgp_filter *filter;
4387 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004388 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004389
4390 if (! peer->afc[afi][safi])
4391 return BGP_ERR_PEER_INACTIVE;
4392
4393 if (peer_is_group_member (peer, afi, safi))
4394 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4395
4396 filter = &peer->filter[afi][safi];
4397
4398 if (filter->usmap.name)
4399 free (filter->usmap.name);
4400
4401 filter->usmap.name = strdup (name);
4402 filter->usmap.map = route_map_lookup_by_name (name);
4403
4404 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4405 return 0;
4406
4407 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004408 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004409 {
4410 filter = &peer->filter[afi][safi];
4411
4412 if (! peer->af_group[afi][safi])
4413 continue;
4414
4415 if (filter->usmap.name)
4416 free (filter->usmap.name);
4417 filter->usmap.name = strdup (name);
4418 filter->usmap.map = route_map_lookup_by_name (name);
4419 }
4420 return 0;
4421}
4422
4423/* Unset route-map from the peer. */
4424int
4425peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4426{
4427 struct bgp_filter *filter;
4428 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004429 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004430
4431 if (! peer->afc[afi][safi])
4432 return BGP_ERR_PEER_INACTIVE;
4433
4434 if (peer_is_group_member (peer, afi, safi))
4435 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4436
4437 filter = &peer->filter[afi][safi];
4438
4439 if (filter->usmap.name)
4440 free (filter->usmap.name);
4441 filter->usmap.name = NULL;
4442 filter->usmap.map = NULL;
4443
4444 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4445 return 0;
4446
4447 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004448 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004449 {
4450 filter = &peer->filter[afi][safi];
4451
4452 if (! peer->af_group[afi][safi])
4453 continue;
4454
4455 if (filter->usmap.name)
4456 free (filter->usmap.name);
4457 filter->usmap.name = NULL;
4458 filter->usmap.map = NULL;
4459 }
4460 return 0;
4461}
David Lamparter6b0655a2014-06-04 06:53:35 +02004462
paul718e3742002-12-13 20:15:29 +00004463int
4464peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004465 u_int32_t max, u_char threshold,
4466 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004467{
4468 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004469 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004470
4471 if (! peer->afc[afi][safi])
4472 return BGP_ERR_PEER_INACTIVE;
4473
4474 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4475 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004476 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004477 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004478 if (warning)
4479 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4480 else
4481 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4482
4483 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4484 return 0;
4485
4486 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004487 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004488 {
4489 if (! peer->af_group[afi][safi])
4490 continue;
4491
4492 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4493 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004494 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004495 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004496 if (warning)
4497 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4498 else
4499 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4500 }
4501 return 0;
4502}
4503
4504int
4505peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4506{
4507 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004508 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004509
4510 if (! peer->afc[afi][safi])
4511 return BGP_ERR_PEER_INACTIVE;
4512
4513 /* apply peer-group config */
4514 if (peer->af_group[afi][safi])
4515 {
4516 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4517 PEER_FLAG_MAX_PREFIX))
4518 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4519 else
4520 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4521
4522 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4523 PEER_FLAG_MAX_PREFIX_WARNING))
4524 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4525 else
4526 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4527
4528 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004529 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004530 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004531 return 0;
4532 }
4533
4534 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4535 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4536 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004537 peer->pmax_threshold[afi][safi] = 0;
4538 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004539
4540 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4541 return 0;
4542
4543 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004544 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004545 {
4546 if (! peer->af_group[afi][safi])
4547 continue;
4548
4549 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4550 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4551 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004552 peer->pmax_threshold[afi][safi] = 0;
4553 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004554 }
4555 return 0;
4556}
David Lamparter5f9adb52014-05-19 23:15:02 +02004557
4558static int is_ebgp_multihop_configured (struct peer *peer)
4559{
4560 struct peer_group *group;
4561 struct listnode *node, *nnode;
4562 struct peer *peer1;
4563
4564 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4565 {
4566 group = peer->group;
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004567 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4568 (group->conf->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004569 return 1;
4570
4571 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4572 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004573 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
4574 (peer1->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004575 return 1;
4576 }
4577 }
4578 else
4579 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004580 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4581 (peer->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004582 return 1;
4583 }
4584 return 0;
4585}
4586
Nick Hilliardfa411a22011-03-23 15:33:17 +00004587/* Set # of hops between us and BGP peer. */
4588int
4589peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4590{
4591 struct peer_group *group;
4592 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004593 int ret;
4594
4595 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4596
Nick Hilliardfa411a22011-03-23 15:33:17 +00004597 /* We cannot configure ttl-security hops when ebgp-multihop is already
4598 set. For non peer-groups, the check is simple. For peer-groups, it's
4599 slightly messy, because we need to check both the peer-group structure
4600 and all peer-group members for any trace of ebgp-multihop configuration
4601 before actually applying the ttl-security rules. Cisco really made a
4602 mess of this configuration parameter, and OpenBGPD got it right.
4603 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004604
David Lamparter5f9adb52014-05-19 23:15:02 +02004605 if (peer->gtsm_hops == 0)
4606 {
4607 if (is_ebgp_multihop_configured (peer))
4608 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004609
David Lamparter5f9adb52014-05-19 23:15:02 +02004610 /* specify MAXTTL on outgoing packets */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004611 /* Routine handles iBGP peers correctly */
David Lamparter5f9adb52014-05-19 23:15:02 +02004612 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4613 if (ret != 0)
4614 return ret;
4615 }
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004616
Nick Hilliardfa411a22011-03-23 15:33:17 +00004617 peer->gtsm_hops = gtsm_hops;
4618
Nick Hilliardfa411a22011-03-23 15:33:17 +00004619 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4620 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004621 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004622 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4623 }
4624 else
4625 {
4626 group = peer->group;
4627 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4628 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004629 peer->gtsm_hops = group->conf->gtsm_hops;
4630
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004631 /* Change setting of existing peer
4632 * established then change value (may break connectivity)
4633 * not established yet (teardown session and restart)
4634 * no session then do nothing (will get handled by next connection)
4635 */
4636 if (peer->status == Established)
4637 {
4638 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4639 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4640 MAXTTL + 1 - peer->gtsm_hops);
4641 }
4642 else if (peer->status < Established)
4643 {
4644 if (BGP_DEBUG (events, EVENTS))
4645 zlog_debug ("%s Min-ttl changed", peer->host);
4646 BGP_EVENT_ADD (peer, BGP_Stop);
4647 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004648 }
4649 }
4650
4651 return 0;
4652}
4653
4654int
4655peer_ttl_security_hops_unset (struct peer *peer)
4656{
4657 struct peer_group *group;
4658 struct listnode *node, *nnode;
4659 struct peer *opeer;
4660
4661 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4662
Nick Hilliardfa411a22011-03-23 15:33:17 +00004663 /* if a peer-group member, then reset to peer-group default rather than 0 */
4664 if (peer_group_active (peer))
4665 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4666 else
4667 peer->gtsm_hops = 0;
4668
4669 opeer = peer;
4670 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4671 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004672 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004673 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4674 }
4675 else
4676 {
4677 group = peer->group;
4678 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4679 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004680 peer->gtsm_hops = 0;
4681
4682 if (peer->fd >= 0)
4683 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4684 }
4685 }
4686
4687 return peer_ebgp_multihop_unset (opeer);
4688}
David Lamparter6b0655a2014-06-04 06:53:35 +02004689
paul718e3742002-12-13 20:15:29 +00004690int
4691peer_clear (struct peer *peer)
4692{
4693 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4694 {
hasso0a486e52005-02-01 20:57:17 +00004695 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4696 {
4697 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4698 if (peer->t_pmax_restart)
4699 {
4700 BGP_TIMER_OFF (peer->t_pmax_restart);
4701 if (BGP_DEBUG (events, EVENTS))
4702 zlog_debug ("%s Maximum-prefix restart timer canceled",
4703 peer->host);
4704 }
4705 BGP_EVENT_ADD (peer, BGP_Start);
4706 return 0;
4707 }
4708
paul718e3742002-12-13 20:15:29 +00004709 peer->v_start = BGP_INIT_START_TIMER;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00004710 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00004711 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4712 BGP_NOTIFY_CEASE_ADMIN_RESET);
4713 else
4714 BGP_EVENT_ADD (peer, BGP_Stop);
4715 }
4716 return 0;
4717}
4718
4719int
4720peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4721 enum bgp_clear_type stype)
4722{
4723 if (peer->status != Established)
4724 return 0;
4725
4726 if (! peer->afc[afi][safi])
4727 return BGP_ERR_AF_UNCONFIGURED;
4728
Timo Teräs5a2a1ec2015-10-22 11:35:18 +03004729 peer->rtt = sockopt_tcp_rtt (peer->fd);
4730
paulfee0f4c2004-09-13 05:12:46 +00004731 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4732 {
4733 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4734 return 0;
4735 bgp_check_local_routes_rsclient (peer, afi, safi);
4736 bgp_soft_reconfig_rsclient (peer, afi, safi);
4737 }
4738
paul718e3742002-12-13 20:15:29 +00004739 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4740 bgp_announce_route (peer, afi, safi);
4741
4742 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4743 {
4744 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4745 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4746 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4747 {
4748 struct bgp_filter *filter = &peer->filter[afi][safi];
4749 u_char prefix_type;
4750
4751 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4752 prefix_type = ORF_TYPE_PREFIX;
4753 else
4754 prefix_type = ORF_TYPE_PREFIX_OLD;
4755
4756 if (filter->plist[FILTER_IN].plist)
4757 {
4758 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4759 bgp_route_refresh_send (peer, afi, safi,
4760 prefix_type, REFRESH_DEFER, 1);
4761 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4762 REFRESH_IMMEDIATE, 0);
4763 }
4764 else
4765 {
4766 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4767 bgp_route_refresh_send (peer, afi, safi,
4768 prefix_type, REFRESH_IMMEDIATE, 1);
4769 else
4770 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4771 }
4772 return 0;
4773 }
4774 }
4775
4776 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4777 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4778 {
4779 /* If neighbor has soft reconfiguration inbound flag.
4780 Use Adj-RIB-In database. */
4781 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4782 bgp_soft_reconfig_in (peer, afi, safi);
4783 else
4784 {
4785 /* If neighbor has route refresh capability, send route refresh
4786 message to the peer. */
4787 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4788 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4789 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4790 else
4791 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4792 }
4793 }
4794 return 0;
4795}
David Lamparter6b0655a2014-06-04 06:53:35 +02004796
paulfd79ac92004-10-13 05:06:08 +00004797/* Display peer uptime.*/
4798/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004799char *
4800peer_uptime (time_t uptime2, char *buf, size_t len)
4801{
4802 time_t uptime1;
4803 struct tm *tm;
4804
4805 /* Check buffer length. */
4806 if (len < BGP_UPTIME_LEN)
4807 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004808 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004809 /* XXX: should return status instead of buf... */
4810 snprintf (buf, len, "<error> ");
4811 return buf;
paul718e3742002-12-13 20:15:29 +00004812 }
4813
4814 /* If there is no connection has been done before print `never'. */
4815 if (uptime2 == 0)
4816 {
4817 snprintf (buf, len, "never ");
4818 return buf;
4819 }
4820
4821 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004822 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004823 uptime1 -= uptime2;
4824 tm = gmtime (&uptime1);
Paul Jakma84c38402015-05-26 15:19:38 +01004825
paul718e3742002-12-13 20:15:29 +00004826 /* Making formatted timer strings. */
4827#define ONE_DAY_SECOND 60*60*24
Paul Jakma84c38402015-05-26 15:19:38 +01004828#define ONE_WEEK_SECOND ONE_DAY_SECOND*7
4829#define ONE_YEAR_SECOND ONE_DAY_SECOND*365
paul718e3742002-12-13 20:15:29 +00004830
4831 if (uptime1 < ONE_DAY_SECOND)
4832 snprintf (buf, len, "%02d:%02d:%02d",
4833 tm->tm_hour, tm->tm_min, tm->tm_sec);
4834 else if (uptime1 < ONE_WEEK_SECOND)
4835 snprintf (buf, len, "%dd%02dh%02dm",
4836 tm->tm_yday, tm->tm_hour, tm->tm_min);
Paul Jakma84c38402015-05-26 15:19:38 +01004837 else if (uptime1 < ONE_YEAR_SECOND)
paul718e3742002-12-13 20:15:29 +00004838 snprintf (buf, len, "%02dw%dd%02dh",
4839 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
Paul Jakma84c38402015-05-26 15:19:38 +01004840 else
4841 snprintf (buf, len, "%02dy%02dw%dd",
4842 tm->tm_year - 70, tm->tm_yday/7,
4843 tm->tm_yday - ((tm->tm_yday/7) * 7));
paul718e3742002-12-13 20:15:29 +00004844 return buf;
4845}
David Lamparter6b0655a2014-06-04 06:53:35 +02004846
paul94f2b392005-06-28 12:44:16 +00004847static void
paul718e3742002-12-13 20:15:29 +00004848bgp_config_write_filter (struct vty *vty, struct peer *peer,
4849 afi_t afi, safi_t safi)
4850{
4851 struct bgp_filter *filter;
4852 struct bgp_filter *gfilter = NULL;
4853 char *addr;
4854 int in = FILTER_IN;
4855 int out = FILTER_OUT;
4856
4857 addr = peer->host;
4858 filter = &peer->filter[afi][safi];
4859 if (peer->af_group[afi][safi])
4860 gfilter = &peer->group->conf->filter[afi][safi];
4861
4862 /* distribute-list. */
4863 if (filter->dlist[in].name)
4864 if (! gfilter || ! gfilter->dlist[in].name
4865 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4866 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4867 filter->dlist[in].name, VTY_NEWLINE);
4868 if (filter->dlist[out].name && ! gfilter)
4869 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4870 filter->dlist[out].name, VTY_NEWLINE);
4871
4872 /* prefix-list. */
4873 if (filter->plist[in].name)
4874 if (! gfilter || ! gfilter->plist[in].name
4875 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4876 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4877 filter->plist[in].name, VTY_NEWLINE);
4878 if (filter->plist[out].name && ! gfilter)
4879 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4880 filter->plist[out].name, VTY_NEWLINE);
4881
4882 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004883 if (filter->map[RMAP_IN].name)
4884 if (! gfilter || ! gfilter->map[RMAP_IN].name
4885 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004886 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004887 filter->map[RMAP_IN].name, VTY_NEWLINE);
4888 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004889 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004890 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4891 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4892 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4893 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4894 if (filter->map[RMAP_EXPORT].name)
4895 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4896 || strcmp (filter->map[RMAP_EXPORT].name,
4897 gfilter->map[RMAP_EXPORT].name) != 0)
4898 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4899 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004900
4901 /* unsuppress-map */
4902 if (filter->usmap.name && ! gfilter)
4903 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4904 filter->usmap.name, VTY_NEWLINE);
4905
4906 /* filter-list. */
4907 if (filter->aslist[in].name)
4908 if (! gfilter || ! gfilter->aslist[in].name
4909 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4910 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4911 filter->aslist[in].name, VTY_NEWLINE);
4912 if (filter->aslist[out].name && ! gfilter)
4913 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4914 filter->aslist[out].name, VTY_NEWLINE);
4915}
4916
4917/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004918static void
paul718e3742002-12-13 20:15:29 +00004919bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4920 struct peer *peer, afi_t afi, safi_t safi)
4921{
paul718e3742002-12-13 20:15:29 +00004922 struct peer *g_peer = NULL;
4923 char buf[SU_ADDRSTRLEN];
4924 char *addr;
4925
paul718e3742002-12-13 20:15:29 +00004926 addr = peer->host;
4927 if (peer_group_active (peer))
4928 g_peer = peer->group->conf;
4929
4930 /************************************
4931 ****** Global to the neighbor ******
4932 ************************************/
4933 if (afi == AFI_IP && safi == SAFI_UNICAST)
4934 {
4935 /* remote-as. */
4936 if (! peer_group_active (peer))
4937 {
4938 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4939 vty_out (vty, " neighbor %s peer-group%s", addr,
4940 VTY_NEWLINE);
4941 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004942 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004943 VTY_NEWLINE);
4944 }
4945 else
4946 {
4947 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004948 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004949 VTY_NEWLINE);
4950 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4951 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4952 peer->group->name, VTY_NEWLINE);
4953 }
4954
4955 /* local-as. */
4956 if (peer->change_local_as)
4957 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00004958 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004959 peer->change_local_as,
4960 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00004961 " no-prepend" : "",
4962 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
4963 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004964
4965 /* Description. */
4966 if (peer->desc)
4967 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4968 VTY_NEWLINE);
4969
4970 /* Shutdown. */
4971 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4972 if (! peer_group_active (peer) ||
4973 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4974 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4975
Paul Jakma0df7c912008-07-21 21:02:49 +00004976 /* Password. */
4977 if (peer->password)
4978 if (!peer_group_active (peer)
4979 || ! g_peer->password
4980 || strcmp (peer->password, g_peer->password) != 0)
4981 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4982 VTY_NEWLINE);
4983
paul718e3742002-12-13 20:15:29 +00004984 /* BGP port. */
4985 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004986 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004987 VTY_NEWLINE);
4988
4989 /* Local interface name. */
4990 if (peer->ifname)
4991 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4992 VTY_NEWLINE);
4993
4994 /* Passive. */
4995 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4996 if (! peer_group_active (peer) ||
4997 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4998 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4999
5000 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00005001 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00005002 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00005003 if (! peer_group_active (peer) ||
5004 g_peer->ttl != peer->ttl)
5005 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
5006 VTY_NEWLINE);
5007
Nick Hilliardfa411a22011-03-23 15:33:17 +00005008 /* ttl-security hops */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00005009 if (peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00005010 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00005011 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00005012 peer->gtsm_hops, VTY_NEWLINE);
5013
hasso6ffd2072005-02-02 14:50:11 +00005014 /* disable-connected-check. */
5015 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00005016 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00005017 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
5018 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005019
5020 /* Update-source. */
5021 if (peer->update_if)
5022 if (! peer_group_active (peer) || ! g_peer->update_if
5023 || strcmp (g_peer->update_if, peer->update_if) != 0)
5024 vty_out (vty, " neighbor %s update-source %s%s", addr,
5025 peer->update_if, VTY_NEWLINE);
5026 if (peer->update_source)
5027 if (! peer_group_active (peer) || ! g_peer->update_source
5028 || sockunion_cmp (g_peer->update_source,
5029 peer->update_source) != 0)
5030 vty_out (vty, " neighbor %s update-source %s%s", addr,
5031 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
5032 VTY_NEWLINE);
5033
paul718e3742002-12-13 20:15:29 +00005034 /* advertisement-interval */
Daniel Walton0d7435f2015-10-22 11:35:20 +03005035 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV) &&
5036 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00005037 vty_out (vty, " neighbor %s advertisement-interval %d%s",
5038 addr, peer->v_routeadv, VTY_NEWLINE);
5039
5040 /* timers. */
5041 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
5042 && ! peer_group_active (peer))
5043 vty_out (vty, " neighbor %s timers %d %d%s", addr,
5044 peer->keepalive, peer->holdtime, VTY_NEWLINE);
5045
Daniel Walton0d7435f2015-10-22 11:35:20 +03005046 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT) &&
5047 ! peer_group_active (peer))
paul718e3742002-12-13 20:15:29 +00005048 vty_out (vty, " neighbor %s timers connect %d%s", addr,
5049 peer->connect, VTY_NEWLINE);
5050
5051 /* Default weight. */
5052 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
5053 if (! peer_group_active (peer) ||
5054 g_peer->weight != peer->weight)
5055 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
5056 VTY_NEWLINE);
5057
paul718e3742002-12-13 20:15:29 +00005058 /* Dynamic capability. */
5059 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5060 if (! peer_group_active (peer) ||
5061 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
5062 vty_out (vty, " neighbor %s capability dynamic%s", addr,
5063 VTY_NEWLINE);
5064
5065 /* dont capability negotiation. */
5066 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
5067 if (! peer_group_active (peer) ||
5068 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
5069 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
5070 VTY_NEWLINE);
5071
5072 /* override capability negotiation. */
5073 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5074 if (! peer_group_active (peer) ||
5075 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
5076 vty_out (vty, " neighbor %s override-capability%s", addr,
5077 VTY_NEWLINE);
5078
5079 /* strict capability negotiation. */
5080 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5081 if (! peer_group_active (peer) ||
5082 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5083 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
5084 VTY_NEWLINE);
5085
Christian Franke15c71342012-11-19 11:17:31 +00005086 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
paul718e3742002-12-13 20:15:29 +00005087 {
5088 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5089 {
5090 if (peer->afc[AFI_IP][SAFI_UNICAST])
5091 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5092 }
5093 else
5094 {
5095 if (! peer->afc[AFI_IP][SAFI_UNICAST])
5096 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
5097 }
5098 }
5099 }
5100
5101
5102 /************************************
5103 ****** Per AF to the neighbor ******
5104 ************************************/
5105
5106 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
5107 {
5108 if (peer->af_group[afi][safi])
5109 vty_out (vty, " neighbor %s peer-group %s%s", addr,
5110 peer->group->name, VTY_NEWLINE);
5111 else
5112 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5113 }
5114
5115 /* ORF capability. */
5116 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5117 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5118 if (! peer->af_group[afi][safi])
5119 {
5120 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
5121
5122 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5123 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5124 vty_out (vty, " both");
5125 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
5126 vty_out (vty, " send");
5127 else
5128 vty_out (vty, " receive");
5129 vty_out (vty, "%s", VTY_NEWLINE);
5130 }
5131
5132 /* Route reflector client. */
5133 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
5134 && ! peer->af_group[afi][safi])
5135 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
5136 VTY_NEWLINE);
5137
5138 /* Nexthop self. */
5139 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
5140 && ! peer->af_group[afi][safi])
Timo Teräs9e7a53c2014-04-24 10:22:37 +03005141 vty_out (vty, " neighbor %s next-hop-self%s%s", addr,
5142 peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ?
5143 " all" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005144
5145 /* Remove private AS. */
5146 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
5147 && ! peer->af_group[afi][safi])
5148 vty_out (vty, " neighbor %s remove-private-AS%s",
5149 addr, VTY_NEWLINE);
5150
5151 /* send-community print. */
5152 if (! peer->af_group[afi][safi])
5153 {
5154 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5155 {
5156 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5157 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5158 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
5159 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5160 vty_out (vty, " neighbor %s send-community extended%s",
5161 addr, VTY_NEWLINE);
5162 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5163 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
5164 }
5165 else
5166 {
5167 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5168 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5169 vty_out (vty, " no neighbor %s send-community both%s",
5170 addr, VTY_NEWLINE);
5171 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5172 vty_out (vty, " no neighbor %s send-community extended%s",
5173 addr, VTY_NEWLINE);
5174 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5175 vty_out (vty, " no neighbor %s send-community%s",
5176 addr, VTY_NEWLINE);
5177 }
5178 }
5179
5180 /* Default information */
5181 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5182 && ! peer->af_group[afi][safi])
5183 {
5184 vty_out (vty, " neighbor %s default-originate", addr);
5185 if (peer->default_rmap[afi][safi].name)
5186 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5187 vty_out (vty, "%s", VTY_NEWLINE);
5188 }
5189
5190 /* Soft reconfiguration inbound. */
5191 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5192 if (! peer->af_group[afi][safi] ||
5193 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5194 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5195 VTY_NEWLINE);
5196
5197 /* maximum-prefix. */
5198 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5199 if (! peer->af_group[afi][safi]
5200 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005201 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005202 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5203 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005204 {
hasso0a486e52005-02-01 20:57:17 +00005205 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5206 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5207 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5208 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5209 vty_out (vty, " warning-only");
5210 if (peer->pmax_restart[afi][safi])
5211 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5212 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005213 }
paul718e3742002-12-13 20:15:29 +00005214
5215 /* Route server client. */
5216 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5217 && ! peer->af_group[afi][safi])
5218 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5219
Dylan Hall3cf12882011-10-27 15:28:17 +04005220 /* Nexthop-local unchanged. */
5221 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5222 && ! peer->af_group[afi][safi])
5223 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5224
paul718e3742002-12-13 20:15:29 +00005225 /* Allow AS in. */
5226 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5227 if (! peer_group_active (peer)
5228 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5229 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5230 {
5231 if (peer->allowas_in[afi][safi] == 3)
5232 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5233 else
5234 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5235 peer->allowas_in[afi][safi], VTY_NEWLINE);
5236 }
5237
5238 /* Filter. */
5239 bgp_config_write_filter (vty, peer, afi, safi);
5240
5241 /* atribute-unchanged. */
5242 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5243 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5244 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5245 && ! peer->af_group[afi][safi])
5246 {
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 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5251 else
5252 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5253 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5254 " as-path" : "",
5255 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5256 " next-hop" : "",
5257 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5258 " med" : "", VTY_NEWLINE);
5259 }
5260}
5261
5262/* Display "address-family" configuration header. */
5263void
5264bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5265 int *write)
5266{
5267 if (*write)
5268 return;
5269
5270 if (afi == AFI_IP && safi == SAFI_UNICAST)
5271 return;
5272
5273 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5274
5275 if (afi == AFI_IP)
5276 {
5277 if (safi == SAFI_MULTICAST)
5278 vty_out (vty, "ipv4 multicast");
5279 else if (safi == SAFI_MPLS_VPN)
5280 vty_out (vty, "vpnv4 unicast");
5281 }
5282 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005283 {
5284 vty_out (vty, "ipv6");
5285
5286 if (safi == SAFI_MULTICAST)
5287 vty_out (vty, " multicast");
5288 }
paul718e3742002-12-13 20:15:29 +00005289
5290 vty_out (vty, "%s", VTY_NEWLINE);
5291
5292 *write = 1;
5293}
5294
5295/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005296static int
paul718e3742002-12-13 20:15:29 +00005297bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5298 safi_t safi)
5299{
5300 int write = 0;
5301 struct peer *peer;
5302 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005303 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005304
5305 bgp_config_write_network (vty, bgp, afi, safi, &write);
5306
5307 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5308
paul1eb8ef22005-04-07 07:30:20 +00005309 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005310 {
5311 if (group->conf->afc[afi][safi])
5312 {
5313 bgp_config_write_family_header (vty, afi, safi, &write);
5314 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5315 }
5316 }
paul1eb8ef22005-04-07 07:30:20 +00005317 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005318 {
5319 if (peer->afc[afi][safi])
5320 {
5321 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5322 {
5323 bgp_config_write_family_header (vty, afi, safi, &write);
5324 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5325 }
5326 }
5327 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005328
5329 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5330
paul718e3742002-12-13 20:15:29 +00005331 if (write)
5332 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5333
5334 return write;
5335}
5336
5337int
5338bgp_config_write (struct vty *vty)
5339{
5340 int write = 0;
5341 struct bgp *bgp;
5342 struct peer_group *group;
5343 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005344 struct listnode *node, *nnode;
5345 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005346
5347 /* BGP Multiple instance. */
5348 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5349 {
5350 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5351 write++;
5352 }
5353
5354 /* BGP Config type. */
5355 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5356 {
5357 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5358 write++;
5359 }
5360
5361 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005362 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005363 {
5364 if (write)
5365 vty_out (vty, "!%s", VTY_NEWLINE);
5366
5367 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005368 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005369
5370 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5371 {
5372 if (bgp->name)
5373 vty_out (vty, " view %s", bgp->name);
5374 }
5375 vty_out (vty, "%s", VTY_NEWLINE);
5376
5377 /* No Synchronization */
5378 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5379 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5380
5381 /* BGP fast-external-failover. */
5382 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5383 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5384
5385 /* BGP router ID. */
5386 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5387 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5388 VTY_NEWLINE);
5389
paul848973c2003-08-13 00:32:49 +00005390 /* BGP log-neighbor-changes. */
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07005391 if (!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5392 vty_out (vty, " no bgp log-neighbor-changes%s", VTY_NEWLINE);
paul848973c2003-08-13 00:32:49 +00005393
paul718e3742002-12-13 20:15:29 +00005394 /* BGP configuration. */
5395 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5396 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5397
5398 /* BGP default ipv4-unicast. */
5399 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5400 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5401
5402 /* BGP default local-preference. */
5403 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5404 vty_out (vty, " bgp default local-preference %d%s",
5405 bgp->default_local_pref, VTY_NEWLINE);
5406
5407 /* BGP client-to-client reflection. */
5408 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5409 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5410
5411 /* BGP cluster ID. */
5412 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5413 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5414 VTY_NEWLINE);
5415
hassoe0701b72004-05-20 09:19:34 +00005416 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005417 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005418 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5419 VTY_NEWLINE);
5420
5421 /* Confederation peer */
5422 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005423 {
hassoe0701b72004-05-20 09:19:34 +00005424 int i;
paul718e3742002-12-13 20:15:29 +00005425
hassoe0701b72004-05-20 09:19:34 +00005426 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005427
hassoe0701b72004-05-20 09:19:34 +00005428 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005429 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005430
hassoe0701b72004-05-20 09:19:34 +00005431 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005432 }
5433
5434 /* BGP enforce-first-as. */
5435 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5436 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5437
5438 /* BGP deterministic-med. */
5439 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5440 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005441
5442 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005443 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5444 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5445 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005446 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5447 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5448
paul718e3742002-12-13 20:15:29 +00005449 /* BGP bestpath method. */
5450 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5451 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005452 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5453 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
Pradosh Mohapatra2fdd4552013-09-07 07:02:36 +00005454 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
5455 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
5456 }
paul718e3742002-12-13 20:15:29 +00005457 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5458 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5459 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5460 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5461 {
5462 vty_out (vty, " bgp bestpath med");
5463 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5464 vty_out (vty, " confed");
5465 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5466 vty_out (vty, " missing-as-worst");
5467 vty_out (vty, "%s", VTY_NEWLINE);
5468 }
5469
5470 /* BGP network import check. */
5471 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5472 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5473
5474 /* BGP scan interval. */
5475 bgp_config_write_scan_time (vty);
5476
5477 /* BGP flag dampening. */
5478 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5479 BGP_CONFIG_DAMPENING))
5480 bgp_config_write_damp (vty);
5481
5482 /* BGP static route configuration. */
5483 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5484
5485 /* BGP redistribute configuration. */
5486 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5487
5488 /* BGP timers configuration. */
5489 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5490 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5491 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5492 bgp->default_holdtime, VTY_NEWLINE);
5493
5494 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005495 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005496 {
5497 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5498 }
5499
5500 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005501 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005502 {
5503 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5504 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5505 }
5506
Josh Bailey165b5ff2011-07-20 20:43:22 -07005507 /* maximum-paths */
5508 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5509
paul718e3742002-12-13 20:15:29 +00005510 /* Distance configuration. */
5511 bgp_config_write_distance (vty, bgp);
5512
5513 /* No auto-summary */
5514 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5515 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5516
5517 /* IPv4 multicast configuration. */
5518 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5519
5520 /* IPv4 VPN configuration. */
5521 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5522
5523 /* IPv6 unicast configuration. */
5524 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5525
Paul Jakma37a217a2007-04-10 19:20:29 +00005526 /* IPv6 multicast configuration. */
5527 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5528
paul718e3742002-12-13 20:15:29 +00005529 write++;
5530 }
5531 return write;
5532}
5533
5534void
paul94f2b392005-06-28 12:44:16 +00005535bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005536{
5537 memset (&bgp_master, 0, sizeof (struct bgp_master));
5538
5539 bm = &bgp_master;
5540 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005541 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005542 bm->port = BGP_PORT_DEFAULT;
5543 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005544 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005545}
paul200df112005-06-01 11:17:05 +00005546
David Lamparter6b0655a2014-06-04 06:53:35 +02005547
paul718e3742002-12-13 20:15:29 +00005548void
paul94f2b392005-06-28 12:44:16 +00005549bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005550{
paul718e3742002-12-13 20:15:29 +00005551 /* BGP VTY commands installation. */
5552 bgp_vty_init ();
5553
paul718e3742002-12-13 20:15:29 +00005554 /* Init zebra. */
Donald Sharp774914f2015-10-14 08:50:39 -04005555 bgp_zebra_init (bm->master);
paul718e3742002-12-13 20:15:29 +00005556
5557 /* BGP inits. */
5558 bgp_attr_init ();
5559 bgp_debug_init ();
5560 bgp_dump_init ();
5561 bgp_route_init ();
5562 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005563 bgp_address_init ();
paul718e3742002-12-13 20:15:29 +00005564 bgp_scan_init ();
5565 bgp_mplsvpn_init ();
5566
5567 /* Access list initialize. */
5568 access_list_init ();
5569 access_list_add_hook (peer_distribute_update);
5570 access_list_delete_hook (peer_distribute_update);
5571
5572 /* Filter list initialize. */
5573 bgp_filter_init ();
5574 as_list_add_hook (peer_aslist_update);
5575 as_list_delete_hook (peer_aslist_update);
5576
5577 /* Prefix list initialize.*/
5578 prefix_list_init ();
5579 prefix_list_add_hook (peer_prefix_list_update);
5580 prefix_list_delete_hook (peer_prefix_list_update);
5581
5582 /* Community list initialize. */
5583 bgp_clist = community_list_init ();
5584
5585#ifdef HAVE_SNMP
5586 bgp_snmp_init ();
5587#endif /* HAVE_SNMP */
5588}
paul545acaf2004-04-20 15:13:15 +00005589
5590void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005591bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005592{
paul545acaf2004-04-20 15:13:15 +00005593 struct bgp *bgp;
5594 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005595 struct listnode *node, *nnode;
5596 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005597
paul1eb8ef22005-04-07 07:30:20 +00005598 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5599 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005600 if (peer->status == Established)
5601 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5602 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005603
paul545acaf2004-04-20 15:13:15 +00005604 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005605
paule210cf92005-06-15 19:15:35 +00005606 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005607 {
5608 work_queue_free (bm->process_main_queue);
5609 bm->process_main_queue = NULL;
5610 }
paule210cf92005-06-15 19:15:35 +00005611 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005612 {
5613 work_queue_free (bm->process_rsclient_queue);
5614 bm->process_rsclient_queue = NULL;
5615 }
paul545acaf2004-04-20 15:13:15 +00005616}