blob: 90e77f217cba02a7c47449cb100cf6af69f84076 [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
Lou Berger056f3762013-04-10 12:30:04 -0700740 if (peer->notify.data)
741 XFREE(MTYPE_TMP, peer->notify.data);
742
Paul Jakmaca058a32006-09-14 02:58:49 +0000743 bgp_sync_delete (peer);
paul200df112005-06-01 11:17:05 +0000744 memset (peer, 0, sizeof (struct peer));
745
746 XFREE (MTYPE_BGP_PEER, peer);
747}
748
749/* increase reference count on a struct peer */
750struct peer *
Donald Sharp104576d2015-09-16 13:17:55 -0400751peer_lock_with_caller (const char *name, struct peer *peer)
paul200df112005-06-01 11:17:05 +0000752{
753 assert (peer && (peer->lock >= 0));
Donald Sharp104576d2015-09-16 13:17:55 -0400754
755#if 0
756 zlog_debug("%s peer_lock %p %d", name, peer, peer->lock);
757#endif
758
paul200df112005-06-01 11:17:05 +0000759 peer->lock++;
760
761 return peer;
762}
763
764/* decrease reference count on a struct peer
765 * struct peer is freed and NULL returned if last reference
766 */
767struct peer *
Donald Sharp104576d2015-09-16 13:17:55 -0400768peer_unlock_with_caller (const char *name, struct peer *peer)
paul200df112005-06-01 11:17:05 +0000769{
770 assert (peer && (peer->lock > 0));
Donald Sharp104576d2015-09-16 13:17:55 -0400771
772#if 0
773 zlog_debug("%s peer_unlock %p %d", name, peer, peer->lock);
774#endif
775
paul200df112005-06-01 11:17:05 +0000776 peer->lock--;
777
778 if (peer->lock == 0)
779 {
paul200df112005-06-01 11:17:05 +0000780 peer_free (peer);
781 return NULL;
782 }
783
paul200df112005-06-01 11:17:05 +0000784 return peer;
785}
786
787/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000788static struct peer *
Paul Jakma6f585442006-10-22 19:13:07 +0000789peer_new (struct bgp *bgp)
paul718e3742002-12-13 20:15:29 +0000790{
791 afi_t afi;
792 safi_t safi;
793 struct peer *peer;
794 struct servent *sp;
Paul Jakma6f585442006-10-22 19:13:07 +0000795
796 /* bgp argument is absolutely required */
797 assert (bgp);
798 if (!bgp)
799 return NULL;
800
paul718e3742002-12-13 20:15:29 +0000801 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000802 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000803
804 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000805 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000806 peer->v_start = BGP_INIT_START_TIMER;
807 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
808 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
809 peer->status = Idle;
810 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000811 peer->weight = 0;
Paul Jakma0df7c912008-07-21 21:02:49 +0000812 peer->password = NULL;
Paul Jakma6f585442006-10-22 19:13:07 +0000813 peer->bgp = bgp;
Paul Jakmaca058a32006-09-14 02:58:49 +0000814 peer = peer_lock (peer); /* initial reference */
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700815 bgp_lock (bgp);
paul718e3742002-12-13 20:15:29 +0000816
817 /* Set default flags. */
818 for (afi = AFI_IP; afi < AFI_MAX; afi++)
819 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
820 {
821 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
822 {
823 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
824 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
825 }
826 peer->orf_plist[afi][safi] = NULL;
827 }
828 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
829
830 /* Create buffers. */
831 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
832 peer->obuf = stream_fifo_new ();
833 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000834 peer->scratch = stream_new (BGP_MAX_PACKET_SIZE);
paul718e3742002-12-13 20:15:29 +0000835
836 bgp_sync_init (peer);
837
838 /* Get service port number. */
839 sp = getservbyname ("bgp", "tcp");
840 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
841
842 return peer;
843}
844
845/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000846static struct peer *
paul718e3742002-12-13 20:15:29 +0000847peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
848 as_t remote_as, afi_t afi, safi_t safi)
849{
850 int active;
851 struct peer *peer;
852 char buf[SU_ADDRSTRLEN];
853
Paul Jakma6f585442006-10-22 19:13:07 +0000854 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000855 peer->su = *su;
856 peer->local_as = local_as;
857 peer->as = remote_as;
858 peer->local_id = bgp->router_id;
859 peer->v_holdtime = bgp->default_holdtime;
860 peer->v_keepalive = bgp->default_keepalive;
861 if (peer_sort (peer) == BGP_PEER_IBGP)
862 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
863 else
864 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000865
866 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000867 listnode_add_sort (bgp->peer, peer);
868
869 active = peer_active (peer);
870
871 if (afi && safi)
872 peer->afc[afi][safi] = 1;
873
Stephen Hemminger65957882010-01-15 16:22:10 +0300874 /* Last read and reset time set */
875 peer->readtime = peer->resettime = bgp_clock ();
paul848973c2003-08-13 00:32:49 +0000876
paul718e3742002-12-13 20:15:29 +0000877 /* Default TTL set. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000878 peer->ttl = (peer->sort == BGP_PEER_IBGP) ? 255 : 1;
paul718e3742002-12-13 20:15:29 +0000879
880 /* Make peer's address string. */
881 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000882 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000883
884 /* Set up peer's events and timers. */
885 if (! active && peer_active (peer))
886 bgp_timer_set (peer);
887
888 return peer;
889}
890
pauleb821182004-05-01 08:44:08 +0000891/* Make accept BGP peer. Called from bgp_accept (). */
892struct peer *
893peer_create_accept (struct bgp *bgp)
894{
895 struct peer *peer;
896
Paul Jakma6f585442006-10-22 19:13:07 +0000897 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000898
899 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000900 listnode_add_sort (bgp->peer, peer);
901
902 return peer;
903}
904
paul718e3742002-12-13 20:15:29 +0000905/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000906static void
paul718e3742002-12-13 20:15:29 +0000907peer_as_change (struct peer *peer, as_t as)
908{
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000909 bgp_peer_sort_t type;
paul718e3742002-12-13 20:15:29 +0000910
911 /* Stop peer. */
912 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
913 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000914 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000915 {
916 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
917 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
918 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
919 }
paul718e3742002-12-13 20:15:29 +0000920 else
921 BGP_EVENT_ADD (peer, BGP_Stop);
922 }
923 type = peer_sort (peer);
924 peer->as = as;
925
paul848973c2003-08-13 00:32:49 +0000926 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
927 && ! bgp_confederation_peers_check (peer->bgp, as)
928 && peer->bgp->as != as)
929 peer->local_as = peer->bgp->confed_id;
930 else
931 peer->local_as = peer->bgp->as;
932
paul718e3742002-12-13 20:15:29 +0000933 /* Advertisement-interval reset */
934 if (peer_sort (peer) == BGP_PEER_IBGP)
935 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
936 else
937 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
938
939 /* TTL reset */
940 if (peer_sort (peer) == BGP_PEER_IBGP)
941 peer->ttl = 255;
942 else if (type == BGP_PEER_IBGP)
943 peer->ttl = 1;
944
945 /* reflector-client reset */
946 if (peer_sort (peer) != BGP_PEER_IBGP)
947 {
948 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
949 PEER_FLAG_REFLECTOR_CLIENT);
950 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
951 PEER_FLAG_REFLECTOR_CLIENT);
952 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
953 PEER_FLAG_REFLECTOR_CLIENT);
954 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
955 PEER_FLAG_REFLECTOR_CLIENT);
956 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
957 PEER_FLAG_REFLECTOR_CLIENT);
958 }
959
960 /* local-as reset */
961 if (peer_sort (peer) != BGP_PEER_EBGP)
962 {
963 peer->change_local_as = 0;
964 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +0000965 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +0000966 }
967}
968
969/* If peer does not exist, create new one. If peer already exists,
970 set AS number to the peer. */
971int
972peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
973 afi_t afi, safi_t safi)
974{
975 struct peer *peer;
976 as_t local_as;
977
978 peer = peer_lookup (bgp, su);
979
980 if (peer)
981 {
982 /* When this peer is a member of peer-group. */
983 if (peer->group)
984 {
985 if (peer->group->conf->as)
986 {
987 /* Return peer group's AS number. */
988 *as = peer->group->conf->as;
989 return BGP_ERR_PEER_GROUP_MEMBER;
990 }
991 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
992 {
993 if (bgp->as != *as)
994 {
995 *as = peer->as;
996 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
997 }
998 }
999 else
1000 {
1001 if (bgp->as == *as)
1002 {
1003 *as = peer->as;
1004 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1005 }
1006 }
1007 }
1008
1009 /* Existing peer's AS number change. */
1010 if (peer->as != *as)
1011 peer_as_change (peer, *as);
1012 }
1013 else
1014 {
1015
1016 /* If the peer is not part of our confederation, and its not an
1017 iBGP peer then spoof the source AS */
1018 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1019 && ! bgp_confederation_peers_check (bgp, *as)
1020 && bgp->as != *as)
1021 local_as = bgp->confed_id;
1022 else
1023 local_as = bgp->as;
1024
1025 /* If this is IPv4 unicast configuration and "no bgp default
1026 ipv4-unicast" is specified. */
1027
1028 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1029 && afi == AFI_IP && safi == SAFI_UNICAST)
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001030 peer_create (su, bgp, local_as, *as, 0, 0);
paul718e3742002-12-13 20:15:29 +00001031 else
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001032 peer_create (su, bgp, local_as, *as, afi, safi);
paul718e3742002-12-13 20:15:29 +00001033 }
1034
1035 return 0;
1036}
1037
1038/* Activate the peer or peer group for specified AFI and SAFI. */
1039int
1040peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1041{
1042 int active;
1043
1044 if (peer->afc[afi][safi])
1045 return 0;
1046
1047 /* Activate the address family configuration. */
1048 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1049 peer->afc[afi][safi] = 1;
1050 else
1051 {
1052 active = peer_active (peer);
1053
1054 peer->afc[afi][safi] = 1;
1055
1056 if (! active && peer_active (peer))
1057 bgp_timer_set (peer);
1058 else
1059 {
1060 if (peer->status == Established)
1061 {
1062 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1063 {
1064 peer->afc_adv[afi][safi] = 1;
1065 bgp_capability_send (peer, afi, safi,
1066 CAPABILITY_CODE_MP,
1067 CAPABILITY_ACTION_SET);
1068 if (peer->afc_recv[afi][safi])
1069 {
1070 peer->afc_nego[afi][safi] = 1;
1071 bgp_announce_route (peer, afi, safi);
1072 }
1073 }
1074 else
hassoe0701b72004-05-20 09:19:34 +00001075 {
1076 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1077 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1078 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1079 }
paul718e3742002-12-13 20:15:29 +00001080 }
1081 }
1082 }
1083 return 0;
1084}
1085
1086int
1087peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1088{
1089 struct peer_group *group;
1090 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001091 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001092
1093 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1094 {
1095 group = peer->group;
1096
paul1eb8ef22005-04-07 07:30:20 +00001097 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001098 {
1099 if (peer1->af_group[afi][safi])
1100 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1101 }
1102 }
1103 else
1104 {
1105 if (peer->af_group[afi][safi])
1106 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1107 }
1108
1109 if (! peer->afc[afi][safi])
1110 return 0;
1111
1112 /* De-activate the address family configuration. */
1113 peer->afc[afi][safi] = 0;
1114 peer_af_flag_reset (peer, afi, safi);
1115
1116 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1117 {
1118 if (peer->status == Established)
1119 {
1120 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1121 {
1122 peer->afc_adv[afi][safi] = 0;
1123 peer->afc_nego[afi][safi] = 0;
1124
1125 if (peer_active_nego (peer))
1126 {
1127 bgp_capability_send (peer, afi, safi,
1128 CAPABILITY_CODE_MP,
1129 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001130 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001131 peer->pcount[afi][safi] = 0;
1132 }
1133 else
hassoe0701b72004-05-20 09:19:34 +00001134 {
1135 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1136 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1137 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1138 }
paul718e3742002-12-13 20:15:29 +00001139 }
1140 else
hassoe0701b72004-05-20 09:19:34 +00001141 {
1142 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1143 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1144 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1145 }
paul718e3742002-12-13 20:15:29 +00001146 }
1147 }
1148 return 0;
1149}
1150
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001151static void
hasso93406d82005-02-02 14:40:33 +00001152peer_nsf_stop (struct peer *peer)
1153{
1154 afi_t afi;
1155 safi_t safi;
1156
1157 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1158 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1159
1160 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +04001161 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +00001162 peer->nsf[afi][safi] = 0;
1163
1164 if (peer->t_gr_restart)
1165 {
1166 BGP_TIMER_OFF (peer->t_gr_restart);
1167 if (BGP_DEBUG (events, EVENTS))
1168 zlog_debug ("%s graceful restart timer stopped", peer->host);
1169 }
1170 if (peer->t_gr_stale)
1171 {
1172 BGP_TIMER_OFF (peer->t_gr_stale);
1173 if (BGP_DEBUG (events, EVENTS))
1174 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1175 }
1176 bgp_clear_route_all (peer);
1177}
1178
Paul Jakmaca058a32006-09-14 02:58:49 +00001179/* Delete peer from confguration.
1180 *
1181 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1182 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1183 *
1184 * This function /should/ take care to be idempotent, to guard against
1185 * it being called multiple times through stray events that come in
1186 * that happen to result in this function being called again. That
1187 * said, getting here for a "Deleted" peer is a bug in the neighbour
1188 * FSM.
1189 */
paul718e3742002-12-13 20:15:29 +00001190int
1191peer_delete (struct peer *peer)
1192{
1193 int i;
1194 afi_t afi;
1195 safi_t safi;
1196 struct bgp *bgp;
1197 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001198 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001199
Paul Jakmaca058a32006-09-14 02:58:49 +00001200 assert (peer->status != Deleted);
1201
paul718e3742002-12-13 20:15:29 +00001202 bgp = peer->bgp;
1203
hasso93406d82005-02-02 14:40:33 +00001204 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1205 peer_nsf_stop (peer);
1206
Chris Caputo228da422009-07-18 05:44:03 +00001207 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001208 relationship. */
1209 if (peer->group)
1210 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001211 if ((pn = listnode_lookup (peer->group->peer, peer)))
1212 {
1213 peer = peer_unlock (peer); /* group->peer list reference */
1214 list_delete_node (peer->group->peer, pn);
1215 }
paul718e3742002-12-13 20:15:29 +00001216 peer->group = NULL;
1217 }
paul200df112005-06-01 11:17:05 +00001218
paul718e3742002-12-13 20:15:29 +00001219 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001220 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1221 * executed after peer structure is deleted.
1222 */
hassoe0701b72004-05-20 09:19:34 +00001223 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001224 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001225 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001226
1227 /* Password configuration */
1228 if (peer->password)
1229 {
1230 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1231 peer->password = NULL;
1232
1233 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1234 bgp_md5_set (peer);
1235 }
1236
Paul Jakmaca058a32006-09-14 02:58:49 +00001237 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001238
paul718e3742002-12-13 20:15:29 +00001239 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001240 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1241 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001242 {
Chris Caputo228da422009-07-18 05:44:03 +00001243 peer_unlock (peer); /* bgp peer list reference */
1244 list_delete_node (bgp->peer, pn);
1245 }
paul200df112005-06-01 11:17:05 +00001246
Chris Caputo228da422009-07-18 05:44:03 +00001247 if (peer_rsclient_active (peer)
1248 && (pn = listnode_lookup (bgp->rsclient, peer)))
1249 {
1250 peer_unlock (peer); /* rsclient list reference */
1251 list_delete_node (bgp->rsclient, pn);
1252
1253 /* Clear our own rsclient ribs. */
1254 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1255 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1256 if (CHECK_FLAG(peer->af_flags[afi][safi],
1257 PEER_FLAG_RSERVER_CLIENT))
1258 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001259 }
1260
1261 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1262 member of a peer_group. */
1263 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1264 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1265 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001266 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001267
paul200df112005-06-01 11:17:05 +00001268 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001269 if (peer->ibuf)
1270 stream_free (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001271 if (peer->obuf)
1272 stream_fifo_free (peer->obuf);
paul718e3742002-12-13 20:15:29 +00001273 if (peer->work)
1274 stream_free (peer->work);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00001275 if (peer->scratch)
1276 stream_free(peer->scratch);
Paul Jakma18937402006-07-27 19:05:12 +00001277 peer->obuf = NULL;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00001278 peer->work = peer->scratch = peer->ibuf = NULL;
Paul Jakma18937402006-07-27 19:05:12 +00001279
paul718e3742002-12-13 20:15:29 +00001280 /* Local and remote addresses. */
1281 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001282 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001283 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001284 sockunion_free (peer->su_remote);
Paul Jakma18937402006-07-27 19:05:12 +00001285 peer->su_local = peer->su_remote = NULL;
paul200df112005-06-01 11:17:05 +00001286
paul718e3742002-12-13 20:15:29 +00001287 /* Free filter related memory. */
1288 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1289 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1290 {
1291 filter = &peer->filter[afi][safi];
1292
1293 for (i = FILTER_IN; i < FILTER_MAX; i++)
1294 {
1295 if (filter->dlist[i].name)
1296 free (filter->dlist[i].name);
1297 if (filter->plist[i].name)
1298 free (filter->plist[i].name);
1299 if (filter->aslist[i].name)
1300 free (filter->aslist[i].name);
paul200df112005-06-01 11:17:05 +00001301
1302 filter->dlist[i].name = NULL;
1303 filter->plist[i].name = NULL;
1304 filter->aslist[i].name = NULL;
1305 }
1306 for (i = RMAP_IN; i < RMAP_MAX; i++)
1307 {
paul718e3742002-12-13 20:15:29 +00001308 if (filter->map[i].name)
1309 free (filter->map[i].name);
paul200df112005-06-01 11:17:05 +00001310 filter->map[i].name = NULL;
paul718e3742002-12-13 20:15:29 +00001311 }
1312
1313 if (filter->usmap.name)
1314 free (filter->usmap.name);
1315
1316 if (peer->default_rmap[afi][safi].name)
1317 free (peer->default_rmap[afi][safi].name);
paul200df112005-06-01 11:17:05 +00001318
1319 filter->usmap.name = NULL;
1320 peer->default_rmap[afi][safi].name = NULL;
paul718e3742002-12-13 20:15:29 +00001321 }
paul200df112005-06-01 11:17:05 +00001322
1323 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001324
1325 return 0;
1326}
David Lamparter6b0655a2014-06-04 06:53:35 +02001327
paul94f2b392005-06-28 12:44:16 +00001328static int
paul718e3742002-12-13 20:15:29 +00001329peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1330{
1331 return strcmp (g1->name, g2->name);
1332}
1333
1334/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001335static int
paul718e3742002-12-13 20:15:29 +00001336peer_group_active (struct peer *peer)
1337{
1338 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1339 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1340 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1341 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1342 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1343 return 1;
1344 return 0;
1345}
1346
1347/* Peer group cofiguration. */
1348static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001349peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001350{
1351 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1352 sizeof (struct peer_group));
1353}
1354
paul94f2b392005-06-28 12:44:16 +00001355static void
paul718e3742002-12-13 20:15:29 +00001356peer_group_free (struct peer_group *group)
1357{
1358 XFREE (MTYPE_PEER_GROUP, group);
1359}
1360
1361struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001362peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001363{
1364 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001365 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001366
paul1eb8ef22005-04-07 07:30:20 +00001367 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001368 {
1369 if (strcmp (group->name, name) == 0)
1370 return group;
1371 }
1372 return NULL;
1373}
1374
1375struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001376peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001377{
1378 struct peer_group *group;
1379
1380 group = peer_group_lookup (bgp, name);
1381 if (group)
1382 return group;
1383
1384 group = peer_group_new ();
1385 group->bgp = bgp;
1386 group->name = strdup (name);
1387 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001388 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001389 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1390 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001391 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001392 group->conf->group = group;
1393 group->conf->as = 0;
1394 group->conf->ttl = 1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001395 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001396 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1397 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1398 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1399 group->conf->keepalive = 0;
1400 group->conf->holdtime = 0;
1401 group->conf->connect = 0;
1402 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1403 listnode_add_sort (bgp->group, group);
1404
1405 return 0;
1406}
1407
paul94f2b392005-06-28 12:44:16 +00001408static void
paul718e3742002-12-13 20:15:29 +00001409peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1410 afi_t afi, safi_t safi)
1411{
1412 int in = FILTER_IN;
1413 int out = FILTER_OUT;
1414 struct peer *conf;
1415 struct bgp_filter *pfilter;
1416 struct bgp_filter *gfilter;
1417
1418 conf = group->conf;
1419 pfilter = &peer->filter[afi][safi];
1420 gfilter = &conf->filter[afi][safi];
1421
1422 /* remote-as */
1423 if (conf->as)
1424 peer->as = conf->as;
1425
1426 /* remote-as */
1427 if (conf->change_local_as)
1428 peer->change_local_as = conf->change_local_as;
1429
1430 /* TTL */
1431 peer->ttl = conf->ttl;
1432
Nick Hilliardfa411a22011-03-23 15:33:17 +00001433 /* GTSM hops */
1434 peer->gtsm_hops = conf->gtsm_hops;
1435
paul718e3742002-12-13 20:15:29 +00001436 /* Weight */
1437 peer->weight = conf->weight;
1438
1439 /* peer flags apply */
1440 peer->flags = conf->flags;
1441 /* peer af_flags apply */
1442 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1443 /* peer config apply */
1444 peer->config = conf->config;
1445
1446 /* peer timers apply */
1447 peer->holdtime = conf->holdtime;
1448 peer->keepalive = conf->keepalive;
1449 peer->connect = conf->connect;
1450 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1451 peer->v_connect = conf->connect;
1452 else
1453 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1454
1455 /* advertisement-interval reset */
1456 if (peer_sort (peer) == BGP_PEER_IBGP)
1457 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1458 else
1459 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1460
Paul Jakma0df7c912008-07-21 21:02:49 +00001461 /* password apply */
Roman Hoog Antink0e4303d2013-01-18 13:52:03 +01001462 if (conf->password && !peer->password)
Paul Jakma0df7c912008-07-21 21:02:49 +00001463 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
Paul Jakma0df7c912008-07-21 21:02:49 +00001464
1465 bgp_md5_set (peer);
1466
paul718e3742002-12-13 20:15:29 +00001467 /* maximum-prefix */
1468 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001469 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001470 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001471
1472 /* allowas-in */
1473 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1474
paulfee0f4c2004-09-13 05:12:46 +00001475 /* route-server-client */
1476 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1477 {
1478 /* Make peer's RIB point to group's RIB. */
1479 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1480
1481 /* Import policy. */
1482 if (pfilter->map[RMAP_IMPORT].name)
1483 free (pfilter->map[RMAP_IMPORT].name);
1484 if (gfilter->map[RMAP_IMPORT].name)
1485 {
1486 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1487 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1488 }
1489 else
1490 {
1491 pfilter->map[RMAP_IMPORT].name = NULL;
1492 pfilter->map[RMAP_IMPORT].map = NULL;
1493 }
1494
1495 /* Export policy. */
1496 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1497 {
1498 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1499 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1500 }
1501 }
1502
paul718e3742002-12-13 20:15:29 +00001503 /* default-originate route-map */
1504 if (conf->default_rmap[afi][safi].name)
1505 {
1506 if (peer->default_rmap[afi][safi].name)
1507 free (peer->default_rmap[afi][safi].name);
1508 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1509 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1510 }
1511
1512 /* update-source apply */
1513 if (conf->update_source)
1514 {
1515 if (peer->update_source)
1516 sockunion_free (peer->update_source);
1517 if (peer->update_if)
1518 {
1519 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1520 peer->update_if = NULL;
1521 }
1522 peer->update_source = sockunion_dup (conf->update_source);
1523 }
1524 else if (conf->update_if)
1525 {
1526 if (peer->update_if)
1527 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1528 if (peer->update_source)
1529 {
1530 sockunion_free (peer->update_source);
1531 peer->update_source = NULL;
1532 }
1533 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1534 }
1535
1536 /* inbound filter apply */
1537 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1538 {
1539 if (pfilter->dlist[in].name)
1540 free (pfilter->dlist[in].name);
1541 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1542 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1543 }
1544 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1545 {
1546 if (pfilter->plist[in].name)
1547 free (pfilter->plist[in].name);
1548 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1549 pfilter->plist[in].plist = gfilter->plist[in].plist;
1550 }
1551 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1552 {
1553 if (pfilter->aslist[in].name)
1554 free (pfilter->aslist[in].name);
1555 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1556 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1557 }
paulfee0f4c2004-09-13 05:12:46 +00001558 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001559 {
paulfee0f4c2004-09-13 05:12:46 +00001560 if (pfilter->map[RMAP_IN].name)
1561 free (pfilter->map[RMAP_IN].name);
1562 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1563 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001564 }
1565
1566 /* outbound filter apply */
1567 if (gfilter->dlist[out].name)
1568 {
1569 if (pfilter->dlist[out].name)
1570 free (pfilter->dlist[out].name);
1571 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1572 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1573 }
1574 else
1575 {
1576 if (pfilter->dlist[out].name)
1577 free (pfilter->dlist[out].name);
1578 pfilter->dlist[out].name = NULL;
1579 pfilter->dlist[out].alist = NULL;
1580 }
1581 if (gfilter->plist[out].name)
1582 {
1583 if (pfilter->plist[out].name)
1584 free (pfilter->plist[out].name);
1585 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1586 pfilter->plist[out].plist = gfilter->plist[out].plist;
1587 }
1588 else
1589 {
1590 if (pfilter->plist[out].name)
1591 free (pfilter->plist[out].name);
1592 pfilter->plist[out].name = NULL;
1593 pfilter->plist[out].plist = NULL;
1594 }
1595 if (gfilter->aslist[out].name)
1596 {
1597 if (pfilter->aslist[out].name)
1598 free (pfilter->aslist[out].name);
1599 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1600 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1601 }
1602 else
1603 {
1604 if (pfilter->aslist[out].name)
1605 free (pfilter->aslist[out].name);
1606 pfilter->aslist[out].name = NULL;
1607 pfilter->aslist[out].aslist = NULL;
1608 }
paulfee0f4c2004-09-13 05:12:46 +00001609 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001610 {
paulfee0f4c2004-09-13 05:12:46 +00001611 if (pfilter->map[RMAP_OUT].name)
1612 free (pfilter->map[RMAP_OUT].name);
1613 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1614 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001615 }
1616 else
1617 {
paulfee0f4c2004-09-13 05:12:46 +00001618 if (pfilter->map[RMAP_OUT].name)
1619 free (pfilter->map[RMAP_OUT].name);
1620 pfilter->map[RMAP_OUT].name = NULL;
1621 pfilter->map[RMAP_OUT].map = NULL;
1622 }
1623
1624 /* RS-client's import/export route-maps. */
1625 if (gfilter->map[RMAP_IMPORT].name)
1626 {
1627 if (pfilter->map[RMAP_IMPORT].name)
1628 free (pfilter->map[RMAP_IMPORT].name);
1629 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1630 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1631 }
1632 else
1633 {
1634 if (pfilter->map[RMAP_IMPORT].name)
1635 free (pfilter->map[RMAP_IMPORT].name);
1636 pfilter->map[RMAP_IMPORT].name = NULL;
1637 pfilter->map[RMAP_IMPORT].map = NULL;
1638 }
1639 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1640 {
1641 if (pfilter->map[RMAP_EXPORT].name)
1642 free (pfilter->map[RMAP_EXPORT].name);
1643 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1644 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001645 }
1646
1647 if (gfilter->usmap.name)
1648 {
1649 if (pfilter->usmap.name)
1650 free (pfilter->usmap.name);
1651 pfilter->usmap.name = strdup (gfilter->usmap.name);
1652 pfilter->usmap.map = gfilter->usmap.map;
1653 }
1654 else
1655 {
1656 if (pfilter->usmap.name)
1657 free (pfilter->usmap.name);
1658 pfilter->usmap.name = NULL;
1659 pfilter->usmap.map = NULL;
1660 }
1661}
1662
1663/* Peer group's remote AS configuration. */
1664int
paulfd79ac92004-10-13 05:06:08 +00001665peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001666{
1667 struct peer_group *group;
1668 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001669 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001670
1671 group = peer_group_lookup (bgp, group_name);
1672 if (! group)
1673 return -1;
1674
1675 if (group->conf->as == *as)
1676 return 0;
1677
1678 /* When we setup peer-group AS number all peer group member's AS
1679 number must be updated to same number. */
1680 peer_as_change (group->conf, *as);
1681
paul1eb8ef22005-04-07 07:30:20 +00001682 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001683 {
1684 if (peer->as != *as)
1685 peer_as_change (peer, *as);
1686 }
1687
1688 return 0;
1689}
1690
1691int
1692peer_group_delete (struct peer_group *group)
1693{
1694 struct bgp *bgp;
1695 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001696 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001697
1698 bgp = group->bgp;
1699
paul1eb8ef22005-04-07 07:30:20 +00001700 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001701 {
paul718e3742002-12-13 20:15:29 +00001702 peer_delete (peer);
1703 }
1704 list_delete (group->peer);
1705
1706 free (group->name);
1707 group->name = NULL;
1708
1709 group->conf->group = NULL;
1710 peer_delete (group->conf);
1711
1712 /* Delete from all peer_group list. */
1713 listnode_delete (bgp->group, group);
1714
1715 peer_group_free (group);
1716
1717 return 0;
1718}
1719
1720int
1721peer_group_remote_as_delete (struct peer_group *group)
1722{
1723 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001724 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001725
1726 if (! group->conf->as)
1727 return 0;
1728
paul1eb8ef22005-04-07 07:30:20 +00001729 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001730 {
paul718e3742002-12-13 20:15:29 +00001731 peer_delete (peer);
1732 }
1733 list_delete_all_node (group->peer);
1734
1735 group->conf->as = 0;
1736
1737 return 0;
1738}
1739
1740/* Bind specified peer to peer group. */
1741int
1742peer_group_bind (struct bgp *bgp, union sockunion *su,
1743 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1744{
1745 struct peer *peer;
1746 int first_member = 0;
1747
1748 /* Check peer group's address family. */
1749 if (! group->conf->afc[afi][safi])
1750 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1751
1752 /* Lookup the peer. */
1753 peer = peer_lookup (bgp, su);
1754
1755 /* Create a new peer. */
1756 if (! peer)
1757 {
1758 if (! group->conf->as)
1759 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1760
1761 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1762 peer->group = group;
1763 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001764
Paul Jakmaca058a32006-09-14 02:58:49 +00001765 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001766 listnode_add (group->peer, peer);
1767 peer_group2peer_config_copy (group, peer, afi, safi);
1768
1769 return 0;
1770 }
1771
1772 /* When the peer already belongs to peer group, check the consistency. */
1773 if (peer->af_group[afi][safi])
1774 {
1775 if (strcmp (peer->group->name, group->name) != 0)
1776 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1777
1778 return 0;
1779 }
1780
1781 /* Check current peer group configuration. */
1782 if (peer_group_active (peer)
1783 && strcmp (peer->group->name, group->name) != 0)
1784 return BGP_ERR_PEER_GROUP_MISMATCH;
1785
1786 if (! group->conf->as)
1787 {
1788 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1789 && peer_sort (group->conf) != peer_sort (peer))
1790 {
1791 if (as)
1792 *as = peer->as;
1793 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1794 }
1795
1796 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1797 first_member = 1;
1798 }
1799
1800 peer->af_group[afi][safi] = 1;
1801 peer->afc[afi][safi] = 1;
1802 if (! peer->group)
1803 {
1804 peer->group = group;
paul200df112005-06-01 11:17:05 +00001805
Paul Jakmaca058a32006-09-14 02:58:49 +00001806 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001807 listnode_add (group->peer, peer);
1808 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001809 else
1810 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001811
1812 if (first_member)
1813 {
1814 /* Advertisement-interval reset */
1815 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1816 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1817 else
1818 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1819
1820 /* ebgp-multihop reset */
1821 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1822 group->conf->ttl = 255;
1823
1824 /* local-as reset */
1825 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1826 {
1827 group->conf->change_local_as = 0;
1828 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001829 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001830 }
1831 }
paulfee0f4c2004-09-13 05:12:46 +00001832
1833 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1834 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001835 struct listnode *pn;
1836
paulfee0f4c2004-09-13 05:12:46 +00001837 /* If it's not configured as RSERVER_CLIENT in any other address
1838 family, without being member of a peer_group, remove it from
1839 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001840 if (! peer_rsclient_active (peer)
1841 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001842 {
1843 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001844 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001845
1846 /* Clear our own rsclient rib for this afi/safi. */
1847 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001848 }
paulfee0f4c2004-09-13 05:12:46 +00001849
Paul Jakmab608d5b2008-07-02 02:12:07 +00001850 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001851
1852 /* Import policy. */
1853 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1854 {
1855 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1856 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1857 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1858 }
1859
1860 /* Export policy. */
1861 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1862 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1863 {
1864 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1865 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1866 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1867 }
1868 }
1869
paul718e3742002-12-13 20:15:29 +00001870 peer_group2peer_config_copy (group, peer, afi, safi);
1871
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001872 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001873 {
1874 peer->last_reset = PEER_DOWN_RMAP_BIND;
1875 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1876 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1877 }
paul718e3742002-12-13 20:15:29 +00001878 else
1879 BGP_EVENT_ADD (peer, BGP_Stop);
1880
1881 return 0;
1882}
1883
1884int
1885peer_group_unbind (struct bgp *bgp, struct peer *peer,
1886 struct peer_group *group, afi_t afi, safi_t safi)
1887{
1888 if (! peer->af_group[afi][safi])
1889 return 0;
1890
1891 if (group != peer->group)
1892 return BGP_ERR_PEER_GROUP_MISMATCH;
1893
1894 peer->af_group[afi][safi] = 0;
1895 peer->afc[afi][safi] = 0;
1896 peer_af_flag_reset (peer, afi, safi);
1897
paulfee0f4c2004-09-13 05:12:46 +00001898 if (peer->rib[afi][safi])
1899 peer->rib[afi][safi] = NULL;
1900
paul718e3742002-12-13 20:15:29 +00001901 if (! peer_group_active (peer))
1902 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001903 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001904 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001905 listnode_delete (group->peer, peer);
1906 peer->group = NULL;
1907 if (group->conf->as)
1908 {
1909 peer_delete (peer);
1910 return 0;
1911 }
1912 peer_global_config_reset (peer);
1913 }
1914
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001915 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001916 {
1917 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1918 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1919 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1920 }
paul718e3742002-12-13 20:15:29 +00001921 else
1922 BGP_EVENT_ADD (peer, BGP_Stop);
1923
1924 return 0;
1925}
David Lamparter6b0655a2014-06-04 06:53:35 +02001926
Vipin Kumardd49eb12014-09-30 14:36:38 -07001927
1928static int
1929bgp_startup_timer_expire (struct thread *thread)
1930{
1931 struct bgp *bgp;
1932
1933 bgp = THREAD_ARG (thread);
1934 bgp->t_startup = NULL;
1935
1936 return 0;
1937}
1938
paul718e3742002-12-13 20:15:29 +00001939/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001940static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001941bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001942{
1943 struct bgp *bgp;
1944 afi_t afi;
1945 safi_t safi;
1946
paul200df112005-06-01 11:17:05 +00001947 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1948 return NULL;
1949
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07001950 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00001951 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00001952 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00001953
1954 bgp->peer = list_new ();
1955 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1956
1957 bgp->group = list_new ();
1958 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1959
paulfee0f4c2004-09-13 05:12:46 +00001960 bgp->rsclient = list_new ();
1961 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1962
paul718e3742002-12-13 20:15:29 +00001963 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1964 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1965 {
Paul Jakma64e580a2006-02-21 01:09:01 +00001966 bgp->route[afi][safi] = bgp_table_init (afi, safi);
1967 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1968 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07001969 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
1970 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00001971 }
1972
1973 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1974 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1975 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001976 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1977 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001978
1979 bgp->as = *as;
1980
1981 if (name)
1982 bgp->name = strdup (name);
1983
Donald Sharp774914f2015-10-14 08:50:39 -04001984 THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire,
Vipin Kumardd49eb12014-09-30 14:36:38 -07001985 bgp, bgp->restart_time);
1986
paul718e3742002-12-13 20:15:29 +00001987 return bgp;
1988}
1989
1990/* Return first entry of BGP. */
1991struct bgp *
paul94f2b392005-06-28 12:44:16 +00001992bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001993{
Lou Berger056f3762013-04-10 12:30:04 -07001994 if (bm && bm->bgp && bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001995 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001996 return NULL;
1997}
1998
1999/* Lookup BGP entry. */
2000struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002001bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00002002{
2003 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002004 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002005
paul1eb8ef22005-04-07 07:30:20 +00002006 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002007 if (bgp->as == as
2008 && ((bgp->name == NULL && name == NULL)
2009 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
2010 return bgp;
2011 return NULL;
2012}
2013
2014/* Lookup BGP structure by view name. */
2015struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002016bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002017{
2018 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002019 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002020
paul1eb8ef22005-04-07 07:30:20 +00002021 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002022 if ((bgp->name == NULL && name == NULL)
2023 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2024 return bgp;
2025 return NULL;
2026}
2027
2028/* Called from VTY commands. */
2029int
paulfd79ac92004-10-13 05:06:08 +00002030bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002031{
2032 struct bgp *bgp;
2033
2034 /* Multiple instance check. */
2035 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2036 {
2037 if (name)
2038 bgp = bgp_lookup_by_name (name);
2039 else
2040 bgp = bgp_get_default ();
2041
2042 /* Already exists. */
2043 if (bgp)
2044 {
2045 if (bgp->as != *as)
2046 {
2047 *as = bgp->as;
2048 return BGP_ERR_INSTANCE_MISMATCH;
2049 }
2050 *bgp_val = bgp;
2051 return 0;
2052 }
2053 }
2054 else
2055 {
2056 /* BGP instance name can not be specified for single instance. */
2057 if (name)
2058 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2059
2060 /* Get default BGP structure if exists. */
2061 bgp = bgp_get_default ();
2062
2063 if (bgp)
2064 {
2065 if (bgp->as != *as)
2066 {
2067 *as = bgp->as;
2068 return BGP_ERR_AS_MISMATCH;
2069 }
2070 *bgp_val = bgp;
2071 return 0;
2072 }
2073 }
2074
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002075 bgp = bgp_create (as, name);
2076 bgp_router_id_set(bgp, &router_id_zebra);
2077 *bgp_val = bgp;
2078
Paul Jakmaad12dde2012-06-13 22:50:07 +01002079 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002080 if (list_isempty(bm->bgp)
2081 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002082 {
2083 if (bgp_socket (bm->port, bm->address) < 0)
2084 return BGP_ERR_INVALID_VALUE;
2085 }
2086
paul718e3742002-12-13 20:15:29 +00002087 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002088
2089 return 0;
2090}
2091
2092/* Delete BGP instance. */
2093int
2094bgp_delete (struct bgp *bgp)
2095{
2096 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002097 struct peer_group *group;
Denil Vira57cd5e72015-08-10 12:46:14 -07002098 struct listnode *node, *pnode;
2099 struct listnode *next, *pnext;
paul718e3742002-12-13 20:15:29 +00002100 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002101 int i;
2102
David Lampartercffe7802014-12-07 03:27:13 +01002103 THREAD_OFF (bgp->t_startup);
2104
paul718e3742002-12-13 20:15:29 +00002105 /* Delete static route. */
2106 bgp_static_delete (bgp);
2107
2108 /* Unset redistribution. */
2109 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2110 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2111 if (i != ZEBRA_ROUTE_BGP)
2112 bgp_redistribute_unset (bgp, afi, i);
2113
paul1eb8ef22005-04-07 07:30:20 +00002114 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002115 {
2116 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2117 {
2118 /* Send notify to remote peer. */
2119 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2120 }
2121
2122 peer_delete (peer);
2123 }
paul718e3742002-12-13 20:15:29 +00002124
Chris Caputo228da422009-07-18 05:44:03 +00002125 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002126 {
Denil Vira57cd5e72015-08-10 12:46:14 -07002127 for (ALL_LIST_ELEMENTS (group->peer, pnode, pnext, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002128 {
2129 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2130 {
2131 /* Send notify to remote peer. */
2132 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2133 }
2134 }
2135 peer_group_delete (group);
2136 }
Chris Caputo228da422009-07-18 05:44:03 +00002137
2138 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002139
2140 if (bgp->peer_self) {
2141 peer_delete(bgp->peer_self);
2142 bgp->peer_self = NULL;
2143 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002144
2145 /* Remove visibility via the master list - there may however still be
2146 * routes to be processed still referencing the struct bgp.
2147 */
2148 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002149 if (list_isempty(bm->bgp))
2150 bgp_close ();
2151
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002152 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002153
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002154 return 0;
2155}
2156
2157static void bgp_free (struct bgp *);
2158
2159void
2160bgp_lock (struct bgp *bgp)
2161{
2162 ++bgp->lock;
2163}
2164
2165void
2166bgp_unlock(struct bgp *bgp)
2167{
Chris Caputo228da422009-07-18 05:44:03 +00002168 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002169 if (--bgp->lock == 0)
2170 bgp_free (bgp);
2171}
2172
2173static void
2174bgp_free (struct bgp *bgp)
2175{
2176 afi_t afi;
2177 safi_t safi;
2178
2179 list_delete (bgp->group);
2180 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002181 list_delete (bgp->rsclient);
2182
paul718e3742002-12-13 20:15:29 +00002183 if (bgp->name)
2184 free (bgp->name);
2185
2186 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2187 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2188 {
2189 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002190 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002191 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002192 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002193 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002194 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002195 }
2196 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002197}
David Lamparter6b0655a2014-06-04 06:53:35 +02002198
paul718e3742002-12-13 20:15:29 +00002199struct peer *
2200peer_lookup (struct bgp *bgp, union sockunion *su)
2201{
2202 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002203 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002204
Steve Hillfc4dc592009-07-28 17:54:35 +01002205 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002206 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002207 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2208 if (sockunion_same (&peer->su, su)
2209 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2210 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002211 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002212 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002213 {
2214 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002215
Paul Jakma2158ad22009-07-28 18:10:55 +01002216 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2217 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2218 if (sockunion_same (&peer->su, su)
2219 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2220 return peer;
paul718e3742002-12-13 20:15:29 +00002221 }
2222 return NULL;
2223}
2224
2225struct peer *
2226peer_lookup_with_open (union sockunion *su, as_t remote_as,
2227 struct in_addr *remote_id, int *as)
2228{
2229 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002230 struct listnode *node;
2231 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002232 struct bgp *bgp;
2233
Steve Hillfc4dc592009-07-28 17:54:35 +01002234 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002235 return NULL;
2236
Paul Jakma9d878772009-08-05 16:25:16 +01002237 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002238 {
Paul Jakma9d878772009-08-05 16:25:16 +01002239 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2240 {
2241 if (sockunion_same (&peer->su, su)
2242 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2243 {
2244 if (peer->as == remote_as
2245 && peer->remote_id.s_addr == remote_id->s_addr)
2246 return peer;
2247 if (peer->as == remote_as)
2248 *as = 1;
2249 }
2250 }
2251
2252 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2253 {
2254 if (sockunion_same (&peer->su, su)
2255 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2256 {
2257 if (peer->as == remote_as
2258 && peer->remote_id.s_addr == 0)
2259 return peer;
2260 if (peer->as == remote_as)
2261 *as = 1;
2262 }
2263 }
paul718e3742002-12-13 20:15:29 +00002264 }
2265 return NULL;
2266}
David Lamparter6b0655a2014-06-04 06:53:35 +02002267
paul718e3742002-12-13 20:15:29 +00002268/* If peer is configured at least one address family return 1. */
2269int
2270peer_active (struct peer *peer)
2271{
2272 if (peer->afc[AFI_IP][SAFI_UNICAST]
2273 || peer->afc[AFI_IP][SAFI_MULTICAST]
2274 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2275 || peer->afc[AFI_IP6][SAFI_UNICAST]
2276 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2277 return 1;
2278 return 0;
2279}
2280
2281/* If peer is negotiated at least one address family return 1. */
2282int
2283peer_active_nego (struct peer *peer)
2284{
2285 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2286 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2287 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2288 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2289 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2290 return 1;
2291 return 0;
2292}
David Lamparter6b0655a2014-06-04 06:53:35 +02002293
paul718e3742002-12-13 20:15:29 +00002294/* peer_flag_change_type. */
2295enum peer_change_type
2296{
2297 peer_change_none,
2298 peer_change_reset,
2299 peer_change_reset_in,
2300 peer_change_reset_out,
2301};
2302
paul94f2b392005-06-28 12:44:16 +00002303static void
paul718e3742002-12-13 20:15:29 +00002304peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2305 enum peer_change_type type)
2306{
2307 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2308 return;
2309
Stephen Hemmingerd9d4ae52010-01-13 00:32:39 +00002310 if (peer->status != Established)
2311 return;
2312
paul718e3742002-12-13 20:15:29 +00002313 if (type == peer_change_reset)
2314 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2315 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2316 else if (type == peer_change_reset_in)
2317 {
2318 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2319 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2320 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2321 else
2322 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2323 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2324 }
2325 else if (type == peer_change_reset_out)
2326 bgp_announce_route (peer, afi, safi);
2327}
2328
2329struct peer_flag_action
2330{
2331 /* Peer's flag. */
2332 u_int32_t flag;
2333
2334 /* This flag can be set for peer-group member. */
2335 u_char not_for_member;
2336
2337 /* Action when the flag is changed. */
2338 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002339
2340 /* Peer down cause */
2341 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002342};
2343
Stephen Hemminger03621952009-07-21 16:27:20 -07002344static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002345 {
2346 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2347 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2348 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2349 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2350 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002351 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002352 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002353 { 0, 0, 0 }
2354 };
2355
Stephen Hemminger03621952009-07-21 16:27:20 -07002356static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002357 {
2358 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2359 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2360 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2361 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2362 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2363 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2364 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2365 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2366 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2367 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2368 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2369 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2370 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002371 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
Timo Teräs9e7a53c2014-04-24 10:22:37 +03002372 { PEER_FLAG_NEXTHOP_SELF_ALL, 1, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002373 { 0, 0, 0 }
2374 };
2375
2376/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002377static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002378peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002379 struct peer_flag_action *action, u_int32_t flag)
2380{
2381 int i;
2382 int found = 0;
2383 int reset_in = 0;
2384 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002385 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002386
2387 /* Check peer's frag action. */
2388 for (i = 0; i < size; i++)
2389 {
2390 match = &action_list[i];
2391
2392 if (match->flag == 0)
2393 break;
2394
2395 if (match->flag & flag)
2396 {
2397 found = 1;
2398
2399 if (match->type == peer_change_reset_in)
2400 reset_in = 1;
2401 if (match->type == peer_change_reset_out)
2402 reset_out = 1;
2403 if (match->type == peer_change_reset)
2404 {
2405 reset_in = 1;
2406 reset_out = 1;
2407 }
2408 if (match->not_for_member)
2409 action->not_for_member = 1;
2410 }
2411 }
2412
2413 /* Set peer clear type. */
2414 if (reset_in && reset_out)
2415 action->type = peer_change_reset;
2416 else if (reset_in)
2417 action->type = peer_change_reset_in;
2418 else if (reset_out)
2419 action->type = peer_change_reset_out;
2420 else
2421 action->type = peer_change_none;
2422
2423 return found;
2424}
2425
paul94f2b392005-06-28 12:44:16 +00002426static void
paul718e3742002-12-13 20:15:29 +00002427peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2428{
2429 if (flag == PEER_FLAG_SHUTDOWN)
2430 {
2431 if (CHECK_FLAG (peer->flags, flag))
2432 {
hasso93406d82005-02-02 14:40:33 +00002433 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2434 peer_nsf_stop (peer);
2435
hasso0a486e52005-02-01 20:57:17 +00002436 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2437 if (peer->t_pmax_restart)
2438 {
2439 BGP_TIMER_OFF (peer->t_pmax_restart);
2440 if (BGP_DEBUG (events, EVENTS))
2441 zlog_debug ("%s Maximum-prefix restart timer canceled",
2442 peer->host);
2443 }
2444
hasso93406d82005-02-02 14:40:33 +00002445 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2446 peer_nsf_stop (peer);
2447
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002448 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002449 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2450 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2451 else
2452 BGP_EVENT_ADD (peer, BGP_Stop);
2453 }
2454 else
2455 {
2456 peer->v_start = BGP_INIT_START_TIMER;
2457 BGP_EVENT_ADD (peer, BGP_Stop);
2458 }
2459 }
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002460 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002461 {
hassoc9502432005-02-01 22:01:48 +00002462 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2463 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2464 else if (flag == PEER_FLAG_PASSIVE)
2465 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002466 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002467 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002468
hassoc9502432005-02-01 22:01:48 +00002469 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2470 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002471 }
2472 else
2473 BGP_EVENT_ADD (peer, BGP_Stop);
2474}
2475
2476/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002477static int
paul718e3742002-12-13 20:15:29 +00002478peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2479{
2480 int found;
2481 int size;
2482 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002483 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002484 struct peer_flag_action action;
2485
2486 memset (&action, 0, sizeof (struct peer_flag_action));
2487 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2488
2489 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2490
2491 /* No flag action is found. */
2492 if (! found)
2493 return BGP_ERR_INVALID_FLAG;
2494
2495 /* Not for peer-group member. */
2496 if (action.not_for_member && peer_group_active (peer))
2497 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2498
2499 /* When unset the peer-group member's flag we have to check
2500 peer-group configuration. */
2501 if (! set && peer_group_active (peer))
2502 if (CHECK_FLAG (peer->group->conf->flags, flag))
2503 {
2504 if (flag == PEER_FLAG_SHUTDOWN)
2505 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2506 else
2507 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2508 }
2509
2510 /* Flag conflict check. */
2511 if (set
2512 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2513 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2514 return BGP_ERR_PEER_FLAG_CONFLICT;
2515
2516 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2517 {
2518 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2519 return 0;
2520 if (! set && ! CHECK_FLAG (peer->flags, flag))
2521 return 0;
2522 }
2523
2524 if (set)
2525 SET_FLAG (peer->flags, flag);
2526 else
2527 UNSET_FLAG (peer->flags, flag);
2528
2529 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2530 {
2531 if (action.type == peer_change_reset)
2532 peer_flag_modify_action (peer, flag);
2533
2534 return 0;
2535 }
2536
2537 /* peer-group member updates. */
2538 group = peer->group;
2539
paul1eb8ef22005-04-07 07:30:20 +00002540 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002541 {
2542 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2543 continue;
2544
2545 if (! set && ! CHECK_FLAG (peer->flags, flag))
2546 continue;
2547
2548 if (set)
2549 SET_FLAG (peer->flags, flag);
2550 else
2551 UNSET_FLAG (peer->flags, flag);
2552
2553 if (action.type == peer_change_reset)
2554 peer_flag_modify_action (peer, flag);
2555 }
2556 return 0;
2557}
2558
2559int
2560peer_flag_set (struct peer *peer, u_int32_t flag)
2561{
2562 return peer_flag_modify (peer, flag, 1);
2563}
2564
2565int
2566peer_flag_unset (struct peer *peer, u_int32_t flag)
2567{
2568 return peer_flag_modify (peer, flag, 0);
2569}
2570
paul94f2b392005-06-28 12:44:16 +00002571static int
paul718e3742002-12-13 20:15:29 +00002572peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2573{
2574 if (peer->af_group[afi][safi])
2575 return 1;
2576 return 0;
2577}
2578
paul94f2b392005-06-28 12:44:16 +00002579static int
paul718e3742002-12-13 20:15:29 +00002580peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2581 int set)
2582{
2583 int found;
2584 int size;
paul1eb8ef22005-04-07 07:30:20 +00002585 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002586 struct peer_group *group;
2587 struct peer_flag_action action;
2588
2589 memset (&action, 0, sizeof (struct peer_flag_action));
2590 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2591
2592 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2593
2594 /* No flag action is found. */
2595 if (! found)
2596 return BGP_ERR_INVALID_FLAG;
2597
2598 /* Adress family must be activated. */
2599 if (! peer->afc[afi][safi])
2600 return BGP_ERR_PEER_INACTIVE;
2601
2602 /* Not for peer-group member. */
2603 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2604 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2605
2606 /* Spcecial check for reflector client. */
2607 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2608 && peer_sort (peer) != BGP_PEER_IBGP)
2609 return BGP_ERR_NOT_INTERNAL_PEER;
2610
2611 /* Spcecial check for remove-private-AS. */
2612 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2613 && peer_sort (peer) == BGP_PEER_IBGP)
2614 return BGP_ERR_REMOVE_PRIVATE_AS;
2615
2616 /* When unset the peer-group member's flag we have to check
2617 peer-group configuration. */
2618 if (! set && peer->af_group[afi][safi])
2619 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2620 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2621
2622 /* When current flag configuration is same as requested one. */
2623 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2624 {
2625 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2626 return 0;
2627 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2628 return 0;
2629 }
2630
2631 if (set)
2632 SET_FLAG (peer->af_flags[afi][safi], flag);
2633 else
2634 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2635
2636 /* Execute action when peer is established. */
2637 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2638 && peer->status == Established)
2639 {
2640 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2641 bgp_clear_adj_in (peer, afi, safi);
2642 else
hassoe0701b72004-05-20 09:19:34 +00002643 {
2644 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2645 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2646 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2647 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2648 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2649 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2650 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2651 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2652
2653 peer_change_action (peer, afi, safi, action.type);
2654 }
2655
paul718e3742002-12-13 20:15:29 +00002656 }
2657
2658 /* Peer group member updates. */
2659 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2660 {
2661 group = peer->group;
2662
paul1eb8ef22005-04-07 07:30:20 +00002663 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002664 {
2665 if (! peer->af_group[afi][safi])
2666 continue;
2667
2668 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2669 continue;
2670
2671 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2672 continue;
2673
2674 if (set)
2675 SET_FLAG (peer->af_flags[afi][safi], flag);
2676 else
2677 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2678
2679 if (peer->status == Established)
2680 {
2681 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2682 bgp_clear_adj_in (peer, afi, safi);
2683 else
hassoe0701b72004-05-20 09:19:34 +00002684 {
2685 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2686 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2687 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2688 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2689 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2690 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2691 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2692 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2693
2694 peer_change_action (peer, afi, safi, action.type);
2695 }
paul718e3742002-12-13 20:15:29 +00002696 }
2697 }
2698 }
2699 return 0;
2700}
2701
2702int
2703peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2704{
2705 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2706}
2707
2708int
2709peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2710{
2711 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2712}
David Lamparter6b0655a2014-06-04 06:53:35 +02002713
paul718e3742002-12-13 20:15:29 +00002714/* EBGP multihop configuration. */
2715int
2716peer_ebgp_multihop_set (struct peer *peer, int ttl)
2717{
2718 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002719 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002720 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002721
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002722 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002723 return 0;
2724
Nick Hilliardfa411a22011-03-23 15:33:17 +00002725 /* see comment in peer_ttl_security_hops_set() */
2726 if (ttl != MAXTTL)
2727 {
2728 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2729 {
2730 group = peer->group;
2731 if (group->conf->gtsm_hops != 0)
2732 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2733
2734 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2735 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002736 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002737 continue;
2738
2739 if (peer1->gtsm_hops != 0)
2740 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2741 }
2742 }
2743 else
2744 {
2745 if (peer->gtsm_hops != 0)
2746 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2747 }
2748 }
2749
paul718e3742002-12-13 20:15:29 +00002750 peer->ttl = ttl;
2751
2752 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2753 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002754 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002755 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002756 }
2757 else
2758 {
2759 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002760 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002761 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002762 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002763 continue;
paul718e3742002-12-13 20:15:29 +00002764
pauleb821182004-05-01 08:44:08 +00002765 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002766
pauleb821182004-05-01 08:44:08 +00002767 if (peer->fd >= 0)
2768 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2769 }
paul718e3742002-12-13 20:15:29 +00002770 }
2771 return 0;
2772}
2773
2774int
2775peer_ebgp_multihop_unset (struct peer *peer)
2776{
2777 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002778 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002779
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002780 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002781 return 0;
2782
Nick Hilliardfa411a22011-03-23 15:33:17 +00002783 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2784 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2785
paul718e3742002-12-13 20:15:29 +00002786 if (peer_group_active (peer))
2787 peer->ttl = peer->group->conf->ttl;
2788 else
2789 peer->ttl = 1;
2790
2791 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2792 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002793 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002794 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002795 }
2796 else
2797 {
2798 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002799 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002800 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002801 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002802 continue;
paul718e3742002-12-13 20:15:29 +00002803
pauleb821182004-05-01 08:44:08 +00002804 peer->ttl = 1;
2805
2806 if (peer->fd >= 0)
2807 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2808 }
paul718e3742002-12-13 20:15:29 +00002809 }
2810 return 0;
2811}
David Lamparter6b0655a2014-06-04 06:53:35 +02002812
paul718e3742002-12-13 20:15:29 +00002813/* Neighbor description. */
2814int
2815peer_description_set (struct peer *peer, char *desc)
2816{
2817 if (peer->desc)
2818 XFREE (MTYPE_PEER_DESC, peer->desc);
2819
2820 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2821
2822 return 0;
2823}
2824
2825int
2826peer_description_unset (struct peer *peer)
2827{
2828 if (peer->desc)
2829 XFREE (MTYPE_PEER_DESC, peer->desc);
2830
2831 peer->desc = NULL;
2832
2833 return 0;
2834}
David Lamparter6b0655a2014-06-04 06:53:35 +02002835
paul718e3742002-12-13 20:15:29 +00002836/* Neighbor update-source. */
2837int
paulfd79ac92004-10-13 05:06:08 +00002838peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002839{
2840 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002841 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002842
2843 if (peer->update_if)
2844 {
2845 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2846 && strcmp (peer->update_if, ifname) == 0)
2847 return 0;
2848
2849 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2850 peer->update_if = NULL;
2851 }
2852
2853 if (peer->update_source)
2854 {
2855 sockunion_free (peer->update_source);
2856 peer->update_source = NULL;
2857 }
2858
2859 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2860
2861 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2862 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002863 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002864 {
2865 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2866 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2867 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2868 }
paul718e3742002-12-13 20:15:29 +00002869 else
2870 BGP_EVENT_ADD (peer, BGP_Stop);
2871 return 0;
2872 }
2873
2874 /* peer-group member updates. */
2875 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002876 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002877 {
2878 if (peer->update_if)
2879 {
2880 if (strcmp (peer->update_if, ifname) == 0)
2881 continue;
2882
2883 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2884 peer->update_if = NULL;
2885 }
2886
2887 if (peer->update_source)
2888 {
2889 sockunion_free (peer->update_source);
2890 peer->update_source = NULL;
2891 }
2892
2893 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2894
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002895 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002896 {
2897 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2898 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2899 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2900 }
paul718e3742002-12-13 20:15:29 +00002901 else
2902 BGP_EVENT_ADD (peer, BGP_Stop);
2903 }
2904 return 0;
2905}
2906
2907int
2908peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2909{
2910 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002911 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002912
2913 if (peer->update_source)
2914 {
2915 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2916 && sockunion_cmp (peer->update_source, su) == 0)
2917 return 0;
2918 sockunion_free (peer->update_source);
2919 peer->update_source = NULL;
2920 }
2921
2922 if (peer->update_if)
2923 {
2924 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2925 peer->update_if = NULL;
2926 }
2927
2928 peer->update_source = sockunion_dup (su);
2929
2930 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2931 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002932 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002933 {
2934 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2935 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2936 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2937 }
paul718e3742002-12-13 20:15:29 +00002938 else
2939 BGP_EVENT_ADD (peer, BGP_Stop);
2940 return 0;
2941 }
2942
2943 /* peer-group member updates. */
2944 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002945 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002946 {
2947 if (peer->update_source)
2948 {
2949 if (sockunion_cmp (peer->update_source, su) == 0)
2950 continue;
2951 sockunion_free (peer->update_source);
2952 peer->update_source = NULL;
2953 }
2954
2955 if (peer->update_if)
2956 {
2957 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2958 peer->update_if = NULL;
2959 }
2960
2961 peer->update_source = sockunion_dup (su);
2962
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002963 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002964 {
2965 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2966 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2967 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2968 }
paul718e3742002-12-13 20:15:29 +00002969 else
2970 BGP_EVENT_ADD (peer, BGP_Stop);
2971 }
2972 return 0;
2973}
2974
2975int
2976peer_update_source_unset (struct peer *peer)
2977{
2978 union sockunion *su;
2979 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002980 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002981
2982 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2983 && ! peer->update_source
2984 && ! peer->update_if)
2985 return 0;
2986
2987 if (peer->update_source)
2988 {
2989 sockunion_free (peer->update_source);
2990 peer->update_source = NULL;
2991 }
2992 if (peer->update_if)
2993 {
2994 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2995 peer->update_if = NULL;
2996 }
2997
2998 if (peer_group_active (peer))
2999 {
3000 group = peer->group;
3001
3002 if (group->conf->update_source)
3003 {
3004 su = sockunion_dup (group->conf->update_source);
3005 peer->update_source = su;
3006 }
3007 else if (group->conf->update_if)
3008 peer->update_if =
3009 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
3010 }
3011
3012 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3013 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003014 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003015 {
3016 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3017 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3018 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3019 }
paul718e3742002-12-13 20:15:29 +00003020 else
3021 BGP_EVENT_ADD (peer, BGP_Stop);
3022 return 0;
3023 }
3024
3025 /* peer-group member updates. */
3026 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003027 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003028 {
3029 if (! peer->update_source && ! peer->update_if)
3030 continue;
3031
3032 if (peer->update_source)
3033 {
3034 sockunion_free (peer->update_source);
3035 peer->update_source = NULL;
3036 }
3037
3038 if (peer->update_if)
3039 {
3040 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3041 peer->update_if = NULL;
3042 }
3043
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003044 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003045 {
3046 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3047 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3048 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3049 }
paul718e3742002-12-13 20:15:29 +00003050 else
3051 BGP_EVENT_ADD (peer, BGP_Stop);
3052 }
3053 return 0;
3054}
David Lamparter6b0655a2014-06-04 06:53:35 +02003055
paul718e3742002-12-13 20:15:29 +00003056int
3057peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003058 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003059{
3060 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003061 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003062
3063 /* Adress family must be activated. */
3064 if (! peer->afc[afi][safi])
3065 return BGP_ERR_PEER_INACTIVE;
3066
3067 /* Default originate can't be used for peer group memeber. */
3068 if (peer_is_group_member (peer, afi, safi))
3069 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3070
3071 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3072 || (rmap && ! peer->default_rmap[afi][safi].name)
3073 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3074 {
3075 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3076
3077 if (rmap)
3078 {
3079 if (peer->default_rmap[afi][safi].name)
3080 free (peer->default_rmap[afi][safi].name);
3081 peer->default_rmap[afi][safi].name = strdup (rmap);
3082 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3083 }
3084 }
3085
3086 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3087 {
3088 if (peer->status == Established && peer->afc_nego[afi][safi])
3089 bgp_default_originate (peer, afi, safi, 0);
3090 return 0;
3091 }
3092
3093 /* peer-group member updates. */
3094 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003095 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003096 {
3097 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3098
3099 if (rmap)
3100 {
3101 if (peer->default_rmap[afi][safi].name)
3102 free (peer->default_rmap[afi][safi].name);
3103 peer->default_rmap[afi][safi].name = strdup (rmap);
3104 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3105 }
3106
3107 if (peer->status == Established && peer->afc_nego[afi][safi])
3108 bgp_default_originate (peer, afi, safi, 0);
3109 }
3110 return 0;
3111}
3112
3113int
3114peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3115{
3116 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003117 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003118
3119 /* Adress family must be activated. */
3120 if (! peer->afc[afi][safi])
3121 return BGP_ERR_PEER_INACTIVE;
3122
3123 /* Default originate can't be used for peer group memeber. */
3124 if (peer_is_group_member (peer, afi, safi))
3125 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3126
3127 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3128 {
3129 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3130
3131 if (peer->default_rmap[afi][safi].name)
3132 free (peer->default_rmap[afi][safi].name);
3133 peer->default_rmap[afi][safi].name = NULL;
3134 peer->default_rmap[afi][safi].map = NULL;
3135 }
3136
3137 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3138 {
3139 if (peer->status == Established && peer->afc_nego[afi][safi])
3140 bgp_default_originate (peer, afi, safi, 1);
3141 return 0;
3142 }
3143
3144 /* peer-group member updates. */
3145 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003146 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003147 {
3148 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3149
3150 if (peer->default_rmap[afi][safi].name)
3151 free (peer->default_rmap[afi][safi].name);
3152 peer->default_rmap[afi][safi].name = NULL;
3153 peer->default_rmap[afi][safi].map = NULL;
3154
3155 if (peer->status == Established && peer->afc_nego[afi][safi])
3156 bgp_default_originate (peer, afi, safi, 1);
3157 }
3158 return 0;
3159}
David Lamparter6b0655a2014-06-04 06:53:35 +02003160
paul718e3742002-12-13 20:15:29 +00003161int
3162peer_port_set (struct peer *peer, u_int16_t port)
3163{
3164 peer->port = port;
3165 return 0;
3166}
3167
3168int
3169peer_port_unset (struct peer *peer)
3170{
3171 peer->port = BGP_PORT_DEFAULT;
3172 return 0;
3173}
David Lamparter6b0655a2014-06-04 06:53:35 +02003174
paul718e3742002-12-13 20:15:29 +00003175/* neighbor weight. */
3176int
3177peer_weight_set (struct peer *peer, u_int16_t weight)
3178{
3179 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003180 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003181
3182 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3183 peer->weight = weight;
3184
3185 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3186 return 0;
3187
3188 /* peer-group member updates. */
3189 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003190 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003191 {
3192 peer->weight = group->conf->weight;
3193 }
3194 return 0;
3195}
3196
3197int
3198peer_weight_unset (struct peer *peer)
3199{
3200 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003201 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003202
3203 /* Set default weight. */
3204 if (peer_group_active (peer))
3205 peer->weight = peer->group->conf->weight;
3206 else
3207 peer->weight = 0;
3208
3209 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3210
3211 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3212 return 0;
3213
3214 /* peer-group member updates. */
3215 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003216 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003217 {
3218 peer->weight = 0;
3219 }
3220 return 0;
3221}
David Lamparter6b0655a2014-06-04 06:53:35 +02003222
paul718e3742002-12-13 20:15:29 +00003223int
3224peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3225{
3226 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003227 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003228
3229 /* Not for peer group memeber. */
3230 if (peer_group_active (peer))
3231 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3232
3233 /* keepalive value check. */
3234 if (keepalive > 65535)
3235 return BGP_ERR_INVALID_VALUE;
3236
3237 /* Holdtime value check. */
3238 if (holdtime > 65535)
3239 return BGP_ERR_INVALID_VALUE;
3240
3241 /* Holdtime value must be either 0 or greater than 3. */
3242 if (holdtime < 3 && holdtime != 0)
3243 return BGP_ERR_INVALID_VALUE;
3244
3245 /* Set value to the configuration. */
3246 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3247 peer->holdtime = holdtime;
3248 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3249
3250 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3251 return 0;
3252
3253 /* peer-group member updates. */
3254 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003255 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003256 {
3257 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3258 peer->holdtime = group->conf->holdtime;
3259 peer->keepalive = group->conf->keepalive;
3260 }
3261 return 0;
3262}
3263
3264int
3265peer_timers_unset (struct peer *peer)
3266{
3267 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003268 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003269
3270 if (peer_group_active (peer))
3271 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3272
3273 /* Clear configuration. */
3274 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3275 peer->keepalive = 0;
3276 peer->holdtime = 0;
3277
3278 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3279 return 0;
3280
3281 /* peer-group member updates. */
3282 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003283 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003284 {
3285 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3286 peer->holdtime = 0;
3287 peer->keepalive = 0;
3288 }
3289
3290 return 0;
3291}
David Lamparter6b0655a2014-06-04 06:53:35 +02003292
paul718e3742002-12-13 20:15:29 +00003293int
3294peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3295{
3296 if (peer_group_active (peer))
3297 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3298
3299 if (connect > 65535)
3300 return BGP_ERR_INVALID_VALUE;
3301
3302 /* Set value to the configuration. */
3303 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3304 peer->connect = connect;
3305
3306 /* Set value to timer setting. */
3307 peer->v_connect = connect;
3308
3309 return 0;
3310}
3311
3312int
3313peer_timers_connect_unset (struct peer *peer)
3314{
3315 if (peer_group_active (peer))
3316 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3317
3318 /* Clear configuration. */
3319 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3320 peer->connect = 0;
3321
3322 /* Set timer setting to default value. */
3323 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3324
3325 return 0;
3326}
David Lamparter6b0655a2014-06-04 06:53:35 +02003327
paul718e3742002-12-13 20:15:29 +00003328int
3329peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3330{
3331 if (peer_group_active (peer))
3332 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3333
3334 if (routeadv > 600)
3335 return BGP_ERR_INVALID_VALUE;
3336
3337 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3338 peer->routeadv = routeadv;
3339 peer->v_routeadv = routeadv;
3340
3341 return 0;
3342}
3343
3344int
3345peer_advertise_interval_unset (struct peer *peer)
3346{
3347 if (peer_group_active (peer))
3348 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3349
3350 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3351 peer->routeadv = 0;
3352
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003353 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003354 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3355 else
3356 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3357
3358 return 0;
3359}
David Lamparter6b0655a2014-06-04 06:53:35 +02003360
paul718e3742002-12-13 20:15:29 +00003361/* neighbor interface */
3362int
paulfd79ac92004-10-13 05:06:08 +00003363peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003364{
3365 if (peer->ifname)
3366 free (peer->ifname);
3367 peer->ifname = strdup (str);
3368
3369 return 0;
3370}
3371
3372int
3373peer_interface_unset (struct peer *peer)
3374{
3375 if (peer->ifname)
3376 free (peer->ifname);
3377 peer->ifname = NULL;
3378
3379 return 0;
3380}
David Lamparter6b0655a2014-06-04 06:53:35 +02003381
paul718e3742002-12-13 20:15:29 +00003382/* Allow-as in. */
3383int
3384peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3385{
3386 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003387 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003388
3389 if (allow_num < 1 || allow_num > 10)
3390 return BGP_ERR_INVALID_VALUE;
3391
3392 if (peer->allowas_in[afi][safi] != allow_num)
3393 {
3394 peer->allowas_in[afi][safi] = allow_num;
3395 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3396 peer_change_action (peer, afi, safi, peer_change_reset_in);
3397 }
3398
3399 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3400 return 0;
3401
3402 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003403 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003404 {
3405 if (peer->allowas_in[afi][safi] != allow_num)
3406 {
3407 peer->allowas_in[afi][safi] = allow_num;
3408 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3409 peer_change_action (peer, afi, safi, peer_change_reset_in);
3410 }
3411
3412 }
3413 return 0;
3414}
3415
3416int
3417peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3418{
3419 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003420 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003421
3422 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3423 {
3424 peer->allowas_in[afi][safi] = 0;
3425 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3426 }
3427
3428 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3429 return 0;
3430
3431 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003432 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003433 {
3434 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3435 {
3436 peer->allowas_in[afi][safi] = 0;
3437 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3438 }
3439 }
3440 return 0;
3441}
David Lamparter6b0655a2014-06-04 06:53:35 +02003442
paul718e3742002-12-13 20:15:29 +00003443int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003444peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003445{
3446 struct bgp *bgp = peer->bgp;
3447 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003448 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003449
3450 if (peer_sort (peer) != BGP_PEER_EBGP
3451 && peer_sort (peer) != BGP_PEER_INTERNAL)
3452 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3453
3454 if (bgp->as == as)
3455 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3456
3457 if (peer_group_active (peer))
3458 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3459
Andrew Certain9d3f9702012-11-07 23:50:07 +00003460 if (peer->as == as)
3461 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3462
paul718e3742002-12-13 20:15:29 +00003463 if (peer->change_local_as == as &&
3464 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003465 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3466 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3467 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003468 return 0;
3469
3470 peer->change_local_as = as;
3471 if (no_prepend)
3472 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3473 else
3474 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3475
Andrew Certain9d3f9702012-11-07 23:50:07 +00003476 if (replace_as)
3477 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3478 else
3479 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3480
paul718e3742002-12-13 20:15:29 +00003481 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3482 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003483 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003484 {
3485 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3486 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3487 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3488 }
paul718e3742002-12-13 20:15:29 +00003489 else
3490 BGP_EVENT_ADD (peer, BGP_Stop);
3491
3492 return 0;
3493 }
3494
3495 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003496 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003497 {
3498 peer->change_local_as = as;
3499 if (no_prepend)
3500 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3501 else
3502 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3503
Andrew Certain9d3f9702012-11-07 23:50:07 +00003504 if (replace_as)
3505 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3506 else
3507 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3508
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003509 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003510 {
3511 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3512 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3513 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3514 }
paul718e3742002-12-13 20:15:29 +00003515 else
3516 BGP_EVENT_ADD (peer, BGP_Stop);
3517 }
3518
3519 return 0;
3520}
3521
3522int
3523peer_local_as_unset (struct peer *peer)
3524{
3525 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003526 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003527
3528 if (peer_group_active (peer))
3529 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3530
3531 if (! peer->change_local_as)
3532 return 0;
3533
3534 peer->change_local_as = 0;
3535 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003536 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003537
3538 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3539 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003540 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003541 {
3542 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3543 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3544 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3545 }
paul718e3742002-12-13 20:15:29 +00003546 else
3547 BGP_EVENT_ADD (peer, BGP_Stop);
3548
3549 return 0;
3550 }
3551
3552 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003553 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003554 {
3555 peer->change_local_as = 0;
3556 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003557 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003558
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003559 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003560 {
3561 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3562 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3563 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3564 }
paul718e3742002-12-13 20:15:29 +00003565 else
3566 BGP_EVENT_ADD (peer, BGP_Stop);
3567 }
3568 return 0;
3569}
David Lamparter6b0655a2014-06-04 06:53:35 +02003570
Paul Jakma0df7c912008-07-21 21:02:49 +00003571/* Set password for authenticating with the peer. */
3572int
3573peer_password_set (struct peer *peer, const char *password)
3574{
3575 struct listnode *nn, *nnode;
3576 int len = password ? strlen(password) : 0;
3577 int ret = BGP_SUCCESS;
3578
3579 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3580 return BGP_ERR_INVALID_VALUE;
3581
3582 if (peer->password && strcmp (peer->password, password) == 0
3583 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3584 return 0;
3585
3586 if (peer->password)
3587 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3588
3589 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3590
3591 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3592 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003593 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3594 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
Paul Jakma0df7c912008-07-21 21:02:49 +00003595 else
3596 BGP_EVENT_ADD (peer, BGP_Stop);
3597
3598 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3599 }
3600
3601 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3602 {
3603 if (peer->password && strcmp (peer->password, password) == 0)
3604 continue;
3605
3606 if (peer->password)
3607 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3608
3609 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3610
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003611 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003612 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3613 else
3614 BGP_EVENT_ADD (peer, BGP_Stop);
3615
3616 if (bgp_md5_set (peer) < 0)
3617 ret = BGP_ERR_TCPSIG_FAILED;
3618 }
3619
3620 return ret;
3621}
3622
3623int
3624peer_password_unset (struct peer *peer)
3625{
3626 struct listnode *nn, *nnode;
3627
3628 if (!peer->password
3629 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3630 return 0;
3631
3632 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3633 {
3634 if (peer_group_active (peer)
3635 && peer->group->conf->password
3636 && strcmp (peer->group->conf->password, peer->password) == 0)
3637 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3638
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003639 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003640 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3641 else
3642 BGP_EVENT_ADD (peer, BGP_Stop);
3643
3644 if (peer->password)
3645 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3646
3647 peer->password = NULL;
3648
3649 bgp_md5_set (peer);
3650
3651 return 0;
3652 }
3653
3654 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3655 peer->password = NULL;
3656
3657 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3658 {
3659 if (!peer->password)
3660 continue;
3661
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003662 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003663 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3664 else
3665 BGP_EVENT_ADD (peer, BGP_Stop);
3666
3667 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3668 peer->password = NULL;
3669
3670 bgp_md5_set (peer);
3671 }
3672
3673 return 0;
3674}
David Lamparter6b0655a2014-06-04 06:53:35 +02003675
paul718e3742002-12-13 20:15:29 +00003676/* Set distribute list to the peer. */
3677int
3678peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003679 const char *name)
paul718e3742002-12-13 20:15:29 +00003680{
3681 struct bgp_filter *filter;
3682 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003683 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003684
3685 if (! peer->afc[afi][safi])
3686 return BGP_ERR_PEER_INACTIVE;
3687
3688 if (direct != FILTER_IN && direct != FILTER_OUT)
3689 return BGP_ERR_INVALID_VALUE;
3690
3691 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3692 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3693
3694 filter = &peer->filter[afi][safi];
3695
3696 if (filter->plist[direct].name)
3697 return BGP_ERR_PEER_FILTER_CONFLICT;
3698
3699 if (filter->dlist[direct].name)
3700 free (filter->dlist[direct].name);
3701 filter->dlist[direct].name = strdup (name);
3702 filter->dlist[direct].alist = access_list_lookup (afi, name);
3703
3704 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3705 return 0;
3706
3707 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003708 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003709 {
3710 filter = &peer->filter[afi][safi];
3711
3712 if (! peer->af_group[afi][safi])
3713 continue;
3714
3715 if (filter->dlist[direct].name)
3716 free (filter->dlist[direct].name);
3717 filter->dlist[direct].name = strdup (name);
3718 filter->dlist[direct].alist = access_list_lookup (afi, name);
3719 }
3720
3721 return 0;
3722}
3723
3724int
3725peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3726{
3727 struct bgp_filter *filter;
3728 struct bgp_filter *gfilter;
3729 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003730 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003731
3732 if (! peer->afc[afi][safi])
3733 return BGP_ERR_PEER_INACTIVE;
3734
3735 if (direct != FILTER_IN && direct != FILTER_OUT)
3736 return BGP_ERR_INVALID_VALUE;
3737
3738 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3739 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3740
3741 filter = &peer->filter[afi][safi];
3742
3743 /* apply peer-group filter */
3744 if (peer->af_group[afi][safi])
3745 {
3746 gfilter = &peer->group->conf->filter[afi][safi];
3747
3748 if (gfilter->dlist[direct].name)
3749 {
3750 if (filter->dlist[direct].name)
3751 free (filter->dlist[direct].name);
3752 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3753 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3754 return 0;
3755 }
3756 }
3757
3758 if (filter->dlist[direct].name)
3759 free (filter->dlist[direct].name);
3760 filter->dlist[direct].name = NULL;
3761 filter->dlist[direct].alist = NULL;
3762
3763 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3764 return 0;
3765
3766 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003767 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003768 {
3769 filter = &peer->filter[afi][safi];
3770
3771 if (! peer->af_group[afi][safi])
3772 continue;
3773
3774 if (filter->dlist[direct].name)
3775 free (filter->dlist[direct].name);
3776 filter->dlist[direct].name = NULL;
3777 filter->dlist[direct].alist = NULL;
3778 }
3779
3780 return 0;
3781}
3782
3783/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003784static void
paul718e3742002-12-13 20:15:29 +00003785peer_distribute_update (struct access_list *access)
3786{
3787 afi_t afi;
3788 safi_t safi;
3789 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003790 struct listnode *mnode, *mnnode;
3791 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003792 struct bgp *bgp;
3793 struct peer *peer;
3794 struct peer_group *group;
3795 struct bgp_filter *filter;
3796
paul1eb8ef22005-04-07 07:30:20 +00003797 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003798 {
paul1eb8ef22005-04-07 07:30:20 +00003799 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003800 {
3801 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3802 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3803 {
3804 filter = &peer->filter[afi][safi];
3805
3806 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3807 {
3808 if (filter->dlist[direct].name)
3809 filter->dlist[direct].alist =
3810 access_list_lookup (afi, filter->dlist[direct].name);
3811 else
3812 filter->dlist[direct].alist = NULL;
3813 }
3814 }
3815 }
paul1eb8ef22005-04-07 07:30:20 +00003816 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003817 {
3818 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3819 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3820 {
3821 filter = &group->conf->filter[afi][safi];
3822
3823 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3824 {
3825 if (filter->dlist[direct].name)
3826 filter->dlist[direct].alist =
3827 access_list_lookup (afi, filter->dlist[direct].name);
3828 else
3829 filter->dlist[direct].alist = NULL;
3830 }
3831 }
3832 }
3833 }
3834}
David Lamparter6b0655a2014-06-04 06:53:35 +02003835
paul718e3742002-12-13 20:15:29 +00003836/* Set prefix list to the peer. */
3837int
3838peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003839 const char *name)
paul718e3742002-12-13 20:15:29 +00003840{
3841 struct bgp_filter *filter;
3842 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003843 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003844
3845 if (! peer->afc[afi][safi])
3846 return BGP_ERR_PEER_INACTIVE;
3847
3848 if (direct != FILTER_IN && direct != FILTER_OUT)
3849 return BGP_ERR_INVALID_VALUE;
3850
3851 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3852 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3853
3854 filter = &peer->filter[afi][safi];
3855
3856 if (filter->dlist[direct].name)
3857 return BGP_ERR_PEER_FILTER_CONFLICT;
3858
3859 if (filter->plist[direct].name)
3860 free (filter->plist[direct].name);
3861 filter->plist[direct].name = strdup (name);
3862 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3863
3864 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3865 return 0;
3866
3867 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003868 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003869 {
3870 filter = &peer->filter[afi][safi];
3871
3872 if (! peer->af_group[afi][safi])
3873 continue;
3874
3875 if (filter->plist[direct].name)
3876 free (filter->plist[direct].name);
3877 filter->plist[direct].name = strdup (name);
3878 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3879 }
3880 return 0;
3881}
3882
3883int
3884peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3885{
3886 struct bgp_filter *filter;
3887 struct bgp_filter *gfilter;
3888 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003889 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003890
3891 if (! peer->afc[afi][safi])
3892 return BGP_ERR_PEER_INACTIVE;
3893
3894 if (direct != FILTER_IN && direct != FILTER_OUT)
3895 return BGP_ERR_INVALID_VALUE;
3896
3897 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3898 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3899
3900 filter = &peer->filter[afi][safi];
3901
3902 /* apply peer-group filter */
3903 if (peer->af_group[afi][safi])
3904 {
3905 gfilter = &peer->group->conf->filter[afi][safi];
3906
3907 if (gfilter->plist[direct].name)
3908 {
3909 if (filter->plist[direct].name)
3910 free (filter->plist[direct].name);
3911 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3912 filter->plist[direct].plist = gfilter->plist[direct].plist;
3913 return 0;
3914 }
3915 }
3916
3917 if (filter->plist[direct].name)
3918 free (filter->plist[direct].name);
3919 filter->plist[direct].name = NULL;
3920 filter->plist[direct].plist = NULL;
3921
3922 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3923 return 0;
3924
3925 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003926 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003927 {
3928 filter = &peer->filter[afi][safi];
3929
3930 if (! peer->af_group[afi][safi])
3931 continue;
3932
3933 if (filter->plist[direct].name)
3934 free (filter->plist[direct].name);
3935 filter->plist[direct].name = NULL;
3936 filter->plist[direct].plist = NULL;
3937 }
3938
3939 return 0;
3940}
3941
3942/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003943static void
paul718e3742002-12-13 20:15:29 +00003944peer_prefix_list_update (struct prefix_list *plist)
3945{
paul1eb8ef22005-04-07 07:30:20 +00003946 struct listnode *mnode, *mnnode;
3947 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003948 struct bgp *bgp;
3949 struct peer *peer;
3950 struct peer_group *group;
3951 struct bgp_filter *filter;
3952 afi_t afi;
3953 safi_t safi;
3954 int direct;
3955
paul1eb8ef22005-04-07 07:30:20 +00003956 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003957 {
paul1eb8ef22005-04-07 07:30:20 +00003958 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003959 {
3960 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3961 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3962 {
3963 filter = &peer->filter[afi][safi];
3964
3965 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3966 {
3967 if (filter->plist[direct].name)
3968 filter->plist[direct].plist =
3969 prefix_list_lookup (afi, filter->plist[direct].name);
3970 else
3971 filter->plist[direct].plist = NULL;
3972 }
3973 }
3974 }
paul1eb8ef22005-04-07 07:30:20 +00003975 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003976 {
3977 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3978 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3979 {
3980 filter = &group->conf->filter[afi][safi];
3981
3982 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3983 {
3984 if (filter->plist[direct].name)
3985 filter->plist[direct].plist =
3986 prefix_list_lookup (afi, filter->plist[direct].name);
3987 else
3988 filter->plist[direct].plist = NULL;
3989 }
3990 }
3991 }
3992 }
3993}
David Lamparter6b0655a2014-06-04 06:53:35 +02003994
paul718e3742002-12-13 20:15:29 +00003995int
3996peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003997 const char *name)
paul718e3742002-12-13 20:15:29 +00003998{
3999 struct bgp_filter *filter;
4000 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004001 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004002
4003 if (! peer->afc[afi][safi])
4004 return BGP_ERR_PEER_INACTIVE;
4005
4006 if (direct != FILTER_IN && direct != FILTER_OUT)
4007 return BGP_ERR_INVALID_VALUE;
4008
4009 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4010 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4011
4012 filter = &peer->filter[afi][safi];
4013
4014 if (filter->aslist[direct].name)
4015 free (filter->aslist[direct].name);
4016 filter->aslist[direct].name = strdup (name);
4017 filter->aslist[direct].aslist = as_list_lookup (name);
4018
4019 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4020 return 0;
4021
4022 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004023 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004024 {
4025 filter = &peer->filter[afi][safi];
4026
4027 if (! peer->af_group[afi][safi])
4028 continue;
4029
4030 if (filter->aslist[direct].name)
4031 free (filter->aslist[direct].name);
4032 filter->aslist[direct].name = strdup (name);
4033 filter->aslist[direct].aslist = as_list_lookup (name);
4034 }
4035 return 0;
4036}
4037
4038int
4039peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4040{
4041 struct bgp_filter *filter;
4042 struct bgp_filter *gfilter;
4043 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004044 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004045
4046 if (! peer->afc[afi][safi])
4047 return BGP_ERR_PEER_INACTIVE;
4048
hassob5f29602005-05-25 21:00:28 +00004049 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004050 return BGP_ERR_INVALID_VALUE;
4051
hassob5f29602005-05-25 21:00:28 +00004052 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004053 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4054
4055 filter = &peer->filter[afi][safi];
4056
4057 /* apply peer-group filter */
4058 if (peer->af_group[afi][safi])
4059 {
4060 gfilter = &peer->group->conf->filter[afi][safi];
4061
4062 if (gfilter->aslist[direct].name)
4063 {
4064 if (filter->aslist[direct].name)
4065 free (filter->aslist[direct].name);
4066 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4067 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4068 return 0;
4069 }
4070 }
4071
4072 if (filter->aslist[direct].name)
4073 free (filter->aslist[direct].name);
4074 filter->aslist[direct].name = NULL;
4075 filter->aslist[direct].aslist = NULL;
4076
4077 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4078 return 0;
4079
4080 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004081 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004082 {
4083 filter = &peer->filter[afi][safi];
4084
4085 if (! peer->af_group[afi][safi])
4086 continue;
4087
4088 if (filter->aslist[direct].name)
4089 free (filter->aslist[direct].name);
4090 filter->aslist[direct].name = NULL;
4091 filter->aslist[direct].aslist = NULL;
4092 }
4093
4094 return 0;
4095}
4096
paul94f2b392005-06-28 12:44:16 +00004097static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004098peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004099{
4100 afi_t afi;
4101 safi_t safi;
4102 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004103 struct listnode *mnode, *mnnode;
4104 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004105 struct bgp *bgp;
4106 struct peer *peer;
4107 struct peer_group *group;
4108 struct bgp_filter *filter;
4109
paul1eb8ef22005-04-07 07:30:20 +00004110 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004111 {
paul1eb8ef22005-04-07 07:30:20 +00004112 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004113 {
4114 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4115 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4116 {
4117 filter = &peer->filter[afi][safi];
4118
4119 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4120 {
4121 if (filter->aslist[direct].name)
4122 filter->aslist[direct].aslist =
4123 as_list_lookup (filter->aslist[direct].name);
4124 else
4125 filter->aslist[direct].aslist = NULL;
4126 }
4127 }
4128 }
paul1eb8ef22005-04-07 07:30:20 +00004129 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004130 {
4131 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4132 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4133 {
4134 filter = &group->conf->filter[afi][safi];
4135
4136 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4137 {
4138 if (filter->aslist[direct].name)
4139 filter->aslist[direct].aslist =
4140 as_list_lookup (filter->aslist[direct].name);
4141 else
4142 filter->aslist[direct].aslist = NULL;
4143 }
4144 }
4145 }
4146 }
4147}
David Lamparter6b0655a2014-06-04 06:53:35 +02004148
paul718e3742002-12-13 20:15:29 +00004149/* Set route-map to the peer. */
4150int
4151peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004152 const char *name)
paul718e3742002-12-13 20:15:29 +00004153{
4154 struct bgp_filter *filter;
4155 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004156 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004157
4158 if (! peer->afc[afi][safi])
4159 return BGP_ERR_PEER_INACTIVE;
4160
paulfee0f4c2004-09-13 05:12:46 +00004161 if (direct != RMAP_IN && direct != RMAP_OUT &&
4162 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004163 return BGP_ERR_INVALID_VALUE;
4164
paulfee0f4c2004-09-13 05:12:46 +00004165 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4166 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004167 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4168
4169 filter = &peer->filter[afi][safi];
4170
4171 if (filter->map[direct].name)
4172 free (filter->map[direct].name);
4173
4174 filter->map[direct].name = strdup (name);
4175 filter->map[direct].map = route_map_lookup_by_name (name);
4176
4177 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4178 return 0;
4179
4180 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004181 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004182 {
4183 filter = &peer->filter[afi][safi];
4184
4185 if (! peer->af_group[afi][safi])
4186 continue;
4187
4188 if (filter->map[direct].name)
4189 free (filter->map[direct].name);
4190 filter->map[direct].name = strdup (name);
4191 filter->map[direct].map = route_map_lookup_by_name (name);
4192 }
4193 return 0;
4194}
4195
4196/* Unset route-map from the peer. */
4197int
4198peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4199{
4200 struct bgp_filter *filter;
4201 struct bgp_filter *gfilter;
4202 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004203 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004204
4205 if (! peer->afc[afi][safi])
4206 return BGP_ERR_PEER_INACTIVE;
4207
hassob5f29602005-05-25 21:00:28 +00004208 if (direct != RMAP_IN && direct != RMAP_OUT &&
4209 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004210 return BGP_ERR_INVALID_VALUE;
4211
hassob5f29602005-05-25 21:00:28 +00004212 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4213 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004214 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4215
4216 filter = &peer->filter[afi][safi];
4217
4218 /* apply peer-group filter */
4219 if (peer->af_group[afi][safi])
4220 {
4221 gfilter = &peer->group->conf->filter[afi][safi];
4222
4223 if (gfilter->map[direct].name)
4224 {
4225 if (filter->map[direct].name)
4226 free (filter->map[direct].name);
4227 filter->map[direct].name = strdup (gfilter->map[direct].name);
4228 filter->map[direct].map = gfilter->map[direct].map;
4229 return 0;
4230 }
4231 }
4232
4233 if (filter->map[direct].name)
4234 free (filter->map[direct].name);
4235 filter->map[direct].name = NULL;
4236 filter->map[direct].map = NULL;
4237
4238 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4239 return 0;
4240
4241 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004242 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004243 {
4244 filter = &peer->filter[afi][safi];
4245
4246 if (! peer->af_group[afi][safi])
4247 continue;
4248
4249 if (filter->map[direct].name)
4250 free (filter->map[direct].name);
4251 filter->map[direct].name = NULL;
4252 filter->map[direct].map = NULL;
4253 }
4254 return 0;
4255}
David Lamparter6b0655a2014-06-04 06:53:35 +02004256
paul718e3742002-12-13 20:15:29 +00004257/* Set unsuppress-map to the peer. */
4258int
paulfd79ac92004-10-13 05:06:08 +00004259peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4260 const char *name)
paul718e3742002-12-13 20:15:29 +00004261{
4262 struct bgp_filter *filter;
4263 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004264 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004265
4266 if (! peer->afc[afi][safi])
4267 return BGP_ERR_PEER_INACTIVE;
4268
4269 if (peer_is_group_member (peer, afi, safi))
4270 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4271
4272 filter = &peer->filter[afi][safi];
4273
4274 if (filter->usmap.name)
4275 free (filter->usmap.name);
4276
4277 filter->usmap.name = strdup (name);
4278 filter->usmap.map = route_map_lookup_by_name (name);
4279
4280 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4281 return 0;
4282
4283 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004284 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004285 {
4286 filter = &peer->filter[afi][safi];
4287
4288 if (! peer->af_group[afi][safi])
4289 continue;
4290
4291 if (filter->usmap.name)
4292 free (filter->usmap.name);
4293 filter->usmap.name = strdup (name);
4294 filter->usmap.map = route_map_lookup_by_name (name);
4295 }
4296 return 0;
4297}
4298
4299/* Unset route-map from the peer. */
4300int
4301peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4302{
4303 struct bgp_filter *filter;
4304 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004305 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004306
4307 if (! peer->afc[afi][safi])
4308 return BGP_ERR_PEER_INACTIVE;
4309
4310 if (peer_is_group_member (peer, afi, safi))
4311 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4312
4313 filter = &peer->filter[afi][safi];
4314
4315 if (filter->usmap.name)
4316 free (filter->usmap.name);
4317 filter->usmap.name = NULL;
4318 filter->usmap.map = NULL;
4319
4320 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4321 return 0;
4322
4323 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004324 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004325 {
4326 filter = &peer->filter[afi][safi];
4327
4328 if (! peer->af_group[afi][safi])
4329 continue;
4330
4331 if (filter->usmap.name)
4332 free (filter->usmap.name);
4333 filter->usmap.name = NULL;
4334 filter->usmap.map = NULL;
4335 }
4336 return 0;
4337}
David Lamparter6b0655a2014-06-04 06:53:35 +02004338
paul718e3742002-12-13 20:15:29 +00004339int
4340peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004341 u_int32_t max, u_char threshold,
4342 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004343{
4344 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004345 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004346
4347 if (! peer->afc[afi][safi])
4348 return BGP_ERR_PEER_INACTIVE;
4349
4350 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4351 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004352 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004353 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004354 if (warning)
4355 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4356 else
4357 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4358
4359 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4360 return 0;
4361
4362 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004363 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004364 {
4365 if (! peer->af_group[afi][safi])
4366 continue;
4367
4368 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4369 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004370 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004371 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004372 if (warning)
4373 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4374 else
4375 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4376 }
4377 return 0;
4378}
4379
4380int
4381peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4382{
4383 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004384 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004385
4386 if (! peer->afc[afi][safi])
4387 return BGP_ERR_PEER_INACTIVE;
4388
4389 /* apply peer-group config */
4390 if (peer->af_group[afi][safi])
4391 {
4392 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4393 PEER_FLAG_MAX_PREFIX))
4394 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4395 else
4396 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4397
4398 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4399 PEER_FLAG_MAX_PREFIX_WARNING))
4400 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4401 else
4402 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4403
4404 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004405 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004406 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004407 return 0;
4408 }
4409
4410 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4411 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4412 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004413 peer->pmax_threshold[afi][safi] = 0;
4414 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004415
4416 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4417 return 0;
4418
4419 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004420 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004421 {
4422 if (! peer->af_group[afi][safi])
4423 continue;
4424
4425 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4426 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4427 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004428 peer->pmax_threshold[afi][safi] = 0;
4429 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004430 }
4431 return 0;
4432}
David Lamparter5f9adb52014-05-19 23:15:02 +02004433
4434static int is_ebgp_multihop_configured (struct peer *peer)
4435{
4436 struct peer_group *group;
4437 struct listnode *node, *nnode;
4438 struct peer *peer1;
4439
4440 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4441 {
4442 group = peer->group;
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004443 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4444 (group->conf->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004445 return 1;
4446
4447 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4448 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004449 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
4450 (peer1->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004451 return 1;
4452 }
4453 }
4454 else
4455 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004456 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4457 (peer->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004458 return 1;
4459 }
4460 return 0;
4461}
4462
Nick Hilliardfa411a22011-03-23 15:33:17 +00004463/* Set # of hops between us and BGP peer. */
4464int
4465peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4466{
4467 struct peer_group *group;
4468 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004469 int ret;
4470
4471 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4472
Nick Hilliardfa411a22011-03-23 15:33:17 +00004473 /* We cannot configure ttl-security hops when ebgp-multihop is already
4474 set. For non peer-groups, the check is simple. For peer-groups, it's
4475 slightly messy, because we need to check both the peer-group structure
4476 and all peer-group members for any trace of ebgp-multihop configuration
4477 before actually applying the ttl-security rules. Cisco really made a
4478 mess of this configuration parameter, and OpenBGPD got it right.
4479 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004480
David Lamparter5f9adb52014-05-19 23:15:02 +02004481 if (peer->gtsm_hops == 0)
4482 {
4483 if (is_ebgp_multihop_configured (peer))
4484 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004485
David Lamparter5f9adb52014-05-19 23:15:02 +02004486 /* specify MAXTTL on outgoing packets */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004487 /* Routine handles iBGP peers correctly */
David Lamparter5f9adb52014-05-19 23:15:02 +02004488 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4489 if (ret != 0)
4490 return ret;
4491 }
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004492
Nick Hilliardfa411a22011-03-23 15:33:17 +00004493 peer->gtsm_hops = gtsm_hops;
4494
Nick Hilliardfa411a22011-03-23 15:33:17 +00004495 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4496 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004497 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004498 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4499 }
4500 else
4501 {
4502 group = peer->group;
4503 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4504 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004505 peer->gtsm_hops = group->conf->gtsm_hops;
4506
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004507 /* Change setting of existing peer
4508 * established then change value (may break connectivity)
4509 * not established yet (teardown session and restart)
4510 * no session then do nothing (will get handled by next connection)
4511 */
4512 if (peer->status == Established)
4513 {
4514 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4515 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4516 MAXTTL + 1 - peer->gtsm_hops);
4517 }
4518 else if (peer->status < Established)
4519 {
4520 if (BGP_DEBUG (events, EVENTS))
4521 zlog_debug ("%s Min-ttl changed", peer->host);
4522 BGP_EVENT_ADD (peer, BGP_Stop);
4523 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004524 }
4525 }
4526
4527 return 0;
4528}
4529
4530int
4531peer_ttl_security_hops_unset (struct peer *peer)
4532{
4533 struct peer_group *group;
4534 struct listnode *node, *nnode;
4535 struct peer *opeer;
4536
4537 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4538
Nick Hilliardfa411a22011-03-23 15:33:17 +00004539 /* if a peer-group member, then reset to peer-group default rather than 0 */
4540 if (peer_group_active (peer))
4541 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4542 else
4543 peer->gtsm_hops = 0;
4544
4545 opeer = peer;
4546 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4547 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004548 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004549 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4550 }
4551 else
4552 {
4553 group = peer->group;
4554 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4555 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004556 peer->gtsm_hops = 0;
4557
4558 if (peer->fd >= 0)
4559 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4560 }
4561 }
4562
4563 return peer_ebgp_multihop_unset (opeer);
4564}
David Lamparter6b0655a2014-06-04 06:53:35 +02004565
paul718e3742002-12-13 20:15:29 +00004566int
4567peer_clear (struct peer *peer)
4568{
4569 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4570 {
hasso0a486e52005-02-01 20:57:17 +00004571 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4572 {
4573 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4574 if (peer->t_pmax_restart)
4575 {
4576 BGP_TIMER_OFF (peer->t_pmax_restart);
4577 if (BGP_DEBUG (events, EVENTS))
4578 zlog_debug ("%s Maximum-prefix restart timer canceled",
4579 peer->host);
4580 }
4581 BGP_EVENT_ADD (peer, BGP_Start);
4582 return 0;
4583 }
4584
paul718e3742002-12-13 20:15:29 +00004585 peer->v_start = BGP_INIT_START_TIMER;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00004586 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00004587 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4588 BGP_NOTIFY_CEASE_ADMIN_RESET);
4589 else
4590 BGP_EVENT_ADD (peer, BGP_Stop);
4591 }
4592 return 0;
4593}
4594
4595int
4596peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4597 enum bgp_clear_type stype)
4598{
4599 if (peer->status != Established)
4600 return 0;
4601
4602 if (! peer->afc[afi][safi])
4603 return BGP_ERR_AF_UNCONFIGURED;
4604
paulfee0f4c2004-09-13 05:12:46 +00004605 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4606 {
4607 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4608 return 0;
4609 bgp_check_local_routes_rsclient (peer, afi, safi);
4610 bgp_soft_reconfig_rsclient (peer, afi, safi);
4611 }
4612
paul718e3742002-12-13 20:15:29 +00004613 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4614 bgp_announce_route (peer, afi, safi);
4615
4616 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4617 {
4618 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4619 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4620 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4621 {
4622 struct bgp_filter *filter = &peer->filter[afi][safi];
4623 u_char prefix_type;
4624
4625 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4626 prefix_type = ORF_TYPE_PREFIX;
4627 else
4628 prefix_type = ORF_TYPE_PREFIX_OLD;
4629
4630 if (filter->plist[FILTER_IN].plist)
4631 {
4632 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4633 bgp_route_refresh_send (peer, afi, safi,
4634 prefix_type, REFRESH_DEFER, 1);
4635 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4636 REFRESH_IMMEDIATE, 0);
4637 }
4638 else
4639 {
4640 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4641 bgp_route_refresh_send (peer, afi, safi,
4642 prefix_type, REFRESH_IMMEDIATE, 1);
4643 else
4644 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4645 }
4646 return 0;
4647 }
4648 }
4649
4650 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4651 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4652 {
4653 /* If neighbor has soft reconfiguration inbound flag.
4654 Use Adj-RIB-In database. */
4655 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4656 bgp_soft_reconfig_in (peer, afi, safi);
4657 else
4658 {
4659 /* If neighbor has route refresh capability, send route refresh
4660 message to the peer. */
4661 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4662 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4663 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4664 else
4665 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4666 }
4667 }
4668 return 0;
4669}
David Lamparter6b0655a2014-06-04 06:53:35 +02004670
paulfd79ac92004-10-13 05:06:08 +00004671/* Display peer uptime.*/
4672/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004673char *
4674peer_uptime (time_t uptime2, char *buf, size_t len)
4675{
4676 time_t uptime1;
4677 struct tm *tm;
4678
4679 /* Check buffer length. */
4680 if (len < BGP_UPTIME_LEN)
4681 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004682 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004683 /* XXX: should return status instead of buf... */
4684 snprintf (buf, len, "<error> ");
4685 return buf;
paul718e3742002-12-13 20:15:29 +00004686 }
4687
4688 /* If there is no connection has been done before print `never'. */
4689 if (uptime2 == 0)
4690 {
4691 snprintf (buf, len, "never ");
4692 return buf;
4693 }
4694
4695 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004696 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004697 uptime1 -= uptime2;
4698 tm = gmtime (&uptime1);
Paul Jakma84c38402015-05-26 15:19:38 +01004699
paul718e3742002-12-13 20:15:29 +00004700 /* Making formatted timer strings. */
4701#define ONE_DAY_SECOND 60*60*24
Paul Jakma84c38402015-05-26 15:19:38 +01004702#define ONE_WEEK_SECOND ONE_DAY_SECOND*7
4703#define ONE_YEAR_SECOND ONE_DAY_SECOND*365
paul718e3742002-12-13 20:15:29 +00004704
4705 if (uptime1 < ONE_DAY_SECOND)
4706 snprintf (buf, len, "%02d:%02d:%02d",
4707 tm->tm_hour, tm->tm_min, tm->tm_sec);
4708 else if (uptime1 < ONE_WEEK_SECOND)
4709 snprintf (buf, len, "%dd%02dh%02dm",
4710 tm->tm_yday, tm->tm_hour, tm->tm_min);
Paul Jakma84c38402015-05-26 15:19:38 +01004711 else if (uptime1 < ONE_YEAR_SECOND)
paul718e3742002-12-13 20:15:29 +00004712 snprintf (buf, len, "%02dw%dd%02dh",
4713 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
Paul Jakma84c38402015-05-26 15:19:38 +01004714 else
4715 snprintf (buf, len, "%02dy%02dw%dd",
4716 tm->tm_year - 70, tm->tm_yday/7,
4717 tm->tm_yday - ((tm->tm_yday/7) * 7));
paul718e3742002-12-13 20:15:29 +00004718 return buf;
4719}
David Lamparter6b0655a2014-06-04 06:53:35 +02004720
paul94f2b392005-06-28 12:44:16 +00004721static void
paul718e3742002-12-13 20:15:29 +00004722bgp_config_write_filter (struct vty *vty, struct peer *peer,
4723 afi_t afi, safi_t safi)
4724{
4725 struct bgp_filter *filter;
4726 struct bgp_filter *gfilter = NULL;
4727 char *addr;
4728 int in = FILTER_IN;
4729 int out = FILTER_OUT;
4730
4731 addr = peer->host;
4732 filter = &peer->filter[afi][safi];
4733 if (peer->af_group[afi][safi])
4734 gfilter = &peer->group->conf->filter[afi][safi];
4735
4736 /* distribute-list. */
4737 if (filter->dlist[in].name)
4738 if (! gfilter || ! gfilter->dlist[in].name
4739 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4740 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4741 filter->dlist[in].name, VTY_NEWLINE);
4742 if (filter->dlist[out].name && ! gfilter)
4743 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4744 filter->dlist[out].name, VTY_NEWLINE);
4745
4746 /* prefix-list. */
4747 if (filter->plist[in].name)
4748 if (! gfilter || ! gfilter->plist[in].name
4749 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4750 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4751 filter->plist[in].name, VTY_NEWLINE);
4752 if (filter->plist[out].name && ! gfilter)
4753 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4754 filter->plist[out].name, VTY_NEWLINE);
4755
4756 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004757 if (filter->map[RMAP_IN].name)
4758 if (! gfilter || ! gfilter->map[RMAP_IN].name
4759 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004760 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004761 filter->map[RMAP_IN].name, VTY_NEWLINE);
4762 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004763 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004764 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4765 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4766 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4767 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4768 if (filter->map[RMAP_EXPORT].name)
4769 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4770 || strcmp (filter->map[RMAP_EXPORT].name,
4771 gfilter->map[RMAP_EXPORT].name) != 0)
4772 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4773 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004774
4775 /* unsuppress-map */
4776 if (filter->usmap.name && ! gfilter)
4777 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4778 filter->usmap.name, VTY_NEWLINE);
4779
4780 /* filter-list. */
4781 if (filter->aslist[in].name)
4782 if (! gfilter || ! gfilter->aslist[in].name
4783 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4784 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4785 filter->aslist[in].name, VTY_NEWLINE);
4786 if (filter->aslist[out].name && ! gfilter)
4787 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4788 filter->aslist[out].name, VTY_NEWLINE);
4789}
4790
4791/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004792static void
paul718e3742002-12-13 20:15:29 +00004793bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4794 struct peer *peer, afi_t afi, safi_t safi)
4795{
paul718e3742002-12-13 20:15:29 +00004796 struct peer *g_peer = NULL;
4797 char buf[SU_ADDRSTRLEN];
4798 char *addr;
4799
paul718e3742002-12-13 20:15:29 +00004800 addr = peer->host;
4801 if (peer_group_active (peer))
4802 g_peer = peer->group->conf;
4803
4804 /************************************
4805 ****** Global to the neighbor ******
4806 ************************************/
4807 if (afi == AFI_IP && safi == SAFI_UNICAST)
4808 {
4809 /* remote-as. */
4810 if (! peer_group_active (peer))
4811 {
4812 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4813 vty_out (vty, " neighbor %s peer-group%s", addr,
4814 VTY_NEWLINE);
4815 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004816 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004817 VTY_NEWLINE);
4818 }
4819 else
4820 {
4821 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004822 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004823 VTY_NEWLINE);
4824 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4825 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4826 peer->group->name, VTY_NEWLINE);
4827 }
4828
4829 /* local-as. */
4830 if (peer->change_local_as)
4831 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00004832 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004833 peer->change_local_as,
4834 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00004835 " no-prepend" : "",
4836 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
4837 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004838
4839 /* Description. */
4840 if (peer->desc)
4841 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4842 VTY_NEWLINE);
4843
4844 /* Shutdown. */
4845 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4846 if (! peer_group_active (peer) ||
4847 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4848 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4849
Paul Jakma0df7c912008-07-21 21:02:49 +00004850 /* Password. */
4851 if (peer->password)
4852 if (!peer_group_active (peer)
4853 || ! g_peer->password
4854 || strcmp (peer->password, g_peer->password) != 0)
4855 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4856 VTY_NEWLINE);
4857
paul718e3742002-12-13 20:15:29 +00004858 /* BGP port. */
4859 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004860 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004861 VTY_NEWLINE);
4862
4863 /* Local interface name. */
4864 if (peer->ifname)
4865 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4866 VTY_NEWLINE);
4867
4868 /* Passive. */
4869 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4870 if (! peer_group_active (peer) ||
4871 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4872 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4873
4874 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004875 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00004876 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00004877 if (! peer_group_active (peer) ||
4878 g_peer->ttl != peer->ttl)
4879 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4880 VTY_NEWLINE);
4881
Nick Hilliardfa411a22011-03-23 15:33:17 +00004882 /* ttl-security hops */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004883 if (peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004884 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004885 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00004886 peer->gtsm_hops, VTY_NEWLINE);
4887
hasso6ffd2072005-02-02 14:50:11 +00004888 /* disable-connected-check. */
4889 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004890 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004891 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4892 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004893
4894 /* Update-source. */
4895 if (peer->update_if)
4896 if (! peer_group_active (peer) || ! g_peer->update_if
4897 || strcmp (g_peer->update_if, peer->update_if) != 0)
4898 vty_out (vty, " neighbor %s update-source %s%s", addr,
4899 peer->update_if, VTY_NEWLINE);
4900 if (peer->update_source)
4901 if (! peer_group_active (peer) || ! g_peer->update_source
4902 || sockunion_cmp (g_peer->update_source,
4903 peer->update_source) != 0)
4904 vty_out (vty, " neighbor %s update-source %s%s", addr,
4905 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4906 VTY_NEWLINE);
4907
paul718e3742002-12-13 20:15:29 +00004908 /* advertisement-interval */
4909 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4910 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4911 addr, peer->v_routeadv, VTY_NEWLINE);
4912
4913 /* timers. */
4914 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4915 && ! peer_group_active (peer))
4916 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4917 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4918
4919 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4920 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4921 peer->connect, VTY_NEWLINE);
4922
4923 /* Default weight. */
4924 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4925 if (! peer_group_active (peer) ||
4926 g_peer->weight != peer->weight)
4927 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4928 VTY_NEWLINE);
4929
paul718e3742002-12-13 20:15:29 +00004930 /* Dynamic capability. */
4931 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4932 if (! peer_group_active (peer) ||
4933 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4934 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4935 VTY_NEWLINE);
4936
4937 /* dont capability negotiation. */
4938 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4939 if (! peer_group_active (peer) ||
4940 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4941 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4942 VTY_NEWLINE);
4943
4944 /* override capability negotiation. */
4945 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4946 if (! peer_group_active (peer) ||
4947 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4948 vty_out (vty, " neighbor %s override-capability%s", addr,
4949 VTY_NEWLINE);
4950
4951 /* strict capability negotiation. */
4952 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4953 if (! peer_group_active (peer) ||
4954 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4955 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4956 VTY_NEWLINE);
4957
Christian Franke15c71342012-11-19 11:17:31 +00004958 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
paul718e3742002-12-13 20:15:29 +00004959 {
4960 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4961 {
4962 if (peer->afc[AFI_IP][SAFI_UNICAST])
4963 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4964 }
4965 else
4966 {
4967 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4968 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4969 }
4970 }
4971 }
4972
4973
4974 /************************************
4975 ****** Per AF to the neighbor ******
4976 ************************************/
4977
4978 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4979 {
4980 if (peer->af_group[afi][safi])
4981 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4982 peer->group->name, VTY_NEWLINE);
4983 else
4984 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4985 }
4986
4987 /* ORF capability. */
4988 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4989 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4990 if (! peer->af_group[afi][safi])
4991 {
4992 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4993
4994 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4995 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4996 vty_out (vty, " both");
4997 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4998 vty_out (vty, " send");
4999 else
5000 vty_out (vty, " receive");
5001 vty_out (vty, "%s", VTY_NEWLINE);
5002 }
5003
5004 /* Route reflector client. */
5005 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
5006 && ! peer->af_group[afi][safi])
5007 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
5008 VTY_NEWLINE);
5009
5010 /* Nexthop self. */
5011 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
5012 && ! peer->af_group[afi][safi])
Timo Teräs9e7a53c2014-04-24 10:22:37 +03005013 vty_out (vty, " neighbor %s next-hop-self%s%s", addr,
5014 peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ?
5015 " all" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005016
5017 /* Remove private AS. */
5018 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
5019 && ! peer->af_group[afi][safi])
5020 vty_out (vty, " neighbor %s remove-private-AS%s",
5021 addr, VTY_NEWLINE);
5022
5023 /* send-community print. */
5024 if (! peer->af_group[afi][safi])
5025 {
5026 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5027 {
5028 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5029 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5030 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
5031 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5032 vty_out (vty, " neighbor %s send-community extended%s",
5033 addr, VTY_NEWLINE);
5034 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5035 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
5036 }
5037 else
5038 {
5039 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5040 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5041 vty_out (vty, " no neighbor %s send-community both%s",
5042 addr, VTY_NEWLINE);
5043 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5044 vty_out (vty, " no neighbor %s send-community extended%s",
5045 addr, VTY_NEWLINE);
5046 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5047 vty_out (vty, " no neighbor %s send-community%s",
5048 addr, VTY_NEWLINE);
5049 }
5050 }
5051
5052 /* Default information */
5053 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5054 && ! peer->af_group[afi][safi])
5055 {
5056 vty_out (vty, " neighbor %s default-originate", addr);
5057 if (peer->default_rmap[afi][safi].name)
5058 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5059 vty_out (vty, "%s", VTY_NEWLINE);
5060 }
5061
5062 /* Soft reconfiguration inbound. */
5063 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5064 if (! peer->af_group[afi][safi] ||
5065 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5066 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5067 VTY_NEWLINE);
5068
5069 /* maximum-prefix. */
5070 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5071 if (! peer->af_group[afi][safi]
5072 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005073 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005074 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5075 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005076 {
hasso0a486e52005-02-01 20:57:17 +00005077 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5078 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5079 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5080 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5081 vty_out (vty, " warning-only");
5082 if (peer->pmax_restart[afi][safi])
5083 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5084 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005085 }
paul718e3742002-12-13 20:15:29 +00005086
5087 /* Route server client. */
5088 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5089 && ! peer->af_group[afi][safi])
5090 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5091
Dylan Hall3cf12882011-10-27 15:28:17 +04005092 /* Nexthop-local unchanged. */
5093 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5094 && ! peer->af_group[afi][safi])
5095 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5096
paul718e3742002-12-13 20:15:29 +00005097 /* Allow AS in. */
5098 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5099 if (! peer_group_active (peer)
5100 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5101 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5102 {
5103 if (peer->allowas_in[afi][safi] == 3)
5104 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5105 else
5106 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5107 peer->allowas_in[afi][safi], VTY_NEWLINE);
5108 }
5109
5110 /* Filter. */
5111 bgp_config_write_filter (vty, peer, afi, safi);
5112
5113 /* atribute-unchanged. */
5114 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5115 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5116 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5117 && ! peer->af_group[afi][safi])
5118 {
5119 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5120 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5121 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5122 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5123 else
5124 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5125 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5126 " as-path" : "",
5127 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5128 " next-hop" : "",
5129 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5130 " med" : "", VTY_NEWLINE);
5131 }
5132}
5133
5134/* Display "address-family" configuration header. */
5135void
5136bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5137 int *write)
5138{
5139 if (*write)
5140 return;
5141
5142 if (afi == AFI_IP && safi == SAFI_UNICAST)
5143 return;
5144
5145 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5146
5147 if (afi == AFI_IP)
5148 {
5149 if (safi == SAFI_MULTICAST)
5150 vty_out (vty, "ipv4 multicast");
5151 else if (safi == SAFI_MPLS_VPN)
5152 vty_out (vty, "vpnv4 unicast");
5153 }
5154 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005155 {
5156 vty_out (vty, "ipv6");
5157
5158 if (safi == SAFI_MULTICAST)
5159 vty_out (vty, " multicast");
5160 }
paul718e3742002-12-13 20:15:29 +00005161
5162 vty_out (vty, "%s", VTY_NEWLINE);
5163
5164 *write = 1;
5165}
5166
5167/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005168static int
paul718e3742002-12-13 20:15:29 +00005169bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5170 safi_t safi)
5171{
5172 int write = 0;
5173 struct peer *peer;
5174 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005175 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005176
5177 bgp_config_write_network (vty, bgp, afi, safi, &write);
5178
5179 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5180
paul1eb8ef22005-04-07 07:30:20 +00005181 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005182 {
5183 if (group->conf->afc[afi][safi])
5184 {
5185 bgp_config_write_family_header (vty, afi, safi, &write);
5186 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5187 }
5188 }
paul1eb8ef22005-04-07 07:30:20 +00005189 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005190 {
5191 if (peer->afc[afi][safi])
5192 {
5193 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5194 {
5195 bgp_config_write_family_header (vty, afi, safi, &write);
5196 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5197 }
5198 }
5199 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005200
5201 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5202
paul718e3742002-12-13 20:15:29 +00005203 if (write)
5204 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5205
5206 return write;
5207}
5208
5209int
5210bgp_config_write (struct vty *vty)
5211{
5212 int write = 0;
5213 struct bgp *bgp;
5214 struct peer_group *group;
5215 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005216 struct listnode *node, *nnode;
5217 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005218
5219 /* BGP Multiple instance. */
5220 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5221 {
5222 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5223 write++;
5224 }
5225
5226 /* BGP Config type. */
5227 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5228 {
5229 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5230 write++;
5231 }
5232
5233 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005234 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005235 {
5236 if (write)
5237 vty_out (vty, "!%s", VTY_NEWLINE);
5238
5239 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005240 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005241
5242 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5243 {
5244 if (bgp->name)
5245 vty_out (vty, " view %s", bgp->name);
5246 }
5247 vty_out (vty, "%s", VTY_NEWLINE);
5248
5249 /* No Synchronization */
5250 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5251 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5252
5253 /* BGP fast-external-failover. */
5254 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5255 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5256
5257 /* BGP router ID. */
5258 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5259 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5260 VTY_NEWLINE);
5261
paul848973c2003-08-13 00:32:49 +00005262 /* BGP log-neighbor-changes. */
5263 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5264 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
5265
paul718e3742002-12-13 20:15:29 +00005266 /* BGP configuration. */
5267 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5268 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5269
5270 /* BGP default ipv4-unicast. */
5271 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5272 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5273
5274 /* BGP default local-preference. */
5275 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5276 vty_out (vty, " bgp default local-preference %d%s",
5277 bgp->default_local_pref, VTY_NEWLINE);
5278
5279 /* BGP client-to-client reflection. */
5280 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5281 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5282
5283 /* BGP cluster ID. */
5284 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5285 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5286 VTY_NEWLINE);
5287
hassoe0701b72004-05-20 09:19:34 +00005288 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005289 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005290 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5291 VTY_NEWLINE);
5292
5293 /* Confederation peer */
5294 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005295 {
hassoe0701b72004-05-20 09:19:34 +00005296 int i;
paul718e3742002-12-13 20:15:29 +00005297
hassoe0701b72004-05-20 09:19:34 +00005298 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005299
hassoe0701b72004-05-20 09:19:34 +00005300 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005301 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005302
hassoe0701b72004-05-20 09:19:34 +00005303 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005304 }
5305
5306 /* BGP enforce-first-as. */
5307 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5308 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5309
5310 /* BGP deterministic-med. */
5311 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5312 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005313
5314 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005315 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5316 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5317 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005318 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5319 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5320
paul718e3742002-12-13 20:15:29 +00005321 /* BGP bestpath method. */
5322 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5323 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005324 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5325 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
Pradosh Mohapatra2fdd4552013-09-07 07:02:36 +00005326 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
5327 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
5328 }
paul718e3742002-12-13 20:15:29 +00005329 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5330 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5331 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5332 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5333 {
5334 vty_out (vty, " bgp bestpath med");
5335 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5336 vty_out (vty, " confed");
5337 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5338 vty_out (vty, " missing-as-worst");
5339 vty_out (vty, "%s", VTY_NEWLINE);
5340 }
5341
5342 /* BGP network import check. */
5343 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5344 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5345
5346 /* BGP scan interval. */
5347 bgp_config_write_scan_time (vty);
5348
5349 /* BGP flag dampening. */
5350 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5351 BGP_CONFIG_DAMPENING))
5352 bgp_config_write_damp (vty);
5353
5354 /* BGP static route configuration. */
5355 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5356
5357 /* BGP redistribute configuration. */
5358 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5359
5360 /* BGP timers configuration. */
5361 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5362 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5363 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5364 bgp->default_holdtime, VTY_NEWLINE);
5365
5366 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005367 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005368 {
5369 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5370 }
5371
5372 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005373 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005374 {
5375 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5376 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5377 }
5378
Josh Bailey165b5ff2011-07-20 20:43:22 -07005379 /* maximum-paths */
5380 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5381
paul718e3742002-12-13 20:15:29 +00005382 /* Distance configuration. */
5383 bgp_config_write_distance (vty, bgp);
5384
5385 /* No auto-summary */
5386 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5387 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5388
5389 /* IPv4 multicast configuration. */
5390 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5391
5392 /* IPv4 VPN configuration. */
5393 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5394
5395 /* IPv6 unicast configuration. */
5396 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5397
Paul Jakma37a217a2007-04-10 19:20:29 +00005398 /* IPv6 multicast configuration. */
5399 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5400
paul718e3742002-12-13 20:15:29 +00005401 write++;
5402 }
5403 return write;
5404}
5405
5406void
paul94f2b392005-06-28 12:44:16 +00005407bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005408{
5409 memset (&bgp_master, 0, sizeof (struct bgp_master));
5410
5411 bm = &bgp_master;
5412 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005413 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005414 bm->port = BGP_PORT_DEFAULT;
5415 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005416 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005417}
paul200df112005-06-01 11:17:05 +00005418
David Lamparter6b0655a2014-06-04 06:53:35 +02005419
paul718e3742002-12-13 20:15:29 +00005420void
paul94f2b392005-06-28 12:44:16 +00005421bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005422{
paul718e3742002-12-13 20:15:29 +00005423 /* BGP VTY commands installation. */
5424 bgp_vty_init ();
5425
paul718e3742002-12-13 20:15:29 +00005426 /* Init zebra. */
Donald Sharp774914f2015-10-14 08:50:39 -04005427 bgp_zebra_init (bm->master);
paul718e3742002-12-13 20:15:29 +00005428
5429 /* BGP inits. */
5430 bgp_attr_init ();
5431 bgp_debug_init ();
5432 bgp_dump_init ();
5433 bgp_route_init ();
5434 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005435 bgp_address_init ();
paul718e3742002-12-13 20:15:29 +00005436 bgp_scan_init ();
5437 bgp_mplsvpn_init ();
5438
5439 /* Access list initialize. */
5440 access_list_init ();
5441 access_list_add_hook (peer_distribute_update);
5442 access_list_delete_hook (peer_distribute_update);
5443
5444 /* Filter list initialize. */
5445 bgp_filter_init ();
5446 as_list_add_hook (peer_aslist_update);
5447 as_list_delete_hook (peer_aslist_update);
5448
5449 /* Prefix list initialize.*/
5450 prefix_list_init ();
5451 prefix_list_add_hook (peer_prefix_list_update);
5452 prefix_list_delete_hook (peer_prefix_list_update);
5453
5454 /* Community list initialize. */
5455 bgp_clist = community_list_init ();
5456
5457#ifdef HAVE_SNMP
5458 bgp_snmp_init ();
5459#endif /* HAVE_SNMP */
5460}
paul545acaf2004-04-20 15:13:15 +00005461
5462void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005463bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005464{
paul545acaf2004-04-20 15:13:15 +00005465 struct bgp *bgp;
5466 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005467 struct listnode *node, *nnode;
5468 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005469
paul1eb8ef22005-04-07 07:30:20 +00005470 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5471 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005472 if (peer->status == Established)
5473 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5474 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005475
paul545acaf2004-04-20 15:13:15 +00005476 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005477
paule210cf92005-06-15 19:15:35 +00005478 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005479 {
5480 work_queue_free (bm->process_main_queue);
5481 bm->process_main_queue = NULL;
5482 }
paule210cf92005-06-15 19:15:35 +00005483 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005484 {
5485 work_queue_free (bm->process_rsclient_queue);
5486 bm->process_rsclient_queue = NULL;
5487 }
paul545acaf2004-04-20 15:13:15 +00005488}