blob: 19b96fa93a8e0bfa3aba0f1c8f2f5fac18cba11a [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)
1031 peer = peer_create (su, bgp, local_as, *as, 0, 0);
1032 else
1033 peer = peer_create (su, bgp, local_as, *as, afi, safi);
1034 }
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
paul718e3742002-12-13 20:15:29 +00001930/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001931static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001932bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001933{
1934 struct bgp *bgp;
1935 afi_t afi;
1936 safi_t safi;
1937
paul200df112005-06-01 11:17:05 +00001938 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1939 return NULL;
1940
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07001941 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00001942 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00001943 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00001944
1945 bgp->peer = list_new ();
1946 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1947
1948 bgp->group = list_new ();
1949 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1950
paulfee0f4c2004-09-13 05:12:46 +00001951 bgp->rsclient = list_new ();
1952 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1953
paul718e3742002-12-13 20:15:29 +00001954 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1955 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1956 {
Paul Jakma64e580a2006-02-21 01:09:01 +00001957 bgp->route[afi][safi] = bgp_table_init (afi, safi);
1958 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1959 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07001960 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
1961 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00001962 }
1963
1964 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1965 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1966 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001967 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1968 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001969
1970 bgp->as = *as;
1971
1972 if (name)
1973 bgp->name = strdup (name);
1974
1975 return bgp;
1976}
1977
1978/* Return first entry of BGP. */
1979struct bgp *
paul94f2b392005-06-28 12:44:16 +00001980bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001981{
1982 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001983 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001984 return NULL;
1985}
1986
1987/* Lookup BGP entry. */
1988struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001989bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001990{
1991 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001992 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001993
paul1eb8ef22005-04-07 07:30:20 +00001994 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001995 if (bgp->as == as
1996 && ((bgp->name == NULL && name == NULL)
1997 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1998 return bgp;
1999 return NULL;
2000}
2001
2002/* Lookup BGP structure by view name. */
2003struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002004bgp_lookup_by_name (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->name == NULL && name == NULL)
2011 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2012 return bgp;
2013 return NULL;
2014}
2015
2016/* Called from VTY commands. */
2017int
paulfd79ac92004-10-13 05:06:08 +00002018bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002019{
2020 struct bgp *bgp;
2021
2022 /* Multiple instance check. */
2023 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2024 {
2025 if (name)
2026 bgp = bgp_lookup_by_name (name);
2027 else
2028 bgp = bgp_get_default ();
2029
2030 /* Already exists. */
2031 if (bgp)
2032 {
2033 if (bgp->as != *as)
2034 {
2035 *as = bgp->as;
2036 return BGP_ERR_INSTANCE_MISMATCH;
2037 }
2038 *bgp_val = bgp;
2039 return 0;
2040 }
2041 }
2042 else
2043 {
2044 /* BGP instance name can not be specified for single instance. */
2045 if (name)
2046 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2047
2048 /* Get default BGP structure if exists. */
2049 bgp = bgp_get_default ();
2050
2051 if (bgp)
2052 {
2053 if (bgp->as != *as)
2054 {
2055 *as = bgp->as;
2056 return BGP_ERR_AS_MISMATCH;
2057 }
2058 *bgp_val = bgp;
2059 return 0;
2060 }
2061 }
2062
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002063 bgp = bgp_create (as, name);
2064 bgp_router_id_set(bgp, &router_id_zebra);
2065 *bgp_val = bgp;
2066
Paul Jakmaad12dde2012-06-13 22:50:07 +01002067 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002068 if (list_isempty(bm->bgp)
2069 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002070 {
2071 if (bgp_socket (bm->port, bm->address) < 0)
2072 return BGP_ERR_INVALID_VALUE;
2073 }
2074
paul718e3742002-12-13 20:15:29 +00002075 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002076
2077 return 0;
2078}
2079
2080/* Delete BGP instance. */
2081int
2082bgp_delete (struct bgp *bgp)
2083{
2084 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002085 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002086 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002087 struct listnode *next;
2088 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002089 int i;
2090
2091 /* Delete static route. */
2092 bgp_static_delete (bgp);
2093
2094 /* Unset redistribution. */
2095 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2096 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2097 if (i != ZEBRA_ROUTE_BGP)
2098 bgp_redistribute_unset (bgp, afi, i);
2099
paul1eb8ef22005-04-07 07:30:20 +00002100 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002101 {
2102 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2103 {
2104 /* Send notify to remote peer. */
2105 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2106 }
2107
2108 peer_delete (peer);
2109 }
paul718e3742002-12-13 20:15:29 +00002110
Chris Caputo228da422009-07-18 05:44:03 +00002111 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002112 {
2113 for (ALL_LIST_ELEMENTS (group->peer, node, next, peer))
2114 {
2115 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2116 {
2117 /* Send notify to remote peer. */
2118 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2119 }
2120 }
2121 peer_group_delete (group);
2122 }
Chris Caputo228da422009-07-18 05:44:03 +00002123
2124 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002125
2126 if (bgp->peer_self) {
2127 peer_delete(bgp->peer_self);
2128 bgp->peer_self = NULL;
2129 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002130
2131 /* Remove visibility via the master list - there may however still be
2132 * routes to be processed still referencing the struct bgp.
2133 */
2134 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002135 if (list_isempty(bm->bgp))
2136 bgp_close ();
2137
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002138 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002139
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002140 return 0;
2141}
2142
2143static void bgp_free (struct bgp *);
2144
2145void
2146bgp_lock (struct bgp *bgp)
2147{
2148 ++bgp->lock;
2149}
2150
2151void
2152bgp_unlock(struct bgp *bgp)
2153{
Chris Caputo228da422009-07-18 05:44:03 +00002154 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002155 if (--bgp->lock == 0)
2156 bgp_free (bgp);
2157}
2158
2159static void
2160bgp_free (struct bgp *bgp)
2161{
2162 afi_t afi;
2163 safi_t safi;
2164
2165 list_delete (bgp->group);
2166 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002167 list_delete (bgp->rsclient);
2168
paul718e3742002-12-13 20:15:29 +00002169 if (bgp->name)
2170 free (bgp->name);
2171
2172 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2173 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2174 {
2175 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002176 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002177 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002178 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002179 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002180 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002181 }
2182 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002183}
David Lamparter6b0655a2014-06-04 06:53:35 +02002184
paul718e3742002-12-13 20:15:29 +00002185struct peer *
2186peer_lookup (struct bgp *bgp, union sockunion *su)
2187{
2188 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002189 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002190
Steve Hillfc4dc592009-07-28 17:54:35 +01002191 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002192 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002193 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2194 if (sockunion_same (&peer->su, su)
2195 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2196 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002197 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002198 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002199 {
2200 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002201
Paul Jakma2158ad22009-07-28 18:10:55 +01002202 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2203 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2204 if (sockunion_same (&peer->su, su)
2205 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2206 return peer;
paul718e3742002-12-13 20:15:29 +00002207 }
2208 return NULL;
2209}
2210
2211struct peer *
2212peer_lookup_with_open (union sockunion *su, as_t remote_as,
2213 struct in_addr *remote_id, int *as)
2214{
2215 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002216 struct listnode *node;
2217 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002218 struct bgp *bgp;
2219
Steve Hillfc4dc592009-07-28 17:54:35 +01002220 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002221 return NULL;
2222
Paul Jakma9d878772009-08-05 16:25:16 +01002223 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002224 {
Paul Jakma9d878772009-08-05 16:25:16 +01002225 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2226 {
2227 if (sockunion_same (&peer->su, su)
2228 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2229 {
2230 if (peer->as == remote_as
2231 && peer->remote_id.s_addr == remote_id->s_addr)
2232 return peer;
2233 if (peer->as == remote_as)
2234 *as = 1;
2235 }
2236 }
2237
2238 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2239 {
2240 if (sockunion_same (&peer->su, su)
2241 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2242 {
2243 if (peer->as == remote_as
2244 && peer->remote_id.s_addr == 0)
2245 return peer;
2246 if (peer->as == remote_as)
2247 *as = 1;
2248 }
2249 }
paul718e3742002-12-13 20:15:29 +00002250 }
2251 return NULL;
2252}
David Lamparter6b0655a2014-06-04 06:53:35 +02002253
paul718e3742002-12-13 20:15:29 +00002254/* If peer is configured at least one address family return 1. */
2255int
2256peer_active (struct peer *peer)
2257{
2258 if (peer->afc[AFI_IP][SAFI_UNICAST]
2259 || peer->afc[AFI_IP][SAFI_MULTICAST]
2260 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2261 || peer->afc[AFI_IP6][SAFI_UNICAST]
2262 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2263 return 1;
2264 return 0;
2265}
2266
2267/* If peer is negotiated at least one address family return 1. */
2268int
2269peer_active_nego (struct peer *peer)
2270{
2271 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2272 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2273 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2274 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2275 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2276 return 1;
2277 return 0;
2278}
David Lamparter6b0655a2014-06-04 06:53:35 +02002279
paul718e3742002-12-13 20:15:29 +00002280/* peer_flag_change_type. */
2281enum peer_change_type
2282{
2283 peer_change_none,
2284 peer_change_reset,
2285 peer_change_reset_in,
2286 peer_change_reset_out,
2287};
2288
paul94f2b392005-06-28 12:44:16 +00002289static void
paul718e3742002-12-13 20:15:29 +00002290peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2291 enum peer_change_type type)
2292{
2293 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2294 return;
2295
Stephen Hemmingerd9d4ae52010-01-13 00:32:39 +00002296 if (peer->status != Established)
2297 return;
2298
paul718e3742002-12-13 20:15:29 +00002299 if (type == peer_change_reset)
2300 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2301 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2302 else if (type == peer_change_reset_in)
2303 {
2304 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2305 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2306 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2307 else
2308 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2309 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2310 }
2311 else if (type == peer_change_reset_out)
2312 bgp_announce_route (peer, afi, safi);
2313}
2314
2315struct peer_flag_action
2316{
2317 /* Peer's flag. */
2318 u_int32_t flag;
2319
2320 /* This flag can be set for peer-group member. */
2321 u_char not_for_member;
2322
2323 /* Action when the flag is changed. */
2324 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002325
2326 /* Peer down cause */
2327 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002328};
2329
Stephen Hemminger03621952009-07-21 16:27:20 -07002330static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002331 {
2332 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2333 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2334 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2335 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2336 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002337 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002338 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002339 { 0, 0, 0 }
2340 };
2341
Stephen Hemminger03621952009-07-21 16:27:20 -07002342static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002343 {
2344 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2345 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2346 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2347 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2348 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2349 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2350 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2351 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2352 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2353 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2354 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2355 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2356 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002357 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002358 { 0, 0, 0 }
2359 };
2360
2361/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002362static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002363peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002364 struct peer_flag_action *action, u_int32_t flag)
2365{
2366 int i;
2367 int found = 0;
2368 int reset_in = 0;
2369 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002370 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002371
2372 /* Check peer's frag action. */
2373 for (i = 0; i < size; i++)
2374 {
2375 match = &action_list[i];
2376
2377 if (match->flag == 0)
2378 break;
2379
2380 if (match->flag & flag)
2381 {
2382 found = 1;
2383
2384 if (match->type == peer_change_reset_in)
2385 reset_in = 1;
2386 if (match->type == peer_change_reset_out)
2387 reset_out = 1;
2388 if (match->type == peer_change_reset)
2389 {
2390 reset_in = 1;
2391 reset_out = 1;
2392 }
2393 if (match->not_for_member)
2394 action->not_for_member = 1;
2395 }
2396 }
2397
2398 /* Set peer clear type. */
2399 if (reset_in && reset_out)
2400 action->type = peer_change_reset;
2401 else if (reset_in)
2402 action->type = peer_change_reset_in;
2403 else if (reset_out)
2404 action->type = peer_change_reset_out;
2405 else
2406 action->type = peer_change_none;
2407
2408 return found;
2409}
2410
paul94f2b392005-06-28 12:44:16 +00002411static void
paul718e3742002-12-13 20:15:29 +00002412peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2413{
2414 if (flag == PEER_FLAG_SHUTDOWN)
2415 {
2416 if (CHECK_FLAG (peer->flags, flag))
2417 {
hasso93406d82005-02-02 14:40:33 +00002418 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2419 peer_nsf_stop (peer);
2420
hasso0a486e52005-02-01 20:57:17 +00002421 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2422 if (peer->t_pmax_restart)
2423 {
2424 BGP_TIMER_OFF (peer->t_pmax_restart);
2425 if (BGP_DEBUG (events, EVENTS))
2426 zlog_debug ("%s Maximum-prefix restart timer canceled",
2427 peer->host);
2428 }
2429
hasso93406d82005-02-02 14:40:33 +00002430 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2431 peer_nsf_stop (peer);
2432
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002433 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002434 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2435 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2436 else
2437 BGP_EVENT_ADD (peer, BGP_Stop);
2438 }
2439 else
2440 {
2441 peer->v_start = BGP_INIT_START_TIMER;
2442 BGP_EVENT_ADD (peer, BGP_Stop);
2443 }
2444 }
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002445 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002446 {
hassoc9502432005-02-01 22:01:48 +00002447 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2448 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2449 else if (flag == PEER_FLAG_PASSIVE)
2450 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002451 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002452 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002453
hassoc9502432005-02-01 22:01:48 +00002454 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2455 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002456 }
2457 else
2458 BGP_EVENT_ADD (peer, BGP_Stop);
2459}
2460
2461/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002462static int
paul718e3742002-12-13 20:15:29 +00002463peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2464{
2465 int found;
2466 int size;
2467 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002468 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002469 struct peer_flag_action action;
2470
2471 memset (&action, 0, sizeof (struct peer_flag_action));
2472 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2473
2474 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2475
2476 /* No flag action is found. */
2477 if (! found)
2478 return BGP_ERR_INVALID_FLAG;
2479
2480 /* Not for peer-group member. */
2481 if (action.not_for_member && peer_group_active (peer))
2482 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2483
2484 /* When unset the peer-group member's flag we have to check
2485 peer-group configuration. */
2486 if (! set && peer_group_active (peer))
2487 if (CHECK_FLAG (peer->group->conf->flags, flag))
2488 {
2489 if (flag == PEER_FLAG_SHUTDOWN)
2490 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2491 else
2492 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2493 }
2494
2495 /* Flag conflict check. */
2496 if (set
2497 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2498 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2499 return BGP_ERR_PEER_FLAG_CONFLICT;
2500
2501 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2502 {
2503 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2504 return 0;
2505 if (! set && ! CHECK_FLAG (peer->flags, flag))
2506 return 0;
2507 }
2508
2509 if (set)
2510 SET_FLAG (peer->flags, flag);
2511 else
2512 UNSET_FLAG (peer->flags, flag);
2513
2514 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2515 {
2516 if (action.type == peer_change_reset)
2517 peer_flag_modify_action (peer, flag);
2518
2519 return 0;
2520 }
2521
2522 /* peer-group member updates. */
2523 group = peer->group;
2524
paul1eb8ef22005-04-07 07:30:20 +00002525 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002526 {
2527 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2528 continue;
2529
2530 if (! set && ! CHECK_FLAG (peer->flags, flag))
2531 continue;
2532
2533 if (set)
2534 SET_FLAG (peer->flags, flag);
2535 else
2536 UNSET_FLAG (peer->flags, flag);
2537
2538 if (action.type == peer_change_reset)
2539 peer_flag_modify_action (peer, flag);
2540 }
2541 return 0;
2542}
2543
2544int
2545peer_flag_set (struct peer *peer, u_int32_t flag)
2546{
2547 return peer_flag_modify (peer, flag, 1);
2548}
2549
2550int
2551peer_flag_unset (struct peer *peer, u_int32_t flag)
2552{
2553 return peer_flag_modify (peer, flag, 0);
2554}
2555
paul94f2b392005-06-28 12:44:16 +00002556static int
paul718e3742002-12-13 20:15:29 +00002557peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2558{
2559 if (peer->af_group[afi][safi])
2560 return 1;
2561 return 0;
2562}
2563
paul94f2b392005-06-28 12:44:16 +00002564static int
paul718e3742002-12-13 20:15:29 +00002565peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2566 int set)
2567{
2568 int found;
2569 int size;
paul1eb8ef22005-04-07 07:30:20 +00002570 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002571 struct peer_group *group;
2572 struct peer_flag_action action;
2573
2574 memset (&action, 0, sizeof (struct peer_flag_action));
2575 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2576
2577 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2578
2579 /* No flag action is found. */
2580 if (! found)
2581 return BGP_ERR_INVALID_FLAG;
2582
2583 /* Adress family must be activated. */
2584 if (! peer->afc[afi][safi])
2585 return BGP_ERR_PEER_INACTIVE;
2586
2587 /* Not for peer-group member. */
2588 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2589 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2590
2591 /* Spcecial check for reflector client. */
2592 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2593 && peer_sort (peer) != BGP_PEER_IBGP)
2594 return BGP_ERR_NOT_INTERNAL_PEER;
2595
2596 /* Spcecial check for remove-private-AS. */
2597 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2598 && peer_sort (peer) == BGP_PEER_IBGP)
2599 return BGP_ERR_REMOVE_PRIVATE_AS;
2600
2601 /* When unset the peer-group member's flag we have to check
2602 peer-group configuration. */
2603 if (! set && peer->af_group[afi][safi])
2604 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2605 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2606
2607 /* When current flag configuration is same as requested one. */
2608 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2609 {
2610 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2611 return 0;
2612 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2613 return 0;
2614 }
2615
2616 if (set)
2617 SET_FLAG (peer->af_flags[afi][safi], flag);
2618 else
2619 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2620
2621 /* Execute action when peer is established. */
2622 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2623 && peer->status == Established)
2624 {
2625 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2626 bgp_clear_adj_in (peer, afi, safi);
2627 else
hassoe0701b72004-05-20 09:19:34 +00002628 {
2629 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2630 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2631 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2632 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2633 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2634 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2635 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2636 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2637
2638 peer_change_action (peer, afi, safi, action.type);
2639 }
2640
paul718e3742002-12-13 20:15:29 +00002641 }
2642
2643 /* Peer group member updates. */
2644 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2645 {
2646 group = peer->group;
2647
paul1eb8ef22005-04-07 07:30:20 +00002648 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002649 {
2650 if (! peer->af_group[afi][safi])
2651 continue;
2652
2653 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2654 continue;
2655
2656 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2657 continue;
2658
2659 if (set)
2660 SET_FLAG (peer->af_flags[afi][safi], flag);
2661 else
2662 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2663
2664 if (peer->status == Established)
2665 {
2666 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2667 bgp_clear_adj_in (peer, afi, safi);
2668 else
hassoe0701b72004-05-20 09:19:34 +00002669 {
2670 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2671 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2672 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2673 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2674 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2675 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2676 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2677 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2678
2679 peer_change_action (peer, afi, safi, action.type);
2680 }
paul718e3742002-12-13 20:15:29 +00002681 }
2682 }
2683 }
2684 return 0;
2685}
2686
2687int
2688peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2689{
2690 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2691}
2692
2693int
2694peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2695{
2696 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2697}
David Lamparter6b0655a2014-06-04 06:53:35 +02002698
paul718e3742002-12-13 20:15:29 +00002699/* EBGP multihop configuration. */
2700int
2701peer_ebgp_multihop_set (struct peer *peer, int ttl)
2702{
2703 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002704 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002705 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002706
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002707 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002708 return 0;
2709
Nick Hilliardfa411a22011-03-23 15:33:17 +00002710 /* see comment in peer_ttl_security_hops_set() */
2711 if (ttl != MAXTTL)
2712 {
2713 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2714 {
2715 group = peer->group;
2716 if (group->conf->gtsm_hops != 0)
2717 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2718
2719 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2720 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002721 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002722 continue;
2723
2724 if (peer1->gtsm_hops != 0)
2725 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2726 }
2727 }
2728 else
2729 {
2730 if (peer->gtsm_hops != 0)
2731 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2732 }
2733 }
2734
paul718e3742002-12-13 20:15:29 +00002735 peer->ttl = ttl;
2736
2737 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2738 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002739 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002740 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002741 }
2742 else
2743 {
2744 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002745 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002746 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002747 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002748 continue;
paul718e3742002-12-13 20:15:29 +00002749
pauleb821182004-05-01 08:44:08 +00002750 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002751
pauleb821182004-05-01 08:44:08 +00002752 if (peer->fd >= 0)
2753 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2754 }
paul718e3742002-12-13 20:15:29 +00002755 }
2756 return 0;
2757}
2758
2759int
2760peer_ebgp_multihop_unset (struct peer *peer)
2761{
2762 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002763 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002764
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002765 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002766 return 0;
2767
Nick Hilliardfa411a22011-03-23 15:33:17 +00002768 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2769 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2770
paul718e3742002-12-13 20:15:29 +00002771 if (peer_group_active (peer))
2772 peer->ttl = peer->group->conf->ttl;
2773 else
2774 peer->ttl = 1;
2775
2776 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2777 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002778 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002779 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002780 }
2781 else
2782 {
2783 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002784 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002785 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002786 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002787 continue;
paul718e3742002-12-13 20:15:29 +00002788
pauleb821182004-05-01 08:44:08 +00002789 peer->ttl = 1;
2790
2791 if (peer->fd >= 0)
2792 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2793 }
paul718e3742002-12-13 20:15:29 +00002794 }
2795 return 0;
2796}
David Lamparter6b0655a2014-06-04 06:53:35 +02002797
paul718e3742002-12-13 20:15:29 +00002798/* Neighbor description. */
2799int
2800peer_description_set (struct peer *peer, char *desc)
2801{
2802 if (peer->desc)
2803 XFREE (MTYPE_PEER_DESC, peer->desc);
2804
2805 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2806
2807 return 0;
2808}
2809
2810int
2811peer_description_unset (struct peer *peer)
2812{
2813 if (peer->desc)
2814 XFREE (MTYPE_PEER_DESC, peer->desc);
2815
2816 peer->desc = NULL;
2817
2818 return 0;
2819}
David Lamparter6b0655a2014-06-04 06:53:35 +02002820
paul718e3742002-12-13 20:15:29 +00002821/* Neighbor update-source. */
2822int
paulfd79ac92004-10-13 05:06:08 +00002823peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002824{
2825 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002826 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002827
2828 if (peer->update_if)
2829 {
2830 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2831 && strcmp (peer->update_if, ifname) == 0)
2832 return 0;
2833
2834 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2835 peer->update_if = NULL;
2836 }
2837
2838 if (peer->update_source)
2839 {
2840 sockunion_free (peer->update_source);
2841 peer->update_source = NULL;
2842 }
2843
2844 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2845
2846 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2847 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002848 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002849 {
2850 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2851 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2852 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2853 }
paul718e3742002-12-13 20:15:29 +00002854 else
2855 BGP_EVENT_ADD (peer, BGP_Stop);
2856 return 0;
2857 }
2858
2859 /* peer-group member updates. */
2860 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002861 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002862 {
2863 if (peer->update_if)
2864 {
2865 if (strcmp (peer->update_if, ifname) == 0)
2866 continue;
2867
2868 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2869 peer->update_if = NULL;
2870 }
2871
2872 if (peer->update_source)
2873 {
2874 sockunion_free (peer->update_source);
2875 peer->update_source = NULL;
2876 }
2877
2878 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2879
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002880 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002881 {
2882 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2883 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2884 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2885 }
paul718e3742002-12-13 20:15:29 +00002886 else
2887 BGP_EVENT_ADD (peer, BGP_Stop);
2888 }
2889 return 0;
2890}
2891
2892int
2893peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2894{
2895 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002896 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002897
2898 if (peer->update_source)
2899 {
2900 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2901 && sockunion_cmp (peer->update_source, su) == 0)
2902 return 0;
2903 sockunion_free (peer->update_source);
2904 peer->update_source = NULL;
2905 }
2906
2907 if (peer->update_if)
2908 {
2909 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2910 peer->update_if = NULL;
2911 }
2912
2913 peer->update_source = sockunion_dup (su);
2914
2915 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2916 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002917 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002918 {
2919 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2920 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2921 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2922 }
paul718e3742002-12-13 20:15:29 +00002923 else
2924 BGP_EVENT_ADD (peer, BGP_Stop);
2925 return 0;
2926 }
2927
2928 /* peer-group member updates. */
2929 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002930 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002931 {
2932 if (peer->update_source)
2933 {
2934 if (sockunion_cmp (peer->update_source, su) == 0)
2935 continue;
2936 sockunion_free (peer->update_source);
2937 peer->update_source = NULL;
2938 }
2939
2940 if (peer->update_if)
2941 {
2942 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2943 peer->update_if = NULL;
2944 }
2945
2946 peer->update_source = sockunion_dup (su);
2947
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002948 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002949 {
2950 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2951 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2952 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2953 }
paul718e3742002-12-13 20:15:29 +00002954 else
2955 BGP_EVENT_ADD (peer, BGP_Stop);
2956 }
2957 return 0;
2958}
2959
2960int
2961peer_update_source_unset (struct peer *peer)
2962{
2963 union sockunion *su;
2964 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002965 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002966
2967 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2968 && ! peer->update_source
2969 && ! peer->update_if)
2970 return 0;
2971
2972 if (peer->update_source)
2973 {
2974 sockunion_free (peer->update_source);
2975 peer->update_source = NULL;
2976 }
2977 if (peer->update_if)
2978 {
2979 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2980 peer->update_if = NULL;
2981 }
2982
2983 if (peer_group_active (peer))
2984 {
2985 group = peer->group;
2986
2987 if (group->conf->update_source)
2988 {
2989 su = sockunion_dup (group->conf->update_source);
2990 peer->update_source = su;
2991 }
2992 else if (group->conf->update_if)
2993 peer->update_if =
2994 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2995 }
2996
2997 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2998 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002999 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003000 {
3001 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3002 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3003 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3004 }
paul718e3742002-12-13 20:15:29 +00003005 else
3006 BGP_EVENT_ADD (peer, BGP_Stop);
3007 return 0;
3008 }
3009
3010 /* peer-group member updates. */
3011 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003012 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003013 {
3014 if (! peer->update_source && ! peer->update_if)
3015 continue;
3016
3017 if (peer->update_source)
3018 {
3019 sockunion_free (peer->update_source);
3020 peer->update_source = NULL;
3021 }
3022
3023 if (peer->update_if)
3024 {
3025 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3026 peer->update_if = NULL;
3027 }
3028
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003029 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003030 {
3031 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3032 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3033 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3034 }
paul718e3742002-12-13 20:15:29 +00003035 else
3036 BGP_EVENT_ADD (peer, BGP_Stop);
3037 }
3038 return 0;
3039}
David Lamparter6b0655a2014-06-04 06:53:35 +02003040
paul718e3742002-12-13 20:15:29 +00003041int
3042peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003043 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003044{
3045 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003046 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003047
3048 /* Adress family must be activated. */
3049 if (! peer->afc[afi][safi])
3050 return BGP_ERR_PEER_INACTIVE;
3051
3052 /* Default originate can't be used for peer group memeber. */
3053 if (peer_is_group_member (peer, afi, safi))
3054 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3055
3056 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3057 || (rmap && ! peer->default_rmap[afi][safi].name)
3058 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3059 {
3060 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3061
3062 if (rmap)
3063 {
3064 if (peer->default_rmap[afi][safi].name)
3065 free (peer->default_rmap[afi][safi].name);
3066 peer->default_rmap[afi][safi].name = strdup (rmap);
3067 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3068 }
3069 }
3070
3071 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3072 {
3073 if (peer->status == Established && peer->afc_nego[afi][safi])
3074 bgp_default_originate (peer, afi, safi, 0);
3075 return 0;
3076 }
3077
3078 /* peer-group member updates. */
3079 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003080 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003081 {
3082 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3083
3084 if (rmap)
3085 {
3086 if (peer->default_rmap[afi][safi].name)
3087 free (peer->default_rmap[afi][safi].name);
3088 peer->default_rmap[afi][safi].name = strdup (rmap);
3089 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3090 }
3091
3092 if (peer->status == Established && peer->afc_nego[afi][safi])
3093 bgp_default_originate (peer, afi, safi, 0);
3094 }
3095 return 0;
3096}
3097
3098int
3099peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3100{
3101 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003102 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003103
3104 /* Adress family must be activated. */
3105 if (! peer->afc[afi][safi])
3106 return BGP_ERR_PEER_INACTIVE;
3107
3108 /* Default originate can't be used for peer group memeber. */
3109 if (peer_is_group_member (peer, afi, safi))
3110 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3111
3112 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3113 {
3114 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3115
3116 if (peer->default_rmap[afi][safi].name)
3117 free (peer->default_rmap[afi][safi].name);
3118 peer->default_rmap[afi][safi].name = NULL;
3119 peer->default_rmap[afi][safi].map = NULL;
3120 }
3121
3122 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3123 {
3124 if (peer->status == Established && peer->afc_nego[afi][safi])
3125 bgp_default_originate (peer, afi, safi, 1);
3126 return 0;
3127 }
3128
3129 /* peer-group member updates. */
3130 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003131 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003132 {
3133 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3134
3135 if (peer->default_rmap[afi][safi].name)
3136 free (peer->default_rmap[afi][safi].name);
3137 peer->default_rmap[afi][safi].name = NULL;
3138 peer->default_rmap[afi][safi].map = NULL;
3139
3140 if (peer->status == Established && peer->afc_nego[afi][safi])
3141 bgp_default_originate (peer, afi, safi, 1);
3142 }
3143 return 0;
3144}
David Lamparter6b0655a2014-06-04 06:53:35 +02003145
paul718e3742002-12-13 20:15:29 +00003146int
3147peer_port_set (struct peer *peer, u_int16_t port)
3148{
3149 peer->port = port;
3150 return 0;
3151}
3152
3153int
3154peer_port_unset (struct peer *peer)
3155{
3156 peer->port = BGP_PORT_DEFAULT;
3157 return 0;
3158}
David Lamparter6b0655a2014-06-04 06:53:35 +02003159
paul718e3742002-12-13 20:15:29 +00003160/* neighbor weight. */
3161int
3162peer_weight_set (struct peer *peer, u_int16_t weight)
3163{
3164 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003165 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003166
3167 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3168 peer->weight = weight;
3169
3170 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3171 return 0;
3172
3173 /* peer-group member updates. */
3174 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003175 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003176 {
3177 peer->weight = group->conf->weight;
3178 }
3179 return 0;
3180}
3181
3182int
3183peer_weight_unset (struct peer *peer)
3184{
3185 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003186 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003187
3188 /* Set default weight. */
3189 if (peer_group_active (peer))
3190 peer->weight = peer->group->conf->weight;
3191 else
3192 peer->weight = 0;
3193
3194 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3195
3196 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3197 return 0;
3198
3199 /* peer-group member updates. */
3200 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003201 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003202 {
3203 peer->weight = 0;
3204 }
3205 return 0;
3206}
David Lamparter6b0655a2014-06-04 06:53:35 +02003207
paul718e3742002-12-13 20:15:29 +00003208int
3209peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3210{
3211 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003212 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003213
3214 /* Not for peer group memeber. */
3215 if (peer_group_active (peer))
3216 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3217
3218 /* keepalive value check. */
3219 if (keepalive > 65535)
3220 return BGP_ERR_INVALID_VALUE;
3221
3222 /* Holdtime value check. */
3223 if (holdtime > 65535)
3224 return BGP_ERR_INVALID_VALUE;
3225
3226 /* Holdtime value must be either 0 or greater than 3. */
3227 if (holdtime < 3 && holdtime != 0)
3228 return BGP_ERR_INVALID_VALUE;
3229
3230 /* Set value to the configuration. */
3231 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3232 peer->holdtime = holdtime;
3233 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3234
3235 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3236 return 0;
3237
3238 /* peer-group member updates. */
3239 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003240 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003241 {
3242 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3243 peer->holdtime = group->conf->holdtime;
3244 peer->keepalive = group->conf->keepalive;
3245 }
3246 return 0;
3247}
3248
3249int
3250peer_timers_unset (struct peer *peer)
3251{
3252 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003253 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003254
3255 if (peer_group_active (peer))
3256 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3257
3258 /* Clear configuration. */
3259 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3260 peer->keepalive = 0;
3261 peer->holdtime = 0;
3262
3263 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3264 return 0;
3265
3266 /* peer-group member updates. */
3267 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003268 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003269 {
3270 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3271 peer->holdtime = 0;
3272 peer->keepalive = 0;
3273 }
3274
3275 return 0;
3276}
David Lamparter6b0655a2014-06-04 06:53:35 +02003277
paul718e3742002-12-13 20:15:29 +00003278int
3279peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3280{
3281 if (peer_group_active (peer))
3282 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3283
3284 if (connect > 65535)
3285 return BGP_ERR_INVALID_VALUE;
3286
3287 /* Set value to the configuration. */
3288 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3289 peer->connect = connect;
3290
3291 /* Set value to timer setting. */
3292 peer->v_connect = connect;
3293
3294 return 0;
3295}
3296
3297int
3298peer_timers_connect_unset (struct peer *peer)
3299{
3300 if (peer_group_active (peer))
3301 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3302
3303 /* Clear configuration. */
3304 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3305 peer->connect = 0;
3306
3307 /* Set timer setting to default value. */
3308 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3309
3310 return 0;
3311}
David Lamparter6b0655a2014-06-04 06:53:35 +02003312
paul718e3742002-12-13 20:15:29 +00003313int
3314peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3315{
3316 if (peer_group_active (peer))
3317 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3318
3319 if (routeadv > 600)
3320 return BGP_ERR_INVALID_VALUE;
3321
3322 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3323 peer->routeadv = routeadv;
3324 peer->v_routeadv = routeadv;
3325
3326 return 0;
3327}
3328
3329int
3330peer_advertise_interval_unset (struct peer *peer)
3331{
3332 if (peer_group_active (peer))
3333 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3334
3335 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3336 peer->routeadv = 0;
3337
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003338 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003339 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3340 else
3341 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3342
3343 return 0;
3344}
David Lamparter6b0655a2014-06-04 06:53:35 +02003345
paul718e3742002-12-13 20:15:29 +00003346/* neighbor interface */
3347int
paulfd79ac92004-10-13 05:06:08 +00003348peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003349{
3350 if (peer->ifname)
3351 free (peer->ifname);
3352 peer->ifname = strdup (str);
3353
3354 return 0;
3355}
3356
3357int
3358peer_interface_unset (struct peer *peer)
3359{
3360 if (peer->ifname)
3361 free (peer->ifname);
3362 peer->ifname = NULL;
3363
3364 return 0;
3365}
David Lamparter6b0655a2014-06-04 06:53:35 +02003366
paul718e3742002-12-13 20:15:29 +00003367/* Allow-as in. */
3368int
3369peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3370{
3371 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003372 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003373
3374 if (allow_num < 1 || allow_num > 10)
3375 return BGP_ERR_INVALID_VALUE;
3376
3377 if (peer->allowas_in[afi][safi] != allow_num)
3378 {
3379 peer->allowas_in[afi][safi] = allow_num;
3380 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3381 peer_change_action (peer, afi, safi, peer_change_reset_in);
3382 }
3383
3384 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3385 return 0;
3386
3387 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003388 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003389 {
3390 if (peer->allowas_in[afi][safi] != allow_num)
3391 {
3392 peer->allowas_in[afi][safi] = allow_num;
3393 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3394 peer_change_action (peer, afi, safi, peer_change_reset_in);
3395 }
3396
3397 }
3398 return 0;
3399}
3400
3401int
3402peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3403{
3404 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003405 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003406
3407 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3408 {
3409 peer->allowas_in[afi][safi] = 0;
3410 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3411 }
3412
3413 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3414 return 0;
3415
3416 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003417 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003418 {
3419 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3420 {
3421 peer->allowas_in[afi][safi] = 0;
3422 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3423 }
3424 }
3425 return 0;
3426}
David Lamparter6b0655a2014-06-04 06:53:35 +02003427
paul718e3742002-12-13 20:15:29 +00003428int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003429peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003430{
3431 struct bgp *bgp = peer->bgp;
3432 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003433 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003434
3435 if (peer_sort (peer) != BGP_PEER_EBGP
3436 && peer_sort (peer) != BGP_PEER_INTERNAL)
3437 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3438
3439 if (bgp->as == as)
3440 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3441
3442 if (peer_group_active (peer))
3443 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3444
Andrew Certain9d3f9702012-11-07 23:50:07 +00003445 if (peer->as == as)
3446 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3447
paul718e3742002-12-13 20:15:29 +00003448 if (peer->change_local_as == as &&
3449 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003450 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3451 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3452 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003453 return 0;
3454
3455 peer->change_local_as = as;
3456 if (no_prepend)
3457 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3458 else
3459 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3460
Andrew Certain9d3f9702012-11-07 23:50:07 +00003461 if (replace_as)
3462 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3463 else
3464 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3465
paul718e3742002-12-13 20:15:29 +00003466 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3467 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003468 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003469 {
3470 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3471 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3472 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3473 }
paul718e3742002-12-13 20:15:29 +00003474 else
3475 BGP_EVENT_ADD (peer, BGP_Stop);
3476
3477 return 0;
3478 }
3479
3480 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003481 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003482 {
3483 peer->change_local_as = as;
3484 if (no_prepend)
3485 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3486 else
3487 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3488
Andrew Certain9d3f9702012-11-07 23:50:07 +00003489 if (replace_as)
3490 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3491 else
3492 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3493
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003494 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003495 {
3496 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3497 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3498 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3499 }
paul718e3742002-12-13 20:15:29 +00003500 else
3501 BGP_EVENT_ADD (peer, BGP_Stop);
3502 }
3503
3504 return 0;
3505}
3506
3507int
3508peer_local_as_unset (struct peer *peer)
3509{
3510 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003511 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003512
3513 if (peer_group_active (peer))
3514 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3515
3516 if (! peer->change_local_as)
3517 return 0;
3518
3519 peer->change_local_as = 0;
3520 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003521 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003522
3523 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3524 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003525 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003526 {
3527 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3528 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3529 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3530 }
paul718e3742002-12-13 20:15:29 +00003531 else
3532 BGP_EVENT_ADD (peer, BGP_Stop);
3533
3534 return 0;
3535 }
3536
3537 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003538 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003539 {
3540 peer->change_local_as = 0;
3541 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003542 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003543
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003544 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003545 {
3546 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3547 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3548 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3549 }
paul718e3742002-12-13 20:15:29 +00003550 else
3551 BGP_EVENT_ADD (peer, BGP_Stop);
3552 }
3553 return 0;
3554}
David Lamparter6b0655a2014-06-04 06:53:35 +02003555
Paul Jakma0df7c912008-07-21 21:02:49 +00003556/* Set password for authenticating with the peer. */
3557int
3558peer_password_set (struct peer *peer, const char *password)
3559{
3560 struct listnode *nn, *nnode;
3561 int len = password ? strlen(password) : 0;
3562 int ret = BGP_SUCCESS;
3563
3564 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3565 return BGP_ERR_INVALID_VALUE;
3566
3567 if (peer->password && strcmp (peer->password, password) == 0
3568 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3569 return 0;
3570
3571 if (peer->password)
3572 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3573
3574 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3575
3576 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3577 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003578 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3579 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
Paul Jakma0df7c912008-07-21 21:02:49 +00003580 else
3581 BGP_EVENT_ADD (peer, BGP_Stop);
3582
3583 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3584 }
3585
3586 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3587 {
3588 if (peer->password && strcmp (peer->password, password) == 0)
3589 continue;
3590
3591 if (peer->password)
3592 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3593
3594 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3595
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003596 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003597 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3598 else
3599 BGP_EVENT_ADD (peer, BGP_Stop);
3600
3601 if (bgp_md5_set (peer) < 0)
3602 ret = BGP_ERR_TCPSIG_FAILED;
3603 }
3604
3605 return ret;
3606}
3607
3608int
3609peer_password_unset (struct peer *peer)
3610{
3611 struct listnode *nn, *nnode;
3612
3613 if (!peer->password
3614 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3615 return 0;
3616
3617 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3618 {
3619 if (peer_group_active (peer)
3620 && peer->group->conf->password
3621 && strcmp (peer->group->conf->password, peer->password) == 0)
3622 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3623
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003624 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003625 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3626 else
3627 BGP_EVENT_ADD (peer, BGP_Stop);
3628
3629 if (peer->password)
3630 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3631
3632 peer->password = NULL;
3633
3634 bgp_md5_set (peer);
3635
3636 return 0;
3637 }
3638
3639 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3640 peer->password = NULL;
3641
3642 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3643 {
3644 if (!peer->password)
3645 continue;
3646
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003647 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003648 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3649 else
3650 BGP_EVENT_ADD (peer, BGP_Stop);
3651
3652 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3653 peer->password = NULL;
3654
3655 bgp_md5_set (peer);
3656 }
3657
3658 return 0;
3659}
David Lamparter6b0655a2014-06-04 06:53:35 +02003660
paul718e3742002-12-13 20:15:29 +00003661/* Set distribute list to the peer. */
3662int
3663peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003664 const char *name)
paul718e3742002-12-13 20:15:29 +00003665{
3666 struct bgp_filter *filter;
3667 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003668 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003669
3670 if (! peer->afc[afi][safi])
3671 return BGP_ERR_PEER_INACTIVE;
3672
3673 if (direct != FILTER_IN && direct != FILTER_OUT)
3674 return BGP_ERR_INVALID_VALUE;
3675
3676 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3677 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3678
3679 filter = &peer->filter[afi][safi];
3680
3681 if (filter->plist[direct].name)
3682 return BGP_ERR_PEER_FILTER_CONFLICT;
3683
3684 if (filter->dlist[direct].name)
3685 free (filter->dlist[direct].name);
3686 filter->dlist[direct].name = strdup (name);
3687 filter->dlist[direct].alist = access_list_lookup (afi, name);
3688
3689 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3690 return 0;
3691
3692 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003693 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003694 {
3695 filter = &peer->filter[afi][safi];
3696
3697 if (! peer->af_group[afi][safi])
3698 continue;
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
3706 return 0;
3707}
3708
3709int
3710peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3711{
3712 struct bgp_filter *filter;
3713 struct bgp_filter *gfilter;
3714 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003715 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003716
3717 if (! peer->afc[afi][safi])
3718 return BGP_ERR_PEER_INACTIVE;
3719
3720 if (direct != FILTER_IN && direct != FILTER_OUT)
3721 return BGP_ERR_INVALID_VALUE;
3722
3723 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3724 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3725
3726 filter = &peer->filter[afi][safi];
3727
3728 /* apply peer-group filter */
3729 if (peer->af_group[afi][safi])
3730 {
3731 gfilter = &peer->group->conf->filter[afi][safi];
3732
3733 if (gfilter->dlist[direct].name)
3734 {
3735 if (filter->dlist[direct].name)
3736 free (filter->dlist[direct].name);
3737 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3738 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3739 return 0;
3740 }
3741 }
3742
3743 if (filter->dlist[direct].name)
3744 free (filter->dlist[direct].name);
3745 filter->dlist[direct].name = NULL;
3746 filter->dlist[direct].alist = NULL;
3747
3748 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3749 return 0;
3750
3751 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003752 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003753 {
3754 filter = &peer->filter[afi][safi];
3755
3756 if (! peer->af_group[afi][safi])
3757 continue;
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
3765 return 0;
3766}
3767
3768/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003769static void
paul718e3742002-12-13 20:15:29 +00003770peer_distribute_update (struct access_list *access)
3771{
3772 afi_t afi;
3773 safi_t safi;
3774 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003775 struct listnode *mnode, *mnnode;
3776 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003777 struct bgp *bgp;
3778 struct peer *peer;
3779 struct peer_group *group;
3780 struct bgp_filter *filter;
3781
paul1eb8ef22005-04-07 07:30:20 +00003782 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003783 {
paul1eb8ef22005-04-07 07:30:20 +00003784 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003785 {
3786 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3787 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3788 {
3789 filter = &peer->filter[afi][safi];
3790
3791 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3792 {
3793 if (filter->dlist[direct].name)
3794 filter->dlist[direct].alist =
3795 access_list_lookup (afi, filter->dlist[direct].name);
3796 else
3797 filter->dlist[direct].alist = NULL;
3798 }
3799 }
3800 }
paul1eb8ef22005-04-07 07:30:20 +00003801 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003802 {
3803 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3804 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3805 {
3806 filter = &group->conf->filter[afi][safi];
3807
3808 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3809 {
3810 if (filter->dlist[direct].name)
3811 filter->dlist[direct].alist =
3812 access_list_lookup (afi, filter->dlist[direct].name);
3813 else
3814 filter->dlist[direct].alist = NULL;
3815 }
3816 }
3817 }
3818 }
3819}
David Lamparter6b0655a2014-06-04 06:53:35 +02003820
paul718e3742002-12-13 20:15:29 +00003821/* Set prefix list to the peer. */
3822int
3823peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003824 const char *name)
paul718e3742002-12-13 20:15:29 +00003825{
3826 struct bgp_filter *filter;
3827 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003828 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003829
3830 if (! peer->afc[afi][safi])
3831 return BGP_ERR_PEER_INACTIVE;
3832
3833 if (direct != FILTER_IN && direct != FILTER_OUT)
3834 return BGP_ERR_INVALID_VALUE;
3835
3836 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3837 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3838
3839 filter = &peer->filter[afi][safi];
3840
3841 if (filter->dlist[direct].name)
3842 return BGP_ERR_PEER_FILTER_CONFLICT;
3843
3844 if (filter->plist[direct].name)
3845 free (filter->plist[direct].name);
3846 filter->plist[direct].name = strdup (name);
3847 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3848
3849 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3850 return 0;
3851
3852 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003853 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003854 {
3855 filter = &peer->filter[afi][safi];
3856
3857 if (! peer->af_group[afi][safi])
3858 continue;
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 return 0;
3866}
3867
3868int
3869peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3870{
3871 struct bgp_filter *filter;
3872 struct bgp_filter *gfilter;
3873 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003874 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003875
3876 if (! peer->afc[afi][safi])
3877 return BGP_ERR_PEER_INACTIVE;
3878
3879 if (direct != FILTER_IN && direct != FILTER_OUT)
3880 return BGP_ERR_INVALID_VALUE;
3881
3882 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3883 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3884
3885 filter = &peer->filter[afi][safi];
3886
3887 /* apply peer-group filter */
3888 if (peer->af_group[afi][safi])
3889 {
3890 gfilter = &peer->group->conf->filter[afi][safi];
3891
3892 if (gfilter->plist[direct].name)
3893 {
3894 if (filter->plist[direct].name)
3895 free (filter->plist[direct].name);
3896 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3897 filter->plist[direct].plist = gfilter->plist[direct].plist;
3898 return 0;
3899 }
3900 }
3901
3902 if (filter->plist[direct].name)
3903 free (filter->plist[direct].name);
3904 filter->plist[direct].name = NULL;
3905 filter->plist[direct].plist = NULL;
3906
3907 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3908 return 0;
3909
3910 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003911 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003912 {
3913 filter = &peer->filter[afi][safi];
3914
3915 if (! peer->af_group[afi][safi])
3916 continue;
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
3924 return 0;
3925}
3926
3927/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003928static void
paul718e3742002-12-13 20:15:29 +00003929peer_prefix_list_update (struct prefix_list *plist)
3930{
paul1eb8ef22005-04-07 07:30:20 +00003931 struct listnode *mnode, *mnnode;
3932 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003933 struct bgp *bgp;
3934 struct peer *peer;
3935 struct peer_group *group;
3936 struct bgp_filter *filter;
3937 afi_t afi;
3938 safi_t safi;
3939 int direct;
3940
paul1eb8ef22005-04-07 07:30:20 +00003941 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003942 {
paul1eb8ef22005-04-07 07:30:20 +00003943 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003944 {
3945 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3946 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3947 {
3948 filter = &peer->filter[afi][safi];
3949
3950 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3951 {
3952 if (filter->plist[direct].name)
3953 filter->plist[direct].plist =
3954 prefix_list_lookup (afi, filter->plist[direct].name);
3955 else
3956 filter->plist[direct].plist = NULL;
3957 }
3958 }
3959 }
paul1eb8ef22005-04-07 07:30:20 +00003960 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003961 {
3962 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3963 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3964 {
3965 filter = &group->conf->filter[afi][safi];
3966
3967 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3968 {
3969 if (filter->plist[direct].name)
3970 filter->plist[direct].plist =
3971 prefix_list_lookup (afi, filter->plist[direct].name);
3972 else
3973 filter->plist[direct].plist = NULL;
3974 }
3975 }
3976 }
3977 }
3978}
David Lamparter6b0655a2014-06-04 06:53:35 +02003979
paul718e3742002-12-13 20:15:29 +00003980int
3981peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003982 const char *name)
paul718e3742002-12-13 20:15:29 +00003983{
3984 struct bgp_filter *filter;
3985 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003986 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003987
3988 if (! peer->afc[afi][safi])
3989 return BGP_ERR_PEER_INACTIVE;
3990
3991 if (direct != FILTER_IN && direct != FILTER_OUT)
3992 return BGP_ERR_INVALID_VALUE;
3993
3994 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3995 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3996
3997 filter = &peer->filter[afi][safi];
3998
3999 if (filter->aslist[direct].name)
4000 free (filter->aslist[direct].name);
4001 filter->aslist[direct].name = strdup (name);
4002 filter->aslist[direct].aslist = as_list_lookup (name);
4003
4004 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4005 return 0;
4006
4007 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004008 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004009 {
4010 filter = &peer->filter[afi][safi];
4011
4012 if (! peer->af_group[afi][safi])
4013 continue;
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 return 0;
4021}
4022
4023int
4024peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4025{
4026 struct bgp_filter *filter;
4027 struct bgp_filter *gfilter;
4028 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004029 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004030
4031 if (! peer->afc[afi][safi])
4032 return BGP_ERR_PEER_INACTIVE;
4033
hassob5f29602005-05-25 21:00:28 +00004034 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004035 return BGP_ERR_INVALID_VALUE;
4036
hassob5f29602005-05-25 21:00:28 +00004037 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004038 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4039
4040 filter = &peer->filter[afi][safi];
4041
4042 /* apply peer-group filter */
4043 if (peer->af_group[afi][safi])
4044 {
4045 gfilter = &peer->group->conf->filter[afi][safi];
4046
4047 if (gfilter->aslist[direct].name)
4048 {
4049 if (filter->aslist[direct].name)
4050 free (filter->aslist[direct].name);
4051 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4052 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4053 return 0;
4054 }
4055 }
4056
4057 if (filter->aslist[direct].name)
4058 free (filter->aslist[direct].name);
4059 filter->aslist[direct].name = NULL;
4060 filter->aslist[direct].aslist = NULL;
4061
4062 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4063 return 0;
4064
4065 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004066 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004067 {
4068 filter = &peer->filter[afi][safi];
4069
4070 if (! peer->af_group[afi][safi])
4071 continue;
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
4079 return 0;
4080}
4081
paul94f2b392005-06-28 12:44:16 +00004082static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004083peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004084{
4085 afi_t afi;
4086 safi_t safi;
4087 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004088 struct listnode *mnode, *mnnode;
4089 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004090 struct bgp *bgp;
4091 struct peer *peer;
4092 struct peer_group *group;
4093 struct bgp_filter *filter;
4094
paul1eb8ef22005-04-07 07:30:20 +00004095 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004096 {
paul1eb8ef22005-04-07 07:30:20 +00004097 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004098 {
4099 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4100 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4101 {
4102 filter = &peer->filter[afi][safi];
4103
4104 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4105 {
4106 if (filter->aslist[direct].name)
4107 filter->aslist[direct].aslist =
4108 as_list_lookup (filter->aslist[direct].name);
4109 else
4110 filter->aslist[direct].aslist = NULL;
4111 }
4112 }
4113 }
paul1eb8ef22005-04-07 07:30:20 +00004114 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004115 {
4116 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4117 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4118 {
4119 filter = &group->conf->filter[afi][safi];
4120
4121 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4122 {
4123 if (filter->aslist[direct].name)
4124 filter->aslist[direct].aslist =
4125 as_list_lookup (filter->aslist[direct].name);
4126 else
4127 filter->aslist[direct].aslist = NULL;
4128 }
4129 }
4130 }
4131 }
4132}
David Lamparter6b0655a2014-06-04 06:53:35 +02004133
paul718e3742002-12-13 20:15:29 +00004134/* Set route-map to the peer. */
4135int
4136peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004137 const char *name)
paul718e3742002-12-13 20:15:29 +00004138{
4139 struct bgp_filter *filter;
4140 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004141 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004142
4143 if (! peer->afc[afi][safi])
4144 return BGP_ERR_PEER_INACTIVE;
4145
paulfee0f4c2004-09-13 05:12:46 +00004146 if (direct != RMAP_IN && direct != RMAP_OUT &&
4147 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004148 return BGP_ERR_INVALID_VALUE;
4149
paulfee0f4c2004-09-13 05:12:46 +00004150 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4151 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004152 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4153
4154 filter = &peer->filter[afi][safi];
4155
4156 if (filter->map[direct].name)
4157 free (filter->map[direct].name);
4158
4159 filter->map[direct].name = strdup (name);
4160 filter->map[direct].map = route_map_lookup_by_name (name);
4161
4162 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4163 return 0;
4164
4165 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004166 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004167 {
4168 filter = &peer->filter[afi][safi];
4169
4170 if (! peer->af_group[afi][safi])
4171 continue;
4172
4173 if (filter->map[direct].name)
4174 free (filter->map[direct].name);
4175 filter->map[direct].name = strdup (name);
4176 filter->map[direct].map = route_map_lookup_by_name (name);
4177 }
4178 return 0;
4179}
4180
4181/* Unset route-map from the peer. */
4182int
4183peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4184{
4185 struct bgp_filter *filter;
4186 struct bgp_filter *gfilter;
4187 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004188 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004189
4190 if (! peer->afc[afi][safi])
4191 return BGP_ERR_PEER_INACTIVE;
4192
hassob5f29602005-05-25 21:00:28 +00004193 if (direct != RMAP_IN && direct != RMAP_OUT &&
4194 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004195 return BGP_ERR_INVALID_VALUE;
4196
hassob5f29602005-05-25 21:00:28 +00004197 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4198 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004199 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4200
4201 filter = &peer->filter[afi][safi];
4202
4203 /* apply peer-group filter */
4204 if (peer->af_group[afi][safi])
4205 {
4206 gfilter = &peer->group->conf->filter[afi][safi];
4207
4208 if (gfilter->map[direct].name)
4209 {
4210 if (filter->map[direct].name)
4211 free (filter->map[direct].name);
4212 filter->map[direct].name = strdup (gfilter->map[direct].name);
4213 filter->map[direct].map = gfilter->map[direct].map;
4214 return 0;
4215 }
4216 }
4217
4218 if (filter->map[direct].name)
4219 free (filter->map[direct].name);
4220 filter->map[direct].name = NULL;
4221 filter->map[direct].map = NULL;
4222
4223 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4224 return 0;
4225
4226 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004227 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004228 {
4229 filter = &peer->filter[afi][safi];
4230
4231 if (! peer->af_group[afi][safi])
4232 continue;
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 return 0;
4240}
David Lamparter6b0655a2014-06-04 06:53:35 +02004241
paul718e3742002-12-13 20:15:29 +00004242/* Set unsuppress-map to the peer. */
4243int
paulfd79ac92004-10-13 05:06:08 +00004244peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4245 const char *name)
paul718e3742002-12-13 20:15:29 +00004246{
4247 struct bgp_filter *filter;
4248 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004249 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004250
4251 if (! peer->afc[afi][safi])
4252 return BGP_ERR_PEER_INACTIVE;
4253
4254 if (peer_is_group_member (peer, afi, safi))
4255 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4256
4257 filter = &peer->filter[afi][safi];
4258
4259 if (filter->usmap.name)
4260 free (filter->usmap.name);
4261
4262 filter->usmap.name = strdup (name);
4263 filter->usmap.map = route_map_lookup_by_name (name);
4264
4265 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4266 return 0;
4267
4268 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004269 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004270 {
4271 filter = &peer->filter[afi][safi];
4272
4273 if (! peer->af_group[afi][safi])
4274 continue;
4275
4276 if (filter->usmap.name)
4277 free (filter->usmap.name);
4278 filter->usmap.name = strdup (name);
4279 filter->usmap.map = route_map_lookup_by_name (name);
4280 }
4281 return 0;
4282}
4283
4284/* Unset route-map from the peer. */
4285int
4286peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4287{
4288 struct bgp_filter *filter;
4289 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004290 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004291
4292 if (! peer->afc[afi][safi])
4293 return BGP_ERR_PEER_INACTIVE;
4294
4295 if (peer_is_group_member (peer, afi, safi))
4296 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4297
4298 filter = &peer->filter[afi][safi];
4299
4300 if (filter->usmap.name)
4301 free (filter->usmap.name);
4302 filter->usmap.name = NULL;
4303 filter->usmap.map = NULL;
4304
4305 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4306 return 0;
4307
4308 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004309 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004310 {
4311 filter = &peer->filter[afi][safi];
4312
4313 if (! peer->af_group[afi][safi])
4314 continue;
4315
4316 if (filter->usmap.name)
4317 free (filter->usmap.name);
4318 filter->usmap.name = NULL;
4319 filter->usmap.map = NULL;
4320 }
4321 return 0;
4322}
David Lamparter6b0655a2014-06-04 06:53:35 +02004323
paul718e3742002-12-13 20:15:29 +00004324int
4325peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004326 u_int32_t max, u_char threshold,
4327 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004328{
4329 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004330 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004331
4332 if (! peer->afc[afi][safi])
4333 return BGP_ERR_PEER_INACTIVE;
4334
4335 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4336 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004337 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004338 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004339 if (warning)
4340 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4341 else
4342 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4343
4344 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4345 return 0;
4346
4347 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004348 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004349 {
4350 if (! peer->af_group[afi][safi])
4351 continue;
4352
4353 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4354 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004355 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004356 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004357 if (warning)
4358 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4359 else
4360 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4361 }
4362 return 0;
4363}
4364
4365int
4366peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4367{
4368 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004369 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004370
4371 if (! peer->afc[afi][safi])
4372 return BGP_ERR_PEER_INACTIVE;
4373
4374 /* apply peer-group config */
4375 if (peer->af_group[afi][safi])
4376 {
4377 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4378 PEER_FLAG_MAX_PREFIX))
4379 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4380 else
4381 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4382
4383 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4384 PEER_FLAG_MAX_PREFIX_WARNING))
4385 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4386 else
4387 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4388
4389 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004390 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004391 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004392 return 0;
4393 }
4394
4395 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4396 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4397 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004398 peer->pmax_threshold[afi][safi] = 0;
4399 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004400
4401 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4402 return 0;
4403
4404 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004405 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004406 {
4407 if (! peer->af_group[afi][safi])
4408 continue;
4409
4410 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4411 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4412 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004413 peer->pmax_threshold[afi][safi] = 0;
4414 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004415 }
4416 return 0;
4417}
David Lamparter5f9adb52014-05-19 23:15:02 +02004418
4419static int is_ebgp_multihop_configured (struct peer *peer)
4420{
4421 struct peer_group *group;
4422 struct listnode *node, *nnode;
4423 struct peer *peer1;
4424
4425 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4426 {
4427 group = peer->group;
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004428 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4429 (group->conf->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004430 return 1;
4431
4432 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4433 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004434 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
4435 (peer1->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004436 return 1;
4437 }
4438 }
4439 else
4440 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004441 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4442 (peer->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004443 return 1;
4444 }
4445 return 0;
4446}
4447
Nick Hilliardfa411a22011-03-23 15:33:17 +00004448/* Set # of hops between us and BGP peer. */
4449int
4450peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4451{
4452 struct peer_group *group;
4453 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004454 int ret;
4455
4456 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4457
Nick Hilliardfa411a22011-03-23 15:33:17 +00004458 /* We cannot configure ttl-security hops when ebgp-multihop is already
4459 set. For non peer-groups, the check is simple. For peer-groups, it's
4460 slightly messy, because we need to check both the peer-group structure
4461 and all peer-group members for any trace of ebgp-multihop configuration
4462 before actually applying the ttl-security rules. Cisco really made a
4463 mess of this configuration parameter, and OpenBGPD got it right.
4464 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004465
David Lamparter5f9adb52014-05-19 23:15:02 +02004466 if (peer->gtsm_hops == 0)
4467 {
4468 if (is_ebgp_multihop_configured (peer))
4469 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004470
David Lamparter5f9adb52014-05-19 23:15:02 +02004471 /* specify MAXTTL on outgoing packets */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004472 /* Routine handles iBGP peers correctly */
David Lamparter5f9adb52014-05-19 23:15:02 +02004473 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4474 if (ret != 0)
4475 return ret;
4476 }
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004477
Nick Hilliardfa411a22011-03-23 15:33:17 +00004478 peer->gtsm_hops = gtsm_hops;
4479
Nick Hilliardfa411a22011-03-23 15:33:17 +00004480 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4481 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004482 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004483 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4484 }
4485 else
4486 {
4487 group = peer->group;
4488 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4489 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004490 peer->gtsm_hops = group->conf->gtsm_hops;
4491
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004492 /* Change setting of existing peer
4493 * established then change value (may break connectivity)
4494 * not established yet (teardown session and restart)
4495 * no session then do nothing (will get handled by next connection)
4496 */
4497 if (peer->status == Established)
4498 {
4499 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4500 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4501 MAXTTL + 1 - peer->gtsm_hops);
4502 }
4503 else if (peer->status < Established)
4504 {
4505 if (BGP_DEBUG (events, EVENTS))
4506 zlog_debug ("%s Min-ttl changed", peer->host);
4507 BGP_EVENT_ADD (peer, BGP_Stop);
4508 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004509 }
4510 }
4511
4512 return 0;
4513}
4514
4515int
4516peer_ttl_security_hops_unset (struct peer *peer)
4517{
4518 struct peer_group *group;
4519 struct listnode *node, *nnode;
4520 struct peer *opeer;
4521
4522 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4523
Nick Hilliardfa411a22011-03-23 15:33:17 +00004524 /* if a peer-group member, then reset to peer-group default rather than 0 */
4525 if (peer_group_active (peer))
4526 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4527 else
4528 peer->gtsm_hops = 0;
4529
4530 opeer = peer;
4531 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4532 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004533 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004534 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4535 }
4536 else
4537 {
4538 group = peer->group;
4539 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4540 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004541 peer->gtsm_hops = 0;
4542
4543 if (peer->fd >= 0)
4544 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4545 }
4546 }
4547
4548 return peer_ebgp_multihop_unset (opeer);
4549}
David Lamparter6b0655a2014-06-04 06:53:35 +02004550
paul718e3742002-12-13 20:15:29 +00004551int
4552peer_clear (struct peer *peer)
4553{
4554 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4555 {
hasso0a486e52005-02-01 20:57:17 +00004556 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4557 {
4558 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4559 if (peer->t_pmax_restart)
4560 {
4561 BGP_TIMER_OFF (peer->t_pmax_restart);
4562 if (BGP_DEBUG (events, EVENTS))
4563 zlog_debug ("%s Maximum-prefix restart timer canceled",
4564 peer->host);
4565 }
4566 BGP_EVENT_ADD (peer, BGP_Start);
4567 return 0;
4568 }
4569
paul718e3742002-12-13 20:15:29 +00004570 peer->v_start = BGP_INIT_START_TIMER;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00004571 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00004572 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4573 BGP_NOTIFY_CEASE_ADMIN_RESET);
4574 else
4575 BGP_EVENT_ADD (peer, BGP_Stop);
4576 }
4577 return 0;
4578}
4579
4580int
4581peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4582 enum bgp_clear_type stype)
4583{
4584 if (peer->status != Established)
4585 return 0;
4586
4587 if (! peer->afc[afi][safi])
4588 return BGP_ERR_AF_UNCONFIGURED;
4589
paulfee0f4c2004-09-13 05:12:46 +00004590 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4591 {
4592 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4593 return 0;
4594 bgp_check_local_routes_rsclient (peer, afi, safi);
4595 bgp_soft_reconfig_rsclient (peer, afi, safi);
4596 }
4597
paul718e3742002-12-13 20:15:29 +00004598 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4599 bgp_announce_route (peer, afi, safi);
4600
4601 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4602 {
4603 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4604 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4605 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4606 {
4607 struct bgp_filter *filter = &peer->filter[afi][safi];
4608 u_char prefix_type;
4609
4610 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4611 prefix_type = ORF_TYPE_PREFIX;
4612 else
4613 prefix_type = ORF_TYPE_PREFIX_OLD;
4614
4615 if (filter->plist[FILTER_IN].plist)
4616 {
4617 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4618 bgp_route_refresh_send (peer, afi, safi,
4619 prefix_type, REFRESH_DEFER, 1);
4620 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4621 REFRESH_IMMEDIATE, 0);
4622 }
4623 else
4624 {
4625 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4626 bgp_route_refresh_send (peer, afi, safi,
4627 prefix_type, REFRESH_IMMEDIATE, 1);
4628 else
4629 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4630 }
4631 return 0;
4632 }
4633 }
4634
4635 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4636 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4637 {
4638 /* If neighbor has soft reconfiguration inbound flag.
4639 Use Adj-RIB-In database. */
4640 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4641 bgp_soft_reconfig_in (peer, afi, safi);
4642 else
4643 {
4644 /* If neighbor has route refresh capability, send route refresh
4645 message to the peer. */
4646 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4647 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4648 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4649 else
4650 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4651 }
4652 }
4653 return 0;
4654}
David Lamparter6b0655a2014-06-04 06:53:35 +02004655
paulfd79ac92004-10-13 05:06:08 +00004656/* Display peer uptime.*/
4657/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004658char *
4659peer_uptime (time_t uptime2, char *buf, size_t len)
4660{
4661 time_t uptime1;
4662 struct tm *tm;
4663
4664 /* Check buffer length. */
4665 if (len < BGP_UPTIME_LEN)
4666 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004667 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004668 /* XXX: should return status instead of buf... */
4669 snprintf (buf, len, "<error> ");
4670 return buf;
paul718e3742002-12-13 20:15:29 +00004671 }
4672
4673 /* If there is no connection has been done before print `never'. */
4674 if (uptime2 == 0)
4675 {
4676 snprintf (buf, len, "never ");
4677 return buf;
4678 }
4679
4680 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004681 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004682 uptime1 -= uptime2;
4683 tm = gmtime (&uptime1);
4684
4685 /* Making formatted timer strings. */
4686#define ONE_DAY_SECOND 60*60*24
4687#define ONE_WEEK_SECOND 60*60*24*7
4688
4689 if (uptime1 < ONE_DAY_SECOND)
4690 snprintf (buf, len, "%02d:%02d:%02d",
4691 tm->tm_hour, tm->tm_min, tm->tm_sec);
4692 else if (uptime1 < ONE_WEEK_SECOND)
4693 snprintf (buf, len, "%dd%02dh%02dm",
4694 tm->tm_yday, tm->tm_hour, tm->tm_min);
4695 else
4696 snprintf (buf, len, "%02dw%dd%02dh",
4697 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4698 return buf;
4699}
David Lamparter6b0655a2014-06-04 06:53:35 +02004700
paul94f2b392005-06-28 12:44:16 +00004701static void
paul718e3742002-12-13 20:15:29 +00004702bgp_config_write_filter (struct vty *vty, struct peer *peer,
4703 afi_t afi, safi_t safi)
4704{
4705 struct bgp_filter *filter;
4706 struct bgp_filter *gfilter = NULL;
4707 char *addr;
4708 int in = FILTER_IN;
4709 int out = FILTER_OUT;
4710
4711 addr = peer->host;
4712 filter = &peer->filter[afi][safi];
4713 if (peer->af_group[afi][safi])
4714 gfilter = &peer->group->conf->filter[afi][safi];
4715
4716 /* distribute-list. */
4717 if (filter->dlist[in].name)
4718 if (! gfilter || ! gfilter->dlist[in].name
4719 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4720 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4721 filter->dlist[in].name, VTY_NEWLINE);
4722 if (filter->dlist[out].name && ! gfilter)
4723 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4724 filter->dlist[out].name, VTY_NEWLINE);
4725
4726 /* prefix-list. */
4727 if (filter->plist[in].name)
4728 if (! gfilter || ! gfilter->plist[in].name
4729 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4730 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4731 filter->plist[in].name, VTY_NEWLINE);
4732 if (filter->plist[out].name && ! gfilter)
4733 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4734 filter->plist[out].name, VTY_NEWLINE);
4735
4736 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004737 if (filter->map[RMAP_IN].name)
4738 if (! gfilter || ! gfilter->map[RMAP_IN].name
4739 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004740 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004741 filter->map[RMAP_IN].name, VTY_NEWLINE);
4742 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004743 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004744 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4745 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4746 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4747 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4748 if (filter->map[RMAP_EXPORT].name)
4749 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4750 || strcmp (filter->map[RMAP_EXPORT].name,
4751 gfilter->map[RMAP_EXPORT].name) != 0)
4752 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4753 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004754
4755 /* unsuppress-map */
4756 if (filter->usmap.name && ! gfilter)
4757 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4758 filter->usmap.name, VTY_NEWLINE);
4759
4760 /* filter-list. */
4761 if (filter->aslist[in].name)
4762 if (! gfilter || ! gfilter->aslist[in].name
4763 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4764 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4765 filter->aslist[in].name, VTY_NEWLINE);
4766 if (filter->aslist[out].name && ! gfilter)
4767 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4768 filter->aslist[out].name, VTY_NEWLINE);
4769}
4770
4771/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004772static void
paul718e3742002-12-13 20:15:29 +00004773bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4774 struct peer *peer, afi_t afi, safi_t safi)
4775{
paul718e3742002-12-13 20:15:29 +00004776 struct peer *g_peer = NULL;
4777 char buf[SU_ADDRSTRLEN];
4778 char *addr;
4779
paul718e3742002-12-13 20:15:29 +00004780 addr = peer->host;
4781 if (peer_group_active (peer))
4782 g_peer = peer->group->conf;
4783
4784 /************************************
4785 ****** Global to the neighbor ******
4786 ************************************/
4787 if (afi == AFI_IP && safi == SAFI_UNICAST)
4788 {
4789 /* remote-as. */
4790 if (! peer_group_active (peer))
4791 {
4792 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4793 vty_out (vty, " neighbor %s peer-group%s", addr,
4794 VTY_NEWLINE);
4795 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004796 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004797 VTY_NEWLINE);
4798 }
4799 else
4800 {
4801 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004802 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004803 VTY_NEWLINE);
4804 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4805 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4806 peer->group->name, VTY_NEWLINE);
4807 }
4808
4809 /* local-as. */
4810 if (peer->change_local_as)
4811 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00004812 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004813 peer->change_local_as,
4814 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00004815 " no-prepend" : "",
4816 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
4817 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004818
4819 /* Description. */
4820 if (peer->desc)
4821 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4822 VTY_NEWLINE);
4823
4824 /* Shutdown. */
4825 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4826 if (! peer_group_active (peer) ||
4827 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4828 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4829
Paul Jakma0df7c912008-07-21 21:02:49 +00004830 /* Password. */
4831 if (peer->password)
4832 if (!peer_group_active (peer)
4833 || ! g_peer->password
4834 || strcmp (peer->password, g_peer->password) != 0)
4835 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4836 VTY_NEWLINE);
4837
paul718e3742002-12-13 20:15:29 +00004838 /* BGP port. */
4839 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004840 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004841 VTY_NEWLINE);
4842
4843 /* Local interface name. */
4844 if (peer->ifname)
4845 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4846 VTY_NEWLINE);
4847
4848 /* Passive. */
4849 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4850 if (! peer_group_active (peer) ||
4851 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4852 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4853
4854 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004855 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00004856 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00004857 if (! peer_group_active (peer) ||
4858 g_peer->ttl != peer->ttl)
4859 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4860 VTY_NEWLINE);
4861
Nick Hilliardfa411a22011-03-23 15:33:17 +00004862 /* ttl-security hops */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004863 if (peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004864 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004865 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00004866 peer->gtsm_hops, VTY_NEWLINE);
4867
hasso6ffd2072005-02-02 14:50:11 +00004868 /* disable-connected-check. */
4869 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004870 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004871 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4872 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004873
4874 /* Update-source. */
4875 if (peer->update_if)
4876 if (! peer_group_active (peer) || ! g_peer->update_if
4877 || strcmp (g_peer->update_if, peer->update_if) != 0)
4878 vty_out (vty, " neighbor %s update-source %s%s", addr,
4879 peer->update_if, VTY_NEWLINE);
4880 if (peer->update_source)
4881 if (! peer_group_active (peer) || ! g_peer->update_source
4882 || sockunion_cmp (g_peer->update_source,
4883 peer->update_source) != 0)
4884 vty_out (vty, " neighbor %s update-source %s%s", addr,
4885 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4886 VTY_NEWLINE);
4887
paul718e3742002-12-13 20:15:29 +00004888 /* advertisement-interval */
4889 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4890 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4891 addr, peer->v_routeadv, VTY_NEWLINE);
4892
4893 /* timers. */
4894 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4895 && ! peer_group_active (peer))
4896 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4897 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4898
4899 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4900 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4901 peer->connect, VTY_NEWLINE);
4902
4903 /* Default weight. */
4904 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4905 if (! peer_group_active (peer) ||
4906 g_peer->weight != peer->weight)
4907 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4908 VTY_NEWLINE);
4909
paul718e3742002-12-13 20:15:29 +00004910 /* Dynamic capability. */
4911 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4912 if (! peer_group_active (peer) ||
4913 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4914 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4915 VTY_NEWLINE);
4916
4917 /* dont capability negotiation. */
4918 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4919 if (! peer_group_active (peer) ||
4920 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4921 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4922 VTY_NEWLINE);
4923
4924 /* override capability negotiation. */
4925 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4926 if (! peer_group_active (peer) ||
4927 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4928 vty_out (vty, " neighbor %s override-capability%s", addr,
4929 VTY_NEWLINE);
4930
4931 /* strict capability negotiation. */
4932 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4933 if (! peer_group_active (peer) ||
4934 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4935 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4936 VTY_NEWLINE);
4937
Christian Franke15c71342012-11-19 11:17:31 +00004938 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
paul718e3742002-12-13 20:15:29 +00004939 {
4940 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4941 {
4942 if (peer->afc[AFI_IP][SAFI_UNICAST])
4943 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4944 }
4945 else
4946 {
4947 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4948 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4949 }
4950 }
4951 }
4952
4953
4954 /************************************
4955 ****** Per AF to the neighbor ******
4956 ************************************/
4957
4958 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4959 {
4960 if (peer->af_group[afi][safi])
4961 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4962 peer->group->name, VTY_NEWLINE);
4963 else
4964 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4965 }
4966
4967 /* ORF capability. */
4968 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4969 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4970 if (! peer->af_group[afi][safi])
4971 {
4972 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4973
4974 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4975 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4976 vty_out (vty, " both");
4977 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4978 vty_out (vty, " send");
4979 else
4980 vty_out (vty, " receive");
4981 vty_out (vty, "%s", VTY_NEWLINE);
4982 }
4983
4984 /* Route reflector client. */
4985 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4986 && ! peer->af_group[afi][safi])
4987 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4988 VTY_NEWLINE);
4989
4990 /* Nexthop self. */
4991 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4992 && ! peer->af_group[afi][safi])
4993 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4994
4995 /* Remove private AS. */
4996 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4997 && ! peer->af_group[afi][safi])
4998 vty_out (vty, " neighbor %s remove-private-AS%s",
4999 addr, VTY_NEWLINE);
5000
5001 /* send-community print. */
5002 if (! peer->af_group[afi][safi])
5003 {
5004 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5005 {
5006 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5007 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5008 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
5009 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5010 vty_out (vty, " neighbor %s send-community extended%s",
5011 addr, VTY_NEWLINE);
5012 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5013 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
5014 }
5015 else
5016 {
5017 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5018 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5019 vty_out (vty, " no neighbor %s send-community both%s",
5020 addr, VTY_NEWLINE);
5021 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5022 vty_out (vty, " no neighbor %s send-community extended%s",
5023 addr, VTY_NEWLINE);
5024 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5025 vty_out (vty, " no neighbor %s send-community%s",
5026 addr, VTY_NEWLINE);
5027 }
5028 }
5029
5030 /* Default information */
5031 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5032 && ! peer->af_group[afi][safi])
5033 {
5034 vty_out (vty, " neighbor %s default-originate", addr);
5035 if (peer->default_rmap[afi][safi].name)
5036 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5037 vty_out (vty, "%s", VTY_NEWLINE);
5038 }
5039
5040 /* Soft reconfiguration inbound. */
5041 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5042 if (! peer->af_group[afi][safi] ||
5043 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5044 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5045 VTY_NEWLINE);
5046
5047 /* maximum-prefix. */
5048 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5049 if (! peer->af_group[afi][safi]
5050 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005051 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005052 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5053 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005054 {
hasso0a486e52005-02-01 20:57:17 +00005055 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5056 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5057 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5058 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5059 vty_out (vty, " warning-only");
5060 if (peer->pmax_restart[afi][safi])
5061 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5062 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005063 }
paul718e3742002-12-13 20:15:29 +00005064
5065 /* Route server client. */
5066 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5067 && ! peer->af_group[afi][safi])
5068 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5069
Dylan Hall3cf12882011-10-27 15:28:17 +04005070 /* Nexthop-local unchanged. */
5071 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5072 && ! peer->af_group[afi][safi])
5073 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5074
paul718e3742002-12-13 20:15:29 +00005075 /* Allow AS in. */
5076 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5077 if (! peer_group_active (peer)
5078 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5079 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5080 {
5081 if (peer->allowas_in[afi][safi] == 3)
5082 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5083 else
5084 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5085 peer->allowas_in[afi][safi], VTY_NEWLINE);
5086 }
5087
5088 /* Filter. */
5089 bgp_config_write_filter (vty, peer, afi, safi);
5090
5091 /* atribute-unchanged. */
5092 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5093 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5094 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5095 && ! peer->af_group[afi][safi])
5096 {
5097 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5098 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5099 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5100 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5101 else
5102 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5103 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5104 " as-path" : "",
5105 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5106 " next-hop" : "",
5107 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5108 " med" : "", VTY_NEWLINE);
5109 }
5110}
5111
5112/* Display "address-family" configuration header. */
5113void
5114bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5115 int *write)
5116{
5117 if (*write)
5118 return;
5119
5120 if (afi == AFI_IP && safi == SAFI_UNICAST)
5121 return;
5122
5123 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5124
5125 if (afi == AFI_IP)
5126 {
5127 if (safi == SAFI_MULTICAST)
5128 vty_out (vty, "ipv4 multicast");
5129 else if (safi == SAFI_MPLS_VPN)
5130 vty_out (vty, "vpnv4 unicast");
5131 }
5132 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005133 {
5134 vty_out (vty, "ipv6");
5135
5136 if (safi == SAFI_MULTICAST)
5137 vty_out (vty, " multicast");
5138 }
paul718e3742002-12-13 20:15:29 +00005139
5140 vty_out (vty, "%s", VTY_NEWLINE);
5141
5142 *write = 1;
5143}
5144
5145/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005146static int
paul718e3742002-12-13 20:15:29 +00005147bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5148 safi_t safi)
5149{
5150 int write = 0;
5151 struct peer *peer;
5152 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005153 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005154
5155 bgp_config_write_network (vty, bgp, afi, safi, &write);
5156
5157 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5158
paul1eb8ef22005-04-07 07:30:20 +00005159 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005160 {
5161 if (group->conf->afc[afi][safi])
5162 {
5163 bgp_config_write_family_header (vty, afi, safi, &write);
5164 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5165 }
5166 }
paul1eb8ef22005-04-07 07:30:20 +00005167 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005168 {
5169 if (peer->afc[afi][safi])
5170 {
5171 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5172 {
5173 bgp_config_write_family_header (vty, afi, safi, &write);
5174 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5175 }
5176 }
5177 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005178
5179 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5180
paul718e3742002-12-13 20:15:29 +00005181 if (write)
5182 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5183
5184 return write;
5185}
5186
5187int
5188bgp_config_write (struct vty *vty)
5189{
5190 int write = 0;
5191 struct bgp *bgp;
5192 struct peer_group *group;
5193 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005194 struct listnode *node, *nnode;
5195 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005196
5197 /* BGP Multiple instance. */
5198 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5199 {
5200 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5201 write++;
5202 }
5203
5204 /* BGP Config type. */
5205 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5206 {
5207 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5208 write++;
5209 }
5210
5211 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005212 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005213 {
5214 if (write)
5215 vty_out (vty, "!%s", VTY_NEWLINE);
5216
5217 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005218 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005219
5220 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5221 {
5222 if (bgp->name)
5223 vty_out (vty, " view %s", bgp->name);
5224 }
5225 vty_out (vty, "%s", VTY_NEWLINE);
5226
5227 /* No Synchronization */
5228 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5229 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5230
5231 /* BGP fast-external-failover. */
5232 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5233 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5234
5235 /* BGP router ID. */
5236 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5237 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5238 VTY_NEWLINE);
5239
paul848973c2003-08-13 00:32:49 +00005240 /* BGP log-neighbor-changes. */
5241 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5242 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
5243
paul718e3742002-12-13 20:15:29 +00005244 /* BGP configuration. */
5245 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5246 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5247
5248 /* BGP default ipv4-unicast. */
5249 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5250 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5251
5252 /* BGP default local-preference. */
5253 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5254 vty_out (vty, " bgp default local-preference %d%s",
5255 bgp->default_local_pref, VTY_NEWLINE);
5256
5257 /* BGP client-to-client reflection. */
5258 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5259 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5260
5261 /* BGP cluster ID. */
5262 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5263 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5264 VTY_NEWLINE);
5265
hassoe0701b72004-05-20 09:19:34 +00005266 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005267 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005268 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5269 VTY_NEWLINE);
5270
5271 /* Confederation peer */
5272 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005273 {
hassoe0701b72004-05-20 09:19:34 +00005274 int i;
paul718e3742002-12-13 20:15:29 +00005275
hassoe0701b72004-05-20 09:19:34 +00005276 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005277
hassoe0701b72004-05-20 09:19:34 +00005278 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005279 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005280
hassoe0701b72004-05-20 09:19:34 +00005281 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005282 }
5283
5284 /* BGP enforce-first-as. */
5285 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5286 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5287
5288 /* BGP deterministic-med. */
5289 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5290 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005291
5292 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005293 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5294 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5295 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005296 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5297 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5298
paul718e3742002-12-13 20:15:29 +00005299 /* BGP bestpath method. */
5300 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5301 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005302 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5303 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
Pradosh Mohapatra2fdd4552013-09-07 07:02:36 +00005304 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
5305 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
5306 }
paul718e3742002-12-13 20:15:29 +00005307 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5308 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5309 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5310 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5311 {
5312 vty_out (vty, " bgp bestpath med");
5313 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5314 vty_out (vty, " confed");
5315 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5316 vty_out (vty, " missing-as-worst");
5317 vty_out (vty, "%s", VTY_NEWLINE);
5318 }
5319
5320 /* BGP network import check. */
5321 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5322 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5323
5324 /* BGP scan interval. */
5325 bgp_config_write_scan_time (vty);
5326
5327 /* BGP flag dampening. */
5328 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5329 BGP_CONFIG_DAMPENING))
5330 bgp_config_write_damp (vty);
5331
5332 /* BGP static route configuration. */
5333 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5334
5335 /* BGP redistribute configuration. */
5336 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5337
5338 /* BGP timers configuration. */
5339 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5340 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5341 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5342 bgp->default_holdtime, VTY_NEWLINE);
5343
5344 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005345 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005346 {
5347 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5348 }
5349
5350 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005351 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005352 {
5353 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5354 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5355 }
5356
Josh Bailey165b5ff2011-07-20 20:43:22 -07005357 /* maximum-paths */
5358 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5359
paul718e3742002-12-13 20:15:29 +00005360 /* Distance configuration. */
5361 bgp_config_write_distance (vty, bgp);
5362
5363 /* No auto-summary */
5364 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5365 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5366
5367 /* IPv4 multicast configuration. */
5368 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5369
5370 /* IPv4 VPN configuration. */
5371 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5372
5373 /* IPv6 unicast configuration. */
5374 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5375
Paul Jakma37a217a2007-04-10 19:20:29 +00005376 /* IPv6 multicast configuration. */
5377 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5378
paul718e3742002-12-13 20:15:29 +00005379 write++;
5380 }
5381 return write;
5382}
5383
5384void
paul94f2b392005-06-28 12:44:16 +00005385bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005386{
5387 memset (&bgp_master, 0, sizeof (struct bgp_master));
5388
5389 bm = &bgp_master;
5390 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005391 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005392 bm->port = BGP_PORT_DEFAULT;
5393 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005394 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005395}
paul200df112005-06-01 11:17:05 +00005396
David Lamparter6b0655a2014-06-04 06:53:35 +02005397
paul718e3742002-12-13 20:15:29 +00005398void
paul94f2b392005-06-28 12:44:16 +00005399bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005400{
paul718e3742002-12-13 20:15:29 +00005401 /* BGP VTY commands installation. */
5402 bgp_vty_init ();
5403
paul718e3742002-12-13 20:15:29 +00005404 /* Init zebra. */
5405 bgp_zebra_init ();
5406
5407 /* BGP inits. */
5408 bgp_attr_init ();
5409 bgp_debug_init ();
5410 bgp_dump_init ();
5411 bgp_route_init ();
5412 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005413 bgp_address_init ();
paul718e3742002-12-13 20:15:29 +00005414 bgp_scan_init ();
5415 bgp_mplsvpn_init ();
5416
5417 /* Access list initialize. */
5418 access_list_init ();
5419 access_list_add_hook (peer_distribute_update);
5420 access_list_delete_hook (peer_distribute_update);
5421
5422 /* Filter list initialize. */
5423 bgp_filter_init ();
5424 as_list_add_hook (peer_aslist_update);
5425 as_list_delete_hook (peer_aslist_update);
5426
5427 /* Prefix list initialize.*/
5428 prefix_list_init ();
5429 prefix_list_add_hook (peer_prefix_list_update);
5430 prefix_list_delete_hook (peer_prefix_list_update);
5431
5432 /* Community list initialize. */
5433 bgp_clist = community_list_init ();
5434
5435#ifdef HAVE_SNMP
5436 bgp_snmp_init ();
5437#endif /* HAVE_SNMP */
5438}
paul545acaf2004-04-20 15:13:15 +00005439
5440void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005441bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005442{
paul545acaf2004-04-20 15:13:15 +00005443 struct bgp *bgp;
5444 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005445 struct listnode *node, *nnode;
5446 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005447
paul1eb8ef22005-04-07 07:30:20 +00005448 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5449 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005450 if (peer->status == Established)
5451 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5452 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005453
paul545acaf2004-04-20 15:13:15 +00005454 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005455
paule210cf92005-06-15 19:15:35 +00005456 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005457 {
5458 work_queue_free (bm->process_main_queue);
5459 bm->process_main_queue = NULL;
5460 }
paule210cf92005-06-15 19:15:35 +00005461 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005462 {
5463 work_queue_free (bm->process_rsclient_queue);
5464 bm->process_rsclient_queue = NULL;
5465 }
paul545acaf2004-04-20 15:13:15 +00005466}