blob: 4de854e4e66c108dd8646de5e7f0cc2abd95247e [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* BGP-4, BGP-4+ daemon program
2 Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "prefix.h"
24#include "thread.h"
25#include "buffer.h"
26#include "stream.h"
27#include "command.h"
28#include "sockunion.h"
29#include "network.h"
30#include "memory.h"
31#include "filter.h"
32#include "routemap.h"
33#include "str.h"
34#include "log.h"
35#include "plist.h"
36#include "linklist.h"
paul200df112005-06-01 11:17:05 +000037#include "workqueue.h"
paul718e3742002-12-13 20:15:29 +000038
39#include "bgpd/bgpd.h"
40#include "bgpd/bgp_table.h"
41#include "bgpd/bgp_aspath.h"
42#include "bgpd/bgp_route.h"
43#include "bgpd/bgp_dump.h"
44#include "bgpd/bgp_debug.h"
45#include "bgpd/bgp_community.h"
46#include "bgpd/bgp_attr.h"
47#include "bgpd/bgp_regex.h"
48#include "bgpd/bgp_clist.h"
49#include "bgpd/bgp_fsm.h"
50#include "bgpd/bgp_packet.h"
51#include "bgpd/bgp_zebra.h"
52#include "bgpd/bgp_open.h"
53#include "bgpd/bgp_filter.h"
54#include "bgpd/bgp_nexthop.h"
55#include "bgpd/bgp_damp.h"
56#include "bgpd/bgp_mplsvpn.h"
57#include "bgpd/bgp_advertise.h"
58#include "bgpd/bgp_network.h"
59#include "bgpd/bgp_vty.h"
Josh Bailey165b5ff2011-07-20 20:43:22 -070060#include "bgpd/bgp_mpath.h"
paul718e3742002-12-13 20:15:29 +000061#ifdef HAVE_SNMP
62#include "bgpd/bgp_snmp.h"
63#endif /* HAVE_SNMP */
David Lamparter6b0655a2014-06-04 06:53:35 +020064
paul718e3742002-12-13 20:15:29 +000065/* BGP process wide configuration. */
66static struct bgp_master bgp_master;
67
hasso18a6dce2004-10-03 18:18:34 +000068extern struct in_addr router_id_zebra;
69
paul718e3742002-12-13 20:15:29 +000070/* BGP process wide configuration pointer to export. */
71struct bgp_master *bm;
72
73/* BGP community-list. */
74struct community_list_handler *bgp_clist;
David Lamparter6b0655a2014-06-04 06:53:35 +020075
paul718e3742002-12-13 20:15:29 +000076/* BGP global flag manipulation. */
77int
78bgp_option_set (int flag)
79{
80 switch (flag)
81 {
82 case BGP_OPT_NO_FIB:
83 case BGP_OPT_MULTIPLE_INSTANCE:
84 case BGP_OPT_CONFIG_CISCO:
Paul Jakmacccbc012012-06-14 10:40:26 +010085 case BGP_OPT_NO_LISTEN:
paul718e3742002-12-13 20:15:29 +000086 SET_FLAG (bm->options, flag);
87 break;
88 default:
89 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +000090 }
91 return 0;
92}
93
94int
95bgp_option_unset (int flag)
96{
97 switch (flag)
98 {
99 case BGP_OPT_MULTIPLE_INSTANCE:
100 if (listcount (bm->bgp) > 1)
101 return BGP_ERR_MULTIPLE_INSTANCE_USED;
102 /* Fall through. */
103 case BGP_OPT_NO_FIB:
104 case BGP_OPT_CONFIG_CISCO:
105 UNSET_FLAG (bm->options, flag);
106 break;
107 default:
108 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +0000109 }
110 return 0;
111}
112
113int
114bgp_option_check (int flag)
115{
116 return CHECK_FLAG (bm->options, flag);
117}
David Lamparter6b0655a2014-06-04 06:53:35 +0200118
paul718e3742002-12-13 20:15:29 +0000119/* BGP flag manipulation. */
120int
121bgp_flag_set (struct bgp *bgp, int flag)
122{
123 SET_FLAG (bgp->flags, flag);
124 return 0;
125}
126
127int
128bgp_flag_unset (struct bgp *bgp, int flag)
129{
130 UNSET_FLAG (bgp->flags, flag);
131 return 0;
132}
133
134int
135bgp_flag_check (struct bgp *bgp, int flag)
136{
137 return CHECK_FLAG (bgp->flags, flag);
138}
David Lamparter6b0655a2014-06-04 06:53:35 +0200139
paul718e3742002-12-13 20:15:29 +0000140/* Internal function to set BGP structure configureation flag. */
141static void
142bgp_config_set (struct bgp *bgp, int config)
143{
144 SET_FLAG (bgp->config, config);
145}
146
147static void
148bgp_config_unset (struct bgp *bgp, int config)
149{
150 UNSET_FLAG (bgp->config, config);
151}
152
153static int
154bgp_config_check (struct bgp *bgp, int config)
155{
156 return CHECK_FLAG (bgp->config, config);
157}
David Lamparter6b0655a2014-06-04 06:53:35 +0200158
paul718e3742002-12-13 20:15:29 +0000159/* Set BGP router identifier. */
160int
161bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
162{
163 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000164 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000165
166 if (bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID)
167 && IPV4_ADDR_SAME (&bgp->router_id, id))
168 return 0;
169
170 IPV4_ADDR_COPY (&bgp->router_id, id);
171 bgp_config_set (bgp, BGP_CONFIG_ROUTER_ID);
172
173 /* Set all peer's local identifier with this value. */
paul1eb8ef22005-04-07 07:30:20 +0000174 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000175 {
176 IPV4_ADDR_COPY (&peer->local_id, id);
177
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000178 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000179 {
180 peer->last_reset = PEER_DOWN_RID_CHANGE;
181 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
182 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
183 }
paul718e3742002-12-13 20:15:29 +0000184 }
185 return 0;
186}
187
paul718e3742002-12-13 20:15:29 +0000188/* BGP's cluster-id control. */
189int
190bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
191{
192 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000193 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000194
195 if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)
196 && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id))
197 return 0;
198
199 IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id);
200 bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID);
201
202 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000203 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000204 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000205 if (peer->sort != BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +0000206 continue;
207
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000208 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000209 {
210 peer->last_reset = PEER_DOWN_CLID_CHANGE;
211 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
212 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
213 }
paul718e3742002-12-13 20:15:29 +0000214 }
215 return 0;
216}
217
218int
219bgp_cluster_id_unset (struct bgp *bgp)
220{
221 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000222 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000223
224 if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID))
225 return 0;
226
227 bgp->cluster_id.s_addr = 0;
228 bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID);
229
230 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000231 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000232 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000233 if (peer->sort != BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +0000234 continue;
235
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000236 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000237 {
238 peer->last_reset = PEER_DOWN_CLID_CHANGE;
239 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
240 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
241 }
paul718e3742002-12-13 20:15:29 +0000242 }
243 return 0;
244}
David Lamparter6b0655a2014-06-04 06:53:35 +0200245
Stephen Hemminger65957882010-01-15 16:22:10 +0300246/* time_t value that is monotonicly increasing
247 * and uneffected by adjustments to system clock
248 */
249time_t bgp_clock (void)
250{
251 struct timeval tv;
252
253 quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv);
254 return tv.tv_sec;
255}
256
paul718e3742002-12-13 20:15:29 +0000257/* BGP timer configuration. */
258int
259bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
260{
261 bgp->default_keepalive = (keepalive < holdtime / 3
262 ? keepalive : holdtime / 3);
263 bgp->default_holdtime = holdtime;
264
265 return 0;
266}
267
268int
269bgp_timers_unset (struct bgp *bgp)
270{
271 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
272 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
273
274 return 0;
275}
David Lamparter6b0655a2014-06-04 06:53:35 +0200276
paul718e3742002-12-13 20:15:29 +0000277/* BGP confederation configuration. */
278int
279bgp_confederation_id_set (struct bgp *bgp, as_t as)
280{
281 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000282 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000283 int already_confed;
284
285 if (as == 0)
286 return BGP_ERR_INVALID_AS;
287
288 /* Remember - were we doing confederation before? */
289 already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);
290 bgp->confed_id = as;
291 bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);
292
293 /* If we were doing confederation already, this is just an external
294 AS change. Just Reset EBGP sessions, not CONFED sessions. If we
295 were not doing confederation before, reset all EBGP sessions. */
paul1eb8ef22005-04-07 07:30:20 +0000296 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000297 {
298 /* We're looking for peers who's AS is not local or part of our
299 confederation. */
300 if (already_confed)
301 {
302 if (peer_sort (peer) == BGP_PEER_EBGP)
303 {
304 peer->local_as = as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000305 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000306 {
307 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
308 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
309 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
310 }
311
paul718e3742002-12-13 20:15:29 +0000312 else
313 BGP_EVENT_ADD (peer, BGP_Stop);
314 }
315 }
316 else
317 {
318 /* Not doign confederation before, so reset every non-local
319 session */
320 if (peer_sort (peer) != BGP_PEER_IBGP)
321 {
322 /* Reset the local_as to be our EBGP one */
323 if (peer_sort (peer) == BGP_PEER_EBGP)
324 peer->local_as = as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000325 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000326 {
327 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
328 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
329 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
330 }
paul718e3742002-12-13 20:15:29 +0000331 else
332 BGP_EVENT_ADD (peer, BGP_Stop);
333 }
334 }
335 }
336 return 0;
337}
338
339int
340bgp_confederation_id_unset (struct bgp *bgp)
341{
342 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000343 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000344
345 bgp->confed_id = 0;
346 bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
347
paul1eb8ef22005-04-07 07:30:20 +0000348 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000349 {
350 /* We're looking for peers who's AS is not local */
351 if (peer_sort (peer) != BGP_PEER_IBGP)
352 {
353 peer->local_as = bgp->as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000354 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000355 {
356 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
357 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
358 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
359 }
360
paul718e3742002-12-13 20:15:29 +0000361 else
362 BGP_EVENT_ADD (peer, BGP_Stop);
363 }
364 }
365 return 0;
366}
367
368/* Is an AS part of the confed or not? */
369int
370bgp_confederation_peers_check (struct bgp *bgp, as_t as)
371{
372 int i;
373
374 if (! bgp)
375 return 0;
376
377 for (i = 0; i < bgp->confed_peers_cnt; i++)
378 if (bgp->confed_peers[i] == as)
379 return 1;
380
381 return 0;
382}
383
384/* Add an AS to the confederation set. */
385int
386bgp_confederation_peers_add (struct bgp *bgp, as_t as)
387{
388 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000389 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000390
391 if (! bgp)
392 return BGP_ERR_INVALID_BGP;
393
394 if (bgp->as == as)
395 return BGP_ERR_INVALID_AS;
396
397 if (bgp_confederation_peers_check (bgp, as))
398 return -1;
399
400 if (bgp->confed_peers)
401 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
402 bgp->confed_peers,
403 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
404 else
405 bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST,
406 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
407
408 bgp->confed_peers[bgp->confed_peers_cnt] = as;
409 bgp->confed_peers_cnt++;
410
411 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
412 {
paul1eb8ef22005-04-07 07:30:20 +0000413 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000414 {
415 if (peer->as == as)
416 {
417 peer->local_as = bgp->as;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000418 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000419 {
420 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
421 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
422 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
423 }
paul718e3742002-12-13 20:15:29 +0000424 else
425 BGP_EVENT_ADD (peer, BGP_Stop);
426 }
427 }
428 }
429 return 0;
430}
431
432/* Delete an AS from the confederation set. */
433int
434bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
435{
436 int i;
437 int j;
438 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000439 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000440
441 if (! bgp)
442 return -1;
443
444 if (! bgp_confederation_peers_check (bgp, as))
445 return -1;
446
447 for (i = 0; i < bgp->confed_peers_cnt; i++)
448 if (bgp->confed_peers[i] == as)
449 for(j = i + 1; j < bgp->confed_peers_cnt; j++)
450 bgp->confed_peers[j - 1] = bgp->confed_peers[j];
451
452 bgp->confed_peers_cnt--;
453
454 if (bgp->confed_peers_cnt == 0)
455 {
456 if (bgp->confed_peers)
457 XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
458 bgp->confed_peers = NULL;
459 }
460 else
461 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
462 bgp->confed_peers,
463 bgp->confed_peers_cnt * sizeof (as_t));
464
465 /* Now reset any peer who's remote AS has just been removed from the
466 CONFED */
467 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
468 {
paul1eb8ef22005-04-07 07:30:20 +0000469 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000470 {
471 if (peer->as == as)
472 {
473 peer->local_as = bgp->confed_id;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000474 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000475 {
476 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
477 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
478 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
479 }
paul718e3742002-12-13 20:15:29 +0000480 else
481 BGP_EVENT_ADD (peer, BGP_Stop);
482 }
483 }
484 }
485
486 return 0;
487}
David Lamparter6b0655a2014-06-04 06:53:35 +0200488
paul718e3742002-12-13 20:15:29 +0000489/* Local preference configuration. */
490int
491bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
492{
493 if (! bgp)
494 return -1;
495
paul718e3742002-12-13 20:15:29 +0000496 bgp->default_local_pref = local_pref;
497
498 return 0;
499}
500
501int
502bgp_default_local_preference_unset (struct bgp *bgp)
503{
504 if (! bgp)
505 return -1;
506
paul718e3742002-12-13 20:15:29 +0000507 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
508
509 return 0;
510}
David Lamparter6b0655a2014-06-04 06:53:35 +0200511
paulfee0f4c2004-09-13 05:12:46 +0000512/* If peer is RSERVER_CLIENT in at least one address family and is not member
513 of a peer_group for that family, return 1.
514 Used to check wether the peer is included in list bgp->rsclient. */
515int
516peer_rsclient_active (struct peer *peer)
517{
518 int i;
519 int j;
520
521 for (i=AFI_IP; i < AFI_MAX; i++)
522 for (j=SAFI_UNICAST; j < SAFI_MAX; j++)
523 if (CHECK_FLAG(peer->af_flags[i][j], PEER_FLAG_RSERVER_CLIENT)
524 && ! peer->af_group[i][j])
525 return 1;
526 return 0;
527}
528
pauleb821182004-05-01 08:44:08 +0000529/* Peer comparison function for sorting. */
paul718e3742002-12-13 20:15:29 +0000530static int
531peer_cmp (struct peer *p1, struct peer *p2)
532{
pauleb821182004-05-01 08:44:08 +0000533 return sockunion_cmp (&p1->su, &p2->su);
paul718e3742002-12-13 20:15:29 +0000534}
535
536int
537peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
538{
539 return CHECK_FLAG (peer->af_flags[afi][safi], flag);
540}
541
542/* Reset all address family specific configuration. */
543static void
544peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
545{
546 int i;
547 struct bgp_filter *filter;
548 char orf_name[BUFSIZ];
549
550 filter = &peer->filter[afi][safi];
551
552 /* Clear neighbor filter and route-map */
553 for (i = FILTER_IN; i < FILTER_MAX; i++)
554 {
555 if (filter->dlist[i].name)
556 {
557 free (filter->dlist[i].name);
558 filter->dlist[i].name = NULL;
559 }
560 if (filter->plist[i].name)
561 {
562 free (filter->plist[i].name);
563 filter->plist[i].name = NULL;
564 }
565 if (filter->aslist[i].name)
566 {
567 free (filter->aslist[i].name);
568 filter->aslist[i].name = NULL;
569 }
paulfee0f4c2004-09-13 05:12:46 +0000570 }
571 for (i = RMAP_IN; i < RMAP_MAX; i++)
572 {
paul718e3742002-12-13 20:15:29 +0000573 if (filter->map[i].name)
574 {
575 free (filter->map[i].name);
576 filter->map[i].name = NULL;
577 }
578 }
579
580 /* Clear unsuppress map. */
581 if (filter->usmap.name)
582 free (filter->usmap.name);
583 filter->usmap.name = NULL;
584 filter->usmap.map = NULL;
585
586 /* Clear neighbor's all address family flags. */
587 peer->af_flags[afi][safi] = 0;
588
589 /* Clear neighbor's all address family sflags. */
590 peer->af_sflags[afi][safi] = 0;
591
592 /* Clear neighbor's all address family capabilities. */
593 peer->af_cap[afi][safi] = 0;
594
595 /* Clear ORF info */
596 peer->orf_plist[afi][safi] = NULL;
597 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
David Lamparterc9c06d02015-04-13 10:21:35 +0200598 prefix_bgp_orf_remove_all (afi, orf_name);
paul718e3742002-12-13 20:15:29 +0000599
600 /* Set default neighbor send-community. */
601 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
602 {
603 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
604 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
605 }
606
607 /* Clear neighbor default_originate_rmap */
608 if (peer->default_rmap[afi][safi].name)
609 free (peer->default_rmap[afi][safi].name);
610 peer->default_rmap[afi][safi].name = NULL;
611 peer->default_rmap[afi][safi].map = NULL;
612
613 /* Clear neighbor maximum-prefix */
614 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +0000615 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000616}
617
618/* peer global config reset */
paul94f2b392005-06-28 12:44:16 +0000619static void
paul718e3742002-12-13 20:15:29 +0000620peer_global_config_reset (struct peer *peer)
621{
622 peer->weight = 0;
623 peer->change_local_as = 0;
624 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
625 if (peer->update_source)
626 {
627 sockunion_free (peer->update_source);
628 peer->update_source = NULL;
629 }
630 if (peer->update_if)
631 {
632 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
633 peer->update_if = NULL;
634 }
635
636 if (peer_sort (peer) == BGP_PEER_IBGP)
637 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
638 else
639 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
640
641 peer->flags = 0;
642 peer->config = 0;
643 peer->holdtime = 0;
644 peer->keepalive = 0;
645 peer->connect = 0;
646 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
647}
648
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000649/* Check peer's AS number and determines if this peer is IBGP or EBGP */
650static bgp_peer_sort_t
651peer_calc_sort (struct peer *peer)
paul718e3742002-12-13 20:15:29 +0000652{
653 struct bgp *bgp;
654
655 bgp = peer->bgp;
656
657 /* Peer-group */
658 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
659 {
660 if (peer->as)
661 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
662 else
663 {
664 struct peer *peer1;
665 peer1 = listnode_head (peer->group->peer);
666 if (peer1)
667 return (peer1->local_as == peer1->as
668 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
669 }
670 return BGP_PEER_INTERNAL;
671 }
672
673 /* Normal peer */
674 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
675 {
676 if (peer->local_as == 0)
677 return BGP_PEER_INTERNAL;
678
679 if (peer->local_as == peer->as)
680 {
681 if (peer->local_as == bgp->confed_id)
682 return BGP_PEER_EBGP;
683 else
684 return BGP_PEER_IBGP;
685 }
686
687 if (bgp_confederation_peers_check (bgp, peer->as))
688 return BGP_PEER_CONFED;
689
690 return BGP_PEER_EBGP;
691 }
692 else
693 {
694 return (peer->local_as == 0
695 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
696 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
697 }
698}
699
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000700/* Calculate and cache the peer "sort" */
701bgp_peer_sort_t
702peer_sort (struct peer *peer)
703{
704 peer->sort = peer_calc_sort (peer);
705 return peer->sort;
706}
707
Paul Jakmaf63f06d2011-04-08 12:44:43 +0100708static void
paul200df112005-06-01 11:17:05 +0000709peer_free (struct peer *peer)
710{
Paul Jakmaca058a32006-09-14 02:58:49 +0000711 assert (peer->status == Deleted);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700712
713 bgp_unlock(peer->bgp);
714
Paul Jakmaca058a32006-09-14 02:58:49 +0000715 /* this /ought/ to have been done already through bgp_stop earlier,
716 * but just to be sure..
717 */
718 bgp_timer_set (peer);
719 BGP_READ_OFF (peer->t_read);
720 BGP_WRITE_OFF (peer->t_write);
Paul Jakma9fde6622006-09-14 03:02:02 +0000721 BGP_EVENT_FLUSH (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +0000722
paul200df112005-06-01 11:17:05 +0000723 if (peer->desc)
724 XFREE (MTYPE_PEER_DESC, peer->desc);
725
726 /* Free allocated host character. */
727 if (peer->host)
728 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
729
730 /* Update source configuration. */
731 if (peer->update_source)
732 sockunion_free (peer->update_source);
733
734 if (peer->update_if)
735 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
Paul Jakmaa625ca32006-03-30 14:12:38 +0000736
737 if (peer->clear_node_queue)
738 work_queue_free (peer->clear_node_queue);
739
Paul Jakmaca058a32006-09-14 02:58:49 +0000740 bgp_sync_delete (peer);
paul200df112005-06-01 11:17:05 +0000741 memset (peer, 0, sizeof (struct peer));
742
743 XFREE (MTYPE_BGP_PEER, peer);
744}
745
746/* increase reference count on a struct peer */
747struct peer *
748peer_lock (struct peer *peer)
749{
750 assert (peer && (peer->lock >= 0));
Paul Jakmaca058a32006-09-14 02:58:49 +0000751
paul200df112005-06-01 11:17:05 +0000752 peer->lock++;
753
754 return peer;
755}
756
757/* decrease reference count on a struct peer
758 * struct peer is freed and NULL returned if last reference
759 */
760struct peer *
761peer_unlock (struct peer *peer)
762{
763 assert (peer && (peer->lock > 0));
764
765 peer->lock--;
766
767 if (peer->lock == 0)
768 {
769#if 0
770 zlog_debug ("unlocked and freeing");
771 zlog_backtrace (LOG_DEBUG);
772#endif
773 peer_free (peer);
774 return NULL;
775 }
776
777#if 0
778 if (peer->lock == 1)
779 {
780 zlog_debug ("unlocked to 1");
781 zlog_backtrace (LOG_DEBUG);
782 }
783#endif
784
785 return peer;
786}
787
788/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000789static struct peer *
Paul Jakma6f585442006-10-22 19:13:07 +0000790peer_new (struct bgp *bgp)
paul718e3742002-12-13 20:15:29 +0000791{
792 afi_t afi;
793 safi_t safi;
794 struct peer *peer;
795 struct servent *sp;
Paul Jakma6f585442006-10-22 19:13:07 +0000796
797 /* bgp argument is absolutely required */
798 assert (bgp);
799 if (!bgp)
800 return NULL;
801
paul718e3742002-12-13 20:15:29 +0000802 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000803 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000804
805 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000806 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000807 peer->v_start = BGP_INIT_START_TIMER;
808 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
809 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
810 peer->status = Idle;
811 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000812 peer->weight = 0;
Paul Jakma0df7c912008-07-21 21:02:49 +0000813 peer->password = NULL;
Paul Jakma6f585442006-10-22 19:13:07 +0000814 peer->bgp = bgp;
Paul Jakmaca058a32006-09-14 02:58:49 +0000815 peer = peer_lock (peer); /* initial reference */
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700816 bgp_lock (bgp);
paul718e3742002-12-13 20:15:29 +0000817
818 /* Set default flags. */
819 for (afi = AFI_IP; afi < AFI_MAX; afi++)
820 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
821 {
822 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
823 {
824 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
825 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
826 }
827 peer->orf_plist[afi][safi] = NULL;
828 }
829 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
830
831 /* Create buffers. */
832 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
833 peer->obuf = stream_fifo_new ();
834 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000835 peer->scratch = stream_new (BGP_MAX_PACKET_SIZE);
paul718e3742002-12-13 20:15:29 +0000836
837 bgp_sync_init (peer);
838
839 /* Get service port number. */
840 sp = getservbyname ("bgp", "tcp");
841 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
842
843 return peer;
844}
845
846/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000847static struct peer *
paul718e3742002-12-13 20:15:29 +0000848peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
849 as_t remote_as, afi_t afi, safi_t safi)
850{
851 int active;
852 struct peer *peer;
853 char buf[SU_ADDRSTRLEN];
854
Paul Jakma6f585442006-10-22 19:13:07 +0000855 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000856 peer->su = *su;
857 peer->local_as = local_as;
858 peer->as = remote_as;
859 peer->local_id = bgp->router_id;
860 peer->v_holdtime = bgp->default_holdtime;
861 peer->v_keepalive = bgp->default_keepalive;
862 if (peer_sort (peer) == BGP_PEER_IBGP)
863 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
864 else
865 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000866
867 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000868 listnode_add_sort (bgp->peer, peer);
869
870 active = peer_active (peer);
871
872 if (afi && safi)
873 peer->afc[afi][safi] = 1;
874
Stephen Hemminger65957882010-01-15 16:22:10 +0300875 /* Last read and reset time set */
876 peer->readtime = peer->resettime = bgp_clock ();
paul848973c2003-08-13 00:32:49 +0000877
paul718e3742002-12-13 20:15:29 +0000878 /* Default TTL set. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000879 peer->ttl = (peer->sort == BGP_PEER_IBGP) ? 255 : 1;
paul718e3742002-12-13 20:15:29 +0000880
881 /* Make peer's address string. */
882 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000883 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000884
885 /* Set up peer's events and timers. */
886 if (! active && peer_active (peer))
887 bgp_timer_set (peer);
888
889 return peer;
890}
891
pauleb821182004-05-01 08:44:08 +0000892/* Make accept BGP peer. Called from bgp_accept (). */
893struct peer *
894peer_create_accept (struct bgp *bgp)
895{
896 struct peer *peer;
897
Paul Jakma6f585442006-10-22 19:13:07 +0000898 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000899
900 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000901 listnode_add_sort (bgp->peer, peer);
902
903 return peer;
904}
905
paul718e3742002-12-13 20:15:29 +0000906/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000907static void
paul718e3742002-12-13 20:15:29 +0000908peer_as_change (struct peer *peer, as_t as)
909{
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000910 bgp_peer_sort_t type;
paul718e3742002-12-13 20:15:29 +0000911
912 /* Stop peer. */
913 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
914 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000915 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000916 {
917 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
918 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
919 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
920 }
paul718e3742002-12-13 20:15:29 +0000921 else
922 BGP_EVENT_ADD (peer, BGP_Stop);
923 }
924 type = peer_sort (peer);
925 peer->as = as;
926
paul848973c2003-08-13 00:32:49 +0000927 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
928 && ! bgp_confederation_peers_check (peer->bgp, as)
929 && peer->bgp->as != as)
930 peer->local_as = peer->bgp->confed_id;
931 else
932 peer->local_as = peer->bgp->as;
933
paul718e3742002-12-13 20:15:29 +0000934 /* Advertisement-interval reset */
935 if (peer_sort (peer) == BGP_PEER_IBGP)
936 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
937 else
938 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
939
940 /* TTL reset */
941 if (peer_sort (peer) == BGP_PEER_IBGP)
942 peer->ttl = 255;
943 else if (type == BGP_PEER_IBGP)
944 peer->ttl = 1;
945
946 /* reflector-client reset */
947 if (peer_sort (peer) != BGP_PEER_IBGP)
948 {
949 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
950 PEER_FLAG_REFLECTOR_CLIENT);
951 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
952 PEER_FLAG_REFLECTOR_CLIENT);
953 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
954 PEER_FLAG_REFLECTOR_CLIENT);
955 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
956 PEER_FLAG_REFLECTOR_CLIENT);
957 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
958 PEER_FLAG_REFLECTOR_CLIENT);
959 }
960
961 /* local-as reset */
962 if (peer_sort (peer) != BGP_PEER_EBGP)
963 {
964 peer->change_local_as = 0;
965 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +0000966 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +0000967 }
968}
969
970/* If peer does not exist, create new one. If peer already exists,
971 set AS number to the peer. */
972int
973peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
974 afi_t afi, safi_t safi)
975{
976 struct peer *peer;
977 as_t local_as;
978
979 peer = peer_lookup (bgp, su);
980
981 if (peer)
982 {
983 /* When this peer is a member of peer-group. */
984 if (peer->group)
985 {
986 if (peer->group->conf->as)
987 {
988 /* Return peer group's AS number. */
989 *as = peer->group->conf->as;
990 return BGP_ERR_PEER_GROUP_MEMBER;
991 }
992 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
993 {
994 if (bgp->as != *as)
995 {
996 *as = peer->as;
997 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
998 }
999 }
1000 else
1001 {
1002 if (bgp->as == *as)
1003 {
1004 *as = peer->as;
1005 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1006 }
1007 }
1008 }
1009
1010 /* Existing peer's AS number change. */
1011 if (peer->as != *as)
1012 peer_as_change (peer, *as);
1013 }
1014 else
1015 {
1016
1017 /* If the peer is not part of our confederation, and its not an
1018 iBGP peer then spoof the source AS */
1019 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1020 && ! bgp_confederation_peers_check (bgp, *as)
1021 && bgp->as != *as)
1022 local_as = bgp->confed_id;
1023 else
1024 local_as = bgp->as;
1025
1026 /* If this is IPv4 unicast configuration and "no bgp default
1027 ipv4-unicast" is specified. */
1028
1029 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1030 && afi == AFI_IP && safi == SAFI_UNICAST)
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001031 peer_create (su, bgp, local_as, *as, 0, 0);
paul718e3742002-12-13 20:15:29 +00001032 else
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001033 peer_create (su, bgp, local_as, *as, afi, safi);
paul718e3742002-12-13 20:15:29 +00001034 }
1035
1036 return 0;
1037}
1038
1039/* Activate the peer or peer group for specified AFI and SAFI. */
1040int
1041peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1042{
1043 int active;
1044
1045 if (peer->afc[afi][safi])
1046 return 0;
1047
1048 /* Activate the address family configuration. */
1049 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1050 peer->afc[afi][safi] = 1;
1051 else
1052 {
1053 active = peer_active (peer);
1054
1055 peer->afc[afi][safi] = 1;
1056
1057 if (! active && peer_active (peer))
1058 bgp_timer_set (peer);
1059 else
1060 {
1061 if (peer->status == Established)
1062 {
1063 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1064 {
1065 peer->afc_adv[afi][safi] = 1;
1066 bgp_capability_send (peer, afi, safi,
1067 CAPABILITY_CODE_MP,
1068 CAPABILITY_ACTION_SET);
1069 if (peer->afc_recv[afi][safi])
1070 {
1071 peer->afc_nego[afi][safi] = 1;
1072 bgp_announce_route (peer, afi, safi);
1073 }
1074 }
1075 else
hassoe0701b72004-05-20 09:19:34 +00001076 {
1077 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1078 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1079 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1080 }
paul718e3742002-12-13 20:15:29 +00001081 }
1082 }
1083 }
1084 return 0;
1085}
1086
1087int
1088peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1089{
1090 struct peer_group *group;
1091 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001092 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001093
1094 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1095 {
1096 group = peer->group;
1097
paul1eb8ef22005-04-07 07:30:20 +00001098 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001099 {
1100 if (peer1->af_group[afi][safi])
1101 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1102 }
1103 }
1104 else
1105 {
1106 if (peer->af_group[afi][safi])
1107 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1108 }
1109
1110 if (! peer->afc[afi][safi])
1111 return 0;
1112
1113 /* De-activate the address family configuration. */
1114 peer->afc[afi][safi] = 0;
1115 peer_af_flag_reset (peer, afi, safi);
1116
1117 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1118 {
1119 if (peer->status == Established)
1120 {
1121 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1122 {
1123 peer->afc_adv[afi][safi] = 0;
1124 peer->afc_nego[afi][safi] = 0;
1125
1126 if (peer_active_nego (peer))
1127 {
1128 bgp_capability_send (peer, afi, safi,
1129 CAPABILITY_CODE_MP,
1130 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001131 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001132 peer->pcount[afi][safi] = 0;
1133 }
1134 else
hassoe0701b72004-05-20 09:19:34 +00001135 {
1136 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1137 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1138 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1139 }
paul718e3742002-12-13 20:15:29 +00001140 }
1141 else
hassoe0701b72004-05-20 09:19:34 +00001142 {
1143 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1144 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1145 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1146 }
paul718e3742002-12-13 20:15:29 +00001147 }
1148 }
1149 return 0;
1150}
1151
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001152static void
hasso93406d82005-02-02 14:40:33 +00001153peer_nsf_stop (struct peer *peer)
1154{
1155 afi_t afi;
1156 safi_t safi;
1157
1158 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1159 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1160
1161 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +04001162 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +00001163 peer->nsf[afi][safi] = 0;
1164
1165 if (peer->t_gr_restart)
1166 {
1167 BGP_TIMER_OFF (peer->t_gr_restart);
1168 if (BGP_DEBUG (events, EVENTS))
1169 zlog_debug ("%s graceful restart timer stopped", peer->host);
1170 }
1171 if (peer->t_gr_stale)
1172 {
1173 BGP_TIMER_OFF (peer->t_gr_stale);
1174 if (BGP_DEBUG (events, EVENTS))
1175 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1176 }
1177 bgp_clear_route_all (peer);
1178}
1179
Paul Jakmaca058a32006-09-14 02:58:49 +00001180/* Delete peer from confguration.
1181 *
1182 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1183 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1184 *
1185 * This function /should/ take care to be idempotent, to guard against
1186 * it being called multiple times through stray events that come in
1187 * that happen to result in this function being called again. That
1188 * said, getting here for a "Deleted" peer is a bug in the neighbour
1189 * FSM.
1190 */
paul718e3742002-12-13 20:15:29 +00001191int
1192peer_delete (struct peer *peer)
1193{
1194 int i;
1195 afi_t afi;
1196 safi_t safi;
1197 struct bgp *bgp;
1198 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001199 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001200
Paul Jakmaca058a32006-09-14 02:58:49 +00001201 assert (peer->status != Deleted);
1202
paul718e3742002-12-13 20:15:29 +00001203 bgp = peer->bgp;
1204
hasso93406d82005-02-02 14:40:33 +00001205 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1206 peer_nsf_stop (peer);
1207
Chris Caputo228da422009-07-18 05:44:03 +00001208 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001209 relationship. */
1210 if (peer->group)
1211 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001212 if ((pn = listnode_lookup (peer->group->peer, peer)))
1213 {
1214 peer = peer_unlock (peer); /* group->peer list reference */
1215 list_delete_node (peer->group->peer, pn);
1216 }
paul718e3742002-12-13 20:15:29 +00001217 peer->group = NULL;
1218 }
paul200df112005-06-01 11:17:05 +00001219
paul718e3742002-12-13 20:15:29 +00001220 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001221 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1222 * executed after peer structure is deleted.
1223 */
hassoe0701b72004-05-20 09:19:34 +00001224 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001225 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001226 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001227
1228 /* Password configuration */
1229 if (peer->password)
1230 {
1231 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1232 peer->password = NULL;
1233
1234 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1235 bgp_md5_set (peer);
1236 }
1237
Paul Jakmaca058a32006-09-14 02:58:49 +00001238 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001239
paul718e3742002-12-13 20:15:29 +00001240 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001241 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1242 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001243 {
Chris Caputo228da422009-07-18 05:44:03 +00001244 peer_unlock (peer); /* bgp peer list reference */
1245 list_delete_node (bgp->peer, pn);
1246 }
paul200df112005-06-01 11:17:05 +00001247
Chris Caputo228da422009-07-18 05:44:03 +00001248 if (peer_rsclient_active (peer)
1249 && (pn = listnode_lookup (bgp->rsclient, peer)))
1250 {
1251 peer_unlock (peer); /* rsclient list reference */
1252 list_delete_node (bgp->rsclient, pn);
1253
1254 /* Clear our own rsclient ribs. */
1255 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1256 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1257 if (CHECK_FLAG(peer->af_flags[afi][safi],
1258 PEER_FLAG_RSERVER_CLIENT))
1259 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001260 }
1261
1262 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1263 member of a peer_group. */
1264 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1265 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1266 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001267 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001268
paul200df112005-06-01 11:17:05 +00001269 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001270 if (peer->ibuf)
1271 stream_free (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001272 if (peer->obuf)
1273 stream_fifo_free (peer->obuf);
paul718e3742002-12-13 20:15:29 +00001274 if (peer->work)
1275 stream_free (peer->work);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00001276 if (peer->scratch)
1277 stream_free(peer->scratch);
Paul Jakma18937402006-07-27 19:05:12 +00001278 peer->obuf = NULL;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00001279 peer->work = peer->scratch = peer->ibuf = NULL;
Paul Jakma18937402006-07-27 19:05:12 +00001280
paul718e3742002-12-13 20:15:29 +00001281 /* Local and remote addresses. */
1282 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001283 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001284 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001285 sockunion_free (peer->su_remote);
Paul Jakma18937402006-07-27 19:05:12 +00001286 peer->su_local = peer->su_remote = NULL;
paul200df112005-06-01 11:17:05 +00001287
paul718e3742002-12-13 20:15:29 +00001288 /* Free filter related memory. */
1289 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1290 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1291 {
1292 filter = &peer->filter[afi][safi];
1293
1294 for (i = FILTER_IN; i < FILTER_MAX; i++)
1295 {
1296 if (filter->dlist[i].name)
1297 free (filter->dlist[i].name);
1298 if (filter->plist[i].name)
1299 free (filter->plist[i].name);
1300 if (filter->aslist[i].name)
1301 free (filter->aslist[i].name);
paul200df112005-06-01 11:17:05 +00001302
1303 filter->dlist[i].name = NULL;
1304 filter->plist[i].name = NULL;
1305 filter->aslist[i].name = NULL;
1306 }
1307 for (i = RMAP_IN; i < RMAP_MAX; i++)
1308 {
paul718e3742002-12-13 20:15:29 +00001309 if (filter->map[i].name)
1310 free (filter->map[i].name);
paul200df112005-06-01 11:17:05 +00001311 filter->map[i].name = NULL;
paul718e3742002-12-13 20:15:29 +00001312 }
1313
1314 if (filter->usmap.name)
1315 free (filter->usmap.name);
1316
1317 if (peer->default_rmap[afi][safi].name)
1318 free (peer->default_rmap[afi][safi].name);
paul200df112005-06-01 11:17:05 +00001319
1320 filter->usmap.name = NULL;
1321 peer->default_rmap[afi][safi].name = NULL;
paul718e3742002-12-13 20:15:29 +00001322 }
paul200df112005-06-01 11:17:05 +00001323
1324 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001325
1326 return 0;
1327}
David Lamparter6b0655a2014-06-04 06:53:35 +02001328
paul94f2b392005-06-28 12:44:16 +00001329static int
paul718e3742002-12-13 20:15:29 +00001330peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1331{
1332 return strcmp (g1->name, g2->name);
1333}
1334
1335/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001336static int
paul718e3742002-12-13 20:15:29 +00001337peer_group_active (struct peer *peer)
1338{
1339 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1340 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1341 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1342 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1343 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1344 return 1;
1345 return 0;
1346}
1347
1348/* Peer group cofiguration. */
1349static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001350peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001351{
1352 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1353 sizeof (struct peer_group));
1354}
1355
paul94f2b392005-06-28 12:44:16 +00001356static void
paul718e3742002-12-13 20:15:29 +00001357peer_group_free (struct peer_group *group)
1358{
1359 XFREE (MTYPE_PEER_GROUP, group);
1360}
1361
1362struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001363peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001364{
1365 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001366 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001367
paul1eb8ef22005-04-07 07:30:20 +00001368 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001369 {
1370 if (strcmp (group->name, name) == 0)
1371 return group;
1372 }
1373 return NULL;
1374}
1375
1376struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001377peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001378{
1379 struct peer_group *group;
1380
1381 group = peer_group_lookup (bgp, name);
1382 if (group)
1383 return group;
1384
1385 group = peer_group_new ();
1386 group->bgp = bgp;
1387 group->name = strdup (name);
1388 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001389 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001390 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1391 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001392 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001393 group->conf->group = group;
1394 group->conf->as = 0;
1395 group->conf->ttl = 1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001396 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001397 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1398 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1399 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1400 group->conf->keepalive = 0;
1401 group->conf->holdtime = 0;
1402 group->conf->connect = 0;
1403 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1404 listnode_add_sort (bgp->group, group);
1405
1406 return 0;
1407}
1408
paul94f2b392005-06-28 12:44:16 +00001409static void
paul718e3742002-12-13 20:15:29 +00001410peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1411 afi_t afi, safi_t safi)
1412{
1413 int in = FILTER_IN;
1414 int out = FILTER_OUT;
1415 struct peer *conf;
1416 struct bgp_filter *pfilter;
1417 struct bgp_filter *gfilter;
1418
1419 conf = group->conf;
1420 pfilter = &peer->filter[afi][safi];
1421 gfilter = &conf->filter[afi][safi];
1422
1423 /* remote-as */
1424 if (conf->as)
1425 peer->as = conf->as;
1426
1427 /* remote-as */
1428 if (conf->change_local_as)
1429 peer->change_local_as = conf->change_local_as;
1430
1431 /* TTL */
1432 peer->ttl = conf->ttl;
1433
Nick Hilliardfa411a22011-03-23 15:33:17 +00001434 /* GTSM hops */
1435 peer->gtsm_hops = conf->gtsm_hops;
1436
paul718e3742002-12-13 20:15:29 +00001437 /* Weight */
1438 peer->weight = conf->weight;
1439
1440 /* peer flags apply */
1441 peer->flags = conf->flags;
1442 /* peer af_flags apply */
1443 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1444 /* peer config apply */
1445 peer->config = conf->config;
1446
1447 /* peer timers apply */
1448 peer->holdtime = conf->holdtime;
1449 peer->keepalive = conf->keepalive;
1450 peer->connect = conf->connect;
1451 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1452 peer->v_connect = conf->connect;
1453 else
1454 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1455
1456 /* advertisement-interval reset */
1457 if (peer_sort (peer) == BGP_PEER_IBGP)
1458 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1459 else
1460 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1461
Paul Jakma0df7c912008-07-21 21:02:49 +00001462 /* password apply */
Roman Hoog Antink0e4303d2013-01-18 13:52:03 +01001463 if (conf->password && !peer->password)
Paul Jakma0df7c912008-07-21 21:02:49 +00001464 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
Paul Jakma0df7c912008-07-21 21:02:49 +00001465
1466 bgp_md5_set (peer);
1467
paul718e3742002-12-13 20:15:29 +00001468 /* maximum-prefix */
1469 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001470 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001471 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001472
1473 /* allowas-in */
1474 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1475
paulfee0f4c2004-09-13 05:12:46 +00001476 /* route-server-client */
1477 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1478 {
1479 /* Make peer's RIB point to group's RIB. */
1480 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1481
1482 /* Import policy. */
1483 if (pfilter->map[RMAP_IMPORT].name)
1484 free (pfilter->map[RMAP_IMPORT].name);
1485 if (gfilter->map[RMAP_IMPORT].name)
1486 {
1487 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1488 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1489 }
1490 else
1491 {
1492 pfilter->map[RMAP_IMPORT].name = NULL;
1493 pfilter->map[RMAP_IMPORT].map = NULL;
1494 }
1495
1496 /* Export policy. */
1497 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1498 {
1499 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1500 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1501 }
1502 }
1503
paul718e3742002-12-13 20:15:29 +00001504 /* default-originate route-map */
1505 if (conf->default_rmap[afi][safi].name)
1506 {
1507 if (peer->default_rmap[afi][safi].name)
1508 free (peer->default_rmap[afi][safi].name);
1509 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1510 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1511 }
1512
1513 /* update-source apply */
1514 if (conf->update_source)
1515 {
1516 if (peer->update_source)
1517 sockunion_free (peer->update_source);
1518 if (peer->update_if)
1519 {
1520 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1521 peer->update_if = NULL;
1522 }
1523 peer->update_source = sockunion_dup (conf->update_source);
1524 }
1525 else if (conf->update_if)
1526 {
1527 if (peer->update_if)
1528 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1529 if (peer->update_source)
1530 {
1531 sockunion_free (peer->update_source);
1532 peer->update_source = NULL;
1533 }
1534 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1535 }
1536
1537 /* inbound filter apply */
1538 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1539 {
1540 if (pfilter->dlist[in].name)
1541 free (pfilter->dlist[in].name);
1542 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1543 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1544 }
1545 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1546 {
1547 if (pfilter->plist[in].name)
1548 free (pfilter->plist[in].name);
1549 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1550 pfilter->plist[in].plist = gfilter->plist[in].plist;
1551 }
1552 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1553 {
1554 if (pfilter->aslist[in].name)
1555 free (pfilter->aslist[in].name);
1556 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1557 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1558 }
paulfee0f4c2004-09-13 05:12:46 +00001559 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001560 {
paulfee0f4c2004-09-13 05:12:46 +00001561 if (pfilter->map[RMAP_IN].name)
1562 free (pfilter->map[RMAP_IN].name);
1563 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1564 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001565 }
1566
1567 /* outbound filter apply */
1568 if (gfilter->dlist[out].name)
1569 {
1570 if (pfilter->dlist[out].name)
1571 free (pfilter->dlist[out].name);
1572 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1573 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1574 }
1575 else
1576 {
1577 if (pfilter->dlist[out].name)
1578 free (pfilter->dlist[out].name);
1579 pfilter->dlist[out].name = NULL;
1580 pfilter->dlist[out].alist = NULL;
1581 }
1582 if (gfilter->plist[out].name)
1583 {
1584 if (pfilter->plist[out].name)
1585 free (pfilter->plist[out].name);
1586 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1587 pfilter->plist[out].plist = gfilter->plist[out].plist;
1588 }
1589 else
1590 {
1591 if (pfilter->plist[out].name)
1592 free (pfilter->plist[out].name);
1593 pfilter->plist[out].name = NULL;
1594 pfilter->plist[out].plist = NULL;
1595 }
1596 if (gfilter->aslist[out].name)
1597 {
1598 if (pfilter->aslist[out].name)
1599 free (pfilter->aslist[out].name);
1600 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1601 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1602 }
1603 else
1604 {
1605 if (pfilter->aslist[out].name)
1606 free (pfilter->aslist[out].name);
1607 pfilter->aslist[out].name = NULL;
1608 pfilter->aslist[out].aslist = NULL;
1609 }
paulfee0f4c2004-09-13 05:12:46 +00001610 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001611 {
paulfee0f4c2004-09-13 05:12:46 +00001612 if (pfilter->map[RMAP_OUT].name)
1613 free (pfilter->map[RMAP_OUT].name);
1614 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1615 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001616 }
1617 else
1618 {
paulfee0f4c2004-09-13 05:12:46 +00001619 if (pfilter->map[RMAP_OUT].name)
1620 free (pfilter->map[RMAP_OUT].name);
1621 pfilter->map[RMAP_OUT].name = NULL;
1622 pfilter->map[RMAP_OUT].map = NULL;
1623 }
1624
1625 /* RS-client's import/export route-maps. */
1626 if (gfilter->map[RMAP_IMPORT].name)
1627 {
1628 if (pfilter->map[RMAP_IMPORT].name)
1629 free (pfilter->map[RMAP_IMPORT].name);
1630 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1631 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1632 }
1633 else
1634 {
1635 if (pfilter->map[RMAP_IMPORT].name)
1636 free (pfilter->map[RMAP_IMPORT].name);
1637 pfilter->map[RMAP_IMPORT].name = NULL;
1638 pfilter->map[RMAP_IMPORT].map = NULL;
1639 }
1640 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1641 {
1642 if (pfilter->map[RMAP_EXPORT].name)
1643 free (pfilter->map[RMAP_EXPORT].name);
1644 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1645 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001646 }
1647
1648 if (gfilter->usmap.name)
1649 {
1650 if (pfilter->usmap.name)
1651 free (pfilter->usmap.name);
1652 pfilter->usmap.name = strdup (gfilter->usmap.name);
1653 pfilter->usmap.map = gfilter->usmap.map;
1654 }
1655 else
1656 {
1657 if (pfilter->usmap.name)
1658 free (pfilter->usmap.name);
1659 pfilter->usmap.name = NULL;
1660 pfilter->usmap.map = NULL;
1661 }
1662}
1663
1664/* Peer group's remote AS configuration. */
1665int
paulfd79ac92004-10-13 05:06:08 +00001666peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001667{
1668 struct peer_group *group;
1669 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001670 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001671
1672 group = peer_group_lookup (bgp, group_name);
1673 if (! group)
1674 return -1;
1675
1676 if (group->conf->as == *as)
1677 return 0;
1678
1679 /* When we setup peer-group AS number all peer group member's AS
1680 number must be updated to same number. */
1681 peer_as_change (group->conf, *as);
1682
paul1eb8ef22005-04-07 07:30:20 +00001683 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001684 {
1685 if (peer->as != *as)
1686 peer_as_change (peer, *as);
1687 }
1688
1689 return 0;
1690}
1691
1692int
1693peer_group_delete (struct peer_group *group)
1694{
1695 struct bgp *bgp;
1696 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001697 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001698
1699 bgp = group->bgp;
1700
paul1eb8ef22005-04-07 07:30:20 +00001701 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001702 {
1703 peer->group = NULL;
1704 peer_delete (peer);
1705 }
1706 list_delete (group->peer);
1707
1708 free (group->name);
1709 group->name = NULL;
1710
1711 group->conf->group = NULL;
1712 peer_delete (group->conf);
1713
1714 /* Delete from all peer_group list. */
1715 listnode_delete (bgp->group, group);
1716
1717 peer_group_free (group);
1718
1719 return 0;
1720}
1721
1722int
1723peer_group_remote_as_delete (struct peer_group *group)
1724{
1725 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001726 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001727
1728 if (! group->conf->as)
1729 return 0;
1730
paul1eb8ef22005-04-07 07:30:20 +00001731 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001732 {
1733 peer->group = NULL;
1734 peer_delete (peer);
1735 }
1736 list_delete_all_node (group->peer);
1737
1738 group->conf->as = 0;
1739
1740 return 0;
1741}
1742
1743/* Bind specified peer to peer group. */
1744int
1745peer_group_bind (struct bgp *bgp, union sockunion *su,
1746 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1747{
1748 struct peer *peer;
1749 int first_member = 0;
1750
1751 /* Check peer group's address family. */
1752 if (! group->conf->afc[afi][safi])
1753 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1754
1755 /* Lookup the peer. */
1756 peer = peer_lookup (bgp, su);
1757
1758 /* Create a new peer. */
1759 if (! peer)
1760 {
1761 if (! group->conf->as)
1762 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1763
1764 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1765 peer->group = group;
1766 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001767
Paul Jakmaca058a32006-09-14 02:58:49 +00001768 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001769 listnode_add (group->peer, peer);
1770 peer_group2peer_config_copy (group, peer, afi, safi);
1771
1772 return 0;
1773 }
1774
1775 /* When the peer already belongs to peer group, check the consistency. */
1776 if (peer->af_group[afi][safi])
1777 {
1778 if (strcmp (peer->group->name, group->name) != 0)
1779 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1780
1781 return 0;
1782 }
1783
1784 /* Check current peer group configuration. */
1785 if (peer_group_active (peer)
1786 && strcmp (peer->group->name, group->name) != 0)
1787 return BGP_ERR_PEER_GROUP_MISMATCH;
1788
1789 if (! group->conf->as)
1790 {
1791 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1792 && peer_sort (group->conf) != peer_sort (peer))
1793 {
1794 if (as)
1795 *as = peer->as;
1796 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1797 }
1798
1799 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1800 first_member = 1;
1801 }
1802
1803 peer->af_group[afi][safi] = 1;
1804 peer->afc[afi][safi] = 1;
1805 if (! peer->group)
1806 {
1807 peer->group = group;
paul200df112005-06-01 11:17:05 +00001808
Paul Jakmaca058a32006-09-14 02:58:49 +00001809 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001810 listnode_add (group->peer, peer);
1811 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001812 else
1813 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001814
1815 if (first_member)
1816 {
1817 /* Advertisement-interval reset */
1818 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1819 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1820 else
1821 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1822
1823 /* ebgp-multihop reset */
1824 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1825 group->conf->ttl = 255;
1826
1827 /* local-as reset */
1828 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1829 {
1830 group->conf->change_local_as = 0;
1831 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001832 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001833 }
1834 }
paulfee0f4c2004-09-13 05:12:46 +00001835
1836 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1837 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001838 struct listnode *pn;
1839
paulfee0f4c2004-09-13 05:12:46 +00001840 /* If it's not configured as RSERVER_CLIENT in any other address
1841 family, without being member of a peer_group, remove it from
1842 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001843 if (! peer_rsclient_active (peer)
1844 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001845 {
1846 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001847 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001848
1849 /* Clear our own rsclient rib for this afi/safi. */
1850 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001851 }
paulfee0f4c2004-09-13 05:12:46 +00001852
Paul Jakmab608d5b2008-07-02 02:12:07 +00001853 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001854
1855 /* Import policy. */
1856 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1857 {
1858 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1859 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1860 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1861 }
1862
1863 /* Export policy. */
1864 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1865 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1866 {
1867 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1868 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1869 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1870 }
1871 }
1872
paul718e3742002-12-13 20:15:29 +00001873 peer_group2peer_config_copy (group, peer, afi, safi);
1874
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001875 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001876 {
1877 peer->last_reset = PEER_DOWN_RMAP_BIND;
1878 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1879 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1880 }
paul718e3742002-12-13 20:15:29 +00001881 else
1882 BGP_EVENT_ADD (peer, BGP_Stop);
1883
1884 return 0;
1885}
1886
1887int
1888peer_group_unbind (struct bgp *bgp, struct peer *peer,
1889 struct peer_group *group, afi_t afi, safi_t safi)
1890{
1891 if (! peer->af_group[afi][safi])
1892 return 0;
1893
1894 if (group != peer->group)
1895 return BGP_ERR_PEER_GROUP_MISMATCH;
1896
1897 peer->af_group[afi][safi] = 0;
1898 peer->afc[afi][safi] = 0;
1899 peer_af_flag_reset (peer, afi, safi);
1900
paulfee0f4c2004-09-13 05:12:46 +00001901 if (peer->rib[afi][safi])
1902 peer->rib[afi][safi] = NULL;
1903
paul718e3742002-12-13 20:15:29 +00001904 if (! peer_group_active (peer))
1905 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001906 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001907 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001908 listnode_delete (group->peer, peer);
1909 peer->group = NULL;
1910 if (group->conf->as)
1911 {
1912 peer_delete (peer);
1913 return 0;
1914 }
1915 peer_global_config_reset (peer);
1916 }
1917
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001918 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001919 {
1920 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1921 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1922 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1923 }
paul718e3742002-12-13 20:15:29 +00001924 else
1925 BGP_EVENT_ADD (peer, BGP_Stop);
1926
1927 return 0;
1928}
David Lamparter6b0655a2014-06-04 06:53:35 +02001929
Vipin Kumardd49eb12014-09-30 14:36:38 -07001930
1931static int
1932bgp_startup_timer_expire (struct thread *thread)
1933{
1934 struct bgp *bgp;
1935
1936 bgp = THREAD_ARG (thread);
1937 bgp->t_startup = NULL;
1938
1939 return 0;
1940}
1941
paul718e3742002-12-13 20:15:29 +00001942/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001943static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001944bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001945{
1946 struct bgp *bgp;
1947 afi_t afi;
1948 safi_t safi;
1949
paul200df112005-06-01 11:17:05 +00001950 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1951 return NULL;
1952
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07001953 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00001954 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00001955 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00001956
1957 bgp->peer = list_new ();
1958 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1959
1960 bgp->group = list_new ();
1961 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1962
paulfee0f4c2004-09-13 05:12:46 +00001963 bgp->rsclient = list_new ();
1964 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1965
paul718e3742002-12-13 20:15:29 +00001966 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1967 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1968 {
Paul Jakma64e580a2006-02-21 01:09:01 +00001969 bgp->route[afi][safi] = bgp_table_init (afi, safi);
1970 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1971 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07001972 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
1973 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00001974 }
1975
1976 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1977 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1978 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001979 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1980 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001981
1982 bgp->as = *as;
1983
1984 if (name)
1985 bgp->name = strdup (name);
1986
Vipin Kumardd49eb12014-09-30 14:36:38 -07001987 THREAD_TIMER_ON (master, bgp->t_startup, bgp_startup_timer_expire,
1988 bgp, bgp->restart_time);
1989
paul718e3742002-12-13 20:15:29 +00001990 return bgp;
1991}
1992
1993/* Return first entry of BGP. */
1994struct bgp *
paul94f2b392005-06-28 12:44:16 +00001995bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001996{
1997 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001998 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001999 return NULL;
2000}
2001
2002/* Lookup BGP entry. */
2003struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002004bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00002005{
2006 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002007 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002008
paul1eb8ef22005-04-07 07:30:20 +00002009 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002010 if (bgp->as == as
2011 && ((bgp->name == NULL && name == NULL)
2012 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
2013 return bgp;
2014 return NULL;
2015}
2016
2017/* Lookup BGP structure by view name. */
2018struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002019bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002020{
2021 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002022 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002023
paul1eb8ef22005-04-07 07:30:20 +00002024 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002025 if ((bgp->name == NULL && name == NULL)
2026 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2027 return bgp;
2028 return NULL;
2029}
2030
2031/* Called from VTY commands. */
2032int
paulfd79ac92004-10-13 05:06:08 +00002033bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002034{
2035 struct bgp *bgp;
2036
2037 /* Multiple instance check. */
2038 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2039 {
2040 if (name)
2041 bgp = bgp_lookup_by_name (name);
2042 else
2043 bgp = bgp_get_default ();
2044
2045 /* Already exists. */
2046 if (bgp)
2047 {
2048 if (bgp->as != *as)
2049 {
2050 *as = bgp->as;
2051 return BGP_ERR_INSTANCE_MISMATCH;
2052 }
2053 *bgp_val = bgp;
2054 return 0;
2055 }
2056 }
2057 else
2058 {
2059 /* BGP instance name can not be specified for single instance. */
2060 if (name)
2061 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2062
2063 /* Get default BGP structure if exists. */
2064 bgp = bgp_get_default ();
2065
2066 if (bgp)
2067 {
2068 if (bgp->as != *as)
2069 {
2070 *as = bgp->as;
2071 return BGP_ERR_AS_MISMATCH;
2072 }
2073 *bgp_val = bgp;
2074 return 0;
2075 }
2076 }
2077
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002078 bgp = bgp_create (as, name);
2079 bgp_router_id_set(bgp, &router_id_zebra);
2080 *bgp_val = bgp;
2081
Paul Jakmaad12dde2012-06-13 22:50:07 +01002082 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002083 if (list_isempty(bm->bgp)
2084 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002085 {
2086 if (bgp_socket (bm->port, bm->address) < 0)
2087 return BGP_ERR_INVALID_VALUE;
2088 }
2089
paul718e3742002-12-13 20:15:29 +00002090 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002091
2092 return 0;
2093}
2094
2095/* Delete BGP instance. */
2096int
2097bgp_delete (struct bgp *bgp)
2098{
2099 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002100 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002101 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002102 struct listnode *next;
2103 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002104 int i;
2105
David Lampartercffe7802014-12-07 03:27:13 +01002106 THREAD_OFF (bgp->t_startup);
2107
paul718e3742002-12-13 20:15:29 +00002108 /* Delete static route. */
2109 bgp_static_delete (bgp);
2110
2111 /* Unset redistribution. */
2112 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2113 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2114 if (i != ZEBRA_ROUTE_BGP)
2115 bgp_redistribute_unset (bgp, afi, i);
2116
paul1eb8ef22005-04-07 07:30:20 +00002117 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002118 {
2119 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2120 {
2121 /* Send notify to remote peer. */
2122 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2123 }
2124
2125 peer_delete (peer);
2126 }
paul718e3742002-12-13 20:15:29 +00002127
Chris Caputo228da422009-07-18 05:44:03 +00002128 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002129 {
2130 for (ALL_LIST_ELEMENTS (group->peer, node, next, peer))
2131 {
2132 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2133 {
2134 /* Send notify to remote peer. */
2135 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2136 }
2137 }
2138 peer_group_delete (group);
2139 }
Chris Caputo228da422009-07-18 05:44:03 +00002140
2141 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002142
2143 if (bgp->peer_self) {
2144 peer_delete(bgp->peer_self);
2145 bgp->peer_self = NULL;
2146 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002147
2148 /* Remove visibility via the master list - there may however still be
2149 * routes to be processed still referencing the struct bgp.
2150 */
2151 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002152 if (list_isempty(bm->bgp))
2153 bgp_close ();
2154
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002155 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002156
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002157 return 0;
2158}
2159
2160static void bgp_free (struct bgp *);
2161
2162void
2163bgp_lock (struct bgp *bgp)
2164{
2165 ++bgp->lock;
2166}
2167
2168void
2169bgp_unlock(struct bgp *bgp)
2170{
Chris Caputo228da422009-07-18 05:44:03 +00002171 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002172 if (--bgp->lock == 0)
2173 bgp_free (bgp);
2174}
2175
2176static void
2177bgp_free (struct bgp *bgp)
2178{
2179 afi_t afi;
2180 safi_t safi;
2181
2182 list_delete (bgp->group);
2183 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002184 list_delete (bgp->rsclient);
2185
paul718e3742002-12-13 20:15:29 +00002186 if (bgp->name)
2187 free (bgp->name);
2188
2189 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2190 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2191 {
2192 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002193 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002194 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002195 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002196 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002197 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002198 }
2199 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002200}
David Lamparter6b0655a2014-06-04 06:53:35 +02002201
paul718e3742002-12-13 20:15:29 +00002202struct peer *
2203peer_lookup (struct bgp *bgp, union sockunion *su)
2204{
2205 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002206 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002207
Steve Hillfc4dc592009-07-28 17:54:35 +01002208 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002209 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002210 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2211 if (sockunion_same (&peer->su, su)
2212 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2213 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002214 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002215 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002216 {
2217 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002218
Paul Jakma2158ad22009-07-28 18:10:55 +01002219 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2220 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2221 if (sockunion_same (&peer->su, su)
2222 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2223 return peer;
paul718e3742002-12-13 20:15:29 +00002224 }
2225 return NULL;
2226}
2227
2228struct peer *
2229peer_lookup_with_open (union sockunion *su, as_t remote_as,
2230 struct in_addr *remote_id, int *as)
2231{
2232 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002233 struct listnode *node;
2234 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002235 struct bgp *bgp;
2236
Steve Hillfc4dc592009-07-28 17:54:35 +01002237 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002238 return NULL;
2239
Paul Jakma9d878772009-08-05 16:25:16 +01002240 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002241 {
Paul Jakma9d878772009-08-05 16:25:16 +01002242 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2243 {
2244 if (sockunion_same (&peer->su, su)
2245 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2246 {
2247 if (peer->as == remote_as
2248 && peer->remote_id.s_addr == remote_id->s_addr)
2249 return peer;
2250 if (peer->as == remote_as)
2251 *as = 1;
2252 }
2253 }
2254
2255 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2256 {
2257 if (sockunion_same (&peer->su, su)
2258 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2259 {
2260 if (peer->as == remote_as
2261 && peer->remote_id.s_addr == 0)
2262 return peer;
2263 if (peer->as == remote_as)
2264 *as = 1;
2265 }
2266 }
paul718e3742002-12-13 20:15:29 +00002267 }
2268 return NULL;
2269}
David Lamparter6b0655a2014-06-04 06:53:35 +02002270
paul718e3742002-12-13 20:15:29 +00002271/* If peer is configured at least one address family return 1. */
2272int
2273peer_active (struct peer *peer)
2274{
2275 if (peer->afc[AFI_IP][SAFI_UNICAST]
2276 || peer->afc[AFI_IP][SAFI_MULTICAST]
2277 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2278 || peer->afc[AFI_IP6][SAFI_UNICAST]
2279 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2280 return 1;
2281 return 0;
2282}
2283
2284/* If peer is negotiated at least one address family return 1. */
2285int
2286peer_active_nego (struct peer *peer)
2287{
2288 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2289 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2290 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2291 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2292 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2293 return 1;
2294 return 0;
2295}
David Lamparter6b0655a2014-06-04 06:53:35 +02002296
paul718e3742002-12-13 20:15:29 +00002297/* peer_flag_change_type. */
2298enum peer_change_type
2299{
2300 peer_change_none,
2301 peer_change_reset,
2302 peer_change_reset_in,
2303 peer_change_reset_out,
2304};
2305
paul94f2b392005-06-28 12:44:16 +00002306static void
paul718e3742002-12-13 20:15:29 +00002307peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2308 enum peer_change_type type)
2309{
2310 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2311 return;
2312
Stephen Hemmingerd9d4ae52010-01-13 00:32:39 +00002313 if (peer->status != Established)
2314 return;
2315
paul718e3742002-12-13 20:15:29 +00002316 if (type == peer_change_reset)
2317 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2318 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2319 else if (type == peer_change_reset_in)
2320 {
2321 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2322 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2323 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2324 else
2325 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2326 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2327 }
2328 else if (type == peer_change_reset_out)
2329 bgp_announce_route (peer, afi, safi);
2330}
2331
2332struct peer_flag_action
2333{
2334 /* Peer's flag. */
2335 u_int32_t flag;
2336
2337 /* This flag can be set for peer-group member. */
2338 u_char not_for_member;
2339
2340 /* Action when the flag is changed. */
2341 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002342
2343 /* Peer down cause */
2344 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002345};
2346
Stephen Hemminger03621952009-07-21 16:27:20 -07002347static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002348 {
2349 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2350 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2351 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2352 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2353 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002354 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002355 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002356 { 0, 0, 0 }
2357 };
2358
Stephen Hemminger03621952009-07-21 16:27:20 -07002359static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002360 {
2361 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2362 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2363 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2364 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2365 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2366 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2367 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2368 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2369 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2370 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2371 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2372 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2373 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002374 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
Timo Teräs9e7a53c2014-04-24 10:22:37 +03002375 { PEER_FLAG_NEXTHOP_SELF_ALL, 1, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002376 { 0, 0, 0 }
2377 };
2378
2379/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002380static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002381peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002382 struct peer_flag_action *action, u_int32_t flag)
2383{
2384 int i;
2385 int found = 0;
2386 int reset_in = 0;
2387 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002388 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002389
2390 /* Check peer's frag action. */
2391 for (i = 0; i < size; i++)
2392 {
2393 match = &action_list[i];
2394
2395 if (match->flag == 0)
2396 break;
2397
2398 if (match->flag & flag)
2399 {
2400 found = 1;
2401
2402 if (match->type == peer_change_reset_in)
2403 reset_in = 1;
2404 if (match->type == peer_change_reset_out)
2405 reset_out = 1;
2406 if (match->type == peer_change_reset)
2407 {
2408 reset_in = 1;
2409 reset_out = 1;
2410 }
2411 if (match->not_for_member)
2412 action->not_for_member = 1;
2413 }
2414 }
2415
2416 /* Set peer clear type. */
2417 if (reset_in && reset_out)
2418 action->type = peer_change_reset;
2419 else if (reset_in)
2420 action->type = peer_change_reset_in;
2421 else if (reset_out)
2422 action->type = peer_change_reset_out;
2423 else
2424 action->type = peer_change_none;
2425
2426 return found;
2427}
2428
paul94f2b392005-06-28 12:44:16 +00002429static void
paul718e3742002-12-13 20:15:29 +00002430peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2431{
2432 if (flag == PEER_FLAG_SHUTDOWN)
2433 {
2434 if (CHECK_FLAG (peer->flags, flag))
2435 {
hasso93406d82005-02-02 14:40:33 +00002436 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2437 peer_nsf_stop (peer);
2438
hasso0a486e52005-02-01 20:57:17 +00002439 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2440 if (peer->t_pmax_restart)
2441 {
2442 BGP_TIMER_OFF (peer->t_pmax_restart);
2443 if (BGP_DEBUG (events, EVENTS))
2444 zlog_debug ("%s Maximum-prefix restart timer canceled",
2445 peer->host);
2446 }
2447
hasso93406d82005-02-02 14:40:33 +00002448 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2449 peer_nsf_stop (peer);
2450
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002451 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002452 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2453 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2454 else
2455 BGP_EVENT_ADD (peer, BGP_Stop);
2456 }
2457 else
2458 {
2459 peer->v_start = BGP_INIT_START_TIMER;
2460 BGP_EVENT_ADD (peer, BGP_Stop);
2461 }
2462 }
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002463 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002464 {
hassoc9502432005-02-01 22:01:48 +00002465 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2466 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2467 else if (flag == PEER_FLAG_PASSIVE)
2468 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002469 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002470 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002471
hassoc9502432005-02-01 22:01:48 +00002472 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2473 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002474 }
2475 else
2476 BGP_EVENT_ADD (peer, BGP_Stop);
2477}
2478
2479/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002480static int
paul718e3742002-12-13 20:15:29 +00002481peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2482{
2483 int found;
2484 int size;
2485 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002486 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002487 struct peer_flag_action action;
2488
2489 memset (&action, 0, sizeof (struct peer_flag_action));
2490 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2491
2492 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2493
2494 /* No flag action is found. */
2495 if (! found)
2496 return BGP_ERR_INVALID_FLAG;
2497
2498 /* Not for peer-group member. */
2499 if (action.not_for_member && peer_group_active (peer))
2500 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2501
2502 /* When unset the peer-group member's flag we have to check
2503 peer-group configuration. */
2504 if (! set && peer_group_active (peer))
2505 if (CHECK_FLAG (peer->group->conf->flags, flag))
2506 {
2507 if (flag == PEER_FLAG_SHUTDOWN)
2508 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2509 else
2510 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2511 }
2512
2513 /* Flag conflict check. */
2514 if (set
2515 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2516 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2517 return BGP_ERR_PEER_FLAG_CONFLICT;
2518
2519 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2520 {
2521 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2522 return 0;
2523 if (! set && ! CHECK_FLAG (peer->flags, flag))
2524 return 0;
2525 }
2526
2527 if (set)
2528 SET_FLAG (peer->flags, flag);
2529 else
2530 UNSET_FLAG (peer->flags, flag);
2531
2532 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2533 {
2534 if (action.type == peer_change_reset)
2535 peer_flag_modify_action (peer, flag);
2536
2537 return 0;
2538 }
2539
2540 /* peer-group member updates. */
2541 group = peer->group;
2542
paul1eb8ef22005-04-07 07:30:20 +00002543 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002544 {
2545 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2546 continue;
2547
2548 if (! set && ! CHECK_FLAG (peer->flags, flag))
2549 continue;
2550
2551 if (set)
2552 SET_FLAG (peer->flags, flag);
2553 else
2554 UNSET_FLAG (peer->flags, flag);
2555
2556 if (action.type == peer_change_reset)
2557 peer_flag_modify_action (peer, flag);
2558 }
2559 return 0;
2560}
2561
2562int
2563peer_flag_set (struct peer *peer, u_int32_t flag)
2564{
2565 return peer_flag_modify (peer, flag, 1);
2566}
2567
2568int
2569peer_flag_unset (struct peer *peer, u_int32_t flag)
2570{
2571 return peer_flag_modify (peer, flag, 0);
2572}
2573
paul94f2b392005-06-28 12:44:16 +00002574static int
paul718e3742002-12-13 20:15:29 +00002575peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2576{
2577 if (peer->af_group[afi][safi])
2578 return 1;
2579 return 0;
2580}
2581
paul94f2b392005-06-28 12:44:16 +00002582static int
paul718e3742002-12-13 20:15:29 +00002583peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2584 int set)
2585{
2586 int found;
2587 int size;
paul1eb8ef22005-04-07 07:30:20 +00002588 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002589 struct peer_group *group;
2590 struct peer_flag_action action;
2591
2592 memset (&action, 0, sizeof (struct peer_flag_action));
2593 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2594
2595 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2596
2597 /* No flag action is found. */
2598 if (! found)
2599 return BGP_ERR_INVALID_FLAG;
2600
2601 /* Adress family must be activated. */
2602 if (! peer->afc[afi][safi])
2603 return BGP_ERR_PEER_INACTIVE;
2604
2605 /* Not for peer-group member. */
2606 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2607 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2608
2609 /* Spcecial check for reflector client. */
2610 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2611 && peer_sort (peer) != BGP_PEER_IBGP)
2612 return BGP_ERR_NOT_INTERNAL_PEER;
2613
2614 /* Spcecial check for remove-private-AS. */
2615 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2616 && peer_sort (peer) == BGP_PEER_IBGP)
2617 return BGP_ERR_REMOVE_PRIVATE_AS;
2618
2619 /* When unset the peer-group member's flag we have to check
2620 peer-group configuration. */
2621 if (! set && peer->af_group[afi][safi])
2622 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2623 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2624
2625 /* When current flag configuration is same as requested one. */
2626 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2627 {
2628 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2629 return 0;
2630 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2631 return 0;
2632 }
2633
2634 if (set)
2635 SET_FLAG (peer->af_flags[afi][safi], flag);
2636 else
2637 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2638
2639 /* Execute action when peer is established. */
2640 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2641 && peer->status == Established)
2642 {
2643 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2644 bgp_clear_adj_in (peer, afi, safi);
2645 else
hassoe0701b72004-05-20 09:19:34 +00002646 {
2647 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2648 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2649 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2650 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2651 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2652 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2653 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2654 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2655
2656 peer_change_action (peer, afi, safi, action.type);
2657 }
2658
paul718e3742002-12-13 20:15:29 +00002659 }
2660
2661 /* Peer group member updates. */
2662 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2663 {
2664 group = peer->group;
2665
paul1eb8ef22005-04-07 07:30:20 +00002666 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002667 {
2668 if (! peer->af_group[afi][safi])
2669 continue;
2670
2671 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2672 continue;
2673
2674 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2675 continue;
2676
2677 if (set)
2678 SET_FLAG (peer->af_flags[afi][safi], flag);
2679 else
2680 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2681
2682 if (peer->status == Established)
2683 {
2684 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2685 bgp_clear_adj_in (peer, afi, safi);
2686 else
hassoe0701b72004-05-20 09:19:34 +00002687 {
2688 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2689 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2690 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2691 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2692 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2693 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2694 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2695 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2696
2697 peer_change_action (peer, afi, safi, action.type);
2698 }
paul718e3742002-12-13 20:15:29 +00002699 }
2700 }
2701 }
2702 return 0;
2703}
2704
2705int
2706peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2707{
2708 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2709}
2710
2711int
2712peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2713{
2714 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2715}
David Lamparter6b0655a2014-06-04 06:53:35 +02002716
paul718e3742002-12-13 20:15:29 +00002717/* EBGP multihop configuration. */
2718int
2719peer_ebgp_multihop_set (struct peer *peer, int ttl)
2720{
2721 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002722 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002723 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002724
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002725 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002726 return 0;
2727
Nick Hilliardfa411a22011-03-23 15:33:17 +00002728 /* see comment in peer_ttl_security_hops_set() */
2729 if (ttl != MAXTTL)
2730 {
2731 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2732 {
2733 group = peer->group;
2734 if (group->conf->gtsm_hops != 0)
2735 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2736
2737 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2738 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002739 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002740 continue;
2741
2742 if (peer1->gtsm_hops != 0)
2743 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2744 }
2745 }
2746 else
2747 {
2748 if (peer->gtsm_hops != 0)
2749 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2750 }
2751 }
2752
paul718e3742002-12-13 20:15:29 +00002753 peer->ttl = ttl;
2754
2755 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2756 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002757 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002758 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002759 }
2760 else
2761 {
2762 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002763 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002764 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002765 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002766 continue;
paul718e3742002-12-13 20:15:29 +00002767
pauleb821182004-05-01 08:44:08 +00002768 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002769
pauleb821182004-05-01 08:44:08 +00002770 if (peer->fd >= 0)
2771 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2772 }
paul718e3742002-12-13 20:15:29 +00002773 }
2774 return 0;
2775}
2776
2777int
2778peer_ebgp_multihop_unset (struct peer *peer)
2779{
2780 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002781 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002782
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002783 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002784 return 0;
2785
Nick Hilliardfa411a22011-03-23 15:33:17 +00002786 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2787 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2788
paul718e3742002-12-13 20:15:29 +00002789 if (peer_group_active (peer))
2790 peer->ttl = peer->group->conf->ttl;
2791 else
2792 peer->ttl = 1;
2793
2794 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2795 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002796 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002797 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002798 }
2799 else
2800 {
2801 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002802 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002803 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002804 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002805 continue;
paul718e3742002-12-13 20:15:29 +00002806
pauleb821182004-05-01 08:44:08 +00002807 peer->ttl = 1;
2808
2809 if (peer->fd >= 0)
2810 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2811 }
paul718e3742002-12-13 20:15:29 +00002812 }
2813 return 0;
2814}
David Lamparter6b0655a2014-06-04 06:53:35 +02002815
paul718e3742002-12-13 20:15:29 +00002816/* Neighbor description. */
2817int
2818peer_description_set (struct peer *peer, char *desc)
2819{
2820 if (peer->desc)
2821 XFREE (MTYPE_PEER_DESC, peer->desc);
2822
2823 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2824
2825 return 0;
2826}
2827
2828int
2829peer_description_unset (struct peer *peer)
2830{
2831 if (peer->desc)
2832 XFREE (MTYPE_PEER_DESC, peer->desc);
2833
2834 peer->desc = NULL;
2835
2836 return 0;
2837}
David Lamparter6b0655a2014-06-04 06:53:35 +02002838
paul718e3742002-12-13 20:15:29 +00002839/* Neighbor update-source. */
2840int
paulfd79ac92004-10-13 05:06:08 +00002841peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002842{
2843 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002844 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002845
2846 if (peer->update_if)
2847 {
2848 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2849 && strcmp (peer->update_if, ifname) == 0)
2850 return 0;
2851
2852 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2853 peer->update_if = NULL;
2854 }
2855
2856 if (peer->update_source)
2857 {
2858 sockunion_free (peer->update_source);
2859 peer->update_source = NULL;
2860 }
2861
2862 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2863
2864 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2865 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002866 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002867 {
2868 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2869 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2870 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2871 }
paul718e3742002-12-13 20:15:29 +00002872 else
2873 BGP_EVENT_ADD (peer, BGP_Stop);
2874 return 0;
2875 }
2876
2877 /* peer-group member updates. */
2878 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002879 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002880 {
2881 if (peer->update_if)
2882 {
2883 if (strcmp (peer->update_if, ifname) == 0)
2884 continue;
2885
2886 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2887 peer->update_if = NULL;
2888 }
2889
2890 if (peer->update_source)
2891 {
2892 sockunion_free (peer->update_source);
2893 peer->update_source = NULL;
2894 }
2895
2896 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2897
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002898 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002899 {
2900 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2901 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2902 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2903 }
paul718e3742002-12-13 20:15:29 +00002904 else
2905 BGP_EVENT_ADD (peer, BGP_Stop);
2906 }
2907 return 0;
2908}
2909
2910int
2911peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2912{
2913 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002914 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002915
2916 if (peer->update_source)
2917 {
2918 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2919 && sockunion_cmp (peer->update_source, su) == 0)
2920 return 0;
2921 sockunion_free (peer->update_source);
2922 peer->update_source = NULL;
2923 }
2924
2925 if (peer->update_if)
2926 {
2927 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2928 peer->update_if = NULL;
2929 }
2930
2931 peer->update_source = sockunion_dup (su);
2932
2933 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2934 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002935 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002936 {
2937 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2938 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2939 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2940 }
paul718e3742002-12-13 20:15:29 +00002941 else
2942 BGP_EVENT_ADD (peer, BGP_Stop);
2943 return 0;
2944 }
2945
2946 /* peer-group member updates. */
2947 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002948 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002949 {
2950 if (peer->update_source)
2951 {
2952 if (sockunion_cmp (peer->update_source, su) == 0)
2953 continue;
2954 sockunion_free (peer->update_source);
2955 peer->update_source = NULL;
2956 }
2957
2958 if (peer->update_if)
2959 {
2960 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2961 peer->update_if = NULL;
2962 }
2963
2964 peer->update_source = sockunion_dup (su);
2965
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002966 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002967 {
2968 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2969 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2970 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2971 }
paul718e3742002-12-13 20:15:29 +00002972 else
2973 BGP_EVENT_ADD (peer, BGP_Stop);
2974 }
2975 return 0;
2976}
2977
2978int
2979peer_update_source_unset (struct peer *peer)
2980{
2981 union sockunion *su;
2982 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002983 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002984
2985 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2986 && ! peer->update_source
2987 && ! peer->update_if)
2988 return 0;
2989
2990 if (peer->update_source)
2991 {
2992 sockunion_free (peer->update_source);
2993 peer->update_source = NULL;
2994 }
2995 if (peer->update_if)
2996 {
2997 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2998 peer->update_if = NULL;
2999 }
3000
3001 if (peer_group_active (peer))
3002 {
3003 group = peer->group;
3004
3005 if (group->conf->update_source)
3006 {
3007 su = sockunion_dup (group->conf->update_source);
3008 peer->update_source = su;
3009 }
3010 else if (group->conf->update_if)
3011 peer->update_if =
3012 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
3013 }
3014
3015 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3016 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003017 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003018 {
3019 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3020 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3021 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3022 }
paul718e3742002-12-13 20:15:29 +00003023 else
3024 BGP_EVENT_ADD (peer, BGP_Stop);
3025 return 0;
3026 }
3027
3028 /* peer-group member updates. */
3029 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003030 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003031 {
3032 if (! peer->update_source && ! peer->update_if)
3033 continue;
3034
3035 if (peer->update_source)
3036 {
3037 sockunion_free (peer->update_source);
3038 peer->update_source = NULL;
3039 }
3040
3041 if (peer->update_if)
3042 {
3043 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3044 peer->update_if = NULL;
3045 }
3046
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003047 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003048 {
3049 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3050 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3051 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3052 }
paul718e3742002-12-13 20:15:29 +00003053 else
3054 BGP_EVENT_ADD (peer, BGP_Stop);
3055 }
3056 return 0;
3057}
David Lamparter6b0655a2014-06-04 06:53:35 +02003058
paul718e3742002-12-13 20:15:29 +00003059int
3060peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003061 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003062{
3063 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003064 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003065
3066 /* Adress family must be activated. */
3067 if (! peer->afc[afi][safi])
3068 return BGP_ERR_PEER_INACTIVE;
3069
3070 /* Default originate can't be used for peer group memeber. */
3071 if (peer_is_group_member (peer, afi, safi))
3072 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3073
3074 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3075 || (rmap && ! peer->default_rmap[afi][safi].name)
3076 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3077 {
3078 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3079
3080 if (rmap)
3081 {
3082 if (peer->default_rmap[afi][safi].name)
3083 free (peer->default_rmap[afi][safi].name);
3084 peer->default_rmap[afi][safi].name = strdup (rmap);
3085 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3086 }
3087 }
3088
3089 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3090 {
3091 if (peer->status == Established && peer->afc_nego[afi][safi])
3092 bgp_default_originate (peer, afi, safi, 0);
3093 return 0;
3094 }
3095
3096 /* peer-group member updates. */
3097 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003098 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003099 {
3100 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3101
3102 if (rmap)
3103 {
3104 if (peer->default_rmap[afi][safi].name)
3105 free (peer->default_rmap[afi][safi].name);
3106 peer->default_rmap[afi][safi].name = strdup (rmap);
3107 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3108 }
3109
3110 if (peer->status == Established && peer->afc_nego[afi][safi])
3111 bgp_default_originate (peer, afi, safi, 0);
3112 }
3113 return 0;
3114}
3115
3116int
3117peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3118{
3119 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003120 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003121
3122 /* Adress family must be activated. */
3123 if (! peer->afc[afi][safi])
3124 return BGP_ERR_PEER_INACTIVE;
3125
3126 /* Default originate can't be used for peer group memeber. */
3127 if (peer_is_group_member (peer, afi, safi))
3128 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3129
3130 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3131 {
3132 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3133
3134 if (peer->default_rmap[afi][safi].name)
3135 free (peer->default_rmap[afi][safi].name);
3136 peer->default_rmap[afi][safi].name = NULL;
3137 peer->default_rmap[afi][safi].map = NULL;
3138 }
3139
3140 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3141 {
3142 if (peer->status == Established && peer->afc_nego[afi][safi])
3143 bgp_default_originate (peer, afi, safi, 1);
3144 return 0;
3145 }
3146
3147 /* peer-group member updates. */
3148 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003149 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003150 {
3151 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3152
3153 if (peer->default_rmap[afi][safi].name)
3154 free (peer->default_rmap[afi][safi].name);
3155 peer->default_rmap[afi][safi].name = NULL;
3156 peer->default_rmap[afi][safi].map = NULL;
3157
3158 if (peer->status == Established && peer->afc_nego[afi][safi])
3159 bgp_default_originate (peer, afi, safi, 1);
3160 }
3161 return 0;
3162}
David Lamparter6b0655a2014-06-04 06:53:35 +02003163
paul718e3742002-12-13 20:15:29 +00003164int
3165peer_port_set (struct peer *peer, u_int16_t port)
3166{
3167 peer->port = port;
3168 return 0;
3169}
3170
3171int
3172peer_port_unset (struct peer *peer)
3173{
3174 peer->port = BGP_PORT_DEFAULT;
3175 return 0;
3176}
David Lamparter6b0655a2014-06-04 06:53:35 +02003177
paul718e3742002-12-13 20:15:29 +00003178/* neighbor weight. */
3179int
3180peer_weight_set (struct peer *peer, u_int16_t weight)
3181{
3182 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003183 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003184
3185 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3186 peer->weight = weight;
3187
3188 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3189 return 0;
3190
3191 /* peer-group member updates. */
3192 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003193 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003194 {
3195 peer->weight = group->conf->weight;
3196 }
3197 return 0;
3198}
3199
3200int
3201peer_weight_unset (struct peer *peer)
3202{
3203 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003204 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003205
3206 /* Set default weight. */
3207 if (peer_group_active (peer))
3208 peer->weight = peer->group->conf->weight;
3209 else
3210 peer->weight = 0;
3211
3212 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3213
3214 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3215 return 0;
3216
3217 /* peer-group member updates. */
3218 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003219 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003220 {
3221 peer->weight = 0;
3222 }
3223 return 0;
3224}
David Lamparter6b0655a2014-06-04 06:53:35 +02003225
paul718e3742002-12-13 20:15:29 +00003226int
3227peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3228{
3229 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003230 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003231
3232 /* Not for peer group memeber. */
3233 if (peer_group_active (peer))
3234 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3235
3236 /* keepalive value check. */
3237 if (keepalive > 65535)
3238 return BGP_ERR_INVALID_VALUE;
3239
3240 /* Holdtime value check. */
3241 if (holdtime > 65535)
3242 return BGP_ERR_INVALID_VALUE;
3243
3244 /* Holdtime value must be either 0 or greater than 3. */
3245 if (holdtime < 3 && holdtime != 0)
3246 return BGP_ERR_INVALID_VALUE;
3247
3248 /* Set value to the configuration. */
3249 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3250 peer->holdtime = holdtime;
3251 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3252
3253 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3254 return 0;
3255
3256 /* peer-group member updates. */
3257 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003258 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003259 {
3260 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3261 peer->holdtime = group->conf->holdtime;
3262 peer->keepalive = group->conf->keepalive;
3263 }
3264 return 0;
3265}
3266
3267int
3268peer_timers_unset (struct peer *peer)
3269{
3270 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003271 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003272
3273 if (peer_group_active (peer))
3274 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3275
3276 /* Clear configuration. */
3277 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3278 peer->keepalive = 0;
3279 peer->holdtime = 0;
3280
3281 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3282 return 0;
3283
3284 /* peer-group member updates. */
3285 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003286 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003287 {
3288 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3289 peer->holdtime = 0;
3290 peer->keepalive = 0;
3291 }
3292
3293 return 0;
3294}
David Lamparter6b0655a2014-06-04 06:53:35 +02003295
paul718e3742002-12-13 20:15:29 +00003296int
3297peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3298{
3299 if (peer_group_active (peer))
3300 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3301
3302 if (connect > 65535)
3303 return BGP_ERR_INVALID_VALUE;
3304
3305 /* Set value to the configuration. */
3306 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3307 peer->connect = connect;
3308
3309 /* Set value to timer setting. */
3310 peer->v_connect = connect;
3311
3312 return 0;
3313}
3314
3315int
3316peer_timers_connect_unset (struct peer *peer)
3317{
3318 if (peer_group_active (peer))
3319 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3320
3321 /* Clear configuration. */
3322 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3323 peer->connect = 0;
3324
3325 /* Set timer setting to default value. */
3326 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3327
3328 return 0;
3329}
David Lamparter6b0655a2014-06-04 06:53:35 +02003330
paul718e3742002-12-13 20:15:29 +00003331int
3332peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3333{
3334 if (peer_group_active (peer))
3335 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3336
3337 if (routeadv > 600)
3338 return BGP_ERR_INVALID_VALUE;
3339
3340 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3341 peer->routeadv = routeadv;
3342 peer->v_routeadv = routeadv;
3343
3344 return 0;
3345}
3346
3347int
3348peer_advertise_interval_unset (struct peer *peer)
3349{
3350 if (peer_group_active (peer))
3351 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3352
3353 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3354 peer->routeadv = 0;
3355
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003356 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003357 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3358 else
3359 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3360
3361 return 0;
3362}
David Lamparter6b0655a2014-06-04 06:53:35 +02003363
paul718e3742002-12-13 20:15:29 +00003364/* neighbor interface */
3365int
paulfd79ac92004-10-13 05:06:08 +00003366peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003367{
3368 if (peer->ifname)
3369 free (peer->ifname);
3370 peer->ifname = strdup (str);
3371
3372 return 0;
3373}
3374
3375int
3376peer_interface_unset (struct peer *peer)
3377{
3378 if (peer->ifname)
3379 free (peer->ifname);
3380 peer->ifname = NULL;
3381
3382 return 0;
3383}
David Lamparter6b0655a2014-06-04 06:53:35 +02003384
paul718e3742002-12-13 20:15:29 +00003385/* Allow-as in. */
3386int
3387peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3388{
3389 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003390 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003391
3392 if (allow_num < 1 || allow_num > 10)
3393 return BGP_ERR_INVALID_VALUE;
3394
3395 if (peer->allowas_in[afi][safi] != allow_num)
3396 {
3397 peer->allowas_in[afi][safi] = allow_num;
3398 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3399 peer_change_action (peer, afi, safi, peer_change_reset_in);
3400 }
3401
3402 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3403 return 0;
3404
3405 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003406 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003407 {
3408 if (peer->allowas_in[afi][safi] != allow_num)
3409 {
3410 peer->allowas_in[afi][safi] = allow_num;
3411 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3412 peer_change_action (peer, afi, safi, peer_change_reset_in);
3413 }
3414
3415 }
3416 return 0;
3417}
3418
3419int
3420peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3421{
3422 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003423 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003424
3425 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3426 {
3427 peer->allowas_in[afi][safi] = 0;
3428 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3429 }
3430
3431 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3432 return 0;
3433
3434 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003435 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003436 {
3437 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3438 {
3439 peer->allowas_in[afi][safi] = 0;
3440 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3441 }
3442 }
3443 return 0;
3444}
David Lamparter6b0655a2014-06-04 06:53:35 +02003445
paul718e3742002-12-13 20:15:29 +00003446int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003447peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003448{
3449 struct bgp *bgp = peer->bgp;
3450 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003451 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003452
3453 if (peer_sort (peer) != BGP_PEER_EBGP
3454 && peer_sort (peer) != BGP_PEER_INTERNAL)
3455 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3456
3457 if (bgp->as == as)
3458 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3459
3460 if (peer_group_active (peer))
3461 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3462
Andrew Certain9d3f9702012-11-07 23:50:07 +00003463 if (peer->as == as)
3464 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3465
paul718e3742002-12-13 20:15:29 +00003466 if (peer->change_local_as == as &&
3467 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003468 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3469 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3470 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003471 return 0;
3472
3473 peer->change_local_as = as;
3474 if (no_prepend)
3475 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3476 else
3477 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3478
Andrew Certain9d3f9702012-11-07 23:50:07 +00003479 if (replace_as)
3480 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3481 else
3482 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3483
paul718e3742002-12-13 20:15:29 +00003484 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3485 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003486 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003487 {
3488 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3489 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3490 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3491 }
paul718e3742002-12-13 20:15:29 +00003492 else
3493 BGP_EVENT_ADD (peer, BGP_Stop);
3494
3495 return 0;
3496 }
3497
3498 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003499 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003500 {
3501 peer->change_local_as = as;
3502 if (no_prepend)
3503 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3504 else
3505 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3506
Andrew Certain9d3f9702012-11-07 23:50:07 +00003507 if (replace_as)
3508 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3509 else
3510 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3511
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003512 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003513 {
3514 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3515 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3516 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3517 }
paul718e3742002-12-13 20:15:29 +00003518 else
3519 BGP_EVENT_ADD (peer, BGP_Stop);
3520 }
3521
3522 return 0;
3523}
3524
3525int
3526peer_local_as_unset (struct peer *peer)
3527{
3528 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003529 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003530
3531 if (peer_group_active (peer))
3532 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3533
3534 if (! peer->change_local_as)
3535 return 0;
3536
3537 peer->change_local_as = 0;
3538 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003539 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003540
3541 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3542 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003543 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003544 {
3545 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3546 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3547 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3548 }
paul718e3742002-12-13 20:15:29 +00003549 else
3550 BGP_EVENT_ADD (peer, BGP_Stop);
3551
3552 return 0;
3553 }
3554
3555 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003556 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003557 {
3558 peer->change_local_as = 0;
3559 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003560 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003561
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003562 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003563 {
3564 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3565 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3566 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3567 }
paul718e3742002-12-13 20:15:29 +00003568 else
3569 BGP_EVENT_ADD (peer, BGP_Stop);
3570 }
3571 return 0;
3572}
David Lamparter6b0655a2014-06-04 06:53:35 +02003573
Paul Jakma0df7c912008-07-21 21:02:49 +00003574/* Set password for authenticating with the peer. */
3575int
3576peer_password_set (struct peer *peer, const char *password)
3577{
3578 struct listnode *nn, *nnode;
3579 int len = password ? strlen(password) : 0;
3580 int ret = BGP_SUCCESS;
3581
3582 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3583 return BGP_ERR_INVALID_VALUE;
3584
3585 if (peer->password && strcmp (peer->password, password) == 0
3586 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3587 return 0;
3588
3589 if (peer->password)
3590 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3591
3592 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3593
3594 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3595 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003596 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3597 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
Paul Jakma0df7c912008-07-21 21:02:49 +00003598 else
3599 BGP_EVENT_ADD (peer, BGP_Stop);
3600
3601 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3602 }
3603
3604 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3605 {
3606 if (peer->password && strcmp (peer->password, password) == 0)
3607 continue;
3608
3609 if (peer->password)
3610 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3611
3612 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3613
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003614 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003615 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3616 else
3617 BGP_EVENT_ADD (peer, BGP_Stop);
3618
3619 if (bgp_md5_set (peer) < 0)
3620 ret = BGP_ERR_TCPSIG_FAILED;
3621 }
3622
3623 return ret;
3624}
3625
3626int
3627peer_password_unset (struct peer *peer)
3628{
3629 struct listnode *nn, *nnode;
3630
3631 if (!peer->password
3632 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3633 return 0;
3634
3635 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3636 {
3637 if (peer_group_active (peer)
3638 && peer->group->conf->password
3639 && strcmp (peer->group->conf->password, peer->password) == 0)
3640 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3641
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003642 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003643 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3644 else
3645 BGP_EVENT_ADD (peer, BGP_Stop);
3646
3647 if (peer->password)
3648 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3649
3650 peer->password = NULL;
3651
3652 bgp_md5_set (peer);
3653
3654 return 0;
3655 }
3656
3657 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3658 peer->password = NULL;
3659
3660 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3661 {
3662 if (!peer->password)
3663 continue;
3664
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003665 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003666 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3667 else
3668 BGP_EVENT_ADD (peer, BGP_Stop);
3669
3670 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3671 peer->password = NULL;
3672
3673 bgp_md5_set (peer);
3674 }
3675
3676 return 0;
3677}
David Lamparter6b0655a2014-06-04 06:53:35 +02003678
paul718e3742002-12-13 20:15:29 +00003679/* Set distribute list to the peer. */
3680int
3681peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003682 const char *name)
paul718e3742002-12-13 20:15:29 +00003683{
3684 struct bgp_filter *filter;
3685 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003686 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003687
3688 if (! peer->afc[afi][safi])
3689 return BGP_ERR_PEER_INACTIVE;
3690
3691 if (direct != FILTER_IN && direct != FILTER_OUT)
3692 return BGP_ERR_INVALID_VALUE;
3693
3694 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3695 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3696
3697 filter = &peer->filter[afi][safi];
3698
3699 if (filter->plist[direct].name)
3700 return BGP_ERR_PEER_FILTER_CONFLICT;
3701
3702 if (filter->dlist[direct].name)
3703 free (filter->dlist[direct].name);
3704 filter->dlist[direct].name = strdup (name);
3705 filter->dlist[direct].alist = access_list_lookup (afi, name);
3706
3707 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3708 return 0;
3709
3710 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003711 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003712 {
3713 filter = &peer->filter[afi][safi];
3714
3715 if (! peer->af_group[afi][safi])
3716 continue;
3717
3718 if (filter->dlist[direct].name)
3719 free (filter->dlist[direct].name);
3720 filter->dlist[direct].name = strdup (name);
3721 filter->dlist[direct].alist = access_list_lookup (afi, name);
3722 }
3723
3724 return 0;
3725}
3726
3727int
3728peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3729{
3730 struct bgp_filter *filter;
3731 struct bgp_filter *gfilter;
3732 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003733 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003734
3735 if (! peer->afc[afi][safi])
3736 return BGP_ERR_PEER_INACTIVE;
3737
3738 if (direct != FILTER_IN && direct != FILTER_OUT)
3739 return BGP_ERR_INVALID_VALUE;
3740
3741 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3742 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3743
3744 filter = &peer->filter[afi][safi];
3745
3746 /* apply peer-group filter */
3747 if (peer->af_group[afi][safi])
3748 {
3749 gfilter = &peer->group->conf->filter[afi][safi];
3750
3751 if (gfilter->dlist[direct].name)
3752 {
3753 if (filter->dlist[direct].name)
3754 free (filter->dlist[direct].name);
3755 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3756 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3757 return 0;
3758 }
3759 }
3760
3761 if (filter->dlist[direct].name)
3762 free (filter->dlist[direct].name);
3763 filter->dlist[direct].name = NULL;
3764 filter->dlist[direct].alist = NULL;
3765
3766 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3767 return 0;
3768
3769 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003770 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003771 {
3772 filter = &peer->filter[afi][safi];
3773
3774 if (! peer->af_group[afi][safi])
3775 continue;
3776
3777 if (filter->dlist[direct].name)
3778 free (filter->dlist[direct].name);
3779 filter->dlist[direct].name = NULL;
3780 filter->dlist[direct].alist = NULL;
3781 }
3782
3783 return 0;
3784}
3785
3786/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003787static void
paul718e3742002-12-13 20:15:29 +00003788peer_distribute_update (struct access_list *access)
3789{
3790 afi_t afi;
3791 safi_t safi;
3792 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003793 struct listnode *mnode, *mnnode;
3794 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003795 struct bgp *bgp;
3796 struct peer *peer;
3797 struct peer_group *group;
3798 struct bgp_filter *filter;
3799
paul1eb8ef22005-04-07 07:30:20 +00003800 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003801 {
paul1eb8ef22005-04-07 07:30:20 +00003802 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003803 {
3804 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3805 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3806 {
3807 filter = &peer->filter[afi][safi];
3808
3809 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3810 {
3811 if (filter->dlist[direct].name)
3812 filter->dlist[direct].alist =
3813 access_list_lookup (afi, filter->dlist[direct].name);
3814 else
3815 filter->dlist[direct].alist = NULL;
3816 }
3817 }
3818 }
paul1eb8ef22005-04-07 07:30:20 +00003819 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003820 {
3821 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3822 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3823 {
3824 filter = &group->conf->filter[afi][safi];
3825
3826 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3827 {
3828 if (filter->dlist[direct].name)
3829 filter->dlist[direct].alist =
3830 access_list_lookup (afi, filter->dlist[direct].name);
3831 else
3832 filter->dlist[direct].alist = NULL;
3833 }
3834 }
3835 }
3836 }
3837}
David Lamparter6b0655a2014-06-04 06:53:35 +02003838
paul718e3742002-12-13 20:15:29 +00003839/* Set prefix list to the peer. */
3840int
3841peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003842 const char *name)
paul718e3742002-12-13 20:15:29 +00003843{
3844 struct bgp_filter *filter;
3845 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003846 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003847
3848 if (! peer->afc[afi][safi])
3849 return BGP_ERR_PEER_INACTIVE;
3850
3851 if (direct != FILTER_IN && direct != FILTER_OUT)
3852 return BGP_ERR_INVALID_VALUE;
3853
3854 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3855 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3856
3857 filter = &peer->filter[afi][safi];
3858
3859 if (filter->dlist[direct].name)
3860 return BGP_ERR_PEER_FILTER_CONFLICT;
3861
3862 if (filter->plist[direct].name)
3863 free (filter->plist[direct].name);
3864 filter->plist[direct].name = strdup (name);
3865 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3866
3867 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3868 return 0;
3869
3870 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003871 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003872 {
3873 filter = &peer->filter[afi][safi];
3874
3875 if (! peer->af_group[afi][safi])
3876 continue;
3877
3878 if (filter->plist[direct].name)
3879 free (filter->plist[direct].name);
3880 filter->plist[direct].name = strdup (name);
3881 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3882 }
3883 return 0;
3884}
3885
3886int
3887peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3888{
3889 struct bgp_filter *filter;
3890 struct bgp_filter *gfilter;
3891 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003892 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003893
3894 if (! peer->afc[afi][safi])
3895 return BGP_ERR_PEER_INACTIVE;
3896
3897 if (direct != FILTER_IN && direct != FILTER_OUT)
3898 return BGP_ERR_INVALID_VALUE;
3899
3900 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3901 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3902
3903 filter = &peer->filter[afi][safi];
3904
3905 /* apply peer-group filter */
3906 if (peer->af_group[afi][safi])
3907 {
3908 gfilter = &peer->group->conf->filter[afi][safi];
3909
3910 if (gfilter->plist[direct].name)
3911 {
3912 if (filter->plist[direct].name)
3913 free (filter->plist[direct].name);
3914 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3915 filter->plist[direct].plist = gfilter->plist[direct].plist;
3916 return 0;
3917 }
3918 }
3919
3920 if (filter->plist[direct].name)
3921 free (filter->plist[direct].name);
3922 filter->plist[direct].name = NULL;
3923 filter->plist[direct].plist = NULL;
3924
3925 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3926 return 0;
3927
3928 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003929 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003930 {
3931 filter = &peer->filter[afi][safi];
3932
3933 if (! peer->af_group[afi][safi])
3934 continue;
3935
3936 if (filter->plist[direct].name)
3937 free (filter->plist[direct].name);
3938 filter->plist[direct].name = NULL;
3939 filter->plist[direct].plist = NULL;
3940 }
3941
3942 return 0;
3943}
3944
3945/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003946static void
paul718e3742002-12-13 20:15:29 +00003947peer_prefix_list_update (struct prefix_list *plist)
3948{
paul1eb8ef22005-04-07 07:30:20 +00003949 struct listnode *mnode, *mnnode;
3950 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003951 struct bgp *bgp;
3952 struct peer *peer;
3953 struct peer_group *group;
3954 struct bgp_filter *filter;
3955 afi_t afi;
3956 safi_t safi;
3957 int direct;
3958
paul1eb8ef22005-04-07 07:30:20 +00003959 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003960 {
paul1eb8ef22005-04-07 07:30:20 +00003961 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003962 {
3963 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3964 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3965 {
3966 filter = &peer->filter[afi][safi];
3967
3968 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3969 {
3970 if (filter->plist[direct].name)
3971 filter->plist[direct].plist =
3972 prefix_list_lookup (afi, filter->plist[direct].name);
3973 else
3974 filter->plist[direct].plist = NULL;
3975 }
3976 }
3977 }
paul1eb8ef22005-04-07 07:30:20 +00003978 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003979 {
3980 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3981 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3982 {
3983 filter = &group->conf->filter[afi][safi];
3984
3985 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3986 {
3987 if (filter->plist[direct].name)
3988 filter->plist[direct].plist =
3989 prefix_list_lookup (afi, filter->plist[direct].name);
3990 else
3991 filter->plist[direct].plist = NULL;
3992 }
3993 }
3994 }
3995 }
3996}
David Lamparter6b0655a2014-06-04 06:53:35 +02003997
paul718e3742002-12-13 20:15:29 +00003998int
3999peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004000 const char *name)
paul718e3742002-12-13 20:15:29 +00004001{
4002 struct bgp_filter *filter;
4003 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004004 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004005
4006 if (! peer->afc[afi][safi])
4007 return BGP_ERR_PEER_INACTIVE;
4008
4009 if (direct != FILTER_IN && direct != FILTER_OUT)
4010 return BGP_ERR_INVALID_VALUE;
4011
4012 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4013 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4014
4015 filter = &peer->filter[afi][safi];
4016
4017 if (filter->aslist[direct].name)
4018 free (filter->aslist[direct].name);
4019 filter->aslist[direct].name = strdup (name);
4020 filter->aslist[direct].aslist = as_list_lookup (name);
4021
4022 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4023 return 0;
4024
4025 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004026 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004027 {
4028 filter = &peer->filter[afi][safi];
4029
4030 if (! peer->af_group[afi][safi])
4031 continue;
4032
4033 if (filter->aslist[direct].name)
4034 free (filter->aslist[direct].name);
4035 filter->aslist[direct].name = strdup (name);
4036 filter->aslist[direct].aslist = as_list_lookup (name);
4037 }
4038 return 0;
4039}
4040
4041int
4042peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4043{
4044 struct bgp_filter *filter;
4045 struct bgp_filter *gfilter;
4046 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004047 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004048
4049 if (! peer->afc[afi][safi])
4050 return BGP_ERR_PEER_INACTIVE;
4051
hassob5f29602005-05-25 21:00:28 +00004052 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004053 return BGP_ERR_INVALID_VALUE;
4054
hassob5f29602005-05-25 21:00:28 +00004055 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004056 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4057
4058 filter = &peer->filter[afi][safi];
4059
4060 /* apply peer-group filter */
4061 if (peer->af_group[afi][safi])
4062 {
4063 gfilter = &peer->group->conf->filter[afi][safi];
4064
4065 if (gfilter->aslist[direct].name)
4066 {
4067 if (filter->aslist[direct].name)
4068 free (filter->aslist[direct].name);
4069 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4070 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4071 return 0;
4072 }
4073 }
4074
4075 if (filter->aslist[direct].name)
4076 free (filter->aslist[direct].name);
4077 filter->aslist[direct].name = NULL;
4078 filter->aslist[direct].aslist = NULL;
4079
4080 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4081 return 0;
4082
4083 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004084 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004085 {
4086 filter = &peer->filter[afi][safi];
4087
4088 if (! peer->af_group[afi][safi])
4089 continue;
4090
4091 if (filter->aslist[direct].name)
4092 free (filter->aslist[direct].name);
4093 filter->aslist[direct].name = NULL;
4094 filter->aslist[direct].aslist = NULL;
4095 }
4096
4097 return 0;
4098}
4099
paul94f2b392005-06-28 12:44:16 +00004100static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004101peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004102{
4103 afi_t afi;
4104 safi_t safi;
4105 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004106 struct listnode *mnode, *mnnode;
4107 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004108 struct bgp *bgp;
4109 struct peer *peer;
4110 struct peer_group *group;
4111 struct bgp_filter *filter;
4112
paul1eb8ef22005-04-07 07:30:20 +00004113 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004114 {
paul1eb8ef22005-04-07 07:30:20 +00004115 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004116 {
4117 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4118 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4119 {
4120 filter = &peer->filter[afi][safi];
4121
4122 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4123 {
4124 if (filter->aslist[direct].name)
4125 filter->aslist[direct].aslist =
4126 as_list_lookup (filter->aslist[direct].name);
4127 else
4128 filter->aslist[direct].aslist = NULL;
4129 }
4130 }
4131 }
paul1eb8ef22005-04-07 07:30:20 +00004132 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004133 {
4134 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4135 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4136 {
4137 filter = &group->conf->filter[afi][safi];
4138
4139 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4140 {
4141 if (filter->aslist[direct].name)
4142 filter->aslist[direct].aslist =
4143 as_list_lookup (filter->aslist[direct].name);
4144 else
4145 filter->aslist[direct].aslist = NULL;
4146 }
4147 }
4148 }
4149 }
4150}
David Lamparter6b0655a2014-06-04 06:53:35 +02004151
paul718e3742002-12-13 20:15:29 +00004152/* Set route-map to the peer. */
4153int
4154peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004155 const char *name)
paul718e3742002-12-13 20:15:29 +00004156{
4157 struct bgp_filter *filter;
4158 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004159 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004160
4161 if (! peer->afc[afi][safi])
4162 return BGP_ERR_PEER_INACTIVE;
4163
paulfee0f4c2004-09-13 05:12:46 +00004164 if (direct != RMAP_IN && direct != RMAP_OUT &&
4165 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004166 return BGP_ERR_INVALID_VALUE;
4167
paulfee0f4c2004-09-13 05:12:46 +00004168 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4169 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004170 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4171
4172 filter = &peer->filter[afi][safi];
4173
4174 if (filter->map[direct].name)
4175 free (filter->map[direct].name);
4176
4177 filter->map[direct].name = strdup (name);
4178 filter->map[direct].map = route_map_lookup_by_name (name);
4179
4180 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4181 return 0;
4182
4183 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004184 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004185 {
4186 filter = &peer->filter[afi][safi];
4187
4188 if (! peer->af_group[afi][safi])
4189 continue;
4190
4191 if (filter->map[direct].name)
4192 free (filter->map[direct].name);
4193 filter->map[direct].name = strdup (name);
4194 filter->map[direct].map = route_map_lookup_by_name (name);
4195 }
4196 return 0;
4197}
4198
4199/* Unset route-map from the peer. */
4200int
4201peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4202{
4203 struct bgp_filter *filter;
4204 struct bgp_filter *gfilter;
4205 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004206 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004207
4208 if (! peer->afc[afi][safi])
4209 return BGP_ERR_PEER_INACTIVE;
4210
hassob5f29602005-05-25 21:00:28 +00004211 if (direct != RMAP_IN && direct != RMAP_OUT &&
4212 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004213 return BGP_ERR_INVALID_VALUE;
4214
hassob5f29602005-05-25 21:00:28 +00004215 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4216 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004217 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4218
4219 filter = &peer->filter[afi][safi];
4220
4221 /* apply peer-group filter */
4222 if (peer->af_group[afi][safi])
4223 {
4224 gfilter = &peer->group->conf->filter[afi][safi];
4225
4226 if (gfilter->map[direct].name)
4227 {
4228 if (filter->map[direct].name)
4229 free (filter->map[direct].name);
4230 filter->map[direct].name = strdup (gfilter->map[direct].name);
4231 filter->map[direct].map = gfilter->map[direct].map;
4232 return 0;
4233 }
4234 }
4235
4236 if (filter->map[direct].name)
4237 free (filter->map[direct].name);
4238 filter->map[direct].name = NULL;
4239 filter->map[direct].map = NULL;
4240
4241 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4242 return 0;
4243
4244 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004245 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004246 {
4247 filter = &peer->filter[afi][safi];
4248
4249 if (! peer->af_group[afi][safi])
4250 continue;
4251
4252 if (filter->map[direct].name)
4253 free (filter->map[direct].name);
4254 filter->map[direct].name = NULL;
4255 filter->map[direct].map = NULL;
4256 }
4257 return 0;
4258}
David Lamparter6b0655a2014-06-04 06:53:35 +02004259
paul718e3742002-12-13 20:15:29 +00004260/* Set unsuppress-map to the peer. */
4261int
paulfd79ac92004-10-13 05:06:08 +00004262peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4263 const char *name)
paul718e3742002-12-13 20:15:29 +00004264{
4265 struct bgp_filter *filter;
4266 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004267 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004268
4269 if (! peer->afc[afi][safi])
4270 return BGP_ERR_PEER_INACTIVE;
4271
4272 if (peer_is_group_member (peer, afi, safi))
4273 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4274
4275 filter = &peer->filter[afi][safi];
4276
4277 if (filter->usmap.name)
4278 free (filter->usmap.name);
4279
4280 filter->usmap.name = strdup (name);
4281 filter->usmap.map = route_map_lookup_by_name (name);
4282
4283 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4284 return 0;
4285
4286 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004287 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004288 {
4289 filter = &peer->filter[afi][safi];
4290
4291 if (! peer->af_group[afi][safi])
4292 continue;
4293
4294 if (filter->usmap.name)
4295 free (filter->usmap.name);
4296 filter->usmap.name = strdup (name);
4297 filter->usmap.map = route_map_lookup_by_name (name);
4298 }
4299 return 0;
4300}
4301
4302/* Unset route-map from the peer. */
4303int
4304peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4305{
4306 struct bgp_filter *filter;
4307 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004308 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004309
4310 if (! peer->afc[afi][safi])
4311 return BGP_ERR_PEER_INACTIVE;
4312
4313 if (peer_is_group_member (peer, afi, safi))
4314 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4315
4316 filter = &peer->filter[afi][safi];
4317
4318 if (filter->usmap.name)
4319 free (filter->usmap.name);
4320 filter->usmap.name = NULL;
4321 filter->usmap.map = NULL;
4322
4323 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4324 return 0;
4325
4326 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004327 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004328 {
4329 filter = &peer->filter[afi][safi];
4330
4331 if (! peer->af_group[afi][safi])
4332 continue;
4333
4334 if (filter->usmap.name)
4335 free (filter->usmap.name);
4336 filter->usmap.name = NULL;
4337 filter->usmap.map = NULL;
4338 }
4339 return 0;
4340}
David Lamparter6b0655a2014-06-04 06:53:35 +02004341
paul718e3742002-12-13 20:15:29 +00004342int
4343peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004344 u_int32_t max, u_char threshold,
4345 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004346{
4347 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004348 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004349
4350 if (! peer->afc[afi][safi])
4351 return BGP_ERR_PEER_INACTIVE;
4352
4353 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4354 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004355 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004356 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004357 if (warning)
4358 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4359 else
4360 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4361
4362 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4363 return 0;
4364
4365 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004366 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004367 {
4368 if (! peer->af_group[afi][safi])
4369 continue;
4370
4371 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4372 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004373 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004374 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004375 if (warning)
4376 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4377 else
4378 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4379 }
4380 return 0;
4381}
4382
4383int
4384peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4385{
4386 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004387 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004388
4389 if (! peer->afc[afi][safi])
4390 return BGP_ERR_PEER_INACTIVE;
4391
4392 /* apply peer-group config */
4393 if (peer->af_group[afi][safi])
4394 {
4395 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4396 PEER_FLAG_MAX_PREFIX))
4397 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4398 else
4399 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4400
4401 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4402 PEER_FLAG_MAX_PREFIX_WARNING))
4403 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4404 else
4405 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4406
4407 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004408 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004409 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004410 return 0;
4411 }
4412
4413 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4414 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4415 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004416 peer->pmax_threshold[afi][safi] = 0;
4417 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004418
4419 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4420 return 0;
4421
4422 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004423 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004424 {
4425 if (! peer->af_group[afi][safi])
4426 continue;
4427
4428 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4429 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4430 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004431 peer->pmax_threshold[afi][safi] = 0;
4432 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004433 }
4434 return 0;
4435}
David Lamparter5f9adb52014-05-19 23:15:02 +02004436
4437static int is_ebgp_multihop_configured (struct peer *peer)
4438{
4439 struct peer_group *group;
4440 struct listnode *node, *nnode;
4441 struct peer *peer1;
4442
4443 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4444 {
4445 group = peer->group;
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004446 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4447 (group->conf->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004448 return 1;
4449
4450 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4451 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004452 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
4453 (peer1->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004454 return 1;
4455 }
4456 }
4457 else
4458 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004459 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4460 (peer->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004461 return 1;
4462 }
4463 return 0;
4464}
4465
Nick Hilliardfa411a22011-03-23 15:33:17 +00004466/* Set # of hops between us and BGP peer. */
4467int
4468peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4469{
4470 struct peer_group *group;
4471 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004472 int ret;
4473
4474 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4475
Nick Hilliardfa411a22011-03-23 15:33:17 +00004476 /* We cannot configure ttl-security hops when ebgp-multihop is already
4477 set. For non peer-groups, the check is simple. For peer-groups, it's
4478 slightly messy, because we need to check both the peer-group structure
4479 and all peer-group members for any trace of ebgp-multihop configuration
4480 before actually applying the ttl-security rules. Cisco really made a
4481 mess of this configuration parameter, and OpenBGPD got it right.
4482 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004483
David Lamparter5f9adb52014-05-19 23:15:02 +02004484 if (peer->gtsm_hops == 0)
4485 {
4486 if (is_ebgp_multihop_configured (peer))
4487 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004488
David Lamparter5f9adb52014-05-19 23:15:02 +02004489 /* specify MAXTTL on outgoing packets */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004490 /* Routine handles iBGP peers correctly */
David Lamparter5f9adb52014-05-19 23:15:02 +02004491 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4492 if (ret != 0)
4493 return ret;
4494 }
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004495
Nick Hilliardfa411a22011-03-23 15:33:17 +00004496 peer->gtsm_hops = gtsm_hops;
4497
Nick Hilliardfa411a22011-03-23 15:33:17 +00004498 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4499 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004500 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004501 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4502 }
4503 else
4504 {
4505 group = peer->group;
4506 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4507 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004508 peer->gtsm_hops = group->conf->gtsm_hops;
4509
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004510 /* Change setting of existing peer
4511 * established then change value (may break connectivity)
4512 * not established yet (teardown session and restart)
4513 * no session then do nothing (will get handled by next connection)
4514 */
4515 if (peer->status == Established)
4516 {
4517 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4518 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4519 MAXTTL + 1 - peer->gtsm_hops);
4520 }
4521 else if (peer->status < Established)
4522 {
4523 if (BGP_DEBUG (events, EVENTS))
4524 zlog_debug ("%s Min-ttl changed", peer->host);
4525 BGP_EVENT_ADD (peer, BGP_Stop);
4526 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004527 }
4528 }
4529
4530 return 0;
4531}
4532
4533int
4534peer_ttl_security_hops_unset (struct peer *peer)
4535{
4536 struct peer_group *group;
4537 struct listnode *node, *nnode;
4538 struct peer *opeer;
4539
4540 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4541
Nick Hilliardfa411a22011-03-23 15:33:17 +00004542 /* if a peer-group member, then reset to peer-group default rather than 0 */
4543 if (peer_group_active (peer))
4544 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4545 else
4546 peer->gtsm_hops = 0;
4547
4548 opeer = peer;
4549 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4550 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004551 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004552 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4553 }
4554 else
4555 {
4556 group = peer->group;
4557 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4558 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004559 peer->gtsm_hops = 0;
4560
4561 if (peer->fd >= 0)
4562 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4563 }
4564 }
4565
4566 return peer_ebgp_multihop_unset (opeer);
4567}
David Lamparter6b0655a2014-06-04 06:53:35 +02004568
paul718e3742002-12-13 20:15:29 +00004569int
4570peer_clear (struct peer *peer)
4571{
4572 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4573 {
hasso0a486e52005-02-01 20:57:17 +00004574 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4575 {
4576 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4577 if (peer->t_pmax_restart)
4578 {
4579 BGP_TIMER_OFF (peer->t_pmax_restart);
4580 if (BGP_DEBUG (events, EVENTS))
4581 zlog_debug ("%s Maximum-prefix restart timer canceled",
4582 peer->host);
4583 }
4584 BGP_EVENT_ADD (peer, BGP_Start);
4585 return 0;
4586 }
4587
paul718e3742002-12-13 20:15:29 +00004588 peer->v_start = BGP_INIT_START_TIMER;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00004589 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00004590 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4591 BGP_NOTIFY_CEASE_ADMIN_RESET);
4592 else
4593 BGP_EVENT_ADD (peer, BGP_Stop);
4594 }
4595 return 0;
4596}
4597
4598int
4599peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4600 enum bgp_clear_type stype)
4601{
4602 if (peer->status != Established)
4603 return 0;
4604
4605 if (! peer->afc[afi][safi])
4606 return BGP_ERR_AF_UNCONFIGURED;
4607
paulfee0f4c2004-09-13 05:12:46 +00004608 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4609 {
4610 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4611 return 0;
4612 bgp_check_local_routes_rsclient (peer, afi, safi);
4613 bgp_soft_reconfig_rsclient (peer, afi, safi);
4614 }
4615
paul718e3742002-12-13 20:15:29 +00004616 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4617 bgp_announce_route (peer, afi, safi);
4618
4619 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4620 {
4621 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4622 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4623 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4624 {
4625 struct bgp_filter *filter = &peer->filter[afi][safi];
4626 u_char prefix_type;
4627
4628 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4629 prefix_type = ORF_TYPE_PREFIX;
4630 else
4631 prefix_type = ORF_TYPE_PREFIX_OLD;
4632
4633 if (filter->plist[FILTER_IN].plist)
4634 {
4635 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4636 bgp_route_refresh_send (peer, afi, safi,
4637 prefix_type, REFRESH_DEFER, 1);
4638 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4639 REFRESH_IMMEDIATE, 0);
4640 }
4641 else
4642 {
4643 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4644 bgp_route_refresh_send (peer, afi, safi,
4645 prefix_type, REFRESH_IMMEDIATE, 1);
4646 else
4647 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4648 }
4649 return 0;
4650 }
4651 }
4652
4653 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4654 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4655 {
4656 /* If neighbor has soft reconfiguration inbound flag.
4657 Use Adj-RIB-In database. */
4658 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4659 bgp_soft_reconfig_in (peer, afi, safi);
4660 else
4661 {
4662 /* If neighbor has route refresh capability, send route refresh
4663 message to the peer. */
4664 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4665 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4666 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4667 else
4668 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4669 }
4670 }
4671 return 0;
4672}
David Lamparter6b0655a2014-06-04 06:53:35 +02004673
paulfd79ac92004-10-13 05:06:08 +00004674/* Display peer uptime.*/
4675/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004676char *
4677peer_uptime (time_t uptime2, char *buf, size_t len)
4678{
4679 time_t uptime1;
4680 struct tm *tm;
4681
4682 /* Check buffer length. */
4683 if (len < BGP_UPTIME_LEN)
4684 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004685 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004686 /* XXX: should return status instead of buf... */
4687 snprintf (buf, len, "<error> ");
4688 return buf;
paul718e3742002-12-13 20:15:29 +00004689 }
4690
4691 /* If there is no connection has been done before print `never'. */
4692 if (uptime2 == 0)
4693 {
4694 snprintf (buf, len, "never ");
4695 return buf;
4696 }
4697
4698 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004699 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004700 uptime1 -= uptime2;
4701 tm = gmtime (&uptime1);
4702
4703 /* Making formatted timer strings. */
4704#define ONE_DAY_SECOND 60*60*24
4705#define ONE_WEEK_SECOND 60*60*24*7
4706
4707 if (uptime1 < ONE_DAY_SECOND)
4708 snprintf (buf, len, "%02d:%02d:%02d",
4709 tm->tm_hour, tm->tm_min, tm->tm_sec);
4710 else if (uptime1 < ONE_WEEK_SECOND)
4711 snprintf (buf, len, "%dd%02dh%02dm",
4712 tm->tm_yday, tm->tm_hour, tm->tm_min);
4713 else
4714 snprintf (buf, len, "%02dw%dd%02dh",
4715 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4716 return buf;
4717}
David Lamparter6b0655a2014-06-04 06:53:35 +02004718
paul94f2b392005-06-28 12:44:16 +00004719static void
paul718e3742002-12-13 20:15:29 +00004720bgp_config_write_filter (struct vty *vty, struct peer *peer,
4721 afi_t afi, safi_t safi)
4722{
4723 struct bgp_filter *filter;
4724 struct bgp_filter *gfilter = NULL;
4725 char *addr;
4726 int in = FILTER_IN;
4727 int out = FILTER_OUT;
4728
4729 addr = peer->host;
4730 filter = &peer->filter[afi][safi];
4731 if (peer->af_group[afi][safi])
4732 gfilter = &peer->group->conf->filter[afi][safi];
4733
4734 /* distribute-list. */
4735 if (filter->dlist[in].name)
4736 if (! gfilter || ! gfilter->dlist[in].name
4737 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4738 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4739 filter->dlist[in].name, VTY_NEWLINE);
4740 if (filter->dlist[out].name && ! gfilter)
4741 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4742 filter->dlist[out].name, VTY_NEWLINE);
4743
4744 /* prefix-list. */
4745 if (filter->plist[in].name)
4746 if (! gfilter || ! gfilter->plist[in].name
4747 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4748 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4749 filter->plist[in].name, VTY_NEWLINE);
4750 if (filter->plist[out].name && ! gfilter)
4751 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4752 filter->plist[out].name, VTY_NEWLINE);
4753
4754 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004755 if (filter->map[RMAP_IN].name)
4756 if (! gfilter || ! gfilter->map[RMAP_IN].name
4757 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004758 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004759 filter->map[RMAP_IN].name, VTY_NEWLINE);
4760 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004761 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004762 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4763 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4764 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4765 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4766 if (filter->map[RMAP_EXPORT].name)
4767 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4768 || strcmp (filter->map[RMAP_EXPORT].name,
4769 gfilter->map[RMAP_EXPORT].name) != 0)
4770 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4771 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004772
4773 /* unsuppress-map */
4774 if (filter->usmap.name && ! gfilter)
4775 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4776 filter->usmap.name, VTY_NEWLINE);
4777
4778 /* filter-list. */
4779 if (filter->aslist[in].name)
4780 if (! gfilter || ! gfilter->aslist[in].name
4781 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4782 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4783 filter->aslist[in].name, VTY_NEWLINE);
4784 if (filter->aslist[out].name && ! gfilter)
4785 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4786 filter->aslist[out].name, VTY_NEWLINE);
4787}
4788
4789/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004790static void
paul718e3742002-12-13 20:15:29 +00004791bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4792 struct peer *peer, afi_t afi, safi_t safi)
4793{
paul718e3742002-12-13 20:15:29 +00004794 struct peer *g_peer = NULL;
4795 char buf[SU_ADDRSTRLEN];
4796 char *addr;
4797
paul718e3742002-12-13 20:15:29 +00004798 addr = peer->host;
4799 if (peer_group_active (peer))
4800 g_peer = peer->group->conf;
4801
4802 /************************************
4803 ****** Global to the neighbor ******
4804 ************************************/
4805 if (afi == AFI_IP && safi == SAFI_UNICAST)
4806 {
4807 /* remote-as. */
4808 if (! peer_group_active (peer))
4809 {
4810 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4811 vty_out (vty, " neighbor %s peer-group%s", addr,
4812 VTY_NEWLINE);
4813 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004814 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004815 VTY_NEWLINE);
4816 }
4817 else
4818 {
4819 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004820 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004821 VTY_NEWLINE);
4822 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4823 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4824 peer->group->name, VTY_NEWLINE);
4825 }
4826
4827 /* local-as. */
4828 if (peer->change_local_as)
4829 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00004830 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004831 peer->change_local_as,
4832 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00004833 " no-prepend" : "",
4834 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
4835 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004836
4837 /* Description. */
4838 if (peer->desc)
4839 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4840 VTY_NEWLINE);
4841
4842 /* Shutdown. */
4843 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4844 if (! peer_group_active (peer) ||
4845 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4846 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4847
Paul Jakma0df7c912008-07-21 21:02:49 +00004848 /* Password. */
4849 if (peer->password)
4850 if (!peer_group_active (peer)
4851 || ! g_peer->password
4852 || strcmp (peer->password, g_peer->password) != 0)
4853 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4854 VTY_NEWLINE);
4855
paul718e3742002-12-13 20:15:29 +00004856 /* BGP port. */
4857 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004858 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004859 VTY_NEWLINE);
4860
4861 /* Local interface name. */
4862 if (peer->ifname)
4863 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4864 VTY_NEWLINE);
4865
4866 /* Passive. */
4867 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4868 if (! peer_group_active (peer) ||
4869 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4870 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4871
4872 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004873 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00004874 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00004875 if (! peer_group_active (peer) ||
4876 g_peer->ttl != peer->ttl)
4877 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4878 VTY_NEWLINE);
4879
Nick Hilliardfa411a22011-03-23 15:33:17 +00004880 /* ttl-security hops */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004881 if (peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004882 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004883 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00004884 peer->gtsm_hops, VTY_NEWLINE);
4885
hasso6ffd2072005-02-02 14:50:11 +00004886 /* disable-connected-check. */
4887 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004888 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004889 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4890 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004891
4892 /* Update-source. */
4893 if (peer->update_if)
4894 if (! peer_group_active (peer) || ! g_peer->update_if
4895 || strcmp (g_peer->update_if, peer->update_if) != 0)
4896 vty_out (vty, " neighbor %s update-source %s%s", addr,
4897 peer->update_if, VTY_NEWLINE);
4898 if (peer->update_source)
4899 if (! peer_group_active (peer) || ! g_peer->update_source
4900 || sockunion_cmp (g_peer->update_source,
4901 peer->update_source) != 0)
4902 vty_out (vty, " neighbor %s update-source %s%s", addr,
4903 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4904 VTY_NEWLINE);
4905
paul718e3742002-12-13 20:15:29 +00004906 /* advertisement-interval */
4907 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4908 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4909 addr, peer->v_routeadv, VTY_NEWLINE);
4910
4911 /* timers. */
4912 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4913 && ! peer_group_active (peer))
4914 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4915 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4916
4917 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4918 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4919 peer->connect, VTY_NEWLINE);
4920
4921 /* Default weight. */
4922 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4923 if (! peer_group_active (peer) ||
4924 g_peer->weight != peer->weight)
4925 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4926 VTY_NEWLINE);
4927
paul718e3742002-12-13 20:15:29 +00004928 /* Dynamic capability. */
4929 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4930 if (! peer_group_active (peer) ||
4931 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4932 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4933 VTY_NEWLINE);
4934
4935 /* dont capability negotiation. */
4936 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4937 if (! peer_group_active (peer) ||
4938 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4939 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4940 VTY_NEWLINE);
4941
4942 /* override capability negotiation. */
4943 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4944 if (! peer_group_active (peer) ||
4945 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4946 vty_out (vty, " neighbor %s override-capability%s", addr,
4947 VTY_NEWLINE);
4948
4949 /* strict capability negotiation. */
4950 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4951 if (! peer_group_active (peer) ||
4952 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4953 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4954 VTY_NEWLINE);
4955
Christian Franke15c71342012-11-19 11:17:31 +00004956 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
paul718e3742002-12-13 20:15:29 +00004957 {
4958 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4959 {
4960 if (peer->afc[AFI_IP][SAFI_UNICAST])
4961 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4962 }
4963 else
4964 {
4965 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4966 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4967 }
4968 }
4969 }
4970
4971
4972 /************************************
4973 ****** Per AF to the neighbor ******
4974 ************************************/
4975
4976 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4977 {
4978 if (peer->af_group[afi][safi])
4979 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4980 peer->group->name, VTY_NEWLINE);
4981 else
4982 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4983 }
4984
4985 /* ORF capability. */
4986 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4987 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4988 if (! peer->af_group[afi][safi])
4989 {
4990 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4991
4992 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4993 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4994 vty_out (vty, " both");
4995 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4996 vty_out (vty, " send");
4997 else
4998 vty_out (vty, " receive");
4999 vty_out (vty, "%s", VTY_NEWLINE);
5000 }
5001
5002 /* Route reflector client. */
5003 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
5004 && ! peer->af_group[afi][safi])
5005 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
5006 VTY_NEWLINE);
5007
5008 /* Nexthop self. */
5009 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
5010 && ! peer->af_group[afi][safi])
Timo Teräs9e7a53c2014-04-24 10:22:37 +03005011 vty_out (vty, " neighbor %s next-hop-self%s%s", addr,
5012 peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ?
5013 " all" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005014
5015 /* Remove private AS. */
5016 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
5017 && ! peer->af_group[afi][safi])
5018 vty_out (vty, " neighbor %s remove-private-AS%s",
5019 addr, VTY_NEWLINE);
5020
5021 /* send-community print. */
5022 if (! peer->af_group[afi][safi])
5023 {
5024 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5025 {
5026 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5027 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5028 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
5029 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5030 vty_out (vty, " neighbor %s send-community extended%s",
5031 addr, VTY_NEWLINE);
5032 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5033 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
5034 }
5035 else
5036 {
5037 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5038 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5039 vty_out (vty, " no neighbor %s send-community both%s",
5040 addr, VTY_NEWLINE);
5041 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5042 vty_out (vty, " no neighbor %s send-community extended%s",
5043 addr, VTY_NEWLINE);
5044 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5045 vty_out (vty, " no neighbor %s send-community%s",
5046 addr, VTY_NEWLINE);
5047 }
5048 }
5049
5050 /* Default information */
5051 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5052 && ! peer->af_group[afi][safi])
5053 {
5054 vty_out (vty, " neighbor %s default-originate", addr);
5055 if (peer->default_rmap[afi][safi].name)
5056 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5057 vty_out (vty, "%s", VTY_NEWLINE);
5058 }
5059
5060 /* Soft reconfiguration inbound. */
5061 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5062 if (! peer->af_group[afi][safi] ||
5063 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5064 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5065 VTY_NEWLINE);
5066
5067 /* maximum-prefix. */
5068 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5069 if (! peer->af_group[afi][safi]
5070 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005071 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005072 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5073 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005074 {
hasso0a486e52005-02-01 20:57:17 +00005075 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5076 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5077 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5078 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5079 vty_out (vty, " warning-only");
5080 if (peer->pmax_restart[afi][safi])
5081 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5082 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005083 }
paul718e3742002-12-13 20:15:29 +00005084
5085 /* Route server client. */
5086 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5087 && ! peer->af_group[afi][safi])
5088 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5089
Dylan Hall3cf12882011-10-27 15:28:17 +04005090 /* Nexthop-local unchanged. */
5091 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5092 && ! peer->af_group[afi][safi])
5093 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5094
paul718e3742002-12-13 20:15:29 +00005095 /* Allow AS in. */
5096 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5097 if (! peer_group_active (peer)
5098 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5099 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5100 {
5101 if (peer->allowas_in[afi][safi] == 3)
5102 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5103 else
5104 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5105 peer->allowas_in[afi][safi], VTY_NEWLINE);
5106 }
5107
5108 /* Filter. */
5109 bgp_config_write_filter (vty, peer, afi, safi);
5110
5111 /* atribute-unchanged. */
5112 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5113 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5114 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5115 && ! peer->af_group[afi][safi])
5116 {
5117 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5118 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5119 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5120 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5121 else
5122 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5123 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5124 " as-path" : "",
5125 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5126 " next-hop" : "",
5127 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5128 " med" : "", VTY_NEWLINE);
5129 }
5130}
5131
5132/* Display "address-family" configuration header. */
5133void
5134bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5135 int *write)
5136{
5137 if (*write)
5138 return;
5139
5140 if (afi == AFI_IP && safi == SAFI_UNICAST)
5141 return;
5142
5143 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5144
5145 if (afi == AFI_IP)
5146 {
5147 if (safi == SAFI_MULTICAST)
5148 vty_out (vty, "ipv4 multicast");
5149 else if (safi == SAFI_MPLS_VPN)
5150 vty_out (vty, "vpnv4 unicast");
5151 }
5152 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005153 {
5154 vty_out (vty, "ipv6");
5155
5156 if (safi == SAFI_MULTICAST)
5157 vty_out (vty, " multicast");
5158 }
paul718e3742002-12-13 20:15:29 +00005159
5160 vty_out (vty, "%s", VTY_NEWLINE);
5161
5162 *write = 1;
5163}
5164
5165/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005166static int
paul718e3742002-12-13 20:15:29 +00005167bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5168 safi_t safi)
5169{
5170 int write = 0;
5171 struct peer *peer;
5172 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005173 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005174
5175 bgp_config_write_network (vty, bgp, afi, safi, &write);
5176
5177 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5178
paul1eb8ef22005-04-07 07:30:20 +00005179 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005180 {
5181 if (group->conf->afc[afi][safi])
5182 {
5183 bgp_config_write_family_header (vty, afi, safi, &write);
5184 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5185 }
5186 }
paul1eb8ef22005-04-07 07:30:20 +00005187 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005188 {
5189 if (peer->afc[afi][safi])
5190 {
5191 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5192 {
5193 bgp_config_write_family_header (vty, afi, safi, &write);
5194 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5195 }
5196 }
5197 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005198
5199 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5200
paul718e3742002-12-13 20:15:29 +00005201 if (write)
5202 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5203
5204 return write;
5205}
5206
5207int
5208bgp_config_write (struct vty *vty)
5209{
5210 int write = 0;
5211 struct bgp *bgp;
5212 struct peer_group *group;
5213 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005214 struct listnode *node, *nnode;
5215 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005216
5217 /* BGP Multiple instance. */
5218 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5219 {
5220 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5221 write++;
5222 }
5223
5224 /* BGP Config type. */
5225 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5226 {
5227 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5228 write++;
5229 }
5230
5231 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005232 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005233 {
5234 if (write)
5235 vty_out (vty, "!%s", VTY_NEWLINE);
5236
5237 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005238 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005239
5240 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5241 {
5242 if (bgp->name)
5243 vty_out (vty, " view %s", bgp->name);
5244 }
5245 vty_out (vty, "%s", VTY_NEWLINE);
5246
5247 /* No Synchronization */
5248 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5249 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5250
5251 /* BGP fast-external-failover. */
5252 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5253 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5254
5255 /* BGP router ID. */
5256 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5257 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5258 VTY_NEWLINE);
5259
paul848973c2003-08-13 00:32:49 +00005260 /* BGP log-neighbor-changes. */
5261 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5262 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
5263
paul718e3742002-12-13 20:15:29 +00005264 /* BGP configuration. */
5265 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5266 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5267
5268 /* BGP default ipv4-unicast. */
5269 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5270 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5271
5272 /* BGP default local-preference. */
5273 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5274 vty_out (vty, " bgp default local-preference %d%s",
5275 bgp->default_local_pref, VTY_NEWLINE);
5276
5277 /* BGP client-to-client reflection. */
5278 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5279 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5280
5281 /* BGP cluster ID. */
5282 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5283 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5284 VTY_NEWLINE);
5285
hassoe0701b72004-05-20 09:19:34 +00005286 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005287 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005288 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5289 VTY_NEWLINE);
5290
5291 /* Confederation peer */
5292 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005293 {
hassoe0701b72004-05-20 09:19:34 +00005294 int i;
paul718e3742002-12-13 20:15:29 +00005295
hassoe0701b72004-05-20 09:19:34 +00005296 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005297
hassoe0701b72004-05-20 09:19:34 +00005298 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005299 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005300
hassoe0701b72004-05-20 09:19:34 +00005301 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005302 }
5303
5304 /* BGP enforce-first-as. */
5305 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5306 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5307
5308 /* BGP deterministic-med. */
5309 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5310 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005311
5312 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005313 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5314 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5315 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005316 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5317 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5318
paul718e3742002-12-13 20:15:29 +00005319 /* BGP bestpath method. */
5320 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5321 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005322 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5323 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
Pradosh Mohapatra2fdd4552013-09-07 07:02:36 +00005324 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
5325 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
5326 }
paul718e3742002-12-13 20:15:29 +00005327 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5328 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5329 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5330 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5331 {
5332 vty_out (vty, " bgp bestpath med");
5333 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5334 vty_out (vty, " confed");
5335 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5336 vty_out (vty, " missing-as-worst");
5337 vty_out (vty, "%s", VTY_NEWLINE);
5338 }
5339
5340 /* BGP network import check. */
5341 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5342 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5343
5344 /* BGP scan interval. */
5345 bgp_config_write_scan_time (vty);
5346
5347 /* BGP flag dampening. */
5348 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5349 BGP_CONFIG_DAMPENING))
5350 bgp_config_write_damp (vty);
5351
5352 /* BGP static route configuration. */
5353 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5354
5355 /* BGP redistribute configuration. */
5356 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5357
5358 /* BGP timers configuration. */
5359 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5360 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5361 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5362 bgp->default_holdtime, VTY_NEWLINE);
5363
5364 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005365 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005366 {
5367 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5368 }
5369
5370 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005371 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005372 {
5373 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5374 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5375 }
5376
Josh Bailey165b5ff2011-07-20 20:43:22 -07005377 /* maximum-paths */
5378 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5379
paul718e3742002-12-13 20:15:29 +00005380 /* Distance configuration. */
5381 bgp_config_write_distance (vty, bgp);
5382
5383 /* No auto-summary */
5384 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5385 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5386
5387 /* IPv4 multicast configuration. */
5388 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5389
5390 /* IPv4 VPN configuration. */
5391 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5392
5393 /* IPv6 unicast configuration. */
5394 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5395
Paul Jakma37a217a2007-04-10 19:20:29 +00005396 /* IPv6 multicast configuration. */
5397 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5398
paul718e3742002-12-13 20:15:29 +00005399 write++;
5400 }
5401 return write;
5402}
5403
5404void
paul94f2b392005-06-28 12:44:16 +00005405bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005406{
5407 memset (&bgp_master, 0, sizeof (struct bgp_master));
5408
5409 bm = &bgp_master;
5410 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005411 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005412 bm->port = BGP_PORT_DEFAULT;
5413 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005414 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005415}
paul200df112005-06-01 11:17:05 +00005416
David Lamparter6b0655a2014-06-04 06:53:35 +02005417
paul718e3742002-12-13 20:15:29 +00005418void
paul94f2b392005-06-28 12:44:16 +00005419bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005420{
paul718e3742002-12-13 20:15:29 +00005421 /* BGP VTY commands installation. */
5422 bgp_vty_init ();
5423
paul718e3742002-12-13 20:15:29 +00005424 /* Init zebra. */
5425 bgp_zebra_init ();
5426
5427 /* BGP inits. */
5428 bgp_attr_init ();
5429 bgp_debug_init ();
5430 bgp_dump_init ();
5431 bgp_route_init ();
5432 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005433 bgp_address_init ();
paul718e3742002-12-13 20:15:29 +00005434 bgp_scan_init ();
5435 bgp_mplsvpn_init ();
5436
5437 /* Access list initialize. */
5438 access_list_init ();
5439 access_list_add_hook (peer_distribute_update);
5440 access_list_delete_hook (peer_distribute_update);
5441
5442 /* Filter list initialize. */
5443 bgp_filter_init ();
5444 as_list_add_hook (peer_aslist_update);
5445 as_list_delete_hook (peer_aslist_update);
5446
5447 /* Prefix list initialize.*/
5448 prefix_list_init ();
5449 prefix_list_add_hook (peer_prefix_list_update);
5450 prefix_list_delete_hook (peer_prefix_list_update);
5451
5452 /* Community list initialize. */
5453 bgp_clist = community_list_init ();
5454
5455#ifdef HAVE_SNMP
5456 bgp_snmp_init ();
5457#endif /* HAVE_SNMP */
5458}
paul545acaf2004-04-20 15:13:15 +00005459
5460void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005461bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005462{
paul545acaf2004-04-20 15:13:15 +00005463 struct bgp *bgp;
5464 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005465 struct listnode *node, *nnode;
5466 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005467
paul1eb8ef22005-04-07 07:30:20 +00005468 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5469 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005470 if (peer->status == Established)
5471 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5472 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005473
paul545acaf2004-04-20 15:13:15 +00005474 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005475
paule210cf92005-06-15 19:15:35 +00005476 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005477 {
5478 work_queue_free (bm->process_main_queue);
5479 bm->process_main_queue = NULL;
5480 }
paule210cf92005-06-15 19:15:35 +00005481 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005482 {
5483 work_queue_free (bm->process_rsclient_queue);
5484 bm->process_rsclient_queue = NULL;
5485 }
paul545acaf2004-04-20 15:13:15 +00005486}