blob: 734c0df4468e9cb9060994563ff865f58dcf5c06 [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;
paul718e3742002-12-13 20:15:29 +0000925
926 /* Stop peer. */
927 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
928 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000929 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000930 {
931 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
932 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
933 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
934 }
paul718e3742002-12-13 20:15:29 +0000935 else
936 BGP_EVENT_ADD (peer, BGP_Stop);
937 }
938 type = peer_sort (peer);
939 peer->as = as;
940
paul848973c2003-08-13 00:32:49 +0000941 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
942 && ! bgp_confederation_peers_check (peer->bgp, as)
943 && peer->bgp->as != as)
944 peer->local_as = peer->bgp->confed_id;
945 else
946 peer->local_as = peer->bgp->as;
947
paul718e3742002-12-13 20:15:29 +0000948 /* Advertisement-interval reset */
949 if (peer_sort (peer) == BGP_PEER_IBGP)
950 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
951 else
952 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
953
954 /* TTL reset */
955 if (peer_sort (peer) == BGP_PEER_IBGP)
956 peer->ttl = 255;
957 else if (type == BGP_PEER_IBGP)
958 peer->ttl = 1;
959
960 /* reflector-client reset */
961 if (peer_sort (peer) != BGP_PEER_IBGP)
962 {
963 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
964 PEER_FLAG_REFLECTOR_CLIENT);
965 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
966 PEER_FLAG_REFLECTOR_CLIENT);
967 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
968 PEER_FLAG_REFLECTOR_CLIENT);
969 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
970 PEER_FLAG_REFLECTOR_CLIENT);
971 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
972 PEER_FLAG_REFLECTOR_CLIENT);
973 }
974
975 /* local-as reset */
976 if (peer_sort (peer) != BGP_PEER_EBGP)
977 {
978 peer->change_local_as = 0;
979 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +0000980 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +0000981 }
982}
983
984/* If peer does not exist, create new one. If peer already exists,
985 set AS number to the peer. */
986int
987peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
988 afi_t afi, safi_t safi)
989{
990 struct peer *peer;
991 as_t local_as;
992
993 peer = peer_lookup (bgp, su);
994
995 if (peer)
996 {
997 /* When this peer is a member of peer-group. */
998 if (peer->group)
999 {
1000 if (peer->group->conf->as)
1001 {
1002 /* Return peer group's AS number. */
1003 *as = peer->group->conf->as;
1004 return BGP_ERR_PEER_GROUP_MEMBER;
1005 }
1006 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
1007 {
1008 if (bgp->as != *as)
1009 {
1010 *as = peer->as;
1011 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1012 }
1013 }
1014 else
1015 {
1016 if (bgp->as == *as)
1017 {
1018 *as = peer->as;
1019 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1020 }
1021 }
1022 }
1023
1024 /* Existing peer's AS number change. */
1025 if (peer->as != *as)
1026 peer_as_change (peer, *as);
1027 }
1028 else
1029 {
1030
1031 /* If the peer is not part of our confederation, and its not an
1032 iBGP peer then spoof the source AS */
1033 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1034 && ! bgp_confederation_peers_check (bgp, *as)
1035 && bgp->as != *as)
1036 local_as = bgp->confed_id;
1037 else
1038 local_as = bgp->as;
1039
1040 /* If this is IPv4 unicast configuration and "no bgp default
1041 ipv4-unicast" is specified. */
1042
1043 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1044 && afi == AFI_IP && safi == SAFI_UNICAST)
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001045 peer_create (su, bgp, local_as, *as, 0, 0);
paul718e3742002-12-13 20:15:29 +00001046 else
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001047 peer_create (su, bgp, local_as, *as, afi, safi);
paul718e3742002-12-13 20:15:29 +00001048 }
1049
1050 return 0;
1051}
1052
1053/* Activate the peer or peer group for specified AFI and SAFI. */
1054int
1055peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1056{
1057 int active;
1058
1059 if (peer->afc[afi][safi])
1060 return 0;
1061
1062 /* Activate the address family configuration. */
1063 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1064 peer->afc[afi][safi] = 1;
1065 else
1066 {
1067 active = peer_active (peer);
1068
1069 peer->afc[afi][safi] = 1;
1070
1071 if (! active && peer_active (peer))
1072 bgp_timer_set (peer);
1073 else
1074 {
1075 if (peer->status == Established)
1076 {
1077 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1078 {
1079 peer->afc_adv[afi][safi] = 1;
1080 bgp_capability_send (peer, afi, safi,
1081 CAPABILITY_CODE_MP,
1082 CAPABILITY_ACTION_SET);
1083 if (peer->afc_recv[afi][safi])
1084 {
1085 peer->afc_nego[afi][safi] = 1;
1086 bgp_announce_route (peer, afi, safi);
1087 }
1088 }
1089 else
hassoe0701b72004-05-20 09:19:34 +00001090 {
1091 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1092 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1093 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1094 }
paul718e3742002-12-13 20:15:29 +00001095 }
1096 }
1097 }
1098 return 0;
1099}
1100
1101int
1102peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1103{
1104 struct peer_group *group;
1105 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001106 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001107
1108 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1109 {
1110 group = peer->group;
1111
paul1eb8ef22005-04-07 07:30:20 +00001112 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001113 {
1114 if (peer1->af_group[afi][safi])
1115 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1116 }
1117 }
1118 else
1119 {
1120 if (peer->af_group[afi][safi])
1121 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1122 }
1123
1124 if (! peer->afc[afi][safi])
1125 return 0;
1126
1127 /* De-activate the address family configuration. */
1128 peer->afc[afi][safi] = 0;
1129 peer_af_flag_reset (peer, afi, safi);
1130
1131 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1132 {
1133 if (peer->status == Established)
1134 {
1135 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1136 {
1137 peer->afc_adv[afi][safi] = 0;
1138 peer->afc_nego[afi][safi] = 0;
1139
1140 if (peer_active_nego (peer))
1141 {
1142 bgp_capability_send (peer, afi, safi,
1143 CAPABILITY_CODE_MP,
1144 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001145 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001146 peer->pcount[afi][safi] = 0;
1147 }
1148 else
hassoe0701b72004-05-20 09:19:34 +00001149 {
1150 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1151 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1152 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1153 }
paul718e3742002-12-13 20:15:29 +00001154 }
1155 else
hassoe0701b72004-05-20 09:19:34 +00001156 {
1157 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1158 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1159 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1160 }
paul718e3742002-12-13 20:15:29 +00001161 }
1162 }
1163 return 0;
1164}
1165
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001166static void
hasso93406d82005-02-02 14:40:33 +00001167peer_nsf_stop (struct peer *peer)
1168{
1169 afi_t afi;
1170 safi_t safi;
1171
1172 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1173 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1174
1175 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +04001176 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +00001177 peer->nsf[afi][safi] = 0;
1178
1179 if (peer->t_gr_restart)
1180 {
1181 BGP_TIMER_OFF (peer->t_gr_restart);
1182 if (BGP_DEBUG (events, EVENTS))
1183 zlog_debug ("%s graceful restart timer stopped", peer->host);
1184 }
1185 if (peer->t_gr_stale)
1186 {
1187 BGP_TIMER_OFF (peer->t_gr_stale);
1188 if (BGP_DEBUG (events, EVENTS))
1189 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1190 }
1191 bgp_clear_route_all (peer);
1192}
1193
Paul Jakmaca058a32006-09-14 02:58:49 +00001194/* Delete peer from confguration.
1195 *
1196 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1197 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1198 *
1199 * This function /should/ take care to be idempotent, to guard against
1200 * it being called multiple times through stray events that come in
1201 * that happen to result in this function being called again. That
1202 * said, getting here for a "Deleted" peer is a bug in the neighbour
1203 * FSM.
1204 */
paul718e3742002-12-13 20:15:29 +00001205int
1206peer_delete (struct peer *peer)
1207{
1208 int i;
1209 afi_t afi;
1210 safi_t safi;
1211 struct bgp *bgp;
1212 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001213 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001214
Paul Jakmaca058a32006-09-14 02:58:49 +00001215 assert (peer->status != Deleted);
1216
paul718e3742002-12-13 20:15:29 +00001217 bgp = peer->bgp;
1218
hasso93406d82005-02-02 14:40:33 +00001219 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1220 peer_nsf_stop (peer);
1221
Chris Caputo228da422009-07-18 05:44:03 +00001222 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001223 relationship. */
1224 if (peer->group)
1225 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001226 if ((pn = listnode_lookup (peer->group->peer, peer)))
1227 {
1228 peer = peer_unlock (peer); /* group->peer list reference */
1229 list_delete_node (peer->group->peer, pn);
1230 }
paul718e3742002-12-13 20:15:29 +00001231 peer->group = NULL;
1232 }
paul200df112005-06-01 11:17:05 +00001233
paul718e3742002-12-13 20:15:29 +00001234 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001235 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1236 * executed after peer structure is deleted.
1237 */
hassoe0701b72004-05-20 09:19:34 +00001238 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001239 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001240 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001241
1242 /* Password configuration */
1243 if (peer->password)
1244 {
1245 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1246 peer->password = NULL;
1247
1248 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1249 bgp_md5_set (peer);
1250 }
1251
Paul Jakmaca058a32006-09-14 02:58:49 +00001252 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001253
paul718e3742002-12-13 20:15:29 +00001254 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001255 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1256 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001257 {
Chris Caputo228da422009-07-18 05:44:03 +00001258 peer_unlock (peer); /* bgp peer list reference */
1259 list_delete_node (bgp->peer, pn);
1260 }
paul200df112005-06-01 11:17:05 +00001261
Chris Caputo228da422009-07-18 05:44:03 +00001262 if (peer_rsclient_active (peer)
1263 && (pn = listnode_lookup (bgp->rsclient, peer)))
1264 {
1265 peer_unlock (peer); /* rsclient list reference */
1266 list_delete_node (bgp->rsclient, pn);
1267
1268 /* Clear our own rsclient ribs. */
1269 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1270 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1271 if (CHECK_FLAG(peer->af_flags[afi][safi],
1272 PEER_FLAG_RSERVER_CLIENT))
1273 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001274 }
1275
1276 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1277 member of a peer_group. */
1278 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1279 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1280 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001281 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001282
paul200df112005-06-01 11:17:05 +00001283 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001284 if (peer->ibuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001285 {
1286 stream_free (peer->ibuf);
1287 peer->ibuf = NULL;
1288 }
1289
paul718e3742002-12-13 20:15:29 +00001290 if (peer->obuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001291 {
1292 stream_fifo_free (peer->obuf);
1293 peer->obuf = NULL;
1294 }
1295
paul718e3742002-12-13 20:15:29 +00001296 if (peer->work)
Daniel Walton363c9032015-10-21 06:42:54 -07001297 {
1298 stream_free (peer->work);
1299 peer->work = NULL;
1300 }
1301
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00001302 if (peer->scratch)
Daniel Walton363c9032015-10-21 06:42:54 -07001303 {
1304 stream_free(peer->scratch);
1305 peer->scratch = NULL;
1306 }
Paul Jakma18937402006-07-27 19:05:12 +00001307
paul718e3742002-12-13 20:15:29 +00001308 /* Local and remote addresses. */
1309 if (peer->su_local)
Daniel Walton363c9032015-10-21 06:42:54 -07001310 {
1311 sockunion_free (peer->su_local);
1312 peer->su_local = NULL;
1313 }
1314
paul718e3742002-12-13 20:15:29 +00001315 if (peer->su_remote)
Daniel Walton363c9032015-10-21 06:42:54 -07001316 {
1317 sockunion_free (peer->su_remote);
1318 peer->su_remote = NULL;
1319 }
paul200df112005-06-01 11:17:05 +00001320
paul718e3742002-12-13 20:15:29 +00001321 /* Free filter related memory. */
1322 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1323 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1324 {
1325 filter = &peer->filter[afi][safi];
1326
1327 for (i = FILTER_IN; i < FILTER_MAX; i++)
1328 {
1329 if (filter->dlist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001330 {
1331 free(filter->dlist[i].name);
1332 filter->dlist[i].name = NULL;
1333 }
1334
paul718e3742002-12-13 20:15:29 +00001335 if (filter->plist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001336 {
1337 free(filter->plist[i].name);
1338 filter->plist[i].name = NULL;
1339 }
1340
paul718e3742002-12-13 20:15:29 +00001341 if (filter->aslist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001342 {
1343 free(filter->aslist[i].name);
1344 filter->aslist[i].name = NULL;
1345 }
paul200df112005-06-01 11:17:05 +00001346 }
Daniel Walton363c9032015-10-21 06:42:54 -07001347
paul200df112005-06-01 11:17:05 +00001348 for (i = RMAP_IN; i < RMAP_MAX; i++)
1349 {
paul718e3742002-12-13 20:15:29 +00001350 if (filter->map[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001351 {
1352 free (filter->map[i].name);
1353 filter->map[i].name = NULL;
1354 }
paul718e3742002-12-13 20:15:29 +00001355 }
1356
1357 if (filter->usmap.name)
Daniel Walton363c9032015-10-21 06:42:54 -07001358 {
1359 free (filter->usmap.name);
1360 filter->usmap.name = NULL;
1361 }
paul718e3742002-12-13 20:15:29 +00001362
1363 if (peer->default_rmap[afi][safi].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001364 {
1365 free (peer->default_rmap[afi][safi].name);
1366 peer->default_rmap[afi][safi].name = NULL;
1367 }
paul718e3742002-12-13 20:15:29 +00001368 }
paul200df112005-06-01 11:17:05 +00001369
1370 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001371
1372 return 0;
1373}
David Lamparter6b0655a2014-06-04 06:53:35 +02001374
paul94f2b392005-06-28 12:44:16 +00001375static int
paul718e3742002-12-13 20:15:29 +00001376peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1377{
1378 return strcmp (g1->name, g2->name);
1379}
1380
1381/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001382static int
paul718e3742002-12-13 20:15:29 +00001383peer_group_active (struct peer *peer)
1384{
1385 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1386 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1387 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1388 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1389 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1390 return 1;
1391 return 0;
1392}
1393
1394/* Peer group cofiguration. */
1395static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001396peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001397{
1398 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1399 sizeof (struct peer_group));
1400}
1401
paul94f2b392005-06-28 12:44:16 +00001402static void
paul718e3742002-12-13 20:15:29 +00001403peer_group_free (struct peer_group *group)
1404{
1405 XFREE (MTYPE_PEER_GROUP, group);
1406}
1407
1408struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001409peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001410{
1411 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001412 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001413
paul1eb8ef22005-04-07 07:30:20 +00001414 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001415 {
1416 if (strcmp (group->name, name) == 0)
1417 return group;
1418 }
1419 return NULL;
1420}
1421
1422struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001423peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001424{
1425 struct peer_group *group;
1426
1427 group = peer_group_lookup (bgp, name);
1428 if (group)
1429 return group;
1430
1431 group = peer_group_new ();
1432 group->bgp = bgp;
1433 group->name = strdup (name);
1434 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001435 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001436 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1437 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001438 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001439 group->conf->group = group;
1440 group->conf->as = 0;
1441 group->conf->ttl = 1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001442 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001443 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1444 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1445 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1446 group->conf->keepalive = 0;
1447 group->conf->holdtime = 0;
1448 group->conf->connect = 0;
1449 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1450 listnode_add_sort (bgp->group, group);
1451
1452 return 0;
1453}
1454
paul94f2b392005-06-28 12:44:16 +00001455static void
paul718e3742002-12-13 20:15:29 +00001456peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1457 afi_t afi, safi_t safi)
1458{
1459 int in = FILTER_IN;
1460 int out = FILTER_OUT;
1461 struct peer *conf;
1462 struct bgp_filter *pfilter;
1463 struct bgp_filter *gfilter;
1464
1465 conf = group->conf;
1466 pfilter = &peer->filter[afi][safi];
1467 gfilter = &conf->filter[afi][safi];
1468
1469 /* remote-as */
1470 if (conf->as)
1471 peer->as = conf->as;
1472
1473 /* remote-as */
1474 if (conf->change_local_as)
1475 peer->change_local_as = conf->change_local_as;
1476
1477 /* TTL */
1478 peer->ttl = conf->ttl;
1479
Nick Hilliardfa411a22011-03-23 15:33:17 +00001480 /* GTSM hops */
1481 peer->gtsm_hops = conf->gtsm_hops;
1482
paul718e3742002-12-13 20:15:29 +00001483 /* Weight */
1484 peer->weight = conf->weight;
1485
1486 /* peer flags apply */
1487 peer->flags = conf->flags;
1488 /* peer af_flags apply */
1489 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1490 /* peer config apply */
1491 peer->config = conf->config;
1492
1493 /* peer timers apply */
1494 peer->holdtime = conf->holdtime;
1495 peer->keepalive = conf->keepalive;
1496 peer->connect = conf->connect;
1497 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1498 peer->v_connect = conf->connect;
1499 else
1500 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1501
1502 /* advertisement-interval reset */
1503 if (peer_sort (peer) == BGP_PEER_IBGP)
1504 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1505 else
1506 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1507
Paul Jakma0df7c912008-07-21 21:02:49 +00001508 /* password apply */
Roman Hoog Antink0e4303d2013-01-18 13:52:03 +01001509 if (conf->password && !peer->password)
Paul Jakma0df7c912008-07-21 21:02:49 +00001510 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
Paul Jakma0df7c912008-07-21 21:02:49 +00001511
1512 bgp_md5_set (peer);
1513
paul718e3742002-12-13 20:15:29 +00001514 /* maximum-prefix */
1515 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001516 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001517 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001518
1519 /* allowas-in */
1520 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1521
paulfee0f4c2004-09-13 05:12:46 +00001522 /* route-server-client */
1523 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1524 {
1525 /* Make peer's RIB point to group's RIB. */
1526 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1527
1528 /* Import policy. */
1529 if (pfilter->map[RMAP_IMPORT].name)
1530 free (pfilter->map[RMAP_IMPORT].name);
1531 if (gfilter->map[RMAP_IMPORT].name)
1532 {
1533 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1534 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1535 }
1536 else
1537 {
1538 pfilter->map[RMAP_IMPORT].name = NULL;
1539 pfilter->map[RMAP_IMPORT].map = NULL;
1540 }
1541
1542 /* Export policy. */
1543 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1544 {
1545 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1546 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1547 }
1548 }
1549
paul718e3742002-12-13 20:15:29 +00001550 /* default-originate route-map */
1551 if (conf->default_rmap[afi][safi].name)
1552 {
1553 if (peer->default_rmap[afi][safi].name)
1554 free (peer->default_rmap[afi][safi].name);
1555 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1556 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1557 }
1558
1559 /* update-source apply */
1560 if (conf->update_source)
1561 {
1562 if (peer->update_source)
1563 sockunion_free (peer->update_source);
1564 if (peer->update_if)
1565 {
1566 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1567 peer->update_if = NULL;
1568 }
1569 peer->update_source = sockunion_dup (conf->update_source);
1570 }
1571 else if (conf->update_if)
1572 {
1573 if (peer->update_if)
1574 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1575 if (peer->update_source)
1576 {
1577 sockunion_free (peer->update_source);
1578 peer->update_source = NULL;
1579 }
1580 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1581 }
1582
1583 /* inbound filter apply */
1584 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1585 {
1586 if (pfilter->dlist[in].name)
1587 free (pfilter->dlist[in].name);
1588 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1589 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1590 }
1591 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1592 {
1593 if (pfilter->plist[in].name)
1594 free (pfilter->plist[in].name);
1595 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1596 pfilter->plist[in].plist = gfilter->plist[in].plist;
1597 }
1598 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1599 {
1600 if (pfilter->aslist[in].name)
1601 free (pfilter->aslist[in].name);
1602 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1603 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1604 }
paulfee0f4c2004-09-13 05:12:46 +00001605 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001606 {
paulfee0f4c2004-09-13 05:12:46 +00001607 if (pfilter->map[RMAP_IN].name)
1608 free (pfilter->map[RMAP_IN].name);
1609 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1610 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001611 }
1612
1613 /* outbound filter apply */
1614 if (gfilter->dlist[out].name)
1615 {
1616 if (pfilter->dlist[out].name)
1617 free (pfilter->dlist[out].name);
1618 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1619 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1620 }
1621 else
1622 {
1623 if (pfilter->dlist[out].name)
1624 free (pfilter->dlist[out].name);
1625 pfilter->dlist[out].name = NULL;
1626 pfilter->dlist[out].alist = NULL;
1627 }
1628 if (gfilter->plist[out].name)
1629 {
1630 if (pfilter->plist[out].name)
1631 free (pfilter->plist[out].name);
1632 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1633 pfilter->plist[out].plist = gfilter->plist[out].plist;
1634 }
1635 else
1636 {
1637 if (pfilter->plist[out].name)
1638 free (pfilter->plist[out].name);
1639 pfilter->plist[out].name = NULL;
1640 pfilter->plist[out].plist = NULL;
1641 }
1642 if (gfilter->aslist[out].name)
1643 {
1644 if (pfilter->aslist[out].name)
1645 free (pfilter->aslist[out].name);
1646 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1647 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1648 }
1649 else
1650 {
1651 if (pfilter->aslist[out].name)
1652 free (pfilter->aslist[out].name);
1653 pfilter->aslist[out].name = NULL;
1654 pfilter->aslist[out].aslist = NULL;
1655 }
paulfee0f4c2004-09-13 05:12:46 +00001656 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001657 {
paulfee0f4c2004-09-13 05:12:46 +00001658 if (pfilter->map[RMAP_OUT].name)
1659 free (pfilter->map[RMAP_OUT].name);
1660 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1661 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001662 }
1663 else
1664 {
paulfee0f4c2004-09-13 05:12:46 +00001665 if (pfilter->map[RMAP_OUT].name)
1666 free (pfilter->map[RMAP_OUT].name);
1667 pfilter->map[RMAP_OUT].name = NULL;
1668 pfilter->map[RMAP_OUT].map = NULL;
1669 }
1670
1671 /* RS-client's import/export route-maps. */
1672 if (gfilter->map[RMAP_IMPORT].name)
1673 {
1674 if (pfilter->map[RMAP_IMPORT].name)
1675 free (pfilter->map[RMAP_IMPORT].name);
1676 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1677 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1678 }
1679 else
1680 {
1681 if (pfilter->map[RMAP_IMPORT].name)
1682 free (pfilter->map[RMAP_IMPORT].name);
1683 pfilter->map[RMAP_IMPORT].name = NULL;
1684 pfilter->map[RMAP_IMPORT].map = NULL;
1685 }
1686 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1687 {
1688 if (pfilter->map[RMAP_EXPORT].name)
1689 free (pfilter->map[RMAP_EXPORT].name);
1690 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1691 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001692 }
1693
1694 if (gfilter->usmap.name)
1695 {
1696 if (pfilter->usmap.name)
1697 free (pfilter->usmap.name);
1698 pfilter->usmap.name = strdup (gfilter->usmap.name);
1699 pfilter->usmap.map = gfilter->usmap.map;
1700 }
1701 else
1702 {
1703 if (pfilter->usmap.name)
1704 free (pfilter->usmap.name);
1705 pfilter->usmap.name = NULL;
1706 pfilter->usmap.map = NULL;
1707 }
1708}
1709
1710/* Peer group's remote AS configuration. */
1711int
paulfd79ac92004-10-13 05:06:08 +00001712peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001713{
1714 struct peer_group *group;
1715 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001716 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001717
1718 group = peer_group_lookup (bgp, group_name);
1719 if (! group)
1720 return -1;
1721
1722 if (group->conf->as == *as)
1723 return 0;
1724
1725 /* When we setup peer-group AS number all peer group member's AS
1726 number must be updated to same number. */
1727 peer_as_change (group->conf, *as);
1728
paul1eb8ef22005-04-07 07:30:20 +00001729 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001730 {
1731 if (peer->as != *as)
1732 peer_as_change (peer, *as);
1733 }
1734
1735 return 0;
1736}
1737
1738int
1739peer_group_delete (struct peer_group *group)
1740{
1741 struct bgp *bgp;
1742 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001743 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001744
1745 bgp = group->bgp;
1746
paul1eb8ef22005-04-07 07:30:20 +00001747 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001748 {
paul718e3742002-12-13 20:15:29 +00001749 peer_delete (peer);
1750 }
1751 list_delete (group->peer);
1752
1753 free (group->name);
1754 group->name = NULL;
1755
1756 group->conf->group = NULL;
1757 peer_delete (group->conf);
1758
1759 /* Delete from all peer_group list. */
1760 listnode_delete (bgp->group, group);
1761
1762 peer_group_free (group);
1763
1764 return 0;
1765}
1766
1767int
1768peer_group_remote_as_delete (struct peer_group *group)
1769{
1770 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001771 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001772
1773 if (! group->conf->as)
1774 return 0;
1775
paul1eb8ef22005-04-07 07:30:20 +00001776 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001777 {
paul718e3742002-12-13 20:15:29 +00001778 peer_delete (peer);
1779 }
1780 list_delete_all_node (group->peer);
1781
1782 group->conf->as = 0;
1783
1784 return 0;
1785}
1786
1787/* Bind specified peer to peer group. */
1788int
1789peer_group_bind (struct bgp *bgp, union sockunion *su,
1790 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1791{
1792 struct peer *peer;
1793 int first_member = 0;
1794
1795 /* Check peer group's address family. */
1796 if (! group->conf->afc[afi][safi])
1797 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1798
1799 /* Lookup the peer. */
1800 peer = peer_lookup (bgp, su);
1801
1802 /* Create a new peer. */
1803 if (! peer)
1804 {
1805 if (! group->conf->as)
1806 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1807
1808 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1809 peer->group = group;
1810 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001811
Paul Jakmaca058a32006-09-14 02:58:49 +00001812 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001813 listnode_add (group->peer, peer);
1814 peer_group2peer_config_copy (group, peer, afi, safi);
1815
1816 return 0;
1817 }
1818
1819 /* When the peer already belongs to peer group, check the consistency. */
1820 if (peer->af_group[afi][safi])
1821 {
1822 if (strcmp (peer->group->name, group->name) != 0)
1823 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1824
1825 return 0;
1826 }
1827
1828 /* Check current peer group configuration. */
1829 if (peer_group_active (peer)
1830 && strcmp (peer->group->name, group->name) != 0)
1831 return BGP_ERR_PEER_GROUP_MISMATCH;
1832
1833 if (! group->conf->as)
1834 {
1835 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1836 && peer_sort (group->conf) != peer_sort (peer))
1837 {
1838 if (as)
1839 *as = peer->as;
1840 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1841 }
1842
1843 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1844 first_member = 1;
1845 }
1846
1847 peer->af_group[afi][safi] = 1;
1848 peer->afc[afi][safi] = 1;
1849 if (! peer->group)
1850 {
1851 peer->group = group;
paul200df112005-06-01 11:17:05 +00001852
Paul Jakmaca058a32006-09-14 02:58:49 +00001853 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001854 listnode_add (group->peer, peer);
1855 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001856 else
1857 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001858
1859 if (first_member)
1860 {
1861 /* Advertisement-interval reset */
1862 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1863 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1864 else
1865 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1866
1867 /* ebgp-multihop reset */
1868 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1869 group->conf->ttl = 255;
1870
1871 /* local-as reset */
1872 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1873 {
1874 group->conf->change_local_as = 0;
1875 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001876 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001877 }
1878 }
paulfee0f4c2004-09-13 05:12:46 +00001879
1880 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1881 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001882 struct listnode *pn;
1883
paulfee0f4c2004-09-13 05:12:46 +00001884 /* If it's not configured as RSERVER_CLIENT in any other address
1885 family, without being member of a peer_group, remove it from
1886 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001887 if (! peer_rsclient_active (peer)
1888 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001889 {
1890 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001891 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001892
1893 /* Clear our own rsclient rib for this afi/safi. */
1894 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001895 }
paulfee0f4c2004-09-13 05:12:46 +00001896
Paul Jakmab608d5b2008-07-02 02:12:07 +00001897 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001898
1899 /* Import policy. */
1900 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1901 {
1902 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1903 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1904 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1905 }
1906
1907 /* Export policy. */
1908 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1909 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1910 {
1911 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1912 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1913 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1914 }
1915 }
1916
paul718e3742002-12-13 20:15:29 +00001917 peer_group2peer_config_copy (group, peer, afi, safi);
1918
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001919 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001920 {
1921 peer->last_reset = PEER_DOWN_RMAP_BIND;
1922 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1923 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1924 }
paul718e3742002-12-13 20:15:29 +00001925 else
1926 BGP_EVENT_ADD (peer, BGP_Stop);
1927
1928 return 0;
1929}
1930
1931int
1932peer_group_unbind (struct bgp *bgp, struct peer *peer,
1933 struct peer_group *group, afi_t afi, safi_t safi)
1934{
1935 if (! peer->af_group[afi][safi])
1936 return 0;
1937
1938 if (group != peer->group)
1939 return BGP_ERR_PEER_GROUP_MISMATCH;
1940
1941 peer->af_group[afi][safi] = 0;
1942 peer->afc[afi][safi] = 0;
1943 peer_af_flag_reset (peer, afi, safi);
1944
paulfee0f4c2004-09-13 05:12:46 +00001945 if (peer->rib[afi][safi])
1946 peer->rib[afi][safi] = NULL;
1947
paul718e3742002-12-13 20:15:29 +00001948 if (! peer_group_active (peer))
1949 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001950 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001951 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001952 listnode_delete (group->peer, peer);
1953 peer->group = NULL;
1954 if (group->conf->as)
1955 {
1956 peer_delete (peer);
1957 return 0;
1958 }
1959 peer_global_config_reset (peer);
1960 }
1961
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001962 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001963 {
1964 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1965 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1966 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1967 }
paul718e3742002-12-13 20:15:29 +00001968 else
1969 BGP_EVENT_ADD (peer, BGP_Stop);
1970
1971 return 0;
1972}
David Lamparter6b0655a2014-06-04 06:53:35 +02001973
Vipin Kumardd49eb12014-09-30 14:36:38 -07001974
1975static int
1976bgp_startup_timer_expire (struct thread *thread)
1977{
1978 struct bgp *bgp;
1979
1980 bgp = THREAD_ARG (thread);
1981 bgp->t_startup = NULL;
1982
1983 return 0;
1984}
1985
paul718e3742002-12-13 20:15:29 +00001986/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001987static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001988bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001989{
1990 struct bgp *bgp;
1991 afi_t afi;
1992 safi_t safi;
1993
paul200df112005-06-01 11:17:05 +00001994 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1995 return NULL;
1996
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07001997 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00001998 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00001999 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00002000
2001 bgp->peer = list_new ();
2002 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
2003
2004 bgp->group = list_new ();
2005 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
2006
paulfee0f4c2004-09-13 05:12:46 +00002007 bgp->rsclient = list_new ();
2008 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
2009
paul718e3742002-12-13 20:15:29 +00002010 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2011 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2012 {
Paul Jakma64e580a2006-02-21 01:09:01 +00002013 bgp->route[afi][safi] = bgp_table_init (afi, safi);
2014 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
2015 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07002016 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
2017 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00002018 }
2019
2020 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
2021 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
2022 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00002023 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
2024 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07002025 bgp_flag_set (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES);
paul718e3742002-12-13 20:15:29 +00002026
2027 bgp->as = *as;
2028
2029 if (name)
2030 bgp->name = strdup (name);
2031
Donald Sharp774914f2015-10-14 08:50:39 -04002032 THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire,
Vipin Kumardd49eb12014-09-30 14:36:38 -07002033 bgp, bgp->restart_time);
2034
paul718e3742002-12-13 20:15:29 +00002035 return bgp;
2036}
2037
2038/* Return first entry of BGP. */
2039struct bgp *
paul94f2b392005-06-28 12:44:16 +00002040bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00002041{
Lou Berger056f3762013-04-10 12:30:04 -07002042 if (bm && bm->bgp && bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00002043 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00002044 return NULL;
2045}
2046
2047/* Lookup BGP entry. */
2048struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002049bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00002050{
2051 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002052 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002053
paul1eb8ef22005-04-07 07:30:20 +00002054 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002055 if (bgp->as == as
2056 && ((bgp->name == NULL && name == NULL)
2057 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
2058 return bgp;
2059 return NULL;
2060}
2061
2062/* Lookup BGP structure by view name. */
2063struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002064bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002065{
2066 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002067 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002068
paul1eb8ef22005-04-07 07:30:20 +00002069 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002070 if ((bgp->name == NULL && name == NULL)
2071 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2072 return bgp;
2073 return NULL;
2074}
2075
2076/* Called from VTY commands. */
2077int
paulfd79ac92004-10-13 05:06:08 +00002078bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002079{
2080 struct bgp *bgp;
2081
2082 /* Multiple instance check. */
2083 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2084 {
2085 if (name)
2086 bgp = bgp_lookup_by_name (name);
2087 else
2088 bgp = bgp_get_default ();
2089
2090 /* Already exists. */
2091 if (bgp)
2092 {
2093 if (bgp->as != *as)
2094 {
2095 *as = bgp->as;
2096 return BGP_ERR_INSTANCE_MISMATCH;
2097 }
2098 *bgp_val = bgp;
2099 return 0;
2100 }
2101 }
2102 else
2103 {
2104 /* BGP instance name can not be specified for single instance. */
2105 if (name)
2106 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2107
2108 /* Get default BGP structure if exists. */
2109 bgp = bgp_get_default ();
2110
2111 if (bgp)
2112 {
2113 if (bgp->as != *as)
2114 {
2115 *as = bgp->as;
2116 return BGP_ERR_AS_MISMATCH;
2117 }
2118 *bgp_val = bgp;
2119 return 0;
2120 }
2121 }
2122
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002123 bgp = bgp_create (as, name);
2124 bgp_router_id_set(bgp, &router_id_zebra);
2125 *bgp_val = bgp;
2126
Paul Jakmaad12dde2012-06-13 22:50:07 +01002127 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002128 if (list_isempty(bm->bgp)
2129 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002130 {
2131 if (bgp_socket (bm->port, bm->address) < 0)
2132 return BGP_ERR_INVALID_VALUE;
2133 }
2134
paul718e3742002-12-13 20:15:29 +00002135 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002136
2137 return 0;
2138}
2139
2140/* Delete BGP instance. */
2141int
2142bgp_delete (struct bgp *bgp)
2143{
2144 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002145 struct peer_group *group;
Denil Vira57cd5e72015-08-10 12:46:14 -07002146 struct listnode *node, *pnode;
2147 struct listnode *next, *pnext;
paul718e3742002-12-13 20:15:29 +00002148 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002149 int i;
2150
David Lampartercffe7802014-12-07 03:27:13 +01002151 THREAD_OFF (bgp->t_startup);
2152
paul718e3742002-12-13 20:15:29 +00002153 /* Delete static route. */
2154 bgp_static_delete (bgp);
2155
2156 /* Unset redistribution. */
2157 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2158 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2159 if (i != ZEBRA_ROUTE_BGP)
2160 bgp_redistribute_unset (bgp, afi, i);
2161
paul1eb8ef22005-04-07 07:30:20 +00002162 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002163 {
2164 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2165 {
2166 /* Send notify to remote peer. */
2167 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2168 }
2169
2170 peer_delete (peer);
2171 }
paul718e3742002-12-13 20:15:29 +00002172
Chris Caputo228da422009-07-18 05:44:03 +00002173 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002174 {
Denil Vira57cd5e72015-08-10 12:46:14 -07002175 for (ALL_LIST_ELEMENTS (group->peer, pnode, pnext, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002176 {
2177 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2178 {
2179 /* Send notify to remote peer. */
2180 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2181 }
2182 }
2183 peer_group_delete (group);
2184 }
Chris Caputo228da422009-07-18 05:44:03 +00002185
2186 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002187
2188 if (bgp->peer_self) {
2189 peer_delete(bgp->peer_self);
2190 bgp->peer_self = NULL;
2191 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002192
2193 /* Remove visibility via the master list - there may however still be
2194 * routes to be processed still referencing the struct bgp.
2195 */
2196 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002197 if (list_isempty(bm->bgp))
2198 bgp_close ();
2199
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002200 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002201
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002202 return 0;
2203}
2204
2205static void bgp_free (struct bgp *);
2206
2207void
2208bgp_lock (struct bgp *bgp)
2209{
2210 ++bgp->lock;
2211}
2212
2213void
2214bgp_unlock(struct bgp *bgp)
2215{
Chris Caputo228da422009-07-18 05:44:03 +00002216 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002217 if (--bgp->lock == 0)
2218 bgp_free (bgp);
2219}
2220
2221static void
2222bgp_free (struct bgp *bgp)
2223{
2224 afi_t afi;
2225 safi_t safi;
2226
2227 list_delete (bgp->group);
2228 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002229 list_delete (bgp->rsclient);
2230
paul718e3742002-12-13 20:15:29 +00002231 if (bgp->name)
2232 free (bgp->name);
2233
2234 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2235 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2236 {
2237 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002238 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002239 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002240 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002241 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002242 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002243 }
2244 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002245}
David Lamparter6b0655a2014-06-04 06:53:35 +02002246
paul718e3742002-12-13 20:15:29 +00002247struct peer *
2248peer_lookup (struct bgp *bgp, union sockunion *su)
2249{
2250 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002251 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002252
Steve Hillfc4dc592009-07-28 17:54:35 +01002253 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002254 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002255 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2256 if (sockunion_same (&peer->su, su)
2257 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2258 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002259 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002260 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002261 {
2262 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002263
Paul Jakma2158ad22009-07-28 18:10:55 +01002264 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2265 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2266 if (sockunion_same (&peer->su, su)
2267 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2268 return peer;
paul718e3742002-12-13 20:15:29 +00002269 }
2270 return NULL;
2271}
2272
2273struct peer *
2274peer_lookup_with_open (union sockunion *su, as_t remote_as,
2275 struct in_addr *remote_id, int *as)
2276{
2277 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002278 struct listnode *node;
2279 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002280 struct bgp *bgp;
2281
Steve Hillfc4dc592009-07-28 17:54:35 +01002282 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002283 return NULL;
2284
Paul Jakma9d878772009-08-05 16:25:16 +01002285 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002286 {
Paul Jakma9d878772009-08-05 16:25:16 +01002287 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2288 {
2289 if (sockunion_same (&peer->su, su)
2290 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2291 {
2292 if (peer->as == remote_as
2293 && peer->remote_id.s_addr == remote_id->s_addr)
2294 return peer;
2295 if (peer->as == remote_as)
2296 *as = 1;
2297 }
2298 }
2299
2300 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2301 {
2302 if (sockunion_same (&peer->su, su)
2303 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2304 {
2305 if (peer->as == remote_as
2306 && peer->remote_id.s_addr == 0)
2307 return peer;
2308 if (peer->as == remote_as)
2309 *as = 1;
2310 }
2311 }
paul718e3742002-12-13 20:15:29 +00002312 }
2313 return NULL;
2314}
David Lamparter6b0655a2014-06-04 06:53:35 +02002315
paul718e3742002-12-13 20:15:29 +00002316/* If peer is configured at least one address family return 1. */
2317int
2318peer_active (struct peer *peer)
2319{
2320 if (peer->afc[AFI_IP][SAFI_UNICAST]
2321 || peer->afc[AFI_IP][SAFI_MULTICAST]
2322 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2323 || peer->afc[AFI_IP6][SAFI_UNICAST]
2324 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2325 return 1;
2326 return 0;
2327}
2328
2329/* If peer is negotiated at least one address family return 1. */
2330int
2331peer_active_nego (struct peer *peer)
2332{
2333 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2334 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2335 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2336 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2337 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2338 return 1;
2339 return 0;
2340}
David Lamparter6b0655a2014-06-04 06:53:35 +02002341
paul718e3742002-12-13 20:15:29 +00002342/* peer_flag_change_type. */
2343enum peer_change_type
2344{
2345 peer_change_none,
2346 peer_change_reset,
2347 peer_change_reset_in,
2348 peer_change_reset_out,
2349};
2350
paul94f2b392005-06-28 12:44:16 +00002351static void
paul718e3742002-12-13 20:15:29 +00002352peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2353 enum peer_change_type type)
2354{
2355 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2356 return;
2357
Stephen Hemmingerd9d4ae52010-01-13 00:32:39 +00002358 if (peer->status != Established)
2359 return;
2360
paul718e3742002-12-13 20:15:29 +00002361 if (type == peer_change_reset)
2362 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2363 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2364 else if (type == peer_change_reset_in)
2365 {
2366 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2367 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2368 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2369 else
2370 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2371 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2372 }
2373 else if (type == peer_change_reset_out)
2374 bgp_announce_route (peer, afi, safi);
2375}
2376
2377struct peer_flag_action
2378{
2379 /* Peer's flag. */
2380 u_int32_t flag;
2381
2382 /* This flag can be set for peer-group member. */
2383 u_char not_for_member;
2384
2385 /* Action when the flag is changed. */
2386 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002387
2388 /* Peer down cause */
2389 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002390};
2391
Stephen Hemminger03621952009-07-21 16:27:20 -07002392static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002393 {
2394 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2395 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2396 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2397 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2398 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002399 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002400 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002401 { 0, 0, 0 }
2402 };
2403
Stephen Hemminger03621952009-07-21 16:27:20 -07002404static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002405 {
2406 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2407 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2408 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2409 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2410 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2411 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2412 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2413 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2414 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2415 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2416 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2417 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2418 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002419 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
Timo Teräs9e7a53c2014-04-24 10:22:37 +03002420 { PEER_FLAG_NEXTHOP_SELF_ALL, 1, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002421 { 0, 0, 0 }
2422 };
2423
2424/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002425static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002426peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002427 struct peer_flag_action *action, u_int32_t flag)
2428{
2429 int i;
2430 int found = 0;
2431 int reset_in = 0;
2432 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002433 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002434
2435 /* Check peer's frag action. */
2436 for (i = 0; i < size; i++)
2437 {
2438 match = &action_list[i];
2439
2440 if (match->flag == 0)
2441 break;
2442
2443 if (match->flag & flag)
2444 {
2445 found = 1;
2446
2447 if (match->type == peer_change_reset_in)
2448 reset_in = 1;
2449 if (match->type == peer_change_reset_out)
2450 reset_out = 1;
2451 if (match->type == peer_change_reset)
2452 {
2453 reset_in = 1;
2454 reset_out = 1;
2455 }
2456 if (match->not_for_member)
2457 action->not_for_member = 1;
2458 }
2459 }
2460
2461 /* Set peer clear type. */
2462 if (reset_in && reset_out)
2463 action->type = peer_change_reset;
2464 else if (reset_in)
2465 action->type = peer_change_reset_in;
2466 else if (reset_out)
2467 action->type = peer_change_reset_out;
2468 else
2469 action->type = peer_change_none;
2470
2471 return found;
2472}
2473
paul94f2b392005-06-28 12:44:16 +00002474static void
paul718e3742002-12-13 20:15:29 +00002475peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2476{
2477 if (flag == PEER_FLAG_SHUTDOWN)
2478 {
2479 if (CHECK_FLAG (peer->flags, flag))
2480 {
hasso93406d82005-02-02 14:40:33 +00002481 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2482 peer_nsf_stop (peer);
2483
hasso0a486e52005-02-01 20:57:17 +00002484 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2485 if (peer->t_pmax_restart)
2486 {
2487 BGP_TIMER_OFF (peer->t_pmax_restart);
2488 if (BGP_DEBUG (events, EVENTS))
2489 zlog_debug ("%s Maximum-prefix restart timer canceled",
2490 peer->host);
2491 }
2492
hasso93406d82005-02-02 14:40:33 +00002493 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2494 peer_nsf_stop (peer);
2495
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002496 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002497 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2498 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2499 else
2500 BGP_EVENT_ADD (peer, BGP_Stop);
2501 }
2502 else
2503 {
2504 peer->v_start = BGP_INIT_START_TIMER;
2505 BGP_EVENT_ADD (peer, BGP_Stop);
2506 }
2507 }
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002508 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002509 {
hassoc9502432005-02-01 22:01:48 +00002510 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2511 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2512 else if (flag == PEER_FLAG_PASSIVE)
2513 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002514 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002515 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002516
hassoc9502432005-02-01 22:01:48 +00002517 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2518 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002519 }
2520 else
2521 BGP_EVENT_ADD (peer, BGP_Stop);
2522}
2523
2524/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002525static int
paul718e3742002-12-13 20:15:29 +00002526peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2527{
2528 int found;
2529 int size;
2530 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002531 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002532 struct peer_flag_action action;
2533
2534 memset (&action, 0, sizeof (struct peer_flag_action));
2535 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2536
2537 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2538
2539 /* No flag action is found. */
2540 if (! found)
2541 return BGP_ERR_INVALID_FLAG;
2542
2543 /* Not for peer-group member. */
2544 if (action.not_for_member && peer_group_active (peer))
2545 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2546
2547 /* When unset the peer-group member's flag we have to check
2548 peer-group configuration. */
2549 if (! set && peer_group_active (peer))
2550 if (CHECK_FLAG (peer->group->conf->flags, flag))
2551 {
2552 if (flag == PEER_FLAG_SHUTDOWN)
2553 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2554 else
2555 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2556 }
2557
2558 /* Flag conflict check. */
2559 if (set
2560 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2561 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2562 return BGP_ERR_PEER_FLAG_CONFLICT;
2563
2564 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2565 {
2566 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2567 return 0;
2568 if (! set && ! CHECK_FLAG (peer->flags, flag))
2569 return 0;
2570 }
2571
2572 if (set)
2573 SET_FLAG (peer->flags, flag);
2574 else
2575 UNSET_FLAG (peer->flags, flag);
2576
2577 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2578 {
2579 if (action.type == peer_change_reset)
2580 peer_flag_modify_action (peer, flag);
2581
2582 return 0;
2583 }
2584
2585 /* peer-group member updates. */
2586 group = peer->group;
2587
paul1eb8ef22005-04-07 07:30:20 +00002588 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002589 {
2590 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2591 continue;
2592
2593 if (! set && ! CHECK_FLAG (peer->flags, flag))
2594 continue;
2595
2596 if (set)
2597 SET_FLAG (peer->flags, flag);
2598 else
2599 UNSET_FLAG (peer->flags, flag);
2600
2601 if (action.type == peer_change_reset)
2602 peer_flag_modify_action (peer, flag);
2603 }
2604 return 0;
2605}
2606
2607int
2608peer_flag_set (struct peer *peer, u_int32_t flag)
2609{
2610 return peer_flag_modify (peer, flag, 1);
2611}
2612
2613int
2614peer_flag_unset (struct peer *peer, u_int32_t flag)
2615{
2616 return peer_flag_modify (peer, flag, 0);
2617}
2618
paul94f2b392005-06-28 12:44:16 +00002619static int
paul718e3742002-12-13 20:15:29 +00002620peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2621{
2622 if (peer->af_group[afi][safi])
2623 return 1;
2624 return 0;
2625}
2626
paul94f2b392005-06-28 12:44:16 +00002627static int
paul718e3742002-12-13 20:15:29 +00002628peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2629 int set)
2630{
2631 int found;
2632 int size;
paul1eb8ef22005-04-07 07:30:20 +00002633 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002634 struct peer_group *group;
2635 struct peer_flag_action action;
2636
2637 memset (&action, 0, sizeof (struct peer_flag_action));
2638 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2639
2640 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2641
2642 /* No flag action is found. */
2643 if (! found)
2644 return BGP_ERR_INVALID_FLAG;
2645
2646 /* Adress family must be activated. */
2647 if (! peer->afc[afi][safi])
2648 return BGP_ERR_PEER_INACTIVE;
2649
2650 /* Not for peer-group member. */
2651 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2652 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2653
2654 /* Spcecial check for reflector client. */
2655 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2656 && peer_sort (peer) != BGP_PEER_IBGP)
2657 return BGP_ERR_NOT_INTERNAL_PEER;
2658
2659 /* Spcecial check for remove-private-AS. */
2660 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2661 && peer_sort (peer) == BGP_PEER_IBGP)
2662 return BGP_ERR_REMOVE_PRIVATE_AS;
2663
2664 /* When unset the peer-group member's flag we have to check
2665 peer-group configuration. */
2666 if (! set && peer->af_group[afi][safi])
2667 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2668 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2669
2670 /* When current flag configuration is same as requested one. */
2671 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2672 {
2673 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2674 return 0;
2675 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2676 return 0;
2677 }
2678
2679 if (set)
2680 SET_FLAG (peer->af_flags[afi][safi], flag);
2681 else
2682 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2683
2684 /* Execute action when peer is established. */
2685 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2686 && peer->status == Established)
2687 {
2688 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2689 bgp_clear_adj_in (peer, afi, safi);
2690 else
hassoe0701b72004-05-20 09:19:34 +00002691 {
2692 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2693 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2694 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2695 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2696 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2697 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2698 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2699 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2700
2701 peer_change_action (peer, afi, safi, action.type);
2702 }
2703
paul718e3742002-12-13 20:15:29 +00002704 }
2705
2706 /* Peer group member updates. */
2707 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2708 {
2709 group = peer->group;
2710
paul1eb8ef22005-04-07 07:30:20 +00002711 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002712 {
2713 if (! peer->af_group[afi][safi])
2714 continue;
2715
2716 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2717 continue;
2718
2719 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2720 continue;
2721
2722 if (set)
2723 SET_FLAG (peer->af_flags[afi][safi], flag);
2724 else
2725 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2726
2727 if (peer->status == Established)
2728 {
2729 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2730 bgp_clear_adj_in (peer, afi, safi);
2731 else
hassoe0701b72004-05-20 09:19:34 +00002732 {
2733 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2734 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2735 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2736 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2737 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2738 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2739 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2740 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2741
2742 peer_change_action (peer, afi, safi, action.type);
2743 }
paul718e3742002-12-13 20:15:29 +00002744 }
2745 }
2746 }
2747 return 0;
2748}
2749
2750int
2751peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2752{
2753 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2754}
2755
2756int
2757peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2758{
2759 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2760}
David Lamparter6b0655a2014-06-04 06:53:35 +02002761
paul718e3742002-12-13 20:15:29 +00002762/* EBGP multihop configuration. */
2763int
2764peer_ebgp_multihop_set (struct peer *peer, int ttl)
2765{
2766 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002767 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002768 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002769
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002770 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002771 return 0;
2772
Nick Hilliardfa411a22011-03-23 15:33:17 +00002773 /* see comment in peer_ttl_security_hops_set() */
2774 if (ttl != MAXTTL)
2775 {
2776 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2777 {
2778 group = peer->group;
2779 if (group->conf->gtsm_hops != 0)
2780 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2781
2782 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2783 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002784 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002785 continue;
2786
2787 if (peer1->gtsm_hops != 0)
2788 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2789 }
2790 }
2791 else
2792 {
2793 if (peer->gtsm_hops != 0)
2794 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2795 }
2796 }
2797
paul718e3742002-12-13 20:15:29 +00002798 peer->ttl = ttl;
2799
2800 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2801 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002802 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002803 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002804 }
2805 else
2806 {
2807 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002808 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002809 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002810 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002811 continue;
paul718e3742002-12-13 20:15:29 +00002812
pauleb821182004-05-01 08:44:08 +00002813 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002814
pauleb821182004-05-01 08:44:08 +00002815 if (peer->fd >= 0)
2816 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2817 }
paul718e3742002-12-13 20:15:29 +00002818 }
2819 return 0;
2820}
2821
2822int
2823peer_ebgp_multihop_unset (struct peer *peer)
2824{
2825 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002826 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002827
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002828 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002829 return 0;
2830
Nick Hilliardfa411a22011-03-23 15:33:17 +00002831 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2832 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2833
paul718e3742002-12-13 20:15:29 +00002834 if (peer_group_active (peer))
2835 peer->ttl = peer->group->conf->ttl;
2836 else
2837 peer->ttl = 1;
2838
2839 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2840 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002841 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002842 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002843 }
2844 else
2845 {
2846 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002847 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002848 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002849 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002850 continue;
paul718e3742002-12-13 20:15:29 +00002851
pauleb821182004-05-01 08:44:08 +00002852 peer->ttl = 1;
2853
2854 if (peer->fd >= 0)
2855 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2856 }
paul718e3742002-12-13 20:15:29 +00002857 }
2858 return 0;
2859}
David Lamparter6b0655a2014-06-04 06:53:35 +02002860
paul718e3742002-12-13 20:15:29 +00002861/* Neighbor description. */
2862int
2863peer_description_set (struct peer *peer, char *desc)
2864{
2865 if (peer->desc)
2866 XFREE (MTYPE_PEER_DESC, peer->desc);
2867
2868 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2869
2870 return 0;
2871}
2872
2873int
2874peer_description_unset (struct peer *peer)
2875{
2876 if (peer->desc)
2877 XFREE (MTYPE_PEER_DESC, peer->desc);
2878
2879 peer->desc = NULL;
2880
2881 return 0;
2882}
David Lamparter6b0655a2014-06-04 06:53:35 +02002883
paul718e3742002-12-13 20:15:29 +00002884/* Neighbor update-source. */
2885int
paulfd79ac92004-10-13 05:06:08 +00002886peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002887{
2888 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002889 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002890
2891 if (peer->update_if)
2892 {
2893 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2894 && strcmp (peer->update_if, ifname) == 0)
2895 return 0;
2896
2897 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2898 peer->update_if = NULL;
2899 }
2900
2901 if (peer->update_source)
2902 {
2903 sockunion_free (peer->update_source);
2904 peer->update_source = NULL;
2905 }
2906
2907 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2908
2909 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2910 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002911 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002912 {
2913 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2914 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2915 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2916 }
paul718e3742002-12-13 20:15:29 +00002917 else
2918 BGP_EVENT_ADD (peer, BGP_Stop);
2919 return 0;
2920 }
2921
2922 /* peer-group member updates. */
2923 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002924 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002925 {
2926 if (peer->update_if)
2927 {
2928 if (strcmp (peer->update_if, ifname) == 0)
2929 continue;
2930
2931 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2932 peer->update_if = NULL;
2933 }
2934
2935 if (peer->update_source)
2936 {
2937 sockunion_free (peer->update_source);
2938 peer->update_source = NULL;
2939 }
2940
2941 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2942
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002943 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002944 {
2945 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2946 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2947 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2948 }
paul718e3742002-12-13 20:15:29 +00002949 else
2950 BGP_EVENT_ADD (peer, BGP_Stop);
2951 }
2952 return 0;
2953}
2954
2955int
2956peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2957{
2958 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002959 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002960
2961 if (peer->update_source)
2962 {
2963 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2964 && sockunion_cmp (peer->update_source, su) == 0)
2965 return 0;
2966 sockunion_free (peer->update_source);
2967 peer->update_source = NULL;
2968 }
2969
2970 if (peer->update_if)
2971 {
2972 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2973 peer->update_if = NULL;
2974 }
2975
2976 peer->update_source = sockunion_dup (su);
2977
2978 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2979 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002980 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002981 {
2982 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2983 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2984 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2985 }
paul718e3742002-12-13 20:15:29 +00002986 else
2987 BGP_EVENT_ADD (peer, BGP_Stop);
2988 return 0;
2989 }
2990
2991 /* peer-group member updates. */
2992 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002993 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002994 {
2995 if (peer->update_source)
2996 {
2997 if (sockunion_cmp (peer->update_source, su) == 0)
2998 continue;
2999 sockunion_free (peer->update_source);
3000 peer->update_source = NULL;
3001 }
3002
3003 if (peer->update_if)
3004 {
3005 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3006 peer->update_if = NULL;
3007 }
3008
3009 peer->update_source = sockunion_dup (su);
3010
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003011 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003012 {
3013 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3014 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3015 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3016 }
paul718e3742002-12-13 20:15:29 +00003017 else
3018 BGP_EVENT_ADD (peer, BGP_Stop);
3019 }
3020 return 0;
3021}
3022
3023int
3024peer_update_source_unset (struct peer *peer)
3025{
3026 union sockunion *su;
3027 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003028 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003029
3030 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3031 && ! peer->update_source
3032 && ! peer->update_if)
3033 return 0;
3034
3035 if (peer->update_source)
3036 {
3037 sockunion_free (peer->update_source);
3038 peer->update_source = NULL;
3039 }
3040 if (peer->update_if)
3041 {
3042 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3043 peer->update_if = NULL;
3044 }
3045
3046 if (peer_group_active (peer))
3047 {
3048 group = peer->group;
3049
3050 if (group->conf->update_source)
3051 {
3052 su = sockunion_dup (group->conf->update_source);
3053 peer->update_source = su;
3054 }
3055 else if (group->conf->update_if)
3056 peer->update_if =
3057 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
3058 }
3059
3060 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3061 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003062 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003063 {
3064 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3065 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3066 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3067 }
paul718e3742002-12-13 20:15:29 +00003068 else
3069 BGP_EVENT_ADD (peer, BGP_Stop);
3070 return 0;
3071 }
3072
3073 /* peer-group member updates. */
3074 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003075 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003076 {
3077 if (! peer->update_source && ! peer->update_if)
3078 continue;
3079
3080 if (peer->update_source)
3081 {
3082 sockunion_free (peer->update_source);
3083 peer->update_source = NULL;
3084 }
3085
3086 if (peer->update_if)
3087 {
3088 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3089 peer->update_if = NULL;
3090 }
3091
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003092 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003093 {
3094 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3095 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3096 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3097 }
paul718e3742002-12-13 20:15:29 +00003098 else
3099 BGP_EVENT_ADD (peer, BGP_Stop);
3100 }
3101 return 0;
3102}
David Lamparter6b0655a2014-06-04 06:53:35 +02003103
paul718e3742002-12-13 20:15:29 +00003104int
3105peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003106 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003107{
3108 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003109 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003110
3111 /* Adress family must be activated. */
3112 if (! peer->afc[afi][safi])
3113 return BGP_ERR_PEER_INACTIVE;
3114
3115 /* Default originate can't be used for peer group memeber. */
3116 if (peer_is_group_member (peer, afi, safi))
3117 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3118
3119 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3120 || (rmap && ! peer->default_rmap[afi][safi].name)
3121 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3122 {
3123 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3124
3125 if (rmap)
3126 {
3127 if (peer->default_rmap[afi][safi].name)
3128 free (peer->default_rmap[afi][safi].name);
3129 peer->default_rmap[afi][safi].name = strdup (rmap);
3130 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3131 }
3132 }
3133
3134 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3135 {
3136 if (peer->status == Established && peer->afc_nego[afi][safi])
3137 bgp_default_originate (peer, afi, safi, 0);
3138 return 0;
3139 }
3140
3141 /* peer-group member updates. */
3142 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003143 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003144 {
3145 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3146
3147 if (rmap)
3148 {
3149 if (peer->default_rmap[afi][safi].name)
3150 free (peer->default_rmap[afi][safi].name);
3151 peer->default_rmap[afi][safi].name = strdup (rmap);
3152 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3153 }
3154
3155 if (peer->status == Established && peer->afc_nego[afi][safi])
3156 bgp_default_originate (peer, afi, safi, 0);
3157 }
3158 return 0;
3159}
3160
3161int
3162peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3163{
3164 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003165 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003166
3167 /* Adress family must be activated. */
3168 if (! peer->afc[afi][safi])
3169 return BGP_ERR_PEER_INACTIVE;
3170
3171 /* Default originate can't be used for peer group memeber. */
3172 if (peer_is_group_member (peer, afi, safi))
3173 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3174
3175 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3176 {
3177 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3178
3179 if (peer->default_rmap[afi][safi].name)
3180 free (peer->default_rmap[afi][safi].name);
3181 peer->default_rmap[afi][safi].name = NULL;
3182 peer->default_rmap[afi][safi].map = NULL;
3183 }
3184
3185 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3186 {
3187 if (peer->status == Established && peer->afc_nego[afi][safi])
3188 bgp_default_originate (peer, afi, safi, 1);
3189 return 0;
3190 }
3191
3192 /* peer-group member updates. */
3193 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003194 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003195 {
3196 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3197
3198 if (peer->default_rmap[afi][safi].name)
3199 free (peer->default_rmap[afi][safi].name);
3200 peer->default_rmap[afi][safi].name = NULL;
3201 peer->default_rmap[afi][safi].map = NULL;
3202
3203 if (peer->status == Established && peer->afc_nego[afi][safi])
3204 bgp_default_originate (peer, afi, safi, 1);
3205 }
3206 return 0;
3207}
David Lamparter6b0655a2014-06-04 06:53:35 +02003208
paul718e3742002-12-13 20:15:29 +00003209int
3210peer_port_set (struct peer *peer, u_int16_t port)
3211{
3212 peer->port = port;
3213 return 0;
3214}
3215
3216int
3217peer_port_unset (struct peer *peer)
3218{
3219 peer->port = BGP_PORT_DEFAULT;
3220 return 0;
3221}
David Lamparter6b0655a2014-06-04 06:53:35 +02003222
paul718e3742002-12-13 20:15:29 +00003223/* neighbor weight. */
3224int
3225peer_weight_set (struct peer *peer, u_int16_t weight)
3226{
3227 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003228 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003229
3230 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3231 peer->weight = weight;
3232
3233 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3234 return 0;
3235
3236 /* peer-group member updates. */
3237 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003238 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003239 {
3240 peer->weight = group->conf->weight;
3241 }
3242 return 0;
3243}
3244
3245int
3246peer_weight_unset (struct peer *peer)
3247{
3248 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003249 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003250
3251 /* Set default weight. */
3252 if (peer_group_active (peer))
3253 peer->weight = peer->group->conf->weight;
3254 else
3255 peer->weight = 0;
3256
3257 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3258
3259 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3260 return 0;
3261
3262 /* peer-group member updates. */
3263 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003264 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003265 {
3266 peer->weight = 0;
3267 }
3268 return 0;
3269}
David Lamparter6b0655a2014-06-04 06:53:35 +02003270
paul718e3742002-12-13 20:15:29 +00003271int
3272peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3273{
3274 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003275 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003276
3277 /* Not for peer group memeber. */
3278 if (peer_group_active (peer))
3279 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3280
3281 /* keepalive value check. */
3282 if (keepalive > 65535)
3283 return BGP_ERR_INVALID_VALUE;
3284
3285 /* Holdtime value check. */
3286 if (holdtime > 65535)
3287 return BGP_ERR_INVALID_VALUE;
3288
3289 /* Holdtime value must be either 0 or greater than 3. */
3290 if (holdtime < 3 && holdtime != 0)
3291 return BGP_ERR_INVALID_VALUE;
3292
3293 /* Set value to the configuration. */
3294 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3295 peer->holdtime = holdtime;
3296 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3297
3298 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3299 return 0;
3300
3301 /* peer-group member updates. */
3302 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003303 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003304 {
3305 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3306 peer->holdtime = group->conf->holdtime;
3307 peer->keepalive = group->conf->keepalive;
3308 }
3309 return 0;
3310}
3311
3312int
3313peer_timers_unset (struct peer *peer)
3314{
3315 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003316 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003317
3318 if (peer_group_active (peer))
3319 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3320
3321 /* Clear configuration. */
3322 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3323 peer->keepalive = 0;
3324 peer->holdtime = 0;
3325
3326 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3327 return 0;
3328
3329 /* peer-group member updates. */
3330 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003331 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003332 {
3333 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3334 peer->holdtime = 0;
3335 peer->keepalive = 0;
3336 }
3337
3338 return 0;
3339}
David Lamparter6b0655a2014-06-04 06:53:35 +02003340
paul718e3742002-12-13 20:15:29 +00003341int
3342peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3343{
3344 if (peer_group_active (peer))
3345 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3346
3347 if (connect > 65535)
3348 return BGP_ERR_INVALID_VALUE;
3349
3350 /* Set value to the configuration. */
3351 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3352 peer->connect = connect;
3353
3354 /* Set value to timer setting. */
3355 peer->v_connect = connect;
3356
3357 return 0;
3358}
3359
3360int
3361peer_timers_connect_unset (struct peer *peer)
3362{
3363 if (peer_group_active (peer))
3364 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3365
3366 /* Clear configuration. */
3367 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3368 peer->connect = 0;
3369
3370 /* Set timer setting to default value. */
3371 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3372
3373 return 0;
3374}
David Lamparter6b0655a2014-06-04 06:53:35 +02003375
paul718e3742002-12-13 20:15:29 +00003376int
3377peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3378{
3379 if (peer_group_active (peer))
3380 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3381
3382 if (routeadv > 600)
3383 return BGP_ERR_INVALID_VALUE;
3384
3385 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3386 peer->routeadv = routeadv;
3387 peer->v_routeadv = routeadv;
3388
3389 return 0;
3390}
3391
3392int
3393peer_advertise_interval_unset (struct peer *peer)
3394{
3395 if (peer_group_active (peer))
3396 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3397
3398 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3399 peer->routeadv = 0;
3400
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003401 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003402 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3403 else
3404 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3405
3406 return 0;
3407}
David Lamparter6b0655a2014-06-04 06:53:35 +02003408
paul718e3742002-12-13 20:15:29 +00003409/* neighbor interface */
3410int
paulfd79ac92004-10-13 05:06:08 +00003411peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003412{
3413 if (peer->ifname)
3414 free (peer->ifname);
3415 peer->ifname = strdup (str);
3416
3417 return 0;
3418}
3419
3420int
3421peer_interface_unset (struct peer *peer)
3422{
3423 if (peer->ifname)
3424 free (peer->ifname);
3425 peer->ifname = NULL;
3426
3427 return 0;
3428}
David Lamparter6b0655a2014-06-04 06:53:35 +02003429
paul718e3742002-12-13 20:15:29 +00003430/* Allow-as in. */
3431int
3432peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3433{
3434 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003435 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003436
3437 if (allow_num < 1 || allow_num > 10)
3438 return BGP_ERR_INVALID_VALUE;
3439
3440 if (peer->allowas_in[afi][safi] != allow_num)
3441 {
3442 peer->allowas_in[afi][safi] = allow_num;
3443 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3444 peer_change_action (peer, afi, safi, peer_change_reset_in);
3445 }
3446
3447 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3448 return 0;
3449
3450 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003451 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003452 {
3453 if (peer->allowas_in[afi][safi] != allow_num)
3454 {
3455 peer->allowas_in[afi][safi] = allow_num;
3456 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3457 peer_change_action (peer, afi, safi, peer_change_reset_in);
3458 }
3459
3460 }
3461 return 0;
3462}
3463
3464int
3465peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3466{
3467 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003468 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003469
3470 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3471 {
3472 peer->allowas_in[afi][safi] = 0;
3473 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3474 }
3475
3476 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3477 return 0;
3478
3479 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003480 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003481 {
3482 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3483 {
3484 peer->allowas_in[afi][safi] = 0;
3485 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3486 }
3487 }
3488 return 0;
3489}
David Lamparter6b0655a2014-06-04 06:53:35 +02003490
paul718e3742002-12-13 20:15:29 +00003491int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003492peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003493{
3494 struct bgp *bgp = peer->bgp;
3495 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003496 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003497
3498 if (peer_sort (peer) != BGP_PEER_EBGP
3499 && peer_sort (peer) != BGP_PEER_INTERNAL)
3500 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3501
3502 if (bgp->as == as)
3503 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3504
3505 if (peer_group_active (peer))
3506 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3507
Andrew Certain9d3f9702012-11-07 23:50:07 +00003508 if (peer->as == as)
3509 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3510
paul718e3742002-12-13 20:15:29 +00003511 if (peer->change_local_as == as &&
3512 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003513 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3514 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3515 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003516 return 0;
3517
3518 peer->change_local_as = as;
3519 if (no_prepend)
3520 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3521 else
3522 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3523
Andrew Certain9d3f9702012-11-07 23:50:07 +00003524 if (replace_as)
3525 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3526 else
3527 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3528
paul718e3742002-12-13 20:15:29 +00003529 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3530 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003531 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003532 {
3533 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3534 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3535 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3536 }
paul718e3742002-12-13 20:15:29 +00003537 else
3538 BGP_EVENT_ADD (peer, BGP_Stop);
3539
3540 return 0;
3541 }
3542
3543 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003544 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003545 {
3546 peer->change_local_as = as;
3547 if (no_prepend)
3548 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3549 else
3550 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3551
Andrew Certain9d3f9702012-11-07 23:50:07 +00003552 if (replace_as)
3553 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3554 else
3555 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3556
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003557 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003558 {
3559 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3560 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3561 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3562 }
paul718e3742002-12-13 20:15:29 +00003563 else
3564 BGP_EVENT_ADD (peer, BGP_Stop);
3565 }
3566
3567 return 0;
3568}
3569
3570int
3571peer_local_as_unset (struct peer *peer)
3572{
3573 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003574 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003575
3576 if (peer_group_active (peer))
3577 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3578
3579 if (! peer->change_local_as)
3580 return 0;
3581
3582 peer->change_local_as = 0;
3583 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003584 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003585
3586 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3587 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003588 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003589 {
3590 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3591 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3592 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3593 }
paul718e3742002-12-13 20:15:29 +00003594 else
3595 BGP_EVENT_ADD (peer, BGP_Stop);
3596
3597 return 0;
3598 }
3599
3600 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003601 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003602 {
3603 peer->change_local_as = 0;
3604 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003605 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003606
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}
David Lamparter6b0655a2014-06-04 06:53:35 +02003618
Paul Jakma0df7c912008-07-21 21:02:49 +00003619/* Set password for authenticating with the peer. */
3620int
3621peer_password_set (struct peer *peer, const char *password)
3622{
3623 struct listnode *nn, *nnode;
3624 int len = password ? strlen(password) : 0;
3625 int ret = BGP_SUCCESS;
3626
3627 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3628 return BGP_ERR_INVALID_VALUE;
3629
3630 if (peer->password && strcmp (peer->password, password) == 0
3631 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3632 return 0;
3633
3634 if (peer->password)
3635 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3636
3637 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3638
3639 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3640 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003641 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3642 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
Paul Jakma0df7c912008-07-21 21:02:49 +00003643 else
3644 BGP_EVENT_ADD (peer, BGP_Stop);
3645
3646 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3647 }
3648
3649 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3650 {
3651 if (peer->password && strcmp (peer->password, password) == 0)
3652 continue;
3653
3654 if (peer->password)
3655 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3656
3657 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3658
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003659 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003660 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3661 else
3662 BGP_EVENT_ADD (peer, BGP_Stop);
3663
3664 if (bgp_md5_set (peer) < 0)
3665 ret = BGP_ERR_TCPSIG_FAILED;
3666 }
3667
3668 return ret;
3669}
3670
3671int
3672peer_password_unset (struct peer *peer)
3673{
3674 struct listnode *nn, *nnode;
3675
3676 if (!peer->password
3677 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3678 return 0;
3679
3680 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3681 {
3682 if (peer_group_active (peer)
3683 && peer->group->conf->password
3684 && strcmp (peer->group->conf->password, peer->password) == 0)
3685 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3686
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003687 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003688 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3689 else
3690 BGP_EVENT_ADD (peer, BGP_Stop);
3691
3692 if (peer->password)
3693 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3694
3695 peer->password = NULL;
3696
3697 bgp_md5_set (peer);
3698
3699 return 0;
3700 }
3701
3702 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3703 peer->password = NULL;
3704
3705 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3706 {
3707 if (!peer->password)
3708 continue;
3709
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003710 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003711 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3712 else
3713 BGP_EVENT_ADD (peer, BGP_Stop);
3714
3715 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3716 peer->password = NULL;
3717
3718 bgp_md5_set (peer);
3719 }
3720
3721 return 0;
3722}
David Lamparter6b0655a2014-06-04 06:53:35 +02003723
paul718e3742002-12-13 20:15:29 +00003724/* Set distribute list to the peer. */
3725int
3726peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003727 const char *name)
paul718e3742002-12-13 20:15:29 +00003728{
3729 struct bgp_filter *filter;
3730 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003731 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003732
3733 if (! peer->afc[afi][safi])
3734 return BGP_ERR_PEER_INACTIVE;
3735
3736 if (direct != FILTER_IN && direct != FILTER_OUT)
3737 return BGP_ERR_INVALID_VALUE;
3738
3739 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3740 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3741
3742 filter = &peer->filter[afi][safi];
3743
3744 if (filter->plist[direct].name)
3745 return BGP_ERR_PEER_FILTER_CONFLICT;
3746
3747 if (filter->dlist[direct].name)
3748 free (filter->dlist[direct].name);
3749 filter->dlist[direct].name = strdup (name);
3750 filter->dlist[direct].alist = access_list_lookup (afi, name);
3751
3752 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3753 return 0;
3754
3755 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003756 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003757 {
3758 filter = &peer->filter[afi][safi];
3759
3760 if (! peer->af_group[afi][safi])
3761 continue;
3762
3763 if (filter->dlist[direct].name)
3764 free (filter->dlist[direct].name);
3765 filter->dlist[direct].name = strdup (name);
3766 filter->dlist[direct].alist = access_list_lookup (afi, name);
3767 }
3768
3769 return 0;
3770}
3771
3772int
3773peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3774{
3775 struct bgp_filter *filter;
3776 struct bgp_filter *gfilter;
3777 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003778 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003779
3780 if (! peer->afc[afi][safi])
3781 return BGP_ERR_PEER_INACTIVE;
3782
3783 if (direct != FILTER_IN && direct != FILTER_OUT)
3784 return BGP_ERR_INVALID_VALUE;
3785
3786 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3787 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3788
3789 filter = &peer->filter[afi][safi];
3790
3791 /* apply peer-group filter */
3792 if (peer->af_group[afi][safi])
3793 {
3794 gfilter = &peer->group->conf->filter[afi][safi];
3795
3796 if (gfilter->dlist[direct].name)
3797 {
3798 if (filter->dlist[direct].name)
3799 free (filter->dlist[direct].name);
3800 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3801 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3802 return 0;
3803 }
3804 }
3805
3806 if (filter->dlist[direct].name)
3807 free (filter->dlist[direct].name);
3808 filter->dlist[direct].name = NULL;
3809 filter->dlist[direct].alist = NULL;
3810
3811 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3812 return 0;
3813
3814 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003815 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003816 {
3817 filter = &peer->filter[afi][safi];
3818
3819 if (! peer->af_group[afi][safi])
3820 continue;
3821
3822 if (filter->dlist[direct].name)
3823 free (filter->dlist[direct].name);
3824 filter->dlist[direct].name = NULL;
3825 filter->dlist[direct].alist = NULL;
3826 }
3827
3828 return 0;
3829}
3830
3831/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003832static void
paul718e3742002-12-13 20:15:29 +00003833peer_distribute_update (struct access_list *access)
3834{
3835 afi_t afi;
3836 safi_t safi;
3837 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003838 struct listnode *mnode, *mnnode;
3839 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003840 struct bgp *bgp;
3841 struct peer *peer;
3842 struct peer_group *group;
3843 struct bgp_filter *filter;
3844
paul1eb8ef22005-04-07 07:30:20 +00003845 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003846 {
paul1eb8ef22005-04-07 07:30:20 +00003847 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003848 {
3849 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3850 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3851 {
3852 filter = &peer->filter[afi][safi];
3853
3854 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3855 {
3856 if (filter->dlist[direct].name)
3857 filter->dlist[direct].alist =
3858 access_list_lookup (afi, filter->dlist[direct].name);
3859 else
3860 filter->dlist[direct].alist = NULL;
3861 }
3862 }
3863 }
paul1eb8ef22005-04-07 07:30:20 +00003864 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003865 {
3866 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3867 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3868 {
3869 filter = &group->conf->filter[afi][safi];
3870
3871 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3872 {
3873 if (filter->dlist[direct].name)
3874 filter->dlist[direct].alist =
3875 access_list_lookup (afi, filter->dlist[direct].name);
3876 else
3877 filter->dlist[direct].alist = NULL;
3878 }
3879 }
3880 }
3881 }
3882}
David Lamparter6b0655a2014-06-04 06:53:35 +02003883
paul718e3742002-12-13 20:15:29 +00003884/* Set prefix list to the peer. */
3885int
3886peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003887 const char *name)
paul718e3742002-12-13 20:15:29 +00003888{
3889 struct bgp_filter *filter;
3890 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003891 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003892
3893 if (! peer->afc[afi][safi])
3894 return BGP_ERR_PEER_INACTIVE;
3895
3896 if (direct != FILTER_IN && direct != FILTER_OUT)
3897 return BGP_ERR_INVALID_VALUE;
3898
3899 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3900 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3901
3902 filter = &peer->filter[afi][safi];
3903
3904 if (filter->dlist[direct].name)
3905 return BGP_ERR_PEER_FILTER_CONFLICT;
3906
3907 if (filter->plist[direct].name)
3908 free (filter->plist[direct].name);
3909 filter->plist[direct].name = strdup (name);
3910 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3911
3912 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3913 return 0;
3914
3915 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003916 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003917 {
3918 filter = &peer->filter[afi][safi];
3919
3920 if (! peer->af_group[afi][safi])
3921 continue;
3922
3923 if (filter->plist[direct].name)
3924 free (filter->plist[direct].name);
3925 filter->plist[direct].name = strdup (name);
3926 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3927 }
3928 return 0;
3929}
3930
3931int
3932peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3933{
3934 struct bgp_filter *filter;
3935 struct bgp_filter *gfilter;
3936 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003937 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003938
3939 if (! peer->afc[afi][safi])
3940 return BGP_ERR_PEER_INACTIVE;
3941
3942 if (direct != FILTER_IN && direct != FILTER_OUT)
3943 return BGP_ERR_INVALID_VALUE;
3944
3945 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3946 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3947
3948 filter = &peer->filter[afi][safi];
3949
3950 /* apply peer-group filter */
3951 if (peer->af_group[afi][safi])
3952 {
3953 gfilter = &peer->group->conf->filter[afi][safi];
3954
3955 if (gfilter->plist[direct].name)
3956 {
3957 if (filter->plist[direct].name)
3958 free (filter->plist[direct].name);
3959 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3960 filter->plist[direct].plist = gfilter->plist[direct].plist;
3961 return 0;
3962 }
3963 }
3964
3965 if (filter->plist[direct].name)
3966 free (filter->plist[direct].name);
3967 filter->plist[direct].name = NULL;
3968 filter->plist[direct].plist = NULL;
3969
3970 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3971 return 0;
3972
3973 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003974 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003975 {
3976 filter = &peer->filter[afi][safi];
3977
3978 if (! peer->af_group[afi][safi])
3979 continue;
3980
3981 if (filter->plist[direct].name)
3982 free (filter->plist[direct].name);
3983 filter->plist[direct].name = NULL;
3984 filter->plist[direct].plist = NULL;
3985 }
3986
3987 return 0;
3988}
3989
3990/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003991static void
paul718e3742002-12-13 20:15:29 +00003992peer_prefix_list_update (struct prefix_list *plist)
3993{
paul1eb8ef22005-04-07 07:30:20 +00003994 struct listnode *mnode, *mnnode;
3995 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003996 struct bgp *bgp;
3997 struct peer *peer;
3998 struct peer_group *group;
3999 struct bgp_filter *filter;
4000 afi_t afi;
4001 safi_t safi;
4002 int direct;
4003
paul1eb8ef22005-04-07 07:30:20 +00004004 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004005 {
paul1eb8ef22005-04-07 07:30:20 +00004006 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004007 {
4008 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4009 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4010 {
4011 filter = &peer->filter[afi][safi];
4012
4013 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4014 {
4015 if (filter->plist[direct].name)
4016 filter->plist[direct].plist =
4017 prefix_list_lookup (afi, filter->plist[direct].name);
4018 else
4019 filter->plist[direct].plist = NULL;
4020 }
4021 }
4022 }
paul1eb8ef22005-04-07 07:30:20 +00004023 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004024 {
4025 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4026 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4027 {
4028 filter = &group->conf->filter[afi][safi];
4029
4030 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4031 {
4032 if (filter->plist[direct].name)
4033 filter->plist[direct].plist =
4034 prefix_list_lookup (afi, filter->plist[direct].name);
4035 else
4036 filter->plist[direct].plist = NULL;
4037 }
4038 }
4039 }
4040 }
4041}
David Lamparter6b0655a2014-06-04 06:53:35 +02004042
paul718e3742002-12-13 20:15:29 +00004043int
4044peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004045 const char *name)
paul718e3742002-12-13 20:15:29 +00004046{
4047 struct bgp_filter *filter;
4048 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004049 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004050
4051 if (! peer->afc[afi][safi])
4052 return BGP_ERR_PEER_INACTIVE;
4053
4054 if (direct != FILTER_IN && direct != FILTER_OUT)
4055 return BGP_ERR_INVALID_VALUE;
4056
4057 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4058 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4059
4060 filter = &peer->filter[afi][safi];
4061
4062 if (filter->aslist[direct].name)
4063 free (filter->aslist[direct].name);
4064 filter->aslist[direct].name = strdup (name);
4065 filter->aslist[direct].aslist = as_list_lookup (name);
4066
4067 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4068 return 0;
4069
4070 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004071 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004072 {
4073 filter = &peer->filter[afi][safi];
4074
4075 if (! peer->af_group[afi][safi])
4076 continue;
4077
4078 if (filter->aslist[direct].name)
4079 free (filter->aslist[direct].name);
4080 filter->aslist[direct].name = strdup (name);
4081 filter->aslist[direct].aslist = as_list_lookup (name);
4082 }
4083 return 0;
4084}
4085
4086int
4087peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4088{
4089 struct bgp_filter *filter;
4090 struct bgp_filter *gfilter;
4091 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004092 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004093
4094 if (! peer->afc[afi][safi])
4095 return BGP_ERR_PEER_INACTIVE;
4096
hassob5f29602005-05-25 21:00:28 +00004097 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004098 return BGP_ERR_INVALID_VALUE;
4099
hassob5f29602005-05-25 21:00:28 +00004100 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004101 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4102
4103 filter = &peer->filter[afi][safi];
4104
4105 /* apply peer-group filter */
4106 if (peer->af_group[afi][safi])
4107 {
4108 gfilter = &peer->group->conf->filter[afi][safi];
4109
4110 if (gfilter->aslist[direct].name)
4111 {
4112 if (filter->aslist[direct].name)
4113 free (filter->aslist[direct].name);
4114 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4115 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4116 return 0;
4117 }
4118 }
4119
4120 if (filter->aslist[direct].name)
4121 free (filter->aslist[direct].name);
4122 filter->aslist[direct].name = NULL;
4123 filter->aslist[direct].aslist = NULL;
4124
4125 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4126 return 0;
4127
4128 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004129 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004130 {
4131 filter = &peer->filter[afi][safi];
4132
4133 if (! peer->af_group[afi][safi])
4134 continue;
4135
4136 if (filter->aslist[direct].name)
4137 free (filter->aslist[direct].name);
4138 filter->aslist[direct].name = NULL;
4139 filter->aslist[direct].aslist = NULL;
4140 }
4141
4142 return 0;
4143}
4144
paul94f2b392005-06-28 12:44:16 +00004145static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004146peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004147{
4148 afi_t afi;
4149 safi_t safi;
4150 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004151 struct listnode *mnode, *mnnode;
4152 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004153 struct bgp *bgp;
4154 struct peer *peer;
4155 struct peer_group *group;
4156 struct bgp_filter *filter;
4157
paul1eb8ef22005-04-07 07:30:20 +00004158 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004159 {
paul1eb8ef22005-04-07 07:30:20 +00004160 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004161 {
4162 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4163 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4164 {
4165 filter = &peer->filter[afi][safi];
4166
4167 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4168 {
4169 if (filter->aslist[direct].name)
4170 filter->aslist[direct].aslist =
4171 as_list_lookup (filter->aslist[direct].name);
4172 else
4173 filter->aslist[direct].aslist = NULL;
4174 }
4175 }
4176 }
paul1eb8ef22005-04-07 07:30:20 +00004177 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004178 {
4179 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4180 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4181 {
4182 filter = &group->conf->filter[afi][safi];
4183
4184 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4185 {
4186 if (filter->aslist[direct].name)
4187 filter->aslist[direct].aslist =
4188 as_list_lookup (filter->aslist[direct].name);
4189 else
4190 filter->aslist[direct].aslist = NULL;
4191 }
4192 }
4193 }
4194 }
4195}
David Lamparter6b0655a2014-06-04 06:53:35 +02004196
paul718e3742002-12-13 20:15:29 +00004197/* Set route-map to the peer. */
4198int
4199peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004200 const char *name)
paul718e3742002-12-13 20:15:29 +00004201{
4202 struct bgp_filter *filter;
4203 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004204 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004205
4206 if (! peer->afc[afi][safi])
4207 return BGP_ERR_PEER_INACTIVE;
4208
paulfee0f4c2004-09-13 05:12:46 +00004209 if (direct != RMAP_IN && direct != RMAP_OUT &&
4210 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004211 return BGP_ERR_INVALID_VALUE;
4212
paulfee0f4c2004-09-13 05:12:46 +00004213 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4214 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004215 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4216
4217 filter = &peer->filter[afi][safi];
4218
4219 if (filter->map[direct].name)
4220 free (filter->map[direct].name);
4221
4222 filter->map[direct].name = strdup (name);
4223 filter->map[direct].map = route_map_lookup_by_name (name);
4224
4225 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4226 return 0;
4227
4228 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004229 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004230 {
4231 filter = &peer->filter[afi][safi];
4232
4233 if (! peer->af_group[afi][safi])
4234 continue;
4235
4236 if (filter->map[direct].name)
4237 free (filter->map[direct].name);
4238 filter->map[direct].name = strdup (name);
4239 filter->map[direct].map = route_map_lookup_by_name (name);
4240 }
4241 return 0;
4242}
4243
4244/* Unset route-map from the peer. */
4245int
4246peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4247{
4248 struct bgp_filter *filter;
4249 struct bgp_filter *gfilter;
4250 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004251 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004252
4253 if (! peer->afc[afi][safi])
4254 return BGP_ERR_PEER_INACTIVE;
4255
hassob5f29602005-05-25 21:00:28 +00004256 if (direct != RMAP_IN && direct != RMAP_OUT &&
4257 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004258 return BGP_ERR_INVALID_VALUE;
4259
hassob5f29602005-05-25 21:00:28 +00004260 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4261 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004262 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4263
4264 filter = &peer->filter[afi][safi];
4265
4266 /* apply peer-group filter */
4267 if (peer->af_group[afi][safi])
4268 {
4269 gfilter = &peer->group->conf->filter[afi][safi];
4270
4271 if (gfilter->map[direct].name)
4272 {
4273 if (filter->map[direct].name)
4274 free (filter->map[direct].name);
4275 filter->map[direct].name = strdup (gfilter->map[direct].name);
4276 filter->map[direct].map = gfilter->map[direct].map;
4277 return 0;
4278 }
4279 }
4280
4281 if (filter->map[direct].name)
4282 free (filter->map[direct].name);
4283 filter->map[direct].name = NULL;
4284 filter->map[direct].map = NULL;
4285
4286 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4287 return 0;
4288
4289 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004290 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004291 {
4292 filter = &peer->filter[afi][safi];
4293
4294 if (! peer->af_group[afi][safi])
4295 continue;
4296
4297 if (filter->map[direct].name)
4298 free (filter->map[direct].name);
4299 filter->map[direct].name = NULL;
4300 filter->map[direct].map = NULL;
4301 }
4302 return 0;
4303}
David Lamparter6b0655a2014-06-04 06:53:35 +02004304
paul718e3742002-12-13 20:15:29 +00004305/* Set unsuppress-map to the peer. */
4306int
paulfd79ac92004-10-13 05:06:08 +00004307peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4308 const char *name)
paul718e3742002-12-13 20:15:29 +00004309{
4310 struct bgp_filter *filter;
4311 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004312 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004313
4314 if (! peer->afc[afi][safi])
4315 return BGP_ERR_PEER_INACTIVE;
4316
4317 if (peer_is_group_member (peer, afi, safi))
4318 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4319
4320 filter = &peer->filter[afi][safi];
4321
4322 if (filter->usmap.name)
4323 free (filter->usmap.name);
4324
4325 filter->usmap.name = strdup (name);
4326 filter->usmap.map = route_map_lookup_by_name (name);
4327
4328 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4329 return 0;
4330
4331 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004332 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004333 {
4334 filter = &peer->filter[afi][safi];
4335
4336 if (! peer->af_group[afi][safi])
4337 continue;
4338
4339 if (filter->usmap.name)
4340 free (filter->usmap.name);
4341 filter->usmap.name = strdup (name);
4342 filter->usmap.map = route_map_lookup_by_name (name);
4343 }
4344 return 0;
4345}
4346
4347/* Unset route-map from the peer. */
4348int
4349peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4350{
4351 struct bgp_filter *filter;
4352 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004353 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004354
4355 if (! peer->afc[afi][safi])
4356 return BGP_ERR_PEER_INACTIVE;
4357
4358 if (peer_is_group_member (peer, afi, safi))
4359 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4360
4361 filter = &peer->filter[afi][safi];
4362
4363 if (filter->usmap.name)
4364 free (filter->usmap.name);
4365 filter->usmap.name = NULL;
4366 filter->usmap.map = NULL;
4367
4368 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4369 return 0;
4370
4371 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004372 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004373 {
4374 filter = &peer->filter[afi][safi];
4375
4376 if (! peer->af_group[afi][safi])
4377 continue;
4378
4379 if (filter->usmap.name)
4380 free (filter->usmap.name);
4381 filter->usmap.name = NULL;
4382 filter->usmap.map = NULL;
4383 }
4384 return 0;
4385}
David Lamparter6b0655a2014-06-04 06:53:35 +02004386
paul718e3742002-12-13 20:15:29 +00004387int
4388peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004389 u_int32_t max, u_char threshold,
4390 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004391{
4392 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004393 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004394
4395 if (! peer->afc[afi][safi])
4396 return BGP_ERR_PEER_INACTIVE;
4397
4398 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4399 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004400 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004401 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004402 if (warning)
4403 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4404 else
4405 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4406
4407 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4408 return 0;
4409
4410 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004411 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004412 {
4413 if (! peer->af_group[afi][safi])
4414 continue;
4415
4416 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4417 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004418 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004419 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004420 if (warning)
4421 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4422 else
4423 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4424 }
4425 return 0;
4426}
4427
4428int
4429peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4430{
4431 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004432 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004433
4434 if (! peer->afc[afi][safi])
4435 return BGP_ERR_PEER_INACTIVE;
4436
4437 /* apply peer-group config */
4438 if (peer->af_group[afi][safi])
4439 {
4440 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4441 PEER_FLAG_MAX_PREFIX))
4442 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4443 else
4444 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4445
4446 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4447 PEER_FLAG_MAX_PREFIX_WARNING))
4448 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4449 else
4450 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4451
4452 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004453 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004454 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004455 return 0;
4456 }
4457
4458 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4459 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4460 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004461 peer->pmax_threshold[afi][safi] = 0;
4462 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004463
4464 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4465 return 0;
4466
4467 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004468 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004469 {
4470 if (! peer->af_group[afi][safi])
4471 continue;
4472
4473 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4474 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4475 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004476 peer->pmax_threshold[afi][safi] = 0;
4477 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004478 }
4479 return 0;
4480}
David Lamparter5f9adb52014-05-19 23:15:02 +02004481
4482static int is_ebgp_multihop_configured (struct peer *peer)
4483{
4484 struct peer_group *group;
4485 struct listnode *node, *nnode;
4486 struct peer *peer1;
4487
4488 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4489 {
4490 group = peer->group;
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004491 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4492 (group->conf->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004493 return 1;
4494
4495 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4496 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004497 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
4498 (peer1->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004499 return 1;
4500 }
4501 }
4502 else
4503 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004504 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4505 (peer->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004506 return 1;
4507 }
4508 return 0;
4509}
4510
Nick Hilliardfa411a22011-03-23 15:33:17 +00004511/* Set # of hops between us and BGP peer. */
4512int
4513peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4514{
4515 struct peer_group *group;
4516 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004517 int ret;
4518
4519 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4520
Nick Hilliardfa411a22011-03-23 15:33:17 +00004521 /* We cannot configure ttl-security hops when ebgp-multihop is already
4522 set. For non peer-groups, the check is simple. For peer-groups, it's
4523 slightly messy, because we need to check both the peer-group structure
4524 and all peer-group members for any trace of ebgp-multihop configuration
4525 before actually applying the ttl-security rules. Cisco really made a
4526 mess of this configuration parameter, and OpenBGPD got it right.
4527 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004528
David Lamparter5f9adb52014-05-19 23:15:02 +02004529 if (peer->gtsm_hops == 0)
4530 {
4531 if (is_ebgp_multihop_configured (peer))
4532 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004533
David Lamparter5f9adb52014-05-19 23:15:02 +02004534 /* specify MAXTTL on outgoing packets */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004535 /* Routine handles iBGP peers correctly */
David Lamparter5f9adb52014-05-19 23:15:02 +02004536 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4537 if (ret != 0)
4538 return ret;
4539 }
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004540
Nick Hilliardfa411a22011-03-23 15:33:17 +00004541 peer->gtsm_hops = gtsm_hops;
4542
Nick Hilliardfa411a22011-03-23 15:33:17 +00004543 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4544 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004545 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004546 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4547 }
4548 else
4549 {
4550 group = peer->group;
4551 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4552 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004553 peer->gtsm_hops = group->conf->gtsm_hops;
4554
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004555 /* Change setting of existing peer
4556 * established then change value (may break connectivity)
4557 * not established yet (teardown session and restart)
4558 * no session then do nothing (will get handled by next connection)
4559 */
4560 if (peer->status == Established)
4561 {
4562 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4563 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4564 MAXTTL + 1 - peer->gtsm_hops);
4565 }
4566 else if (peer->status < Established)
4567 {
4568 if (BGP_DEBUG (events, EVENTS))
4569 zlog_debug ("%s Min-ttl changed", peer->host);
4570 BGP_EVENT_ADD (peer, BGP_Stop);
4571 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004572 }
4573 }
4574
4575 return 0;
4576}
4577
4578int
4579peer_ttl_security_hops_unset (struct peer *peer)
4580{
4581 struct peer_group *group;
4582 struct listnode *node, *nnode;
4583 struct peer *opeer;
4584
4585 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4586
Nick Hilliardfa411a22011-03-23 15:33:17 +00004587 /* if a peer-group member, then reset to peer-group default rather than 0 */
4588 if (peer_group_active (peer))
4589 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4590 else
4591 peer->gtsm_hops = 0;
4592
4593 opeer = peer;
4594 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4595 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004596 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004597 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4598 }
4599 else
4600 {
4601 group = peer->group;
4602 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4603 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004604 peer->gtsm_hops = 0;
4605
4606 if (peer->fd >= 0)
4607 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4608 }
4609 }
4610
4611 return peer_ebgp_multihop_unset (opeer);
4612}
David Lamparter6b0655a2014-06-04 06:53:35 +02004613
paul718e3742002-12-13 20:15:29 +00004614int
4615peer_clear (struct peer *peer)
4616{
4617 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4618 {
hasso0a486e52005-02-01 20:57:17 +00004619 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4620 {
4621 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4622 if (peer->t_pmax_restart)
4623 {
4624 BGP_TIMER_OFF (peer->t_pmax_restart);
4625 if (BGP_DEBUG (events, EVENTS))
4626 zlog_debug ("%s Maximum-prefix restart timer canceled",
4627 peer->host);
4628 }
4629 BGP_EVENT_ADD (peer, BGP_Start);
4630 return 0;
4631 }
4632
paul718e3742002-12-13 20:15:29 +00004633 peer->v_start = BGP_INIT_START_TIMER;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00004634 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00004635 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4636 BGP_NOTIFY_CEASE_ADMIN_RESET);
4637 else
4638 BGP_EVENT_ADD (peer, BGP_Stop);
4639 }
4640 return 0;
4641}
4642
4643int
4644peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4645 enum bgp_clear_type stype)
4646{
4647 if (peer->status != Established)
4648 return 0;
4649
4650 if (! peer->afc[afi][safi])
4651 return BGP_ERR_AF_UNCONFIGURED;
4652
Timo Teräs5a2a1ec2015-10-22 11:35:18 +03004653 peer->rtt = sockopt_tcp_rtt (peer->fd);
4654
paulfee0f4c2004-09-13 05:12:46 +00004655 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4656 {
4657 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4658 return 0;
4659 bgp_check_local_routes_rsclient (peer, afi, safi);
4660 bgp_soft_reconfig_rsclient (peer, afi, safi);
4661 }
4662
paul718e3742002-12-13 20:15:29 +00004663 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4664 bgp_announce_route (peer, afi, safi);
4665
4666 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4667 {
4668 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4669 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4670 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4671 {
4672 struct bgp_filter *filter = &peer->filter[afi][safi];
4673 u_char prefix_type;
4674
4675 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4676 prefix_type = ORF_TYPE_PREFIX;
4677 else
4678 prefix_type = ORF_TYPE_PREFIX_OLD;
4679
4680 if (filter->plist[FILTER_IN].plist)
4681 {
4682 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4683 bgp_route_refresh_send (peer, afi, safi,
4684 prefix_type, REFRESH_DEFER, 1);
4685 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4686 REFRESH_IMMEDIATE, 0);
4687 }
4688 else
4689 {
4690 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4691 bgp_route_refresh_send (peer, afi, safi,
4692 prefix_type, REFRESH_IMMEDIATE, 1);
4693 else
4694 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4695 }
4696 return 0;
4697 }
4698 }
4699
4700 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4701 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4702 {
4703 /* If neighbor has soft reconfiguration inbound flag.
4704 Use Adj-RIB-In database. */
4705 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4706 bgp_soft_reconfig_in (peer, afi, safi);
4707 else
4708 {
4709 /* If neighbor has route refresh capability, send route refresh
4710 message to the peer. */
4711 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4712 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4713 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4714 else
4715 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4716 }
4717 }
4718 return 0;
4719}
David Lamparter6b0655a2014-06-04 06:53:35 +02004720
paulfd79ac92004-10-13 05:06:08 +00004721/* Display peer uptime.*/
4722/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004723char *
4724peer_uptime (time_t uptime2, char *buf, size_t len)
4725{
4726 time_t uptime1;
4727 struct tm *tm;
4728
4729 /* Check buffer length. */
4730 if (len < BGP_UPTIME_LEN)
4731 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004732 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004733 /* XXX: should return status instead of buf... */
4734 snprintf (buf, len, "<error> ");
4735 return buf;
paul718e3742002-12-13 20:15:29 +00004736 }
4737
4738 /* If there is no connection has been done before print `never'. */
4739 if (uptime2 == 0)
4740 {
4741 snprintf (buf, len, "never ");
4742 return buf;
4743 }
4744
4745 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004746 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004747 uptime1 -= uptime2;
4748 tm = gmtime (&uptime1);
Paul Jakma84c38402015-05-26 15:19:38 +01004749
paul718e3742002-12-13 20:15:29 +00004750 /* Making formatted timer strings. */
4751#define ONE_DAY_SECOND 60*60*24
Paul Jakma84c38402015-05-26 15:19:38 +01004752#define ONE_WEEK_SECOND ONE_DAY_SECOND*7
4753#define ONE_YEAR_SECOND ONE_DAY_SECOND*365
paul718e3742002-12-13 20:15:29 +00004754
4755 if (uptime1 < ONE_DAY_SECOND)
4756 snprintf (buf, len, "%02d:%02d:%02d",
4757 tm->tm_hour, tm->tm_min, tm->tm_sec);
4758 else if (uptime1 < ONE_WEEK_SECOND)
4759 snprintf (buf, len, "%dd%02dh%02dm",
4760 tm->tm_yday, tm->tm_hour, tm->tm_min);
Paul Jakma84c38402015-05-26 15:19:38 +01004761 else if (uptime1 < ONE_YEAR_SECOND)
paul718e3742002-12-13 20:15:29 +00004762 snprintf (buf, len, "%02dw%dd%02dh",
4763 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
Paul Jakma84c38402015-05-26 15:19:38 +01004764 else
4765 snprintf (buf, len, "%02dy%02dw%dd",
4766 tm->tm_year - 70, tm->tm_yday/7,
4767 tm->tm_yday - ((tm->tm_yday/7) * 7));
paul718e3742002-12-13 20:15:29 +00004768 return buf;
4769}
David Lamparter6b0655a2014-06-04 06:53:35 +02004770
paul94f2b392005-06-28 12:44:16 +00004771static void
paul718e3742002-12-13 20:15:29 +00004772bgp_config_write_filter (struct vty *vty, struct peer *peer,
4773 afi_t afi, safi_t safi)
4774{
4775 struct bgp_filter *filter;
4776 struct bgp_filter *gfilter = NULL;
4777 char *addr;
4778 int in = FILTER_IN;
4779 int out = FILTER_OUT;
4780
4781 addr = peer->host;
4782 filter = &peer->filter[afi][safi];
4783 if (peer->af_group[afi][safi])
4784 gfilter = &peer->group->conf->filter[afi][safi];
4785
4786 /* distribute-list. */
4787 if (filter->dlist[in].name)
4788 if (! gfilter || ! gfilter->dlist[in].name
4789 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4790 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4791 filter->dlist[in].name, VTY_NEWLINE);
4792 if (filter->dlist[out].name && ! gfilter)
4793 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4794 filter->dlist[out].name, VTY_NEWLINE);
4795
4796 /* prefix-list. */
4797 if (filter->plist[in].name)
4798 if (! gfilter || ! gfilter->plist[in].name
4799 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4800 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4801 filter->plist[in].name, VTY_NEWLINE);
4802 if (filter->plist[out].name && ! gfilter)
4803 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4804 filter->plist[out].name, VTY_NEWLINE);
4805
4806 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004807 if (filter->map[RMAP_IN].name)
4808 if (! gfilter || ! gfilter->map[RMAP_IN].name
4809 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004810 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004811 filter->map[RMAP_IN].name, VTY_NEWLINE);
4812 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004813 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004814 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4815 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4816 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4817 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4818 if (filter->map[RMAP_EXPORT].name)
4819 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4820 || strcmp (filter->map[RMAP_EXPORT].name,
4821 gfilter->map[RMAP_EXPORT].name) != 0)
4822 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4823 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004824
4825 /* unsuppress-map */
4826 if (filter->usmap.name && ! gfilter)
4827 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4828 filter->usmap.name, VTY_NEWLINE);
4829
4830 /* filter-list. */
4831 if (filter->aslist[in].name)
4832 if (! gfilter || ! gfilter->aslist[in].name
4833 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4834 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4835 filter->aslist[in].name, VTY_NEWLINE);
4836 if (filter->aslist[out].name && ! gfilter)
4837 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4838 filter->aslist[out].name, VTY_NEWLINE);
4839}
4840
4841/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004842static void
paul718e3742002-12-13 20:15:29 +00004843bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4844 struct peer *peer, afi_t afi, safi_t safi)
4845{
paul718e3742002-12-13 20:15:29 +00004846 struct peer *g_peer = NULL;
4847 char buf[SU_ADDRSTRLEN];
4848 char *addr;
4849
paul718e3742002-12-13 20:15:29 +00004850 addr = peer->host;
4851 if (peer_group_active (peer))
4852 g_peer = peer->group->conf;
4853
4854 /************************************
4855 ****** Global to the neighbor ******
4856 ************************************/
4857 if (afi == AFI_IP && safi == SAFI_UNICAST)
4858 {
4859 /* remote-as. */
4860 if (! peer_group_active (peer))
4861 {
4862 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4863 vty_out (vty, " neighbor %s peer-group%s", addr,
4864 VTY_NEWLINE);
4865 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004866 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004867 VTY_NEWLINE);
4868 }
4869 else
4870 {
4871 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004872 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004873 VTY_NEWLINE);
4874 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4875 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4876 peer->group->name, VTY_NEWLINE);
4877 }
4878
4879 /* local-as. */
4880 if (peer->change_local_as)
4881 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00004882 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004883 peer->change_local_as,
4884 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00004885 " no-prepend" : "",
4886 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
4887 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004888
4889 /* Description. */
4890 if (peer->desc)
4891 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4892 VTY_NEWLINE);
4893
4894 /* Shutdown. */
4895 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4896 if (! peer_group_active (peer) ||
4897 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4898 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4899
Paul Jakma0df7c912008-07-21 21:02:49 +00004900 /* Password. */
4901 if (peer->password)
4902 if (!peer_group_active (peer)
4903 || ! g_peer->password
4904 || strcmp (peer->password, g_peer->password) != 0)
4905 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4906 VTY_NEWLINE);
4907
paul718e3742002-12-13 20:15:29 +00004908 /* BGP port. */
4909 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004910 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004911 VTY_NEWLINE);
4912
4913 /* Local interface name. */
4914 if (peer->ifname)
4915 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4916 VTY_NEWLINE);
4917
4918 /* Passive. */
4919 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4920 if (! peer_group_active (peer) ||
4921 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4922 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4923
4924 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004925 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00004926 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00004927 if (! peer_group_active (peer) ||
4928 g_peer->ttl != peer->ttl)
4929 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4930 VTY_NEWLINE);
4931
Nick Hilliardfa411a22011-03-23 15:33:17 +00004932 /* ttl-security hops */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004933 if (peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004934 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004935 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00004936 peer->gtsm_hops, VTY_NEWLINE);
4937
hasso6ffd2072005-02-02 14:50:11 +00004938 /* disable-connected-check. */
4939 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004940 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004941 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4942 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004943
4944 /* Update-source. */
4945 if (peer->update_if)
4946 if (! peer_group_active (peer) || ! g_peer->update_if
4947 || strcmp (g_peer->update_if, peer->update_if) != 0)
4948 vty_out (vty, " neighbor %s update-source %s%s", addr,
4949 peer->update_if, VTY_NEWLINE);
4950 if (peer->update_source)
4951 if (! peer_group_active (peer) || ! g_peer->update_source
4952 || sockunion_cmp (g_peer->update_source,
4953 peer->update_source) != 0)
4954 vty_out (vty, " neighbor %s update-source %s%s", addr,
4955 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4956 VTY_NEWLINE);
4957
paul718e3742002-12-13 20:15:29 +00004958 /* advertisement-interval */
4959 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4960 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4961 addr, peer->v_routeadv, VTY_NEWLINE);
4962
4963 /* timers. */
4964 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4965 && ! peer_group_active (peer))
4966 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4967 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4968
4969 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4970 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4971 peer->connect, VTY_NEWLINE);
4972
4973 /* Default weight. */
4974 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4975 if (! peer_group_active (peer) ||
4976 g_peer->weight != peer->weight)
4977 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4978 VTY_NEWLINE);
4979
paul718e3742002-12-13 20:15:29 +00004980 /* Dynamic capability. */
4981 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4982 if (! peer_group_active (peer) ||
4983 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4984 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4985 VTY_NEWLINE);
4986
4987 /* dont capability negotiation. */
4988 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4989 if (! peer_group_active (peer) ||
4990 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4991 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4992 VTY_NEWLINE);
4993
4994 /* override capability negotiation. */
4995 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4996 if (! peer_group_active (peer) ||
4997 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4998 vty_out (vty, " neighbor %s override-capability%s", addr,
4999 VTY_NEWLINE);
5000
5001 /* strict capability negotiation. */
5002 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5003 if (! peer_group_active (peer) ||
5004 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5005 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
5006 VTY_NEWLINE);
5007
Christian Franke15c71342012-11-19 11:17:31 +00005008 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
paul718e3742002-12-13 20:15:29 +00005009 {
5010 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5011 {
5012 if (peer->afc[AFI_IP][SAFI_UNICAST])
5013 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5014 }
5015 else
5016 {
5017 if (! peer->afc[AFI_IP][SAFI_UNICAST])
5018 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
5019 }
5020 }
5021 }
5022
5023
5024 /************************************
5025 ****** Per AF to the neighbor ******
5026 ************************************/
5027
5028 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
5029 {
5030 if (peer->af_group[afi][safi])
5031 vty_out (vty, " neighbor %s peer-group %s%s", addr,
5032 peer->group->name, VTY_NEWLINE);
5033 else
5034 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5035 }
5036
5037 /* ORF capability. */
5038 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5039 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5040 if (! peer->af_group[afi][safi])
5041 {
5042 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
5043
5044 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5045 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5046 vty_out (vty, " both");
5047 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
5048 vty_out (vty, " send");
5049 else
5050 vty_out (vty, " receive");
5051 vty_out (vty, "%s", VTY_NEWLINE);
5052 }
5053
5054 /* Route reflector client. */
5055 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
5056 && ! peer->af_group[afi][safi])
5057 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
5058 VTY_NEWLINE);
5059
5060 /* Nexthop self. */
5061 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
5062 && ! peer->af_group[afi][safi])
Timo Teräs9e7a53c2014-04-24 10:22:37 +03005063 vty_out (vty, " neighbor %s next-hop-self%s%s", addr,
5064 peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ?
5065 " all" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005066
5067 /* Remove private AS. */
5068 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
5069 && ! peer->af_group[afi][safi])
5070 vty_out (vty, " neighbor %s remove-private-AS%s",
5071 addr, VTY_NEWLINE);
5072
5073 /* send-community print. */
5074 if (! peer->af_group[afi][safi])
5075 {
5076 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5077 {
5078 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5079 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5080 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
5081 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5082 vty_out (vty, " neighbor %s send-community extended%s",
5083 addr, VTY_NEWLINE);
5084 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5085 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
5086 }
5087 else
5088 {
5089 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5090 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5091 vty_out (vty, " no neighbor %s send-community both%s",
5092 addr, VTY_NEWLINE);
5093 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5094 vty_out (vty, " no neighbor %s send-community extended%s",
5095 addr, VTY_NEWLINE);
5096 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5097 vty_out (vty, " no neighbor %s send-community%s",
5098 addr, VTY_NEWLINE);
5099 }
5100 }
5101
5102 /* Default information */
5103 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5104 && ! peer->af_group[afi][safi])
5105 {
5106 vty_out (vty, " neighbor %s default-originate", addr);
5107 if (peer->default_rmap[afi][safi].name)
5108 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5109 vty_out (vty, "%s", VTY_NEWLINE);
5110 }
5111
5112 /* Soft reconfiguration inbound. */
5113 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5114 if (! peer->af_group[afi][safi] ||
5115 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5116 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5117 VTY_NEWLINE);
5118
5119 /* maximum-prefix. */
5120 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5121 if (! peer->af_group[afi][safi]
5122 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005123 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005124 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5125 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005126 {
hasso0a486e52005-02-01 20:57:17 +00005127 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5128 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5129 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5130 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5131 vty_out (vty, " warning-only");
5132 if (peer->pmax_restart[afi][safi])
5133 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5134 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005135 }
paul718e3742002-12-13 20:15:29 +00005136
5137 /* Route server client. */
5138 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5139 && ! peer->af_group[afi][safi])
5140 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5141
Dylan Hall3cf12882011-10-27 15:28:17 +04005142 /* Nexthop-local unchanged. */
5143 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5144 && ! peer->af_group[afi][safi])
5145 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5146
paul718e3742002-12-13 20:15:29 +00005147 /* Allow AS in. */
5148 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5149 if (! peer_group_active (peer)
5150 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5151 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5152 {
5153 if (peer->allowas_in[afi][safi] == 3)
5154 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5155 else
5156 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5157 peer->allowas_in[afi][safi], VTY_NEWLINE);
5158 }
5159
5160 /* Filter. */
5161 bgp_config_write_filter (vty, peer, afi, safi);
5162
5163 /* atribute-unchanged. */
5164 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5165 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5166 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5167 && ! peer->af_group[afi][safi])
5168 {
5169 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5170 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5171 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5172 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5173 else
5174 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5175 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5176 " as-path" : "",
5177 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5178 " next-hop" : "",
5179 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5180 " med" : "", VTY_NEWLINE);
5181 }
5182}
5183
5184/* Display "address-family" configuration header. */
5185void
5186bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5187 int *write)
5188{
5189 if (*write)
5190 return;
5191
5192 if (afi == AFI_IP && safi == SAFI_UNICAST)
5193 return;
5194
5195 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5196
5197 if (afi == AFI_IP)
5198 {
5199 if (safi == SAFI_MULTICAST)
5200 vty_out (vty, "ipv4 multicast");
5201 else if (safi == SAFI_MPLS_VPN)
5202 vty_out (vty, "vpnv4 unicast");
5203 }
5204 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005205 {
5206 vty_out (vty, "ipv6");
5207
5208 if (safi == SAFI_MULTICAST)
5209 vty_out (vty, " multicast");
5210 }
paul718e3742002-12-13 20:15:29 +00005211
5212 vty_out (vty, "%s", VTY_NEWLINE);
5213
5214 *write = 1;
5215}
5216
5217/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005218static int
paul718e3742002-12-13 20:15:29 +00005219bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5220 safi_t safi)
5221{
5222 int write = 0;
5223 struct peer *peer;
5224 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005225 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005226
5227 bgp_config_write_network (vty, bgp, afi, safi, &write);
5228
5229 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5230
paul1eb8ef22005-04-07 07:30:20 +00005231 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005232 {
5233 if (group->conf->afc[afi][safi])
5234 {
5235 bgp_config_write_family_header (vty, afi, safi, &write);
5236 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5237 }
5238 }
paul1eb8ef22005-04-07 07:30:20 +00005239 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005240 {
5241 if (peer->afc[afi][safi])
5242 {
5243 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5244 {
5245 bgp_config_write_family_header (vty, afi, safi, &write);
5246 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5247 }
5248 }
5249 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005250
5251 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5252
paul718e3742002-12-13 20:15:29 +00005253 if (write)
5254 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5255
5256 return write;
5257}
5258
5259int
5260bgp_config_write (struct vty *vty)
5261{
5262 int write = 0;
5263 struct bgp *bgp;
5264 struct peer_group *group;
5265 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005266 struct listnode *node, *nnode;
5267 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005268
5269 /* BGP Multiple instance. */
5270 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5271 {
5272 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5273 write++;
5274 }
5275
5276 /* BGP Config type. */
5277 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5278 {
5279 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5280 write++;
5281 }
5282
5283 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005284 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005285 {
5286 if (write)
5287 vty_out (vty, "!%s", VTY_NEWLINE);
5288
5289 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005290 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005291
5292 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5293 {
5294 if (bgp->name)
5295 vty_out (vty, " view %s", bgp->name);
5296 }
5297 vty_out (vty, "%s", VTY_NEWLINE);
5298
5299 /* No Synchronization */
5300 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5301 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5302
5303 /* BGP fast-external-failover. */
5304 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5305 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5306
5307 /* BGP router ID. */
5308 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5309 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5310 VTY_NEWLINE);
5311
paul848973c2003-08-13 00:32:49 +00005312 /* BGP log-neighbor-changes. */
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07005313 if (!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5314 vty_out (vty, " no bgp log-neighbor-changes%s", VTY_NEWLINE);
paul848973c2003-08-13 00:32:49 +00005315
paul718e3742002-12-13 20:15:29 +00005316 /* BGP configuration. */
5317 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5318 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5319
5320 /* BGP default ipv4-unicast. */
5321 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5322 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5323
5324 /* BGP default local-preference. */
5325 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5326 vty_out (vty, " bgp default local-preference %d%s",
5327 bgp->default_local_pref, VTY_NEWLINE);
5328
5329 /* BGP client-to-client reflection. */
5330 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5331 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5332
5333 /* BGP cluster ID. */
5334 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5335 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5336 VTY_NEWLINE);
5337
hassoe0701b72004-05-20 09:19:34 +00005338 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005339 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005340 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5341 VTY_NEWLINE);
5342
5343 /* Confederation peer */
5344 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005345 {
hassoe0701b72004-05-20 09:19:34 +00005346 int i;
paul718e3742002-12-13 20:15:29 +00005347
hassoe0701b72004-05-20 09:19:34 +00005348 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005349
hassoe0701b72004-05-20 09:19:34 +00005350 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005351 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005352
hassoe0701b72004-05-20 09:19:34 +00005353 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005354 }
5355
5356 /* BGP enforce-first-as. */
5357 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5358 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5359
5360 /* BGP deterministic-med. */
5361 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5362 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005363
5364 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005365 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5366 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5367 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005368 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5369 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5370
paul718e3742002-12-13 20:15:29 +00005371 /* BGP bestpath method. */
5372 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5373 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005374 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5375 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
Pradosh Mohapatra2fdd4552013-09-07 07:02:36 +00005376 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
5377 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
5378 }
paul718e3742002-12-13 20:15:29 +00005379 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5380 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5381 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5382 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5383 {
5384 vty_out (vty, " bgp bestpath med");
5385 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5386 vty_out (vty, " confed");
5387 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5388 vty_out (vty, " missing-as-worst");
5389 vty_out (vty, "%s", VTY_NEWLINE);
5390 }
5391
5392 /* BGP network import check. */
5393 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5394 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5395
5396 /* BGP scan interval. */
5397 bgp_config_write_scan_time (vty);
5398
5399 /* BGP flag dampening. */
5400 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5401 BGP_CONFIG_DAMPENING))
5402 bgp_config_write_damp (vty);
5403
5404 /* BGP static route configuration. */
5405 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5406
5407 /* BGP redistribute configuration. */
5408 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5409
5410 /* BGP timers configuration. */
5411 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5412 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5413 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5414 bgp->default_holdtime, VTY_NEWLINE);
5415
5416 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005417 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005418 {
5419 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5420 }
5421
5422 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005423 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005424 {
5425 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5426 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5427 }
5428
Josh Bailey165b5ff2011-07-20 20:43:22 -07005429 /* maximum-paths */
5430 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5431
paul718e3742002-12-13 20:15:29 +00005432 /* Distance configuration. */
5433 bgp_config_write_distance (vty, bgp);
5434
5435 /* No auto-summary */
5436 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5437 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5438
5439 /* IPv4 multicast configuration. */
5440 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5441
5442 /* IPv4 VPN configuration. */
5443 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5444
5445 /* IPv6 unicast configuration. */
5446 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5447
Paul Jakma37a217a2007-04-10 19:20:29 +00005448 /* IPv6 multicast configuration. */
5449 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5450
paul718e3742002-12-13 20:15:29 +00005451 write++;
5452 }
5453 return write;
5454}
5455
5456void
paul94f2b392005-06-28 12:44:16 +00005457bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005458{
5459 memset (&bgp_master, 0, sizeof (struct bgp_master));
5460
5461 bm = &bgp_master;
5462 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005463 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005464 bm->port = BGP_PORT_DEFAULT;
5465 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005466 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005467}
paul200df112005-06-01 11:17:05 +00005468
David Lamparter6b0655a2014-06-04 06:53:35 +02005469
paul718e3742002-12-13 20:15:29 +00005470void
paul94f2b392005-06-28 12:44:16 +00005471bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005472{
paul718e3742002-12-13 20:15:29 +00005473 /* BGP VTY commands installation. */
5474 bgp_vty_init ();
5475
paul718e3742002-12-13 20:15:29 +00005476 /* Init zebra. */
Donald Sharp774914f2015-10-14 08:50:39 -04005477 bgp_zebra_init (bm->master);
paul718e3742002-12-13 20:15:29 +00005478
5479 /* BGP inits. */
5480 bgp_attr_init ();
5481 bgp_debug_init ();
5482 bgp_dump_init ();
5483 bgp_route_init ();
5484 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005485 bgp_address_init ();
paul718e3742002-12-13 20:15:29 +00005486 bgp_scan_init ();
5487 bgp_mplsvpn_init ();
5488
5489 /* Access list initialize. */
5490 access_list_init ();
5491 access_list_add_hook (peer_distribute_update);
5492 access_list_delete_hook (peer_distribute_update);
5493
5494 /* Filter list initialize. */
5495 bgp_filter_init ();
5496 as_list_add_hook (peer_aslist_update);
5497 as_list_delete_hook (peer_aslist_update);
5498
5499 /* Prefix list initialize.*/
5500 prefix_list_init ();
5501 prefix_list_add_hook (peer_prefix_list_update);
5502 prefix_list_delete_hook (peer_prefix_list_update);
5503
5504 /* Community list initialize. */
5505 bgp_clist = community_list_init ();
5506
5507#ifdef HAVE_SNMP
5508 bgp_snmp_init ();
5509#endif /* HAVE_SNMP */
5510}
paul545acaf2004-04-20 15:13:15 +00005511
5512void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005513bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005514{
paul545acaf2004-04-20 15:13:15 +00005515 struct bgp *bgp;
5516 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005517 struct listnode *node, *nnode;
5518 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005519
paul1eb8ef22005-04-07 07:30:20 +00005520 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5521 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005522 if (peer->status == Established)
5523 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5524 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005525
paul545acaf2004-04-20 15:13:15 +00005526 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005527
paule210cf92005-06-15 19:15:35 +00005528 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005529 {
5530 work_queue_free (bm->process_main_queue);
5531 bm->process_main_queue = NULL;
5532 }
paule210cf92005-06-15 19:15:35 +00005533 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005534 {
5535 work_queue_free (bm->process_rsclient_queue);
5536 bm->process_rsclient_queue = NULL;
5537 }
paul545acaf2004-04-20 15:13:15 +00005538}