blob: 79bcaaf05c1e65033297152d39f451c3b1baf3d7 [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);
598 prefix_bgp_orf_remove_all (orf_name);
599
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)
724 XFREE (MTYPE_PEER_DESC, peer->desc);
725
726 /* Free allocated host character. */
727 if (peer->host)
728 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
729
730 /* Update source configuration. */
731 if (peer->update_source)
732 sockunion_free (peer->update_source);
733
734 if (peer->update_if)
735 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
Paul Jakmaa625ca32006-03-30 14:12:38 +0000736
737 if (peer->clear_node_queue)
738 work_queue_free (peer->clear_node_queue);
739
Paul Jakmaca058a32006-09-14 02:58:49 +0000740 bgp_sync_delete (peer);
paul200df112005-06-01 11:17:05 +0000741 memset (peer, 0, sizeof (struct peer));
742
743 XFREE (MTYPE_BGP_PEER, peer);
744}
745
746/* increase reference count on a struct peer */
747struct peer *
748peer_lock (struct peer *peer)
749{
750 assert (peer && (peer->lock >= 0));
Paul Jakmaca058a32006-09-14 02:58:49 +0000751
paul200df112005-06-01 11:17:05 +0000752 peer->lock++;
753
754 return peer;
755}
756
757/* decrease reference count on a struct peer
758 * struct peer is freed and NULL returned if last reference
759 */
760struct peer *
761peer_unlock (struct peer *peer)
762{
763 assert (peer && (peer->lock > 0));
764
765 peer->lock--;
766
767 if (peer->lock == 0)
768 {
769#if 0
770 zlog_debug ("unlocked and freeing");
771 zlog_backtrace (LOG_DEBUG);
772#endif
773 peer_free (peer);
774 return NULL;
775 }
776
777#if 0
778 if (peer->lock == 1)
779 {
780 zlog_debug ("unlocked to 1");
781 zlog_backtrace (LOG_DEBUG);
782 }
783#endif
784
785 return peer;
786}
787
788/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000789static struct peer *
Paul Jakma6f585442006-10-22 19:13:07 +0000790peer_new (struct bgp *bgp)
paul718e3742002-12-13 20:15:29 +0000791{
792 afi_t afi;
793 safi_t safi;
794 struct peer *peer;
795 struct servent *sp;
Paul Jakma6f585442006-10-22 19:13:07 +0000796
797 /* bgp argument is absolutely required */
798 assert (bgp);
799 if (!bgp)
800 return NULL;
801
paul718e3742002-12-13 20:15:29 +0000802 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000803 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000804
805 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000806 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000807 peer->v_start = BGP_INIT_START_TIMER;
808 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
809 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
810 peer->status = Idle;
811 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000812 peer->weight = 0;
Paul Jakma0df7c912008-07-21 21:02:49 +0000813 peer->password = NULL;
Paul Jakma6f585442006-10-22 19:13:07 +0000814 peer->bgp = bgp;
Paul Jakmaca058a32006-09-14 02:58:49 +0000815 peer = peer_lock (peer); /* initial reference */
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700816 bgp_lock (bgp);
paul718e3742002-12-13 20:15:29 +0000817
818 /* Set default flags. */
819 for (afi = AFI_IP; afi < AFI_MAX; afi++)
820 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
821 {
822 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
823 {
824 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
825 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
826 }
827 peer->orf_plist[afi][safi] = NULL;
828 }
829 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
830
831 /* Create buffers. */
832 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
833 peer->obuf = stream_fifo_new ();
834 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000835 peer->scratch = stream_new (BGP_MAX_PACKET_SIZE);
paul718e3742002-12-13 20:15:29 +0000836
837 bgp_sync_init (peer);
838
839 /* Get service port number. */
840 sp = getservbyname ("bgp", "tcp");
841 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
842
843 return peer;
844}
845
846/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000847static struct peer *
paul718e3742002-12-13 20:15:29 +0000848peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
849 as_t remote_as, afi_t afi, safi_t safi)
850{
851 int active;
852 struct peer *peer;
853 char buf[SU_ADDRSTRLEN];
854
Paul Jakma6f585442006-10-22 19:13:07 +0000855 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000856 peer->su = *su;
857 peer->local_as = local_as;
858 peer->as = remote_as;
859 peer->local_id = bgp->router_id;
860 peer->v_holdtime = bgp->default_holdtime;
861 peer->v_keepalive = bgp->default_keepalive;
862 if (peer_sort (peer) == BGP_PEER_IBGP)
863 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
864 else
865 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000866
867 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000868 listnode_add_sort (bgp->peer, peer);
869
870 active = peer_active (peer);
871
872 if (afi && safi)
873 peer->afc[afi][safi] = 1;
874
Stephen Hemminger65957882010-01-15 16:22:10 +0300875 /* Last read and reset time set */
876 peer->readtime = peer->resettime = bgp_clock ();
paul848973c2003-08-13 00:32:49 +0000877
paul718e3742002-12-13 20:15:29 +0000878 /* Default TTL set. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000879 peer->ttl = (peer->sort == BGP_PEER_IBGP) ? 255 : 1;
paul718e3742002-12-13 20:15:29 +0000880
881 /* Make peer's address string. */
882 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000883 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000884
885 /* Set up peer's events and timers. */
886 if (! active && peer_active (peer))
887 bgp_timer_set (peer);
888
889 return peer;
890}
891
pauleb821182004-05-01 08:44:08 +0000892/* Make accept BGP peer. Called from bgp_accept (). */
893struct peer *
894peer_create_accept (struct bgp *bgp)
895{
896 struct peer *peer;
897
Paul Jakma6f585442006-10-22 19:13:07 +0000898 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000899
900 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000901 listnode_add_sort (bgp->peer, peer);
902
903 return peer;
904}
905
paul718e3742002-12-13 20:15:29 +0000906/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000907static void
paul718e3742002-12-13 20:15:29 +0000908peer_as_change (struct peer *peer, as_t as)
909{
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000910 bgp_peer_sort_t type;
paul718e3742002-12-13 20:15:29 +0000911
912 /* Stop peer. */
913 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
914 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000915 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000916 {
917 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
918 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
919 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
920 }
paul718e3742002-12-13 20:15:29 +0000921 else
922 BGP_EVENT_ADD (peer, BGP_Stop);
923 }
924 type = peer_sort (peer);
925 peer->as = as;
926
paul848973c2003-08-13 00:32:49 +0000927 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
928 && ! bgp_confederation_peers_check (peer->bgp, as)
929 && peer->bgp->as != as)
930 peer->local_as = peer->bgp->confed_id;
931 else
932 peer->local_as = peer->bgp->as;
933
paul718e3742002-12-13 20:15:29 +0000934 /* Advertisement-interval reset */
935 if (peer_sort (peer) == BGP_PEER_IBGP)
936 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
937 else
938 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
939
940 /* TTL reset */
941 if (peer_sort (peer) == BGP_PEER_IBGP)
942 peer->ttl = 255;
943 else if (type == BGP_PEER_IBGP)
944 peer->ttl = 1;
945
946 /* reflector-client reset */
947 if (peer_sort (peer) != BGP_PEER_IBGP)
948 {
949 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
950 PEER_FLAG_REFLECTOR_CLIENT);
951 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
952 PEER_FLAG_REFLECTOR_CLIENT);
953 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
954 PEER_FLAG_REFLECTOR_CLIENT);
955 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
956 PEER_FLAG_REFLECTOR_CLIENT);
957 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
958 PEER_FLAG_REFLECTOR_CLIENT);
959 }
960
961 /* local-as reset */
962 if (peer_sort (peer) != BGP_PEER_EBGP)
963 {
964 peer->change_local_as = 0;
965 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +0000966 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +0000967 }
968}
969
970/* If peer does not exist, create new one. If peer already exists,
971 set AS number to the peer. */
972int
973peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
974 afi_t afi, safi_t safi)
975{
976 struct peer *peer;
977 as_t local_as;
978
979 peer = peer_lookup (bgp, su);
980
981 if (peer)
982 {
983 /* When this peer is a member of peer-group. */
984 if (peer->group)
985 {
986 if (peer->group->conf->as)
987 {
988 /* Return peer group's AS number. */
989 *as = peer->group->conf->as;
990 return BGP_ERR_PEER_GROUP_MEMBER;
991 }
992 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
993 {
994 if (bgp->as != *as)
995 {
996 *as = peer->as;
997 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
998 }
999 }
1000 else
1001 {
1002 if (bgp->as == *as)
1003 {
1004 *as = peer->as;
1005 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1006 }
1007 }
1008 }
1009
1010 /* Existing peer's AS number change. */
1011 if (peer->as != *as)
1012 peer_as_change (peer, *as);
1013 }
1014 else
1015 {
1016
1017 /* If the peer is not part of our confederation, and its not an
1018 iBGP peer then spoof the source AS */
1019 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1020 && ! bgp_confederation_peers_check (bgp, *as)
1021 && bgp->as != *as)
1022 local_as = bgp->confed_id;
1023 else
1024 local_as = bgp->as;
1025
1026 /* If this is IPv4 unicast configuration and "no bgp default
1027 ipv4-unicast" is specified. */
1028
1029 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1030 && afi == AFI_IP && safi == SAFI_UNICAST)
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001031 peer_create (su, bgp, local_as, *as, 0, 0);
paul718e3742002-12-13 20:15:29 +00001032 else
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001033 peer_create (su, bgp, local_as, *as, afi, safi);
paul718e3742002-12-13 20:15:29 +00001034 }
1035
1036 return 0;
1037}
1038
1039/* Activate the peer or peer group for specified AFI and SAFI. */
1040int
1041peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1042{
1043 int active;
1044
1045 if (peer->afc[afi][safi])
1046 return 0;
1047
1048 /* Activate the address family configuration. */
1049 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1050 peer->afc[afi][safi] = 1;
1051 else
1052 {
1053 active = peer_active (peer);
1054
1055 peer->afc[afi][safi] = 1;
1056
1057 if (! active && peer_active (peer))
1058 bgp_timer_set (peer);
1059 else
1060 {
1061 if (peer->status == Established)
1062 {
1063 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1064 {
1065 peer->afc_adv[afi][safi] = 1;
1066 bgp_capability_send (peer, afi, safi,
1067 CAPABILITY_CODE_MP,
1068 CAPABILITY_ACTION_SET);
1069 if (peer->afc_recv[afi][safi])
1070 {
1071 peer->afc_nego[afi][safi] = 1;
1072 bgp_announce_route (peer, afi, safi);
1073 }
1074 }
1075 else
hassoe0701b72004-05-20 09:19:34 +00001076 {
1077 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1078 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1079 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1080 }
paul718e3742002-12-13 20:15:29 +00001081 }
1082 }
1083 }
1084 return 0;
1085}
1086
1087int
1088peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1089{
1090 struct peer_group *group;
1091 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001092 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001093
1094 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1095 {
1096 group = peer->group;
1097
paul1eb8ef22005-04-07 07:30:20 +00001098 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001099 {
1100 if (peer1->af_group[afi][safi])
1101 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1102 }
1103 }
1104 else
1105 {
1106 if (peer->af_group[afi][safi])
1107 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1108 }
1109
1110 if (! peer->afc[afi][safi])
1111 return 0;
1112
1113 /* De-activate the address family configuration. */
1114 peer->afc[afi][safi] = 0;
1115 peer_af_flag_reset (peer, afi, safi);
1116
1117 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1118 {
1119 if (peer->status == Established)
1120 {
1121 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1122 {
1123 peer->afc_adv[afi][safi] = 0;
1124 peer->afc_nego[afi][safi] = 0;
1125
1126 if (peer_active_nego (peer))
1127 {
1128 bgp_capability_send (peer, afi, safi,
1129 CAPABILITY_CODE_MP,
1130 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001131 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001132 peer->pcount[afi][safi] = 0;
1133 }
1134 else
hassoe0701b72004-05-20 09:19:34 +00001135 {
1136 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1137 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1138 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1139 }
paul718e3742002-12-13 20:15:29 +00001140 }
1141 else
hassoe0701b72004-05-20 09:19:34 +00001142 {
1143 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1144 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1145 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1146 }
paul718e3742002-12-13 20:15:29 +00001147 }
1148 }
1149 return 0;
1150}
1151
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001152static void
hasso93406d82005-02-02 14:40:33 +00001153peer_nsf_stop (struct peer *peer)
1154{
1155 afi_t afi;
1156 safi_t safi;
1157
1158 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1159 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1160
1161 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +04001162 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +00001163 peer->nsf[afi][safi] = 0;
1164
1165 if (peer->t_gr_restart)
1166 {
1167 BGP_TIMER_OFF (peer->t_gr_restart);
1168 if (BGP_DEBUG (events, EVENTS))
1169 zlog_debug ("%s graceful restart timer stopped", peer->host);
1170 }
1171 if (peer->t_gr_stale)
1172 {
1173 BGP_TIMER_OFF (peer->t_gr_stale);
1174 if (BGP_DEBUG (events, EVENTS))
1175 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1176 }
1177 bgp_clear_route_all (peer);
1178}
1179
Paul Jakmaca058a32006-09-14 02:58:49 +00001180/* Delete peer from confguration.
1181 *
1182 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1183 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1184 *
1185 * This function /should/ take care to be idempotent, to guard against
1186 * it being called multiple times through stray events that come in
1187 * that happen to result in this function being called again. That
1188 * said, getting here for a "Deleted" peer is a bug in the neighbour
1189 * FSM.
1190 */
paul718e3742002-12-13 20:15:29 +00001191int
1192peer_delete (struct peer *peer)
1193{
1194 int i;
1195 afi_t afi;
1196 safi_t safi;
1197 struct bgp *bgp;
1198 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001199 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001200
Paul Jakmaca058a32006-09-14 02:58:49 +00001201 assert (peer->status != Deleted);
1202
paul718e3742002-12-13 20:15:29 +00001203 bgp = peer->bgp;
1204
hasso93406d82005-02-02 14:40:33 +00001205 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1206 peer_nsf_stop (peer);
1207
Chris Caputo228da422009-07-18 05:44:03 +00001208 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001209 relationship. */
1210 if (peer->group)
1211 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001212 if ((pn = listnode_lookup (peer->group->peer, peer)))
1213 {
1214 peer = peer_unlock (peer); /* group->peer list reference */
1215 list_delete_node (peer->group->peer, pn);
1216 }
paul718e3742002-12-13 20:15:29 +00001217 peer->group = NULL;
1218 }
paul200df112005-06-01 11:17:05 +00001219
paul718e3742002-12-13 20:15:29 +00001220 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001221 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1222 * executed after peer structure is deleted.
1223 */
hassoe0701b72004-05-20 09:19:34 +00001224 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001225 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001226 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001227
1228 /* Password configuration */
1229 if (peer->password)
1230 {
1231 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1232 peer->password = NULL;
1233
1234 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1235 bgp_md5_set (peer);
1236 }
1237
Paul Jakmaca058a32006-09-14 02:58:49 +00001238 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001239
paul718e3742002-12-13 20:15:29 +00001240 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001241 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1242 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001243 {
Chris Caputo228da422009-07-18 05:44:03 +00001244 peer_unlock (peer); /* bgp peer list reference */
1245 list_delete_node (bgp->peer, pn);
1246 }
paul200df112005-06-01 11:17:05 +00001247
Chris Caputo228da422009-07-18 05:44:03 +00001248 if (peer_rsclient_active (peer)
1249 && (pn = listnode_lookup (bgp->rsclient, peer)))
1250 {
1251 peer_unlock (peer); /* rsclient list reference */
1252 list_delete_node (bgp->rsclient, pn);
1253
1254 /* Clear our own rsclient ribs. */
1255 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1256 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1257 if (CHECK_FLAG(peer->af_flags[afi][safi],
1258 PEER_FLAG_RSERVER_CLIENT))
1259 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001260 }
1261
1262 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1263 member of a peer_group. */
1264 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1265 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1266 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001267 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001268
paul200df112005-06-01 11:17:05 +00001269 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001270 if (peer->ibuf)
1271 stream_free (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001272 if (peer->obuf)
1273 stream_fifo_free (peer->obuf);
paul718e3742002-12-13 20:15:29 +00001274 if (peer->work)
1275 stream_free (peer->work);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00001276 if (peer->scratch)
1277 stream_free(peer->scratch);
Paul Jakma18937402006-07-27 19:05:12 +00001278 peer->obuf = NULL;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00001279 peer->work = peer->scratch = peer->ibuf = NULL;
Paul Jakma18937402006-07-27 19:05:12 +00001280
paul718e3742002-12-13 20:15:29 +00001281 /* Local and remote addresses. */
1282 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001283 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001284 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001285 sockunion_free (peer->su_remote);
Paul Jakma18937402006-07-27 19:05:12 +00001286 peer->su_local = peer->su_remote = NULL;
paul200df112005-06-01 11:17:05 +00001287
paul718e3742002-12-13 20:15:29 +00001288 /* Free filter related memory. */
1289 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1290 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1291 {
1292 filter = &peer->filter[afi][safi];
1293
1294 for (i = FILTER_IN; i < FILTER_MAX; i++)
1295 {
1296 if (filter->dlist[i].name)
1297 free (filter->dlist[i].name);
1298 if (filter->plist[i].name)
1299 free (filter->plist[i].name);
1300 if (filter->aslist[i].name)
1301 free (filter->aslist[i].name);
paul200df112005-06-01 11:17:05 +00001302
1303 filter->dlist[i].name = NULL;
1304 filter->plist[i].name = NULL;
1305 filter->aslist[i].name = NULL;
1306 }
1307 for (i = RMAP_IN; i < RMAP_MAX; i++)
1308 {
paul718e3742002-12-13 20:15:29 +00001309 if (filter->map[i].name)
1310 free (filter->map[i].name);
paul200df112005-06-01 11:17:05 +00001311 filter->map[i].name = NULL;
paul718e3742002-12-13 20:15:29 +00001312 }
1313
1314 if (filter->usmap.name)
1315 free (filter->usmap.name);
1316
1317 if (peer->default_rmap[afi][safi].name)
1318 free (peer->default_rmap[afi][safi].name);
paul200df112005-06-01 11:17:05 +00001319
1320 filter->usmap.name = NULL;
1321 peer->default_rmap[afi][safi].name = NULL;
paul718e3742002-12-13 20:15:29 +00001322 }
paul200df112005-06-01 11:17:05 +00001323
1324 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001325
1326 return 0;
1327}
David Lamparter6b0655a2014-06-04 06:53:35 +02001328
paul94f2b392005-06-28 12:44:16 +00001329static int
paul718e3742002-12-13 20:15:29 +00001330peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1331{
1332 return strcmp (g1->name, g2->name);
1333}
1334
1335/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001336static int
paul718e3742002-12-13 20:15:29 +00001337peer_group_active (struct peer *peer)
1338{
1339 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1340 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1341 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1342 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1343 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1344 return 1;
1345 return 0;
1346}
1347
1348/* Peer group cofiguration. */
1349static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001350peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001351{
1352 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1353 sizeof (struct peer_group));
1354}
1355
paul94f2b392005-06-28 12:44:16 +00001356static void
paul718e3742002-12-13 20:15:29 +00001357peer_group_free (struct peer_group *group)
1358{
1359 XFREE (MTYPE_PEER_GROUP, group);
1360}
1361
1362struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001363peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001364{
1365 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001366 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001367
paul1eb8ef22005-04-07 07:30:20 +00001368 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001369 {
1370 if (strcmp (group->name, name) == 0)
1371 return group;
1372 }
1373 return NULL;
1374}
1375
1376struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001377peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001378{
1379 struct peer_group *group;
1380
1381 group = peer_group_lookup (bgp, name);
1382 if (group)
1383 return group;
1384
1385 group = peer_group_new ();
1386 group->bgp = bgp;
1387 group->name = strdup (name);
1388 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001389 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001390 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1391 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001392 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001393 group->conf->group = group;
1394 group->conf->as = 0;
1395 group->conf->ttl = 1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001396 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001397 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1398 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1399 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1400 group->conf->keepalive = 0;
1401 group->conf->holdtime = 0;
1402 group->conf->connect = 0;
1403 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1404 listnode_add_sort (bgp->group, group);
1405
1406 return 0;
1407}
1408
paul94f2b392005-06-28 12:44:16 +00001409static void
paul718e3742002-12-13 20:15:29 +00001410peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1411 afi_t afi, safi_t safi)
1412{
1413 int in = FILTER_IN;
1414 int out = FILTER_OUT;
1415 struct peer *conf;
1416 struct bgp_filter *pfilter;
1417 struct bgp_filter *gfilter;
1418
1419 conf = group->conf;
1420 pfilter = &peer->filter[afi][safi];
1421 gfilter = &conf->filter[afi][safi];
1422
1423 /* remote-as */
1424 if (conf->as)
1425 peer->as = conf->as;
1426
1427 /* remote-as */
1428 if (conf->change_local_as)
1429 peer->change_local_as = conf->change_local_as;
1430
1431 /* TTL */
1432 peer->ttl = conf->ttl;
1433
Nick Hilliardfa411a22011-03-23 15:33:17 +00001434 /* GTSM hops */
1435 peer->gtsm_hops = conf->gtsm_hops;
1436
paul718e3742002-12-13 20:15:29 +00001437 /* Weight */
1438 peer->weight = conf->weight;
1439
1440 /* peer flags apply */
1441 peer->flags = conf->flags;
1442 /* peer af_flags apply */
1443 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1444 /* peer config apply */
1445 peer->config = conf->config;
1446
1447 /* peer timers apply */
1448 peer->holdtime = conf->holdtime;
1449 peer->keepalive = conf->keepalive;
1450 peer->connect = conf->connect;
1451 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1452 peer->v_connect = conf->connect;
1453 else
1454 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1455
1456 /* advertisement-interval reset */
1457 if (peer_sort (peer) == BGP_PEER_IBGP)
1458 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1459 else
1460 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1461
Paul Jakma0df7c912008-07-21 21:02:49 +00001462 /* password apply */
Roman Hoog Antink0e4303d2013-01-18 13:52:03 +01001463 if (conf->password && !peer->password)
Paul Jakma0df7c912008-07-21 21:02:49 +00001464 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
Paul Jakma0df7c912008-07-21 21:02:49 +00001465
1466 bgp_md5_set (peer);
1467
paul718e3742002-12-13 20:15:29 +00001468 /* maximum-prefix */
1469 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001470 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001471 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001472
1473 /* allowas-in */
1474 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1475
paulfee0f4c2004-09-13 05:12:46 +00001476 /* route-server-client */
1477 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1478 {
1479 /* Make peer's RIB point to group's RIB. */
1480 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1481
1482 /* Import policy. */
1483 if (pfilter->map[RMAP_IMPORT].name)
1484 free (pfilter->map[RMAP_IMPORT].name);
1485 if (gfilter->map[RMAP_IMPORT].name)
1486 {
1487 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1488 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1489 }
1490 else
1491 {
1492 pfilter->map[RMAP_IMPORT].name = NULL;
1493 pfilter->map[RMAP_IMPORT].map = NULL;
1494 }
1495
1496 /* Export policy. */
1497 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1498 {
1499 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1500 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1501 }
1502 }
1503
paul718e3742002-12-13 20:15:29 +00001504 /* default-originate route-map */
1505 if (conf->default_rmap[afi][safi].name)
1506 {
1507 if (peer->default_rmap[afi][safi].name)
1508 free (peer->default_rmap[afi][safi].name);
1509 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1510 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1511 }
1512
1513 /* update-source apply */
1514 if (conf->update_source)
1515 {
1516 if (peer->update_source)
1517 sockunion_free (peer->update_source);
1518 if (peer->update_if)
1519 {
1520 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1521 peer->update_if = NULL;
1522 }
1523 peer->update_source = sockunion_dup (conf->update_source);
1524 }
1525 else if (conf->update_if)
1526 {
1527 if (peer->update_if)
1528 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1529 if (peer->update_source)
1530 {
1531 sockunion_free (peer->update_source);
1532 peer->update_source = NULL;
1533 }
1534 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1535 }
1536
1537 /* inbound filter apply */
1538 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1539 {
1540 if (pfilter->dlist[in].name)
1541 free (pfilter->dlist[in].name);
1542 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1543 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1544 }
1545 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1546 {
1547 if (pfilter->plist[in].name)
1548 free (pfilter->plist[in].name);
1549 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1550 pfilter->plist[in].plist = gfilter->plist[in].plist;
1551 }
1552 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1553 {
1554 if (pfilter->aslist[in].name)
1555 free (pfilter->aslist[in].name);
1556 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1557 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1558 }
paulfee0f4c2004-09-13 05:12:46 +00001559 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001560 {
paulfee0f4c2004-09-13 05:12:46 +00001561 if (pfilter->map[RMAP_IN].name)
1562 free (pfilter->map[RMAP_IN].name);
1563 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1564 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001565 }
1566
1567 /* outbound filter apply */
1568 if (gfilter->dlist[out].name)
1569 {
1570 if (pfilter->dlist[out].name)
1571 free (pfilter->dlist[out].name);
1572 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1573 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1574 }
1575 else
1576 {
1577 if (pfilter->dlist[out].name)
1578 free (pfilter->dlist[out].name);
1579 pfilter->dlist[out].name = NULL;
1580 pfilter->dlist[out].alist = NULL;
1581 }
1582 if (gfilter->plist[out].name)
1583 {
1584 if (pfilter->plist[out].name)
1585 free (pfilter->plist[out].name);
1586 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1587 pfilter->plist[out].plist = gfilter->plist[out].plist;
1588 }
1589 else
1590 {
1591 if (pfilter->plist[out].name)
1592 free (pfilter->plist[out].name);
1593 pfilter->plist[out].name = NULL;
1594 pfilter->plist[out].plist = NULL;
1595 }
1596 if (gfilter->aslist[out].name)
1597 {
1598 if (pfilter->aslist[out].name)
1599 free (pfilter->aslist[out].name);
1600 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1601 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1602 }
1603 else
1604 {
1605 if (pfilter->aslist[out].name)
1606 free (pfilter->aslist[out].name);
1607 pfilter->aslist[out].name = NULL;
1608 pfilter->aslist[out].aslist = NULL;
1609 }
paulfee0f4c2004-09-13 05:12:46 +00001610 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001611 {
paulfee0f4c2004-09-13 05:12:46 +00001612 if (pfilter->map[RMAP_OUT].name)
1613 free (pfilter->map[RMAP_OUT].name);
1614 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1615 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001616 }
1617 else
1618 {
paulfee0f4c2004-09-13 05:12:46 +00001619 if (pfilter->map[RMAP_OUT].name)
1620 free (pfilter->map[RMAP_OUT].name);
1621 pfilter->map[RMAP_OUT].name = NULL;
1622 pfilter->map[RMAP_OUT].map = NULL;
1623 }
1624
1625 /* RS-client's import/export route-maps. */
1626 if (gfilter->map[RMAP_IMPORT].name)
1627 {
1628 if (pfilter->map[RMAP_IMPORT].name)
1629 free (pfilter->map[RMAP_IMPORT].name);
1630 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1631 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1632 }
1633 else
1634 {
1635 if (pfilter->map[RMAP_IMPORT].name)
1636 free (pfilter->map[RMAP_IMPORT].name);
1637 pfilter->map[RMAP_IMPORT].name = NULL;
1638 pfilter->map[RMAP_IMPORT].map = NULL;
1639 }
1640 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1641 {
1642 if (pfilter->map[RMAP_EXPORT].name)
1643 free (pfilter->map[RMAP_EXPORT].name);
1644 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1645 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001646 }
1647
1648 if (gfilter->usmap.name)
1649 {
1650 if (pfilter->usmap.name)
1651 free (pfilter->usmap.name);
1652 pfilter->usmap.name = strdup (gfilter->usmap.name);
1653 pfilter->usmap.map = gfilter->usmap.map;
1654 }
1655 else
1656 {
1657 if (pfilter->usmap.name)
1658 free (pfilter->usmap.name);
1659 pfilter->usmap.name = NULL;
1660 pfilter->usmap.map = NULL;
1661 }
1662}
1663
1664/* Peer group's remote AS configuration. */
1665int
paulfd79ac92004-10-13 05:06:08 +00001666peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001667{
1668 struct peer_group *group;
1669 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001670 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001671
1672 group = peer_group_lookup (bgp, group_name);
1673 if (! group)
1674 return -1;
1675
1676 if (group->conf->as == *as)
1677 return 0;
1678
1679 /* When we setup peer-group AS number all peer group member's AS
1680 number must be updated to same number. */
1681 peer_as_change (group->conf, *as);
1682
paul1eb8ef22005-04-07 07:30:20 +00001683 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001684 {
1685 if (peer->as != *as)
1686 peer_as_change (peer, *as);
1687 }
1688
1689 return 0;
1690}
1691
1692int
1693peer_group_delete (struct peer_group *group)
1694{
1695 struct bgp *bgp;
1696 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001697 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001698
1699 bgp = group->bgp;
1700
paul1eb8ef22005-04-07 07:30:20 +00001701 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001702 {
1703 peer->group = NULL;
1704 peer_delete (peer);
1705 }
1706 list_delete (group->peer);
1707
1708 free (group->name);
1709 group->name = NULL;
1710
1711 group->conf->group = NULL;
1712 peer_delete (group->conf);
1713
1714 /* Delete from all peer_group list. */
1715 listnode_delete (bgp->group, group);
1716
1717 peer_group_free (group);
1718
1719 return 0;
1720}
1721
1722int
1723peer_group_remote_as_delete (struct peer_group *group)
1724{
1725 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001726 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001727
1728 if (! group->conf->as)
1729 return 0;
1730
paul1eb8ef22005-04-07 07:30:20 +00001731 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001732 {
1733 peer->group = NULL;
1734 peer_delete (peer);
1735 }
1736 list_delete_all_node (group->peer);
1737
1738 group->conf->as = 0;
1739
1740 return 0;
1741}
1742
1743/* Bind specified peer to peer group. */
1744int
1745peer_group_bind (struct bgp *bgp, union sockunion *su,
1746 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1747{
1748 struct peer *peer;
1749 int first_member = 0;
1750
1751 /* Check peer group's address family. */
1752 if (! group->conf->afc[afi][safi])
1753 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1754
1755 /* Lookup the peer. */
1756 peer = peer_lookup (bgp, su);
1757
1758 /* Create a new peer. */
1759 if (! peer)
1760 {
1761 if (! group->conf->as)
1762 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1763
1764 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1765 peer->group = group;
1766 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001767
Paul Jakmaca058a32006-09-14 02:58:49 +00001768 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001769 listnode_add (group->peer, peer);
1770 peer_group2peer_config_copy (group, peer, afi, safi);
1771
1772 return 0;
1773 }
1774
1775 /* When the peer already belongs to peer group, check the consistency. */
1776 if (peer->af_group[afi][safi])
1777 {
1778 if (strcmp (peer->group->name, group->name) != 0)
1779 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1780
1781 return 0;
1782 }
1783
1784 /* Check current peer group configuration. */
1785 if (peer_group_active (peer)
1786 && strcmp (peer->group->name, group->name) != 0)
1787 return BGP_ERR_PEER_GROUP_MISMATCH;
1788
1789 if (! group->conf->as)
1790 {
1791 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1792 && peer_sort (group->conf) != peer_sort (peer))
1793 {
1794 if (as)
1795 *as = peer->as;
1796 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1797 }
1798
1799 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1800 first_member = 1;
1801 }
1802
1803 peer->af_group[afi][safi] = 1;
1804 peer->afc[afi][safi] = 1;
1805 if (! peer->group)
1806 {
1807 peer->group = group;
paul200df112005-06-01 11:17:05 +00001808
Paul Jakmaca058a32006-09-14 02:58:49 +00001809 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001810 listnode_add (group->peer, peer);
1811 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001812 else
1813 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001814
1815 if (first_member)
1816 {
1817 /* Advertisement-interval reset */
1818 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1819 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1820 else
1821 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1822
1823 /* ebgp-multihop reset */
1824 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1825 group->conf->ttl = 255;
1826
1827 /* local-as reset */
1828 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1829 {
1830 group->conf->change_local_as = 0;
1831 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001832 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001833 }
1834 }
paulfee0f4c2004-09-13 05:12:46 +00001835
1836 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1837 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001838 struct listnode *pn;
1839
paulfee0f4c2004-09-13 05:12:46 +00001840 /* If it's not configured as RSERVER_CLIENT in any other address
1841 family, without being member of a peer_group, remove it from
1842 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001843 if (! peer_rsclient_active (peer)
1844 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001845 {
1846 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001847 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001848
1849 /* Clear our own rsclient rib for this afi/safi. */
1850 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001851 }
paulfee0f4c2004-09-13 05:12:46 +00001852
Paul Jakmab608d5b2008-07-02 02:12:07 +00001853 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001854
1855 /* Import policy. */
1856 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1857 {
1858 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1859 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1860 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1861 }
1862
1863 /* Export policy. */
1864 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1865 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1866 {
1867 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1868 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1869 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1870 }
1871 }
1872
paul718e3742002-12-13 20:15:29 +00001873 peer_group2peer_config_copy (group, peer, afi, safi);
1874
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001875 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001876 {
1877 peer->last_reset = PEER_DOWN_RMAP_BIND;
1878 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1879 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1880 }
paul718e3742002-12-13 20:15:29 +00001881 else
1882 BGP_EVENT_ADD (peer, BGP_Stop);
1883
1884 return 0;
1885}
1886
1887int
1888peer_group_unbind (struct bgp *bgp, struct peer *peer,
1889 struct peer_group *group, afi_t afi, safi_t safi)
1890{
1891 if (! peer->af_group[afi][safi])
1892 return 0;
1893
1894 if (group != peer->group)
1895 return BGP_ERR_PEER_GROUP_MISMATCH;
1896
1897 peer->af_group[afi][safi] = 0;
1898 peer->afc[afi][safi] = 0;
1899 peer_af_flag_reset (peer, afi, safi);
1900
paulfee0f4c2004-09-13 05:12:46 +00001901 if (peer->rib[afi][safi])
1902 peer->rib[afi][safi] = NULL;
1903
paul718e3742002-12-13 20:15:29 +00001904 if (! peer_group_active (peer))
1905 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001906 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001907 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001908 listnode_delete (group->peer, peer);
1909 peer->group = NULL;
1910 if (group->conf->as)
1911 {
1912 peer_delete (peer);
1913 return 0;
1914 }
1915 peer_global_config_reset (peer);
1916 }
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_UNBIND;
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}
David Lamparter6b0655a2014-06-04 06:53:35 +02001929
Vipin Kumardd49eb12014-09-30 14:36:38 -07001930
1931static int
1932bgp_startup_timer_expire (struct thread *thread)
1933{
1934 struct bgp *bgp;
1935
1936 bgp = THREAD_ARG (thread);
1937 bgp->t_startup = NULL;
1938
1939 return 0;
1940}
1941
paul718e3742002-12-13 20:15:29 +00001942/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001943static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001944bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001945{
1946 struct bgp *bgp;
1947 afi_t afi;
1948 safi_t safi;
1949
paul200df112005-06-01 11:17:05 +00001950 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1951 return NULL;
1952
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07001953 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00001954 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00001955 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00001956
1957 bgp->peer = list_new ();
1958 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1959
1960 bgp->group = list_new ();
1961 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1962
paulfee0f4c2004-09-13 05:12:46 +00001963 bgp->rsclient = list_new ();
1964 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1965
paul718e3742002-12-13 20:15:29 +00001966 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1967 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1968 {
Paul Jakma64e580a2006-02-21 01:09:01 +00001969 bgp->route[afi][safi] = bgp_table_init (afi, safi);
1970 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1971 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07001972 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
1973 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00001974 }
1975
1976 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1977 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1978 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001979 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1980 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001981
1982 bgp->as = *as;
1983
1984 if (name)
1985 bgp->name = strdup (name);
1986
Vipin Kumardd49eb12014-09-30 14:36:38 -07001987 THREAD_TIMER_ON (master, bgp->t_startup, bgp_startup_timer_expire,
1988 bgp, bgp->restart_time);
1989
paul718e3742002-12-13 20:15:29 +00001990 return bgp;
1991}
1992
1993/* Return first entry of BGP. */
1994struct bgp *
paul94f2b392005-06-28 12:44:16 +00001995bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001996{
1997 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001998 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001999 return NULL;
2000}
2001
2002/* Lookup BGP entry. */
2003struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002004bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00002005{
2006 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002007 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002008
paul1eb8ef22005-04-07 07:30:20 +00002009 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002010 if (bgp->as == as
2011 && ((bgp->name == NULL && name == NULL)
2012 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
2013 return bgp;
2014 return NULL;
2015}
2016
2017/* Lookup BGP structure by view name. */
2018struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002019bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002020{
2021 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002022 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002023
paul1eb8ef22005-04-07 07:30:20 +00002024 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002025 if ((bgp->name == NULL && name == NULL)
2026 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2027 return bgp;
2028 return NULL;
2029}
2030
2031/* Called from VTY commands. */
2032int
paulfd79ac92004-10-13 05:06:08 +00002033bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002034{
2035 struct bgp *bgp;
2036
2037 /* Multiple instance check. */
2038 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2039 {
2040 if (name)
2041 bgp = bgp_lookup_by_name (name);
2042 else
2043 bgp = bgp_get_default ();
2044
2045 /* Already exists. */
2046 if (bgp)
2047 {
2048 if (bgp->as != *as)
2049 {
2050 *as = bgp->as;
2051 return BGP_ERR_INSTANCE_MISMATCH;
2052 }
2053 *bgp_val = bgp;
2054 return 0;
2055 }
2056 }
2057 else
2058 {
2059 /* BGP instance name can not be specified for single instance. */
2060 if (name)
2061 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2062
2063 /* Get default BGP structure if exists. */
2064 bgp = bgp_get_default ();
2065
2066 if (bgp)
2067 {
2068 if (bgp->as != *as)
2069 {
2070 *as = bgp->as;
2071 return BGP_ERR_AS_MISMATCH;
2072 }
2073 *bgp_val = bgp;
2074 return 0;
2075 }
2076 }
2077
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002078 bgp = bgp_create (as, name);
2079 bgp_router_id_set(bgp, &router_id_zebra);
2080 *bgp_val = bgp;
2081
Paul Jakmaad12dde2012-06-13 22:50:07 +01002082 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002083 if (list_isempty(bm->bgp)
2084 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002085 {
2086 if (bgp_socket (bm->port, bm->address) < 0)
2087 return BGP_ERR_INVALID_VALUE;
2088 }
2089
paul718e3742002-12-13 20:15:29 +00002090 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002091
2092 return 0;
2093}
2094
2095/* Delete BGP instance. */
2096int
2097bgp_delete (struct bgp *bgp)
2098{
2099 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002100 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002101 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002102 struct listnode *next;
2103 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002104 int i;
2105
2106 /* Delete static route. */
2107 bgp_static_delete (bgp);
2108
2109 /* Unset redistribution. */
2110 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2111 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2112 if (i != ZEBRA_ROUTE_BGP)
2113 bgp_redistribute_unset (bgp, afi, i);
2114
paul1eb8ef22005-04-07 07:30:20 +00002115 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002116 {
2117 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2118 {
2119 /* Send notify to remote peer. */
2120 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2121 }
2122
2123 peer_delete (peer);
2124 }
paul718e3742002-12-13 20:15:29 +00002125
Chris Caputo228da422009-07-18 05:44:03 +00002126 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002127 {
2128 for (ALL_LIST_ELEMENTS (group->peer, node, next, peer))
2129 {
2130 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2131 {
2132 /* Send notify to remote peer. */
2133 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2134 }
2135 }
2136 peer_group_delete (group);
2137 }
Chris Caputo228da422009-07-18 05:44:03 +00002138
2139 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002140
2141 if (bgp->peer_self) {
2142 peer_delete(bgp->peer_self);
2143 bgp->peer_self = NULL;
2144 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002145
2146 /* Remove visibility via the master list - there may however still be
2147 * routes to be processed still referencing the struct bgp.
2148 */
2149 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002150 if (list_isempty(bm->bgp))
2151 bgp_close ();
2152
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002153 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002154
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002155 return 0;
2156}
2157
2158static void bgp_free (struct bgp *);
2159
2160void
2161bgp_lock (struct bgp *bgp)
2162{
2163 ++bgp->lock;
2164}
2165
2166void
2167bgp_unlock(struct bgp *bgp)
2168{
Chris Caputo228da422009-07-18 05:44:03 +00002169 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002170 if (--bgp->lock == 0)
2171 bgp_free (bgp);
2172}
2173
2174static void
2175bgp_free (struct bgp *bgp)
2176{
2177 afi_t afi;
2178 safi_t safi;
2179
2180 list_delete (bgp->group);
2181 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002182 list_delete (bgp->rsclient);
2183
paul718e3742002-12-13 20:15:29 +00002184 if (bgp->name)
2185 free (bgp->name);
2186
2187 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2188 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2189 {
2190 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002191 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002192 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002193 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002194 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002195 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002196 }
2197 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002198}
David Lamparter6b0655a2014-06-04 06:53:35 +02002199
paul718e3742002-12-13 20:15:29 +00002200struct peer *
2201peer_lookup (struct bgp *bgp, union sockunion *su)
2202{
2203 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002204 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002205
Steve Hillfc4dc592009-07-28 17:54:35 +01002206 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002207 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002208 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2209 if (sockunion_same (&peer->su, su)
2210 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2211 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002212 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002213 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002214 {
2215 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002216
Paul Jakma2158ad22009-07-28 18:10:55 +01002217 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2218 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2219 if (sockunion_same (&peer->su, su)
2220 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2221 return peer;
paul718e3742002-12-13 20:15:29 +00002222 }
2223 return NULL;
2224}
2225
2226struct peer *
2227peer_lookup_with_open (union sockunion *su, as_t remote_as,
2228 struct in_addr *remote_id, int *as)
2229{
2230 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002231 struct listnode *node;
2232 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002233 struct bgp *bgp;
2234
Steve Hillfc4dc592009-07-28 17:54:35 +01002235 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002236 return NULL;
2237
Paul Jakma9d878772009-08-05 16:25:16 +01002238 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002239 {
Paul Jakma9d878772009-08-05 16:25:16 +01002240 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2241 {
2242 if (sockunion_same (&peer->su, su)
2243 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2244 {
2245 if (peer->as == remote_as
2246 && peer->remote_id.s_addr == remote_id->s_addr)
2247 return peer;
2248 if (peer->as == remote_as)
2249 *as = 1;
2250 }
2251 }
2252
2253 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2254 {
2255 if (sockunion_same (&peer->su, su)
2256 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2257 {
2258 if (peer->as == remote_as
2259 && peer->remote_id.s_addr == 0)
2260 return peer;
2261 if (peer->as == remote_as)
2262 *as = 1;
2263 }
2264 }
paul718e3742002-12-13 20:15:29 +00002265 }
2266 return NULL;
2267}
David Lamparter6b0655a2014-06-04 06:53:35 +02002268
paul718e3742002-12-13 20:15:29 +00002269/* If peer is configured at least one address family return 1. */
2270int
2271peer_active (struct peer *peer)
2272{
2273 if (peer->afc[AFI_IP][SAFI_UNICAST]
2274 || peer->afc[AFI_IP][SAFI_MULTICAST]
2275 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2276 || peer->afc[AFI_IP6][SAFI_UNICAST]
2277 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2278 return 1;
2279 return 0;
2280}
2281
2282/* If peer is negotiated at least one address family return 1. */
2283int
2284peer_active_nego (struct peer *peer)
2285{
2286 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2287 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2288 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2289 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2290 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2291 return 1;
2292 return 0;
2293}
David Lamparter6b0655a2014-06-04 06:53:35 +02002294
paul718e3742002-12-13 20:15:29 +00002295/* peer_flag_change_type. */
2296enum peer_change_type
2297{
2298 peer_change_none,
2299 peer_change_reset,
2300 peer_change_reset_in,
2301 peer_change_reset_out,
2302};
2303
paul94f2b392005-06-28 12:44:16 +00002304static void
paul718e3742002-12-13 20:15:29 +00002305peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2306 enum peer_change_type type)
2307{
2308 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2309 return;
2310
Stephen Hemmingerd9d4ae52010-01-13 00:32:39 +00002311 if (peer->status != Established)
2312 return;
2313
paul718e3742002-12-13 20:15:29 +00002314 if (type == peer_change_reset)
2315 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2316 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2317 else if (type == peer_change_reset_in)
2318 {
2319 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2320 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2321 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2322 else
2323 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2324 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2325 }
2326 else if (type == peer_change_reset_out)
2327 bgp_announce_route (peer, afi, safi);
2328}
2329
2330struct peer_flag_action
2331{
2332 /* Peer's flag. */
2333 u_int32_t flag;
2334
2335 /* This flag can be set for peer-group member. */
2336 u_char not_for_member;
2337
2338 /* Action when the flag is changed. */
2339 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002340
2341 /* Peer down cause */
2342 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002343};
2344
Stephen Hemminger03621952009-07-21 16:27:20 -07002345static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002346 {
2347 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2348 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2349 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2350 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2351 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002352 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002353 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002354 { 0, 0, 0 }
2355 };
2356
Stephen Hemminger03621952009-07-21 16:27:20 -07002357static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002358 {
2359 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2360 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2361 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2362 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2363 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2364 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2365 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2366 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2367 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2368 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2369 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2370 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2371 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002372 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
Timo Teräs9e7a53c2014-04-24 10:22:37 +03002373 { PEER_FLAG_NEXTHOP_SELF_ALL, 1, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002374 { 0, 0, 0 }
2375 };
2376
2377/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002378static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002379peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002380 struct peer_flag_action *action, u_int32_t flag)
2381{
2382 int i;
2383 int found = 0;
2384 int reset_in = 0;
2385 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002386 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002387
2388 /* Check peer's frag action. */
2389 for (i = 0; i < size; i++)
2390 {
2391 match = &action_list[i];
2392
2393 if (match->flag == 0)
2394 break;
2395
2396 if (match->flag & flag)
2397 {
2398 found = 1;
2399
2400 if (match->type == peer_change_reset_in)
2401 reset_in = 1;
2402 if (match->type == peer_change_reset_out)
2403 reset_out = 1;
2404 if (match->type == peer_change_reset)
2405 {
2406 reset_in = 1;
2407 reset_out = 1;
2408 }
2409 if (match->not_for_member)
2410 action->not_for_member = 1;
2411 }
2412 }
2413
2414 /* Set peer clear type. */
2415 if (reset_in && reset_out)
2416 action->type = peer_change_reset;
2417 else if (reset_in)
2418 action->type = peer_change_reset_in;
2419 else if (reset_out)
2420 action->type = peer_change_reset_out;
2421 else
2422 action->type = peer_change_none;
2423
2424 return found;
2425}
2426
paul94f2b392005-06-28 12:44:16 +00002427static void
paul718e3742002-12-13 20:15:29 +00002428peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2429{
2430 if (flag == PEER_FLAG_SHUTDOWN)
2431 {
2432 if (CHECK_FLAG (peer->flags, flag))
2433 {
hasso93406d82005-02-02 14:40:33 +00002434 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2435 peer_nsf_stop (peer);
2436
hasso0a486e52005-02-01 20:57:17 +00002437 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2438 if (peer->t_pmax_restart)
2439 {
2440 BGP_TIMER_OFF (peer->t_pmax_restart);
2441 if (BGP_DEBUG (events, EVENTS))
2442 zlog_debug ("%s Maximum-prefix restart timer canceled",
2443 peer->host);
2444 }
2445
hasso93406d82005-02-02 14:40:33 +00002446 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2447 peer_nsf_stop (peer);
2448
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002449 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002450 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2451 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2452 else
2453 BGP_EVENT_ADD (peer, BGP_Stop);
2454 }
2455 else
2456 {
2457 peer->v_start = BGP_INIT_START_TIMER;
2458 BGP_EVENT_ADD (peer, BGP_Stop);
2459 }
2460 }
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002461 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002462 {
hassoc9502432005-02-01 22:01:48 +00002463 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2464 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2465 else if (flag == PEER_FLAG_PASSIVE)
2466 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002467 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002468 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002469
hassoc9502432005-02-01 22:01:48 +00002470 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2471 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002472 }
2473 else
2474 BGP_EVENT_ADD (peer, BGP_Stop);
2475}
2476
2477/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002478static int
paul718e3742002-12-13 20:15:29 +00002479peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2480{
2481 int found;
2482 int size;
2483 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002484 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002485 struct peer_flag_action action;
2486
2487 memset (&action, 0, sizeof (struct peer_flag_action));
2488 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2489
2490 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2491
2492 /* No flag action is found. */
2493 if (! found)
2494 return BGP_ERR_INVALID_FLAG;
2495
2496 /* Not for peer-group member. */
2497 if (action.not_for_member && peer_group_active (peer))
2498 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2499
2500 /* When unset the peer-group member's flag we have to check
2501 peer-group configuration. */
2502 if (! set && peer_group_active (peer))
2503 if (CHECK_FLAG (peer->group->conf->flags, flag))
2504 {
2505 if (flag == PEER_FLAG_SHUTDOWN)
2506 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2507 else
2508 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2509 }
2510
2511 /* Flag conflict check. */
2512 if (set
2513 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2514 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2515 return BGP_ERR_PEER_FLAG_CONFLICT;
2516
2517 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2518 {
2519 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2520 return 0;
2521 if (! set && ! CHECK_FLAG (peer->flags, flag))
2522 return 0;
2523 }
2524
2525 if (set)
2526 SET_FLAG (peer->flags, flag);
2527 else
2528 UNSET_FLAG (peer->flags, flag);
2529
2530 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2531 {
2532 if (action.type == peer_change_reset)
2533 peer_flag_modify_action (peer, flag);
2534
2535 return 0;
2536 }
2537
2538 /* peer-group member updates. */
2539 group = peer->group;
2540
paul1eb8ef22005-04-07 07:30:20 +00002541 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002542 {
2543 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2544 continue;
2545
2546 if (! set && ! CHECK_FLAG (peer->flags, flag))
2547 continue;
2548
2549 if (set)
2550 SET_FLAG (peer->flags, flag);
2551 else
2552 UNSET_FLAG (peer->flags, flag);
2553
2554 if (action.type == peer_change_reset)
2555 peer_flag_modify_action (peer, flag);
2556 }
2557 return 0;
2558}
2559
2560int
2561peer_flag_set (struct peer *peer, u_int32_t flag)
2562{
2563 return peer_flag_modify (peer, flag, 1);
2564}
2565
2566int
2567peer_flag_unset (struct peer *peer, u_int32_t flag)
2568{
2569 return peer_flag_modify (peer, flag, 0);
2570}
2571
paul94f2b392005-06-28 12:44:16 +00002572static int
paul718e3742002-12-13 20:15:29 +00002573peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2574{
2575 if (peer->af_group[afi][safi])
2576 return 1;
2577 return 0;
2578}
2579
paul94f2b392005-06-28 12:44:16 +00002580static int
paul718e3742002-12-13 20:15:29 +00002581peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2582 int set)
2583{
2584 int found;
2585 int size;
paul1eb8ef22005-04-07 07:30:20 +00002586 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002587 struct peer_group *group;
2588 struct peer_flag_action action;
2589
2590 memset (&action, 0, sizeof (struct peer_flag_action));
2591 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2592
2593 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2594
2595 /* No flag action is found. */
2596 if (! found)
2597 return BGP_ERR_INVALID_FLAG;
2598
2599 /* Adress family must be activated. */
2600 if (! peer->afc[afi][safi])
2601 return BGP_ERR_PEER_INACTIVE;
2602
2603 /* Not for peer-group member. */
2604 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2605 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2606
2607 /* Spcecial check for reflector client. */
2608 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2609 && peer_sort (peer) != BGP_PEER_IBGP)
2610 return BGP_ERR_NOT_INTERNAL_PEER;
2611
2612 /* Spcecial check for remove-private-AS. */
2613 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2614 && peer_sort (peer) == BGP_PEER_IBGP)
2615 return BGP_ERR_REMOVE_PRIVATE_AS;
2616
2617 /* When unset the peer-group member's flag we have to check
2618 peer-group configuration. */
2619 if (! set && peer->af_group[afi][safi])
2620 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2621 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2622
2623 /* When current flag configuration is same as requested one. */
2624 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2625 {
2626 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2627 return 0;
2628 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2629 return 0;
2630 }
2631
2632 if (set)
2633 SET_FLAG (peer->af_flags[afi][safi], flag);
2634 else
2635 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2636
2637 /* Execute action when peer is established. */
2638 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2639 && peer->status == Established)
2640 {
2641 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2642 bgp_clear_adj_in (peer, afi, safi);
2643 else
hassoe0701b72004-05-20 09:19:34 +00002644 {
2645 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2646 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2647 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2648 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2649 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2650 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2651 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2652 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2653
2654 peer_change_action (peer, afi, safi, action.type);
2655 }
2656
paul718e3742002-12-13 20:15:29 +00002657 }
2658
2659 /* Peer group member updates. */
2660 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2661 {
2662 group = peer->group;
2663
paul1eb8ef22005-04-07 07:30:20 +00002664 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002665 {
2666 if (! peer->af_group[afi][safi])
2667 continue;
2668
2669 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2670 continue;
2671
2672 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2673 continue;
2674
2675 if (set)
2676 SET_FLAG (peer->af_flags[afi][safi], flag);
2677 else
2678 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2679
2680 if (peer->status == Established)
2681 {
2682 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2683 bgp_clear_adj_in (peer, afi, safi);
2684 else
hassoe0701b72004-05-20 09:19:34 +00002685 {
2686 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2687 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2688 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2689 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2690 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2691 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2692 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2693 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2694
2695 peer_change_action (peer, afi, safi, action.type);
2696 }
paul718e3742002-12-13 20:15:29 +00002697 }
2698 }
2699 }
2700 return 0;
2701}
2702
2703int
2704peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2705{
2706 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2707}
2708
2709int
2710peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2711{
2712 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2713}
David Lamparter6b0655a2014-06-04 06:53:35 +02002714
paul718e3742002-12-13 20:15:29 +00002715/* EBGP multihop configuration. */
2716int
2717peer_ebgp_multihop_set (struct peer *peer, int ttl)
2718{
2719 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002720 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002721 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002722
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002723 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002724 return 0;
2725
Nick Hilliardfa411a22011-03-23 15:33:17 +00002726 /* see comment in peer_ttl_security_hops_set() */
2727 if (ttl != MAXTTL)
2728 {
2729 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2730 {
2731 group = peer->group;
2732 if (group->conf->gtsm_hops != 0)
2733 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2734
2735 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2736 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002737 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002738 continue;
2739
2740 if (peer1->gtsm_hops != 0)
2741 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2742 }
2743 }
2744 else
2745 {
2746 if (peer->gtsm_hops != 0)
2747 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2748 }
2749 }
2750
paul718e3742002-12-13 20:15:29 +00002751 peer->ttl = ttl;
2752
2753 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2754 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002755 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002756 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002757 }
2758 else
2759 {
2760 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002761 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002762 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002763 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002764 continue;
paul718e3742002-12-13 20:15:29 +00002765
pauleb821182004-05-01 08:44:08 +00002766 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002767
pauleb821182004-05-01 08:44:08 +00002768 if (peer->fd >= 0)
2769 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2770 }
paul718e3742002-12-13 20:15:29 +00002771 }
2772 return 0;
2773}
2774
2775int
2776peer_ebgp_multihop_unset (struct peer *peer)
2777{
2778 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002779 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002780
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002781 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002782 return 0;
2783
Nick Hilliardfa411a22011-03-23 15:33:17 +00002784 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2785 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2786
paul718e3742002-12-13 20:15:29 +00002787 if (peer_group_active (peer))
2788 peer->ttl = peer->group->conf->ttl;
2789 else
2790 peer->ttl = 1;
2791
2792 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2793 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002794 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002795 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002796 }
2797 else
2798 {
2799 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002800 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002801 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002802 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002803 continue;
paul718e3742002-12-13 20:15:29 +00002804
pauleb821182004-05-01 08:44:08 +00002805 peer->ttl = 1;
2806
2807 if (peer->fd >= 0)
2808 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2809 }
paul718e3742002-12-13 20:15:29 +00002810 }
2811 return 0;
2812}
David Lamparter6b0655a2014-06-04 06:53:35 +02002813
paul718e3742002-12-13 20:15:29 +00002814/* Neighbor description. */
2815int
2816peer_description_set (struct peer *peer, char *desc)
2817{
2818 if (peer->desc)
2819 XFREE (MTYPE_PEER_DESC, peer->desc);
2820
2821 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2822
2823 return 0;
2824}
2825
2826int
2827peer_description_unset (struct peer *peer)
2828{
2829 if (peer->desc)
2830 XFREE (MTYPE_PEER_DESC, peer->desc);
2831
2832 peer->desc = NULL;
2833
2834 return 0;
2835}
David Lamparter6b0655a2014-06-04 06:53:35 +02002836
paul718e3742002-12-13 20:15:29 +00002837/* Neighbor update-source. */
2838int
paulfd79ac92004-10-13 05:06:08 +00002839peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002840{
2841 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002842 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002843
2844 if (peer->update_if)
2845 {
2846 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2847 && strcmp (peer->update_if, ifname) == 0)
2848 return 0;
2849
2850 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2851 peer->update_if = NULL;
2852 }
2853
2854 if (peer->update_source)
2855 {
2856 sockunion_free (peer->update_source);
2857 peer->update_source = NULL;
2858 }
2859
2860 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2861
2862 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2863 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002864 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002865 {
2866 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2867 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2868 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2869 }
paul718e3742002-12-13 20:15:29 +00002870 else
2871 BGP_EVENT_ADD (peer, BGP_Stop);
2872 return 0;
2873 }
2874
2875 /* peer-group member updates. */
2876 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002877 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002878 {
2879 if (peer->update_if)
2880 {
2881 if (strcmp (peer->update_if, ifname) == 0)
2882 continue;
2883
2884 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2885 peer->update_if = NULL;
2886 }
2887
2888 if (peer->update_source)
2889 {
2890 sockunion_free (peer->update_source);
2891 peer->update_source = NULL;
2892 }
2893
2894 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2895
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002896 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002897 {
2898 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2899 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2900 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2901 }
paul718e3742002-12-13 20:15:29 +00002902 else
2903 BGP_EVENT_ADD (peer, BGP_Stop);
2904 }
2905 return 0;
2906}
2907
2908int
2909peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2910{
2911 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002912 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002913
2914 if (peer->update_source)
2915 {
2916 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2917 && sockunion_cmp (peer->update_source, su) == 0)
2918 return 0;
2919 sockunion_free (peer->update_source);
2920 peer->update_source = NULL;
2921 }
2922
2923 if (peer->update_if)
2924 {
2925 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2926 peer->update_if = NULL;
2927 }
2928
2929 peer->update_source = sockunion_dup (su);
2930
2931 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2932 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002933 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002934 {
2935 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2936 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2937 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2938 }
paul718e3742002-12-13 20:15:29 +00002939 else
2940 BGP_EVENT_ADD (peer, BGP_Stop);
2941 return 0;
2942 }
2943
2944 /* peer-group member updates. */
2945 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002946 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002947 {
2948 if (peer->update_source)
2949 {
2950 if (sockunion_cmp (peer->update_source, su) == 0)
2951 continue;
2952 sockunion_free (peer->update_source);
2953 peer->update_source = NULL;
2954 }
2955
2956 if (peer->update_if)
2957 {
2958 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2959 peer->update_if = NULL;
2960 }
2961
2962 peer->update_source = sockunion_dup (su);
2963
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002964 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002965 {
2966 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2967 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2968 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2969 }
paul718e3742002-12-13 20:15:29 +00002970 else
2971 BGP_EVENT_ADD (peer, BGP_Stop);
2972 }
2973 return 0;
2974}
2975
2976int
2977peer_update_source_unset (struct peer *peer)
2978{
2979 union sockunion *su;
2980 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002981 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002982
2983 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2984 && ! peer->update_source
2985 && ! peer->update_if)
2986 return 0;
2987
2988 if (peer->update_source)
2989 {
2990 sockunion_free (peer->update_source);
2991 peer->update_source = NULL;
2992 }
2993 if (peer->update_if)
2994 {
2995 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2996 peer->update_if = NULL;
2997 }
2998
2999 if (peer_group_active (peer))
3000 {
3001 group = peer->group;
3002
3003 if (group->conf->update_source)
3004 {
3005 su = sockunion_dup (group->conf->update_source);
3006 peer->update_source = su;
3007 }
3008 else if (group->conf->update_if)
3009 peer->update_if =
3010 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
3011 }
3012
3013 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3014 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003015 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003016 {
3017 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3018 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3019 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3020 }
paul718e3742002-12-13 20:15:29 +00003021 else
3022 BGP_EVENT_ADD (peer, BGP_Stop);
3023 return 0;
3024 }
3025
3026 /* peer-group member updates. */
3027 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003028 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003029 {
3030 if (! peer->update_source && ! peer->update_if)
3031 continue;
3032
3033 if (peer->update_source)
3034 {
3035 sockunion_free (peer->update_source);
3036 peer->update_source = NULL;
3037 }
3038
3039 if (peer->update_if)
3040 {
3041 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3042 peer->update_if = NULL;
3043 }
3044
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003045 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003046 {
3047 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3048 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3049 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3050 }
paul718e3742002-12-13 20:15:29 +00003051 else
3052 BGP_EVENT_ADD (peer, BGP_Stop);
3053 }
3054 return 0;
3055}
David Lamparter6b0655a2014-06-04 06:53:35 +02003056
paul718e3742002-12-13 20:15:29 +00003057int
3058peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003059 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003060{
3061 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003062 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003063
3064 /* Adress family must be activated. */
3065 if (! peer->afc[afi][safi])
3066 return BGP_ERR_PEER_INACTIVE;
3067
3068 /* Default originate can't be used for peer group memeber. */
3069 if (peer_is_group_member (peer, afi, safi))
3070 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3071
3072 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3073 || (rmap && ! peer->default_rmap[afi][safi].name)
3074 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3075 {
3076 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3077
3078 if (rmap)
3079 {
3080 if (peer->default_rmap[afi][safi].name)
3081 free (peer->default_rmap[afi][safi].name);
3082 peer->default_rmap[afi][safi].name = strdup (rmap);
3083 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3084 }
3085 }
3086
3087 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3088 {
3089 if (peer->status == Established && peer->afc_nego[afi][safi])
3090 bgp_default_originate (peer, afi, safi, 0);
3091 return 0;
3092 }
3093
3094 /* peer-group member updates. */
3095 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003096 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003097 {
3098 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3099
3100 if (rmap)
3101 {
3102 if (peer->default_rmap[afi][safi].name)
3103 free (peer->default_rmap[afi][safi].name);
3104 peer->default_rmap[afi][safi].name = strdup (rmap);
3105 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3106 }
3107
3108 if (peer->status == Established && peer->afc_nego[afi][safi])
3109 bgp_default_originate (peer, afi, safi, 0);
3110 }
3111 return 0;
3112}
3113
3114int
3115peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3116{
3117 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003118 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003119
3120 /* Adress family must be activated. */
3121 if (! peer->afc[afi][safi])
3122 return BGP_ERR_PEER_INACTIVE;
3123
3124 /* Default originate can't be used for peer group memeber. */
3125 if (peer_is_group_member (peer, afi, safi))
3126 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3127
3128 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3129 {
3130 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3131
3132 if (peer->default_rmap[afi][safi].name)
3133 free (peer->default_rmap[afi][safi].name);
3134 peer->default_rmap[afi][safi].name = NULL;
3135 peer->default_rmap[afi][safi].map = NULL;
3136 }
3137
3138 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3139 {
3140 if (peer->status == Established && peer->afc_nego[afi][safi])
3141 bgp_default_originate (peer, afi, safi, 1);
3142 return 0;
3143 }
3144
3145 /* peer-group member updates. */
3146 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003147 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003148 {
3149 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3150
3151 if (peer->default_rmap[afi][safi].name)
3152 free (peer->default_rmap[afi][safi].name);
3153 peer->default_rmap[afi][safi].name = NULL;
3154 peer->default_rmap[afi][safi].map = NULL;
3155
3156 if (peer->status == Established && peer->afc_nego[afi][safi])
3157 bgp_default_originate (peer, afi, safi, 1);
3158 }
3159 return 0;
3160}
David Lamparter6b0655a2014-06-04 06:53:35 +02003161
paul718e3742002-12-13 20:15:29 +00003162int
3163peer_port_set (struct peer *peer, u_int16_t port)
3164{
3165 peer->port = port;
3166 return 0;
3167}
3168
3169int
3170peer_port_unset (struct peer *peer)
3171{
3172 peer->port = BGP_PORT_DEFAULT;
3173 return 0;
3174}
David Lamparter6b0655a2014-06-04 06:53:35 +02003175
paul718e3742002-12-13 20:15:29 +00003176/* neighbor weight. */
3177int
3178peer_weight_set (struct peer *peer, u_int16_t weight)
3179{
3180 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003181 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003182
3183 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3184 peer->weight = weight;
3185
3186 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3187 return 0;
3188
3189 /* peer-group member updates. */
3190 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003191 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003192 {
3193 peer->weight = group->conf->weight;
3194 }
3195 return 0;
3196}
3197
3198int
3199peer_weight_unset (struct peer *peer)
3200{
3201 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003202 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003203
3204 /* Set default weight. */
3205 if (peer_group_active (peer))
3206 peer->weight = peer->group->conf->weight;
3207 else
3208 peer->weight = 0;
3209
3210 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3211
3212 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3213 return 0;
3214
3215 /* peer-group member updates. */
3216 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003217 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003218 {
3219 peer->weight = 0;
3220 }
3221 return 0;
3222}
David Lamparter6b0655a2014-06-04 06:53:35 +02003223
paul718e3742002-12-13 20:15:29 +00003224int
3225peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3226{
3227 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003228 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003229
3230 /* Not for peer group memeber. */
3231 if (peer_group_active (peer))
3232 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3233
3234 /* keepalive value check. */
3235 if (keepalive > 65535)
3236 return BGP_ERR_INVALID_VALUE;
3237
3238 /* Holdtime value check. */
3239 if (holdtime > 65535)
3240 return BGP_ERR_INVALID_VALUE;
3241
3242 /* Holdtime value must be either 0 or greater than 3. */
3243 if (holdtime < 3 && holdtime != 0)
3244 return BGP_ERR_INVALID_VALUE;
3245
3246 /* Set value to the configuration. */
3247 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3248 peer->holdtime = holdtime;
3249 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3250
3251 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3252 return 0;
3253
3254 /* peer-group member updates. */
3255 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003256 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003257 {
3258 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3259 peer->holdtime = group->conf->holdtime;
3260 peer->keepalive = group->conf->keepalive;
3261 }
3262 return 0;
3263}
3264
3265int
3266peer_timers_unset (struct peer *peer)
3267{
3268 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003269 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003270
3271 if (peer_group_active (peer))
3272 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3273
3274 /* Clear configuration. */
3275 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3276 peer->keepalive = 0;
3277 peer->holdtime = 0;
3278
3279 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3280 return 0;
3281
3282 /* peer-group member updates. */
3283 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003284 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003285 {
3286 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3287 peer->holdtime = 0;
3288 peer->keepalive = 0;
3289 }
3290
3291 return 0;
3292}
David Lamparter6b0655a2014-06-04 06:53:35 +02003293
paul718e3742002-12-13 20:15:29 +00003294int
3295peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3296{
3297 if (peer_group_active (peer))
3298 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3299
3300 if (connect > 65535)
3301 return BGP_ERR_INVALID_VALUE;
3302
3303 /* Set value to the configuration. */
3304 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3305 peer->connect = connect;
3306
3307 /* Set value to timer setting. */
3308 peer->v_connect = connect;
3309
3310 return 0;
3311}
3312
3313int
3314peer_timers_connect_unset (struct peer *peer)
3315{
3316 if (peer_group_active (peer))
3317 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3318
3319 /* Clear configuration. */
3320 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3321 peer->connect = 0;
3322
3323 /* Set timer setting to default value. */
3324 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3325
3326 return 0;
3327}
David Lamparter6b0655a2014-06-04 06:53:35 +02003328
paul718e3742002-12-13 20:15:29 +00003329int
3330peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3331{
3332 if (peer_group_active (peer))
3333 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3334
3335 if (routeadv > 600)
3336 return BGP_ERR_INVALID_VALUE;
3337
3338 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3339 peer->routeadv = routeadv;
3340 peer->v_routeadv = routeadv;
3341
3342 return 0;
3343}
3344
3345int
3346peer_advertise_interval_unset (struct peer *peer)
3347{
3348 if (peer_group_active (peer))
3349 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3350
3351 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3352 peer->routeadv = 0;
3353
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003354 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003355 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3356 else
3357 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3358
3359 return 0;
3360}
David Lamparter6b0655a2014-06-04 06:53:35 +02003361
paul718e3742002-12-13 20:15:29 +00003362/* neighbor interface */
3363int
paulfd79ac92004-10-13 05:06:08 +00003364peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003365{
3366 if (peer->ifname)
3367 free (peer->ifname);
3368 peer->ifname = strdup (str);
3369
3370 return 0;
3371}
3372
3373int
3374peer_interface_unset (struct peer *peer)
3375{
3376 if (peer->ifname)
3377 free (peer->ifname);
3378 peer->ifname = NULL;
3379
3380 return 0;
3381}
David Lamparter6b0655a2014-06-04 06:53:35 +02003382
paul718e3742002-12-13 20:15:29 +00003383/* Allow-as in. */
3384int
3385peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3386{
3387 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003388 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003389
3390 if (allow_num < 1 || allow_num > 10)
3391 return BGP_ERR_INVALID_VALUE;
3392
3393 if (peer->allowas_in[afi][safi] != allow_num)
3394 {
3395 peer->allowas_in[afi][safi] = allow_num;
3396 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3397 peer_change_action (peer, afi, safi, peer_change_reset_in);
3398 }
3399
3400 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3401 return 0;
3402
3403 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003404 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003405 {
3406 if (peer->allowas_in[afi][safi] != allow_num)
3407 {
3408 peer->allowas_in[afi][safi] = allow_num;
3409 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3410 peer_change_action (peer, afi, safi, peer_change_reset_in);
3411 }
3412
3413 }
3414 return 0;
3415}
3416
3417int
3418peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3419{
3420 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003421 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003422
3423 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3424 {
3425 peer->allowas_in[afi][safi] = 0;
3426 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3427 }
3428
3429 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3430 return 0;
3431
3432 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003433 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003434 {
3435 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3436 {
3437 peer->allowas_in[afi][safi] = 0;
3438 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3439 }
3440 }
3441 return 0;
3442}
David Lamparter6b0655a2014-06-04 06:53:35 +02003443
paul718e3742002-12-13 20:15:29 +00003444int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003445peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003446{
3447 struct bgp *bgp = peer->bgp;
3448 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003449 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003450
3451 if (peer_sort (peer) != BGP_PEER_EBGP
3452 && peer_sort (peer) != BGP_PEER_INTERNAL)
3453 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3454
3455 if (bgp->as == as)
3456 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3457
3458 if (peer_group_active (peer))
3459 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3460
Andrew Certain9d3f9702012-11-07 23:50:07 +00003461 if (peer->as == as)
3462 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3463
paul718e3742002-12-13 20:15:29 +00003464 if (peer->change_local_as == as &&
3465 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003466 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3467 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3468 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003469 return 0;
3470
3471 peer->change_local_as = as;
3472 if (no_prepend)
3473 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3474 else
3475 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3476
Andrew Certain9d3f9702012-11-07 23:50:07 +00003477 if (replace_as)
3478 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3479 else
3480 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3481
paul718e3742002-12-13 20:15:29 +00003482 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3483 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003484 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003485 {
3486 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3487 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3488 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3489 }
paul718e3742002-12-13 20:15:29 +00003490 else
3491 BGP_EVENT_ADD (peer, BGP_Stop);
3492
3493 return 0;
3494 }
3495
3496 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003497 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003498 {
3499 peer->change_local_as = as;
3500 if (no_prepend)
3501 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3502 else
3503 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3504
Andrew Certain9d3f9702012-11-07 23:50:07 +00003505 if (replace_as)
3506 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3507 else
3508 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3509
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003510 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003511 {
3512 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3513 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3514 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3515 }
paul718e3742002-12-13 20:15:29 +00003516 else
3517 BGP_EVENT_ADD (peer, BGP_Stop);
3518 }
3519
3520 return 0;
3521}
3522
3523int
3524peer_local_as_unset (struct peer *peer)
3525{
3526 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003527 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003528
3529 if (peer_group_active (peer))
3530 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3531
3532 if (! peer->change_local_as)
3533 return 0;
3534
3535 peer->change_local_as = 0;
3536 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003537 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003538
3539 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3540 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003541 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003542 {
3543 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3544 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3545 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3546 }
paul718e3742002-12-13 20:15:29 +00003547 else
3548 BGP_EVENT_ADD (peer, BGP_Stop);
3549
3550 return 0;
3551 }
3552
3553 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003554 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003555 {
3556 peer->change_local_as = 0;
3557 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003558 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003559
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003560 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003561 {
3562 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3563 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3564 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3565 }
paul718e3742002-12-13 20:15:29 +00003566 else
3567 BGP_EVENT_ADD (peer, BGP_Stop);
3568 }
3569 return 0;
3570}
David Lamparter6b0655a2014-06-04 06:53:35 +02003571
Paul Jakma0df7c912008-07-21 21:02:49 +00003572/* Set password for authenticating with the peer. */
3573int
3574peer_password_set (struct peer *peer, const char *password)
3575{
3576 struct listnode *nn, *nnode;
3577 int len = password ? strlen(password) : 0;
3578 int ret = BGP_SUCCESS;
3579
3580 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3581 return BGP_ERR_INVALID_VALUE;
3582
3583 if (peer->password && strcmp (peer->password, password) == 0
3584 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3585 return 0;
3586
3587 if (peer->password)
3588 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3589
3590 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3591
3592 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3593 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003594 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3595 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
Paul Jakma0df7c912008-07-21 21:02:49 +00003596 else
3597 BGP_EVENT_ADD (peer, BGP_Stop);
3598
3599 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3600 }
3601
3602 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3603 {
3604 if (peer->password && strcmp (peer->password, password) == 0)
3605 continue;
3606
3607 if (peer->password)
3608 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3609
3610 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3611
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003612 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003613 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3614 else
3615 BGP_EVENT_ADD (peer, BGP_Stop);
3616
3617 if (bgp_md5_set (peer) < 0)
3618 ret = BGP_ERR_TCPSIG_FAILED;
3619 }
3620
3621 return ret;
3622}
3623
3624int
3625peer_password_unset (struct peer *peer)
3626{
3627 struct listnode *nn, *nnode;
3628
3629 if (!peer->password
3630 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3631 return 0;
3632
3633 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3634 {
3635 if (peer_group_active (peer)
3636 && peer->group->conf->password
3637 && strcmp (peer->group->conf->password, peer->password) == 0)
3638 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3639
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003640 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003641 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3642 else
3643 BGP_EVENT_ADD (peer, BGP_Stop);
3644
3645 if (peer->password)
3646 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3647
3648 peer->password = NULL;
3649
3650 bgp_md5_set (peer);
3651
3652 return 0;
3653 }
3654
3655 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3656 peer->password = NULL;
3657
3658 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3659 {
3660 if (!peer->password)
3661 continue;
3662
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003663 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003664 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3665 else
3666 BGP_EVENT_ADD (peer, BGP_Stop);
3667
3668 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3669 peer->password = NULL;
3670
3671 bgp_md5_set (peer);
3672 }
3673
3674 return 0;
3675}
David Lamparter6b0655a2014-06-04 06:53:35 +02003676
paul718e3742002-12-13 20:15:29 +00003677/* Set distribute list to the peer. */
3678int
3679peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003680 const char *name)
paul718e3742002-12-13 20:15:29 +00003681{
3682 struct bgp_filter *filter;
3683 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003684 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003685
3686 if (! peer->afc[afi][safi])
3687 return BGP_ERR_PEER_INACTIVE;
3688
3689 if (direct != FILTER_IN && direct != FILTER_OUT)
3690 return BGP_ERR_INVALID_VALUE;
3691
3692 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3693 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3694
3695 filter = &peer->filter[afi][safi];
3696
3697 if (filter->plist[direct].name)
3698 return BGP_ERR_PEER_FILTER_CONFLICT;
3699
3700 if (filter->dlist[direct].name)
3701 free (filter->dlist[direct].name);
3702 filter->dlist[direct].name = strdup (name);
3703 filter->dlist[direct].alist = access_list_lookup (afi, name);
3704
3705 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3706 return 0;
3707
3708 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003709 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003710 {
3711 filter = &peer->filter[afi][safi];
3712
3713 if (! peer->af_group[afi][safi])
3714 continue;
3715
3716 if (filter->dlist[direct].name)
3717 free (filter->dlist[direct].name);
3718 filter->dlist[direct].name = strdup (name);
3719 filter->dlist[direct].alist = access_list_lookup (afi, name);
3720 }
3721
3722 return 0;
3723}
3724
3725int
3726peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3727{
3728 struct bgp_filter *filter;
3729 struct bgp_filter *gfilter;
3730 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003731 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003732
3733 if (! peer->afc[afi][safi])
3734 return BGP_ERR_PEER_INACTIVE;
3735
3736 if (direct != FILTER_IN && direct != FILTER_OUT)
3737 return BGP_ERR_INVALID_VALUE;
3738
3739 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3740 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3741
3742 filter = &peer->filter[afi][safi];
3743
3744 /* apply peer-group filter */
3745 if (peer->af_group[afi][safi])
3746 {
3747 gfilter = &peer->group->conf->filter[afi][safi];
3748
3749 if (gfilter->dlist[direct].name)
3750 {
3751 if (filter->dlist[direct].name)
3752 free (filter->dlist[direct].name);
3753 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3754 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3755 return 0;
3756 }
3757 }
3758
3759 if (filter->dlist[direct].name)
3760 free (filter->dlist[direct].name);
3761 filter->dlist[direct].name = NULL;
3762 filter->dlist[direct].alist = NULL;
3763
3764 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3765 return 0;
3766
3767 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003768 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003769 {
3770 filter = &peer->filter[afi][safi];
3771
3772 if (! peer->af_group[afi][safi])
3773 continue;
3774
3775 if (filter->dlist[direct].name)
3776 free (filter->dlist[direct].name);
3777 filter->dlist[direct].name = NULL;
3778 filter->dlist[direct].alist = NULL;
3779 }
3780
3781 return 0;
3782}
3783
3784/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003785static void
paul718e3742002-12-13 20:15:29 +00003786peer_distribute_update (struct access_list *access)
3787{
3788 afi_t afi;
3789 safi_t safi;
3790 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003791 struct listnode *mnode, *mnnode;
3792 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003793 struct bgp *bgp;
3794 struct peer *peer;
3795 struct peer_group *group;
3796 struct bgp_filter *filter;
3797
paul1eb8ef22005-04-07 07:30:20 +00003798 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003799 {
paul1eb8ef22005-04-07 07:30:20 +00003800 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003801 {
3802 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3803 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3804 {
3805 filter = &peer->filter[afi][safi];
3806
3807 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3808 {
3809 if (filter->dlist[direct].name)
3810 filter->dlist[direct].alist =
3811 access_list_lookup (afi, filter->dlist[direct].name);
3812 else
3813 filter->dlist[direct].alist = NULL;
3814 }
3815 }
3816 }
paul1eb8ef22005-04-07 07:30:20 +00003817 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003818 {
3819 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3820 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3821 {
3822 filter = &group->conf->filter[afi][safi];
3823
3824 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3825 {
3826 if (filter->dlist[direct].name)
3827 filter->dlist[direct].alist =
3828 access_list_lookup (afi, filter->dlist[direct].name);
3829 else
3830 filter->dlist[direct].alist = NULL;
3831 }
3832 }
3833 }
3834 }
3835}
David Lamparter6b0655a2014-06-04 06:53:35 +02003836
paul718e3742002-12-13 20:15:29 +00003837/* Set prefix list to the peer. */
3838int
3839peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003840 const char *name)
paul718e3742002-12-13 20:15:29 +00003841{
3842 struct bgp_filter *filter;
3843 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003844 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003845
3846 if (! peer->afc[afi][safi])
3847 return BGP_ERR_PEER_INACTIVE;
3848
3849 if (direct != FILTER_IN && direct != FILTER_OUT)
3850 return BGP_ERR_INVALID_VALUE;
3851
3852 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3853 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3854
3855 filter = &peer->filter[afi][safi];
3856
3857 if (filter->dlist[direct].name)
3858 return BGP_ERR_PEER_FILTER_CONFLICT;
3859
3860 if (filter->plist[direct].name)
3861 free (filter->plist[direct].name);
3862 filter->plist[direct].name = strdup (name);
3863 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3864
3865 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3866 return 0;
3867
3868 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003869 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003870 {
3871 filter = &peer->filter[afi][safi];
3872
3873 if (! peer->af_group[afi][safi])
3874 continue;
3875
3876 if (filter->plist[direct].name)
3877 free (filter->plist[direct].name);
3878 filter->plist[direct].name = strdup (name);
3879 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3880 }
3881 return 0;
3882}
3883
3884int
3885peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3886{
3887 struct bgp_filter *filter;
3888 struct bgp_filter *gfilter;
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 /* apply peer-group filter */
3904 if (peer->af_group[afi][safi])
3905 {
3906 gfilter = &peer->group->conf->filter[afi][safi];
3907
3908 if (gfilter->plist[direct].name)
3909 {
3910 if (filter->plist[direct].name)
3911 free (filter->plist[direct].name);
3912 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3913 filter->plist[direct].plist = gfilter->plist[direct].plist;
3914 return 0;
3915 }
3916 }
3917
3918 if (filter->plist[direct].name)
3919 free (filter->plist[direct].name);
3920 filter->plist[direct].name = NULL;
3921 filter->plist[direct].plist = NULL;
3922
3923 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3924 return 0;
3925
3926 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003927 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003928 {
3929 filter = &peer->filter[afi][safi];
3930
3931 if (! peer->af_group[afi][safi])
3932 continue;
3933
3934 if (filter->plist[direct].name)
3935 free (filter->plist[direct].name);
3936 filter->plist[direct].name = NULL;
3937 filter->plist[direct].plist = NULL;
3938 }
3939
3940 return 0;
3941}
3942
3943/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003944static void
paul718e3742002-12-13 20:15:29 +00003945peer_prefix_list_update (struct prefix_list *plist)
3946{
paul1eb8ef22005-04-07 07:30:20 +00003947 struct listnode *mnode, *mnnode;
3948 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003949 struct bgp *bgp;
3950 struct peer *peer;
3951 struct peer_group *group;
3952 struct bgp_filter *filter;
3953 afi_t afi;
3954 safi_t safi;
3955 int direct;
3956
paul1eb8ef22005-04-07 07:30:20 +00003957 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003958 {
paul1eb8ef22005-04-07 07:30:20 +00003959 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003960 {
3961 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3962 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3963 {
3964 filter = &peer->filter[afi][safi];
3965
3966 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3967 {
3968 if (filter->plist[direct].name)
3969 filter->plist[direct].plist =
3970 prefix_list_lookup (afi, filter->plist[direct].name);
3971 else
3972 filter->plist[direct].plist = NULL;
3973 }
3974 }
3975 }
paul1eb8ef22005-04-07 07:30:20 +00003976 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003977 {
3978 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3979 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3980 {
3981 filter = &group->conf->filter[afi][safi];
3982
3983 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3984 {
3985 if (filter->plist[direct].name)
3986 filter->plist[direct].plist =
3987 prefix_list_lookup (afi, filter->plist[direct].name);
3988 else
3989 filter->plist[direct].plist = NULL;
3990 }
3991 }
3992 }
3993 }
3994}
David Lamparter6b0655a2014-06-04 06:53:35 +02003995
paul718e3742002-12-13 20:15:29 +00003996int
3997peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003998 const char *name)
paul718e3742002-12-13 20:15:29 +00003999{
4000 struct bgp_filter *filter;
4001 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004002 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004003
4004 if (! peer->afc[afi][safi])
4005 return BGP_ERR_PEER_INACTIVE;
4006
4007 if (direct != FILTER_IN && direct != FILTER_OUT)
4008 return BGP_ERR_INVALID_VALUE;
4009
4010 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4011 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4012
4013 filter = &peer->filter[afi][safi];
4014
4015 if (filter->aslist[direct].name)
4016 free (filter->aslist[direct].name);
4017 filter->aslist[direct].name = strdup (name);
4018 filter->aslist[direct].aslist = as_list_lookup (name);
4019
4020 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4021 return 0;
4022
4023 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004024 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004025 {
4026 filter = &peer->filter[afi][safi];
4027
4028 if (! peer->af_group[afi][safi])
4029 continue;
4030
4031 if (filter->aslist[direct].name)
4032 free (filter->aslist[direct].name);
4033 filter->aslist[direct].name = strdup (name);
4034 filter->aslist[direct].aslist = as_list_lookup (name);
4035 }
4036 return 0;
4037}
4038
4039int
4040peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4041{
4042 struct bgp_filter *filter;
4043 struct bgp_filter *gfilter;
4044 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004045 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004046
4047 if (! peer->afc[afi][safi])
4048 return BGP_ERR_PEER_INACTIVE;
4049
hassob5f29602005-05-25 21:00:28 +00004050 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004051 return BGP_ERR_INVALID_VALUE;
4052
hassob5f29602005-05-25 21:00:28 +00004053 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004054 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4055
4056 filter = &peer->filter[afi][safi];
4057
4058 /* apply peer-group filter */
4059 if (peer->af_group[afi][safi])
4060 {
4061 gfilter = &peer->group->conf->filter[afi][safi];
4062
4063 if (gfilter->aslist[direct].name)
4064 {
4065 if (filter->aslist[direct].name)
4066 free (filter->aslist[direct].name);
4067 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4068 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4069 return 0;
4070 }
4071 }
4072
4073 if (filter->aslist[direct].name)
4074 free (filter->aslist[direct].name);
4075 filter->aslist[direct].name = NULL;
4076 filter->aslist[direct].aslist = NULL;
4077
4078 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4079 return 0;
4080
4081 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004082 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004083 {
4084 filter = &peer->filter[afi][safi];
4085
4086 if (! peer->af_group[afi][safi])
4087 continue;
4088
4089 if (filter->aslist[direct].name)
4090 free (filter->aslist[direct].name);
4091 filter->aslist[direct].name = NULL;
4092 filter->aslist[direct].aslist = NULL;
4093 }
4094
4095 return 0;
4096}
4097
paul94f2b392005-06-28 12:44:16 +00004098static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004099peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004100{
4101 afi_t afi;
4102 safi_t safi;
4103 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004104 struct listnode *mnode, *mnnode;
4105 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004106 struct bgp *bgp;
4107 struct peer *peer;
4108 struct peer_group *group;
4109 struct bgp_filter *filter;
4110
paul1eb8ef22005-04-07 07:30:20 +00004111 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004112 {
paul1eb8ef22005-04-07 07:30:20 +00004113 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004114 {
4115 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4116 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4117 {
4118 filter = &peer->filter[afi][safi];
4119
4120 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4121 {
4122 if (filter->aslist[direct].name)
4123 filter->aslist[direct].aslist =
4124 as_list_lookup (filter->aslist[direct].name);
4125 else
4126 filter->aslist[direct].aslist = NULL;
4127 }
4128 }
4129 }
paul1eb8ef22005-04-07 07:30:20 +00004130 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004131 {
4132 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4133 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4134 {
4135 filter = &group->conf->filter[afi][safi];
4136
4137 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4138 {
4139 if (filter->aslist[direct].name)
4140 filter->aslist[direct].aslist =
4141 as_list_lookup (filter->aslist[direct].name);
4142 else
4143 filter->aslist[direct].aslist = NULL;
4144 }
4145 }
4146 }
4147 }
4148}
David Lamparter6b0655a2014-06-04 06:53:35 +02004149
paul718e3742002-12-13 20:15:29 +00004150/* Set route-map to the peer. */
4151int
4152peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004153 const char *name)
paul718e3742002-12-13 20:15:29 +00004154{
4155 struct bgp_filter *filter;
4156 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004157 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004158
4159 if (! peer->afc[afi][safi])
4160 return BGP_ERR_PEER_INACTIVE;
4161
paulfee0f4c2004-09-13 05:12:46 +00004162 if (direct != RMAP_IN && direct != RMAP_OUT &&
4163 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004164 return BGP_ERR_INVALID_VALUE;
4165
paulfee0f4c2004-09-13 05:12:46 +00004166 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4167 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004168 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4169
4170 filter = &peer->filter[afi][safi];
4171
4172 if (filter->map[direct].name)
4173 free (filter->map[direct].name);
4174
4175 filter->map[direct].name = strdup (name);
4176 filter->map[direct].map = route_map_lookup_by_name (name);
4177
4178 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4179 return 0;
4180
4181 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004182 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004183 {
4184 filter = &peer->filter[afi][safi];
4185
4186 if (! peer->af_group[afi][safi])
4187 continue;
4188
4189 if (filter->map[direct].name)
4190 free (filter->map[direct].name);
4191 filter->map[direct].name = strdup (name);
4192 filter->map[direct].map = route_map_lookup_by_name (name);
4193 }
4194 return 0;
4195}
4196
4197/* Unset route-map from the peer. */
4198int
4199peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4200{
4201 struct bgp_filter *filter;
4202 struct bgp_filter *gfilter;
4203 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004204 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004205
4206 if (! peer->afc[afi][safi])
4207 return BGP_ERR_PEER_INACTIVE;
4208
hassob5f29602005-05-25 21:00:28 +00004209 if (direct != RMAP_IN && direct != RMAP_OUT &&
4210 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004211 return BGP_ERR_INVALID_VALUE;
4212
hassob5f29602005-05-25 21:00:28 +00004213 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4214 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004215 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4216
4217 filter = &peer->filter[afi][safi];
4218
4219 /* apply peer-group filter */
4220 if (peer->af_group[afi][safi])
4221 {
4222 gfilter = &peer->group->conf->filter[afi][safi];
4223
4224 if (gfilter->map[direct].name)
4225 {
4226 if (filter->map[direct].name)
4227 free (filter->map[direct].name);
4228 filter->map[direct].name = strdup (gfilter->map[direct].name);
4229 filter->map[direct].map = gfilter->map[direct].map;
4230 return 0;
4231 }
4232 }
4233
4234 if (filter->map[direct].name)
4235 free (filter->map[direct].name);
4236 filter->map[direct].name = NULL;
4237 filter->map[direct].map = NULL;
4238
4239 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4240 return 0;
4241
4242 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004243 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004244 {
4245 filter = &peer->filter[afi][safi];
4246
4247 if (! peer->af_group[afi][safi])
4248 continue;
4249
4250 if (filter->map[direct].name)
4251 free (filter->map[direct].name);
4252 filter->map[direct].name = NULL;
4253 filter->map[direct].map = NULL;
4254 }
4255 return 0;
4256}
David Lamparter6b0655a2014-06-04 06:53:35 +02004257
paul718e3742002-12-13 20:15:29 +00004258/* Set unsuppress-map to the peer. */
4259int
paulfd79ac92004-10-13 05:06:08 +00004260peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4261 const char *name)
paul718e3742002-12-13 20:15:29 +00004262{
4263 struct bgp_filter *filter;
4264 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004265 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004266
4267 if (! peer->afc[afi][safi])
4268 return BGP_ERR_PEER_INACTIVE;
4269
4270 if (peer_is_group_member (peer, afi, safi))
4271 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4272
4273 filter = &peer->filter[afi][safi];
4274
4275 if (filter->usmap.name)
4276 free (filter->usmap.name);
4277
4278 filter->usmap.name = strdup (name);
4279 filter->usmap.map = route_map_lookup_by_name (name);
4280
4281 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4282 return 0;
4283
4284 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004285 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004286 {
4287 filter = &peer->filter[afi][safi];
4288
4289 if (! peer->af_group[afi][safi])
4290 continue;
4291
4292 if (filter->usmap.name)
4293 free (filter->usmap.name);
4294 filter->usmap.name = strdup (name);
4295 filter->usmap.map = route_map_lookup_by_name (name);
4296 }
4297 return 0;
4298}
4299
4300/* Unset route-map from the peer. */
4301int
4302peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4303{
4304 struct bgp_filter *filter;
4305 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004306 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004307
4308 if (! peer->afc[afi][safi])
4309 return BGP_ERR_PEER_INACTIVE;
4310
4311 if (peer_is_group_member (peer, afi, safi))
4312 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4313
4314 filter = &peer->filter[afi][safi];
4315
4316 if (filter->usmap.name)
4317 free (filter->usmap.name);
4318 filter->usmap.name = NULL;
4319 filter->usmap.map = NULL;
4320
4321 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4322 return 0;
4323
4324 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004325 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004326 {
4327 filter = &peer->filter[afi][safi];
4328
4329 if (! peer->af_group[afi][safi])
4330 continue;
4331
4332 if (filter->usmap.name)
4333 free (filter->usmap.name);
4334 filter->usmap.name = NULL;
4335 filter->usmap.map = NULL;
4336 }
4337 return 0;
4338}
David Lamparter6b0655a2014-06-04 06:53:35 +02004339
paul718e3742002-12-13 20:15:29 +00004340int
4341peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004342 u_int32_t max, u_char threshold,
4343 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004344{
4345 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004346 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004347
4348 if (! peer->afc[afi][safi])
4349 return BGP_ERR_PEER_INACTIVE;
4350
4351 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4352 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004353 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004354 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004355 if (warning)
4356 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4357 else
4358 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4359
4360 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4361 return 0;
4362
4363 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004364 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004365 {
4366 if (! peer->af_group[afi][safi])
4367 continue;
4368
4369 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4370 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004371 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004372 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004373 if (warning)
4374 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4375 else
4376 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4377 }
4378 return 0;
4379}
4380
4381int
4382peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4383{
4384 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004385 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004386
4387 if (! peer->afc[afi][safi])
4388 return BGP_ERR_PEER_INACTIVE;
4389
4390 /* apply peer-group config */
4391 if (peer->af_group[afi][safi])
4392 {
4393 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4394 PEER_FLAG_MAX_PREFIX))
4395 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4396 else
4397 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4398
4399 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4400 PEER_FLAG_MAX_PREFIX_WARNING))
4401 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4402 else
4403 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4404
4405 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004406 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004407 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004408 return 0;
4409 }
4410
4411 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4412 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4413 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004414 peer->pmax_threshold[afi][safi] = 0;
4415 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004416
4417 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4418 return 0;
4419
4420 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004421 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004422 {
4423 if (! peer->af_group[afi][safi])
4424 continue;
4425
4426 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4427 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4428 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004429 peer->pmax_threshold[afi][safi] = 0;
4430 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004431 }
4432 return 0;
4433}
David Lamparter5f9adb52014-05-19 23:15:02 +02004434
4435static int is_ebgp_multihop_configured (struct peer *peer)
4436{
4437 struct peer_group *group;
4438 struct listnode *node, *nnode;
4439 struct peer *peer1;
4440
4441 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4442 {
4443 group = peer->group;
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004444 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4445 (group->conf->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004446 return 1;
4447
4448 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4449 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004450 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
4451 (peer1->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004452 return 1;
4453 }
4454 }
4455 else
4456 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004457 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4458 (peer->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004459 return 1;
4460 }
4461 return 0;
4462}
4463
Nick Hilliardfa411a22011-03-23 15:33:17 +00004464/* Set # of hops between us and BGP peer. */
4465int
4466peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4467{
4468 struct peer_group *group;
4469 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004470 int ret;
4471
4472 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4473
Nick Hilliardfa411a22011-03-23 15:33:17 +00004474 /* We cannot configure ttl-security hops when ebgp-multihop is already
4475 set. For non peer-groups, the check is simple. For peer-groups, it's
4476 slightly messy, because we need to check both the peer-group structure
4477 and all peer-group members for any trace of ebgp-multihop configuration
4478 before actually applying the ttl-security rules. Cisco really made a
4479 mess of this configuration parameter, and OpenBGPD got it right.
4480 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004481
David Lamparter5f9adb52014-05-19 23:15:02 +02004482 if (peer->gtsm_hops == 0)
4483 {
4484 if (is_ebgp_multihop_configured (peer))
4485 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004486
David Lamparter5f9adb52014-05-19 23:15:02 +02004487 /* specify MAXTTL on outgoing packets */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004488 /* Routine handles iBGP peers correctly */
David Lamparter5f9adb52014-05-19 23:15:02 +02004489 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4490 if (ret != 0)
4491 return ret;
4492 }
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004493
Nick Hilliardfa411a22011-03-23 15:33:17 +00004494 peer->gtsm_hops = gtsm_hops;
4495
Nick Hilliardfa411a22011-03-23 15:33:17 +00004496 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4497 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004498 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004499 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4500 }
4501 else
4502 {
4503 group = peer->group;
4504 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4505 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004506 peer->gtsm_hops = group->conf->gtsm_hops;
4507
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004508 /* Change setting of existing peer
4509 * established then change value (may break connectivity)
4510 * not established yet (teardown session and restart)
4511 * no session then do nothing (will get handled by next connection)
4512 */
4513 if (peer->status == Established)
4514 {
4515 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4516 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4517 MAXTTL + 1 - peer->gtsm_hops);
4518 }
4519 else if (peer->status < Established)
4520 {
4521 if (BGP_DEBUG (events, EVENTS))
4522 zlog_debug ("%s Min-ttl changed", peer->host);
4523 BGP_EVENT_ADD (peer, BGP_Stop);
4524 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004525 }
4526 }
4527
4528 return 0;
4529}
4530
4531int
4532peer_ttl_security_hops_unset (struct peer *peer)
4533{
4534 struct peer_group *group;
4535 struct listnode *node, *nnode;
4536 struct peer *opeer;
4537
4538 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4539
Nick Hilliardfa411a22011-03-23 15:33:17 +00004540 /* if a peer-group member, then reset to peer-group default rather than 0 */
4541 if (peer_group_active (peer))
4542 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4543 else
4544 peer->gtsm_hops = 0;
4545
4546 opeer = peer;
4547 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4548 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004549 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004550 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4551 }
4552 else
4553 {
4554 group = peer->group;
4555 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4556 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004557 peer->gtsm_hops = 0;
4558
4559 if (peer->fd >= 0)
4560 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4561 }
4562 }
4563
4564 return peer_ebgp_multihop_unset (opeer);
4565}
David Lamparter6b0655a2014-06-04 06:53:35 +02004566
paul718e3742002-12-13 20:15:29 +00004567int
4568peer_clear (struct peer *peer)
4569{
4570 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4571 {
hasso0a486e52005-02-01 20:57:17 +00004572 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4573 {
4574 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4575 if (peer->t_pmax_restart)
4576 {
4577 BGP_TIMER_OFF (peer->t_pmax_restart);
4578 if (BGP_DEBUG (events, EVENTS))
4579 zlog_debug ("%s Maximum-prefix restart timer canceled",
4580 peer->host);
4581 }
4582 BGP_EVENT_ADD (peer, BGP_Start);
4583 return 0;
4584 }
4585
paul718e3742002-12-13 20:15:29 +00004586 peer->v_start = BGP_INIT_START_TIMER;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00004587 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00004588 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4589 BGP_NOTIFY_CEASE_ADMIN_RESET);
4590 else
4591 BGP_EVENT_ADD (peer, BGP_Stop);
4592 }
4593 return 0;
4594}
4595
4596int
4597peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4598 enum bgp_clear_type stype)
4599{
4600 if (peer->status != Established)
4601 return 0;
4602
4603 if (! peer->afc[afi][safi])
4604 return BGP_ERR_AF_UNCONFIGURED;
4605
paulfee0f4c2004-09-13 05:12:46 +00004606 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4607 {
4608 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4609 return 0;
4610 bgp_check_local_routes_rsclient (peer, afi, safi);
4611 bgp_soft_reconfig_rsclient (peer, afi, safi);
4612 }
4613
paul718e3742002-12-13 20:15:29 +00004614 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4615 bgp_announce_route (peer, afi, safi);
4616
4617 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4618 {
4619 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4620 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4621 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4622 {
4623 struct bgp_filter *filter = &peer->filter[afi][safi];
4624 u_char prefix_type;
4625
4626 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4627 prefix_type = ORF_TYPE_PREFIX;
4628 else
4629 prefix_type = ORF_TYPE_PREFIX_OLD;
4630
4631 if (filter->plist[FILTER_IN].plist)
4632 {
4633 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4634 bgp_route_refresh_send (peer, afi, safi,
4635 prefix_type, REFRESH_DEFER, 1);
4636 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4637 REFRESH_IMMEDIATE, 0);
4638 }
4639 else
4640 {
4641 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4642 bgp_route_refresh_send (peer, afi, safi,
4643 prefix_type, REFRESH_IMMEDIATE, 1);
4644 else
4645 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4646 }
4647 return 0;
4648 }
4649 }
4650
4651 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4652 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4653 {
4654 /* If neighbor has soft reconfiguration inbound flag.
4655 Use Adj-RIB-In database. */
4656 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4657 bgp_soft_reconfig_in (peer, afi, safi);
4658 else
4659 {
4660 /* If neighbor has route refresh capability, send route refresh
4661 message to the peer. */
4662 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4663 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4664 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4665 else
4666 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4667 }
4668 }
4669 return 0;
4670}
David Lamparter6b0655a2014-06-04 06:53:35 +02004671
paulfd79ac92004-10-13 05:06:08 +00004672/* Display peer uptime.*/
4673/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004674char *
4675peer_uptime (time_t uptime2, char *buf, size_t len)
4676{
4677 time_t uptime1;
4678 struct tm *tm;
4679
4680 /* Check buffer length. */
4681 if (len < BGP_UPTIME_LEN)
4682 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004683 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004684 /* XXX: should return status instead of buf... */
4685 snprintf (buf, len, "<error> ");
4686 return buf;
paul718e3742002-12-13 20:15:29 +00004687 }
4688
4689 /* If there is no connection has been done before print `never'. */
4690 if (uptime2 == 0)
4691 {
4692 snprintf (buf, len, "never ");
4693 return buf;
4694 }
4695
4696 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004697 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004698 uptime1 -= uptime2;
4699 tm = gmtime (&uptime1);
4700
4701 /* Making formatted timer strings. */
4702#define ONE_DAY_SECOND 60*60*24
4703#define ONE_WEEK_SECOND 60*60*24*7
4704
4705 if (uptime1 < ONE_DAY_SECOND)
4706 snprintf (buf, len, "%02d:%02d:%02d",
4707 tm->tm_hour, tm->tm_min, tm->tm_sec);
4708 else if (uptime1 < ONE_WEEK_SECOND)
4709 snprintf (buf, len, "%dd%02dh%02dm",
4710 tm->tm_yday, tm->tm_hour, tm->tm_min);
4711 else
4712 snprintf (buf, len, "%02dw%dd%02dh",
4713 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4714 return buf;
4715}
David Lamparter6b0655a2014-06-04 06:53:35 +02004716
paul94f2b392005-06-28 12:44:16 +00004717static void
paul718e3742002-12-13 20:15:29 +00004718bgp_config_write_filter (struct vty *vty, struct peer *peer,
4719 afi_t afi, safi_t safi)
4720{
4721 struct bgp_filter *filter;
4722 struct bgp_filter *gfilter = NULL;
4723 char *addr;
4724 int in = FILTER_IN;
4725 int out = FILTER_OUT;
4726
4727 addr = peer->host;
4728 filter = &peer->filter[afi][safi];
4729 if (peer->af_group[afi][safi])
4730 gfilter = &peer->group->conf->filter[afi][safi];
4731
4732 /* distribute-list. */
4733 if (filter->dlist[in].name)
4734 if (! gfilter || ! gfilter->dlist[in].name
4735 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4736 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4737 filter->dlist[in].name, VTY_NEWLINE);
4738 if (filter->dlist[out].name && ! gfilter)
4739 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4740 filter->dlist[out].name, VTY_NEWLINE);
4741
4742 /* prefix-list. */
4743 if (filter->plist[in].name)
4744 if (! gfilter || ! gfilter->plist[in].name
4745 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4746 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4747 filter->plist[in].name, VTY_NEWLINE);
4748 if (filter->plist[out].name && ! gfilter)
4749 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4750 filter->plist[out].name, VTY_NEWLINE);
4751
4752 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004753 if (filter->map[RMAP_IN].name)
4754 if (! gfilter || ! gfilter->map[RMAP_IN].name
4755 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004756 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004757 filter->map[RMAP_IN].name, VTY_NEWLINE);
4758 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004759 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004760 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4761 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4762 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4763 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4764 if (filter->map[RMAP_EXPORT].name)
4765 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4766 || strcmp (filter->map[RMAP_EXPORT].name,
4767 gfilter->map[RMAP_EXPORT].name) != 0)
4768 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4769 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004770
4771 /* unsuppress-map */
4772 if (filter->usmap.name && ! gfilter)
4773 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4774 filter->usmap.name, VTY_NEWLINE);
4775
4776 /* filter-list. */
4777 if (filter->aslist[in].name)
4778 if (! gfilter || ! gfilter->aslist[in].name
4779 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4780 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4781 filter->aslist[in].name, VTY_NEWLINE);
4782 if (filter->aslist[out].name && ! gfilter)
4783 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4784 filter->aslist[out].name, VTY_NEWLINE);
4785}
4786
4787/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004788static void
paul718e3742002-12-13 20:15:29 +00004789bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4790 struct peer *peer, afi_t afi, safi_t safi)
4791{
paul718e3742002-12-13 20:15:29 +00004792 struct peer *g_peer = NULL;
4793 char buf[SU_ADDRSTRLEN];
4794 char *addr;
4795
paul718e3742002-12-13 20:15:29 +00004796 addr = peer->host;
4797 if (peer_group_active (peer))
4798 g_peer = peer->group->conf;
4799
4800 /************************************
4801 ****** Global to the neighbor ******
4802 ************************************/
4803 if (afi == AFI_IP && safi == SAFI_UNICAST)
4804 {
4805 /* remote-as. */
4806 if (! peer_group_active (peer))
4807 {
4808 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4809 vty_out (vty, " neighbor %s peer-group%s", addr,
4810 VTY_NEWLINE);
4811 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004812 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004813 VTY_NEWLINE);
4814 }
4815 else
4816 {
4817 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004818 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004819 VTY_NEWLINE);
4820 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4821 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4822 peer->group->name, VTY_NEWLINE);
4823 }
4824
4825 /* local-as. */
4826 if (peer->change_local_as)
4827 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00004828 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004829 peer->change_local_as,
4830 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00004831 " no-prepend" : "",
4832 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
4833 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004834
4835 /* Description. */
4836 if (peer->desc)
4837 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4838 VTY_NEWLINE);
4839
4840 /* Shutdown. */
4841 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4842 if (! peer_group_active (peer) ||
4843 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4844 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4845
Paul Jakma0df7c912008-07-21 21:02:49 +00004846 /* Password. */
4847 if (peer->password)
4848 if (!peer_group_active (peer)
4849 || ! g_peer->password
4850 || strcmp (peer->password, g_peer->password) != 0)
4851 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4852 VTY_NEWLINE);
4853
paul718e3742002-12-13 20:15:29 +00004854 /* BGP port. */
4855 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004856 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004857 VTY_NEWLINE);
4858
4859 /* Local interface name. */
4860 if (peer->ifname)
4861 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4862 VTY_NEWLINE);
4863
4864 /* Passive. */
4865 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4866 if (! peer_group_active (peer) ||
4867 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4868 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4869
4870 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004871 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00004872 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00004873 if (! peer_group_active (peer) ||
4874 g_peer->ttl != peer->ttl)
4875 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4876 VTY_NEWLINE);
4877
Nick Hilliardfa411a22011-03-23 15:33:17 +00004878 /* ttl-security hops */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004879 if (peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004880 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004881 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00004882 peer->gtsm_hops, VTY_NEWLINE);
4883
hasso6ffd2072005-02-02 14:50:11 +00004884 /* disable-connected-check. */
4885 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004886 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004887 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4888 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004889
4890 /* Update-source. */
4891 if (peer->update_if)
4892 if (! peer_group_active (peer) || ! g_peer->update_if
4893 || strcmp (g_peer->update_if, peer->update_if) != 0)
4894 vty_out (vty, " neighbor %s update-source %s%s", addr,
4895 peer->update_if, VTY_NEWLINE);
4896 if (peer->update_source)
4897 if (! peer_group_active (peer) || ! g_peer->update_source
4898 || sockunion_cmp (g_peer->update_source,
4899 peer->update_source) != 0)
4900 vty_out (vty, " neighbor %s update-source %s%s", addr,
4901 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4902 VTY_NEWLINE);
4903
paul718e3742002-12-13 20:15:29 +00004904 /* advertisement-interval */
4905 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4906 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4907 addr, peer->v_routeadv, VTY_NEWLINE);
4908
4909 /* timers. */
4910 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4911 && ! peer_group_active (peer))
4912 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4913 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4914
4915 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4916 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4917 peer->connect, VTY_NEWLINE);
4918
4919 /* Default weight. */
4920 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4921 if (! peer_group_active (peer) ||
4922 g_peer->weight != peer->weight)
4923 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4924 VTY_NEWLINE);
4925
paul718e3742002-12-13 20:15:29 +00004926 /* Dynamic capability. */
4927 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4928 if (! peer_group_active (peer) ||
4929 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4930 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4931 VTY_NEWLINE);
4932
4933 /* dont capability negotiation. */
4934 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4935 if (! peer_group_active (peer) ||
4936 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4937 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4938 VTY_NEWLINE);
4939
4940 /* override capability negotiation. */
4941 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4942 if (! peer_group_active (peer) ||
4943 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4944 vty_out (vty, " neighbor %s override-capability%s", addr,
4945 VTY_NEWLINE);
4946
4947 /* strict capability negotiation. */
4948 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4949 if (! peer_group_active (peer) ||
4950 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4951 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4952 VTY_NEWLINE);
4953
Christian Franke15c71342012-11-19 11:17:31 +00004954 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
paul718e3742002-12-13 20:15:29 +00004955 {
4956 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4957 {
4958 if (peer->afc[AFI_IP][SAFI_UNICAST])
4959 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4960 }
4961 else
4962 {
4963 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4964 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4965 }
4966 }
4967 }
4968
4969
4970 /************************************
4971 ****** Per AF to the neighbor ******
4972 ************************************/
4973
4974 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4975 {
4976 if (peer->af_group[afi][safi])
4977 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4978 peer->group->name, VTY_NEWLINE);
4979 else
4980 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4981 }
4982
4983 /* ORF capability. */
4984 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4985 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4986 if (! peer->af_group[afi][safi])
4987 {
4988 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4989
4990 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4991 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4992 vty_out (vty, " both");
4993 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4994 vty_out (vty, " send");
4995 else
4996 vty_out (vty, " receive");
4997 vty_out (vty, "%s", VTY_NEWLINE);
4998 }
4999
5000 /* Route reflector client. */
5001 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
5002 && ! peer->af_group[afi][safi])
5003 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
5004 VTY_NEWLINE);
5005
5006 /* Nexthop self. */
5007 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
5008 && ! peer->af_group[afi][safi])
Timo Teräs9e7a53c2014-04-24 10:22:37 +03005009 vty_out (vty, " neighbor %s next-hop-self%s%s", addr,
5010 peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ?
5011 " all" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005012
5013 /* Remove private AS. */
5014 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
5015 && ! peer->af_group[afi][safi])
5016 vty_out (vty, " neighbor %s remove-private-AS%s",
5017 addr, VTY_NEWLINE);
5018
5019 /* send-community print. */
5020 if (! peer->af_group[afi][safi])
5021 {
5022 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5023 {
5024 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5025 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5026 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
5027 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5028 vty_out (vty, " neighbor %s send-community extended%s",
5029 addr, VTY_NEWLINE);
5030 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5031 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
5032 }
5033 else
5034 {
5035 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5036 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5037 vty_out (vty, " no neighbor %s send-community both%s",
5038 addr, VTY_NEWLINE);
5039 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5040 vty_out (vty, " no neighbor %s send-community extended%s",
5041 addr, VTY_NEWLINE);
5042 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5043 vty_out (vty, " no neighbor %s send-community%s",
5044 addr, VTY_NEWLINE);
5045 }
5046 }
5047
5048 /* Default information */
5049 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5050 && ! peer->af_group[afi][safi])
5051 {
5052 vty_out (vty, " neighbor %s default-originate", addr);
5053 if (peer->default_rmap[afi][safi].name)
5054 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5055 vty_out (vty, "%s", VTY_NEWLINE);
5056 }
5057
5058 /* Soft reconfiguration inbound. */
5059 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5060 if (! peer->af_group[afi][safi] ||
5061 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5062 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5063 VTY_NEWLINE);
5064
5065 /* maximum-prefix. */
5066 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5067 if (! peer->af_group[afi][safi]
5068 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005069 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005070 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5071 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005072 {
hasso0a486e52005-02-01 20:57:17 +00005073 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5074 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5075 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5076 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5077 vty_out (vty, " warning-only");
5078 if (peer->pmax_restart[afi][safi])
5079 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5080 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005081 }
paul718e3742002-12-13 20:15:29 +00005082
5083 /* Route server client. */
5084 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5085 && ! peer->af_group[afi][safi])
5086 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5087
Dylan Hall3cf12882011-10-27 15:28:17 +04005088 /* Nexthop-local unchanged. */
5089 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5090 && ! peer->af_group[afi][safi])
5091 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5092
paul718e3742002-12-13 20:15:29 +00005093 /* Allow AS in. */
5094 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5095 if (! peer_group_active (peer)
5096 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5097 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5098 {
5099 if (peer->allowas_in[afi][safi] == 3)
5100 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5101 else
5102 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5103 peer->allowas_in[afi][safi], VTY_NEWLINE);
5104 }
5105
5106 /* Filter. */
5107 bgp_config_write_filter (vty, peer, afi, safi);
5108
5109 /* atribute-unchanged. */
5110 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5111 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5112 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5113 && ! peer->af_group[afi][safi])
5114 {
5115 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5116 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5117 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5118 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5119 else
5120 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5121 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5122 " as-path" : "",
5123 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5124 " next-hop" : "",
5125 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5126 " med" : "", VTY_NEWLINE);
5127 }
5128}
5129
5130/* Display "address-family" configuration header. */
5131void
5132bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5133 int *write)
5134{
5135 if (*write)
5136 return;
5137
5138 if (afi == AFI_IP && safi == SAFI_UNICAST)
5139 return;
5140
5141 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5142
5143 if (afi == AFI_IP)
5144 {
5145 if (safi == SAFI_MULTICAST)
5146 vty_out (vty, "ipv4 multicast");
5147 else if (safi == SAFI_MPLS_VPN)
5148 vty_out (vty, "vpnv4 unicast");
5149 }
5150 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005151 {
5152 vty_out (vty, "ipv6");
5153
5154 if (safi == SAFI_MULTICAST)
5155 vty_out (vty, " multicast");
5156 }
paul718e3742002-12-13 20:15:29 +00005157
5158 vty_out (vty, "%s", VTY_NEWLINE);
5159
5160 *write = 1;
5161}
5162
5163/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005164static int
paul718e3742002-12-13 20:15:29 +00005165bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5166 safi_t safi)
5167{
5168 int write = 0;
5169 struct peer *peer;
5170 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005171 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005172
5173 bgp_config_write_network (vty, bgp, afi, safi, &write);
5174
5175 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5176
paul1eb8ef22005-04-07 07:30:20 +00005177 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005178 {
5179 if (group->conf->afc[afi][safi])
5180 {
5181 bgp_config_write_family_header (vty, afi, safi, &write);
5182 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5183 }
5184 }
paul1eb8ef22005-04-07 07:30:20 +00005185 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005186 {
5187 if (peer->afc[afi][safi])
5188 {
5189 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5190 {
5191 bgp_config_write_family_header (vty, afi, safi, &write);
5192 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5193 }
5194 }
5195 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005196
5197 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5198
paul718e3742002-12-13 20:15:29 +00005199 if (write)
5200 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5201
5202 return write;
5203}
5204
5205int
5206bgp_config_write (struct vty *vty)
5207{
5208 int write = 0;
5209 struct bgp *bgp;
5210 struct peer_group *group;
5211 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005212 struct listnode *node, *nnode;
5213 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005214
5215 /* BGP Multiple instance. */
5216 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5217 {
5218 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5219 write++;
5220 }
5221
5222 /* BGP Config type. */
5223 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5224 {
5225 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5226 write++;
5227 }
5228
5229 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005230 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005231 {
5232 if (write)
5233 vty_out (vty, "!%s", VTY_NEWLINE);
5234
5235 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005236 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005237
5238 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5239 {
5240 if (bgp->name)
5241 vty_out (vty, " view %s", bgp->name);
5242 }
5243 vty_out (vty, "%s", VTY_NEWLINE);
5244
5245 /* No Synchronization */
5246 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5247 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5248
5249 /* BGP fast-external-failover. */
5250 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5251 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5252
5253 /* BGP router ID. */
5254 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5255 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5256 VTY_NEWLINE);
5257
paul848973c2003-08-13 00:32:49 +00005258 /* BGP log-neighbor-changes. */
5259 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5260 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
5261
paul718e3742002-12-13 20:15:29 +00005262 /* BGP configuration. */
5263 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5264 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5265
5266 /* BGP default ipv4-unicast. */
5267 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5268 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5269
5270 /* BGP default local-preference. */
5271 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5272 vty_out (vty, " bgp default local-preference %d%s",
5273 bgp->default_local_pref, VTY_NEWLINE);
5274
5275 /* BGP client-to-client reflection. */
5276 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5277 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5278
5279 /* BGP cluster ID. */
5280 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5281 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5282 VTY_NEWLINE);
5283
hassoe0701b72004-05-20 09:19:34 +00005284 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005285 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005286 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5287 VTY_NEWLINE);
5288
5289 /* Confederation peer */
5290 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005291 {
hassoe0701b72004-05-20 09:19:34 +00005292 int i;
paul718e3742002-12-13 20:15:29 +00005293
hassoe0701b72004-05-20 09:19:34 +00005294 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005295
hassoe0701b72004-05-20 09:19:34 +00005296 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005297 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005298
hassoe0701b72004-05-20 09:19:34 +00005299 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005300 }
5301
5302 /* BGP enforce-first-as. */
5303 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5304 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5305
5306 /* BGP deterministic-med. */
5307 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5308 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005309
5310 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005311 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5312 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5313 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005314 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5315 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5316
paul718e3742002-12-13 20:15:29 +00005317 /* BGP bestpath method. */
5318 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5319 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005320 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5321 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
Pradosh Mohapatra2fdd4552013-09-07 07:02:36 +00005322 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
5323 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
5324 }
paul718e3742002-12-13 20:15:29 +00005325 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5326 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5327 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5328 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5329 {
5330 vty_out (vty, " bgp bestpath med");
5331 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5332 vty_out (vty, " confed");
5333 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5334 vty_out (vty, " missing-as-worst");
5335 vty_out (vty, "%s", VTY_NEWLINE);
5336 }
5337
5338 /* BGP network import check. */
5339 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5340 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5341
5342 /* BGP scan interval. */
5343 bgp_config_write_scan_time (vty);
5344
5345 /* BGP flag dampening. */
5346 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5347 BGP_CONFIG_DAMPENING))
5348 bgp_config_write_damp (vty);
5349
5350 /* BGP static route configuration. */
5351 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5352
5353 /* BGP redistribute configuration. */
5354 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5355
5356 /* BGP timers configuration. */
5357 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5358 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5359 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5360 bgp->default_holdtime, VTY_NEWLINE);
5361
5362 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005363 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005364 {
5365 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5366 }
5367
5368 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005369 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005370 {
5371 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5372 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5373 }
5374
Josh Bailey165b5ff2011-07-20 20:43:22 -07005375 /* maximum-paths */
5376 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5377
paul718e3742002-12-13 20:15:29 +00005378 /* Distance configuration. */
5379 bgp_config_write_distance (vty, bgp);
5380
5381 /* No auto-summary */
5382 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5383 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5384
5385 /* IPv4 multicast configuration. */
5386 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5387
5388 /* IPv4 VPN configuration. */
5389 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5390
5391 /* IPv6 unicast configuration. */
5392 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5393
Paul Jakma37a217a2007-04-10 19:20:29 +00005394 /* IPv6 multicast configuration. */
5395 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5396
paul718e3742002-12-13 20:15:29 +00005397 write++;
5398 }
5399 return write;
5400}
5401
5402void
paul94f2b392005-06-28 12:44:16 +00005403bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005404{
5405 memset (&bgp_master, 0, sizeof (struct bgp_master));
5406
5407 bm = &bgp_master;
5408 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005409 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005410 bm->port = BGP_PORT_DEFAULT;
5411 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005412 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005413}
paul200df112005-06-01 11:17:05 +00005414
David Lamparter6b0655a2014-06-04 06:53:35 +02005415
paul718e3742002-12-13 20:15:29 +00005416void
paul94f2b392005-06-28 12:44:16 +00005417bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005418{
paul718e3742002-12-13 20:15:29 +00005419 /* BGP VTY commands installation. */
5420 bgp_vty_init ();
5421
paul718e3742002-12-13 20:15:29 +00005422 /* Init zebra. */
5423 bgp_zebra_init ();
5424
5425 /* BGP inits. */
5426 bgp_attr_init ();
5427 bgp_debug_init ();
5428 bgp_dump_init ();
5429 bgp_route_init ();
5430 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005431 bgp_address_init ();
paul718e3742002-12-13 20:15:29 +00005432 bgp_scan_init ();
5433 bgp_mplsvpn_init ();
5434
5435 /* Access list initialize. */
5436 access_list_init ();
5437 access_list_add_hook (peer_distribute_update);
5438 access_list_delete_hook (peer_distribute_update);
5439
5440 /* Filter list initialize. */
5441 bgp_filter_init ();
5442 as_list_add_hook (peer_aslist_update);
5443 as_list_delete_hook (peer_aslist_update);
5444
5445 /* Prefix list initialize.*/
5446 prefix_list_init ();
5447 prefix_list_add_hook (peer_prefix_list_update);
5448 prefix_list_delete_hook (peer_prefix_list_update);
5449
5450 /* Community list initialize. */
5451 bgp_clist = community_list_init ();
5452
5453#ifdef HAVE_SNMP
5454 bgp_snmp_init ();
5455#endif /* HAVE_SNMP */
5456}
paul545acaf2004-04-20 15:13:15 +00005457
5458void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005459bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005460{
paul545acaf2004-04-20 15:13:15 +00005461 struct bgp *bgp;
5462 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005463 struct listnode *node, *nnode;
5464 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005465
paul1eb8ef22005-04-07 07:30:20 +00005466 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5467 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005468 if (peer->status == Established)
5469 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5470 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005471
paul545acaf2004-04-20 15:13:15 +00005472 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005473
paule210cf92005-06-15 19:15:35 +00005474 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005475 {
5476 work_queue_free (bm->process_main_queue);
5477 bm->process_main_queue = NULL;
5478 }
paule210cf92005-06-15 19:15:35 +00005479 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005480 {
5481 work_queue_free (bm->process_rsclient_queue);
5482 bm->process_rsclient_queue = NULL;
5483 }
paul545acaf2004-04-20 15:13:15 +00005484}