blob: 60428586a8b868fa7f5cb070e3e45fb62b64e753 [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"
29#include "network.h"
30#include "memory.h"
31#include "filter.h"
32#include "routemap.h"
33#include "str.h"
34#include "log.h"
35#include "plist.h"
36#include "linklist.h"
paul200df112005-06-01 11:17:05 +000037#include "workqueue.h"
paul718e3742002-12-13 20:15:29 +000038
39#include "bgpd/bgpd.h"
40#include "bgpd/bgp_table.h"
41#include "bgpd/bgp_aspath.h"
42#include "bgpd/bgp_route.h"
43#include "bgpd/bgp_dump.h"
44#include "bgpd/bgp_debug.h"
45#include "bgpd/bgp_community.h"
46#include "bgpd/bgp_attr.h"
47#include "bgpd/bgp_regex.h"
48#include "bgpd/bgp_clist.h"
49#include "bgpd/bgp_fsm.h"
50#include "bgpd/bgp_packet.h"
51#include "bgpd/bgp_zebra.h"
52#include "bgpd/bgp_open.h"
53#include "bgpd/bgp_filter.h"
54#include "bgpd/bgp_nexthop.h"
55#include "bgpd/bgp_damp.h"
56#include "bgpd/bgp_mplsvpn.h"
57#include "bgpd/bgp_advertise.h"
58#include "bgpd/bgp_network.h"
59#include "bgpd/bgp_vty.h"
Josh Bailey165b5ff2011-07-20 20:43:22 -070060#include "bgpd/bgp_mpath.h"
paul718e3742002-12-13 20:15:29 +000061#ifdef HAVE_SNMP
62#include "bgpd/bgp_snmp.h"
63#endif /* HAVE_SNMP */
David Lamparter6b0655a2014-06-04 06:53:35 +020064
paul718e3742002-12-13 20:15:29 +000065/* BGP process wide configuration. */
66static struct bgp_master bgp_master;
67
hasso18a6dce2004-10-03 18:18:34 +000068extern struct in_addr router_id_zebra;
69
paul718e3742002-12-13 20:15:29 +000070/* BGP process wide configuration pointer to export. */
71struct bgp_master *bm;
72
73/* BGP community-list. */
74struct community_list_handler *bgp_clist;
David Lamparter6b0655a2014-06-04 06:53:35 +020075
paul718e3742002-12-13 20:15:29 +000076/* BGP global flag manipulation. */
77int
78bgp_option_set (int flag)
79{
80 switch (flag)
81 {
82 case BGP_OPT_NO_FIB:
83 case BGP_OPT_MULTIPLE_INSTANCE:
84 case BGP_OPT_CONFIG_CISCO:
Paul Jakmacccbc012012-06-14 10:40:26 +010085 case BGP_OPT_NO_LISTEN:
paul718e3742002-12-13 20:15:29 +000086 SET_FLAG (bm->options, flag);
87 break;
88 default:
89 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +000090 }
91 return 0;
92}
93
94int
95bgp_option_unset (int flag)
96{
97 switch (flag)
98 {
99 case BGP_OPT_MULTIPLE_INSTANCE:
100 if (listcount (bm->bgp) > 1)
101 return BGP_ERR_MULTIPLE_INSTANCE_USED;
102 /* Fall through. */
103 case BGP_OPT_NO_FIB:
104 case BGP_OPT_CONFIG_CISCO:
105 UNSET_FLAG (bm->options, flag);
106 break;
107 default:
108 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +0000109 }
110 return 0;
111}
112
113int
114bgp_option_check (int flag)
115{
116 return CHECK_FLAG (bm->options, flag);
117}
David Lamparter6b0655a2014-06-04 06:53:35 +0200118
paul718e3742002-12-13 20:15:29 +0000119/* BGP flag manipulation. */
120int
121bgp_flag_set (struct bgp *bgp, int flag)
122{
123 SET_FLAG (bgp->flags, flag);
124 return 0;
125}
126
127int
128bgp_flag_unset (struct bgp *bgp, int flag)
129{
130 UNSET_FLAG (bgp->flags, flag);
131 return 0;
132}
133
134int
135bgp_flag_check (struct bgp *bgp, int flag)
136{
137 return CHECK_FLAG (bgp->flags, flag);
138}
David Lamparter6b0655a2014-06-04 06:53:35 +0200139
paul718e3742002-12-13 20:15:29 +0000140/* Internal function to set BGP structure configureation flag. */
141static void
142bgp_config_set (struct bgp *bgp, int config)
143{
144 SET_FLAG (bgp->config, config);
145}
146
147static void
148bgp_config_unset (struct bgp *bgp, int config)
149{
150 UNSET_FLAG (bgp->config, config);
151}
152
153static int
154bgp_config_check (struct bgp *bgp, int config)
155{
156 return CHECK_FLAG (bgp->config, config);
157}
David Lamparter6b0655a2014-06-04 06:53:35 +0200158
paul718e3742002-12-13 20:15:29 +0000159/* Set BGP router identifier. */
160int
161bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
162{
163 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000164 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000165
166 if (bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID)
167 && IPV4_ADDR_SAME (&bgp->router_id, id))
168 return 0;
169
170 IPV4_ADDR_COPY (&bgp->router_id, id);
171 bgp_config_set (bgp, BGP_CONFIG_ROUTER_ID);
172
173 /* Set all peer's local identifier with this value. */
paul1eb8ef22005-04-07 07:30:20 +0000174 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000175 {
176 IPV4_ADDR_COPY (&peer->local_id, id);
177
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000178 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000179 {
180 peer->last_reset = PEER_DOWN_RID_CHANGE;
181 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
182 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
183 }
paul718e3742002-12-13 20:15:29 +0000184 }
185 return 0;
186}
187
paul718e3742002-12-13 20:15:29 +0000188/* BGP's cluster-id control. */
189int
190bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
191{
192 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000193 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000194
195 if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)
196 && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id))
197 return 0;
198
199 IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id);
200 bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID);
201
202 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000203 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000204 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000205 if (peer->sort != BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +0000206 continue;
207
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000208 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000209 {
210 peer->last_reset = PEER_DOWN_CLID_CHANGE;
211 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
212 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
213 }
paul718e3742002-12-13 20:15:29 +0000214 }
215 return 0;
216}
217
218int
219bgp_cluster_id_unset (struct bgp *bgp)
220{
221 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000222 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000223
224 if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID))
225 return 0;
226
227 bgp->cluster_id.s_addr = 0;
228 bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID);
229
230 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000231 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000232 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000233 if (peer->sort != BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +0000234 continue;
235
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000236 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000237 {
238 peer->last_reset = PEER_DOWN_CLID_CHANGE;
239 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
240 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
241 }
paul718e3742002-12-13 20:15:29 +0000242 }
243 return 0;
244}
David Lamparter6b0655a2014-06-04 06:53:35 +0200245
Stephen Hemminger65957882010-01-15 16:22:10 +0300246/* time_t value that is monotonicly increasing
247 * and uneffected by adjustments to system clock
248 */
249time_t bgp_clock (void)
250{
251 struct timeval tv;
252
253 quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv);
254 return tv.tv_sec;
255}
256
paul718e3742002-12-13 20:15:29 +0000257/* BGP timer configuration. */
258int
259bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
260{
261 bgp->default_keepalive = (keepalive < holdtime / 3
262 ? keepalive : holdtime / 3);
263 bgp->default_holdtime = holdtime;
264
265 return 0;
266}
267
268int
269bgp_timers_unset (struct bgp *bgp)
270{
271 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
272 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
273
274 return 0;
275}
David Lamparter6b0655a2014-06-04 06:53:35 +0200276
paul718e3742002-12-13 20:15:29 +0000277/* BGP confederation configuration. */
278int
279bgp_confederation_id_set (struct bgp *bgp, as_t as)
280{
281 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000282 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000283 int already_confed;
284
285 if (as == 0)
286 return BGP_ERR_INVALID_AS;
287
288 /* Remember - were we doing confederation before? */
289 already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);
290 bgp->confed_id = as;
291 bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);
292
293 /* If we were doing confederation already, this is just an external
294 AS change. Just Reset EBGP sessions, not CONFED sessions. If we
295 were not doing confederation before, reset all EBGP sessions. */
paul1eb8ef22005-04-07 07:30:20 +0000296 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000297 {
298 /* We're looking for peers who's AS is not local or part of our
299 confederation. */
300 if (already_confed)
301 {
302 if (peer_sort (peer) == BGP_PEER_EBGP)
303 {
304 peer->local_as = as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000305 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000306 {
307 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
308 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
309 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
310 }
311
paul718e3742002-12-13 20:15:29 +0000312 else
313 BGP_EVENT_ADD (peer, BGP_Stop);
314 }
315 }
316 else
317 {
318 /* Not doign confederation before, so reset every non-local
319 session */
320 if (peer_sort (peer) != BGP_PEER_IBGP)
321 {
322 /* Reset the local_as to be our EBGP one */
323 if (peer_sort (peer) == BGP_PEER_EBGP)
324 peer->local_as = as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000325 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000326 {
327 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
328 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
329 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
330 }
paul718e3742002-12-13 20:15:29 +0000331 else
332 BGP_EVENT_ADD (peer, BGP_Stop);
333 }
334 }
335 }
336 return 0;
337}
338
339int
340bgp_confederation_id_unset (struct bgp *bgp)
341{
342 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000343 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000344
345 bgp->confed_id = 0;
346 bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
347
paul1eb8ef22005-04-07 07:30:20 +0000348 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000349 {
350 /* We're looking for peers who's AS is not local */
351 if (peer_sort (peer) != BGP_PEER_IBGP)
352 {
353 peer->local_as = bgp->as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000354 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000355 {
356 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
357 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
358 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
359 }
360
paul718e3742002-12-13 20:15:29 +0000361 else
362 BGP_EVENT_ADD (peer, BGP_Stop);
363 }
364 }
365 return 0;
366}
367
368/* Is an AS part of the confed or not? */
369int
370bgp_confederation_peers_check (struct bgp *bgp, as_t as)
371{
372 int i;
373
374 if (! bgp)
375 return 0;
376
377 for (i = 0; i < bgp->confed_peers_cnt; i++)
378 if (bgp->confed_peers[i] == as)
379 return 1;
380
381 return 0;
382}
383
384/* Add an AS to the confederation set. */
385int
386bgp_confederation_peers_add (struct bgp *bgp, as_t as)
387{
388 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000389 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000390
391 if (! bgp)
392 return BGP_ERR_INVALID_BGP;
393
394 if (bgp->as == as)
395 return BGP_ERR_INVALID_AS;
396
397 if (bgp_confederation_peers_check (bgp, as))
398 return -1;
399
400 if (bgp->confed_peers)
401 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
402 bgp->confed_peers,
403 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
404 else
405 bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST,
406 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
407
408 bgp->confed_peers[bgp->confed_peers_cnt] = as;
409 bgp->confed_peers_cnt++;
410
411 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
412 {
paul1eb8ef22005-04-07 07:30:20 +0000413 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000414 {
415 if (peer->as == as)
416 {
417 peer->local_as = bgp->as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000418 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000419 {
420 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
421 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
422 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
423 }
paul718e3742002-12-13 20:15:29 +0000424 else
425 BGP_EVENT_ADD (peer, BGP_Stop);
426 }
427 }
428 }
429 return 0;
430}
431
432/* Delete an AS from the confederation set. */
433int
434bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
435{
436 int i;
437 int j;
438 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000439 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000440
441 if (! bgp)
442 return -1;
443
444 if (! bgp_confederation_peers_check (bgp, as))
445 return -1;
446
447 for (i = 0; i < bgp->confed_peers_cnt; i++)
448 if (bgp->confed_peers[i] == as)
449 for(j = i + 1; j < bgp->confed_peers_cnt; j++)
450 bgp->confed_peers[j - 1] = bgp->confed_peers[j];
451
452 bgp->confed_peers_cnt--;
453
454 if (bgp->confed_peers_cnt == 0)
455 {
456 if (bgp->confed_peers)
457 XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
458 bgp->confed_peers = NULL;
459 }
460 else
461 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
462 bgp->confed_peers,
463 bgp->confed_peers_cnt * sizeof (as_t));
464
465 /* Now reset any peer who's remote AS has just been removed from the
466 CONFED */
467 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
468 {
paul1eb8ef22005-04-07 07:30:20 +0000469 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000470 {
471 if (peer->as == as)
472 {
473 peer->local_as = bgp->confed_id;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000474 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000475 {
476 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
477 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
478 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
479 }
paul718e3742002-12-13 20:15:29 +0000480 else
481 BGP_EVENT_ADD (peer, BGP_Stop);
482 }
483 }
484 }
485
486 return 0;
487}
David Lamparter6b0655a2014-06-04 06:53:35 +0200488
paul718e3742002-12-13 20:15:29 +0000489/* Local preference configuration. */
490int
491bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
492{
493 if (! bgp)
494 return -1;
495
paul718e3742002-12-13 20:15:29 +0000496 bgp->default_local_pref = local_pref;
497
498 return 0;
499}
500
501int
502bgp_default_local_preference_unset (struct bgp *bgp)
503{
504 if (! bgp)
505 return -1;
506
paul718e3742002-12-13 20:15:29 +0000507 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
508
509 return 0;
510}
David Lamparter6b0655a2014-06-04 06:53:35 +0200511
paulfee0f4c2004-09-13 05:12:46 +0000512/* If peer is RSERVER_CLIENT in at least one address family and is not member
513 of a peer_group for that family, return 1.
514 Used to check wether the peer is included in list bgp->rsclient. */
515int
516peer_rsclient_active (struct peer *peer)
517{
518 int i;
519 int j;
520
521 for (i=AFI_IP; i < AFI_MAX; i++)
522 for (j=SAFI_UNICAST; j < SAFI_MAX; j++)
523 if (CHECK_FLAG(peer->af_flags[i][j], PEER_FLAG_RSERVER_CLIENT)
524 && ! peer->af_group[i][j])
525 return 1;
526 return 0;
527}
528
pauleb821182004-05-01 08:44:08 +0000529/* Peer comparison function for sorting. */
paul718e3742002-12-13 20:15:29 +0000530static int
531peer_cmp (struct peer *p1, struct peer *p2)
532{
pauleb821182004-05-01 08:44:08 +0000533 return sockunion_cmp (&p1->su, &p2->su);
paul718e3742002-12-13 20:15:29 +0000534}
535
536int
537peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
538{
539 return CHECK_FLAG (peer->af_flags[afi][safi], flag);
540}
541
542/* Reset all address family specific configuration. */
543static void
544peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
545{
546 int i;
547 struct bgp_filter *filter;
548 char orf_name[BUFSIZ];
549
550 filter = &peer->filter[afi][safi];
551
552 /* Clear neighbor filter and route-map */
553 for (i = FILTER_IN; i < FILTER_MAX; i++)
554 {
555 if (filter->dlist[i].name)
556 {
557 free (filter->dlist[i].name);
558 filter->dlist[i].name = NULL;
559 }
560 if (filter->plist[i].name)
561 {
562 free (filter->plist[i].name);
563 filter->plist[i].name = NULL;
564 }
565 if (filter->aslist[i].name)
566 {
567 free (filter->aslist[i].name);
568 filter->aslist[i].name = NULL;
569 }
paulfee0f4c2004-09-13 05:12:46 +0000570 }
571 for (i = RMAP_IN; i < RMAP_MAX; i++)
572 {
paul718e3742002-12-13 20:15:29 +0000573 if (filter->map[i].name)
574 {
575 free (filter->map[i].name);
576 filter->map[i].name = NULL;
577 }
578 }
579
580 /* Clear unsuppress map. */
581 if (filter->usmap.name)
582 free (filter->usmap.name);
583 filter->usmap.name = NULL;
584 filter->usmap.map = NULL;
585
586 /* Clear neighbor's all address family flags. */
587 peer->af_flags[afi][safi] = 0;
588
589 /* Clear neighbor's all address family sflags. */
590 peer->af_sflags[afi][safi] = 0;
591
592 /* Clear neighbor's all address family capabilities. */
593 peer->af_cap[afi][safi] = 0;
594
595 /* Clear ORF info */
596 peer->orf_plist[afi][safi] = NULL;
597 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
David Lamparterc9c06d02015-04-13 10:21:35 +0200598 prefix_bgp_orf_remove_all (afi, orf_name);
paul718e3742002-12-13 20:15:29 +0000599
600 /* Set default neighbor send-community. */
601 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
602 {
603 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
604 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
605 }
606
607 /* Clear neighbor default_originate_rmap */
608 if (peer->default_rmap[afi][safi].name)
609 free (peer->default_rmap[afi][safi].name);
610 peer->default_rmap[afi][safi].name = NULL;
611 peer->default_rmap[afi][safi].map = NULL;
612
613 /* Clear neighbor maximum-prefix */
614 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +0000615 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000616}
617
618/* peer global config reset */
paul94f2b392005-06-28 12:44:16 +0000619static void
paul718e3742002-12-13 20:15:29 +0000620peer_global_config_reset (struct peer *peer)
621{
622 peer->weight = 0;
623 peer->change_local_as = 0;
624 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
625 if (peer->update_source)
626 {
627 sockunion_free (peer->update_source);
628 peer->update_source = NULL;
629 }
630 if (peer->update_if)
631 {
632 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
633 peer->update_if = NULL;
634 }
635
636 if (peer_sort (peer) == BGP_PEER_IBGP)
637 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
638 else
639 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
640
641 peer->flags = 0;
642 peer->config = 0;
643 peer->holdtime = 0;
644 peer->keepalive = 0;
645 peer->connect = 0;
646 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
647}
648
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000649/* Check peer's AS number and determines if this peer is IBGP or EBGP */
650static bgp_peer_sort_t
651peer_calc_sort (struct peer *peer)
paul718e3742002-12-13 20:15:29 +0000652{
653 struct bgp *bgp;
654
655 bgp = peer->bgp;
656
657 /* Peer-group */
658 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
659 {
660 if (peer->as)
661 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
662 else
663 {
664 struct peer *peer1;
665 peer1 = listnode_head (peer->group->peer);
666 if (peer1)
667 return (peer1->local_as == peer1->as
668 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
669 }
670 return BGP_PEER_INTERNAL;
671 }
672
673 /* Normal peer */
674 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
675 {
676 if (peer->local_as == 0)
677 return BGP_PEER_INTERNAL;
678
679 if (peer->local_as == peer->as)
680 {
681 if (peer->local_as == bgp->confed_id)
682 return BGP_PEER_EBGP;
683 else
684 return BGP_PEER_IBGP;
685 }
686
687 if (bgp_confederation_peers_check (bgp, peer->as))
688 return BGP_PEER_CONFED;
689
690 return BGP_PEER_EBGP;
691 }
692 else
693 {
694 return (peer->local_as == 0
695 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
696 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
697 }
698}
699
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000700/* Calculate and cache the peer "sort" */
701bgp_peer_sort_t
702peer_sort (struct peer *peer)
703{
704 peer->sort = peer_calc_sort (peer);
705 return peer->sort;
706}
707
Paul Jakmaf63f06d2011-04-08 12:44:43 +0100708static void
paul200df112005-06-01 11:17:05 +0000709peer_free (struct peer *peer)
710{
Paul Jakmaca058a32006-09-14 02:58:49 +0000711 assert (peer->status == Deleted);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700712
713 bgp_unlock(peer->bgp);
714
Paul Jakmaca058a32006-09-14 02:58:49 +0000715 /* this /ought/ to have been done already through bgp_stop earlier,
716 * but just to be sure..
717 */
718 bgp_timer_set (peer);
719 BGP_READ_OFF (peer->t_read);
720 BGP_WRITE_OFF (peer->t_write);
Paul Jakma9fde6622006-09-14 03:02:02 +0000721 BGP_EVENT_FLUSH (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +0000722
paul200df112005-06-01 11:17:05 +0000723 if (peer->desc)
Daniel Walton363c9032015-10-21 06:42:54 -0700724 {
725 XFREE (MTYPE_PEER_DESC, peer->desc);
726 peer->desc = NULL;
727 }
paul200df112005-06-01 11:17:05 +0000728
729 /* Free allocated host character. */
730 if (peer->host)
Daniel Walton363c9032015-10-21 06:42:54 -0700731 {
732 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
733 peer->host = NULL;
734 }
735
paul200df112005-06-01 11:17:05 +0000736 /* Update source configuration. */
737 if (peer->update_source)
Daniel Walton363c9032015-10-21 06:42:54 -0700738 {
739 sockunion_free (peer->update_source);
740 peer->update_source = NULL;
741 }
paul200df112005-06-01 11:17:05 +0000742
743 if (peer->update_if)
Daniel Walton363c9032015-10-21 06:42:54 -0700744 {
745 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
746 peer->update_if = NULL;
747 }
Paul Jakmaa625ca32006-03-30 14:12:38 +0000748
749 if (peer->clear_node_queue)
Daniel Walton363c9032015-10-21 06:42:54 -0700750 {
751 work_queue_free(peer->clear_node_queue);
752 peer->clear_node_queue = NULL;
753 }
Paul Jakmaa625ca32006-03-30 14:12:38 +0000754
Lou Berger056f3762013-04-10 12:30:04 -0700755 if (peer->notify.data)
756 XFREE(MTYPE_TMP, peer->notify.data);
757
Paul Jakmaca058a32006-09-14 02:58:49 +0000758 bgp_sync_delete (peer);
paul200df112005-06-01 11:17:05 +0000759 memset (peer, 0, sizeof (struct peer));
760
761 XFREE (MTYPE_BGP_PEER, peer);
762}
763
764/* increase reference count on a struct peer */
765struct peer *
Donald Sharp104576d2015-09-16 13:17:55 -0400766peer_lock_with_caller (const char *name, struct peer *peer)
paul200df112005-06-01 11:17:05 +0000767{
768 assert (peer && (peer->lock >= 0));
Donald Sharp104576d2015-09-16 13:17:55 -0400769
770#if 0
771 zlog_debug("%s peer_lock %p %d", name, peer, peer->lock);
772#endif
773
paul200df112005-06-01 11:17:05 +0000774 peer->lock++;
775
776 return peer;
777}
778
779/* decrease reference count on a struct peer
780 * struct peer is freed and NULL returned if last reference
781 */
782struct peer *
Donald Sharp104576d2015-09-16 13:17:55 -0400783peer_unlock_with_caller (const char *name, struct peer *peer)
paul200df112005-06-01 11:17:05 +0000784{
785 assert (peer && (peer->lock > 0));
Donald Sharp104576d2015-09-16 13:17:55 -0400786
787#if 0
788 zlog_debug("%s peer_unlock %p %d", name, peer, peer->lock);
789#endif
790
paul200df112005-06-01 11:17:05 +0000791 peer->lock--;
792
793 if (peer->lock == 0)
794 {
paul200df112005-06-01 11:17:05 +0000795 peer_free (peer);
796 return NULL;
797 }
798
paul200df112005-06-01 11:17:05 +0000799 return peer;
800}
801
802/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000803static struct peer *
Paul Jakma6f585442006-10-22 19:13:07 +0000804peer_new (struct bgp *bgp)
paul718e3742002-12-13 20:15:29 +0000805{
806 afi_t afi;
807 safi_t safi;
808 struct peer *peer;
809 struct servent *sp;
Paul Jakma6f585442006-10-22 19:13:07 +0000810
811 /* bgp argument is absolutely required */
812 assert (bgp);
813 if (!bgp)
814 return NULL;
815
paul718e3742002-12-13 20:15:29 +0000816 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000817 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000818
819 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000820 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000821 peer->v_start = BGP_INIT_START_TIMER;
822 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
paul718e3742002-12-13 20:15:29 +0000823 peer->status = Idle;
824 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000825 peer->weight = 0;
Paul Jakma0df7c912008-07-21 21:02:49 +0000826 peer->password = NULL;
Paul Jakma6f585442006-10-22 19:13:07 +0000827 peer->bgp = bgp;
Paul Jakmaca058a32006-09-14 02:58:49 +0000828 peer = peer_lock (peer); /* initial reference */
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700829 bgp_lock (bgp);
paul718e3742002-12-13 20:15:29 +0000830
831 /* Set default flags. */
832 for (afi = AFI_IP; afi < AFI_MAX; afi++)
833 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
834 {
835 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
836 {
837 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
838 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
839 }
840 peer->orf_plist[afi][safi] = NULL;
841 }
842 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
843
844 /* Create buffers. */
845 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
846 peer->obuf = stream_fifo_new ();
847 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000848 peer->scratch = stream_new (BGP_MAX_PACKET_SIZE);
paul718e3742002-12-13 20:15:29 +0000849
850 bgp_sync_init (peer);
851
852 /* Get service port number. */
853 sp = getservbyname ("bgp", "tcp");
854 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
855
856 return peer;
857}
858
859/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000860static struct peer *
paul718e3742002-12-13 20:15:29 +0000861peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
862 as_t remote_as, afi_t afi, safi_t safi)
863{
864 int active;
865 struct peer *peer;
866 char buf[SU_ADDRSTRLEN];
867
Paul Jakma6f585442006-10-22 19:13:07 +0000868 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000869 peer->su = *su;
870 peer->local_as = local_as;
871 peer->as = remote_as;
872 peer->local_id = bgp->router_id;
873 peer->v_holdtime = bgp->default_holdtime;
874 peer->v_keepalive = bgp->default_keepalive;
875 if (peer_sort (peer) == BGP_PEER_IBGP)
876 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
877 else
878 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000879
880 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000881 listnode_add_sort (bgp->peer, peer);
882
883 active = peer_active (peer);
884
885 if (afi && safi)
886 peer->afc[afi][safi] = 1;
887
Stephen Hemminger65957882010-01-15 16:22:10 +0300888 /* Last read and reset time set */
889 peer->readtime = peer->resettime = bgp_clock ();
paul848973c2003-08-13 00:32:49 +0000890
paul718e3742002-12-13 20:15:29 +0000891 /* Default TTL set. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000892 peer->ttl = (peer->sort == BGP_PEER_IBGP) ? 255 : 1;
paul718e3742002-12-13 20:15:29 +0000893
894 /* Make peer's address string. */
895 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000896 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000897
898 /* Set up peer's events and timers. */
899 if (! active && peer_active (peer))
900 bgp_timer_set (peer);
901
902 return peer;
903}
904
pauleb821182004-05-01 08:44:08 +0000905/* Make accept BGP peer. Called from bgp_accept (). */
906struct peer *
907peer_create_accept (struct bgp *bgp)
908{
909 struct peer *peer;
910
Paul Jakma6f585442006-10-22 19:13:07 +0000911 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000912
913 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000914 listnode_add_sort (bgp->peer, peer);
915
916 return peer;
917}
918
paul718e3742002-12-13 20:15:29 +0000919/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000920static void
paul718e3742002-12-13 20:15:29 +0000921peer_as_change (struct peer *peer, as_t as)
922{
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000923 bgp_peer_sort_t type;
paul718e3742002-12-13 20:15:29 +0000924
925 /* Stop peer. */
926 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
927 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000928 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000929 {
930 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
931 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
932 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
933 }
paul718e3742002-12-13 20:15:29 +0000934 else
935 BGP_EVENT_ADD (peer, BGP_Stop);
936 }
937 type = peer_sort (peer);
938 peer->as = as;
939
paul848973c2003-08-13 00:32:49 +0000940 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
941 && ! bgp_confederation_peers_check (peer->bgp, as)
942 && peer->bgp->as != as)
943 peer->local_as = peer->bgp->confed_id;
944 else
945 peer->local_as = peer->bgp->as;
946
paul718e3742002-12-13 20:15:29 +0000947 /* Advertisement-interval reset */
948 if (peer_sort (peer) == BGP_PEER_IBGP)
949 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
950 else
951 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
952
953 /* TTL reset */
954 if (peer_sort (peer) == BGP_PEER_IBGP)
955 peer->ttl = 255;
956 else if (type == BGP_PEER_IBGP)
957 peer->ttl = 1;
958
959 /* reflector-client reset */
960 if (peer_sort (peer) != BGP_PEER_IBGP)
961 {
962 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
963 PEER_FLAG_REFLECTOR_CLIENT);
964 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
965 PEER_FLAG_REFLECTOR_CLIENT);
966 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
967 PEER_FLAG_REFLECTOR_CLIENT);
968 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
969 PEER_FLAG_REFLECTOR_CLIENT);
970 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
971 PEER_FLAG_REFLECTOR_CLIENT);
972 }
973
974 /* local-as reset */
975 if (peer_sort (peer) != BGP_PEER_EBGP)
976 {
977 peer->change_local_as = 0;
978 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +0000979 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +0000980 }
981}
982
983/* If peer does not exist, create new one. If peer already exists,
984 set AS number to the peer. */
985int
986peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
987 afi_t afi, safi_t safi)
988{
989 struct peer *peer;
990 as_t local_as;
991
992 peer = peer_lookup (bgp, su);
993
994 if (peer)
995 {
996 /* When this peer is a member of peer-group. */
997 if (peer->group)
998 {
999 if (peer->group->conf->as)
1000 {
1001 /* Return peer group's AS number. */
1002 *as = peer->group->conf->as;
1003 return BGP_ERR_PEER_GROUP_MEMBER;
1004 }
1005 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
1006 {
1007 if (bgp->as != *as)
1008 {
1009 *as = peer->as;
1010 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1011 }
1012 }
1013 else
1014 {
1015 if (bgp->as == *as)
1016 {
1017 *as = peer->as;
1018 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1019 }
1020 }
1021 }
1022
1023 /* Existing peer's AS number change. */
1024 if (peer->as != *as)
1025 peer_as_change (peer, *as);
1026 }
1027 else
1028 {
1029
1030 /* If the peer is not part of our confederation, and its not an
1031 iBGP peer then spoof the source AS */
1032 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1033 && ! bgp_confederation_peers_check (bgp, *as)
1034 && bgp->as != *as)
1035 local_as = bgp->confed_id;
1036 else
1037 local_as = bgp->as;
1038
1039 /* If this is IPv4 unicast configuration and "no bgp default
1040 ipv4-unicast" is specified. */
1041
1042 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1043 && afi == AFI_IP && safi == SAFI_UNICAST)
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001044 peer_create (su, bgp, local_as, *as, 0, 0);
paul718e3742002-12-13 20:15:29 +00001045 else
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001046 peer_create (su, bgp, local_as, *as, afi, safi);
paul718e3742002-12-13 20:15:29 +00001047 }
1048
1049 return 0;
1050}
1051
1052/* Activate the peer or peer group for specified AFI and SAFI. */
1053int
1054peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1055{
1056 int active;
1057
1058 if (peer->afc[afi][safi])
1059 return 0;
1060
1061 /* Activate the address family configuration. */
1062 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1063 peer->afc[afi][safi] = 1;
1064 else
1065 {
1066 active = peer_active (peer);
1067
1068 peer->afc[afi][safi] = 1;
1069
1070 if (! active && peer_active (peer))
1071 bgp_timer_set (peer);
1072 else
1073 {
1074 if (peer->status == Established)
1075 {
1076 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1077 {
1078 peer->afc_adv[afi][safi] = 1;
1079 bgp_capability_send (peer, afi, safi,
1080 CAPABILITY_CODE_MP,
1081 CAPABILITY_ACTION_SET);
1082 if (peer->afc_recv[afi][safi])
1083 {
1084 peer->afc_nego[afi][safi] = 1;
1085 bgp_announce_route (peer, afi, safi);
1086 }
1087 }
1088 else
hassoe0701b72004-05-20 09:19:34 +00001089 {
1090 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1091 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1092 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1093 }
paul718e3742002-12-13 20:15:29 +00001094 }
1095 }
1096 }
1097 return 0;
1098}
1099
1100int
1101peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1102{
1103 struct peer_group *group;
1104 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001105 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001106
1107 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1108 {
1109 group = peer->group;
1110
paul1eb8ef22005-04-07 07:30:20 +00001111 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001112 {
1113 if (peer1->af_group[afi][safi])
1114 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1115 }
1116 }
1117 else
1118 {
1119 if (peer->af_group[afi][safi])
1120 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1121 }
1122
1123 if (! peer->afc[afi][safi])
1124 return 0;
1125
1126 /* De-activate the address family configuration. */
1127 peer->afc[afi][safi] = 0;
1128 peer_af_flag_reset (peer, afi, safi);
1129
1130 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1131 {
1132 if (peer->status == Established)
1133 {
1134 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1135 {
1136 peer->afc_adv[afi][safi] = 0;
1137 peer->afc_nego[afi][safi] = 0;
1138
1139 if (peer_active_nego (peer))
1140 {
1141 bgp_capability_send (peer, afi, safi,
1142 CAPABILITY_CODE_MP,
1143 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001144 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001145 peer->pcount[afi][safi] = 0;
1146 }
1147 else
hassoe0701b72004-05-20 09:19:34 +00001148 {
1149 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1150 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1151 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1152 }
paul718e3742002-12-13 20:15:29 +00001153 }
1154 else
hassoe0701b72004-05-20 09:19:34 +00001155 {
1156 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1157 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1158 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1159 }
paul718e3742002-12-13 20:15:29 +00001160 }
1161 }
1162 return 0;
1163}
1164
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001165static void
hasso93406d82005-02-02 14:40:33 +00001166peer_nsf_stop (struct peer *peer)
1167{
1168 afi_t afi;
1169 safi_t safi;
1170
1171 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1172 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1173
1174 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +04001175 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +00001176 peer->nsf[afi][safi] = 0;
1177
1178 if (peer->t_gr_restart)
1179 {
1180 BGP_TIMER_OFF (peer->t_gr_restart);
1181 if (BGP_DEBUG (events, EVENTS))
1182 zlog_debug ("%s graceful restart timer stopped", peer->host);
1183 }
1184 if (peer->t_gr_stale)
1185 {
1186 BGP_TIMER_OFF (peer->t_gr_stale);
1187 if (BGP_DEBUG (events, EVENTS))
1188 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1189 }
1190 bgp_clear_route_all (peer);
1191}
1192
Paul Jakmaca058a32006-09-14 02:58:49 +00001193/* Delete peer from confguration.
1194 *
1195 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1196 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1197 *
1198 * This function /should/ take care to be idempotent, to guard against
1199 * it being called multiple times through stray events that come in
1200 * that happen to result in this function being called again. That
1201 * said, getting here for a "Deleted" peer is a bug in the neighbour
1202 * FSM.
1203 */
paul718e3742002-12-13 20:15:29 +00001204int
1205peer_delete (struct peer *peer)
1206{
1207 int i;
1208 afi_t afi;
1209 safi_t safi;
1210 struct bgp *bgp;
1211 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001212 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001213
Paul Jakmaca058a32006-09-14 02:58:49 +00001214 assert (peer->status != Deleted);
1215
paul718e3742002-12-13 20:15:29 +00001216 bgp = peer->bgp;
1217
hasso93406d82005-02-02 14:40:33 +00001218 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1219 peer_nsf_stop (peer);
1220
Chris Caputo228da422009-07-18 05:44:03 +00001221 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001222 relationship. */
1223 if (peer->group)
1224 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001225 if ((pn = listnode_lookup (peer->group->peer, peer)))
1226 {
1227 peer = peer_unlock (peer); /* group->peer list reference */
1228 list_delete_node (peer->group->peer, pn);
1229 }
paul718e3742002-12-13 20:15:29 +00001230 peer->group = NULL;
1231 }
paul200df112005-06-01 11:17:05 +00001232
paul718e3742002-12-13 20:15:29 +00001233 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001234 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1235 * executed after peer structure is deleted.
1236 */
hassoe0701b72004-05-20 09:19:34 +00001237 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001238 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001239 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001240
1241 /* Password configuration */
1242 if (peer->password)
1243 {
1244 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1245 peer->password = NULL;
1246
1247 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1248 bgp_md5_set (peer);
1249 }
1250
Paul Jakmaca058a32006-09-14 02:58:49 +00001251 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001252
paul718e3742002-12-13 20:15:29 +00001253 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001254 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1255 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001256 {
Chris Caputo228da422009-07-18 05:44:03 +00001257 peer_unlock (peer); /* bgp peer list reference */
1258 list_delete_node (bgp->peer, pn);
1259 }
paul200df112005-06-01 11:17:05 +00001260
Chris Caputo228da422009-07-18 05:44:03 +00001261 if (peer_rsclient_active (peer)
1262 && (pn = listnode_lookup (bgp->rsclient, peer)))
1263 {
1264 peer_unlock (peer); /* rsclient list reference */
1265 list_delete_node (bgp->rsclient, pn);
1266
1267 /* Clear our own rsclient ribs. */
1268 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1269 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1270 if (CHECK_FLAG(peer->af_flags[afi][safi],
1271 PEER_FLAG_RSERVER_CLIENT))
1272 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001273 }
1274
1275 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1276 member of a peer_group. */
1277 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1278 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1279 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001280 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001281
paul200df112005-06-01 11:17:05 +00001282 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001283 if (peer->ibuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001284 {
1285 stream_free (peer->ibuf);
1286 peer->ibuf = NULL;
1287 }
1288
paul718e3742002-12-13 20:15:29 +00001289 if (peer->obuf)
Daniel Walton363c9032015-10-21 06:42:54 -07001290 {
1291 stream_fifo_free (peer->obuf);
1292 peer->obuf = NULL;
1293 }
1294
paul718e3742002-12-13 20:15:29 +00001295 if (peer->work)
Daniel Walton363c9032015-10-21 06:42:54 -07001296 {
1297 stream_free (peer->work);
1298 peer->work = NULL;
1299 }
1300
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00001301 if (peer->scratch)
Daniel Walton363c9032015-10-21 06:42:54 -07001302 {
1303 stream_free(peer->scratch);
1304 peer->scratch = NULL;
1305 }
Paul Jakma18937402006-07-27 19:05:12 +00001306
paul718e3742002-12-13 20:15:29 +00001307 /* Local and remote addresses. */
1308 if (peer->su_local)
Daniel Walton363c9032015-10-21 06:42:54 -07001309 {
1310 sockunion_free (peer->su_local);
1311 peer->su_local = NULL;
1312 }
1313
paul718e3742002-12-13 20:15:29 +00001314 if (peer->su_remote)
Daniel Walton363c9032015-10-21 06:42:54 -07001315 {
1316 sockunion_free (peer->su_remote);
1317 peer->su_remote = NULL;
1318 }
paul200df112005-06-01 11:17:05 +00001319
paul718e3742002-12-13 20:15:29 +00001320 /* Free filter related memory. */
1321 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1322 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1323 {
1324 filter = &peer->filter[afi][safi];
1325
1326 for (i = FILTER_IN; i < FILTER_MAX; i++)
1327 {
1328 if (filter->dlist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001329 {
1330 free(filter->dlist[i].name);
1331 filter->dlist[i].name = NULL;
1332 }
1333
paul718e3742002-12-13 20:15:29 +00001334 if (filter->plist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001335 {
1336 free(filter->plist[i].name);
1337 filter->plist[i].name = NULL;
1338 }
1339
paul718e3742002-12-13 20:15:29 +00001340 if (filter->aslist[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001341 {
1342 free(filter->aslist[i].name);
1343 filter->aslist[i].name = NULL;
1344 }
paul200df112005-06-01 11:17:05 +00001345 }
Daniel Walton363c9032015-10-21 06:42:54 -07001346
paul200df112005-06-01 11:17:05 +00001347 for (i = RMAP_IN; i < RMAP_MAX; i++)
1348 {
paul718e3742002-12-13 20:15:29 +00001349 if (filter->map[i].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001350 {
1351 free (filter->map[i].name);
1352 filter->map[i].name = NULL;
1353 }
paul718e3742002-12-13 20:15:29 +00001354 }
1355
1356 if (filter->usmap.name)
Daniel Walton363c9032015-10-21 06:42:54 -07001357 {
1358 free (filter->usmap.name);
1359 filter->usmap.name = NULL;
1360 }
paul718e3742002-12-13 20:15:29 +00001361
1362 if (peer->default_rmap[afi][safi].name)
Daniel Walton363c9032015-10-21 06:42:54 -07001363 {
1364 free (peer->default_rmap[afi][safi].name);
1365 peer->default_rmap[afi][safi].name = NULL;
1366 }
paul718e3742002-12-13 20:15:29 +00001367 }
paul200df112005-06-01 11:17:05 +00001368
1369 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001370
1371 return 0;
1372}
David Lamparter6b0655a2014-06-04 06:53:35 +02001373
paul94f2b392005-06-28 12:44:16 +00001374static int
paul718e3742002-12-13 20:15:29 +00001375peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1376{
1377 return strcmp (g1->name, g2->name);
1378}
1379
1380/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001381static int
paul718e3742002-12-13 20:15:29 +00001382peer_group_active (struct peer *peer)
1383{
1384 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1385 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1386 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1387 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1388 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1389 return 1;
1390 return 0;
1391}
1392
1393/* Peer group cofiguration. */
1394static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001395peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001396{
1397 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1398 sizeof (struct peer_group));
1399}
1400
paul94f2b392005-06-28 12:44:16 +00001401static void
paul718e3742002-12-13 20:15:29 +00001402peer_group_free (struct peer_group *group)
1403{
1404 XFREE (MTYPE_PEER_GROUP, group);
1405}
1406
1407struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001408peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001409{
1410 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001411 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001412
paul1eb8ef22005-04-07 07:30:20 +00001413 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001414 {
1415 if (strcmp (group->name, name) == 0)
1416 return group;
1417 }
1418 return NULL;
1419}
1420
1421struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001422peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001423{
1424 struct peer_group *group;
1425
1426 group = peer_group_lookup (bgp, name);
1427 if (group)
1428 return group;
1429
1430 group = peer_group_new ();
1431 group->bgp = bgp;
1432 group->name = strdup (name);
1433 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001434 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001435 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1436 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001437 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001438 group->conf->group = group;
1439 group->conf->as = 0;
1440 group->conf->ttl = 1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001441 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001442 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1443 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1444 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1445 group->conf->keepalive = 0;
1446 group->conf->holdtime = 0;
1447 group->conf->connect = 0;
1448 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1449 listnode_add_sort (bgp->group, group);
1450
1451 return 0;
1452}
1453
paul94f2b392005-06-28 12:44:16 +00001454static void
paul718e3742002-12-13 20:15:29 +00001455peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1456 afi_t afi, safi_t safi)
1457{
1458 int in = FILTER_IN;
1459 int out = FILTER_OUT;
1460 struct peer *conf;
1461 struct bgp_filter *pfilter;
1462 struct bgp_filter *gfilter;
1463
1464 conf = group->conf;
1465 pfilter = &peer->filter[afi][safi];
1466 gfilter = &conf->filter[afi][safi];
1467
1468 /* remote-as */
1469 if (conf->as)
1470 peer->as = conf->as;
1471
1472 /* remote-as */
1473 if (conf->change_local_as)
1474 peer->change_local_as = conf->change_local_as;
1475
1476 /* TTL */
1477 peer->ttl = conf->ttl;
1478
Nick Hilliardfa411a22011-03-23 15:33:17 +00001479 /* GTSM hops */
1480 peer->gtsm_hops = conf->gtsm_hops;
1481
paul718e3742002-12-13 20:15:29 +00001482 /* Weight */
1483 peer->weight = conf->weight;
1484
1485 /* peer flags apply */
1486 peer->flags = conf->flags;
1487 /* peer af_flags apply */
1488 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1489 /* peer config apply */
1490 peer->config = conf->config;
1491
1492 /* peer timers apply */
1493 peer->holdtime = conf->holdtime;
1494 peer->keepalive = conf->keepalive;
1495 peer->connect = conf->connect;
1496 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1497 peer->v_connect = conf->connect;
1498 else
1499 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1500
1501 /* advertisement-interval reset */
1502 if (peer_sort (peer) == BGP_PEER_IBGP)
1503 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1504 else
1505 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1506
Paul Jakma0df7c912008-07-21 21:02:49 +00001507 /* password apply */
Roman Hoog Antink0e4303d2013-01-18 13:52:03 +01001508 if (conf->password && !peer->password)
Paul Jakma0df7c912008-07-21 21:02:49 +00001509 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
Paul Jakma0df7c912008-07-21 21:02:49 +00001510
1511 bgp_md5_set (peer);
1512
paul718e3742002-12-13 20:15:29 +00001513 /* maximum-prefix */
1514 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001515 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001516 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001517
1518 /* allowas-in */
1519 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1520
paulfee0f4c2004-09-13 05:12:46 +00001521 /* route-server-client */
1522 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1523 {
1524 /* Make peer's RIB point to group's RIB. */
1525 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1526
1527 /* Import policy. */
1528 if (pfilter->map[RMAP_IMPORT].name)
1529 free (pfilter->map[RMAP_IMPORT].name);
1530 if (gfilter->map[RMAP_IMPORT].name)
1531 {
1532 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1533 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1534 }
1535 else
1536 {
1537 pfilter->map[RMAP_IMPORT].name = NULL;
1538 pfilter->map[RMAP_IMPORT].map = NULL;
1539 }
1540
1541 /* Export policy. */
1542 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1543 {
1544 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1545 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1546 }
1547 }
1548
paul718e3742002-12-13 20:15:29 +00001549 /* default-originate route-map */
1550 if (conf->default_rmap[afi][safi].name)
1551 {
1552 if (peer->default_rmap[afi][safi].name)
1553 free (peer->default_rmap[afi][safi].name);
1554 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1555 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1556 }
1557
1558 /* update-source apply */
1559 if (conf->update_source)
1560 {
1561 if (peer->update_source)
1562 sockunion_free (peer->update_source);
1563 if (peer->update_if)
1564 {
1565 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1566 peer->update_if = NULL;
1567 }
1568 peer->update_source = sockunion_dup (conf->update_source);
1569 }
1570 else if (conf->update_if)
1571 {
1572 if (peer->update_if)
1573 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1574 if (peer->update_source)
1575 {
1576 sockunion_free (peer->update_source);
1577 peer->update_source = NULL;
1578 }
1579 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1580 }
1581
1582 /* inbound filter apply */
1583 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1584 {
1585 if (pfilter->dlist[in].name)
1586 free (pfilter->dlist[in].name);
1587 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1588 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1589 }
1590 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1591 {
1592 if (pfilter->plist[in].name)
1593 free (pfilter->plist[in].name);
1594 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1595 pfilter->plist[in].plist = gfilter->plist[in].plist;
1596 }
1597 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1598 {
1599 if (pfilter->aslist[in].name)
1600 free (pfilter->aslist[in].name);
1601 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1602 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1603 }
paulfee0f4c2004-09-13 05:12:46 +00001604 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001605 {
paulfee0f4c2004-09-13 05:12:46 +00001606 if (pfilter->map[RMAP_IN].name)
1607 free (pfilter->map[RMAP_IN].name);
1608 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1609 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001610 }
1611
1612 /* outbound filter apply */
1613 if (gfilter->dlist[out].name)
1614 {
1615 if (pfilter->dlist[out].name)
1616 free (pfilter->dlist[out].name);
1617 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1618 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1619 }
1620 else
1621 {
1622 if (pfilter->dlist[out].name)
1623 free (pfilter->dlist[out].name);
1624 pfilter->dlist[out].name = NULL;
1625 pfilter->dlist[out].alist = NULL;
1626 }
1627 if (gfilter->plist[out].name)
1628 {
1629 if (pfilter->plist[out].name)
1630 free (pfilter->plist[out].name);
1631 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1632 pfilter->plist[out].plist = gfilter->plist[out].plist;
1633 }
1634 else
1635 {
1636 if (pfilter->plist[out].name)
1637 free (pfilter->plist[out].name);
1638 pfilter->plist[out].name = NULL;
1639 pfilter->plist[out].plist = NULL;
1640 }
1641 if (gfilter->aslist[out].name)
1642 {
1643 if (pfilter->aslist[out].name)
1644 free (pfilter->aslist[out].name);
1645 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1646 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1647 }
1648 else
1649 {
1650 if (pfilter->aslist[out].name)
1651 free (pfilter->aslist[out].name);
1652 pfilter->aslist[out].name = NULL;
1653 pfilter->aslist[out].aslist = NULL;
1654 }
paulfee0f4c2004-09-13 05:12:46 +00001655 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001656 {
paulfee0f4c2004-09-13 05:12:46 +00001657 if (pfilter->map[RMAP_OUT].name)
1658 free (pfilter->map[RMAP_OUT].name);
1659 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1660 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001661 }
1662 else
1663 {
paulfee0f4c2004-09-13 05:12:46 +00001664 if (pfilter->map[RMAP_OUT].name)
1665 free (pfilter->map[RMAP_OUT].name);
1666 pfilter->map[RMAP_OUT].name = NULL;
1667 pfilter->map[RMAP_OUT].map = NULL;
1668 }
1669
1670 /* RS-client's import/export route-maps. */
1671 if (gfilter->map[RMAP_IMPORT].name)
1672 {
1673 if (pfilter->map[RMAP_IMPORT].name)
1674 free (pfilter->map[RMAP_IMPORT].name);
1675 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1676 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1677 }
1678 else
1679 {
1680 if (pfilter->map[RMAP_IMPORT].name)
1681 free (pfilter->map[RMAP_IMPORT].name);
1682 pfilter->map[RMAP_IMPORT].name = NULL;
1683 pfilter->map[RMAP_IMPORT].map = NULL;
1684 }
1685 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1686 {
1687 if (pfilter->map[RMAP_EXPORT].name)
1688 free (pfilter->map[RMAP_EXPORT].name);
1689 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1690 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001691 }
1692
1693 if (gfilter->usmap.name)
1694 {
1695 if (pfilter->usmap.name)
1696 free (pfilter->usmap.name);
1697 pfilter->usmap.name = strdup (gfilter->usmap.name);
1698 pfilter->usmap.map = gfilter->usmap.map;
1699 }
1700 else
1701 {
1702 if (pfilter->usmap.name)
1703 free (pfilter->usmap.name);
1704 pfilter->usmap.name = NULL;
1705 pfilter->usmap.map = NULL;
1706 }
1707}
1708
1709/* Peer group's remote AS configuration. */
1710int
paulfd79ac92004-10-13 05:06:08 +00001711peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001712{
1713 struct peer_group *group;
1714 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001715 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001716
1717 group = peer_group_lookup (bgp, group_name);
1718 if (! group)
1719 return -1;
1720
1721 if (group->conf->as == *as)
1722 return 0;
1723
1724 /* When we setup peer-group AS number all peer group member's AS
1725 number must be updated to same number. */
1726 peer_as_change (group->conf, *as);
1727
paul1eb8ef22005-04-07 07:30:20 +00001728 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001729 {
1730 if (peer->as != *as)
1731 peer_as_change (peer, *as);
1732 }
1733
1734 return 0;
1735}
1736
1737int
1738peer_group_delete (struct peer_group *group)
1739{
1740 struct bgp *bgp;
1741 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001742 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001743
1744 bgp = group->bgp;
1745
paul1eb8ef22005-04-07 07:30:20 +00001746 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001747 {
paul718e3742002-12-13 20:15:29 +00001748 peer_delete (peer);
1749 }
1750 list_delete (group->peer);
1751
1752 free (group->name);
1753 group->name = NULL;
1754
1755 group->conf->group = NULL;
1756 peer_delete (group->conf);
1757
1758 /* Delete from all peer_group list. */
1759 listnode_delete (bgp->group, group);
1760
1761 peer_group_free (group);
1762
1763 return 0;
1764}
1765
1766int
1767peer_group_remote_as_delete (struct peer_group *group)
1768{
1769 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001770 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001771
1772 if (! group->conf->as)
1773 return 0;
1774
paul1eb8ef22005-04-07 07:30:20 +00001775 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001776 {
paul718e3742002-12-13 20:15:29 +00001777 peer_delete (peer);
1778 }
1779 list_delete_all_node (group->peer);
1780
1781 group->conf->as = 0;
1782
1783 return 0;
1784}
1785
1786/* Bind specified peer to peer group. */
1787int
1788peer_group_bind (struct bgp *bgp, union sockunion *su,
1789 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1790{
1791 struct peer *peer;
1792 int first_member = 0;
1793
1794 /* Check peer group's address family. */
1795 if (! group->conf->afc[afi][safi])
1796 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1797
1798 /* Lookup the peer. */
1799 peer = peer_lookup (bgp, su);
1800
1801 /* Create a new peer. */
1802 if (! peer)
1803 {
1804 if (! group->conf->as)
1805 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1806
1807 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1808 peer->group = group;
1809 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001810
Paul Jakmaca058a32006-09-14 02:58:49 +00001811 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001812 listnode_add (group->peer, peer);
1813 peer_group2peer_config_copy (group, peer, afi, safi);
1814
1815 return 0;
1816 }
1817
1818 /* When the peer already belongs to peer group, check the consistency. */
1819 if (peer->af_group[afi][safi])
1820 {
1821 if (strcmp (peer->group->name, group->name) != 0)
1822 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1823
1824 return 0;
1825 }
1826
1827 /* Check current peer group configuration. */
1828 if (peer_group_active (peer)
1829 && strcmp (peer->group->name, group->name) != 0)
1830 return BGP_ERR_PEER_GROUP_MISMATCH;
1831
1832 if (! group->conf->as)
1833 {
1834 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1835 && peer_sort (group->conf) != peer_sort (peer))
1836 {
1837 if (as)
1838 *as = peer->as;
1839 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1840 }
1841
1842 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1843 first_member = 1;
1844 }
1845
1846 peer->af_group[afi][safi] = 1;
1847 peer->afc[afi][safi] = 1;
1848 if (! peer->group)
1849 {
1850 peer->group = group;
paul200df112005-06-01 11:17:05 +00001851
Paul Jakmaca058a32006-09-14 02:58:49 +00001852 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001853 listnode_add (group->peer, peer);
1854 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001855 else
1856 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001857
1858 if (first_member)
1859 {
1860 /* Advertisement-interval reset */
1861 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1862 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1863 else
1864 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1865
1866 /* ebgp-multihop reset */
1867 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1868 group->conf->ttl = 255;
1869
1870 /* local-as reset */
1871 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1872 {
1873 group->conf->change_local_as = 0;
1874 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001875 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001876 }
1877 }
paulfee0f4c2004-09-13 05:12:46 +00001878
1879 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1880 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001881 struct listnode *pn;
1882
paulfee0f4c2004-09-13 05:12:46 +00001883 /* If it's not configured as RSERVER_CLIENT in any other address
1884 family, without being member of a peer_group, remove it from
1885 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001886 if (! peer_rsclient_active (peer)
1887 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001888 {
1889 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001890 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001891
1892 /* Clear our own rsclient rib for this afi/safi. */
1893 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001894 }
paulfee0f4c2004-09-13 05:12:46 +00001895
Paul Jakmab608d5b2008-07-02 02:12:07 +00001896 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001897
1898 /* Import policy. */
1899 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1900 {
1901 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1902 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1903 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1904 }
1905
1906 /* Export policy. */
1907 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1908 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1909 {
1910 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1911 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1912 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1913 }
1914 }
1915
paul718e3742002-12-13 20:15:29 +00001916 peer_group2peer_config_copy (group, peer, afi, safi);
1917
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001918 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001919 {
1920 peer->last_reset = PEER_DOWN_RMAP_BIND;
1921 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1922 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1923 }
paul718e3742002-12-13 20:15:29 +00001924 else
1925 BGP_EVENT_ADD (peer, BGP_Stop);
1926
1927 return 0;
1928}
1929
1930int
1931peer_group_unbind (struct bgp *bgp, struct peer *peer,
1932 struct peer_group *group, afi_t afi, safi_t safi)
1933{
1934 if (! peer->af_group[afi][safi])
1935 return 0;
1936
1937 if (group != peer->group)
1938 return BGP_ERR_PEER_GROUP_MISMATCH;
1939
1940 peer->af_group[afi][safi] = 0;
1941 peer->afc[afi][safi] = 0;
1942 peer_af_flag_reset (peer, afi, safi);
1943
paulfee0f4c2004-09-13 05:12:46 +00001944 if (peer->rib[afi][safi])
1945 peer->rib[afi][safi] = NULL;
1946
paul718e3742002-12-13 20:15:29 +00001947 if (! peer_group_active (peer))
1948 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001949 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001950 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001951 listnode_delete (group->peer, peer);
1952 peer->group = NULL;
1953 if (group->conf->as)
1954 {
1955 peer_delete (peer);
1956 return 0;
1957 }
1958 peer_global_config_reset (peer);
1959 }
1960
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001961 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001962 {
1963 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1964 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1965 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1966 }
paul718e3742002-12-13 20:15:29 +00001967 else
1968 BGP_EVENT_ADD (peer, BGP_Stop);
1969
1970 return 0;
1971}
David Lamparter6b0655a2014-06-04 06:53:35 +02001972
Vipin Kumardd49eb12014-09-30 14:36:38 -07001973
1974static int
1975bgp_startup_timer_expire (struct thread *thread)
1976{
1977 struct bgp *bgp;
1978
1979 bgp = THREAD_ARG (thread);
1980 bgp->t_startup = NULL;
1981
1982 return 0;
1983}
1984
paul718e3742002-12-13 20:15:29 +00001985/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001986static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001987bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001988{
1989 struct bgp *bgp;
1990 afi_t afi;
1991 safi_t safi;
1992
paul200df112005-06-01 11:17:05 +00001993 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1994 return NULL;
1995
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07001996 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00001997 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00001998 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00001999
2000 bgp->peer = list_new ();
2001 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
2002
2003 bgp->group = list_new ();
2004 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
2005
paulfee0f4c2004-09-13 05:12:46 +00002006 bgp->rsclient = list_new ();
2007 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
2008
paul718e3742002-12-13 20:15:29 +00002009 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2010 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2011 {
Paul Jakma64e580a2006-02-21 01:09:01 +00002012 bgp->route[afi][safi] = bgp_table_init (afi, safi);
2013 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
2014 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07002015 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
2016 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00002017 }
2018
2019 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
2020 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
2021 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00002022 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
2023 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07002024 bgp_flag_set (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES);
paul718e3742002-12-13 20:15:29 +00002025
2026 bgp->as = *as;
2027
2028 if (name)
2029 bgp->name = strdup (name);
2030
Donald Sharp774914f2015-10-14 08:50:39 -04002031 THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire,
Vipin Kumardd49eb12014-09-30 14:36:38 -07002032 bgp, bgp->restart_time);
2033
paul718e3742002-12-13 20:15:29 +00002034 return bgp;
2035}
2036
2037/* Return first entry of BGP. */
2038struct bgp *
paul94f2b392005-06-28 12:44:16 +00002039bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00002040{
Lou Berger056f3762013-04-10 12:30:04 -07002041 if (bm && bm->bgp && bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00002042 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00002043 return NULL;
2044}
2045
2046/* Lookup BGP entry. */
2047struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002048bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00002049{
2050 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002051 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002052
paul1eb8ef22005-04-07 07:30:20 +00002053 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002054 if (bgp->as == as
2055 && ((bgp->name == NULL && name == NULL)
2056 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
2057 return bgp;
2058 return NULL;
2059}
2060
2061/* Lookup BGP structure by view name. */
2062struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002063bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002064{
2065 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002066 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002067
paul1eb8ef22005-04-07 07:30:20 +00002068 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002069 if ((bgp->name == NULL && name == NULL)
2070 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2071 return bgp;
2072 return NULL;
2073}
2074
2075/* Called from VTY commands. */
2076int
paulfd79ac92004-10-13 05:06:08 +00002077bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002078{
2079 struct bgp *bgp;
2080
2081 /* Multiple instance check. */
2082 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2083 {
2084 if (name)
2085 bgp = bgp_lookup_by_name (name);
2086 else
2087 bgp = bgp_get_default ();
2088
2089 /* Already exists. */
2090 if (bgp)
2091 {
2092 if (bgp->as != *as)
2093 {
2094 *as = bgp->as;
2095 return BGP_ERR_INSTANCE_MISMATCH;
2096 }
2097 *bgp_val = bgp;
2098 return 0;
2099 }
2100 }
2101 else
2102 {
2103 /* BGP instance name can not be specified for single instance. */
2104 if (name)
2105 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2106
2107 /* Get default BGP structure if exists. */
2108 bgp = bgp_get_default ();
2109
2110 if (bgp)
2111 {
2112 if (bgp->as != *as)
2113 {
2114 *as = bgp->as;
2115 return BGP_ERR_AS_MISMATCH;
2116 }
2117 *bgp_val = bgp;
2118 return 0;
2119 }
2120 }
2121
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002122 bgp = bgp_create (as, name);
2123 bgp_router_id_set(bgp, &router_id_zebra);
2124 *bgp_val = bgp;
2125
Paul Jakmaad12dde2012-06-13 22:50:07 +01002126 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002127 if (list_isempty(bm->bgp)
2128 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002129 {
2130 if (bgp_socket (bm->port, bm->address) < 0)
2131 return BGP_ERR_INVALID_VALUE;
2132 }
2133
paul718e3742002-12-13 20:15:29 +00002134 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002135
2136 return 0;
2137}
2138
2139/* Delete BGP instance. */
2140int
2141bgp_delete (struct bgp *bgp)
2142{
2143 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002144 struct peer_group *group;
Denil Vira57cd5e72015-08-10 12:46:14 -07002145 struct listnode *node, *pnode;
2146 struct listnode *next, *pnext;
paul718e3742002-12-13 20:15:29 +00002147 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002148 int i;
2149
David Lampartercffe7802014-12-07 03:27:13 +01002150 THREAD_OFF (bgp->t_startup);
2151
paul718e3742002-12-13 20:15:29 +00002152 /* Delete static route. */
2153 bgp_static_delete (bgp);
2154
2155 /* Unset redistribution. */
2156 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2157 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2158 if (i != ZEBRA_ROUTE_BGP)
2159 bgp_redistribute_unset (bgp, afi, i);
2160
paul1eb8ef22005-04-07 07:30:20 +00002161 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002162 {
2163 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2164 {
2165 /* Send notify to remote peer. */
2166 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2167 }
2168
2169 peer_delete (peer);
2170 }
paul718e3742002-12-13 20:15:29 +00002171
Chris Caputo228da422009-07-18 05:44:03 +00002172 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002173 {
Denil Vira57cd5e72015-08-10 12:46:14 -07002174 for (ALL_LIST_ELEMENTS (group->peer, pnode, pnext, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002175 {
2176 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2177 {
2178 /* Send notify to remote peer. */
2179 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2180 }
2181 }
2182 peer_group_delete (group);
2183 }
Chris Caputo228da422009-07-18 05:44:03 +00002184
2185 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002186
2187 if (bgp->peer_self) {
2188 peer_delete(bgp->peer_self);
2189 bgp->peer_self = NULL;
2190 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002191
2192 /* Remove visibility via the master list - there may however still be
2193 * routes to be processed still referencing the struct bgp.
2194 */
2195 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002196 if (list_isempty(bm->bgp))
2197 bgp_close ();
2198
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002199 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002200
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002201 return 0;
2202}
2203
2204static void bgp_free (struct bgp *);
2205
2206void
2207bgp_lock (struct bgp *bgp)
2208{
2209 ++bgp->lock;
2210}
2211
2212void
2213bgp_unlock(struct bgp *bgp)
2214{
Chris Caputo228da422009-07-18 05:44:03 +00002215 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002216 if (--bgp->lock == 0)
2217 bgp_free (bgp);
2218}
2219
2220static void
2221bgp_free (struct bgp *bgp)
2222{
2223 afi_t afi;
2224 safi_t safi;
2225
2226 list_delete (bgp->group);
2227 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002228 list_delete (bgp->rsclient);
2229
paul718e3742002-12-13 20:15:29 +00002230 if (bgp->name)
2231 free (bgp->name);
2232
2233 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2234 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2235 {
2236 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002237 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002238 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002239 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002240 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002241 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002242 }
2243 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002244}
David Lamparter6b0655a2014-06-04 06:53:35 +02002245
paul718e3742002-12-13 20:15:29 +00002246struct peer *
2247peer_lookup (struct bgp *bgp, union sockunion *su)
2248{
2249 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002250 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002251
Steve Hillfc4dc592009-07-28 17:54:35 +01002252 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002253 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002254 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2255 if (sockunion_same (&peer->su, su)
2256 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2257 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002258 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002259 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002260 {
2261 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002262
Paul Jakma2158ad22009-07-28 18:10:55 +01002263 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2264 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2265 if (sockunion_same (&peer->su, su)
2266 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2267 return peer;
paul718e3742002-12-13 20:15:29 +00002268 }
2269 return NULL;
2270}
2271
2272struct peer *
2273peer_lookup_with_open (union sockunion *su, as_t remote_as,
2274 struct in_addr *remote_id, int *as)
2275{
2276 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002277 struct listnode *node;
2278 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002279 struct bgp *bgp;
2280
Steve Hillfc4dc592009-07-28 17:54:35 +01002281 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002282 return NULL;
2283
Paul Jakma9d878772009-08-05 16:25:16 +01002284 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002285 {
Paul Jakma9d878772009-08-05 16:25:16 +01002286 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2287 {
2288 if (sockunion_same (&peer->su, su)
2289 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2290 {
2291 if (peer->as == remote_as
2292 && peer->remote_id.s_addr == remote_id->s_addr)
2293 return peer;
2294 if (peer->as == remote_as)
2295 *as = 1;
2296 }
2297 }
2298
2299 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2300 {
2301 if (sockunion_same (&peer->su, su)
2302 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2303 {
2304 if (peer->as == remote_as
2305 && peer->remote_id.s_addr == 0)
2306 return peer;
2307 if (peer->as == remote_as)
2308 *as = 1;
2309 }
2310 }
paul718e3742002-12-13 20:15:29 +00002311 }
2312 return NULL;
2313}
David Lamparter6b0655a2014-06-04 06:53:35 +02002314
paul718e3742002-12-13 20:15:29 +00002315/* If peer is configured at least one address family return 1. */
2316int
2317peer_active (struct peer *peer)
2318{
2319 if (peer->afc[AFI_IP][SAFI_UNICAST]
2320 || peer->afc[AFI_IP][SAFI_MULTICAST]
2321 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2322 || peer->afc[AFI_IP6][SAFI_UNICAST]
2323 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2324 return 1;
2325 return 0;
2326}
2327
2328/* If peer is negotiated at least one address family return 1. */
2329int
2330peer_active_nego (struct peer *peer)
2331{
2332 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2333 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2334 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2335 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2336 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2337 return 1;
2338 return 0;
2339}
David Lamparter6b0655a2014-06-04 06:53:35 +02002340
paul718e3742002-12-13 20:15:29 +00002341/* peer_flag_change_type. */
2342enum peer_change_type
2343{
2344 peer_change_none,
2345 peer_change_reset,
2346 peer_change_reset_in,
2347 peer_change_reset_out,
2348};
2349
paul94f2b392005-06-28 12:44:16 +00002350static void
paul718e3742002-12-13 20:15:29 +00002351peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2352 enum peer_change_type type)
2353{
2354 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2355 return;
2356
Stephen Hemmingerd9d4ae52010-01-13 00:32:39 +00002357 if (peer->status != Established)
2358 return;
2359
paul718e3742002-12-13 20:15:29 +00002360 if (type == peer_change_reset)
2361 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2362 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2363 else if (type == peer_change_reset_in)
2364 {
2365 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2366 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2367 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2368 else
2369 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2370 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2371 }
2372 else if (type == peer_change_reset_out)
2373 bgp_announce_route (peer, afi, safi);
2374}
2375
2376struct peer_flag_action
2377{
2378 /* Peer's flag. */
2379 u_int32_t flag;
2380
2381 /* This flag can be set for peer-group member. */
2382 u_char not_for_member;
2383
2384 /* Action when the flag is changed. */
2385 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002386
2387 /* Peer down cause */
2388 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002389};
2390
Stephen Hemminger03621952009-07-21 16:27:20 -07002391static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002392 {
2393 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2394 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2395 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2396 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2397 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002398 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002399 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002400 { 0, 0, 0 }
2401 };
2402
Stephen Hemminger03621952009-07-21 16:27:20 -07002403static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002404 {
2405 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2406 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2407 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2408 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2409 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2410 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2411 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2412 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2413 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2414 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2415 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2416 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2417 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002418 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
Timo Teräs9e7a53c2014-04-24 10:22:37 +03002419 { PEER_FLAG_NEXTHOP_SELF_ALL, 1, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002420 { 0, 0, 0 }
2421 };
2422
2423/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002424static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002425peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002426 struct peer_flag_action *action, u_int32_t flag)
2427{
2428 int i;
2429 int found = 0;
2430 int reset_in = 0;
2431 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002432 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002433
2434 /* Check peer's frag action. */
2435 for (i = 0; i < size; i++)
2436 {
2437 match = &action_list[i];
2438
2439 if (match->flag == 0)
2440 break;
2441
2442 if (match->flag & flag)
2443 {
2444 found = 1;
2445
2446 if (match->type == peer_change_reset_in)
2447 reset_in = 1;
2448 if (match->type == peer_change_reset_out)
2449 reset_out = 1;
2450 if (match->type == peer_change_reset)
2451 {
2452 reset_in = 1;
2453 reset_out = 1;
2454 }
2455 if (match->not_for_member)
2456 action->not_for_member = 1;
2457 }
2458 }
2459
2460 /* Set peer clear type. */
2461 if (reset_in && reset_out)
2462 action->type = peer_change_reset;
2463 else if (reset_in)
2464 action->type = peer_change_reset_in;
2465 else if (reset_out)
2466 action->type = peer_change_reset_out;
2467 else
2468 action->type = peer_change_none;
2469
2470 return found;
2471}
2472
paul94f2b392005-06-28 12:44:16 +00002473static void
paul718e3742002-12-13 20:15:29 +00002474peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2475{
2476 if (flag == PEER_FLAG_SHUTDOWN)
2477 {
2478 if (CHECK_FLAG (peer->flags, flag))
2479 {
hasso93406d82005-02-02 14:40:33 +00002480 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2481 peer_nsf_stop (peer);
2482
hasso0a486e52005-02-01 20:57:17 +00002483 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2484 if (peer->t_pmax_restart)
2485 {
2486 BGP_TIMER_OFF (peer->t_pmax_restart);
2487 if (BGP_DEBUG (events, EVENTS))
2488 zlog_debug ("%s Maximum-prefix restart timer canceled",
2489 peer->host);
2490 }
2491
hasso93406d82005-02-02 14:40:33 +00002492 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2493 peer_nsf_stop (peer);
2494
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002495 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002496 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2497 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2498 else
2499 BGP_EVENT_ADD (peer, BGP_Stop);
2500 }
2501 else
2502 {
2503 peer->v_start = BGP_INIT_START_TIMER;
2504 BGP_EVENT_ADD (peer, BGP_Stop);
2505 }
2506 }
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002507 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002508 {
hassoc9502432005-02-01 22:01:48 +00002509 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2510 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2511 else if (flag == PEER_FLAG_PASSIVE)
2512 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002513 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002514 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002515
hassoc9502432005-02-01 22:01:48 +00002516 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2517 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002518 }
2519 else
2520 BGP_EVENT_ADD (peer, BGP_Stop);
2521}
2522
2523/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002524static int
paul718e3742002-12-13 20:15:29 +00002525peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2526{
2527 int found;
2528 int size;
2529 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002530 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002531 struct peer_flag_action action;
2532
2533 memset (&action, 0, sizeof (struct peer_flag_action));
2534 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2535
2536 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2537
2538 /* No flag action is found. */
2539 if (! found)
2540 return BGP_ERR_INVALID_FLAG;
2541
2542 /* Not for peer-group member. */
2543 if (action.not_for_member && peer_group_active (peer))
2544 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2545
2546 /* When unset the peer-group member's flag we have to check
2547 peer-group configuration. */
2548 if (! set && peer_group_active (peer))
2549 if (CHECK_FLAG (peer->group->conf->flags, flag))
2550 {
2551 if (flag == PEER_FLAG_SHUTDOWN)
2552 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2553 else
2554 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2555 }
2556
2557 /* Flag conflict check. */
2558 if (set
2559 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2560 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2561 return BGP_ERR_PEER_FLAG_CONFLICT;
2562
2563 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2564 {
2565 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2566 return 0;
2567 if (! set && ! CHECK_FLAG (peer->flags, flag))
2568 return 0;
2569 }
2570
2571 if (set)
2572 SET_FLAG (peer->flags, flag);
2573 else
2574 UNSET_FLAG (peer->flags, flag);
2575
2576 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2577 {
2578 if (action.type == peer_change_reset)
2579 peer_flag_modify_action (peer, flag);
2580
2581 return 0;
2582 }
2583
2584 /* peer-group member updates. */
2585 group = peer->group;
2586
paul1eb8ef22005-04-07 07:30:20 +00002587 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002588 {
2589 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2590 continue;
2591
2592 if (! set && ! CHECK_FLAG (peer->flags, flag))
2593 continue;
2594
2595 if (set)
2596 SET_FLAG (peer->flags, flag);
2597 else
2598 UNSET_FLAG (peer->flags, flag);
2599
2600 if (action.type == peer_change_reset)
2601 peer_flag_modify_action (peer, flag);
2602 }
2603 return 0;
2604}
2605
2606int
2607peer_flag_set (struct peer *peer, u_int32_t flag)
2608{
2609 return peer_flag_modify (peer, flag, 1);
2610}
2611
2612int
2613peer_flag_unset (struct peer *peer, u_int32_t flag)
2614{
2615 return peer_flag_modify (peer, flag, 0);
2616}
2617
paul94f2b392005-06-28 12:44:16 +00002618static int
paul718e3742002-12-13 20:15:29 +00002619peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2620{
2621 if (peer->af_group[afi][safi])
2622 return 1;
2623 return 0;
2624}
2625
paul94f2b392005-06-28 12:44:16 +00002626static int
paul718e3742002-12-13 20:15:29 +00002627peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2628 int set)
2629{
2630 int found;
2631 int size;
paul1eb8ef22005-04-07 07:30:20 +00002632 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002633 struct peer_group *group;
2634 struct peer_flag_action action;
2635
2636 memset (&action, 0, sizeof (struct peer_flag_action));
2637 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2638
2639 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2640
2641 /* No flag action is found. */
2642 if (! found)
2643 return BGP_ERR_INVALID_FLAG;
2644
2645 /* Adress family must be activated. */
2646 if (! peer->afc[afi][safi])
2647 return BGP_ERR_PEER_INACTIVE;
2648
2649 /* Not for peer-group member. */
2650 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2651 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2652
2653 /* Spcecial check for reflector client. */
2654 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2655 && peer_sort (peer) != BGP_PEER_IBGP)
2656 return BGP_ERR_NOT_INTERNAL_PEER;
2657
2658 /* Spcecial check for remove-private-AS. */
2659 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2660 && peer_sort (peer) == BGP_PEER_IBGP)
2661 return BGP_ERR_REMOVE_PRIVATE_AS;
2662
2663 /* When unset the peer-group member's flag we have to check
2664 peer-group configuration. */
2665 if (! set && peer->af_group[afi][safi])
2666 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2667 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2668
2669 /* When current flag configuration is same as requested one. */
2670 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2671 {
2672 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2673 return 0;
2674 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2675 return 0;
2676 }
2677
2678 if (set)
2679 SET_FLAG (peer->af_flags[afi][safi], flag);
2680 else
2681 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2682
2683 /* Execute action when peer is established. */
2684 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2685 && peer->status == Established)
2686 {
2687 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2688 bgp_clear_adj_in (peer, afi, safi);
2689 else
hassoe0701b72004-05-20 09:19:34 +00002690 {
2691 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2692 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2693 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2694 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2695 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2696 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2697 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2698 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2699
2700 peer_change_action (peer, afi, safi, action.type);
2701 }
2702
paul718e3742002-12-13 20:15:29 +00002703 }
2704
2705 /* Peer group member updates. */
2706 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2707 {
2708 group = peer->group;
2709
paul1eb8ef22005-04-07 07:30:20 +00002710 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002711 {
2712 if (! peer->af_group[afi][safi])
2713 continue;
2714
2715 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2716 continue;
2717
2718 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2719 continue;
2720
2721 if (set)
2722 SET_FLAG (peer->af_flags[afi][safi], flag);
2723 else
2724 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2725
2726 if (peer->status == Established)
2727 {
2728 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2729 bgp_clear_adj_in (peer, afi, safi);
2730 else
hassoe0701b72004-05-20 09:19:34 +00002731 {
2732 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2733 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2734 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2735 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2736 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2737 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2738 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2739 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2740
2741 peer_change_action (peer, afi, safi, action.type);
2742 }
paul718e3742002-12-13 20:15:29 +00002743 }
2744 }
2745 }
2746 return 0;
2747}
2748
2749int
2750peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2751{
2752 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2753}
2754
2755int
2756peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2757{
2758 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2759}
David Lamparter6b0655a2014-06-04 06:53:35 +02002760
paul718e3742002-12-13 20:15:29 +00002761/* EBGP multihop configuration. */
2762int
2763peer_ebgp_multihop_set (struct peer *peer, int ttl)
2764{
2765 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002766 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002767 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002768
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002769 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002770 return 0;
2771
Nick Hilliardfa411a22011-03-23 15:33:17 +00002772 /* see comment in peer_ttl_security_hops_set() */
2773 if (ttl != MAXTTL)
2774 {
2775 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2776 {
2777 group = peer->group;
2778 if (group->conf->gtsm_hops != 0)
2779 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2780
2781 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2782 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002783 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002784 continue;
2785
2786 if (peer1->gtsm_hops != 0)
2787 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2788 }
2789 }
2790 else
2791 {
2792 if (peer->gtsm_hops != 0)
2793 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2794 }
2795 }
2796
paul718e3742002-12-13 20:15:29 +00002797 peer->ttl = ttl;
2798
2799 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2800 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002801 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002802 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002803 }
2804 else
2805 {
2806 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002807 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002808 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002809 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002810 continue;
paul718e3742002-12-13 20:15:29 +00002811
pauleb821182004-05-01 08:44:08 +00002812 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002813
pauleb821182004-05-01 08:44:08 +00002814 if (peer->fd >= 0)
2815 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2816 }
paul718e3742002-12-13 20:15:29 +00002817 }
2818 return 0;
2819}
2820
2821int
2822peer_ebgp_multihop_unset (struct peer *peer)
2823{
2824 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002825 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002826
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002827 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002828 return 0;
2829
Nick Hilliardfa411a22011-03-23 15:33:17 +00002830 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2831 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2832
paul718e3742002-12-13 20:15:29 +00002833 if (peer_group_active (peer))
2834 peer->ttl = peer->group->conf->ttl;
2835 else
2836 peer->ttl = 1;
2837
2838 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2839 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002840 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002841 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002842 }
2843 else
2844 {
2845 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002846 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002847 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002848 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002849 continue;
paul718e3742002-12-13 20:15:29 +00002850
pauleb821182004-05-01 08:44:08 +00002851 peer->ttl = 1;
2852
2853 if (peer->fd >= 0)
2854 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2855 }
paul718e3742002-12-13 20:15:29 +00002856 }
2857 return 0;
2858}
David Lamparter6b0655a2014-06-04 06:53:35 +02002859
paul718e3742002-12-13 20:15:29 +00002860/* Neighbor description. */
2861int
2862peer_description_set (struct peer *peer, char *desc)
2863{
2864 if (peer->desc)
2865 XFREE (MTYPE_PEER_DESC, peer->desc);
2866
2867 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2868
2869 return 0;
2870}
2871
2872int
2873peer_description_unset (struct peer *peer)
2874{
2875 if (peer->desc)
2876 XFREE (MTYPE_PEER_DESC, peer->desc);
2877
2878 peer->desc = NULL;
2879
2880 return 0;
2881}
David Lamparter6b0655a2014-06-04 06:53:35 +02002882
paul718e3742002-12-13 20:15:29 +00002883/* Neighbor update-source. */
2884int
paulfd79ac92004-10-13 05:06:08 +00002885peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002886{
2887 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002888 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002889
2890 if (peer->update_if)
2891 {
2892 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2893 && strcmp (peer->update_if, ifname) == 0)
2894 return 0;
2895
2896 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2897 peer->update_if = NULL;
2898 }
2899
2900 if (peer->update_source)
2901 {
2902 sockunion_free (peer->update_source);
2903 peer->update_source = NULL;
2904 }
2905
2906 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2907
2908 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2909 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002910 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002911 {
2912 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2913 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2914 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2915 }
paul718e3742002-12-13 20:15:29 +00002916 else
2917 BGP_EVENT_ADD (peer, BGP_Stop);
2918 return 0;
2919 }
2920
2921 /* peer-group member updates. */
2922 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002923 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002924 {
2925 if (peer->update_if)
2926 {
2927 if (strcmp (peer->update_if, ifname) == 0)
2928 continue;
2929
2930 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2931 peer->update_if = NULL;
2932 }
2933
2934 if (peer->update_source)
2935 {
2936 sockunion_free (peer->update_source);
2937 peer->update_source = NULL;
2938 }
2939
2940 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2941
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002942 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002943 {
2944 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2945 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2946 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2947 }
paul718e3742002-12-13 20:15:29 +00002948 else
2949 BGP_EVENT_ADD (peer, BGP_Stop);
2950 }
2951 return 0;
2952}
2953
2954int
2955peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2956{
2957 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002958 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002959
2960 if (peer->update_source)
2961 {
2962 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2963 && sockunion_cmp (peer->update_source, su) == 0)
2964 return 0;
2965 sockunion_free (peer->update_source);
2966 peer->update_source = NULL;
2967 }
2968
2969 if (peer->update_if)
2970 {
2971 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2972 peer->update_if = NULL;
2973 }
2974
2975 peer->update_source = sockunion_dup (su);
2976
2977 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2978 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002979 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002980 {
2981 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2982 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2983 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2984 }
paul718e3742002-12-13 20:15:29 +00002985 else
2986 BGP_EVENT_ADD (peer, BGP_Stop);
2987 return 0;
2988 }
2989
2990 /* peer-group member updates. */
2991 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002992 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002993 {
2994 if (peer->update_source)
2995 {
2996 if (sockunion_cmp (peer->update_source, su) == 0)
2997 continue;
2998 sockunion_free (peer->update_source);
2999 peer->update_source = NULL;
3000 }
3001
3002 if (peer->update_if)
3003 {
3004 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3005 peer->update_if = NULL;
3006 }
3007
3008 peer->update_source = sockunion_dup (su);
3009
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003010 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003011 {
3012 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3013 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3014 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3015 }
paul718e3742002-12-13 20:15:29 +00003016 else
3017 BGP_EVENT_ADD (peer, BGP_Stop);
3018 }
3019 return 0;
3020}
3021
3022int
3023peer_update_source_unset (struct peer *peer)
3024{
3025 union sockunion *su;
3026 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003027 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003028
3029 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
3030 && ! peer->update_source
3031 && ! peer->update_if)
3032 return 0;
3033
3034 if (peer->update_source)
3035 {
3036 sockunion_free (peer->update_source);
3037 peer->update_source = NULL;
3038 }
3039 if (peer->update_if)
3040 {
3041 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3042 peer->update_if = NULL;
3043 }
3044
3045 if (peer_group_active (peer))
3046 {
3047 group = peer->group;
3048
3049 if (group->conf->update_source)
3050 {
3051 su = sockunion_dup (group->conf->update_source);
3052 peer->update_source = su;
3053 }
3054 else if (group->conf->update_if)
3055 peer->update_if =
3056 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
3057 }
3058
3059 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3060 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003061 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003062 {
3063 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3064 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3065 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3066 }
paul718e3742002-12-13 20:15:29 +00003067 else
3068 BGP_EVENT_ADD (peer, BGP_Stop);
3069 return 0;
3070 }
3071
3072 /* peer-group member updates. */
3073 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003074 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003075 {
3076 if (! peer->update_source && ! peer->update_if)
3077 continue;
3078
3079 if (peer->update_source)
3080 {
3081 sockunion_free (peer->update_source);
3082 peer->update_source = NULL;
3083 }
3084
3085 if (peer->update_if)
3086 {
3087 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3088 peer->update_if = NULL;
3089 }
3090
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003091 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003092 {
3093 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3094 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3095 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3096 }
paul718e3742002-12-13 20:15:29 +00003097 else
3098 BGP_EVENT_ADD (peer, BGP_Stop);
3099 }
3100 return 0;
3101}
David Lamparter6b0655a2014-06-04 06:53:35 +02003102
paul718e3742002-12-13 20:15:29 +00003103int
3104peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003105 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003106{
3107 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003108 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003109
3110 /* Adress family must be activated. */
3111 if (! peer->afc[afi][safi])
3112 return BGP_ERR_PEER_INACTIVE;
3113
3114 /* Default originate can't be used for peer group memeber. */
3115 if (peer_is_group_member (peer, afi, safi))
3116 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3117
3118 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3119 || (rmap && ! peer->default_rmap[afi][safi].name)
3120 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3121 {
3122 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3123
3124 if (rmap)
3125 {
3126 if (peer->default_rmap[afi][safi].name)
3127 free (peer->default_rmap[afi][safi].name);
3128 peer->default_rmap[afi][safi].name = strdup (rmap);
3129 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3130 }
3131 }
3132
3133 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3134 {
3135 if (peer->status == Established && peer->afc_nego[afi][safi])
3136 bgp_default_originate (peer, afi, safi, 0);
3137 return 0;
3138 }
3139
3140 /* peer-group member updates. */
3141 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003142 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003143 {
3144 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3145
3146 if (rmap)
3147 {
3148 if (peer->default_rmap[afi][safi].name)
3149 free (peer->default_rmap[afi][safi].name);
3150 peer->default_rmap[afi][safi].name = strdup (rmap);
3151 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3152 }
3153
3154 if (peer->status == Established && peer->afc_nego[afi][safi])
3155 bgp_default_originate (peer, afi, safi, 0);
3156 }
3157 return 0;
3158}
3159
3160int
3161peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3162{
3163 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003164 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003165
3166 /* Adress family must be activated. */
3167 if (! peer->afc[afi][safi])
3168 return BGP_ERR_PEER_INACTIVE;
3169
3170 /* Default originate can't be used for peer group memeber. */
3171 if (peer_is_group_member (peer, afi, safi))
3172 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3173
3174 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3175 {
3176 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3177
3178 if (peer->default_rmap[afi][safi].name)
3179 free (peer->default_rmap[afi][safi].name);
3180 peer->default_rmap[afi][safi].name = NULL;
3181 peer->default_rmap[afi][safi].map = NULL;
3182 }
3183
3184 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3185 {
3186 if (peer->status == Established && peer->afc_nego[afi][safi])
3187 bgp_default_originate (peer, afi, safi, 1);
3188 return 0;
3189 }
3190
3191 /* peer-group member updates. */
3192 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003193 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003194 {
3195 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3196
3197 if (peer->default_rmap[afi][safi].name)
3198 free (peer->default_rmap[afi][safi].name);
3199 peer->default_rmap[afi][safi].name = NULL;
3200 peer->default_rmap[afi][safi].map = NULL;
3201
3202 if (peer->status == Established && peer->afc_nego[afi][safi])
3203 bgp_default_originate (peer, afi, safi, 1);
3204 }
3205 return 0;
3206}
David Lamparter6b0655a2014-06-04 06:53:35 +02003207
paul718e3742002-12-13 20:15:29 +00003208int
3209peer_port_set (struct peer *peer, u_int16_t port)
3210{
3211 peer->port = port;
3212 return 0;
3213}
3214
3215int
3216peer_port_unset (struct peer *peer)
3217{
3218 peer->port = BGP_PORT_DEFAULT;
3219 return 0;
3220}
David Lamparter6b0655a2014-06-04 06:53:35 +02003221
paul718e3742002-12-13 20:15:29 +00003222/* neighbor weight. */
3223int
3224peer_weight_set (struct peer *peer, u_int16_t weight)
3225{
3226 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003227 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003228
3229 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3230 peer->weight = weight;
3231
3232 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3233 return 0;
3234
3235 /* peer-group member updates. */
3236 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003237 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003238 {
3239 peer->weight = group->conf->weight;
3240 }
3241 return 0;
3242}
3243
3244int
3245peer_weight_unset (struct peer *peer)
3246{
3247 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003248 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003249
3250 /* Set default weight. */
3251 if (peer_group_active (peer))
3252 peer->weight = peer->group->conf->weight;
3253 else
3254 peer->weight = 0;
3255
3256 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3257
3258 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3259 return 0;
3260
3261 /* peer-group member updates. */
3262 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003263 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003264 {
3265 peer->weight = 0;
3266 }
3267 return 0;
3268}
David Lamparter6b0655a2014-06-04 06:53:35 +02003269
paul718e3742002-12-13 20:15:29 +00003270int
3271peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3272{
3273 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003274 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003275
3276 /* Not for peer group memeber. */
3277 if (peer_group_active (peer))
3278 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3279
3280 /* keepalive value check. */
3281 if (keepalive > 65535)
3282 return BGP_ERR_INVALID_VALUE;
3283
3284 /* Holdtime value check. */
3285 if (holdtime > 65535)
3286 return BGP_ERR_INVALID_VALUE;
3287
3288 /* Holdtime value must be either 0 or greater than 3. */
3289 if (holdtime < 3 && holdtime != 0)
3290 return BGP_ERR_INVALID_VALUE;
3291
3292 /* Set value to the configuration. */
3293 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3294 peer->holdtime = holdtime;
3295 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3296
3297 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3298 return 0;
3299
3300 /* peer-group member updates. */
3301 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003302 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003303 {
3304 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3305 peer->holdtime = group->conf->holdtime;
3306 peer->keepalive = group->conf->keepalive;
3307 }
3308 return 0;
3309}
3310
3311int
3312peer_timers_unset (struct peer *peer)
3313{
3314 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003315 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003316
3317 if (peer_group_active (peer))
3318 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3319
3320 /* Clear configuration. */
3321 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3322 peer->keepalive = 0;
3323 peer->holdtime = 0;
3324
3325 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3326 return 0;
3327
3328 /* peer-group member updates. */
3329 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003330 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003331 {
3332 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3333 peer->holdtime = 0;
3334 peer->keepalive = 0;
3335 }
3336
3337 return 0;
3338}
David Lamparter6b0655a2014-06-04 06:53:35 +02003339
paul718e3742002-12-13 20:15:29 +00003340int
3341peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3342{
3343 if (peer_group_active (peer))
3344 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3345
3346 if (connect > 65535)
3347 return BGP_ERR_INVALID_VALUE;
3348
3349 /* Set value to the configuration. */
3350 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3351 peer->connect = connect;
3352
3353 /* Set value to timer setting. */
3354 peer->v_connect = connect;
3355
3356 return 0;
3357}
3358
3359int
3360peer_timers_connect_unset (struct peer *peer)
3361{
3362 if (peer_group_active (peer))
3363 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3364
3365 /* Clear configuration. */
3366 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3367 peer->connect = 0;
3368
3369 /* Set timer setting to default value. */
3370 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3371
3372 return 0;
3373}
David Lamparter6b0655a2014-06-04 06:53:35 +02003374
paul718e3742002-12-13 20:15:29 +00003375int
3376peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3377{
3378 if (peer_group_active (peer))
3379 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3380
3381 if (routeadv > 600)
3382 return BGP_ERR_INVALID_VALUE;
3383
3384 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3385 peer->routeadv = routeadv;
3386 peer->v_routeadv = routeadv;
3387
3388 return 0;
3389}
3390
3391int
3392peer_advertise_interval_unset (struct peer *peer)
3393{
3394 if (peer_group_active (peer))
3395 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3396
3397 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3398 peer->routeadv = 0;
3399
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003400 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003401 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3402 else
3403 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3404
3405 return 0;
3406}
David Lamparter6b0655a2014-06-04 06:53:35 +02003407
paul718e3742002-12-13 20:15:29 +00003408/* neighbor interface */
3409int
paulfd79ac92004-10-13 05:06:08 +00003410peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003411{
3412 if (peer->ifname)
3413 free (peer->ifname);
3414 peer->ifname = strdup (str);
3415
3416 return 0;
3417}
3418
3419int
3420peer_interface_unset (struct peer *peer)
3421{
3422 if (peer->ifname)
3423 free (peer->ifname);
3424 peer->ifname = NULL;
3425
3426 return 0;
3427}
David Lamparter6b0655a2014-06-04 06:53:35 +02003428
paul718e3742002-12-13 20:15:29 +00003429/* Allow-as in. */
3430int
3431peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3432{
3433 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003434 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003435
3436 if (allow_num < 1 || allow_num > 10)
3437 return BGP_ERR_INVALID_VALUE;
3438
3439 if (peer->allowas_in[afi][safi] != allow_num)
3440 {
3441 peer->allowas_in[afi][safi] = allow_num;
3442 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3443 peer_change_action (peer, afi, safi, peer_change_reset_in);
3444 }
3445
3446 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3447 return 0;
3448
3449 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003450 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003451 {
3452 if (peer->allowas_in[afi][safi] != allow_num)
3453 {
3454 peer->allowas_in[afi][safi] = allow_num;
3455 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3456 peer_change_action (peer, afi, safi, peer_change_reset_in);
3457 }
3458
3459 }
3460 return 0;
3461}
3462
3463int
3464peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3465{
3466 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003467 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003468
3469 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3470 {
3471 peer->allowas_in[afi][safi] = 0;
3472 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3473 }
3474
3475 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3476 return 0;
3477
3478 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003479 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003480 {
3481 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3482 {
3483 peer->allowas_in[afi][safi] = 0;
3484 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3485 }
3486 }
3487 return 0;
3488}
David Lamparter6b0655a2014-06-04 06:53:35 +02003489
paul718e3742002-12-13 20:15:29 +00003490int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003491peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003492{
3493 struct bgp *bgp = peer->bgp;
3494 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003495 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003496
3497 if (peer_sort (peer) != BGP_PEER_EBGP
3498 && peer_sort (peer) != BGP_PEER_INTERNAL)
3499 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3500
3501 if (bgp->as == as)
3502 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3503
3504 if (peer_group_active (peer))
3505 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3506
Andrew Certain9d3f9702012-11-07 23:50:07 +00003507 if (peer->as == as)
3508 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3509
paul718e3742002-12-13 20:15:29 +00003510 if (peer->change_local_as == as &&
3511 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003512 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3513 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3514 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003515 return 0;
3516
3517 peer->change_local_as = as;
3518 if (no_prepend)
3519 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3520 else
3521 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3522
Andrew Certain9d3f9702012-11-07 23:50:07 +00003523 if (replace_as)
3524 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3525 else
3526 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3527
paul718e3742002-12-13 20:15:29 +00003528 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3529 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003530 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003531 {
3532 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3533 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3534 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3535 }
paul718e3742002-12-13 20:15:29 +00003536 else
3537 BGP_EVENT_ADD (peer, BGP_Stop);
3538
3539 return 0;
3540 }
3541
3542 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003543 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003544 {
3545 peer->change_local_as = as;
3546 if (no_prepend)
3547 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3548 else
3549 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3550
Andrew Certain9d3f9702012-11-07 23:50:07 +00003551 if (replace_as)
3552 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3553 else
3554 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3555
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003556 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003557 {
3558 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3559 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3560 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3561 }
paul718e3742002-12-13 20:15:29 +00003562 else
3563 BGP_EVENT_ADD (peer, BGP_Stop);
3564 }
3565
3566 return 0;
3567}
3568
3569int
3570peer_local_as_unset (struct peer *peer)
3571{
3572 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003573 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003574
3575 if (peer_group_active (peer))
3576 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3577
3578 if (! peer->change_local_as)
3579 return 0;
3580
3581 peer->change_local_as = 0;
3582 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003583 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003584
3585 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3586 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003587 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003588 {
3589 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3590 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3591 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3592 }
paul718e3742002-12-13 20:15:29 +00003593 else
3594 BGP_EVENT_ADD (peer, BGP_Stop);
3595
3596 return 0;
3597 }
3598
3599 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003600 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003601 {
3602 peer->change_local_as = 0;
3603 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003604 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003605
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003606 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003607 {
3608 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3609 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3610 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3611 }
paul718e3742002-12-13 20:15:29 +00003612 else
3613 BGP_EVENT_ADD (peer, BGP_Stop);
3614 }
3615 return 0;
3616}
David Lamparter6b0655a2014-06-04 06:53:35 +02003617
Paul Jakma0df7c912008-07-21 21:02:49 +00003618/* Set password for authenticating with the peer. */
3619int
3620peer_password_set (struct peer *peer, const char *password)
3621{
3622 struct listnode *nn, *nnode;
3623 int len = password ? strlen(password) : 0;
3624 int ret = BGP_SUCCESS;
3625
3626 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3627 return BGP_ERR_INVALID_VALUE;
3628
3629 if (peer->password && strcmp (peer->password, password) == 0
3630 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3631 return 0;
3632
3633 if (peer->password)
3634 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3635
3636 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3637
3638 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3639 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003640 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3641 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
Paul Jakma0df7c912008-07-21 21:02:49 +00003642 else
3643 BGP_EVENT_ADD (peer, BGP_Stop);
3644
3645 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3646 }
3647
3648 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3649 {
3650 if (peer->password && strcmp (peer->password, password) == 0)
3651 continue;
3652
3653 if (peer->password)
3654 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3655
3656 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3657
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003658 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003659 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3660 else
3661 BGP_EVENT_ADD (peer, BGP_Stop);
3662
3663 if (bgp_md5_set (peer) < 0)
3664 ret = BGP_ERR_TCPSIG_FAILED;
3665 }
3666
3667 return ret;
3668}
3669
3670int
3671peer_password_unset (struct peer *peer)
3672{
3673 struct listnode *nn, *nnode;
3674
3675 if (!peer->password
3676 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3677 return 0;
3678
3679 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3680 {
3681 if (peer_group_active (peer)
3682 && peer->group->conf->password
3683 && strcmp (peer->group->conf->password, peer->password) == 0)
3684 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3685
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003686 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003687 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3688 else
3689 BGP_EVENT_ADD (peer, BGP_Stop);
3690
3691 if (peer->password)
3692 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3693
3694 peer->password = NULL;
3695
3696 bgp_md5_set (peer);
3697
3698 return 0;
3699 }
3700
3701 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3702 peer->password = NULL;
3703
3704 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3705 {
3706 if (!peer->password)
3707 continue;
3708
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003709 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003710 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3711 else
3712 BGP_EVENT_ADD (peer, BGP_Stop);
3713
3714 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3715 peer->password = NULL;
3716
3717 bgp_md5_set (peer);
3718 }
3719
3720 return 0;
3721}
David Lamparter6b0655a2014-06-04 06:53:35 +02003722
paul718e3742002-12-13 20:15:29 +00003723/* Set distribute list to the peer. */
3724int
3725peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003726 const char *name)
paul718e3742002-12-13 20:15:29 +00003727{
3728 struct bgp_filter *filter;
3729 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003730 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003731
3732 if (! peer->afc[afi][safi])
3733 return BGP_ERR_PEER_INACTIVE;
3734
3735 if (direct != FILTER_IN && direct != FILTER_OUT)
3736 return BGP_ERR_INVALID_VALUE;
3737
3738 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3739 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3740
3741 filter = &peer->filter[afi][safi];
3742
3743 if (filter->plist[direct].name)
3744 return BGP_ERR_PEER_FILTER_CONFLICT;
3745
3746 if (filter->dlist[direct].name)
3747 free (filter->dlist[direct].name);
3748 filter->dlist[direct].name = strdup (name);
3749 filter->dlist[direct].alist = access_list_lookup (afi, name);
3750
3751 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3752 return 0;
3753
3754 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003755 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003756 {
3757 filter = &peer->filter[afi][safi];
3758
3759 if (! peer->af_group[afi][safi])
3760 continue;
3761
3762 if (filter->dlist[direct].name)
3763 free (filter->dlist[direct].name);
3764 filter->dlist[direct].name = strdup (name);
3765 filter->dlist[direct].alist = access_list_lookup (afi, name);
3766 }
3767
3768 return 0;
3769}
3770
3771int
3772peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3773{
3774 struct bgp_filter *filter;
3775 struct bgp_filter *gfilter;
3776 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003777 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003778
3779 if (! peer->afc[afi][safi])
3780 return BGP_ERR_PEER_INACTIVE;
3781
3782 if (direct != FILTER_IN && direct != FILTER_OUT)
3783 return BGP_ERR_INVALID_VALUE;
3784
3785 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3786 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3787
3788 filter = &peer->filter[afi][safi];
3789
3790 /* apply peer-group filter */
3791 if (peer->af_group[afi][safi])
3792 {
3793 gfilter = &peer->group->conf->filter[afi][safi];
3794
3795 if (gfilter->dlist[direct].name)
3796 {
3797 if (filter->dlist[direct].name)
3798 free (filter->dlist[direct].name);
3799 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3800 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3801 return 0;
3802 }
3803 }
3804
3805 if (filter->dlist[direct].name)
3806 free (filter->dlist[direct].name);
3807 filter->dlist[direct].name = NULL;
3808 filter->dlist[direct].alist = NULL;
3809
3810 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3811 return 0;
3812
3813 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003814 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003815 {
3816 filter = &peer->filter[afi][safi];
3817
3818 if (! peer->af_group[afi][safi])
3819 continue;
3820
3821 if (filter->dlist[direct].name)
3822 free (filter->dlist[direct].name);
3823 filter->dlist[direct].name = NULL;
3824 filter->dlist[direct].alist = NULL;
3825 }
3826
3827 return 0;
3828}
3829
3830/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003831static void
paul718e3742002-12-13 20:15:29 +00003832peer_distribute_update (struct access_list *access)
3833{
3834 afi_t afi;
3835 safi_t safi;
3836 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003837 struct listnode *mnode, *mnnode;
3838 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003839 struct bgp *bgp;
3840 struct peer *peer;
3841 struct peer_group *group;
3842 struct bgp_filter *filter;
3843
paul1eb8ef22005-04-07 07:30:20 +00003844 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003845 {
paul1eb8ef22005-04-07 07:30:20 +00003846 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003847 {
3848 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3849 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3850 {
3851 filter = &peer->filter[afi][safi];
3852
3853 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3854 {
3855 if (filter->dlist[direct].name)
3856 filter->dlist[direct].alist =
3857 access_list_lookup (afi, filter->dlist[direct].name);
3858 else
3859 filter->dlist[direct].alist = NULL;
3860 }
3861 }
3862 }
paul1eb8ef22005-04-07 07:30:20 +00003863 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003864 {
3865 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3866 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3867 {
3868 filter = &group->conf->filter[afi][safi];
3869
3870 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3871 {
3872 if (filter->dlist[direct].name)
3873 filter->dlist[direct].alist =
3874 access_list_lookup (afi, filter->dlist[direct].name);
3875 else
3876 filter->dlist[direct].alist = NULL;
3877 }
3878 }
3879 }
3880 }
3881}
David Lamparter6b0655a2014-06-04 06:53:35 +02003882
paul718e3742002-12-13 20:15:29 +00003883/* Set prefix list to the peer. */
3884int
3885peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003886 const char *name)
paul718e3742002-12-13 20:15:29 +00003887{
3888 struct bgp_filter *filter;
3889 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003890 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003891
3892 if (! peer->afc[afi][safi])
3893 return BGP_ERR_PEER_INACTIVE;
3894
3895 if (direct != FILTER_IN && direct != FILTER_OUT)
3896 return BGP_ERR_INVALID_VALUE;
3897
3898 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3899 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3900
3901 filter = &peer->filter[afi][safi];
3902
3903 if (filter->dlist[direct].name)
3904 return BGP_ERR_PEER_FILTER_CONFLICT;
3905
3906 if (filter->plist[direct].name)
3907 free (filter->plist[direct].name);
3908 filter->plist[direct].name = strdup (name);
3909 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3910
3911 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3912 return 0;
3913
3914 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003915 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003916 {
3917 filter = &peer->filter[afi][safi];
3918
3919 if (! peer->af_group[afi][safi])
3920 continue;
3921
3922 if (filter->plist[direct].name)
3923 free (filter->plist[direct].name);
3924 filter->plist[direct].name = strdup (name);
3925 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3926 }
3927 return 0;
3928}
3929
3930int
3931peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3932{
3933 struct bgp_filter *filter;
3934 struct bgp_filter *gfilter;
3935 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003936 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003937
3938 if (! peer->afc[afi][safi])
3939 return BGP_ERR_PEER_INACTIVE;
3940
3941 if (direct != FILTER_IN && direct != FILTER_OUT)
3942 return BGP_ERR_INVALID_VALUE;
3943
3944 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3945 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3946
3947 filter = &peer->filter[afi][safi];
3948
3949 /* apply peer-group filter */
3950 if (peer->af_group[afi][safi])
3951 {
3952 gfilter = &peer->group->conf->filter[afi][safi];
3953
3954 if (gfilter->plist[direct].name)
3955 {
3956 if (filter->plist[direct].name)
3957 free (filter->plist[direct].name);
3958 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3959 filter->plist[direct].plist = gfilter->plist[direct].plist;
3960 return 0;
3961 }
3962 }
3963
3964 if (filter->plist[direct].name)
3965 free (filter->plist[direct].name);
3966 filter->plist[direct].name = NULL;
3967 filter->plist[direct].plist = NULL;
3968
3969 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3970 return 0;
3971
3972 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003973 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003974 {
3975 filter = &peer->filter[afi][safi];
3976
3977 if (! peer->af_group[afi][safi])
3978 continue;
3979
3980 if (filter->plist[direct].name)
3981 free (filter->plist[direct].name);
3982 filter->plist[direct].name = NULL;
3983 filter->plist[direct].plist = NULL;
3984 }
3985
3986 return 0;
3987}
3988
3989/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003990static void
paul718e3742002-12-13 20:15:29 +00003991peer_prefix_list_update (struct prefix_list *plist)
3992{
paul1eb8ef22005-04-07 07:30:20 +00003993 struct listnode *mnode, *mnnode;
3994 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003995 struct bgp *bgp;
3996 struct peer *peer;
3997 struct peer_group *group;
3998 struct bgp_filter *filter;
3999 afi_t afi;
4000 safi_t safi;
4001 int direct;
4002
paul1eb8ef22005-04-07 07:30:20 +00004003 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004004 {
paul1eb8ef22005-04-07 07:30:20 +00004005 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004006 {
4007 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4008 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4009 {
4010 filter = &peer->filter[afi][safi];
4011
4012 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4013 {
4014 if (filter->plist[direct].name)
4015 filter->plist[direct].plist =
4016 prefix_list_lookup (afi, filter->plist[direct].name);
4017 else
4018 filter->plist[direct].plist = NULL;
4019 }
4020 }
4021 }
paul1eb8ef22005-04-07 07:30:20 +00004022 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004023 {
4024 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4025 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4026 {
4027 filter = &group->conf->filter[afi][safi];
4028
4029 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4030 {
4031 if (filter->plist[direct].name)
4032 filter->plist[direct].plist =
4033 prefix_list_lookup (afi, filter->plist[direct].name);
4034 else
4035 filter->plist[direct].plist = NULL;
4036 }
4037 }
4038 }
4039 }
4040}
David Lamparter6b0655a2014-06-04 06:53:35 +02004041
paul718e3742002-12-13 20:15:29 +00004042int
4043peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004044 const char *name)
paul718e3742002-12-13 20:15:29 +00004045{
4046 struct bgp_filter *filter;
4047 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004048 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004049
4050 if (! peer->afc[afi][safi])
4051 return BGP_ERR_PEER_INACTIVE;
4052
4053 if (direct != FILTER_IN && direct != FILTER_OUT)
4054 return BGP_ERR_INVALID_VALUE;
4055
4056 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4057 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4058
4059 filter = &peer->filter[afi][safi];
4060
4061 if (filter->aslist[direct].name)
4062 free (filter->aslist[direct].name);
4063 filter->aslist[direct].name = strdup (name);
4064 filter->aslist[direct].aslist = as_list_lookup (name);
4065
4066 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4067 return 0;
4068
4069 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004070 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004071 {
4072 filter = &peer->filter[afi][safi];
4073
4074 if (! peer->af_group[afi][safi])
4075 continue;
4076
4077 if (filter->aslist[direct].name)
4078 free (filter->aslist[direct].name);
4079 filter->aslist[direct].name = strdup (name);
4080 filter->aslist[direct].aslist = as_list_lookup (name);
4081 }
4082 return 0;
4083}
4084
4085int
4086peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4087{
4088 struct bgp_filter *filter;
4089 struct bgp_filter *gfilter;
4090 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004091 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004092
4093 if (! peer->afc[afi][safi])
4094 return BGP_ERR_PEER_INACTIVE;
4095
hassob5f29602005-05-25 21:00:28 +00004096 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004097 return BGP_ERR_INVALID_VALUE;
4098
hassob5f29602005-05-25 21:00:28 +00004099 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004100 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4101
4102 filter = &peer->filter[afi][safi];
4103
4104 /* apply peer-group filter */
4105 if (peer->af_group[afi][safi])
4106 {
4107 gfilter = &peer->group->conf->filter[afi][safi];
4108
4109 if (gfilter->aslist[direct].name)
4110 {
4111 if (filter->aslist[direct].name)
4112 free (filter->aslist[direct].name);
4113 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4114 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4115 return 0;
4116 }
4117 }
4118
4119 if (filter->aslist[direct].name)
4120 free (filter->aslist[direct].name);
4121 filter->aslist[direct].name = NULL;
4122 filter->aslist[direct].aslist = NULL;
4123
4124 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4125 return 0;
4126
4127 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004128 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004129 {
4130 filter = &peer->filter[afi][safi];
4131
4132 if (! peer->af_group[afi][safi])
4133 continue;
4134
4135 if (filter->aslist[direct].name)
4136 free (filter->aslist[direct].name);
4137 filter->aslist[direct].name = NULL;
4138 filter->aslist[direct].aslist = NULL;
4139 }
4140
4141 return 0;
4142}
4143
paul94f2b392005-06-28 12:44:16 +00004144static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004145peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004146{
4147 afi_t afi;
4148 safi_t safi;
4149 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004150 struct listnode *mnode, *mnnode;
4151 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004152 struct bgp *bgp;
4153 struct peer *peer;
4154 struct peer_group *group;
4155 struct bgp_filter *filter;
4156
paul1eb8ef22005-04-07 07:30:20 +00004157 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004158 {
paul1eb8ef22005-04-07 07:30:20 +00004159 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004160 {
4161 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4162 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4163 {
4164 filter = &peer->filter[afi][safi];
4165
4166 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4167 {
4168 if (filter->aslist[direct].name)
4169 filter->aslist[direct].aslist =
4170 as_list_lookup (filter->aslist[direct].name);
4171 else
4172 filter->aslist[direct].aslist = NULL;
4173 }
4174 }
4175 }
paul1eb8ef22005-04-07 07:30:20 +00004176 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004177 {
4178 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4179 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4180 {
4181 filter = &group->conf->filter[afi][safi];
4182
4183 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4184 {
4185 if (filter->aslist[direct].name)
4186 filter->aslist[direct].aslist =
4187 as_list_lookup (filter->aslist[direct].name);
4188 else
4189 filter->aslist[direct].aslist = NULL;
4190 }
4191 }
4192 }
4193 }
4194}
David Lamparter6b0655a2014-06-04 06:53:35 +02004195
paul718e3742002-12-13 20:15:29 +00004196/* Set route-map to the peer. */
4197int
4198peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004199 const char *name)
paul718e3742002-12-13 20:15:29 +00004200{
4201 struct bgp_filter *filter;
4202 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004203 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004204
4205 if (! peer->afc[afi][safi])
4206 return BGP_ERR_PEER_INACTIVE;
4207
paulfee0f4c2004-09-13 05:12:46 +00004208 if (direct != RMAP_IN && direct != RMAP_OUT &&
4209 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004210 return BGP_ERR_INVALID_VALUE;
4211
paulfee0f4c2004-09-13 05:12:46 +00004212 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4213 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004214 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4215
4216 filter = &peer->filter[afi][safi];
4217
4218 if (filter->map[direct].name)
4219 free (filter->map[direct].name);
4220
4221 filter->map[direct].name = strdup (name);
4222 filter->map[direct].map = route_map_lookup_by_name (name);
4223
4224 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4225 return 0;
4226
4227 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004228 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004229 {
4230 filter = &peer->filter[afi][safi];
4231
4232 if (! peer->af_group[afi][safi])
4233 continue;
4234
4235 if (filter->map[direct].name)
4236 free (filter->map[direct].name);
4237 filter->map[direct].name = strdup (name);
4238 filter->map[direct].map = route_map_lookup_by_name (name);
4239 }
4240 return 0;
4241}
4242
4243/* Unset route-map from the peer. */
4244int
4245peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4246{
4247 struct bgp_filter *filter;
4248 struct bgp_filter *gfilter;
4249 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004250 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004251
4252 if (! peer->afc[afi][safi])
4253 return BGP_ERR_PEER_INACTIVE;
4254
hassob5f29602005-05-25 21:00:28 +00004255 if (direct != RMAP_IN && direct != RMAP_OUT &&
4256 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004257 return BGP_ERR_INVALID_VALUE;
4258
hassob5f29602005-05-25 21:00:28 +00004259 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4260 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004261 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4262
4263 filter = &peer->filter[afi][safi];
4264
4265 /* apply peer-group filter */
4266 if (peer->af_group[afi][safi])
4267 {
4268 gfilter = &peer->group->conf->filter[afi][safi];
4269
4270 if (gfilter->map[direct].name)
4271 {
4272 if (filter->map[direct].name)
4273 free (filter->map[direct].name);
4274 filter->map[direct].name = strdup (gfilter->map[direct].name);
4275 filter->map[direct].map = gfilter->map[direct].map;
4276 return 0;
4277 }
4278 }
4279
4280 if (filter->map[direct].name)
4281 free (filter->map[direct].name);
4282 filter->map[direct].name = NULL;
4283 filter->map[direct].map = NULL;
4284
4285 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4286 return 0;
4287
4288 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004289 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004290 {
4291 filter = &peer->filter[afi][safi];
4292
4293 if (! peer->af_group[afi][safi])
4294 continue;
4295
4296 if (filter->map[direct].name)
4297 free (filter->map[direct].name);
4298 filter->map[direct].name = NULL;
4299 filter->map[direct].map = NULL;
4300 }
4301 return 0;
4302}
David Lamparter6b0655a2014-06-04 06:53:35 +02004303
paul718e3742002-12-13 20:15:29 +00004304/* Set unsuppress-map to the peer. */
4305int
paulfd79ac92004-10-13 05:06:08 +00004306peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4307 const char *name)
paul718e3742002-12-13 20:15:29 +00004308{
4309 struct bgp_filter *filter;
4310 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004311 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004312
4313 if (! peer->afc[afi][safi])
4314 return BGP_ERR_PEER_INACTIVE;
4315
4316 if (peer_is_group_member (peer, afi, safi))
4317 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4318
4319 filter = &peer->filter[afi][safi];
4320
4321 if (filter->usmap.name)
4322 free (filter->usmap.name);
4323
4324 filter->usmap.name = strdup (name);
4325 filter->usmap.map = route_map_lookup_by_name (name);
4326
4327 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4328 return 0;
4329
4330 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004331 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004332 {
4333 filter = &peer->filter[afi][safi];
4334
4335 if (! peer->af_group[afi][safi])
4336 continue;
4337
4338 if (filter->usmap.name)
4339 free (filter->usmap.name);
4340 filter->usmap.name = strdup (name);
4341 filter->usmap.map = route_map_lookup_by_name (name);
4342 }
4343 return 0;
4344}
4345
4346/* Unset route-map from the peer. */
4347int
4348peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4349{
4350 struct bgp_filter *filter;
4351 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004352 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004353
4354 if (! peer->afc[afi][safi])
4355 return BGP_ERR_PEER_INACTIVE;
4356
4357 if (peer_is_group_member (peer, afi, safi))
4358 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4359
4360 filter = &peer->filter[afi][safi];
4361
4362 if (filter->usmap.name)
4363 free (filter->usmap.name);
4364 filter->usmap.name = NULL;
4365 filter->usmap.map = NULL;
4366
4367 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4368 return 0;
4369
4370 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004371 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004372 {
4373 filter = &peer->filter[afi][safi];
4374
4375 if (! peer->af_group[afi][safi])
4376 continue;
4377
4378 if (filter->usmap.name)
4379 free (filter->usmap.name);
4380 filter->usmap.name = NULL;
4381 filter->usmap.map = NULL;
4382 }
4383 return 0;
4384}
David Lamparter6b0655a2014-06-04 06:53:35 +02004385
paul718e3742002-12-13 20:15:29 +00004386int
4387peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004388 u_int32_t max, u_char threshold,
4389 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004390{
4391 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004392 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004393
4394 if (! peer->afc[afi][safi])
4395 return BGP_ERR_PEER_INACTIVE;
4396
4397 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4398 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004399 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004400 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004401 if (warning)
4402 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4403 else
4404 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4405
4406 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4407 return 0;
4408
4409 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004410 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004411 {
4412 if (! peer->af_group[afi][safi])
4413 continue;
4414
4415 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4416 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004417 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004418 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004419 if (warning)
4420 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4421 else
4422 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4423 }
4424 return 0;
4425}
4426
4427int
4428peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4429{
4430 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004431 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004432
4433 if (! peer->afc[afi][safi])
4434 return BGP_ERR_PEER_INACTIVE;
4435
4436 /* apply peer-group config */
4437 if (peer->af_group[afi][safi])
4438 {
4439 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4440 PEER_FLAG_MAX_PREFIX))
4441 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4442 else
4443 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4444
4445 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4446 PEER_FLAG_MAX_PREFIX_WARNING))
4447 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4448 else
4449 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4450
4451 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004452 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004453 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004454 return 0;
4455 }
4456
4457 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4458 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4459 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004460 peer->pmax_threshold[afi][safi] = 0;
4461 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004462
4463 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4464 return 0;
4465
4466 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004467 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004468 {
4469 if (! peer->af_group[afi][safi])
4470 continue;
4471
4472 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4473 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4474 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004475 peer->pmax_threshold[afi][safi] = 0;
4476 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004477 }
4478 return 0;
4479}
David Lamparter5f9adb52014-05-19 23:15:02 +02004480
4481static int is_ebgp_multihop_configured (struct peer *peer)
4482{
4483 struct peer_group *group;
4484 struct listnode *node, *nnode;
4485 struct peer *peer1;
4486
4487 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4488 {
4489 group = peer->group;
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004490 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4491 (group->conf->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004492 return 1;
4493
4494 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4495 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004496 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
4497 (peer1->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004498 return 1;
4499 }
4500 }
4501 else
4502 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004503 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4504 (peer->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004505 return 1;
4506 }
4507 return 0;
4508}
4509
Nick Hilliardfa411a22011-03-23 15:33:17 +00004510/* Set # of hops between us and BGP peer. */
4511int
4512peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4513{
4514 struct peer_group *group;
4515 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004516 int ret;
4517
4518 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4519
Nick Hilliardfa411a22011-03-23 15:33:17 +00004520 /* We cannot configure ttl-security hops when ebgp-multihop is already
4521 set. For non peer-groups, the check is simple. For peer-groups, it's
4522 slightly messy, because we need to check both the peer-group structure
4523 and all peer-group members for any trace of ebgp-multihop configuration
4524 before actually applying the ttl-security rules. Cisco really made a
4525 mess of this configuration parameter, and OpenBGPD got it right.
4526 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004527
David Lamparter5f9adb52014-05-19 23:15:02 +02004528 if (peer->gtsm_hops == 0)
4529 {
4530 if (is_ebgp_multihop_configured (peer))
4531 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004532
David Lamparter5f9adb52014-05-19 23:15:02 +02004533 /* specify MAXTTL on outgoing packets */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004534 /* Routine handles iBGP peers correctly */
David Lamparter5f9adb52014-05-19 23:15:02 +02004535 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4536 if (ret != 0)
4537 return ret;
4538 }
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004539
Nick Hilliardfa411a22011-03-23 15:33:17 +00004540 peer->gtsm_hops = gtsm_hops;
4541
Nick Hilliardfa411a22011-03-23 15:33:17 +00004542 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4543 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004544 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004545 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4546 }
4547 else
4548 {
4549 group = peer->group;
4550 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4551 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004552 peer->gtsm_hops = group->conf->gtsm_hops;
4553
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004554 /* Change setting of existing peer
4555 * established then change value (may break connectivity)
4556 * not established yet (teardown session and restart)
4557 * no session then do nothing (will get handled by next connection)
4558 */
4559 if (peer->status == Established)
4560 {
4561 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4562 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4563 MAXTTL + 1 - peer->gtsm_hops);
4564 }
4565 else if (peer->status < Established)
4566 {
4567 if (BGP_DEBUG (events, EVENTS))
4568 zlog_debug ("%s Min-ttl changed", peer->host);
4569 BGP_EVENT_ADD (peer, BGP_Stop);
4570 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004571 }
4572 }
4573
4574 return 0;
4575}
4576
4577int
4578peer_ttl_security_hops_unset (struct peer *peer)
4579{
4580 struct peer_group *group;
4581 struct listnode *node, *nnode;
4582 struct peer *opeer;
4583
4584 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4585
Nick Hilliardfa411a22011-03-23 15:33:17 +00004586 /* if a peer-group member, then reset to peer-group default rather than 0 */
4587 if (peer_group_active (peer))
4588 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4589 else
4590 peer->gtsm_hops = 0;
4591
4592 opeer = peer;
4593 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4594 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004595 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004596 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4597 }
4598 else
4599 {
4600 group = peer->group;
4601 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4602 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004603 peer->gtsm_hops = 0;
4604
4605 if (peer->fd >= 0)
4606 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4607 }
4608 }
4609
4610 return peer_ebgp_multihop_unset (opeer);
4611}
David Lamparter6b0655a2014-06-04 06:53:35 +02004612
paul718e3742002-12-13 20:15:29 +00004613int
4614peer_clear (struct peer *peer)
4615{
4616 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4617 {
hasso0a486e52005-02-01 20:57:17 +00004618 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4619 {
4620 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4621 if (peer->t_pmax_restart)
4622 {
4623 BGP_TIMER_OFF (peer->t_pmax_restart);
4624 if (BGP_DEBUG (events, EVENTS))
4625 zlog_debug ("%s Maximum-prefix restart timer canceled",
4626 peer->host);
4627 }
4628 BGP_EVENT_ADD (peer, BGP_Start);
4629 return 0;
4630 }
4631
paul718e3742002-12-13 20:15:29 +00004632 peer->v_start = BGP_INIT_START_TIMER;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00004633 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00004634 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4635 BGP_NOTIFY_CEASE_ADMIN_RESET);
4636 else
4637 BGP_EVENT_ADD (peer, BGP_Stop);
4638 }
4639 return 0;
4640}
4641
4642int
4643peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4644 enum bgp_clear_type stype)
4645{
4646 if (peer->status != Established)
4647 return 0;
4648
4649 if (! peer->afc[afi][safi])
4650 return BGP_ERR_AF_UNCONFIGURED;
4651
paulfee0f4c2004-09-13 05:12:46 +00004652 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4653 {
4654 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4655 return 0;
4656 bgp_check_local_routes_rsclient (peer, afi, safi);
4657 bgp_soft_reconfig_rsclient (peer, afi, safi);
4658 }
4659
paul718e3742002-12-13 20:15:29 +00004660 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4661 bgp_announce_route (peer, afi, safi);
4662
4663 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4664 {
4665 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4666 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4667 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4668 {
4669 struct bgp_filter *filter = &peer->filter[afi][safi];
4670 u_char prefix_type;
4671
4672 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4673 prefix_type = ORF_TYPE_PREFIX;
4674 else
4675 prefix_type = ORF_TYPE_PREFIX_OLD;
4676
4677 if (filter->plist[FILTER_IN].plist)
4678 {
4679 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4680 bgp_route_refresh_send (peer, afi, safi,
4681 prefix_type, REFRESH_DEFER, 1);
4682 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4683 REFRESH_IMMEDIATE, 0);
4684 }
4685 else
4686 {
4687 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4688 bgp_route_refresh_send (peer, afi, safi,
4689 prefix_type, REFRESH_IMMEDIATE, 1);
4690 else
4691 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4692 }
4693 return 0;
4694 }
4695 }
4696
4697 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4698 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4699 {
4700 /* If neighbor has soft reconfiguration inbound flag.
4701 Use Adj-RIB-In database. */
4702 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4703 bgp_soft_reconfig_in (peer, afi, safi);
4704 else
4705 {
4706 /* If neighbor has route refresh capability, send route refresh
4707 message to the peer. */
4708 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4709 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4710 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4711 else
4712 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4713 }
4714 }
4715 return 0;
4716}
David Lamparter6b0655a2014-06-04 06:53:35 +02004717
paulfd79ac92004-10-13 05:06:08 +00004718/* Display peer uptime.*/
4719/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004720char *
4721peer_uptime (time_t uptime2, char *buf, size_t len)
4722{
4723 time_t uptime1;
4724 struct tm *tm;
4725
4726 /* Check buffer length. */
4727 if (len < BGP_UPTIME_LEN)
4728 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004729 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004730 /* XXX: should return status instead of buf... */
4731 snprintf (buf, len, "<error> ");
4732 return buf;
paul718e3742002-12-13 20:15:29 +00004733 }
4734
4735 /* If there is no connection has been done before print `never'. */
4736 if (uptime2 == 0)
4737 {
4738 snprintf (buf, len, "never ");
4739 return buf;
4740 }
4741
4742 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004743 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004744 uptime1 -= uptime2;
4745 tm = gmtime (&uptime1);
Paul Jakma84c38402015-05-26 15:19:38 +01004746
paul718e3742002-12-13 20:15:29 +00004747 /* Making formatted timer strings. */
4748#define ONE_DAY_SECOND 60*60*24
Paul Jakma84c38402015-05-26 15:19:38 +01004749#define ONE_WEEK_SECOND ONE_DAY_SECOND*7
4750#define ONE_YEAR_SECOND ONE_DAY_SECOND*365
paul718e3742002-12-13 20:15:29 +00004751
4752 if (uptime1 < ONE_DAY_SECOND)
4753 snprintf (buf, len, "%02d:%02d:%02d",
4754 tm->tm_hour, tm->tm_min, tm->tm_sec);
4755 else if (uptime1 < ONE_WEEK_SECOND)
4756 snprintf (buf, len, "%dd%02dh%02dm",
4757 tm->tm_yday, tm->tm_hour, tm->tm_min);
Paul Jakma84c38402015-05-26 15:19:38 +01004758 else if (uptime1 < ONE_YEAR_SECOND)
paul718e3742002-12-13 20:15:29 +00004759 snprintf (buf, len, "%02dw%dd%02dh",
4760 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
Paul Jakma84c38402015-05-26 15:19:38 +01004761 else
4762 snprintf (buf, len, "%02dy%02dw%dd",
4763 tm->tm_year - 70, tm->tm_yday/7,
4764 tm->tm_yday - ((tm->tm_yday/7) * 7));
paul718e3742002-12-13 20:15:29 +00004765 return buf;
4766}
David Lamparter6b0655a2014-06-04 06:53:35 +02004767
paul94f2b392005-06-28 12:44:16 +00004768static void
paul718e3742002-12-13 20:15:29 +00004769bgp_config_write_filter (struct vty *vty, struct peer *peer,
4770 afi_t afi, safi_t safi)
4771{
4772 struct bgp_filter *filter;
4773 struct bgp_filter *gfilter = NULL;
4774 char *addr;
4775 int in = FILTER_IN;
4776 int out = FILTER_OUT;
4777
4778 addr = peer->host;
4779 filter = &peer->filter[afi][safi];
4780 if (peer->af_group[afi][safi])
4781 gfilter = &peer->group->conf->filter[afi][safi];
4782
4783 /* distribute-list. */
4784 if (filter->dlist[in].name)
4785 if (! gfilter || ! gfilter->dlist[in].name
4786 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4787 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4788 filter->dlist[in].name, VTY_NEWLINE);
4789 if (filter->dlist[out].name && ! gfilter)
4790 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4791 filter->dlist[out].name, VTY_NEWLINE);
4792
4793 /* prefix-list. */
4794 if (filter->plist[in].name)
4795 if (! gfilter || ! gfilter->plist[in].name
4796 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4797 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4798 filter->plist[in].name, VTY_NEWLINE);
4799 if (filter->plist[out].name && ! gfilter)
4800 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4801 filter->plist[out].name, VTY_NEWLINE);
4802
4803 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004804 if (filter->map[RMAP_IN].name)
4805 if (! gfilter || ! gfilter->map[RMAP_IN].name
4806 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004807 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004808 filter->map[RMAP_IN].name, VTY_NEWLINE);
4809 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004810 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004811 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4812 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4813 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4814 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4815 if (filter->map[RMAP_EXPORT].name)
4816 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4817 || strcmp (filter->map[RMAP_EXPORT].name,
4818 gfilter->map[RMAP_EXPORT].name) != 0)
4819 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4820 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004821
4822 /* unsuppress-map */
4823 if (filter->usmap.name && ! gfilter)
4824 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4825 filter->usmap.name, VTY_NEWLINE);
4826
4827 /* filter-list. */
4828 if (filter->aslist[in].name)
4829 if (! gfilter || ! gfilter->aslist[in].name
4830 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4831 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4832 filter->aslist[in].name, VTY_NEWLINE);
4833 if (filter->aslist[out].name && ! gfilter)
4834 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4835 filter->aslist[out].name, VTY_NEWLINE);
4836}
4837
4838/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004839static void
paul718e3742002-12-13 20:15:29 +00004840bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4841 struct peer *peer, afi_t afi, safi_t safi)
4842{
paul718e3742002-12-13 20:15:29 +00004843 struct peer *g_peer = NULL;
4844 char buf[SU_ADDRSTRLEN];
4845 char *addr;
4846
paul718e3742002-12-13 20:15:29 +00004847 addr = peer->host;
4848 if (peer_group_active (peer))
4849 g_peer = peer->group->conf;
4850
4851 /************************************
4852 ****** Global to the neighbor ******
4853 ************************************/
4854 if (afi == AFI_IP && safi == SAFI_UNICAST)
4855 {
4856 /* remote-as. */
4857 if (! peer_group_active (peer))
4858 {
4859 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4860 vty_out (vty, " neighbor %s peer-group%s", addr,
4861 VTY_NEWLINE);
4862 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004863 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004864 VTY_NEWLINE);
4865 }
4866 else
4867 {
4868 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004869 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004870 VTY_NEWLINE);
4871 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4872 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4873 peer->group->name, VTY_NEWLINE);
4874 }
4875
4876 /* local-as. */
4877 if (peer->change_local_as)
4878 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00004879 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004880 peer->change_local_as,
4881 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00004882 " no-prepend" : "",
4883 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
4884 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004885
4886 /* Description. */
4887 if (peer->desc)
4888 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4889 VTY_NEWLINE);
4890
4891 /* Shutdown. */
4892 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4893 if (! peer_group_active (peer) ||
4894 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4895 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4896
Paul Jakma0df7c912008-07-21 21:02:49 +00004897 /* Password. */
4898 if (peer->password)
4899 if (!peer_group_active (peer)
4900 || ! g_peer->password
4901 || strcmp (peer->password, g_peer->password) != 0)
4902 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4903 VTY_NEWLINE);
4904
paul718e3742002-12-13 20:15:29 +00004905 /* BGP port. */
4906 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004907 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004908 VTY_NEWLINE);
4909
4910 /* Local interface name. */
4911 if (peer->ifname)
4912 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4913 VTY_NEWLINE);
4914
4915 /* Passive. */
4916 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4917 if (! peer_group_active (peer) ||
4918 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4919 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4920
4921 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004922 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00004923 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00004924 if (! peer_group_active (peer) ||
4925 g_peer->ttl != peer->ttl)
4926 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4927 VTY_NEWLINE);
4928
Nick Hilliardfa411a22011-03-23 15:33:17 +00004929 /* ttl-security hops */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004930 if (peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004931 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004932 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00004933 peer->gtsm_hops, VTY_NEWLINE);
4934
hasso6ffd2072005-02-02 14:50:11 +00004935 /* disable-connected-check. */
4936 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004937 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004938 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4939 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004940
4941 /* Update-source. */
4942 if (peer->update_if)
4943 if (! peer_group_active (peer) || ! g_peer->update_if
4944 || strcmp (g_peer->update_if, peer->update_if) != 0)
4945 vty_out (vty, " neighbor %s update-source %s%s", addr,
4946 peer->update_if, VTY_NEWLINE);
4947 if (peer->update_source)
4948 if (! peer_group_active (peer) || ! g_peer->update_source
4949 || sockunion_cmp (g_peer->update_source,
4950 peer->update_source) != 0)
4951 vty_out (vty, " neighbor %s update-source %s%s", addr,
4952 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4953 VTY_NEWLINE);
4954
paul718e3742002-12-13 20:15:29 +00004955 /* advertisement-interval */
4956 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4957 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4958 addr, peer->v_routeadv, VTY_NEWLINE);
4959
4960 /* timers. */
4961 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4962 && ! peer_group_active (peer))
4963 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4964 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4965
4966 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4967 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4968 peer->connect, VTY_NEWLINE);
4969
4970 /* Default weight. */
4971 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4972 if (! peer_group_active (peer) ||
4973 g_peer->weight != peer->weight)
4974 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4975 VTY_NEWLINE);
4976
paul718e3742002-12-13 20:15:29 +00004977 /* Dynamic capability. */
4978 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4979 if (! peer_group_active (peer) ||
4980 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4981 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4982 VTY_NEWLINE);
4983
4984 /* dont capability negotiation. */
4985 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4986 if (! peer_group_active (peer) ||
4987 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4988 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4989 VTY_NEWLINE);
4990
4991 /* override capability negotiation. */
4992 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4993 if (! peer_group_active (peer) ||
4994 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4995 vty_out (vty, " neighbor %s override-capability%s", addr,
4996 VTY_NEWLINE);
4997
4998 /* strict capability negotiation. */
4999 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5000 if (! peer_group_active (peer) ||
5001 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
5002 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
5003 VTY_NEWLINE);
5004
Christian Franke15c71342012-11-19 11:17:31 +00005005 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
paul718e3742002-12-13 20:15:29 +00005006 {
5007 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5008 {
5009 if (peer->afc[AFI_IP][SAFI_UNICAST])
5010 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5011 }
5012 else
5013 {
5014 if (! peer->afc[AFI_IP][SAFI_UNICAST])
5015 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
5016 }
5017 }
5018 }
5019
5020
5021 /************************************
5022 ****** Per AF to the neighbor ******
5023 ************************************/
5024
5025 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
5026 {
5027 if (peer->af_group[afi][safi])
5028 vty_out (vty, " neighbor %s peer-group %s%s", addr,
5029 peer->group->name, VTY_NEWLINE);
5030 else
5031 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
5032 }
5033
5034 /* ORF capability. */
5035 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5036 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5037 if (! peer->af_group[afi][safi])
5038 {
5039 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
5040
5041 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
5042 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
5043 vty_out (vty, " both");
5044 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
5045 vty_out (vty, " send");
5046 else
5047 vty_out (vty, " receive");
5048 vty_out (vty, "%s", VTY_NEWLINE);
5049 }
5050
5051 /* Route reflector client. */
5052 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
5053 && ! peer->af_group[afi][safi])
5054 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
5055 VTY_NEWLINE);
5056
5057 /* Nexthop self. */
5058 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
5059 && ! peer->af_group[afi][safi])
Timo Teräs9e7a53c2014-04-24 10:22:37 +03005060 vty_out (vty, " neighbor %s next-hop-self%s%s", addr,
5061 peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ?
5062 " all" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005063
5064 /* Remove private AS. */
5065 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
5066 && ! peer->af_group[afi][safi])
5067 vty_out (vty, " neighbor %s remove-private-AS%s",
5068 addr, VTY_NEWLINE);
5069
5070 /* send-community print. */
5071 if (! peer->af_group[afi][safi])
5072 {
5073 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5074 {
5075 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5076 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5077 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
5078 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5079 vty_out (vty, " neighbor %s send-community extended%s",
5080 addr, VTY_NEWLINE);
5081 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5082 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
5083 }
5084 else
5085 {
5086 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5087 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5088 vty_out (vty, " no neighbor %s send-community both%s",
5089 addr, VTY_NEWLINE);
5090 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5091 vty_out (vty, " no neighbor %s send-community extended%s",
5092 addr, VTY_NEWLINE);
5093 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5094 vty_out (vty, " no neighbor %s send-community%s",
5095 addr, VTY_NEWLINE);
5096 }
5097 }
5098
5099 /* Default information */
5100 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5101 && ! peer->af_group[afi][safi])
5102 {
5103 vty_out (vty, " neighbor %s default-originate", addr);
5104 if (peer->default_rmap[afi][safi].name)
5105 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5106 vty_out (vty, "%s", VTY_NEWLINE);
5107 }
5108
5109 /* Soft reconfiguration inbound. */
5110 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5111 if (! peer->af_group[afi][safi] ||
5112 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5113 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5114 VTY_NEWLINE);
5115
5116 /* maximum-prefix. */
5117 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5118 if (! peer->af_group[afi][safi]
5119 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005120 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005121 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5122 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005123 {
hasso0a486e52005-02-01 20:57:17 +00005124 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5125 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5126 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5127 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5128 vty_out (vty, " warning-only");
5129 if (peer->pmax_restart[afi][safi])
5130 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5131 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005132 }
paul718e3742002-12-13 20:15:29 +00005133
5134 /* Route server client. */
5135 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5136 && ! peer->af_group[afi][safi])
5137 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5138
Dylan Hall3cf12882011-10-27 15:28:17 +04005139 /* Nexthop-local unchanged. */
5140 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5141 && ! peer->af_group[afi][safi])
5142 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5143
paul718e3742002-12-13 20:15:29 +00005144 /* Allow AS in. */
5145 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5146 if (! peer_group_active (peer)
5147 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5148 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5149 {
5150 if (peer->allowas_in[afi][safi] == 3)
5151 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5152 else
5153 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5154 peer->allowas_in[afi][safi], VTY_NEWLINE);
5155 }
5156
5157 /* Filter. */
5158 bgp_config_write_filter (vty, peer, afi, safi);
5159
5160 /* atribute-unchanged. */
5161 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5162 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5163 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5164 && ! peer->af_group[afi][safi])
5165 {
5166 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5167 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5168 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5169 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5170 else
5171 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5172 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5173 " as-path" : "",
5174 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5175 " next-hop" : "",
5176 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5177 " med" : "", VTY_NEWLINE);
5178 }
5179}
5180
5181/* Display "address-family" configuration header. */
5182void
5183bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5184 int *write)
5185{
5186 if (*write)
5187 return;
5188
5189 if (afi == AFI_IP && safi == SAFI_UNICAST)
5190 return;
5191
5192 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5193
5194 if (afi == AFI_IP)
5195 {
5196 if (safi == SAFI_MULTICAST)
5197 vty_out (vty, "ipv4 multicast");
5198 else if (safi == SAFI_MPLS_VPN)
5199 vty_out (vty, "vpnv4 unicast");
5200 }
5201 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005202 {
5203 vty_out (vty, "ipv6");
5204
5205 if (safi == SAFI_MULTICAST)
5206 vty_out (vty, " multicast");
5207 }
paul718e3742002-12-13 20:15:29 +00005208
5209 vty_out (vty, "%s", VTY_NEWLINE);
5210
5211 *write = 1;
5212}
5213
5214/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005215static int
paul718e3742002-12-13 20:15:29 +00005216bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5217 safi_t safi)
5218{
5219 int write = 0;
5220 struct peer *peer;
5221 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005222 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005223
5224 bgp_config_write_network (vty, bgp, afi, safi, &write);
5225
5226 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5227
paul1eb8ef22005-04-07 07:30:20 +00005228 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005229 {
5230 if (group->conf->afc[afi][safi])
5231 {
5232 bgp_config_write_family_header (vty, afi, safi, &write);
5233 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5234 }
5235 }
paul1eb8ef22005-04-07 07:30:20 +00005236 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005237 {
5238 if (peer->afc[afi][safi])
5239 {
5240 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5241 {
5242 bgp_config_write_family_header (vty, afi, safi, &write);
5243 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5244 }
5245 }
5246 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005247
5248 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5249
paul718e3742002-12-13 20:15:29 +00005250 if (write)
5251 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5252
5253 return write;
5254}
5255
5256int
5257bgp_config_write (struct vty *vty)
5258{
5259 int write = 0;
5260 struct bgp *bgp;
5261 struct peer_group *group;
5262 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005263 struct listnode *node, *nnode;
5264 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005265
5266 /* BGP Multiple instance. */
5267 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5268 {
5269 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5270 write++;
5271 }
5272
5273 /* BGP Config type. */
5274 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5275 {
5276 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5277 write++;
5278 }
5279
5280 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005281 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005282 {
5283 if (write)
5284 vty_out (vty, "!%s", VTY_NEWLINE);
5285
5286 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005287 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005288
5289 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5290 {
5291 if (bgp->name)
5292 vty_out (vty, " view %s", bgp->name);
5293 }
5294 vty_out (vty, "%s", VTY_NEWLINE);
5295
5296 /* No Synchronization */
5297 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5298 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5299
5300 /* BGP fast-external-failover. */
5301 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5302 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5303
5304 /* BGP router ID. */
5305 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5306 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5307 VTY_NEWLINE);
5308
paul848973c2003-08-13 00:32:49 +00005309 /* BGP log-neighbor-changes. */
Daniel Waltonc37b9bc2015-10-21 06:42:50 -07005310 if (!bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5311 vty_out (vty, " no bgp log-neighbor-changes%s", VTY_NEWLINE);
paul848973c2003-08-13 00:32:49 +00005312
paul718e3742002-12-13 20:15:29 +00005313 /* BGP configuration. */
5314 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5315 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5316
5317 /* BGP default ipv4-unicast. */
5318 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5319 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5320
5321 /* BGP default local-preference. */
5322 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5323 vty_out (vty, " bgp default local-preference %d%s",
5324 bgp->default_local_pref, VTY_NEWLINE);
5325
5326 /* BGP client-to-client reflection. */
5327 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5328 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5329
5330 /* BGP cluster ID. */
5331 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5332 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5333 VTY_NEWLINE);
5334
hassoe0701b72004-05-20 09:19:34 +00005335 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005336 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005337 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5338 VTY_NEWLINE);
5339
5340 /* Confederation peer */
5341 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005342 {
hassoe0701b72004-05-20 09:19:34 +00005343 int i;
paul718e3742002-12-13 20:15:29 +00005344
hassoe0701b72004-05-20 09:19:34 +00005345 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005346
hassoe0701b72004-05-20 09:19:34 +00005347 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005348 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005349
hassoe0701b72004-05-20 09:19:34 +00005350 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005351 }
5352
5353 /* BGP enforce-first-as. */
5354 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5355 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5356
5357 /* BGP deterministic-med. */
5358 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5359 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005360
5361 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005362 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5363 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5364 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005365 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5366 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5367
paul718e3742002-12-13 20:15:29 +00005368 /* BGP bestpath method. */
5369 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5370 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005371 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5372 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
Pradosh Mohapatra2fdd4552013-09-07 07:02:36 +00005373 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
5374 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
5375 }
paul718e3742002-12-13 20:15:29 +00005376 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5377 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5378 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5379 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5380 {
5381 vty_out (vty, " bgp bestpath med");
5382 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5383 vty_out (vty, " confed");
5384 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5385 vty_out (vty, " missing-as-worst");
5386 vty_out (vty, "%s", VTY_NEWLINE);
5387 }
5388
5389 /* BGP network import check. */
5390 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5391 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5392
5393 /* BGP scan interval. */
5394 bgp_config_write_scan_time (vty);
5395
5396 /* BGP flag dampening. */
5397 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5398 BGP_CONFIG_DAMPENING))
5399 bgp_config_write_damp (vty);
5400
5401 /* BGP static route configuration. */
5402 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5403
5404 /* BGP redistribute configuration. */
5405 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5406
5407 /* BGP timers configuration. */
5408 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5409 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5410 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5411 bgp->default_holdtime, VTY_NEWLINE);
5412
5413 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005414 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005415 {
5416 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5417 }
5418
5419 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005420 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005421 {
5422 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5423 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5424 }
5425
Josh Bailey165b5ff2011-07-20 20:43:22 -07005426 /* maximum-paths */
5427 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5428
paul718e3742002-12-13 20:15:29 +00005429 /* Distance configuration. */
5430 bgp_config_write_distance (vty, bgp);
5431
5432 /* No auto-summary */
5433 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5434 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5435
5436 /* IPv4 multicast configuration. */
5437 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5438
5439 /* IPv4 VPN configuration. */
5440 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5441
5442 /* IPv6 unicast configuration. */
5443 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5444
Paul Jakma37a217a2007-04-10 19:20:29 +00005445 /* IPv6 multicast configuration. */
5446 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5447
paul718e3742002-12-13 20:15:29 +00005448 write++;
5449 }
5450 return write;
5451}
5452
5453void
paul94f2b392005-06-28 12:44:16 +00005454bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005455{
5456 memset (&bgp_master, 0, sizeof (struct bgp_master));
5457
5458 bm = &bgp_master;
5459 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005460 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005461 bm->port = BGP_PORT_DEFAULT;
5462 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005463 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005464}
paul200df112005-06-01 11:17:05 +00005465
David Lamparter6b0655a2014-06-04 06:53:35 +02005466
paul718e3742002-12-13 20:15:29 +00005467void
paul94f2b392005-06-28 12:44:16 +00005468bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005469{
paul718e3742002-12-13 20:15:29 +00005470 /* BGP VTY commands installation. */
5471 bgp_vty_init ();
5472
paul718e3742002-12-13 20:15:29 +00005473 /* Init zebra. */
Donald Sharp774914f2015-10-14 08:50:39 -04005474 bgp_zebra_init (bm->master);
paul718e3742002-12-13 20:15:29 +00005475
5476 /* BGP inits. */
5477 bgp_attr_init ();
5478 bgp_debug_init ();
5479 bgp_dump_init ();
5480 bgp_route_init ();
5481 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005482 bgp_address_init ();
paul718e3742002-12-13 20:15:29 +00005483 bgp_scan_init ();
5484 bgp_mplsvpn_init ();
5485
5486 /* Access list initialize. */
5487 access_list_init ();
5488 access_list_add_hook (peer_distribute_update);
5489 access_list_delete_hook (peer_distribute_update);
5490
5491 /* Filter list initialize. */
5492 bgp_filter_init ();
5493 as_list_add_hook (peer_aslist_update);
5494 as_list_delete_hook (peer_aslist_update);
5495
5496 /* Prefix list initialize.*/
5497 prefix_list_init ();
5498 prefix_list_add_hook (peer_prefix_list_update);
5499 prefix_list_delete_hook (peer_prefix_list_update);
5500
5501 /* Community list initialize. */
5502 bgp_clist = community_list_init ();
5503
5504#ifdef HAVE_SNMP
5505 bgp_snmp_init ();
5506#endif /* HAVE_SNMP */
5507}
paul545acaf2004-04-20 15:13:15 +00005508
5509void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005510bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005511{
paul545acaf2004-04-20 15:13:15 +00005512 struct bgp *bgp;
5513 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005514 struct listnode *node, *nnode;
5515 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005516
paul1eb8ef22005-04-07 07:30:20 +00005517 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5518 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005519 if (peer->status == Established)
5520 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5521 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005522
paul545acaf2004-04-20 15:13:15 +00005523 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005524
paule210cf92005-06-15 19:15:35 +00005525 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005526 {
5527 work_queue_free (bm->process_main_queue);
5528 bm->process_main_queue = NULL;
5529 }
paule210cf92005-06-15 19:15:35 +00005530 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005531 {
5532 work_queue_free (bm->process_rsclient_queue);
5533 bm->process_rsclient_queue = NULL;
5534 }
paul545acaf2004-04-20 15:13:15 +00005535}