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