blob: 3fdd9ff694aa466aa04039cb7aeff454cf6027bb [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* BGP-4, BGP-4+ daemon program
2 Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "prefix.h"
24#include "thread.h"
25#include "buffer.h"
26#include "stream.h"
27#include "command.h"
28#include "sockunion.h"
29#include "network.h"
30#include "memory.h"
31#include "filter.h"
32#include "routemap.h"
33#include "str.h"
34#include "log.h"
35#include "plist.h"
36#include "linklist.h"
paul200df112005-06-01 11:17:05 +000037#include "workqueue.h"
paul718e3742002-12-13 20:15:29 +000038
39#include "bgpd/bgpd.h"
40#include "bgpd/bgp_table.h"
41#include "bgpd/bgp_aspath.h"
42#include "bgpd/bgp_route.h"
43#include "bgpd/bgp_dump.h"
44#include "bgpd/bgp_debug.h"
45#include "bgpd/bgp_community.h"
46#include "bgpd/bgp_attr.h"
47#include "bgpd/bgp_regex.h"
48#include "bgpd/bgp_clist.h"
49#include "bgpd/bgp_fsm.h"
50#include "bgpd/bgp_packet.h"
51#include "bgpd/bgp_zebra.h"
52#include "bgpd/bgp_open.h"
53#include "bgpd/bgp_filter.h"
54#include "bgpd/bgp_nexthop.h"
55#include "bgpd/bgp_damp.h"
56#include "bgpd/bgp_mplsvpn.h"
57#include "bgpd/bgp_advertise.h"
58#include "bgpd/bgp_network.h"
59#include "bgpd/bgp_vty.h"
Josh Bailey165b5ff2011-07-20 20:43:22 -070060#include "bgpd/bgp_mpath.h"
paul718e3742002-12-13 20:15:29 +000061#ifdef HAVE_SNMP
62#include "bgpd/bgp_snmp.h"
63#endif /* HAVE_SNMP */
David Lamparter6b0655a2014-06-04 06:53:35 +020064
paul718e3742002-12-13 20:15:29 +000065/* BGP process wide configuration. */
66static struct bgp_master bgp_master;
67
hasso18a6dce2004-10-03 18:18:34 +000068extern struct in_addr router_id_zebra;
69
paul718e3742002-12-13 20:15:29 +000070/* BGP process wide configuration pointer to export. */
71struct bgp_master *bm;
72
73/* BGP community-list. */
74struct community_list_handler *bgp_clist;
David Lamparter6b0655a2014-06-04 06:53:35 +020075
paul718e3742002-12-13 20:15:29 +000076/* BGP global flag manipulation. */
77int
78bgp_option_set (int flag)
79{
80 switch (flag)
81 {
82 case BGP_OPT_NO_FIB:
83 case BGP_OPT_MULTIPLE_INSTANCE:
84 case BGP_OPT_CONFIG_CISCO:
Paul Jakmacccbc012012-06-14 10:40:26 +010085 case BGP_OPT_NO_LISTEN:
paul718e3742002-12-13 20:15:29 +000086 SET_FLAG (bm->options, flag);
87 break;
88 default:
89 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +000090 }
91 return 0;
92}
93
94int
95bgp_option_unset (int flag)
96{
97 switch (flag)
98 {
99 case BGP_OPT_MULTIPLE_INSTANCE:
100 if (listcount (bm->bgp) > 1)
101 return BGP_ERR_MULTIPLE_INSTANCE_USED;
102 /* Fall through. */
103 case BGP_OPT_NO_FIB:
104 case BGP_OPT_CONFIG_CISCO:
105 UNSET_FLAG (bm->options, flag);
106 break;
107 default:
108 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +0000109 }
110 return 0;
111}
112
113int
114bgp_option_check (int flag)
115{
116 return CHECK_FLAG (bm->options, flag);
117}
David Lamparter6b0655a2014-06-04 06:53:35 +0200118
paul718e3742002-12-13 20:15:29 +0000119/* BGP flag manipulation. */
120int
121bgp_flag_set (struct bgp *bgp, int flag)
122{
123 SET_FLAG (bgp->flags, flag);
124 return 0;
125}
126
127int
128bgp_flag_unset (struct bgp *bgp, int flag)
129{
130 UNSET_FLAG (bgp->flags, flag);
131 return 0;
132}
133
134int
135bgp_flag_check (struct bgp *bgp, int flag)
136{
137 return CHECK_FLAG (bgp->flags, flag);
138}
David Lamparter6b0655a2014-06-04 06:53:35 +0200139
paul718e3742002-12-13 20:15:29 +0000140/* Internal function to set BGP structure configureation flag. */
141static void
142bgp_config_set (struct bgp *bgp, int config)
143{
144 SET_FLAG (bgp->config, config);
145}
146
147static void
148bgp_config_unset (struct bgp *bgp, int config)
149{
150 UNSET_FLAG (bgp->config, config);
151}
152
153static int
154bgp_config_check (struct bgp *bgp, int config)
155{
156 return CHECK_FLAG (bgp->config, config);
157}
David Lamparter6b0655a2014-06-04 06:53:35 +0200158
paul718e3742002-12-13 20:15:29 +0000159/* Set BGP router identifier. */
160int
161bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
162{
163 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000164 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000165
166 if (bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID)
167 && IPV4_ADDR_SAME (&bgp->router_id, id))
168 return 0;
169
170 IPV4_ADDR_COPY (&bgp->router_id, id);
171 bgp_config_set (bgp, BGP_CONFIG_ROUTER_ID);
172
173 /* Set all peer's local identifier with this value. */
paul1eb8ef22005-04-07 07:30:20 +0000174 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000175 {
176 IPV4_ADDR_COPY (&peer->local_id, id);
177
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000178 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000179 {
180 peer->last_reset = PEER_DOWN_RID_CHANGE;
181 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
182 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
183 }
paul718e3742002-12-13 20:15:29 +0000184 }
185 return 0;
186}
187
paul718e3742002-12-13 20:15:29 +0000188/* BGP's cluster-id control. */
189int
190bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
191{
192 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000193 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000194
195 if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)
196 && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id))
197 return 0;
198
199 IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id);
200 bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID);
201
202 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000203 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000204 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000205 if (peer->sort != BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +0000206 continue;
207
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000208 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000209 {
210 peer->last_reset = PEER_DOWN_CLID_CHANGE;
211 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
212 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
213 }
paul718e3742002-12-13 20:15:29 +0000214 }
215 return 0;
216}
217
218int
219bgp_cluster_id_unset (struct bgp *bgp)
220{
221 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000222 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000223
224 if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID))
225 return 0;
226
227 bgp->cluster_id.s_addr = 0;
228 bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID);
229
230 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000231 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000232 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000233 if (peer->sort != BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +0000234 continue;
235
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000236 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000237 {
238 peer->last_reset = PEER_DOWN_CLID_CHANGE;
239 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
240 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
241 }
paul718e3742002-12-13 20:15:29 +0000242 }
243 return 0;
244}
David Lamparter6b0655a2014-06-04 06:53:35 +0200245
Stephen Hemminger65957882010-01-15 16:22:10 +0300246/* time_t value that is monotonicly increasing
247 * and uneffected by adjustments to system clock
248 */
249time_t bgp_clock (void)
250{
251 struct timeval tv;
252
253 quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv);
254 return tv.tv_sec;
255}
256
paul718e3742002-12-13 20:15:29 +0000257/* BGP timer configuration. */
258int
259bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
260{
261 bgp->default_keepalive = (keepalive < holdtime / 3
262 ? keepalive : holdtime / 3);
263 bgp->default_holdtime = holdtime;
264
265 return 0;
266}
267
268int
269bgp_timers_unset (struct bgp *bgp)
270{
271 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
272 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
273
274 return 0;
275}
David Lamparter6b0655a2014-06-04 06:53:35 +0200276
paul718e3742002-12-13 20:15:29 +0000277/* BGP confederation configuration. */
278int
279bgp_confederation_id_set (struct bgp *bgp, as_t as)
280{
281 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000282 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000283 int already_confed;
284
285 if (as == 0)
286 return BGP_ERR_INVALID_AS;
287
288 /* Remember - were we doing confederation before? */
289 already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);
290 bgp->confed_id = as;
291 bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);
292
293 /* If we were doing confederation already, this is just an external
294 AS change. Just Reset EBGP sessions, not CONFED sessions. If we
295 were not doing confederation before, reset all EBGP sessions. */
paul1eb8ef22005-04-07 07:30:20 +0000296 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000297 {
298 /* We're looking for peers who's AS is not local or part of our
299 confederation. */
300 if (already_confed)
301 {
302 if (peer_sort (peer) == BGP_PEER_EBGP)
303 {
304 peer->local_as = as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000305 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000306 {
307 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
308 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
309 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
310 }
311
paul718e3742002-12-13 20:15:29 +0000312 else
313 BGP_EVENT_ADD (peer, BGP_Stop);
314 }
315 }
316 else
317 {
318 /* Not doign confederation before, so reset every non-local
319 session */
320 if (peer_sort (peer) != BGP_PEER_IBGP)
321 {
322 /* Reset the local_as to be our EBGP one */
323 if (peer_sort (peer) == BGP_PEER_EBGP)
324 peer->local_as = as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000325 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000326 {
327 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
328 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
329 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
330 }
paul718e3742002-12-13 20:15:29 +0000331 else
332 BGP_EVENT_ADD (peer, BGP_Stop);
333 }
334 }
335 }
336 return 0;
337}
338
339int
340bgp_confederation_id_unset (struct bgp *bgp)
341{
342 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000343 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000344
345 bgp->confed_id = 0;
346 bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
347
paul1eb8ef22005-04-07 07:30:20 +0000348 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000349 {
350 /* We're looking for peers who's AS is not local */
351 if (peer_sort (peer) != BGP_PEER_IBGP)
352 {
353 peer->local_as = bgp->as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000354 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000355 {
356 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
357 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
358 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
359 }
360
paul718e3742002-12-13 20:15:29 +0000361 else
362 BGP_EVENT_ADD (peer, BGP_Stop);
363 }
364 }
365 return 0;
366}
367
368/* Is an AS part of the confed or not? */
369int
370bgp_confederation_peers_check (struct bgp *bgp, as_t as)
371{
372 int i;
373
374 if (! bgp)
375 return 0;
376
377 for (i = 0; i < bgp->confed_peers_cnt; i++)
378 if (bgp->confed_peers[i] == as)
379 return 1;
380
381 return 0;
382}
383
384/* Add an AS to the confederation set. */
385int
386bgp_confederation_peers_add (struct bgp *bgp, as_t as)
387{
388 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000389 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000390
391 if (! bgp)
392 return BGP_ERR_INVALID_BGP;
393
394 if (bgp->as == as)
395 return BGP_ERR_INVALID_AS;
396
397 if (bgp_confederation_peers_check (bgp, as))
398 return -1;
399
400 if (bgp->confed_peers)
401 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
402 bgp->confed_peers,
403 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
404 else
405 bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST,
406 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
407
408 bgp->confed_peers[bgp->confed_peers_cnt] = as;
409 bgp->confed_peers_cnt++;
410
411 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
412 {
paul1eb8ef22005-04-07 07:30:20 +0000413 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000414 {
415 if (peer->as == as)
416 {
417 peer->local_as = bgp->as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000418 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000419 {
420 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
421 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
422 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
423 }
paul718e3742002-12-13 20:15:29 +0000424 else
425 BGP_EVENT_ADD (peer, BGP_Stop);
426 }
427 }
428 }
429 return 0;
430}
431
432/* Delete an AS from the confederation set. */
433int
434bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
435{
436 int i;
437 int j;
438 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000439 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000440
441 if (! bgp)
442 return -1;
443
444 if (! bgp_confederation_peers_check (bgp, as))
445 return -1;
446
447 for (i = 0; i < bgp->confed_peers_cnt; i++)
448 if (bgp->confed_peers[i] == as)
449 for(j = i + 1; j < bgp->confed_peers_cnt; j++)
450 bgp->confed_peers[j - 1] = bgp->confed_peers[j];
451
452 bgp->confed_peers_cnt--;
453
454 if (bgp->confed_peers_cnt == 0)
455 {
456 if (bgp->confed_peers)
457 XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
458 bgp->confed_peers = NULL;
459 }
460 else
461 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
462 bgp->confed_peers,
463 bgp->confed_peers_cnt * sizeof (as_t));
464
465 /* Now reset any peer who's remote AS has just been removed from the
466 CONFED */
467 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
468 {
paul1eb8ef22005-04-07 07:30:20 +0000469 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000470 {
471 if (peer->as == as)
472 {
473 peer->local_as = bgp->confed_id;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000474 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000475 {
476 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
477 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
478 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
479 }
paul718e3742002-12-13 20:15:29 +0000480 else
481 BGP_EVENT_ADD (peer, BGP_Stop);
482 }
483 }
484 }
485
486 return 0;
487}
David Lamparter6b0655a2014-06-04 06:53:35 +0200488
paul718e3742002-12-13 20:15:29 +0000489/* Local preference configuration. */
490int
491bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
492{
493 if (! bgp)
494 return -1;
495
paul718e3742002-12-13 20:15:29 +0000496 bgp->default_local_pref = local_pref;
497
498 return 0;
499}
500
501int
502bgp_default_local_preference_unset (struct bgp *bgp)
503{
504 if (! bgp)
505 return -1;
506
paul718e3742002-12-13 20:15:29 +0000507 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
508
509 return 0;
510}
David Lamparter6b0655a2014-06-04 06:53:35 +0200511
paulfee0f4c2004-09-13 05:12:46 +0000512/* If peer is RSERVER_CLIENT in at least one address family and is not member
513 of a peer_group for that family, return 1.
514 Used to check wether the peer is included in list bgp->rsclient. */
515int
516peer_rsclient_active (struct peer *peer)
517{
518 int i;
519 int j;
520
521 for (i=AFI_IP; i < AFI_MAX; i++)
522 for (j=SAFI_UNICAST; j < SAFI_MAX; j++)
523 if (CHECK_FLAG(peer->af_flags[i][j], PEER_FLAG_RSERVER_CLIENT)
524 && ! peer->af_group[i][j])
525 return 1;
526 return 0;
527}
528
pauleb821182004-05-01 08:44:08 +0000529/* Peer comparison function for sorting. */
paul718e3742002-12-13 20:15:29 +0000530static int
531peer_cmp (struct peer *p1, struct peer *p2)
532{
pauleb821182004-05-01 08:44:08 +0000533 return sockunion_cmp (&p1->su, &p2->su);
paul718e3742002-12-13 20:15:29 +0000534}
535
536int
537peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
538{
539 return CHECK_FLAG (peer->af_flags[afi][safi], flag);
540}
541
542/* Reset all address family specific configuration. */
543static void
544peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
545{
546 int i;
547 struct bgp_filter *filter;
548 char orf_name[BUFSIZ];
549
550 filter = &peer->filter[afi][safi];
551
552 /* Clear neighbor filter and route-map */
553 for (i = FILTER_IN; i < FILTER_MAX; i++)
554 {
555 if (filter->dlist[i].name)
556 {
557 free (filter->dlist[i].name);
558 filter->dlist[i].name = NULL;
559 }
560 if (filter->plist[i].name)
561 {
562 free (filter->plist[i].name);
563 filter->plist[i].name = NULL;
564 }
565 if (filter->aslist[i].name)
566 {
567 free (filter->aslist[i].name);
568 filter->aslist[i].name = NULL;
569 }
paulfee0f4c2004-09-13 05:12:46 +0000570 }
571 for (i = RMAP_IN; i < RMAP_MAX; i++)
572 {
paul718e3742002-12-13 20:15:29 +0000573 if (filter->map[i].name)
574 {
575 free (filter->map[i].name);
576 filter->map[i].name = NULL;
577 }
578 }
579
580 /* Clear unsuppress map. */
581 if (filter->usmap.name)
582 free (filter->usmap.name);
583 filter->usmap.name = NULL;
584 filter->usmap.map = NULL;
585
586 /* Clear neighbor's all address family flags. */
587 peer->af_flags[afi][safi] = 0;
588
589 /* Clear neighbor's all address family sflags. */
590 peer->af_sflags[afi][safi] = 0;
591
592 /* Clear neighbor's all address family capabilities. */
593 peer->af_cap[afi][safi] = 0;
594
595 /* Clear ORF info */
596 peer->orf_plist[afi][safi] = NULL;
597 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
David Lamparterc9c06d02015-04-13 10:21:35 +0200598 prefix_bgp_orf_remove_all (afi, orf_name);
paul718e3742002-12-13 20:15:29 +0000599
600 /* Set default neighbor send-community. */
601 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
602 {
603 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
604 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
605 }
606
607 /* Clear neighbor default_originate_rmap */
608 if (peer->default_rmap[afi][safi].name)
609 free (peer->default_rmap[afi][safi].name);
610 peer->default_rmap[afi][safi].name = NULL;
611 peer->default_rmap[afi][safi].map = NULL;
612
613 /* Clear neighbor maximum-prefix */
614 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +0000615 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000616}
617
618/* peer global config reset */
paul94f2b392005-06-28 12:44:16 +0000619static void
paul718e3742002-12-13 20:15:29 +0000620peer_global_config_reset (struct peer *peer)
621{
622 peer->weight = 0;
623 peer->change_local_as = 0;
624 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
625 if (peer->update_source)
626 {
627 sockunion_free (peer->update_source);
628 peer->update_source = NULL;
629 }
630 if (peer->update_if)
631 {
632 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
633 peer->update_if = NULL;
634 }
635
636 if (peer_sort (peer) == BGP_PEER_IBGP)
637 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
638 else
639 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
640
641 peer->flags = 0;
642 peer->config = 0;
643 peer->holdtime = 0;
644 peer->keepalive = 0;
645 peer->connect = 0;
646 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
647}
648
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000649/* Check peer's AS number and determines if this peer is IBGP or EBGP */
650static bgp_peer_sort_t
651peer_calc_sort (struct peer *peer)
paul718e3742002-12-13 20:15:29 +0000652{
653 struct bgp *bgp;
654
655 bgp = peer->bgp;
656
657 /* Peer-group */
658 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
659 {
660 if (peer->as)
661 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
662 else
663 {
664 struct peer *peer1;
665 peer1 = listnode_head (peer->group->peer);
666 if (peer1)
667 return (peer1->local_as == peer1->as
668 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
669 }
670 return BGP_PEER_INTERNAL;
671 }
672
673 /* Normal peer */
674 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
675 {
676 if (peer->local_as == 0)
677 return BGP_PEER_INTERNAL;
678
679 if (peer->local_as == peer->as)
680 {
681 if (peer->local_as == bgp->confed_id)
682 return BGP_PEER_EBGP;
683 else
684 return BGP_PEER_IBGP;
685 }
686
687 if (bgp_confederation_peers_check (bgp, peer->as))
688 return BGP_PEER_CONFED;
689
690 return BGP_PEER_EBGP;
691 }
692 else
693 {
694 return (peer->local_as == 0
695 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
696 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
697 }
698}
699
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000700/* Calculate and cache the peer "sort" */
701bgp_peer_sort_t
702peer_sort (struct peer *peer)
703{
704 peer->sort = peer_calc_sort (peer);
705 return peer->sort;
706}
707
Paul Jakmaf63f06d2011-04-08 12:44:43 +0100708static void
paul200df112005-06-01 11:17:05 +0000709peer_free (struct peer *peer)
710{
Paul Jakmaca058a32006-09-14 02:58:49 +0000711 assert (peer->status == Deleted);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700712
713 bgp_unlock(peer->bgp);
714
Paul Jakmaca058a32006-09-14 02:58:49 +0000715 /* this /ought/ to have been done already through bgp_stop earlier,
716 * but just to be sure..
717 */
718 bgp_timer_set (peer);
719 BGP_READ_OFF (peer->t_read);
720 BGP_WRITE_OFF (peer->t_write);
Paul Jakma9fde6622006-09-14 03:02:02 +0000721 BGP_EVENT_FLUSH (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +0000722
paul200df112005-06-01 11:17:05 +0000723 if (peer->desc)
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 *
Donald Sharp104576d2015-09-16 13:17:55 -0400748peer_lock_with_caller (const char *name, struct peer *peer)
paul200df112005-06-01 11:17:05 +0000749{
750 assert (peer && (peer->lock >= 0));
Donald Sharp104576d2015-09-16 13:17:55 -0400751
752#if 0
753 zlog_debug("%s peer_lock %p %d", name, peer, peer->lock);
754#endif
755
paul200df112005-06-01 11:17:05 +0000756 peer->lock++;
757
758 return peer;
759}
760
761/* decrease reference count on a struct peer
762 * struct peer is freed and NULL returned if last reference
763 */
764struct peer *
Donald Sharp104576d2015-09-16 13:17:55 -0400765peer_unlock_with_caller (const char *name, struct peer *peer)
paul200df112005-06-01 11:17:05 +0000766{
767 assert (peer && (peer->lock > 0));
Donald Sharp104576d2015-09-16 13:17:55 -0400768
769#if 0
770 zlog_debug("%s peer_unlock %p %d", name, peer, peer->lock);
771#endif
772
paul200df112005-06-01 11:17:05 +0000773 peer->lock--;
774
775 if (peer->lock == 0)
776 {
paul200df112005-06-01 11:17:05 +0000777 peer_free (peer);
778 return NULL;
779 }
780
paul200df112005-06-01 11:17:05 +0000781 return peer;
782}
783
784/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000785static struct peer *
Paul Jakma6f585442006-10-22 19:13:07 +0000786peer_new (struct bgp *bgp)
paul718e3742002-12-13 20:15:29 +0000787{
788 afi_t afi;
789 safi_t safi;
790 struct peer *peer;
791 struct servent *sp;
Paul Jakma6f585442006-10-22 19:13:07 +0000792
793 /* bgp argument is absolutely required */
794 assert (bgp);
795 if (!bgp)
796 return NULL;
797
paul718e3742002-12-13 20:15:29 +0000798 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000799 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000800
801 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000802 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000803 peer->v_start = BGP_INIT_START_TIMER;
804 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
805 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
806 peer->status = Idle;
807 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000808 peer->weight = 0;
Paul Jakma0df7c912008-07-21 21:02:49 +0000809 peer->password = NULL;
Paul Jakma6f585442006-10-22 19:13:07 +0000810 peer->bgp = bgp;
Paul Jakmaca058a32006-09-14 02:58:49 +0000811 peer = peer_lock (peer); /* initial reference */
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700812 bgp_lock (bgp);
paul718e3742002-12-13 20:15:29 +0000813
814 /* Set default flags. */
815 for (afi = AFI_IP; afi < AFI_MAX; afi++)
816 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
817 {
818 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
819 {
820 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
821 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
822 }
823 peer->orf_plist[afi][safi] = NULL;
824 }
825 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
826
827 /* Create buffers. */
828 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
829 peer->obuf = stream_fifo_new ();
830 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000831 peer->scratch = stream_new (BGP_MAX_PACKET_SIZE);
paul718e3742002-12-13 20:15:29 +0000832
833 bgp_sync_init (peer);
834
835 /* Get service port number. */
836 sp = getservbyname ("bgp", "tcp");
837 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
838
839 return peer;
840}
841
842/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000843static struct peer *
paul718e3742002-12-13 20:15:29 +0000844peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
845 as_t remote_as, afi_t afi, safi_t safi)
846{
847 int active;
848 struct peer *peer;
849 char buf[SU_ADDRSTRLEN];
850
Paul Jakma6f585442006-10-22 19:13:07 +0000851 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000852 peer->su = *su;
853 peer->local_as = local_as;
854 peer->as = remote_as;
855 peer->local_id = bgp->router_id;
856 peer->v_holdtime = bgp->default_holdtime;
857 peer->v_keepalive = bgp->default_keepalive;
858 if (peer_sort (peer) == BGP_PEER_IBGP)
859 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
860 else
861 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000862
863 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000864 listnode_add_sort (bgp->peer, peer);
865
866 active = peer_active (peer);
867
868 if (afi && safi)
869 peer->afc[afi][safi] = 1;
870
Stephen Hemminger65957882010-01-15 16:22:10 +0300871 /* Last read and reset time set */
872 peer->readtime = peer->resettime = bgp_clock ();
paul848973c2003-08-13 00:32:49 +0000873
paul718e3742002-12-13 20:15:29 +0000874 /* Default TTL set. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000875 peer->ttl = (peer->sort == BGP_PEER_IBGP) ? 255 : 1;
paul718e3742002-12-13 20:15:29 +0000876
877 /* Make peer's address string. */
878 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000879 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000880
881 /* Set up peer's events and timers. */
882 if (! active && peer_active (peer))
883 bgp_timer_set (peer);
884
885 return peer;
886}
887
pauleb821182004-05-01 08:44:08 +0000888/* Make accept BGP peer. Called from bgp_accept (). */
889struct peer *
890peer_create_accept (struct bgp *bgp)
891{
892 struct peer *peer;
893
Paul Jakma6f585442006-10-22 19:13:07 +0000894 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000895
896 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000897 listnode_add_sort (bgp->peer, peer);
898
899 return peer;
900}
901
paul718e3742002-12-13 20:15:29 +0000902/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000903static void
paul718e3742002-12-13 20:15:29 +0000904peer_as_change (struct peer *peer, as_t as)
905{
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000906 bgp_peer_sort_t type;
paul718e3742002-12-13 20:15:29 +0000907
908 /* Stop peer. */
909 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
910 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000911 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000912 {
913 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
914 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
915 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
916 }
paul718e3742002-12-13 20:15:29 +0000917 else
918 BGP_EVENT_ADD (peer, BGP_Stop);
919 }
920 type = peer_sort (peer);
921 peer->as = as;
922
paul848973c2003-08-13 00:32:49 +0000923 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
924 && ! bgp_confederation_peers_check (peer->bgp, as)
925 && peer->bgp->as != as)
926 peer->local_as = peer->bgp->confed_id;
927 else
928 peer->local_as = peer->bgp->as;
929
paul718e3742002-12-13 20:15:29 +0000930 /* Advertisement-interval reset */
931 if (peer_sort (peer) == BGP_PEER_IBGP)
932 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
933 else
934 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
935
936 /* TTL reset */
937 if (peer_sort (peer) == BGP_PEER_IBGP)
938 peer->ttl = 255;
939 else if (type == BGP_PEER_IBGP)
940 peer->ttl = 1;
941
942 /* reflector-client reset */
943 if (peer_sort (peer) != BGP_PEER_IBGP)
944 {
945 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
946 PEER_FLAG_REFLECTOR_CLIENT);
947 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
948 PEER_FLAG_REFLECTOR_CLIENT);
949 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
950 PEER_FLAG_REFLECTOR_CLIENT);
951 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
952 PEER_FLAG_REFLECTOR_CLIENT);
953 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
954 PEER_FLAG_REFLECTOR_CLIENT);
955 }
956
957 /* local-as reset */
958 if (peer_sort (peer) != BGP_PEER_EBGP)
959 {
960 peer->change_local_as = 0;
961 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +0000962 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +0000963 }
964}
965
966/* If peer does not exist, create new one. If peer already exists,
967 set AS number to the peer. */
968int
969peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
970 afi_t afi, safi_t safi)
971{
972 struct peer *peer;
973 as_t local_as;
974
975 peer = peer_lookup (bgp, su);
976
977 if (peer)
978 {
979 /* When this peer is a member of peer-group. */
980 if (peer->group)
981 {
982 if (peer->group->conf->as)
983 {
984 /* Return peer group's AS number. */
985 *as = peer->group->conf->as;
986 return BGP_ERR_PEER_GROUP_MEMBER;
987 }
988 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
989 {
990 if (bgp->as != *as)
991 {
992 *as = peer->as;
993 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
994 }
995 }
996 else
997 {
998 if (bgp->as == *as)
999 {
1000 *as = peer->as;
1001 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1002 }
1003 }
1004 }
1005
1006 /* Existing peer's AS number change. */
1007 if (peer->as != *as)
1008 peer_as_change (peer, *as);
1009 }
1010 else
1011 {
1012
1013 /* If the peer is not part of our confederation, and its not an
1014 iBGP peer then spoof the source AS */
1015 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1016 && ! bgp_confederation_peers_check (bgp, *as)
1017 && bgp->as != *as)
1018 local_as = bgp->confed_id;
1019 else
1020 local_as = bgp->as;
1021
1022 /* If this is IPv4 unicast configuration and "no bgp default
1023 ipv4-unicast" is specified. */
1024
1025 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1026 && afi == AFI_IP && safi == SAFI_UNICAST)
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001027 peer_create (su, bgp, local_as, *as, 0, 0);
paul718e3742002-12-13 20:15:29 +00001028 else
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001029 peer_create (su, bgp, local_as, *as, afi, safi);
paul718e3742002-12-13 20:15:29 +00001030 }
1031
1032 return 0;
1033}
1034
1035/* Activate the peer or peer group for specified AFI and SAFI. */
1036int
1037peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1038{
1039 int active;
1040
1041 if (peer->afc[afi][safi])
1042 return 0;
1043
1044 /* Activate the address family configuration. */
1045 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1046 peer->afc[afi][safi] = 1;
1047 else
1048 {
1049 active = peer_active (peer);
1050
1051 peer->afc[afi][safi] = 1;
1052
1053 if (! active && peer_active (peer))
1054 bgp_timer_set (peer);
1055 else
1056 {
1057 if (peer->status == Established)
1058 {
1059 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1060 {
1061 peer->afc_adv[afi][safi] = 1;
1062 bgp_capability_send (peer, afi, safi,
1063 CAPABILITY_CODE_MP,
1064 CAPABILITY_ACTION_SET);
1065 if (peer->afc_recv[afi][safi])
1066 {
1067 peer->afc_nego[afi][safi] = 1;
1068 bgp_announce_route (peer, afi, safi);
1069 }
1070 }
1071 else
hassoe0701b72004-05-20 09:19:34 +00001072 {
1073 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1074 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1075 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1076 }
paul718e3742002-12-13 20:15:29 +00001077 }
1078 }
1079 }
1080 return 0;
1081}
1082
1083int
1084peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1085{
1086 struct peer_group *group;
1087 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001088 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001089
1090 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1091 {
1092 group = peer->group;
1093
paul1eb8ef22005-04-07 07:30:20 +00001094 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001095 {
1096 if (peer1->af_group[afi][safi])
1097 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1098 }
1099 }
1100 else
1101 {
1102 if (peer->af_group[afi][safi])
1103 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1104 }
1105
1106 if (! peer->afc[afi][safi])
1107 return 0;
1108
1109 /* De-activate the address family configuration. */
1110 peer->afc[afi][safi] = 0;
1111 peer_af_flag_reset (peer, afi, safi);
1112
1113 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1114 {
1115 if (peer->status == Established)
1116 {
1117 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1118 {
1119 peer->afc_adv[afi][safi] = 0;
1120 peer->afc_nego[afi][safi] = 0;
1121
1122 if (peer_active_nego (peer))
1123 {
1124 bgp_capability_send (peer, afi, safi,
1125 CAPABILITY_CODE_MP,
1126 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001127 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001128 peer->pcount[afi][safi] = 0;
1129 }
1130 else
hassoe0701b72004-05-20 09:19:34 +00001131 {
1132 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1133 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1134 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1135 }
paul718e3742002-12-13 20:15:29 +00001136 }
1137 else
hassoe0701b72004-05-20 09:19:34 +00001138 {
1139 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1140 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1141 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1142 }
paul718e3742002-12-13 20:15:29 +00001143 }
1144 }
1145 return 0;
1146}
1147
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001148static void
hasso93406d82005-02-02 14:40:33 +00001149peer_nsf_stop (struct peer *peer)
1150{
1151 afi_t afi;
1152 safi_t safi;
1153
1154 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1155 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1156
1157 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +04001158 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +00001159 peer->nsf[afi][safi] = 0;
1160
1161 if (peer->t_gr_restart)
1162 {
1163 BGP_TIMER_OFF (peer->t_gr_restart);
1164 if (BGP_DEBUG (events, EVENTS))
1165 zlog_debug ("%s graceful restart timer stopped", peer->host);
1166 }
1167 if (peer->t_gr_stale)
1168 {
1169 BGP_TIMER_OFF (peer->t_gr_stale);
1170 if (BGP_DEBUG (events, EVENTS))
1171 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1172 }
1173 bgp_clear_route_all (peer);
1174}
1175
Paul Jakmaca058a32006-09-14 02:58:49 +00001176/* Delete peer from confguration.
1177 *
1178 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1179 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1180 *
1181 * This function /should/ take care to be idempotent, to guard against
1182 * it being called multiple times through stray events that come in
1183 * that happen to result in this function being called again. That
1184 * said, getting here for a "Deleted" peer is a bug in the neighbour
1185 * FSM.
1186 */
paul718e3742002-12-13 20:15:29 +00001187int
1188peer_delete (struct peer *peer)
1189{
1190 int i;
1191 afi_t afi;
1192 safi_t safi;
1193 struct bgp *bgp;
1194 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001195 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001196
Paul Jakmaca058a32006-09-14 02:58:49 +00001197 assert (peer->status != Deleted);
1198
paul718e3742002-12-13 20:15:29 +00001199 bgp = peer->bgp;
1200
hasso93406d82005-02-02 14:40:33 +00001201 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1202 peer_nsf_stop (peer);
1203
Chris Caputo228da422009-07-18 05:44:03 +00001204 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001205 relationship. */
1206 if (peer->group)
1207 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001208 if ((pn = listnode_lookup (peer->group->peer, peer)))
1209 {
1210 peer = peer_unlock (peer); /* group->peer list reference */
1211 list_delete_node (peer->group->peer, pn);
1212 }
paul718e3742002-12-13 20:15:29 +00001213 peer->group = NULL;
1214 }
paul200df112005-06-01 11:17:05 +00001215
paul718e3742002-12-13 20:15:29 +00001216 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001217 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1218 * executed after peer structure is deleted.
1219 */
hassoe0701b72004-05-20 09:19:34 +00001220 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001221 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001222 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001223
1224 /* Password configuration */
1225 if (peer->password)
1226 {
1227 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1228 peer->password = NULL;
1229
1230 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1231 bgp_md5_set (peer);
1232 }
1233
Paul Jakmaca058a32006-09-14 02:58:49 +00001234 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001235
paul718e3742002-12-13 20:15:29 +00001236 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001237 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1238 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001239 {
Chris Caputo228da422009-07-18 05:44:03 +00001240 peer_unlock (peer); /* bgp peer list reference */
1241 list_delete_node (bgp->peer, pn);
1242 }
paul200df112005-06-01 11:17:05 +00001243
Chris Caputo228da422009-07-18 05:44:03 +00001244 if (peer_rsclient_active (peer)
1245 && (pn = listnode_lookup (bgp->rsclient, peer)))
1246 {
1247 peer_unlock (peer); /* rsclient list reference */
1248 list_delete_node (bgp->rsclient, pn);
1249
1250 /* Clear our own rsclient ribs. */
1251 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1252 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1253 if (CHECK_FLAG(peer->af_flags[afi][safi],
1254 PEER_FLAG_RSERVER_CLIENT))
1255 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001256 }
1257
1258 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1259 member of a peer_group. */
1260 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1261 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1262 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001263 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001264
paul200df112005-06-01 11:17:05 +00001265 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001266 if (peer->ibuf)
1267 stream_free (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001268 if (peer->obuf)
1269 stream_fifo_free (peer->obuf);
paul718e3742002-12-13 20:15:29 +00001270 if (peer->work)
1271 stream_free (peer->work);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00001272 if (peer->scratch)
1273 stream_free(peer->scratch);
Paul Jakma18937402006-07-27 19:05:12 +00001274 peer->obuf = NULL;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00001275 peer->work = peer->scratch = peer->ibuf = NULL;
Paul Jakma18937402006-07-27 19:05:12 +00001276
paul718e3742002-12-13 20:15:29 +00001277 /* Local and remote addresses. */
1278 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001279 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001280 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001281 sockunion_free (peer->su_remote);
Paul Jakma18937402006-07-27 19:05:12 +00001282 peer->su_local = peer->su_remote = NULL;
paul200df112005-06-01 11:17:05 +00001283
paul718e3742002-12-13 20:15:29 +00001284 /* Free filter related memory. */
1285 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1286 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1287 {
1288 filter = &peer->filter[afi][safi];
1289
1290 for (i = FILTER_IN; i < FILTER_MAX; i++)
1291 {
1292 if (filter->dlist[i].name)
1293 free (filter->dlist[i].name);
1294 if (filter->plist[i].name)
1295 free (filter->plist[i].name);
1296 if (filter->aslist[i].name)
1297 free (filter->aslist[i].name);
paul200df112005-06-01 11:17:05 +00001298
1299 filter->dlist[i].name = NULL;
1300 filter->plist[i].name = NULL;
1301 filter->aslist[i].name = NULL;
1302 }
1303 for (i = RMAP_IN; i < RMAP_MAX; i++)
1304 {
paul718e3742002-12-13 20:15:29 +00001305 if (filter->map[i].name)
1306 free (filter->map[i].name);
paul200df112005-06-01 11:17:05 +00001307 filter->map[i].name = NULL;
paul718e3742002-12-13 20:15:29 +00001308 }
1309
1310 if (filter->usmap.name)
1311 free (filter->usmap.name);
1312
1313 if (peer->default_rmap[afi][safi].name)
1314 free (peer->default_rmap[afi][safi].name);
paul200df112005-06-01 11:17:05 +00001315
1316 filter->usmap.name = NULL;
1317 peer->default_rmap[afi][safi].name = NULL;
paul718e3742002-12-13 20:15:29 +00001318 }
paul200df112005-06-01 11:17:05 +00001319
1320 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001321
1322 return 0;
1323}
David Lamparter6b0655a2014-06-04 06:53:35 +02001324
paul94f2b392005-06-28 12:44:16 +00001325static int
paul718e3742002-12-13 20:15:29 +00001326peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1327{
1328 return strcmp (g1->name, g2->name);
1329}
1330
1331/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001332static int
paul718e3742002-12-13 20:15:29 +00001333peer_group_active (struct peer *peer)
1334{
1335 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1336 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1337 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1338 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1339 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1340 return 1;
1341 return 0;
1342}
1343
1344/* Peer group cofiguration. */
1345static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001346peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001347{
1348 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1349 sizeof (struct peer_group));
1350}
1351
paul94f2b392005-06-28 12:44:16 +00001352static void
paul718e3742002-12-13 20:15:29 +00001353peer_group_free (struct peer_group *group)
1354{
1355 XFREE (MTYPE_PEER_GROUP, group);
1356}
1357
1358struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001359peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001360{
1361 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001362 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001363
paul1eb8ef22005-04-07 07:30:20 +00001364 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001365 {
1366 if (strcmp (group->name, name) == 0)
1367 return group;
1368 }
1369 return NULL;
1370}
1371
1372struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001373peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001374{
1375 struct peer_group *group;
1376
1377 group = peer_group_lookup (bgp, name);
1378 if (group)
1379 return group;
1380
1381 group = peer_group_new ();
1382 group->bgp = bgp;
1383 group->name = strdup (name);
1384 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001385 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001386 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1387 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001388 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001389 group->conf->group = group;
1390 group->conf->as = 0;
1391 group->conf->ttl = 1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001392 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001393 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1394 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1395 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1396 group->conf->keepalive = 0;
1397 group->conf->holdtime = 0;
1398 group->conf->connect = 0;
1399 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1400 listnode_add_sort (bgp->group, group);
1401
1402 return 0;
1403}
1404
paul94f2b392005-06-28 12:44:16 +00001405static void
paul718e3742002-12-13 20:15:29 +00001406peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1407 afi_t afi, safi_t safi)
1408{
1409 int in = FILTER_IN;
1410 int out = FILTER_OUT;
1411 struct peer *conf;
1412 struct bgp_filter *pfilter;
1413 struct bgp_filter *gfilter;
1414
1415 conf = group->conf;
1416 pfilter = &peer->filter[afi][safi];
1417 gfilter = &conf->filter[afi][safi];
1418
1419 /* remote-as */
1420 if (conf->as)
1421 peer->as = conf->as;
1422
1423 /* remote-as */
1424 if (conf->change_local_as)
1425 peer->change_local_as = conf->change_local_as;
1426
1427 /* TTL */
1428 peer->ttl = conf->ttl;
1429
Nick Hilliardfa411a22011-03-23 15:33:17 +00001430 /* GTSM hops */
1431 peer->gtsm_hops = conf->gtsm_hops;
1432
paul718e3742002-12-13 20:15:29 +00001433 /* Weight */
1434 peer->weight = conf->weight;
1435
1436 /* peer flags apply */
1437 peer->flags = conf->flags;
1438 /* peer af_flags apply */
1439 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1440 /* peer config apply */
1441 peer->config = conf->config;
1442
1443 /* peer timers apply */
1444 peer->holdtime = conf->holdtime;
1445 peer->keepalive = conf->keepalive;
1446 peer->connect = conf->connect;
1447 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1448 peer->v_connect = conf->connect;
1449 else
1450 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1451
1452 /* advertisement-interval reset */
1453 if (peer_sort (peer) == BGP_PEER_IBGP)
1454 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1455 else
1456 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1457
Paul Jakma0df7c912008-07-21 21:02:49 +00001458 /* password apply */
Roman Hoog Antink0e4303d2013-01-18 13:52:03 +01001459 if (conf->password && !peer->password)
Paul Jakma0df7c912008-07-21 21:02:49 +00001460 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
Paul Jakma0df7c912008-07-21 21:02:49 +00001461
1462 bgp_md5_set (peer);
1463
paul718e3742002-12-13 20:15:29 +00001464 /* maximum-prefix */
1465 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001466 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001467 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001468
1469 /* allowas-in */
1470 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1471
paulfee0f4c2004-09-13 05:12:46 +00001472 /* route-server-client */
1473 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1474 {
1475 /* Make peer's RIB point to group's RIB. */
1476 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1477
1478 /* Import policy. */
1479 if (pfilter->map[RMAP_IMPORT].name)
1480 free (pfilter->map[RMAP_IMPORT].name);
1481 if (gfilter->map[RMAP_IMPORT].name)
1482 {
1483 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1484 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1485 }
1486 else
1487 {
1488 pfilter->map[RMAP_IMPORT].name = NULL;
1489 pfilter->map[RMAP_IMPORT].map = NULL;
1490 }
1491
1492 /* Export policy. */
1493 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1494 {
1495 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1496 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1497 }
1498 }
1499
paul718e3742002-12-13 20:15:29 +00001500 /* default-originate route-map */
1501 if (conf->default_rmap[afi][safi].name)
1502 {
1503 if (peer->default_rmap[afi][safi].name)
1504 free (peer->default_rmap[afi][safi].name);
1505 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1506 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1507 }
1508
1509 /* update-source apply */
1510 if (conf->update_source)
1511 {
1512 if (peer->update_source)
1513 sockunion_free (peer->update_source);
1514 if (peer->update_if)
1515 {
1516 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1517 peer->update_if = NULL;
1518 }
1519 peer->update_source = sockunion_dup (conf->update_source);
1520 }
1521 else if (conf->update_if)
1522 {
1523 if (peer->update_if)
1524 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1525 if (peer->update_source)
1526 {
1527 sockunion_free (peer->update_source);
1528 peer->update_source = NULL;
1529 }
1530 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1531 }
1532
1533 /* inbound filter apply */
1534 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1535 {
1536 if (pfilter->dlist[in].name)
1537 free (pfilter->dlist[in].name);
1538 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1539 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1540 }
1541 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1542 {
1543 if (pfilter->plist[in].name)
1544 free (pfilter->plist[in].name);
1545 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1546 pfilter->plist[in].plist = gfilter->plist[in].plist;
1547 }
1548 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1549 {
1550 if (pfilter->aslist[in].name)
1551 free (pfilter->aslist[in].name);
1552 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1553 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1554 }
paulfee0f4c2004-09-13 05:12:46 +00001555 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001556 {
paulfee0f4c2004-09-13 05:12:46 +00001557 if (pfilter->map[RMAP_IN].name)
1558 free (pfilter->map[RMAP_IN].name);
1559 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1560 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001561 }
1562
1563 /* outbound filter apply */
1564 if (gfilter->dlist[out].name)
1565 {
1566 if (pfilter->dlist[out].name)
1567 free (pfilter->dlist[out].name);
1568 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1569 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1570 }
1571 else
1572 {
1573 if (pfilter->dlist[out].name)
1574 free (pfilter->dlist[out].name);
1575 pfilter->dlist[out].name = NULL;
1576 pfilter->dlist[out].alist = NULL;
1577 }
1578 if (gfilter->plist[out].name)
1579 {
1580 if (pfilter->plist[out].name)
1581 free (pfilter->plist[out].name);
1582 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1583 pfilter->plist[out].plist = gfilter->plist[out].plist;
1584 }
1585 else
1586 {
1587 if (pfilter->plist[out].name)
1588 free (pfilter->plist[out].name);
1589 pfilter->plist[out].name = NULL;
1590 pfilter->plist[out].plist = NULL;
1591 }
1592 if (gfilter->aslist[out].name)
1593 {
1594 if (pfilter->aslist[out].name)
1595 free (pfilter->aslist[out].name);
1596 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1597 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1598 }
1599 else
1600 {
1601 if (pfilter->aslist[out].name)
1602 free (pfilter->aslist[out].name);
1603 pfilter->aslist[out].name = NULL;
1604 pfilter->aslist[out].aslist = NULL;
1605 }
paulfee0f4c2004-09-13 05:12:46 +00001606 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001607 {
paulfee0f4c2004-09-13 05:12:46 +00001608 if (pfilter->map[RMAP_OUT].name)
1609 free (pfilter->map[RMAP_OUT].name);
1610 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1611 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001612 }
1613 else
1614 {
paulfee0f4c2004-09-13 05:12:46 +00001615 if (pfilter->map[RMAP_OUT].name)
1616 free (pfilter->map[RMAP_OUT].name);
1617 pfilter->map[RMAP_OUT].name = NULL;
1618 pfilter->map[RMAP_OUT].map = NULL;
1619 }
1620
1621 /* RS-client's import/export route-maps. */
1622 if (gfilter->map[RMAP_IMPORT].name)
1623 {
1624 if (pfilter->map[RMAP_IMPORT].name)
1625 free (pfilter->map[RMAP_IMPORT].name);
1626 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1627 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1628 }
1629 else
1630 {
1631 if (pfilter->map[RMAP_IMPORT].name)
1632 free (pfilter->map[RMAP_IMPORT].name);
1633 pfilter->map[RMAP_IMPORT].name = NULL;
1634 pfilter->map[RMAP_IMPORT].map = NULL;
1635 }
1636 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1637 {
1638 if (pfilter->map[RMAP_EXPORT].name)
1639 free (pfilter->map[RMAP_EXPORT].name);
1640 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1641 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001642 }
1643
1644 if (gfilter->usmap.name)
1645 {
1646 if (pfilter->usmap.name)
1647 free (pfilter->usmap.name);
1648 pfilter->usmap.name = strdup (gfilter->usmap.name);
1649 pfilter->usmap.map = gfilter->usmap.map;
1650 }
1651 else
1652 {
1653 if (pfilter->usmap.name)
1654 free (pfilter->usmap.name);
1655 pfilter->usmap.name = NULL;
1656 pfilter->usmap.map = NULL;
1657 }
1658}
1659
1660/* Peer group's remote AS configuration. */
1661int
paulfd79ac92004-10-13 05:06:08 +00001662peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001663{
1664 struct peer_group *group;
1665 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001666 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001667
1668 group = peer_group_lookup (bgp, group_name);
1669 if (! group)
1670 return -1;
1671
1672 if (group->conf->as == *as)
1673 return 0;
1674
1675 /* When we setup peer-group AS number all peer group member's AS
1676 number must be updated to same number. */
1677 peer_as_change (group->conf, *as);
1678
paul1eb8ef22005-04-07 07:30:20 +00001679 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001680 {
1681 if (peer->as != *as)
1682 peer_as_change (peer, *as);
1683 }
1684
1685 return 0;
1686}
1687
1688int
1689peer_group_delete (struct peer_group *group)
1690{
1691 struct bgp *bgp;
1692 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001693 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001694
1695 bgp = group->bgp;
1696
paul1eb8ef22005-04-07 07:30:20 +00001697 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001698 {
paul718e3742002-12-13 20:15:29 +00001699 peer_delete (peer);
1700 }
1701 list_delete (group->peer);
1702
1703 free (group->name);
1704 group->name = NULL;
1705
1706 group->conf->group = NULL;
1707 peer_delete (group->conf);
1708
1709 /* Delete from all peer_group list. */
1710 listnode_delete (bgp->group, group);
1711
1712 peer_group_free (group);
1713
1714 return 0;
1715}
1716
1717int
1718peer_group_remote_as_delete (struct peer_group *group)
1719{
1720 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001721 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001722
1723 if (! group->conf->as)
1724 return 0;
1725
paul1eb8ef22005-04-07 07:30:20 +00001726 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001727 {
paul718e3742002-12-13 20:15:29 +00001728 peer_delete (peer);
1729 }
1730 list_delete_all_node (group->peer);
1731
1732 group->conf->as = 0;
1733
1734 return 0;
1735}
1736
1737/* Bind specified peer to peer group. */
1738int
1739peer_group_bind (struct bgp *bgp, union sockunion *su,
1740 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1741{
1742 struct peer *peer;
1743 int first_member = 0;
1744
1745 /* Check peer group's address family. */
1746 if (! group->conf->afc[afi][safi])
1747 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1748
1749 /* Lookup the peer. */
1750 peer = peer_lookup (bgp, su);
1751
1752 /* Create a new peer. */
1753 if (! peer)
1754 {
1755 if (! group->conf->as)
1756 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1757
1758 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1759 peer->group = group;
1760 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001761
Paul Jakmaca058a32006-09-14 02:58:49 +00001762 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001763 listnode_add (group->peer, peer);
1764 peer_group2peer_config_copy (group, peer, afi, safi);
1765
1766 return 0;
1767 }
1768
1769 /* When the peer already belongs to peer group, check the consistency. */
1770 if (peer->af_group[afi][safi])
1771 {
1772 if (strcmp (peer->group->name, group->name) != 0)
1773 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1774
1775 return 0;
1776 }
1777
1778 /* Check current peer group configuration. */
1779 if (peer_group_active (peer)
1780 && strcmp (peer->group->name, group->name) != 0)
1781 return BGP_ERR_PEER_GROUP_MISMATCH;
1782
1783 if (! group->conf->as)
1784 {
1785 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1786 && peer_sort (group->conf) != peer_sort (peer))
1787 {
1788 if (as)
1789 *as = peer->as;
1790 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1791 }
1792
1793 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1794 first_member = 1;
1795 }
1796
1797 peer->af_group[afi][safi] = 1;
1798 peer->afc[afi][safi] = 1;
1799 if (! peer->group)
1800 {
1801 peer->group = group;
paul200df112005-06-01 11:17:05 +00001802
Paul Jakmaca058a32006-09-14 02:58:49 +00001803 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001804 listnode_add (group->peer, peer);
1805 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001806 else
1807 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001808
1809 if (first_member)
1810 {
1811 /* Advertisement-interval reset */
1812 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1813 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1814 else
1815 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1816
1817 /* ebgp-multihop reset */
1818 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1819 group->conf->ttl = 255;
1820
1821 /* local-as reset */
1822 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1823 {
1824 group->conf->change_local_as = 0;
1825 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001826 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001827 }
1828 }
paulfee0f4c2004-09-13 05:12:46 +00001829
1830 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1831 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001832 struct listnode *pn;
1833
paulfee0f4c2004-09-13 05:12:46 +00001834 /* If it's not configured as RSERVER_CLIENT in any other address
1835 family, without being member of a peer_group, remove it from
1836 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001837 if (! peer_rsclient_active (peer)
1838 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001839 {
1840 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001841 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001842
1843 /* Clear our own rsclient rib for this afi/safi. */
1844 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001845 }
paulfee0f4c2004-09-13 05:12:46 +00001846
Paul Jakmab608d5b2008-07-02 02:12:07 +00001847 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001848
1849 /* Import policy. */
1850 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1851 {
1852 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1853 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1854 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1855 }
1856
1857 /* Export policy. */
1858 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1859 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1860 {
1861 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1862 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1863 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1864 }
1865 }
1866
paul718e3742002-12-13 20:15:29 +00001867 peer_group2peer_config_copy (group, peer, afi, safi);
1868
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001869 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001870 {
1871 peer->last_reset = PEER_DOWN_RMAP_BIND;
1872 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1873 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1874 }
paul718e3742002-12-13 20:15:29 +00001875 else
1876 BGP_EVENT_ADD (peer, BGP_Stop);
1877
1878 return 0;
1879}
1880
1881int
1882peer_group_unbind (struct bgp *bgp, struct peer *peer,
1883 struct peer_group *group, afi_t afi, safi_t safi)
1884{
1885 if (! peer->af_group[afi][safi])
1886 return 0;
1887
1888 if (group != peer->group)
1889 return BGP_ERR_PEER_GROUP_MISMATCH;
1890
1891 peer->af_group[afi][safi] = 0;
1892 peer->afc[afi][safi] = 0;
1893 peer_af_flag_reset (peer, afi, safi);
1894
paulfee0f4c2004-09-13 05:12:46 +00001895 if (peer->rib[afi][safi])
1896 peer->rib[afi][safi] = NULL;
1897
paul718e3742002-12-13 20:15:29 +00001898 if (! peer_group_active (peer))
1899 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001900 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001901 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001902 listnode_delete (group->peer, peer);
1903 peer->group = NULL;
1904 if (group->conf->as)
1905 {
1906 peer_delete (peer);
1907 return 0;
1908 }
1909 peer_global_config_reset (peer);
1910 }
1911
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001912 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001913 {
1914 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1915 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1916 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1917 }
paul718e3742002-12-13 20:15:29 +00001918 else
1919 BGP_EVENT_ADD (peer, BGP_Stop);
1920
1921 return 0;
1922}
David Lamparter6b0655a2014-06-04 06:53:35 +02001923
Vipin Kumardd49eb12014-09-30 14:36:38 -07001924
1925static int
1926bgp_startup_timer_expire (struct thread *thread)
1927{
1928 struct bgp *bgp;
1929
1930 bgp = THREAD_ARG (thread);
1931 bgp->t_startup = NULL;
1932
1933 return 0;
1934}
1935
paul718e3742002-12-13 20:15:29 +00001936/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001937static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001938bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001939{
1940 struct bgp *bgp;
1941 afi_t afi;
1942 safi_t safi;
1943
paul200df112005-06-01 11:17:05 +00001944 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1945 return NULL;
1946
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07001947 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00001948 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00001949 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00001950
1951 bgp->peer = list_new ();
1952 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1953
1954 bgp->group = list_new ();
1955 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1956
paulfee0f4c2004-09-13 05:12:46 +00001957 bgp->rsclient = list_new ();
1958 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1959
paul718e3742002-12-13 20:15:29 +00001960 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1961 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1962 {
Paul Jakma64e580a2006-02-21 01:09:01 +00001963 bgp->route[afi][safi] = bgp_table_init (afi, safi);
1964 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1965 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07001966 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
1967 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00001968 }
1969
1970 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1971 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1972 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001973 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1974 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001975
1976 bgp->as = *as;
1977
1978 if (name)
1979 bgp->name = strdup (name);
1980
Donald Sharp774914f2015-10-14 08:50:39 -04001981 THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire,
Vipin Kumardd49eb12014-09-30 14:36:38 -07001982 bgp, bgp->restart_time);
1983
paul718e3742002-12-13 20:15:29 +00001984 return bgp;
1985}
1986
1987/* Return first entry of BGP. */
1988struct bgp *
paul94f2b392005-06-28 12:44:16 +00001989bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001990{
1991 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001992 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001993 return NULL;
1994}
1995
1996/* Lookup BGP entry. */
1997struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001998bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001999{
2000 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002001 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002002
paul1eb8ef22005-04-07 07:30:20 +00002003 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002004 if (bgp->as == as
2005 && ((bgp->name == NULL && name == NULL)
2006 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
2007 return bgp;
2008 return NULL;
2009}
2010
2011/* Lookup BGP structure by view name. */
2012struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002013bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002014{
2015 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002016 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002017
paul1eb8ef22005-04-07 07:30:20 +00002018 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002019 if ((bgp->name == NULL && name == NULL)
2020 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2021 return bgp;
2022 return NULL;
2023}
2024
2025/* Called from VTY commands. */
2026int
paulfd79ac92004-10-13 05:06:08 +00002027bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002028{
2029 struct bgp *bgp;
2030
2031 /* Multiple instance check. */
2032 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2033 {
2034 if (name)
2035 bgp = bgp_lookup_by_name (name);
2036 else
2037 bgp = bgp_get_default ();
2038
2039 /* Already exists. */
2040 if (bgp)
2041 {
2042 if (bgp->as != *as)
2043 {
2044 *as = bgp->as;
2045 return BGP_ERR_INSTANCE_MISMATCH;
2046 }
2047 *bgp_val = bgp;
2048 return 0;
2049 }
2050 }
2051 else
2052 {
2053 /* BGP instance name can not be specified for single instance. */
2054 if (name)
2055 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2056
2057 /* Get default BGP structure if exists. */
2058 bgp = bgp_get_default ();
2059
2060 if (bgp)
2061 {
2062 if (bgp->as != *as)
2063 {
2064 *as = bgp->as;
2065 return BGP_ERR_AS_MISMATCH;
2066 }
2067 *bgp_val = bgp;
2068 return 0;
2069 }
2070 }
2071
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002072 bgp = bgp_create (as, name);
2073 bgp_router_id_set(bgp, &router_id_zebra);
2074 *bgp_val = bgp;
2075
Paul Jakmaad12dde2012-06-13 22:50:07 +01002076 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002077 if (list_isempty(bm->bgp)
2078 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002079 {
2080 if (bgp_socket (bm->port, bm->address) < 0)
2081 return BGP_ERR_INVALID_VALUE;
2082 }
2083
paul718e3742002-12-13 20:15:29 +00002084 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002085
2086 return 0;
2087}
2088
2089/* Delete BGP instance. */
2090int
2091bgp_delete (struct bgp *bgp)
2092{
2093 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002094 struct peer_group *group;
Denil Vira57cd5e72015-08-10 12:46:14 -07002095 struct listnode *node, *pnode;
2096 struct listnode *next, *pnext;
paul718e3742002-12-13 20:15:29 +00002097 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002098 int i;
2099
David Lampartercffe7802014-12-07 03:27:13 +01002100 THREAD_OFF (bgp->t_startup);
2101
paul718e3742002-12-13 20:15:29 +00002102 /* Delete static route. */
2103 bgp_static_delete (bgp);
2104
2105 /* Unset redistribution. */
2106 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2107 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2108 if (i != ZEBRA_ROUTE_BGP)
2109 bgp_redistribute_unset (bgp, afi, i);
2110
paul1eb8ef22005-04-07 07:30:20 +00002111 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002112 {
2113 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2114 {
2115 /* Send notify to remote peer. */
2116 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2117 }
2118
2119 peer_delete (peer);
2120 }
paul718e3742002-12-13 20:15:29 +00002121
Chris Caputo228da422009-07-18 05:44:03 +00002122 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002123 {
Denil Vira57cd5e72015-08-10 12:46:14 -07002124 for (ALL_LIST_ELEMENTS (group->peer, pnode, pnext, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002125 {
2126 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2127 {
2128 /* Send notify to remote peer. */
2129 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2130 }
2131 }
2132 peer_group_delete (group);
2133 }
Chris Caputo228da422009-07-18 05:44:03 +00002134
2135 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002136
2137 if (bgp->peer_self) {
2138 peer_delete(bgp->peer_self);
2139 bgp->peer_self = NULL;
2140 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002141
2142 /* Remove visibility via the master list - there may however still be
2143 * routes to be processed still referencing the struct bgp.
2144 */
2145 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002146 if (list_isempty(bm->bgp))
2147 bgp_close ();
2148
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002149 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002150
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002151 return 0;
2152}
2153
2154static void bgp_free (struct bgp *);
2155
2156void
2157bgp_lock (struct bgp *bgp)
2158{
2159 ++bgp->lock;
2160}
2161
2162void
2163bgp_unlock(struct bgp *bgp)
2164{
Chris Caputo228da422009-07-18 05:44:03 +00002165 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002166 if (--bgp->lock == 0)
2167 bgp_free (bgp);
2168}
2169
2170static void
2171bgp_free (struct bgp *bgp)
2172{
2173 afi_t afi;
2174 safi_t safi;
2175
2176 list_delete (bgp->group);
2177 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002178 list_delete (bgp->rsclient);
2179
paul718e3742002-12-13 20:15:29 +00002180 if (bgp->name)
2181 free (bgp->name);
2182
2183 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2184 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2185 {
2186 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002187 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002188 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002189 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002190 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002191 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002192 }
2193 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002194}
David Lamparter6b0655a2014-06-04 06:53:35 +02002195
paul718e3742002-12-13 20:15:29 +00002196struct peer *
2197peer_lookup (struct bgp *bgp, union sockunion *su)
2198{
2199 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002200 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002201
Steve Hillfc4dc592009-07-28 17:54:35 +01002202 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002203 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002204 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2205 if (sockunion_same (&peer->su, su)
2206 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2207 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002208 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002209 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002210 {
2211 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002212
Paul Jakma2158ad22009-07-28 18:10:55 +01002213 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2214 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2215 if (sockunion_same (&peer->su, su)
2216 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2217 return peer;
paul718e3742002-12-13 20:15:29 +00002218 }
2219 return NULL;
2220}
2221
2222struct peer *
2223peer_lookup_with_open (union sockunion *su, as_t remote_as,
2224 struct in_addr *remote_id, int *as)
2225{
2226 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002227 struct listnode *node;
2228 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002229 struct bgp *bgp;
2230
Steve Hillfc4dc592009-07-28 17:54:35 +01002231 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002232 return NULL;
2233
Paul Jakma9d878772009-08-05 16:25:16 +01002234 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002235 {
Paul Jakma9d878772009-08-05 16:25:16 +01002236 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2237 {
2238 if (sockunion_same (&peer->su, su)
2239 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2240 {
2241 if (peer->as == remote_as
2242 && peer->remote_id.s_addr == remote_id->s_addr)
2243 return peer;
2244 if (peer->as == remote_as)
2245 *as = 1;
2246 }
2247 }
2248
2249 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2250 {
2251 if (sockunion_same (&peer->su, su)
2252 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2253 {
2254 if (peer->as == remote_as
2255 && peer->remote_id.s_addr == 0)
2256 return peer;
2257 if (peer->as == remote_as)
2258 *as = 1;
2259 }
2260 }
paul718e3742002-12-13 20:15:29 +00002261 }
2262 return NULL;
2263}
David Lamparter6b0655a2014-06-04 06:53:35 +02002264
paul718e3742002-12-13 20:15:29 +00002265/* If peer is configured at least one address family return 1. */
2266int
2267peer_active (struct peer *peer)
2268{
2269 if (peer->afc[AFI_IP][SAFI_UNICAST]
2270 || peer->afc[AFI_IP][SAFI_MULTICAST]
2271 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2272 || peer->afc[AFI_IP6][SAFI_UNICAST]
2273 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2274 return 1;
2275 return 0;
2276}
2277
2278/* If peer is negotiated at least one address family return 1. */
2279int
2280peer_active_nego (struct peer *peer)
2281{
2282 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2283 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2284 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2285 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2286 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2287 return 1;
2288 return 0;
2289}
David Lamparter6b0655a2014-06-04 06:53:35 +02002290
paul718e3742002-12-13 20:15:29 +00002291/* peer_flag_change_type. */
2292enum peer_change_type
2293{
2294 peer_change_none,
2295 peer_change_reset,
2296 peer_change_reset_in,
2297 peer_change_reset_out,
2298};
2299
paul94f2b392005-06-28 12:44:16 +00002300static void
paul718e3742002-12-13 20:15:29 +00002301peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2302 enum peer_change_type type)
2303{
2304 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2305 return;
2306
Stephen Hemmingerd9d4ae52010-01-13 00:32:39 +00002307 if (peer->status != Established)
2308 return;
2309
paul718e3742002-12-13 20:15:29 +00002310 if (type == peer_change_reset)
2311 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2312 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2313 else if (type == peer_change_reset_in)
2314 {
2315 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2316 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2317 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2318 else
2319 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2320 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2321 }
2322 else if (type == peer_change_reset_out)
2323 bgp_announce_route (peer, afi, safi);
2324}
2325
2326struct peer_flag_action
2327{
2328 /* Peer's flag. */
2329 u_int32_t flag;
2330
2331 /* This flag can be set for peer-group member. */
2332 u_char not_for_member;
2333
2334 /* Action when the flag is changed. */
2335 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002336
2337 /* Peer down cause */
2338 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002339};
2340
Stephen Hemminger03621952009-07-21 16:27:20 -07002341static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002342 {
2343 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2344 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2345 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2346 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2347 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002348 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002349 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002350 { 0, 0, 0 }
2351 };
2352
Stephen Hemminger03621952009-07-21 16:27:20 -07002353static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002354 {
2355 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2356 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2357 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2358 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2359 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2360 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2361 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2362 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2363 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2364 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2365 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2366 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2367 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002368 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
Timo Teräs9e7a53c2014-04-24 10:22:37 +03002369 { PEER_FLAG_NEXTHOP_SELF_ALL, 1, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002370 { 0, 0, 0 }
2371 };
2372
2373/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002374static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002375peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002376 struct peer_flag_action *action, u_int32_t flag)
2377{
2378 int i;
2379 int found = 0;
2380 int reset_in = 0;
2381 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002382 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002383
2384 /* Check peer's frag action. */
2385 for (i = 0; i < size; i++)
2386 {
2387 match = &action_list[i];
2388
2389 if (match->flag == 0)
2390 break;
2391
2392 if (match->flag & flag)
2393 {
2394 found = 1;
2395
2396 if (match->type == peer_change_reset_in)
2397 reset_in = 1;
2398 if (match->type == peer_change_reset_out)
2399 reset_out = 1;
2400 if (match->type == peer_change_reset)
2401 {
2402 reset_in = 1;
2403 reset_out = 1;
2404 }
2405 if (match->not_for_member)
2406 action->not_for_member = 1;
2407 }
2408 }
2409
2410 /* Set peer clear type. */
2411 if (reset_in && reset_out)
2412 action->type = peer_change_reset;
2413 else if (reset_in)
2414 action->type = peer_change_reset_in;
2415 else if (reset_out)
2416 action->type = peer_change_reset_out;
2417 else
2418 action->type = peer_change_none;
2419
2420 return found;
2421}
2422
paul94f2b392005-06-28 12:44:16 +00002423static void
paul718e3742002-12-13 20:15:29 +00002424peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2425{
2426 if (flag == PEER_FLAG_SHUTDOWN)
2427 {
2428 if (CHECK_FLAG (peer->flags, flag))
2429 {
hasso93406d82005-02-02 14:40:33 +00002430 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2431 peer_nsf_stop (peer);
2432
hasso0a486e52005-02-01 20:57:17 +00002433 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2434 if (peer->t_pmax_restart)
2435 {
2436 BGP_TIMER_OFF (peer->t_pmax_restart);
2437 if (BGP_DEBUG (events, EVENTS))
2438 zlog_debug ("%s Maximum-prefix restart timer canceled",
2439 peer->host);
2440 }
2441
hasso93406d82005-02-02 14:40:33 +00002442 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2443 peer_nsf_stop (peer);
2444
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002445 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002446 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2447 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2448 else
2449 BGP_EVENT_ADD (peer, BGP_Stop);
2450 }
2451 else
2452 {
2453 peer->v_start = BGP_INIT_START_TIMER;
2454 BGP_EVENT_ADD (peer, BGP_Stop);
2455 }
2456 }
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002457 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002458 {
hassoc9502432005-02-01 22:01:48 +00002459 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2460 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2461 else if (flag == PEER_FLAG_PASSIVE)
2462 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002463 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002464 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002465
hassoc9502432005-02-01 22:01:48 +00002466 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2467 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002468 }
2469 else
2470 BGP_EVENT_ADD (peer, BGP_Stop);
2471}
2472
2473/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002474static int
paul718e3742002-12-13 20:15:29 +00002475peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2476{
2477 int found;
2478 int size;
2479 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002480 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002481 struct peer_flag_action action;
2482
2483 memset (&action, 0, sizeof (struct peer_flag_action));
2484 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2485
2486 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2487
2488 /* No flag action is found. */
2489 if (! found)
2490 return BGP_ERR_INVALID_FLAG;
2491
2492 /* Not for peer-group member. */
2493 if (action.not_for_member && peer_group_active (peer))
2494 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2495
2496 /* When unset the peer-group member's flag we have to check
2497 peer-group configuration. */
2498 if (! set && peer_group_active (peer))
2499 if (CHECK_FLAG (peer->group->conf->flags, flag))
2500 {
2501 if (flag == PEER_FLAG_SHUTDOWN)
2502 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2503 else
2504 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2505 }
2506
2507 /* Flag conflict check. */
2508 if (set
2509 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2510 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2511 return BGP_ERR_PEER_FLAG_CONFLICT;
2512
2513 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2514 {
2515 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2516 return 0;
2517 if (! set && ! CHECK_FLAG (peer->flags, flag))
2518 return 0;
2519 }
2520
2521 if (set)
2522 SET_FLAG (peer->flags, flag);
2523 else
2524 UNSET_FLAG (peer->flags, flag);
2525
2526 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2527 {
2528 if (action.type == peer_change_reset)
2529 peer_flag_modify_action (peer, flag);
2530
2531 return 0;
2532 }
2533
2534 /* peer-group member updates. */
2535 group = peer->group;
2536
paul1eb8ef22005-04-07 07:30:20 +00002537 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002538 {
2539 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2540 continue;
2541
2542 if (! set && ! CHECK_FLAG (peer->flags, flag))
2543 continue;
2544
2545 if (set)
2546 SET_FLAG (peer->flags, flag);
2547 else
2548 UNSET_FLAG (peer->flags, flag);
2549
2550 if (action.type == peer_change_reset)
2551 peer_flag_modify_action (peer, flag);
2552 }
2553 return 0;
2554}
2555
2556int
2557peer_flag_set (struct peer *peer, u_int32_t flag)
2558{
2559 return peer_flag_modify (peer, flag, 1);
2560}
2561
2562int
2563peer_flag_unset (struct peer *peer, u_int32_t flag)
2564{
2565 return peer_flag_modify (peer, flag, 0);
2566}
2567
paul94f2b392005-06-28 12:44:16 +00002568static int
paul718e3742002-12-13 20:15:29 +00002569peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2570{
2571 if (peer->af_group[afi][safi])
2572 return 1;
2573 return 0;
2574}
2575
paul94f2b392005-06-28 12:44:16 +00002576static int
paul718e3742002-12-13 20:15:29 +00002577peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2578 int set)
2579{
2580 int found;
2581 int size;
paul1eb8ef22005-04-07 07:30:20 +00002582 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002583 struct peer_group *group;
2584 struct peer_flag_action action;
2585
2586 memset (&action, 0, sizeof (struct peer_flag_action));
2587 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2588
2589 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2590
2591 /* No flag action is found. */
2592 if (! found)
2593 return BGP_ERR_INVALID_FLAG;
2594
2595 /* Adress family must be activated. */
2596 if (! peer->afc[afi][safi])
2597 return BGP_ERR_PEER_INACTIVE;
2598
2599 /* Not for peer-group member. */
2600 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2601 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2602
2603 /* Spcecial check for reflector client. */
2604 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2605 && peer_sort (peer) != BGP_PEER_IBGP)
2606 return BGP_ERR_NOT_INTERNAL_PEER;
2607
2608 /* Spcecial check for remove-private-AS. */
2609 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2610 && peer_sort (peer) == BGP_PEER_IBGP)
2611 return BGP_ERR_REMOVE_PRIVATE_AS;
2612
2613 /* When unset the peer-group member's flag we have to check
2614 peer-group configuration. */
2615 if (! set && peer->af_group[afi][safi])
2616 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2617 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2618
2619 /* When current flag configuration is same as requested one. */
2620 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2621 {
2622 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2623 return 0;
2624 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2625 return 0;
2626 }
2627
2628 if (set)
2629 SET_FLAG (peer->af_flags[afi][safi], flag);
2630 else
2631 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2632
2633 /* Execute action when peer is established. */
2634 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2635 && peer->status == Established)
2636 {
2637 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2638 bgp_clear_adj_in (peer, afi, safi);
2639 else
hassoe0701b72004-05-20 09:19:34 +00002640 {
2641 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2642 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2643 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2644 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2645 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2646 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2647 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2648 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2649
2650 peer_change_action (peer, afi, safi, action.type);
2651 }
2652
paul718e3742002-12-13 20:15:29 +00002653 }
2654
2655 /* Peer group member updates. */
2656 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2657 {
2658 group = peer->group;
2659
paul1eb8ef22005-04-07 07:30:20 +00002660 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002661 {
2662 if (! peer->af_group[afi][safi])
2663 continue;
2664
2665 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2666 continue;
2667
2668 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2669 continue;
2670
2671 if (set)
2672 SET_FLAG (peer->af_flags[afi][safi], flag);
2673 else
2674 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2675
2676 if (peer->status == Established)
2677 {
2678 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2679 bgp_clear_adj_in (peer, afi, safi);
2680 else
hassoe0701b72004-05-20 09:19:34 +00002681 {
2682 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2683 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2684 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2685 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2686 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2687 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2688 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2689 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2690
2691 peer_change_action (peer, afi, safi, action.type);
2692 }
paul718e3742002-12-13 20:15:29 +00002693 }
2694 }
2695 }
2696 return 0;
2697}
2698
2699int
2700peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2701{
2702 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2703}
2704
2705int
2706peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2707{
2708 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2709}
David Lamparter6b0655a2014-06-04 06:53:35 +02002710
paul718e3742002-12-13 20:15:29 +00002711/* EBGP multihop configuration. */
2712int
2713peer_ebgp_multihop_set (struct peer *peer, int ttl)
2714{
2715 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002716 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002717 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002718
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002719 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002720 return 0;
2721
Nick Hilliardfa411a22011-03-23 15:33:17 +00002722 /* see comment in peer_ttl_security_hops_set() */
2723 if (ttl != MAXTTL)
2724 {
2725 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2726 {
2727 group = peer->group;
2728 if (group->conf->gtsm_hops != 0)
2729 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2730
2731 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2732 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002733 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002734 continue;
2735
2736 if (peer1->gtsm_hops != 0)
2737 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2738 }
2739 }
2740 else
2741 {
2742 if (peer->gtsm_hops != 0)
2743 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2744 }
2745 }
2746
paul718e3742002-12-13 20:15:29 +00002747 peer->ttl = ttl;
2748
2749 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2750 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002751 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002752 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002753 }
2754 else
2755 {
2756 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002757 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002758 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002759 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002760 continue;
paul718e3742002-12-13 20:15:29 +00002761
pauleb821182004-05-01 08:44:08 +00002762 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002763
pauleb821182004-05-01 08:44:08 +00002764 if (peer->fd >= 0)
2765 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2766 }
paul718e3742002-12-13 20:15:29 +00002767 }
2768 return 0;
2769}
2770
2771int
2772peer_ebgp_multihop_unset (struct peer *peer)
2773{
2774 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002775 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002776
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002777 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002778 return 0;
2779
Nick Hilliardfa411a22011-03-23 15:33:17 +00002780 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2781 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2782
paul718e3742002-12-13 20:15:29 +00002783 if (peer_group_active (peer))
2784 peer->ttl = peer->group->conf->ttl;
2785 else
2786 peer->ttl = 1;
2787
2788 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2789 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002790 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002791 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002792 }
2793 else
2794 {
2795 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002796 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002797 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002798 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002799 continue;
paul718e3742002-12-13 20:15:29 +00002800
pauleb821182004-05-01 08:44:08 +00002801 peer->ttl = 1;
2802
2803 if (peer->fd >= 0)
2804 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2805 }
paul718e3742002-12-13 20:15:29 +00002806 }
2807 return 0;
2808}
David Lamparter6b0655a2014-06-04 06:53:35 +02002809
paul718e3742002-12-13 20:15:29 +00002810/* Neighbor description. */
2811int
2812peer_description_set (struct peer *peer, char *desc)
2813{
2814 if (peer->desc)
2815 XFREE (MTYPE_PEER_DESC, peer->desc);
2816
2817 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2818
2819 return 0;
2820}
2821
2822int
2823peer_description_unset (struct peer *peer)
2824{
2825 if (peer->desc)
2826 XFREE (MTYPE_PEER_DESC, peer->desc);
2827
2828 peer->desc = NULL;
2829
2830 return 0;
2831}
David Lamparter6b0655a2014-06-04 06:53:35 +02002832
paul718e3742002-12-13 20:15:29 +00002833/* Neighbor update-source. */
2834int
paulfd79ac92004-10-13 05:06:08 +00002835peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002836{
2837 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002838 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002839
2840 if (peer->update_if)
2841 {
2842 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2843 && strcmp (peer->update_if, ifname) == 0)
2844 return 0;
2845
2846 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2847 peer->update_if = NULL;
2848 }
2849
2850 if (peer->update_source)
2851 {
2852 sockunion_free (peer->update_source);
2853 peer->update_source = NULL;
2854 }
2855
2856 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2857
2858 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2859 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002860 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002861 {
2862 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2863 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2864 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2865 }
paul718e3742002-12-13 20:15:29 +00002866 else
2867 BGP_EVENT_ADD (peer, BGP_Stop);
2868 return 0;
2869 }
2870
2871 /* peer-group member updates. */
2872 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002873 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002874 {
2875 if (peer->update_if)
2876 {
2877 if (strcmp (peer->update_if, ifname) == 0)
2878 continue;
2879
2880 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2881 peer->update_if = NULL;
2882 }
2883
2884 if (peer->update_source)
2885 {
2886 sockunion_free (peer->update_source);
2887 peer->update_source = NULL;
2888 }
2889
2890 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2891
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002892 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002893 {
2894 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2895 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2896 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2897 }
paul718e3742002-12-13 20:15:29 +00002898 else
2899 BGP_EVENT_ADD (peer, BGP_Stop);
2900 }
2901 return 0;
2902}
2903
2904int
2905peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2906{
2907 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002908 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002909
2910 if (peer->update_source)
2911 {
2912 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2913 && sockunion_cmp (peer->update_source, su) == 0)
2914 return 0;
2915 sockunion_free (peer->update_source);
2916 peer->update_source = NULL;
2917 }
2918
2919 if (peer->update_if)
2920 {
2921 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2922 peer->update_if = NULL;
2923 }
2924
2925 peer->update_source = sockunion_dup (su);
2926
2927 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2928 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002929 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002930 {
2931 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2932 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2933 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2934 }
paul718e3742002-12-13 20:15:29 +00002935 else
2936 BGP_EVENT_ADD (peer, BGP_Stop);
2937 return 0;
2938 }
2939
2940 /* peer-group member updates. */
2941 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002942 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002943 {
2944 if (peer->update_source)
2945 {
2946 if (sockunion_cmp (peer->update_source, su) == 0)
2947 continue;
2948 sockunion_free (peer->update_source);
2949 peer->update_source = NULL;
2950 }
2951
2952 if (peer->update_if)
2953 {
2954 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2955 peer->update_if = NULL;
2956 }
2957
2958 peer->update_source = sockunion_dup (su);
2959
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002960 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002961 {
2962 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2963 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2964 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2965 }
paul718e3742002-12-13 20:15:29 +00002966 else
2967 BGP_EVENT_ADD (peer, BGP_Stop);
2968 }
2969 return 0;
2970}
2971
2972int
2973peer_update_source_unset (struct peer *peer)
2974{
2975 union sockunion *su;
2976 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002977 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002978
2979 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2980 && ! peer->update_source
2981 && ! peer->update_if)
2982 return 0;
2983
2984 if (peer->update_source)
2985 {
2986 sockunion_free (peer->update_source);
2987 peer->update_source = NULL;
2988 }
2989 if (peer->update_if)
2990 {
2991 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2992 peer->update_if = NULL;
2993 }
2994
2995 if (peer_group_active (peer))
2996 {
2997 group = peer->group;
2998
2999 if (group->conf->update_source)
3000 {
3001 su = sockunion_dup (group->conf->update_source);
3002 peer->update_source = su;
3003 }
3004 else if (group->conf->update_if)
3005 peer->update_if =
3006 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
3007 }
3008
3009 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3010 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003011 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003012 {
3013 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3014 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3015 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3016 }
paul718e3742002-12-13 20:15:29 +00003017 else
3018 BGP_EVENT_ADD (peer, BGP_Stop);
3019 return 0;
3020 }
3021
3022 /* peer-group member updates. */
3023 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003024 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003025 {
3026 if (! peer->update_source && ! peer->update_if)
3027 continue;
3028
3029 if (peer->update_source)
3030 {
3031 sockunion_free (peer->update_source);
3032 peer->update_source = NULL;
3033 }
3034
3035 if (peer->update_if)
3036 {
3037 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3038 peer->update_if = NULL;
3039 }
3040
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003041 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003042 {
3043 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3044 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3045 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3046 }
paul718e3742002-12-13 20:15:29 +00003047 else
3048 BGP_EVENT_ADD (peer, BGP_Stop);
3049 }
3050 return 0;
3051}
David Lamparter6b0655a2014-06-04 06:53:35 +02003052
paul718e3742002-12-13 20:15:29 +00003053int
3054peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003055 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003056{
3057 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003058 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003059
3060 /* Adress family must be activated. */
3061 if (! peer->afc[afi][safi])
3062 return BGP_ERR_PEER_INACTIVE;
3063
3064 /* Default originate can't be used for peer group memeber. */
3065 if (peer_is_group_member (peer, afi, safi))
3066 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3067
3068 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3069 || (rmap && ! peer->default_rmap[afi][safi].name)
3070 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3071 {
3072 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3073
3074 if (rmap)
3075 {
3076 if (peer->default_rmap[afi][safi].name)
3077 free (peer->default_rmap[afi][safi].name);
3078 peer->default_rmap[afi][safi].name = strdup (rmap);
3079 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3080 }
3081 }
3082
3083 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3084 {
3085 if (peer->status == Established && peer->afc_nego[afi][safi])
3086 bgp_default_originate (peer, afi, safi, 0);
3087 return 0;
3088 }
3089
3090 /* peer-group member updates. */
3091 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003092 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003093 {
3094 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3095
3096 if (rmap)
3097 {
3098 if (peer->default_rmap[afi][safi].name)
3099 free (peer->default_rmap[afi][safi].name);
3100 peer->default_rmap[afi][safi].name = strdup (rmap);
3101 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3102 }
3103
3104 if (peer->status == Established && peer->afc_nego[afi][safi])
3105 bgp_default_originate (peer, afi, safi, 0);
3106 }
3107 return 0;
3108}
3109
3110int
3111peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3112{
3113 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003114 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003115
3116 /* Adress family must be activated. */
3117 if (! peer->afc[afi][safi])
3118 return BGP_ERR_PEER_INACTIVE;
3119
3120 /* Default originate can't be used for peer group memeber. */
3121 if (peer_is_group_member (peer, afi, safi))
3122 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3123
3124 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3125 {
3126 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3127
3128 if (peer->default_rmap[afi][safi].name)
3129 free (peer->default_rmap[afi][safi].name);
3130 peer->default_rmap[afi][safi].name = NULL;
3131 peer->default_rmap[afi][safi].map = NULL;
3132 }
3133
3134 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3135 {
3136 if (peer->status == Established && peer->afc_nego[afi][safi])
3137 bgp_default_originate (peer, afi, safi, 1);
3138 return 0;
3139 }
3140
3141 /* peer-group member updates. */
3142 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003143 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003144 {
3145 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3146
3147 if (peer->default_rmap[afi][safi].name)
3148 free (peer->default_rmap[afi][safi].name);
3149 peer->default_rmap[afi][safi].name = NULL;
3150 peer->default_rmap[afi][safi].map = NULL;
3151
3152 if (peer->status == Established && peer->afc_nego[afi][safi])
3153 bgp_default_originate (peer, afi, safi, 1);
3154 }
3155 return 0;
3156}
David Lamparter6b0655a2014-06-04 06:53:35 +02003157
paul718e3742002-12-13 20:15:29 +00003158int
3159peer_port_set (struct peer *peer, u_int16_t port)
3160{
3161 peer->port = port;
3162 return 0;
3163}
3164
3165int
3166peer_port_unset (struct peer *peer)
3167{
3168 peer->port = BGP_PORT_DEFAULT;
3169 return 0;
3170}
David Lamparter6b0655a2014-06-04 06:53:35 +02003171
paul718e3742002-12-13 20:15:29 +00003172/* neighbor weight. */
3173int
3174peer_weight_set (struct peer *peer, u_int16_t weight)
3175{
3176 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003177 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003178
3179 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3180 peer->weight = weight;
3181
3182 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3183 return 0;
3184
3185 /* peer-group member updates. */
3186 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003187 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003188 {
3189 peer->weight = group->conf->weight;
3190 }
3191 return 0;
3192}
3193
3194int
3195peer_weight_unset (struct peer *peer)
3196{
3197 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003198 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003199
3200 /* Set default weight. */
3201 if (peer_group_active (peer))
3202 peer->weight = peer->group->conf->weight;
3203 else
3204 peer->weight = 0;
3205
3206 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3207
3208 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3209 return 0;
3210
3211 /* peer-group member updates. */
3212 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003213 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003214 {
3215 peer->weight = 0;
3216 }
3217 return 0;
3218}
David Lamparter6b0655a2014-06-04 06:53:35 +02003219
paul718e3742002-12-13 20:15:29 +00003220int
3221peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3222{
3223 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003224 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003225
3226 /* Not for peer group memeber. */
3227 if (peer_group_active (peer))
3228 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3229
3230 /* keepalive value check. */
3231 if (keepalive > 65535)
3232 return BGP_ERR_INVALID_VALUE;
3233
3234 /* Holdtime value check. */
3235 if (holdtime > 65535)
3236 return BGP_ERR_INVALID_VALUE;
3237
3238 /* Holdtime value must be either 0 or greater than 3. */
3239 if (holdtime < 3 && holdtime != 0)
3240 return BGP_ERR_INVALID_VALUE;
3241
3242 /* Set value to the configuration. */
3243 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3244 peer->holdtime = holdtime;
3245 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3246
3247 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3248 return 0;
3249
3250 /* peer-group member updates. */
3251 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003252 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003253 {
3254 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3255 peer->holdtime = group->conf->holdtime;
3256 peer->keepalive = group->conf->keepalive;
3257 }
3258 return 0;
3259}
3260
3261int
3262peer_timers_unset (struct peer *peer)
3263{
3264 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003265 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003266
3267 if (peer_group_active (peer))
3268 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3269
3270 /* Clear configuration. */
3271 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3272 peer->keepalive = 0;
3273 peer->holdtime = 0;
3274
3275 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3276 return 0;
3277
3278 /* peer-group member updates. */
3279 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003280 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003281 {
3282 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3283 peer->holdtime = 0;
3284 peer->keepalive = 0;
3285 }
3286
3287 return 0;
3288}
David Lamparter6b0655a2014-06-04 06:53:35 +02003289
paul718e3742002-12-13 20:15:29 +00003290int
3291peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3292{
3293 if (peer_group_active (peer))
3294 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3295
3296 if (connect > 65535)
3297 return BGP_ERR_INVALID_VALUE;
3298
3299 /* Set value to the configuration. */
3300 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3301 peer->connect = connect;
3302
3303 /* Set value to timer setting. */
3304 peer->v_connect = connect;
3305
3306 return 0;
3307}
3308
3309int
3310peer_timers_connect_unset (struct peer *peer)
3311{
3312 if (peer_group_active (peer))
3313 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3314
3315 /* Clear configuration. */
3316 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3317 peer->connect = 0;
3318
3319 /* Set timer setting to default value. */
3320 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3321
3322 return 0;
3323}
David Lamparter6b0655a2014-06-04 06:53:35 +02003324
paul718e3742002-12-13 20:15:29 +00003325int
3326peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3327{
3328 if (peer_group_active (peer))
3329 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3330
3331 if (routeadv > 600)
3332 return BGP_ERR_INVALID_VALUE;
3333
3334 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3335 peer->routeadv = routeadv;
3336 peer->v_routeadv = routeadv;
3337
3338 return 0;
3339}
3340
3341int
3342peer_advertise_interval_unset (struct peer *peer)
3343{
3344 if (peer_group_active (peer))
3345 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3346
3347 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3348 peer->routeadv = 0;
3349
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003350 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003351 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3352 else
3353 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3354
3355 return 0;
3356}
David Lamparter6b0655a2014-06-04 06:53:35 +02003357
paul718e3742002-12-13 20:15:29 +00003358/* neighbor interface */
3359int
paulfd79ac92004-10-13 05:06:08 +00003360peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003361{
3362 if (peer->ifname)
3363 free (peer->ifname);
3364 peer->ifname = strdup (str);
3365
3366 return 0;
3367}
3368
3369int
3370peer_interface_unset (struct peer *peer)
3371{
3372 if (peer->ifname)
3373 free (peer->ifname);
3374 peer->ifname = NULL;
3375
3376 return 0;
3377}
David Lamparter6b0655a2014-06-04 06:53:35 +02003378
paul718e3742002-12-13 20:15:29 +00003379/* Allow-as in. */
3380int
3381peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3382{
3383 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003384 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003385
3386 if (allow_num < 1 || allow_num > 10)
3387 return BGP_ERR_INVALID_VALUE;
3388
3389 if (peer->allowas_in[afi][safi] != allow_num)
3390 {
3391 peer->allowas_in[afi][safi] = allow_num;
3392 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3393 peer_change_action (peer, afi, safi, peer_change_reset_in);
3394 }
3395
3396 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3397 return 0;
3398
3399 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003400 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003401 {
3402 if (peer->allowas_in[afi][safi] != allow_num)
3403 {
3404 peer->allowas_in[afi][safi] = allow_num;
3405 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3406 peer_change_action (peer, afi, safi, peer_change_reset_in);
3407 }
3408
3409 }
3410 return 0;
3411}
3412
3413int
3414peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3415{
3416 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003417 struct listnode *node, *nnode;
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 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3426 return 0;
3427
3428 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003429 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003430 {
3431 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3432 {
3433 peer->allowas_in[afi][safi] = 0;
3434 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3435 }
3436 }
3437 return 0;
3438}
David Lamparter6b0655a2014-06-04 06:53:35 +02003439
paul718e3742002-12-13 20:15:29 +00003440int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003441peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003442{
3443 struct bgp *bgp = peer->bgp;
3444 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003445 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003446
3447 if (peer_sort (peer) != BGP_PEER_EBGP
3448 && peer_sort (peer) != BGP_PEER_INTERNAL)
3449 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3450
3451 if (bgp->as == as)
3452 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3453
3454 if (peer_group_active (peer))
3455 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3456
Andrew Certain9d3f9702012-11-07 23:50:07 +00003457 if (peer->as == as)
3458 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3459
paul718e3742002-12-13 20:15:29 +00003460 if (peer->change_local_as == as &&
3461 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003462 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3463 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3464 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003465 return 0;
3466
3467 peer->change_local_as = as;
3468 if (no_prepend)
3469 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3470 else
3471 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3472
Andrew Certain9d3f9702012-11-07 23:50:07 +00003473 if (replace_as)
3474 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3475 else
3476 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3477
paul718e3742002-12-13 20:15:29 +00003478 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3479 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003480 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003481 {
3482 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3483 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3484 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3485 }
paul718e3742002-12-13 20:15:29 +00003486 else
3487 BGP_EVENT_ADD (peer, BGP_Stop);
3488
3489 return 0;
3490 }
3491
3492 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003493 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003494 {
3495 peer->change_local_as = as;
3496 if (no_prepend)
3497 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3498 else
3499 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3500
Andrew Certain9d3f9702012-11-07 23:50:07 +00003501 if (replace_as)
3502 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3503 else
3504 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3505
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003506 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003507 {
3508 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3509 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3510 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3511 }
paul718e3742002-12-13 20:15:29 +00003512 else
3513 BGP_EVENT_ADD (peer, BGP_Stop);
3514 }
3515
3516 return 0;
3517}
3518
3519int
3520peer_local_as_unset (struct peer *peer)
3521{
3522 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003523 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003524
3525 if (peer_group_active (peer))
3526 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3527
3528 if (! peer->change_local_as)
3529 return 0;
3530
3531 peer->change_local_as = 0;
3532 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003533 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003534
3535 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3536 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003537 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003538 {
3539 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3540 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3541 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3542 }
paul718e3742002-12-13 20:15:29 +00003543 else
3544 BGP_EVENT_ADD (peer, BGP_Stop);
3545
3546 return 0;
3547 }
3548
3549 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003550 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003551 {
3552 peer->change_local_as = 0;
3553 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003554 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003555
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003556 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003557 {
3558 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3559 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3560 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3561 }
paul718e3742002-12-13 20:15:29 +00003562 else
3563 BGP_EVENT_ADD (peer, BGP_Stop);
3564 }
3565 return 0;
3566}
David Lamparter6b0655a2014-06-04 06:53:35 +02003567
Paul Jakma0df7c912008-07-21 21:02:49 +00003568/* Set password for authenticating with the peer. */
3569int
3570peer_password_set (struct peer *peer, const char *password)
3571{
3572 struct listnode *nn, *nnode;
3573 int len = password ? strlen(password) : 0;
3574 int ret = BGP_SUCCESS;
3575
3576 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3577 return BGP_ERR_INVALID_VALUE;
3578
3579 if (peer->password && strcmp (peer->password, password) == 0
3580 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3581 return 0;
3582
3583 if (peer->password)
3584 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3585
3586 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3587
3588 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3589 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003590 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3591 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
Paul Jakma0df7c912008-07-21 21:02:49 +00003592 else
3593 BGP_EVENT_ADD (peer, BGP_Stop);
3594
3595 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3596 }
3597
3598 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3599 {
3600 if (peer->password && strcmp (peer->password, password) == 0)
3601 continue;
3602
3603 if (peer->password)
3604 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3605
3606 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3607
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003608 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003609 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3610 else
3611 BGP_EVENT_ADD (peer, BGP_Stop);
3612
3613 if (bgp_md5_set (peer) < 0)
3614 ret = BGP_ERR_TCPSIG_FAILED;
3615 }
3616
3617 return ret;
3618}
3619
3620int
3621peer_password_unset (struct peer *peer)
3622{
3623 struct listnode *nn, *nnode;
3624
3625 if (!peer->password
3626 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3627 return 0;
3628
3629 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3630 {
3631 if (peer_group_active (peer)
3632 && peer->group->conf->password
3633 && strcmp (peer->group->conf->password, peer->password) == 0)
3634 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3635
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003636 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003637 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3638 else
3639 BGP_EVENT_ADD (peer, BGP_Stop);
3640
3641 if (peer->password)
3642 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3643
3644 peer->password = NULL;
3645
3646 bgp_md5_set (peer);
3647
3648 return 0;
3649 }
3650
3651 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3652 peer->password = NULL;
3653
3654 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3655 {
3656 if (!peer->password)
3657 continue;
3658
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003659 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003660 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3661 else
3662 BGP_EVENT_ADD (peer, BGP_Stop);
3663
3664 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3665 peer->password = NULL;
3666
3667 bgp_md5_set (peer);
3668 }
3669
3670 return 0;
3671}
David Lamparter6b0655a2014-06-04 06:53:35 +02003672
paul718e3742002-12-13 20:15:29 +00003673/* Set distribute list to the peer. */
3674int
3675peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003676 const char *name)
paul718e3742002-12-13 20:15:29 +00003677{
3678 struct bgp_filter *filter;
3679 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003680 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003681
3682 if (! peer->afc[afi][safi])
3683 return BGP_ERR_PEER_INACTIVE;
3684
3685 if (direct != FILTER_IN && direct != FILTER_OUT)
3686 return BGP_ERR_INVALID_VALUE;
3687
3688 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3689 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3690
3691 filter = &peer->filter[afi][safi];
3692
3693 if (filter->plist[direct].name)
3694 return BGP_ERR_PEER_FILTER_CONFLICT;
3695
3696 if (filter->dlist[direct].name)
3697 free (filter->dlist[direct].name);
3698 filter->dlist[direct].name = strdup (name);
3699 filter->dlist[direct].alist = access_list_lookup (afi, name);
3700
3701 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3702 return 0;
3703
3704 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003705 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003706 {
3707 filter = &peer->filter[afi][safi];
3708
3709 if (! peer->af_group[afi][safi])
3710 continue;
3711
3712 if (filter->dlist[direct].name)
3713 free (filter->dlist[direct].name);
3714 filter->dlist[direct].name = strdup (name);
3715 filter->dlist[direct].alist = access_list_lookup (afi, name);
3716 }
3717
3718 return 0;
3719}
3720
3721int
3722peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3723{
3724 struct bgp_filter *filter;
3725 struct bgp_filter *gfilter;
3726 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003727 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003728
3729 if (! peer->afc[afi][safi])
3730 return BGP_ERR_PEER_INACTIVE;
3731
3732 if (direct != FILTER_IN && direct != FILTER_OUT)
3733 return BGP_ERR_INVALID_VALUE;
3734
3735 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3736 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3737
3738 filter = &peer->filter[afi][safi];
3739
3740 /* apply peer-group filter */
3741 if (peer->af_group[afi][safi])
3742 {
3743 gfilter = &peer->group->conf->filter[afi][safi];
3744
3745 if (gfilter->dlist[direct].name)
3746 {
3747 if (filter->dlist[direct].name)
3748 free (filter->dlist[direct].name);
3749 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3750 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3751 return 0;
3752 }
3753 }
3754
3755 if (filter->dlist[direct].name)
3756 free (filter->dlist[direct].name);
3757 filter->dlist[direct].name = NULL;
3758 filter->dlist[direct].alist = NULL;
3759
3760 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3761 return 0;
3762
3763 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003764 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003765 {
3766 filter = &peer->filter[afi][safi];
3767
3768 if (! peer->af_group[afi][safi])
3769 continue;
3770
3771 if (filter->dlist[direct].name)
3772 free (filter->dlist[direct].name);
3773 filter->dlist[direct].name = NULL;
3774 filter->dlist[direct].alist = NULL;
3775 }
3776
3777 return 0;
3778}
3779
3780/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003781static void
paul718e3742002-12-13 20:15:29 +00003782peer_distribute_update (struct access_list *access)
3783{
3784 afi_t afi;
3785 safi_t safi;
3786 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003787 struct listnode *mnode, *mnnode;
3788 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003789 struct bgp *bgp;
3790 struct peer *peer;
3791 struct peer_group *group;
3792 struct bgp_filter *filter;
3793
paul1eb8ef22005-04-07 07:30:20 +00003794 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003795 {
paul1eb8ef22005-04-07 07:30:20 +00003796 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003797 {
3798 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3799 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3800 {
3801 filter = &peer->filter[afi][safi];
3802
3803 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3804 {
3805 if (filter->dlist[direct].name)
3806 filter->dlist[direct].alist =
3807 access_list_lookup (afi, filter->dlist[direct].name);
3808 else
3809 filter->dlist[direct].alist = NULL;
3810 }
3811 }
3812 }
paul1eb8ef22005-04-07 07:30:20 +00003813 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003814 {
3815 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3816 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3817 {
3818 filter = &group->conf->filter[afi][safi];
3819
3820 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3821 {
3822 if (filter->dlist[direct].name)
3823 filter->dlist[direct].alist =
3824 access_list_lookup (afi, filter->dlist[direct].name);
3825 else
3826 filter->dlist[direct].alist = NULL;
3827 }
3828 }
3829 }
3830 }
3831}
David Lamparter6b0655a2014-06-04 06:53:35 +02003832
paul718e3742002-12-13 20:15:29 +00003833/* Set prefix list to the peer. */
3834int
3835peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003836 const char *name)
paul718e3742002-12-13 20:15:29 +00003837{
3838 struct bgp_filter *filter;
3839 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003840 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003841
3842 if (! peer->afc[afi][safi])
3843 return BGP_ERR_PEER_INACTIVE;
3844
3845 if (direct != FILTER_IN && direct != FILTER_OUT)
3846 return BGP_ERR_INVALID_VALUE;
3847
3848 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3849 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3850
3851 filter = &peer->filter[afi][safi];
3852
3853 if (filter->dlist[direct].name)
3854 return BGP_ERR_PEER_FILTER_CONFLICT;
3855
3856 if (filter->plist[direct].name)
3857 free (filter->plist[direct].name);
3858 filter->plist[direct].name = strdup (name);
3859 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3860
3861 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3862 return 0;
3863
3864 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003865 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003866 {
3867 filter = &peer->filter[afi][safi];
3868
3869 if (! peer->af_group[afi][safi])
3870 continue;
3871
3872 if (filter->plist[direct].name)
3873 free (filter->plist[direct].name);
3874 filter->plist[direct].name = strdup (name);
3875 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3876 }
3877 return 0;
3878}
3879
3880int
3881peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3882{
3883 struct bgp_filter *filter;
3884 struct bgp_filter *gfilter;
3885 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003886 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003887
3888 if (! peer->afc[afi][safi])
3889 return BGP_ERR_PEER_INACTIVE;
3890
3891 if (direct != FILTER_IN && direct != FILTER_OUT)
3892 return BGP_ERR_INVALID_VALUE;
3893
3894 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3895 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3896
3897 filter = &peer->filter[afi][safi];
3898
3899 /* apply peer-group filter */
3900 if (peer->af_group[afi][safi])
3901 {
3902 gfilter = &peer->group->conf->filter[afi][safi];
3903
3904 if (gfilter->plist[direct].name)
3905 {
3906 if (filter->plist[direct].name)
3907 free (filter->plist[direct].name);
3908 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3909 filter->plist[direct].plist = gfilter->plist[direct].plist;
3910 return 0;
3911 }
3912 }
3913
3914 if (filter->plist[direct].name)
3915 free (filter->plist[direct].name);
3916 filter->plist[direct].name = NULL;
3917 filter->plist[direct].plist = NULL;
3918
3919 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3920 return 0;
3921
3922 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003923 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003924 {
3925 filter = &peer->filter[afi][safi];
3926
3927 if (! peer->af_group[afi][safi])
3928 continue;
3929
3930 if (filter->plist[direct].name)
3931 free (filter->plist[direct].name);
3932 filter->plist[direct].name = NULL;
3933 filter->plist[direct].plist = NULL;
3934 }
3935
3936 return 0;
3937}
3938
3939/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003940static void
paul718e3742002-12-13 20:15:29 +00003941peer_prefix_list_update (struct prefix_list *plist)
3942{
paul1eb8ef22005-04-07 07:30:20 +00003943 struct listnode *mnode, *mnnode;
3944 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003945 struct bgp *bgp;
3946 struct peer *peer;
3947 struct peer_group *group;
3948 struct bgp_filter *filter;
3949 afi_t afi;
3950 safi_t safi;
3951 int direct;
3952
paul1eb8ef22005-04-07 07:30:20 +00003953 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003954 {
paul1eb8ef22005-04-07 07:30:20 +00003955 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003956 {
3957 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3958 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3959 {
3960 filter = &peer->filter[afi][safi];
3961
3962 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3963 {
3964 if (filter->plist[direct].name)
3965 filter->plist[direct].plist =
3966 prefix_list_lookup (afi, filter->plist[direct].name);
3967 else
3968 filter->plist[direct].plist = NULL;
3969 }
3970 }
3971 }
paul1eb8ef22005-04-07 07:30:20 +00003972 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003973 {
3974 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3975 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3976 {
3977 filter = &group->conf->filter[afi][safi];
3978
3979 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3980 {
3981 if (filter->plist[direct].name)
3982 filter->plist[direct].plist =
3983 prefix_list_lookup (afi, filter->plist[direct].name);
3984 else
3985 filter->plist[direct].plist = NULL;
3986 }
3987 }
3988 }
3989 }
3990}
David Lamparter6b0655a2014-06-04 06:53:35 +02003991
paul718e3742002-12-13 20:15:29 +00003992int
3993peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003994 const char *name)
paul718e3742002-12-13 20:15:29 +00003995{
3996 struct bgp_filter *filter;
3997 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003998 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003999
4000 if (! peer->afc[afi][safi])
4001 return BGP_ERR_PEER_INACTIVE;
4002
4003 if (direct != FILTER_IN && direct != FILTER_OUT)
4004 return BGP_ERR_INVALID_VALUE;
4005
4006 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4007 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4008
4009 filter = &peer->filter[afi][safi];
4010
4011 if (filter->aslist[direct].name)
4012 free (filter->aslist[direct].name);
4013 filter->aslist[direct].name = strdup (name);
4014 filter->aslist[direct].aslist = as_list_lookup (name);
4015
4016 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4017 return 0;
4018
4019 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004020 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004021 {
4022 filter = &peer->filter[afi][safi];
4023
4024 if (! peer->af_group[afi][safi])
4025 continue;
4026
4027 if (filter->aslist[direct].name)
4028 free (filter->aslist[direct].name);
4029 filter->aslist[direct].name = strdup (name);
4030 filter->aslist[direct].aslist = as_list_lookup (name);
4031 }
4032 return 0;
4033}
4034
4035int
4036peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4037{
4038 struct bgp_filter *filter;
4039 struct bgp_filter *gfilter;
4040 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004041 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004042
4043 if (! peer->afc[afi][safi])
4044 return BGP_ERR_PEER_INACTIVE;
4045
hassob5f29602005-05-25 21:00:28 +00004046 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004047 return BGP_ERR_INVALID_VALUE;
4048
hassob5f29602005-05-25 21:00:28 +00004049 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004050 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4051
4052 filter = &peer->filter[afi][safi];
4053
4054 /* apply peer-group filter */
4055 if (peer->af_group[afi][safi])
4056 {
4057 gfilter = &peer->group->conf->filter[afi][safi];
4058
4059 if (gfilter->aslist[direct].name)
4060 {
4061 if (filter->aslist[direct].name)
4062 free (filter->aslist[direct].name);
4063 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4064 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4065 return 0;
4066 }
4067 }
4068
4069 if (filter->aslist[direct].name)
4070 free (filter->aslist[direct].name);
4071 filter->aslist[direct].name = NULL;
4072 filter->aslist[direct].aslist = NULL;
4073
4074 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4075 return 0;
4076
4077 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004078 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004079 {
4080 filter = &peer->filter[afi][safi];
4081
4082 if (! peer->af_group[afi][safi])
4083 continue;
4084
4085 if (filter->aslist[direct].name)
4086 free (filter->aslist[direct].name);
4087 filter->aslist[direct].name = NULL;
4088 filter->aslist[direct].aslist = NULL;
4089 }
4090
4091 return 0;
4092}
4093
paul94f2b392005-06-28 12:44:16 +00004094static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004095peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004096{
4097 afi_t afi;
4098 safi_t safi;
4099 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004100 struct listnode *mnode, *mnnode;
4101 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004102 struct bgp *bgp;
4103 struct peer *peer;
4104 struct peer_group *group;
4105 struct bgp_filter *filter;
4106
paul1eb8ef22005-04-07 07:30:20 +00004107 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004108 {
paul1eb8ef22005-04-07 07:30:20 +00004109 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004110 {
4111 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4112 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4113 {
4114 filter = &peer->filter[afi][safi];
4115
4116 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4117 {
4118 if (filter->aslist[direct].name)
4119 filter->aslist[direct].aslist =
4120 as_list_lookup (filter->aslist[direct].name);
4121 else
4122 filter->aslist[direct].aslist = NULL;
4123 }
4124 }
4125 }
paul1eb8ef22005-04-07 07:30:20 +00004126 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004127 {
4128 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4129 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4130 {
4131 filter = &group->conf->filter[afi][safi];
4132
4133 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4134 {
4135 if (filter->aslist[direct].name)
4136 filter->aslist[direct].aslist =
4137 as_list_lookup (filter->aslist[direct].name);
4138 else
4139 filter->aslist[direct].aslist = NULL;
4140 }
4141 }
4142 }
4143 }
4144}
David Lamparter6b0655a2014-06-04 06:53:35 +02004145
paul718e3742002-12-13 20:15:29 +00004146/* Set route-map to the peer. */
4147int
4148peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004149 const char *name)
paul718e3742002-12-13 20:15:29 +00004150{
4151 struct bgp_filter *filter;
4152 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004153 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004154
4155 if (! peer->afc[afi][safi])
4156 return BGP_ERR_PEER_INACTIVE;
4157
paulfee0f4c2004-09-13 05:12:46 +00004158 if (direct != RMAP_IN && direct != RMAP_OUT &&
4159 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004160 return BGP_ERR_INVALID_VALUE;
4161
paulfee0f4c2004-09-13 05:12:46 +00004162 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4163 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004164 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4165
4166 filter = &peer->filter[afi][safi];
4167
4168 if (filter->map[direct].name)
4169 free (filter->map[direct].name);
4170
4171 filter->map[direct].name = strdup (name);
4172 filter->map[direct].map = route_map_lookup_by_name (name);
4173
4174 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4175 return 0;
4176
4177 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004178 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004179 {
4180 filter = &peer->filter[afi][safi];
4181
4182 if (! peer->af_group[afi][safi])
4183 continue;
4184
4185 if (filter->map[direct].name)
4186 free (filter->map[direct].name);
4187 filter->map[direct].name = strdup (name);
4188 filter->map[direct].map = route_map_lookup_by_name (name);
4189 }
4190 return 0;
4191}
4192
4193/* Unset route-map from the peer. */
4194int
4195peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4196{
4197 struct bgp_filter *filter;
4198 struct bgp_filter *gfilter;
4199 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004200 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004201
4202 if (! peer->afc[afi][safi])
4203 return BGP_ERR_PEER_INACTIVE;
4204
hassob5f29602005-05-25 21:00:28 +00004205 if (direct != RMAP_IN && direct != RMAP_OUT &&
4206 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004207 return BGP_ERR_INVALID_VALUE;
4208
hassob5f29602005-05-25 21:00:28 +00004209 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4210 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004211 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4212
4213 filter = &peer->filter[afi][safi];
4214
4215 /* apply peer-group filter */
4216 if (peer->af_group[afi][safi])
4217 {
4218 gfilter = &peer->group->conf->filter[afi][safi];
4219
4220 if (gfilter->map[direct].name)
4221 {
4222 if (filter->map[direct].name)
4223 free (filter->map[direct].name);
4224 filter->map[direct].name = strdup (gfilter->map[direct].name);
4225 filter->map[direct].map = gfilter->map[direct].map;
4226 return 0;
4227 }
4228 }
4229
4230 if (filter->map[direct].name)
4231 free (filter->map[direct].name);
4232 filter->map[direct].name = NULL;
4233 filter->map[direct].map = NULL;
4234
4235 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4236 return 0;
4237
4238 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004239 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004240 {
4241 filter = &peer->filter[afi][safi];
4242
4243 if (! peer->af_group[afi][safi])
4244 continue;
4245
4246 if (filter->map[direct].name)
4247 free (filter->map[direct].name);
4248 filter->map[direct].name = NULL;
4249 filter->map[direct].map = NULL;
4250 }
4251 return 0;
4252}
David Lamparter6b0655a2014-06-04 06:53:35 +02004253
paul718e3742002-12-13 20:15:29 +00004254/* Set unsuppress-map to the peer. */
4255int
paulfd79ac92004-10-13 05:06:08 +00004256peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4257 const char *name)
paul718e3742002-12-13 20:15:29 +00004258{
4259 struct bgp_filter *filter;
4260 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004261 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004262
4263 if (! peer->afc[afi][safi])
4264 return BGP_ERR_PEER_INACTIVE;
4265
4266 if (peer_is_group_member (peer, afi, safi))
4267 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4268
4269 filter = &peer->filter[afi][safi];
4270
4271 if (filter->usmap.name)
4272 free (filter->usmap.name);
4273
4274 filter->usmap.name = strdup (name);
4275 filter->usmap.map = route_map_lookup_by_name (name);
4276
4277 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4278 return 0;
4279
4280 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004281 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004282 {
4283 filter = &peer->filter[afi][safi];
4284
4285 if (! peer->af_group[afi][safi])
4286 continue;
4287
4288 if (filter->usmap.name)
4289 free (filter->usmap.name);
4290 filter->usmap.name = strdup (name);
4291 filter->usmap.map = route_map_lookup_by_name (name);
4292 }
4293 return 0;
4294}
4295
4296/* Unset route-map from the peer. */
4297int
4298peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4299{
4300 struct bgp_filter *filter;
4301 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004302 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004303
4304 if (! peer->afc[afi][safi])
4305 return BGP_ERR_PEER_INACTIVE;
4306
4307 if (peer_is_group_member (peer, afi, safi))
4308 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4309
4310 filter = &peer->filter[afi][safi];
4311
4312 if (filter->usmap.name)
4313 free (filter->usmap.name);
4314 filter->usmap.name = NULL;
4315 filter->usmap.map = NULL;
4316
4317 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4318 return 0;
4319
4320 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004321 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004322 {
4323 filter = &peer->filter[afi][safi];
4324
4325 if (! peer->af_group[afi][safi])
4326 continue;
4327
4328 if (filter->usmap.name)
4329 free (filter->usmap.name);
4330 filter->usmap.name = NULL;
4331 filter->usmap.map = NULL;
4332 }
4333 return 0;
4334}
David Lamparter6b0655a2014-06-04 06:53:35 +02004335
paul718e3742002-12-13 20:15:29 +00004336int
4337peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004338 u_int32_t max, u_char threshold,
4339 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004340{
4341 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004342 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004343
4344 if (! peer->afc[afi][safi])
4345 return BGP_ERR_PEER_INACTIVE;
4346
4347 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4348 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004349 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004350 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004351 if (warning)
4352 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4353 else
4354 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4355
4356 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4357 return 0;
4358
4359 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004360 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004361 {
4362 if (! peer->af_group[afi][safi])
4363 continue;
4364
4365 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4366 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004367 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004368 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004369 if (warning)
4370 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4371 else
4372 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4373 }
4374 return 0;
4375}
4376
4377int
4378peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4379{
4380 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004381 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004382
4383 if (! peer->afc[afi][safi])
4384 return BGP_ERR_PEER_INACTIVE;
4385
4386 /* apply peer-group config */
4387 if (peer->af_group[afi][safi])
4388 {
4389 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4390 PEER_FLAG_MAX_PREFIX))
4391 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4392 else
4393 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4394
4395 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4396 PEER_FLAG_MAX_PREFIX_WARNING))
4397 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4398 else
4399 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4400
4401 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004402 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004403 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004404 return 0;
4405 }
4406
4407 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4408 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4409 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004410 peer->pmax_threshold[afi][safi] = 0;
4411 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004412
4413 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4414 return 0;
4415
4416 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004417 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004418 {
4419 if (! peer->af_group[afi][safi])
4420 continue;
4421
4422 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4423 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4424 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004425 peer->pmax_threshold[afi][safi] = 0;
4426 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004427 }
4428 return 0;
4429}
David Lamparter5f9adb52014-05-19 23:15:02 +02004430
4431static int is_ebgp_multihop_configured (struct peer *peer)
4432{
4433 struct peer_group *group;
4434 struct listnode *node, *nnode;
4435 struct peer *peer1;
4436
4437 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4438 {
4439 group = peer->group;
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004440 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4441 (group->conf->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004442 return 1;
4443
4444 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4445 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004446 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
4447 (peer1->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004448 return 1;
4449 }
4450 }
4451 else
4452 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004453 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4454 (peer->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004455 return 1;
4456 }
4457 return 0;
4458}
4459
Nick Hilliardfa411a22011-03-23 15:33:17 +00004460/* Set # of hops between us and BGP peer. */
4461int
4462peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4463{
4464 struct peer_group *group;
4465 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004466 int ret;
4467
4468 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4469
Nick Hilliardfa411a22011-03-23 15:33:17 +00004470 /* We cannot configure ttl-security hops when ebgp-multihop is already
4471 set. For non peer-groups, the check is simple. For peer-groups, it's
4472 slightly messy, because we need to check both the peer-group structure
4473 and all peer-group members for any trace of ebgp-multihop configuration
4474 before actually applying the ttl-security rules. Cisco really made a
4475 mess of this configuration parameter, and OpenBGPD got it right.
4476 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004477
David Lamparter5f9adb52014-05-19 23:15:02 +02004478 if (peer->gtsm_hops == 0)
4479 {
4480 if (is_ebgp_multihop_configured (peer))
4481 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004482
David Lamparter5f9adb52014-05-19 23:15:02 +02004483 /* specify MAXTTL on outgoing packets */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004484 /* Routine handles iBGP peers correctly */
David Lamparter5f9adb52014-05-19 23:15:02 +02004485 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4486 if (ret != 0)
4487 return ret;
4488 }
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004489
Nick Hilliardfa411a22011-03-23 15:33:17 +00004490 peer->gtsm_hops = gtsm_hops;
4491
Nick Hilliardfa411a22011-03-23 15:33:17 +00004492 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4493 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004494 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004495 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4496 }
4497 else
4498 {
4499 group = peer->group;
4500 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4501 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004502 peer->gtsm_hops = group->conf->gtsm_hops;
4503
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004504 /* Change setting of existing peer
4505 * established then change value (may break connectivity)
4506 * not established yet (teardown session and restart)
4507 * no session then do nothing (will get handled by next connection)
4508 */
4509 if (peer->status == Established)
4510 {
4511 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4512 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4513 MAXTTL + 1 - peer->gtsm_hops);
4514 }
4515 else if (peer->status < Established)
4516 {
4517 if (BGP_DEBUG (events, EVENTS))
4518 zlog_debug ("%s Min-ttl changed", peer->host);
4519 BGP_EVENT_ADD (peer, BGP_Stop);
4520 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004521 }
4522 }
4523
4524 return 0;
4525}
4526
4527int
4528peer_ttl_security_hops_unset (struct peer *peer)
4529{
4530 struct peer_group *group;
4531 struct listnode *node, *nnode;
4532 struct peer *opeer;
4533
4534 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4535
Nick Hilliardfa411a22011-03-23 15:33:17 +00004536 /* if a peer-group member, then reset to peer-group default rather than 0 */
4537 if (peer_group_active (peer))
4538 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4539 else
4540 peer->gtsm_hops = 0;
4541
4542 opeer = peer;
4543 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4544 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004545 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004546 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4547 }
4548 else
4549 {
4550 group = peer->group;
4551 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4552 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004553 peer->gtsm_hops = 0;
4554
4555 if (peer->fd >= 0)
4556 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4557 }
4558 }
4559
4560 return peer_ebgp_multihop_unset (opeer);
4561}
David Lamparter6b0655a2014-06-04 06:53:35 +02004562
paul718e3742002-12-13 20:15:29 +00004563int
4564peer_clear (struct peer *peer)
4565{
4566 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4567 {
hasso0a486e52005-02-01 20:57:17 +00004568 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4569 {
4570 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4571 if (peer->t_pmax_restart)
4572 {
4573 BGP_TIMER_OFF (peer->t_pmax_restart);
4574 if (BGP_DEBUG (events, EVENTS))
4575 zlog_debug ("%s Maximum-prefix restart timer canceled",
4576 peer->host);
4577 }
4578 BGP_EVENT_ADD (peer, BGP_Start);
4579 return 0;
4580 }
4581
paul718e3742002-12-13 20:15:29 +00004582 peer->v_start = BGP_INIT_START_TIMER;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00004583 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00004584 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4585 BGP_NOTIFY_CEASE_ADMIN_RESET);
4586 else
4587 BGP_EVENT_ADD (peer, BGP_Stop);
4588 }
4589 return 0;
4590}
4591
4592int
4593peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4594 enum bgp_clear_type stype)
4595{
4596 if (peer->status != Established)
4597 return 0;
4598
4599 if (! peer->afc[afi][safi])
4600 return BGP_ERR_AF_UNCONFIGURED;
4601
paulfee0f4c2004-09-13 05:12:46 +00004602 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4603 {
4604 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4605 return 0;
4606 bgp_check_local_routes_rsclient (peer, afi, safi);
4607 bgp_soft_reconfig_rsclient (peer, afi, safi);
4608 }
4609
paul718e3742002-12-13 20:15:29 +00004610 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4611 bgp_announce_route (peer, afi, safi);
4612
4613 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4614 {
4615 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4616 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4617 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4618 {
4619 struct bgp_filter *filter = &peer->filter[afi][safi];
4620 u_char prefix_type;
4621
4622 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4623 prefix_type = ORF_TYPE_PREFIX;
4624 else
4625 prefix_type = ORF_TYPE_PREFIX_OLD;
4626
4627 if (filter->plist[FILTER_IN].plist)
4628 {
4629 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4630 bgp_route_refresh_send (peer, afi, safi,
4631 prefix_type, REFRESH_DEFER, 1);
4632 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4633 REFRESH_IMMEDIATE, 0);
4634 }
4635 else
4636 {
4637 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4638 bgp_route_refresh_send (peer, afi, safi,
4639 prefix_type, REFRESH_IMMEDIATE, 1);
4640 else
4641 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4642 }
4643 return 0;
4644 }
4645 }
4646
4647 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4648 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4649 {
4650 /* If neighbor has soft reconfiguration inbound flag.
4651 Use Adj-RIB-In database. */
4652 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4653 bgp_soft_reconfig_in (peer, afi, safi);
4654 else
4655 {
4656 /* If neighbor has route refresh capability, send route refresh
4657 message to the peer. */
4658 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4659 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4660 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4661 else
4662 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4663 }
4664 }
4665 return 0;
4666}
David Lamparter6b0655a2014-06-04 06:53:35 +02004667
paulfd79ac92004-10-13 05:06:08 +00004668/* Display peer uptime.*/
4669/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004670char *
4671peer_uptime (time_t uptime2, char *buf, size_t len)
4672{
4673 time_t uptime1;
4674 struct tm *tm;
4675
4676 /* Check buffer length. */
4677 if (len < BGP_UPTIME_LEN)
4678 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004679 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004680 /* XXX: should return status instead of buf... */
4681 snprintf (buf, len, "<error> ");
4682 return buf;
paul718e3742002-12-13 20:15:29 +00004683 }
4684
4685 /* If there is no connection has been done before print `never'. */
4686 if (uptime2 == 0)
4687 {
4688 snprintf (buf, len, "never ");
4689 return buf;
4690 }
4691
4692 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004693 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004694 uptime1 -= uptime2;
4695 tm = gmtime (&uptime1);
Paul Jakma84c38402015-05-26 15:19:38 +01004696
paul718e3742002-12-13 20:15:29 +00004697 /* Making formatted timer strings. */
4698#define ONE_DAY_SECOND 60*60*24
Paul Jakma84c38402015-05-26 15:19:38 +01004699#define ONE_WEEK_SECOND ONE_DAY_SECOND*7
4700#define ONE_YEAR_SECOND ONE_DAY_SECOND*365
paul718e3742002-12-13 20:15:29 +00004701
4702 if (uptime1 < ONE_DAY_SECOND)
4703 snprintf (buf, len, "%02d:%02d:%02d",
4704 tm->tm_hour, tm->tm_min, tm->tm_sec);
4705 else if (uptime1 < ONE_WEEK_SECOND)
4706 snprintf (buf, len, "%dd%02dh%02dm",
4707 tm->tm_yday, tm->tm_hour, tm->tm_min);
Paul Jakma84c38402015-05-26 15:19:38 +01004708 else if (uptime1 < ONE_YEAR_SECOND)
paul718e3742002-12-13 20:15:29 +00004709 snprintf (buf, len, "%02dw%dd%02dh",
4710 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
Paul Jakma84c38402015-05-26 15:19:38 +01004711 else
4712 snprintf (buf, len, "%02dy%02dw%dd",
4713 tm->tm_year - 70, tm->tm_yday/7,
4714 tm->tm_yday - ((tm->tm_yday/7) * 7));
paul718e3742002-12-13 20:15:29 +00004715 return buf;
4716}
David Lamparter6b0655a2014-06-04 06:53:35 +02004717
paul94f2b392005-06-28 12:44:16 +00004718static void
paul718e3742002-12-13 20:15:29 +00004719bgp_config_write_filter (struct vty *vty, struct peer *peer,
4720 afi_t afi, safi_t safi)
4721{
4722 struct bgp_filter *filter;
4723 struct bgp_filter *gfilter = NULL;
4724 char *addr;
4725 int in = FILTER_IN;
4726 int out = FILTER_OUT;
4727
4728 addr = peer->host;
4729 filter = &peer->filter[afi][safi];
4730 if (peer->af_group[afi][safi])
4731 gfilter = &peer->group->conf->filter[afi][safi];
4732
4733 /* distribute-list. */
4734 if (filter->dlist[in].name)
4735 if (! gfilter || ! gfilter->dlist[in].name
4736 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4737 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4738 filter->dlist[in].name, VTY_NEWLINE);
4739 if (filter->dlist[out].name && ! gfilter)
4740 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4741 filter->dlist[out].name, VTY_NEWLINE);
4742
4743 /* prefix-list. */
4744 if (filter->plist[in].name)
4745 if (! gfilter || ! gfilter->plist[in].name
4746 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4747 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4748 filter->plist[in].name, VTY_NEWLINE);
4749 if (filter->plist[out].name && ! gfilter)
4750 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4751 filter->plist[out].name, VTY_NEWLINE);
4752
4753 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004754 if (filter->map[RMAP_IN].name)
4755 if (! gfilter || ! gfilter->map[RMAP_IN].name
4756 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004757 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004758 filter->map[RMAP_IN].name, VTY_NEWLINE);
4759 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004760 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004761 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4762 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4763 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4764 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4765 if (filter->map[RMAP_EXPORT].name)
4766 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4767 || strcmp (filter->map[RMAP_EXPORT].name,
4768 gfilter->map[RMAP_EXPORT].name) != 0)
4769 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4770 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004771
4772 /* unsuppress-map */
4773 if (filter->usmap.name && ! gfilter)
4774 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4775 filter->usmap.name, VTY_NEWLINE);
4776
4777 /* filter-list. */
4778 if (filter->aslist[in].name)
4779 if (! gfilter || ! gfilter->aslist[in].name
4780 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4781 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4782 filter->aslist[in].name, VTY_NEWLINE);
4783 if (filter->aslist[out].name && ! gfilter)
4784 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4785 filter->aslist[out].name, VTY_NEWLINE);
4786}
4787
4788/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004789static void
paul718e3742002-12-13 20:15:29 +00004790bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4791 struct peer *peer, afi_t afi, safi_t safi)
4792{
paul718e3742002-12-13 20:15:29 +00004793 struct peer *g_peer = NULL;
4794 char buf[SU_ADDRSTRLEN];
4795 char *addr;
4796
paul718e3742002-12-13 20:15:29 +00004797 addr = peer->host;
4798 if (peer_group_active (peer))
4799 g_peer = peer->group->conf;
4800
4801 /************************************
4802 ****** Global to the neighbor ******
4803 ************************************/
4804 if (afi == AFI_IP && safi == SAFI_UNICAST)
4805 {
4806 /* remote-as. */
4807 if (! peer_group_active (peer))
4808 {
4809 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4810 vty_out (vty, " neighbor %s peer-group%s", addr,
4811 VTY_NEWLINE);
4812 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004813 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004814 VTY_NEWLINE);
4815 }
4816 else
4817 {
4818 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004819 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004820 VTY_NEWLINE);
4821 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4822 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4823 peer->group->name, VTY_NEWLINE);
4824 }
4825
4826 /* local-as. */
4827 if (peer->change_local_as)
4828 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00004829 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004830 peer->change_local_as,
4831 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00004832 " no-prepend" : "",
4833 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
4834 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004835
4836 /* Description. */
4837 if (peer->desc)
4838 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4839 VTY_NEWLINE);
4840
4841 /* Shutdown. */
4842 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4843 if (! peer_group_active (peer) ||
4844 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4845 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4846
Paul Jakma0df7c912008-07-21 21:02:49 +00004847 /* Password. */
4848 if (peer->password)
4849 if (!peer_group_active (peer)
4850 || ! g_peer->password
4851 || strcmp (peer->password, g_peer->password) != 0)
4852 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4853 VTY_NEWLINE);
4854
paul718e3742002-12-13 20:15:29 +00004855 /* BGP port. */
4856 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004857 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004858 VTY_NEWLINE);
4859
4860 /* Local interface name. */
4861 if (peer->ifname)
4862 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4863 VTY_NEWLINE);
4864
4865 /* Passive. */
4866 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4867 if (! peer_group_active (peer) ||
4868 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4869 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4870
4871 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004872 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00004873 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00004874 if (! peer_group_active (peer) ||
4875 g_peer->ttl != peer->ttl)
4876 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4877 VTY_NEWLINE);
4878
Nick Hilliardfa411a22011-03-23 15:33:17 +00004879 /* ttl-security hops */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004880 if (peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004881 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004882 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00004883 peer->gtsm_hops, VTY_NEWLINE);
4884
hasso6ffd2072005-02-02 14:50:11 +00004885 /* disable-connected-check. */
4886 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004887 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004888 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4889 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004890
4891 /* Update-source. */
4892 if (peer->update_if)
4893 if (! peer_group_active (peer) || ! g_peer->update_if
4894 || strcmp (g_peer->update_if, peer->update_if) != 0)
4895 vty_out (vty, " neighbor %s update-source %s%s", addr,
4896 peer->update_if, VTY_NEWLINE);
4897 if (peer->update_source)
4898 if (! peer_group_active (peer) || ! g_peer->update_source
4899 || sockunion_cmp (g_peer->update_source,
4900 peer->update_source) != 0)
4901 vty_out (vty, " neighbor %s update-source %s%s", addr,
4902 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4903 VTY_NEWLINE);
4904
paul718e3742002-12-13 20:15:29 +00004905 /* advertisement-interval */
4906 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4907 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4908 addr, peer->v_routeadv, VTY_NEWLINE);
4909
4910 /* timers. */
4911 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4912 && ! peer_group_active (peer))
4913 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4914 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4915
4916 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4917 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4918 peer->connect, VTY_NEWLINE);
4919
4920 /* Default weight. */
4921 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4922 if (! peer_group_active (peer) ||
4923 g_peer->weight != peer->weight)
4924 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4925 VTY_NEWLINE);
4926
paul718e3742002-12-13 20:15:29 +00004927 /* Dynamic capability. */
4928 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4929 if (! peer_group_active (peer) ||
4930 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4931 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4932 VTY_NEWLINE);
4933
4934 /* dont capability negotiation. */
4935 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4936 if (! peer_group_active (peer) ||
4937 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4938 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4939 VTY_NEWLINE);
4940
4941 /* override capability negotiation. */
4942 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4943 if (! peer_group_active (peer) ||
4944 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4945 vty_out (vty, " neighbor %s override-capability%s", addr,
4946 VTY_NEWLINE);
4947
4948 /* strict capability negotiation. */
4949 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4950 if (! peer_group_active (peer) ||
4951 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4952 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4953 VTY_NEWLINE);
4954
Christian Franke15c71342012-11-19 11:17:31 +00004955 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
paul718e3742002-12-13 20:15:29 +00004956 {
4957 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4958 {
4959 if (peer->afc[AFI_IP][SAFI_UNICAST])
4960 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4961 }
4962 else
4963 {
4964 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4965 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4966 }
4967 }
4968 }
4969
4970
4971 /************************************
4972 ****** Per AF to the neighbor ******
4973 ************************************/
4974
4975 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4976 {
4977 if (peer->af_group[afi][safi])
4978 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4979 peer->group->name, VTY_NEWLINE);
4980 else
4981 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4982 }
4983
4984 /* ORF capability. */
4985 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4986 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4987 if (! peer->af_group[afi][safi])
4988 {
4989 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4990
4991 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4992 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4993 vty_out (vty, " both");
4994 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4995 vty_out (vty, " send");
4996 else
4997 vty_out (vty, " receive");
4998 vty_out (vty, "%s", VTY_NEWLINE);
4999 }
5000
5001 /* Route reflector client. */
5002 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
5003 && ! peer->af_group[afi][safi])
5004 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
5005 VTY_NEWLINE);
5006
5007 /* Nexthop self. */
5008 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
5009 && ! peer->af_group[afi][safi])
Timo Teräs9e7a53c2014-04-24 10:22:37 +03005010 vty_out (vty, " neighbor %s next-hop-self%s%s", addr,
5011 peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ?
5012 " all" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005013
5014 /* Remove private AS. */
5015 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
5016 && ! peer->af_group[afi][safi])
5017 vty_out (vty, " neighbor %s remove-private-AS%s",
5018 addr, VTY_NEWLINE);
5019
5020 /* send-community print. */
5021 if (! peer->af_group[afi][safi])
5022 {
5023 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5024 {
5025 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5026 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5027 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
5028 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5029 vty_out (vty, " neighbor %s send-community extended%s",
5030 addr, VTY_NEWLINE);
5031 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5032 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
5033 }
5034 else
5035 {
5036 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5037 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5038 vty_out (vty, " no neighbor %s send-community both%s",
5039 addr, VTY_NEWLINE);
5040 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5041 vty_out (vty, " no neighbor %s send-community extended%s",
5042 addr, VTY_NEWLINE);
5043 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5044 vty_out (vty, " no neighbor %s send-community%s",
5045 addr, VTY_NEWLINE);
5046 }
5047 }
5048
5049 /* Default information */
5050 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5051 && ! peer->af_group[afi][safi])
5052 {
5053 vty_out (vty, " neighbor %s default-originate", addr);
5054 if (peer->default_rmap[afi][safi].name)
5055 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5056 vty_out (vty, "%s", VTY_NEWLINE);
5057 }
5058
5059 /* Soft reconfiguration inbound. */
5060 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5061 if (! peer->af_group[afi][safi] ||
5062 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5063 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5064 VTY_NEWLINE);
5065
5066 /* maximum-prefix. */
5067 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5068 if (! peer->af_group[afi][safi]
5069 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005070 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005071 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5072 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005073 {
hasso0a486e52005-02-01 20:57:17 +00005074 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5075 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5076 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5077 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5078 vty_out (vty, " warning-only");
5079 if (peer->pmax_restart[afi][safi])
5080 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5081 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005082 }
paul718e3742002-12-13 20:15:29 +00005083
5084 /* Route server client. */
5085 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5086 && ! peer->af_group[afi][safi])
5087 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5088
Dylan Hall3cf12882011-10-27 15:28:17 +04005089 /* Nexthop-local unchanged. */
5090 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5091 && ! peer->af_group[afi][safi])
5092 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5093
paul718e3742002-12-13 20:15:29 +00005094 /* Allow AS in. */
5095 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5096 if (! peer_group_active (peer)
5097 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5098 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5099 {
5100 if (peer->allowas_in[afi][safi] == 3)
5101 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5102 else
5103 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5104 peer->allowas_in[afi][safi], VTY_NEWLINE);
5105 }
5106
5107 /* Filter. */
5108 bgp_config_write_filter (vty, peer, afi, safi);
5109
5110 /* atribute-unchanged. */
5111 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5112 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5113 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5114 && ! peer->af_group[afi][safi])
5115 {
5116 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5117 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5118 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5119 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5120 else
5121 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5122 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5123 " as-path" : "",
5124 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5125 " next-hop" : "",
5126 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5127 " med" : "", VTY_NEWLINE);
5128 }
5129}
5130
5131/* Display "address-family" configuration header. */
5132void
5133bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5134 int *write)
5135{
5136 if (*write)
5137 return;
5138
5139 if (afi == AFI_IP && safi == SAFI_UNICAST)
5140 return;
5141
5142 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5143
5144 if (afi == AFI_IP)
5145 {
5146 if (safi == SAFI_MULTICAST)
5147 vty_out (vty, "ipv4 multicast");
5148 else if (safi == SAFI_MPLS_VPN)
5149 vty_out (vty, "vpnv4 unicast");
5150 }
5151 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005152 {
5153 vty_out (vty, "ipv6");
5154
5155 if (safi == SAFI_MULTICAST)
5156 vty_out (vty, " multicast");
5157 }
paul718e3742002-12-13 20:15:29 +00005158
5159 vty_out (vty, "%s", VTY_NEWLINE);
5160
5161 *write = 1;
5162}
5163
5164/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005165static int
paul718e3742002-12-13 20:15:29 +00005166bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5167 safi_t safi)
5168{
5169 int write = 0;
5170 struct peer *peer;
5171 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005172 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005173
5174 bgp_config_write_network (vty, bgp, afi, safi, &write);
5175
5176 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5177
paul1eb8ef22005-04-07 07:30:20 +00005178 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005179 {
5180 if (group->conf->afc[afi][safi])
5181 {
5182 bgp_config_write_family_header (vty, afi, safi, &write);
5183 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5184 }
5185 }
paul1eb8ef22005-04-07 07:30:20 +00005186 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005187 {
5188 if (peer->afc[afi][safi])
5189 {
5190 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5191 {
5192 bgp_config_write_family_header (vty, afi, safi, &write);
5193 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5194 }
5195 }
5196 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005197
5198 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5199
paul718e3742002-12-13 20:15:29 +00005200 if (write)
5201 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5202
5203 return write;
5204}
5205
5206int
5207bgp_config_write (struct vty *vty)
5208{
5209 int write = 0;
5210 struct bgp *bgp;
5211 struct peer_group *group;
5212 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005213 struct listnode *node, *nnode;
5214 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005215
5216 /* BGP Multiple instance. */
5217 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5218 {
5219 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5220 write++;
5221 }
5222
5223 /* BGP Config type. */
5224 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5225 {
5226 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5227 write++;
5228 }
5229
5230 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005231 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005232 {
5233 if (write)
5234 vty_out (vty, "!%s", VTY_NEWLINE);
5235
5236 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005237 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005238
5239 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5240 {
5241 if (bgp->name)
5242 vty_out (vty, " view %s", bgp->name);
5243 }
5244 vty_out (vty, "%s", VTY_NEWLINE);
5245
5246 /* No Synchronization */
5247 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5248 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5249
5250 /* BGP fast-external-failover. */
5251 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5252 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5253
5254 /* BGP router ID. */
5255 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5256 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5257 VTY_NEWLINE);
5258
paul848973c2003-08-13 00:32:49 +00005259 /* BGP log-neighbor-changes. */
5260 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5261 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
5262
paul718e3742002-12-13 20:15:29 +00005263 /* BGP configuration. */
5264 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5265 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5266
5267 /* BGP default ipv4-unicast. */
5268 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5269 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5270
5271 /* BGP default local-preference. */
5272 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5273 vty_out (vty, " bgp default local-preference %d%s",
5274 bgp->default_local_pref, VTY_NEWLINE);
5275
5276 /* BGP client-to-client reflection. */
5277 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5278 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5279
5280 /* BGP cluster ID. */
5281 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5282 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5283 VTY_NEWLINE);
5284
hassoe0701b72004-05-20 09:19:34 +00005285 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005286 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005287 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5288 VTY_NEWLINE);
5289
5290 /* Confederation peer */
5291 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005292 {
hassoe0701b72004-05-20 09:19:34 +00005293 int i;
paul718e3742002-12-13 20:15:29 +00005294
hassoe0701b72004-05-20 09:19:34 +00005295 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005296
hassoe0701b72004-05-20 09:19:34 +00005297 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005298 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005299
hassoe0701b72004-05-20 09:19:34 +00005300 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005301 }
5302
5303 /* BGP enforce-first-as. */
5304 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5305 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5306
5307 /* BGP deterministic-med. */
5308 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5309 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005310
5311 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005312 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5313 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5314 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005315 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5316 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5317
paul718e3742002-12-13 20:15:29 +00005318 /* BGP bestpath method. */
5319 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5320 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005321 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5322 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
Pradosh Mohapatra2fdd4552013-09-07 07:02:36 +00005323 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
5324 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
5325 }
paul718e3742002-12-13 20:15:29 +00005326 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5327 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5328 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5329 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5330 {
5331 vty_out (vty, " bgp bestpath med");
5332 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5333 vty_out (vty, " confed");
5334 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5335 vty_out (vty, " missing-as-worst");
5336 vty_out (vty, "%s", VTY_NEWLINE);
5337 }
5338
5339 /* BGP network import check. */
5340 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5341 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5342
5343 /* BGP scan interval. */
5344 bgp_config_write_scan_time (vty);
5345
5346 /* BGP flag dampening. */
5347 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5348 BGP_CONFIG_DAMPENING))
5349 bgp_config_write_damp (vty);
5350
5351 /* BGP static route configuration. */
5352 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5353
5354 /* BGP redistribute configuration. */
5355 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5356
5357 /* BGP timers configuration. */
5358 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5359 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5360 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5361 bgp->default_holdtime, VTY_NEWLINE);
5362
5363 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005364 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005365 {
5366 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5367 }
5368
5369 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005370 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005371 {
5372 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5373 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5374 }
5375
Josh Bailey165b5ff2011-07-20 20:43:22 -07005376 /* maximum-paths */
5377 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5378
paul718e3742002-12-13 20:15:29 +00005379 /* Distance configuration. */
5380 bgp_config_write_distance (vty, bgp);
5381
5382 /* No auto-summary */
5383 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5384 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5385
5386 /* IPv4 multicast configuration. */
5387 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5388
5389 /* IPv4 VPN configuration. */
5390 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5391
5392 /* IPv6 unicast configuration. */
5393 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5394
Paul Jakma37a217a2007-04-10 19:20:29 +00005395 /* IPv6 multicast configuration. */
5396 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5397
paul718e3742002-12-13 20:15:29 +00005398 write++;
5399 }
5400 return write;
5401}
5402
5403void
paul94f2b392005-06-28 12:44:16 +00005404bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005405{
5406 memset (&bgp_master, 0, sizeof (struct bgp_master));
5407
5408 bm = &bgp_master;
5409 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005410 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005411 bm->port = BGP_PORT_DEFAULT;
5412 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005413 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005414}
paul200df112005-06-01 11:17:05 +00005415
David Lamparter6b0655a2014-06-04 06:53:35 +02005416
paul718e3742002-12-13 20:15:29 +00005417void
paul94f2b392005-06-28 12:44:16 +00005418bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005419{
paul718e3742002-12-13 20:15:29 +00005420 /* BGP VTY commands installation. */
5421 bgp_vty_init ();
5422
paul718e3742002-12-13 20:15:29 +00005423 /* Init zebra. */
Donald Sharp774914f2015-10-14 08:50:39 -04005424 bgp_zebra_init (bm->master);
paul718e3742002-12-13 20:15:29 +00005425
5426 /* BGP inits. */
5427 bgp_attr_init ();
5428 bgp_debug_init ();
5429 bgp_dump_init ();
5430 bgp_route_init ();
5431 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005432 bgp_address_init ();
paul718e3742002-12-13 20:15:29 +00005433 bgp_scan_init ();
5434 bgp_mplsvpn_init ();
5435
5436 /* Access list initialize. */
5437 access_list_init ();
5438 access_list_add_hook (peer_distribute_update);
5439 access_list_delete_hook (peer_distribute_update);
5440
5441 /* Filter list initialize. */
5442 bgp_filter_init ();
5443 as_list_add_hook (peer_aslist_update);
5444 as_list_delete_hook (peer_aslist_update);
5445
5446 /* Prefix list initialize.*/
5447 prefix_list_init ();
5448 prefix_list_add_hook (peer_prefix_list_update);
5449 prefix_list_delete_hook (peer_prefix_list_update);
5450
5451 /* Community list initialize. */
5452 bgp_clist = community_list_init ();
5453
5454#ifdef HAVE_SNMP
5455 bgp_snmp_init ();
5456#endif /* HAVE_SNMP */
5457}
paul545acaf2004-04-20 15:13:15 +00005458
5459void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005460bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005461{
paul545acaf2004-04-20 15:13:15 +00005462 struct bgp *bgp;
5463 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005464 struct listnode *node, *nnode;
5465 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005466
paul1eb8ef22005-04-07 07:30:20 +00005467 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5468 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005469 if (peer->status == Established)
5470 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5471 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005472
paul545acaf2004-04-20 15:13:15 +00005473 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005474
paule210cf92005-06-15 19:15:35 +00005475 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005476 {
5477 work_queue_free (bm->process_main_queue);
5478 bm->process_main_queue = NULL;
5479 }
paule210cf92005-06-15 19:15:35 +00005480 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005481 {
5482 work_queue_free (bm->process_rsclient_queue);
5483 bm->process_rsclient_queue = NULL;
5484 }
paul545acaf2004-04-20 15:13:15 +00005485}