blob: c94c381ff46b725e16af5478841f71fb6cf1f585 [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;
paul718e3742002-12-13 20:15:29 +00001977
1978 bgp->as = *as;
1979
1980 if (name)
1981 bgp->name = strdup (name);
1982
Donald Sharp774914f2015-10-14 08:50:39 -04001983 THREAD_TIMER_ON (bm->master, bgp->t_startup, bgp_startup_timer_expire,
Vipin Kumardd49eb12014-09-30 14:36:38 -07001984 bgp, bgp->restart_time);
1985
paul718e3742002-12-13 20:15:29 +00001986 return bgp;
1987}
1988
1989/* Return first entry of BGP. */
1990struct bgp *
paul94f2b392005-06-28 12:44:16 +00001991bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001992{
Lou Berger056f3762013-04-10 12:30:04 -07001993 if (bm && bm->bgp && bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001994 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001995 return NULL;
1996}
1997
1998/* Lookup BGP entry. */
1999struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002000bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00002001{
2002 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002003 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002004
paul1eb8ef22005-04-07 07:30:20 +00002005 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002006 if (bgp->as == as
2007 && ((bgp->name == NULL && name == NULL)
2008 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
2009 return bgp;
2010 return NULL;
2011}
2012
2013/* Lookup BGP structure by view name. */
2014struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002015bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002016{
2017 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002018 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002019
paul1eb8ef22005-04-07 07:30:20 +00002020 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002021 if ((bgp->name == NULL && name == NULL)
2022 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2023 return bgp;
2024 return NULL;
2025}
2026
2027/* Called from VTY commands. */
2028int
paulfd79ac92004-10-13 05:06:08 +00002029bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002030{
2031 struct bgp *bgp;
2032
2033 /* Multiple instance check. */
2034 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2035 {
2036 if (name)
2037 bgp = bgp_lookup_by_name (name);
2038 else
2039 bgp = bgp_get_default ();
2040
2041 /* Already exists. */
2042 if (bgp)
2043 {
2044 if (bgp->as != *as)
2045 {
2046 *as = bgp->as;
2047 return BGP_ERR_INSTANCE_MISMATCH;
2048 }
2049 *bgp_val = bgp;
2050 return 0;
2051 }
2052 }
2053 else
2054 {
2055 /* BGP instance name can not be specified for single instance. */
2056 if (name)
2057 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2058
2059 /* Get default BGP structure if exists. */
2060 bgp = bgp_get_default ();
2061
2062 if (bgp)
2063 {
2064 if (bgp->as != *as)
2065 {
2066 *as = bgp->as;
2067 return BGP_ERR_AS_MISMATCH;
2068 }
2069 *bgp_val = bgp;
2070 return 0;
2071 }
2072 }
2073
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002074 bgp = bgp_create (as, name);
2075 bgp_router_id_set(bgp, &router_id_zebra);
2076 *bgp_val = bgp;
2077
Paul Jakmaad12dde2012-06-13 22:50:07 +01002078 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002079 if (list_isempty(bm->bgp)
2080 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002081 {
2082 if (bgp_socket (bm->port, bm->address) < 0)
2083 return BGP_ERR_INVALID_VALUE;
2084 }
2085
paul718e3742002-12-13 20:15:29 +00002086 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002087
2088 return 0;
2089}
2090
2091/* Delete BGP instance. */
2092int
2093bgp_delete (struct bgp *bgp)
2094{
2095 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002096 struct peer_group *group;
Denil Vira57cd5e72015-08-10 12:46:14 -07002097 struct listnode *node, *pnode;
2098 struct listnode *next, *pnext;
paul718e3742002-12-13 20:15:29 +00002099 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002100 int i;
2101
David Lampartercffe7802014-12-07 03:27:13 +01002102 THREAD_OFF (bgp->t_startup);
2103
paul718e3742002-12-13 20:15:29 +00002104 /* Delete static route. */
2105 bgp_static_delete (bgp);
2106
2107 /* Unset redistribution. */
2108 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2109 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2110 if (i != ZEBRA_ROUTE_BGP)
2111 bgp_redistribute_unset (bgp, afi, i);
2112
paul1eb8ef22005-04-07 07:30:20 +00002113 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002114 {
2115 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2116 {
2117 /* Send notify to remote peer. */
2118 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2119 }
2120
2121 peer_delete (peer);
2122 }
paul718e3742002-12-13 20:15:29 +00002123
Chris Caputo228da422009-07-18 05:44:03 +00002124 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002125 {
Denil Vira57cd5e72015-08-10 12:46:14 -07002126 for (ALL_LIST_ELEMENTS (group->peer, pnode, pnext, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002127 {
2128 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2129 {
2130 /* Send notify to remote peer. */
2131 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2132 }
2133 }
2134 peer_group_delete (group);
2135 }
Chris Caputo228da422009-07-18 05:44:03 +00002136
2137 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002138
2139 if (bgp->peer_self) {
2140 peer_delete(bgp->peer_self);
2141 bgp->peer_self = NULL;
2142 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002143
2144 /* Remove visibility via the master list - there may however still be
2145 * routes to be processed still referencing the struct bgp.
2146 */
2147 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002148 if (list_isempty(bm->bgp))
2149 bgp_close ();
2150
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002151 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002152
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002153 return 0;
2154}
2155
2156static void bgp_free (struct bgp *);
2157
2158void
2159bgp_lock (struct bgp *bgp)
2160{
2161 ++bgp->lock;
2162}
2163
2164void
2165bgp_unlock(struct bgp *bgp)
2166{
Chris Caputo228da422009-07-18 05:44:03 +00002167 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002168 if (--bgp->lock == 0)
2169 bgp_free (bgp);
2170}
2171
2172static void
2173bgp_free (struct bgp *bgp)
2174{
2175 afi_t afi;
2176 safi_t safi;
2177
2178 list_delete (bgp->group);
2179 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002180 list_delete (bgp->rsclient);
2181
paul718e3742002-12-13 20:15:29 +00002182 if (bgp->name)
2183 free (bgp->name);
2184
2185 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2186 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2187 {
2188 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002189 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002190 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002191 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002192 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002193 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002194 }
2195 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002196}
David Lamparter6b0655a2014-06-04 06:53:35 +02002197
paul718e3742002-12-13 20:15:29 +00002198struct peer *
2199peer_lookup (struct bgp *bgp, union sockunion *su)
2200{
2201 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002202 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002203
Steve Hillfc4dc592009-07-28 17:54:35 +01002204 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002205 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002206 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2207 if (sockunion_same (&peer->su, su)
2208 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2209 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002210 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002211 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002212 {
2213 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002214
Paul Jakma2158ad22009-07-28 18:10:55 +01002215 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2216 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2217 if (sockunion_same (&peer->su, su)
2218 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2219 return peer;
paul718e3742002-12-13 20:15:29 +00002220 }
2221 return NULL;
2222}
2223
2224struct peer *
2225peer_lookup_with_open (union sockunion *su, as_t remote_as,
2226 struct in_addr *remote_id, int *as)
2227{
2228 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002229 struct listnode *node;
2230 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002231 struct bgp *bgp;
2232
Steve Hillfc4dc592009-07-28 17:54:35 +01002233 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002234 return NULL;
2235
Paul Jakma9d878772009-08-05 16:25:16 +01002236 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002237 {
Paul Jakma9d878772009-08-05 16:25:16 +01002238 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2239 {
2240 if (sockunion_same (&peer->su, su)
2241 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2242 {
2243 if (peer->as == remote_as
2244 && peer->remote_id.s_addr == remote_id->s_addr)
2245 return peer;
2246 if (peer->as == remote_as)
2247 *as = 1;
2248 }
2249 }
2250
2251 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2252 {
2253 if (sockunion_same (&peer->su, su)
2254 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2255 {
2256 if (peer->as == remote_as
2257 && peer->remote_id.s_addr == 0)
2258 return peer;
2259 if (peer->as == remote_as)
2260 *as = 1;
2261 }
2262 }
paul718e3742002-12-13 20:15:29 +00002263 }
2264 return NULL;
2265}
David Lamparter6b0655a2014-06-04 06:53:35 +02002266
paul718e3742002-12-13 20:15:29 +00002267/* If peer is configured at least one address family return 1. */
2268int
2269peer_active (struct peer *peer)
2270{
2271 if (peer->afc[AFI_IP][SAFI_UNICAST]
2272 || peer->afc[AFI_IP][SAFI_MULTICAST]
2273 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2274 || peer->afc[AFI_IP6][SAFI_UNICAST]
2275 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2276 return 1;
2277 return 0;
2278}
2279
2280/* If peer is negotiated at least one address family return 1. */
2281int
2282peer_active_nego (struct peer *peer)
2283{
2284 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2285 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2286 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2287 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2288 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2289 return 1;
2290 return 0;
2291}
David Lamparter6b0655a2014-06-04 06:53:35 +02002292
paul718e3742002-12-13 20:15:29 +00002293/* peer_flag_change_type. */
2294enum peer_change_type
2295{
2296 peer_change_none,
2297 peer_change_reset,
2298 peer_change_reset_in,
2299 peer_change_reset_out,
2300};
2301
paul94f2b392005-06-28 12:44:16 +00002302static void
paul718e3742002-12-13 20:15:29 +00002303peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2304 enum peer_change_type type)
2305{
2306 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2307 return;
2308
Stephen Hemmingerd9d4ae52010-01-13 00:32:39 +00002309 if (peer->status != Established)
2310 return;
2311
paul718e3742002-12-13 20:15:29 +00002312 if (type == peer_change_reset)
2313 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2314 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2315 else if (type == peer_change_reset_in)
2316 {
2317 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2318 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2319 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2320 else
2321 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2322 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2323 }
2324 else if (type == peer_change_reset_out)
2325 bgp_announce_route (peer, afi, safi);
2326}
2327
2328struct peer_flag_action
2329{
2330 /* Peer's flag. */
2331 u_int32_t flag;
2332
2333 /* This flag can be set for peer-group member. */
2334 u_char not_for_member;
2335
2336 /* Action when the flag is changed. */
2337 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002338
2339 /* Peer down cause */
2340 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002341};
2342
Stephen Hemminger03621952009-07-21 16:27:20 -07002343static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002344 {
2345 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2346 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2347 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2348 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2349 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002350 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002351 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002352 { 0, 0, 0 }
2353 };
2354
Stephen Hemminger03621952009-07-21 16:27:20 -07002355static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002356 {
2357 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2358 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2359 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2360 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2361 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2362 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2363 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2364 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2365 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2366 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2367 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2368 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2369 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002370 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
Timo Teräs9e7a53c2014-04-24 10:22:37 +03002371 { PEER_FLAG_NEXTHOP_SELF_ALL, 1, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002372 { 0, 0, 0 }
2373 };
2374
2375/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002376static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002377peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002378 struct peer_flag_action *action, u_int32_t flag)
2379{
2380 int i;
2381 int found = 0;
2382 int reset_in = 0;
2383 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002384 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002385
2386 /* Check peer's frag action. */
2387 for (i = 0; i < size; i++)
2388 {
2389 match = &action_list[i];
2390
2391 if (match->flag == 0)
2392 break;
2393
2394 if (match->flag & flag)
2395 {
2396 found = 1;
2397
2398 if (match->type == peer_change_reset_in)
2399 reset_in = 1;
2400 if (match->type == peer_change_reset_out)
2401 reset_out = 1;
2402 if (match->type == peer_change_reset)
2403 {
2404 reset_in = 1;
2405 reset_out = 1;
2406 }
2407 if (match->not_for_member)
2408 action->not_for_member = 1;
2409 }
2410 }
2411
2412 /* Set peer clear type. */
2413 if (reset_in && reset_out)
2414 action->type = peer_change_reset;
2415 else if (reset_in)
2416 action->type = peer_change_reset_in;
2417 else if (reset_out)
2418 action->type = peer_change_reset_out;
2419 else
2420 action->type = peer_change_none;
2421
2422 return found;
2423}
2424
paul94f2b392005-06-28 12:44:16 +00002425static void
paul718e3742002-12-13 20:15:29 +00002426peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2427{
2428 if (flag == PEER_FLAG_SHUTDOWN)
2429 {
2430 if (CHECK_FLAG (peer->flags, flag))
2431 {
hasso93406d82005-02-02 14:40:33 +00002432 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2433 peer_nsf_stop (peer);
2434
hasso0a486e52005-02-01 20:57:17 +00002435 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2436 if (peer->t_pmax_restart)
2437 {
2438 BGP_TIMER_OFF (peer->t_pmax_restart);
2439 if (BGP_DEBUG (events, EVENTS))
2440 zlog_debug ("%s Maximum-prefix restart timer canceled",
2441 peer->host);
2442 }
2443
hasso93406d82005-02-02 14:40:33 +00002444 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2445 peer_nsf_stop (peer);
2446
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002447 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002448 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2449 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2450 else
2451 BGP_EVENT_ADD (peer, BGP_Stop);
2452 }
2453 else
2454 {
2455 peer->v_start = BGP_INIT_START_TIMER;
2456 BGP_EVENT_ADD (peer, BGP_Stop);
2457 }
2458 }
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002459 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002460 {
hassoc9502432005-02-01 22:01:48 +00002461 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2462 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2463 else if (flag == PEER_FLAG_PASSIVE)
2464 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002465 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002466 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002467
hassoc9502432005-02-01 22:01:48 +00002468 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2469 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002470 }
2471 else
2472 BGP_EVENT_ADD (peer, BGP_Stop);
2473}
2474
2475/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002476static int
paul718e3742002-12-13 20:15:29 +00002477peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2478{
2479 int found;
2480 int size;
2481 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002482 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002483 struct peer_flag_action action;
2484
2485 memset (&action, 0, sizeof (struct peer_flag_action));
2486 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2487
2488 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2489
2490 /* No flag action is found. */
2491 if (! found)
2492 return BGP_ERR_INVALID_FLAG;
2493
2494 /* Not for peer-group member. */
2495 if (action.not_for_member && peer_group_active (peer))
2496 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2497
2498 /* When unset the peer-group member's flag we have to check
2499 peer-group configuration. */
2500 if (! set && peer_group_active (peer))
2501 if (CHECK_FLAG (peer->group->conf->flags, flag))
2502 {
2503 if (flag == PEER_FLAG_SHUTDOWN)
2504 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2505 else
2506 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2507 }
2508
2509 /* Flag conflict check. */
2510 if (set
2511 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2512 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2513 return BGP_ERR_PEER_FLAG_CONFLICT;
2514
2515 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2516 {
2517 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2518 return 0;
2519 if (! set && ! CHECK_FLAG (peer->flags, flag))
2520 return 0;
2521 }
2522
2523 if (set)
2524 SET_FLAG (peer->flags, flag);
2525 else
2526 UNSET_FLAG (peer->flags, flag);
2527
2528 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2529 {
2530 if (action.type == peer_change_reset)
2531 peer_flag_modify_action (peer, flag);
2532
2533 return 0;
2534 }
2535
2536 /* peer-group member updates. */
2537 group = peer->group;
2538
paul1eb8ef22005-04-07 07:30:20 +00002539 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002540 {
2541 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2542 continue;
2543
2544 if (! set && ! CHECK_FLAG (peer->flags, flag))
2545 continue;
2546
2547 if (set)
2548 SET_FLAG (peer->flags, flag);
2549 else
2550 UNSET_FLAG (peer->flags, flag);
2551
2552 if (action.type == peer_change_reset)
2553 peer_flag_modify_action (peer, flag);
2554 }
2555 return 0;
2556}
2557
2558int
2559peer_flag_set (struct peer *peer, u_int32_t flag)
2560{
2561 return peer_flag_modify (peer, flag, 1);
2562}
2563
2564int
2565peer_flag_unset (struct peer *peer, u_int32_t flag)
2566{
2567 return peer_flag_modify (peer, flag, 0);
2568}
2569
paul94f2b392005-06-28 12:44:16 +00002570static int
paul718e3742002-12-13 20:15:29 +00002571peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2572{
2573 if (peer->af_group[afi][safi])
2574 return 1;
2575 return 0;
2576}
2577
paul94f2b392005-06-28 12:44:16 +00002578static int
paul718e3742002-12-13 20:15:29 +00002579peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2580 int set)
2581{
2582 int found;
2583 int size;
paul1eb8ef22005-04-07 07:30:20 +00002584 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002585 struct peer_group *group;
2586 struct peer_flag_action action;
2587
2588 memset (&action, 0, sizeof (struct peer_flag_action));
2589 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2590
2591 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2592
2593 /* No flag action is found. */
2594 if (! found)
2595 return BGP_ERR_INVALID_FLAG;
2596
2597 /* Adress family must be activated. */
2598 if (! peer->afc[afi][safi])
2599 return BGP_ERR_PEER_INACTIVE;
2600
2601 /* Not for peer-group member. */
2602 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2603 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2604
2605 /* Spcecial check for reflector client. */
2606 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2607 && peer_sort (peer) != BGP_PEER_IBGP)
2608 return BGP_ERR_NOT_INTERNAL_PEER;
2609
2610 /* Spcecial check for remove-private-AS. */
2611 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2612 && peer_sort (peer) == BGP_PEER_IBGP)
2613 return BGP_ERR_REMOVE_PRIVATE_AS;
2614
2615 /* When unset the peer-group member's flag we have to check
2616 peer-group configuration. */
2617 if (! set && peer->af_group[afi][safi])
2618 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2619 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2620
2621 /* When current flag configuration is same as requested one. */
2622 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2623 {
2624 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2625 return 0;
2626 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2627 return 0;
2628 }
2629
2630 if (set)
2631 SET_FLAG (peer->af_flags[afi][safi], flag);
2632 else
2633 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2634
2635 /* Execute action when peer is established. */
2636 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2637 && peer->status == Established)
2638 {
2639 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2640 bgp_clear_adj_in (peer, afi, safi);
2641 else
hassoe0701b72004-05-20 09:19:34 +00002642 {
2643 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2644 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2645 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2646 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2647 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2648 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2649 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2650 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2651
2652 peer_change_action (peer, afi, safi, action.type);
2653 }
2654
paul718e3742002-12-13 20:15:29 +00002655 }
2656
2657 /* Peer group member updates. */
2658 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2659 {
2660 group = peer->group;
2661
paul1eb8ef22005-04-07 07:30:20 +00002662 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002663 {
2664 if (! peer->af_group[afi][safi])
2665 continue;
2666
2667 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2668 continue;
2669
2670 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2671 continue;
2672
2673 if (set)
2674 SET_FLAG (peer->af_flags[afi][safi], flag);
2675 else
2676 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2677
2678 if (peer->status == Established)
2679 {
2680 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2681 bgp_clear_adj_in (peer, afi, safi);
2682 else
hassoe0701b72004-05-20 09:19:34 +00002683 {
2684 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2685 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2686 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2687 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2688 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2689 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2690 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2691 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2692
2693 peer_change_action (peer, afi, safi, action.type);
2694 }
paul718e3742002-12-13 20:15:29 +00002695 }
2696 }
2697 }
2698 return 0;
2699}
2700
2701int
2702peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2703{
2704 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2705}
2706
2707int
2708peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2709{
2710 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2711}
David Lamparter6b0655a2014-06-04 06:53:35 +02002712
paul718e3742002-12-13 20:15:29 +00002713/* EBGP multihop configuration. */
2714int
2715peer_ebgp_multihop_set (struct peer *peer, int ttl)
2716{
2717 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002718 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002719 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002720
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002721 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002722 return 0;
2723
Nick Hilliardfa411a22011-03-23 15:33:17 +00002724 /* see comment in peer_ttl_security_hops_set() */
2725 if (ttl != MAXTTL)
2726 {
2727 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2728 {
2729 group = peer->group;
2730 if (group->conf->gtsm_hops != 0)
2731 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2732
2733 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2734 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002735 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002736 continue;
2737
2738 if (peer1->gtsm_hops != 0)
2739 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2740 }
2741 }
2742 else
2743 {
2744 if (peer->gtsm_hops != 0)
2745 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2746 }
2747 }
2748
paul718e3742002-12-13 20:15:29 +00002749 peer->ttl = ttl;
2750
2751 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2752 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002753 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002754 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002755 }
2756 else
2757 {
2758 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002759 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002760 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002761 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002762 continue;
paul718e3742002-12-13 20:15:29 +00002763
pauleb821182004-05-01 08:44:08 +00002764 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002765
pauleb821182004-05-01 08:44:08 +00002766 if (peer->fd >= 0)
2767 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2768 }
paul718e3742002-12-13 20:15:29 +00002769 }
2770 return 0;
2771}
2772
2773int
2774peer_ebgp_multihop_unset (struct peer *peer)
2775{
2776 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002777 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002778
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002779 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002780 return 0;
2781
Nick Hilliardfa411a22011-03-23 15:33:17 +00002782 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2783 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2784
paul718e3742002-12-13 20:15:29 +00002785 if (peer_group_active (peer))
2786 peer->ttl = peer->group->conf->ttl;
2787 else
2788 peer->ttl = 1;
2789
2790 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2791 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002792 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002793 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002794 }
2795 else
2796 {
2797 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002798 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002799 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002800 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002801 continue;
paul718e3742002-12-13 20:15:29 +00002802
pauleb821182004-05-01 08:44:08 +00002803 peer->ttl = 1;
2804
2805 if (peer->fd >= 0)
2806 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2807 }
paul718e3742002-12-13 20:15:29 +00002808 }
2809 return 0;
2810}
David Lamparter6b0655a2014-06-04 06:53:35 +02002811
paul718e3742002-12-13 20:15:29 +00002812/* Neighbor description. */
2813int
2814peer_description_set (struct peer *peer, char *desc)
2815{
2816 if (peer->desc)
2817 XFREE (MTYPE_PEER_DESC, peer->desc);
2818
2819 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2820
2821 return 0;
2822}
2823
2824int
2825peer_description_unset (struct peer *peer)
2826{
2827 if (peer->desc)
2828 XFREE (MTYPE_PEER_DESC, peer->desc);
2829
2830 peer->desc = NULL;
2831
2832 return 0;
2833}
David Lamparter6b0655a2014-06-04 06:53:35 +02002834
paul718e3742002-12-13 20:15:29 +00002835/* Neighbor update-source. */
2836int
paulfd79ac92004-10-13 05:06:08 +00002837peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002838{
2839 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002840 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002841
2842 if (peer->update_if)
2843 {
2844 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2845 && strcmp (peer->update_if, ifname) == 0)
2846 return 0;
2847
2848 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2849 peer->update_if = NULL;
2850 }
2851
2852 if (peer->update_source)
2853 {
2854 sockunion_free (peer->update_source);
2855 peer->update_source = NULL;
2856 }
2857
2858 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2859
2860 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2861 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002862 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002863 {
2864 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2865 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2866 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2867 }
paul718e3742002-12-13 20:15:29 +00002868 else
2869 BGP_EVENT_ADD (peer, BGP_Stop);
2870 return 0;
2871 }
2872
2873 /* peer-group member updates. */
2874 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002875 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002876 {
2877 if (peer->update_if)
2878 {
2879 if (strcmp (peer->update_if, ifname) == 0)
2880 continue;
2881
2882 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2883 peer->update_if = NULL;
2884 }
2885
2886 if (peer->update_source)
2887 {
2888 sockunion_free (peer->update_source);
2889 peer->update_source = NULL;
2890 }
2891
2892 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2893
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002894 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002895 {
2896 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2897 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2898 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2899 }
paul718e3742002-12-13 20:15:29 +00002900 else
2901 BGP_EVENT_ADD (peer, BGP_Stop);
2902 }
2903 return 0;
2904}
2905
2906int
2907peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2908{
2909 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002910 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002911
2912 if (peer->update_source)
2913 {
2914 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2915 && sockunion_cmp (peer->update_source, su) == 0)
2916 return 0;
2917 sockunion_free (peer->update_source);
2918 peer->update_source = NULL;
2919 }
2920
2921 if (peer->update_if)
2922 {
2923 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2924 peer->update_if = NULL;
2925 }
2926
2927 peer->update_source = sockunion_dup (su);
2928
2929 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2930 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002931 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002932 {
2933 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2934 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2935 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2936 }
paul718e3742002-12-13 20:15:29 +00002937 else
2938 BGP_EVENT_ADD (peer, BGP_Stop);
2939 return 0;
2940 }
2941
2942 /* peer-group member updates. */
2943 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002944 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002945 {
2946 if (peer->update_source)
2947 {
2948 if (sockunion_cmp (peer->update_source, su) == 0)
2949 continue;
2950 sockunion_free (peer->update_source);
2951 peer->update_source = NULL;
2952 }
2953
2954 if (peer->update_if)
2955 {
2956 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2957 peer->update_if = NULL;
2958 }
2959
2960 peer->update_source = sockunion_dup (su);
2961
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002962 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002963 {
2964 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2965 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2966 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2967 }
paul718e3742002-12-13 20:15:29 +00002968 else
2969 BGP_EVENT_ADD (peer, BGP_Stop);
2970 }
2971 return 0;
2972}
2973
2974int
2975peer_update_source_unset (struct peer *peer)
2976{
2977 union sockunion *su;
2978 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002979 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002980
2981 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2982 && ! peer->update_source
2983 && ! peer->update_if)
2984 return 0;
2985
2986 if (peer->update_source)
2987 {
2988 sockunion_free (peer->update_source);
2989 peer->update_source = NULL;
2990 }
2991 if (peer->update_if)
2992 {
2993 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2994 peer->update_if = NULL;
2995 }
2996
2997 if (peer_group_active (peer))
2998 {
2999 group = peer->group;
3000
3001 if (group->conf->update_source)
3002 {
3003 su = sockunion_dup (group->conf->update_source);
3004 peer->update_source = su;
3005 }
3006 else if (group->conf->update_if)
3007 peer->update_if =
3008 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
3009 }
3010
3011 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3012 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003013 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003014 {
3015 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3016 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3017 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3018 }
paul718e3742002-12-13 20:15:29 +00003019 else
3020 BGP_EVENT_ADD (peer, BGP_Stop);
3021 return 0;
3022 }
3023
3024 /* peer-group member updates. */
3025 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003026 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003027 {
3028 if (! peer->update_source && ! peer->update_if)
3029 continue;
3030
3031 if (peer->update_source)
3032 {
3033 sockunion_free (peer->update_source);
3034 peer->update_source = NULL;
3035 }
3036
3037 if (peer->update_if)
3038 {
3039 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3040 peer->update_if = NULL;
3041 }
3042
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003043 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003044 {
3045 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3046 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3047 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3048 }
paul718e3742002-12-13 20:15:29 +00003049 else
3050 BGP_EVENT_ADD (peer, BGP_Stop);
3051 }
3052 return 0;
3053}
David Lamparter6b0655a2014-06-04 06:53:35 +02003054
paul718e3742002-12-13 20:15:29 +00003055int
3056peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003057 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003058{
3059 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003060 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003061
3062 /* Adress family must be activated. */
3063 if (! peer->afc[afi][safi])
3064 return BGP_ERR_PEER_INACTIVE;
3065
3066 /* Default originate can't be used for peer group memeber. */
3067 if (peer_is_group_member (peer, afi, safi))
3068 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3069
3070 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3071 || (rmap && ! peer->default_rmap[afi][safi].name)
3072 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3073 {
3074 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3075
3076 if (rmap)
3077 {
3078 if (peer->default_rmap[afi][safi].name)
3079 free (peer->default_rmap[afi][safi].name);
3080 peer->default_rmap[afi][safi].name = strdup (rmap);
3081 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3082 }
3083 }
3084
3085 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3086 {
3087 if (peer->status == Established && peer->afc_nego[afi][safi])
3088 bgp_default_originate (peer, afi, safi, 0);
3089 return 0;
3090 }
3091
3092 /* peer-group member updates. */
3093 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003094 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003095 {
3096 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3097
3098 if (rmap)
3099 {
3100 if (peer->default_rmap[afi][safi].name)
3101 free (peer->default_rmap[afi][safi].name);
3102 peer->default_rmap[afi][safi].name = strdup (rmap);
3103 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3104 }
3105
3106 if (peer->status == Established && peer->afc_nego[afi][safi])
3107 bgp_default_originate (peer, afi, safi, 0);
3108 }
3109 return 0;
3110}
3111
3112int
3113peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3114{
3115 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003116 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003117
3118 /* Adress family must be activated. */
3119 if (! peer->afc[afi][safi])
3120 return BGP_ERR_PEER_INACTIVE;
3121
3122 /* Default originate can't be used for peer group memeber. */
3123 if (peer_is_group_member (peer, afi, safi))
3124 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3125
3126 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3127 {
3128 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3129
3130 if (peer->default_rmap[afi][safi].name)
3131 free (peer->default_rmap[afi][safi].name);
3132 peer->default_rmap[afi][safi].name = NULL;
3133 peer->default_rmap[afi][safi].map = NULL;
3134 }
3135
3136 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3137 {
3138 if (peer->status == Established && peer->afc_nego[afi][safi])
3139 bgp_default_originate (peer, afi, safi, 1);
3140 return 0;
3141 }
3142
3143 /* peer-group member updates. */
3144 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003145 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003146 {
3147 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3148
3149 if (peer->default_rmap[afi][safi].name)
3150 free (peer->default_rmap[afi][safi].name);
3151 peer->default_rmap[afi][safi].name = NULL;
3152 peer->default_rmap[afi][safi].map = NULL;
3153
3154 if (peer->status == Established && peer->afc_nego[afi][safi])
3155 bgp_default_originate (peer, afi, safi, 1);
3156 }
3157 return 0;
3158}
David Lamparter6b0655a2014-06-04 06:53:35 +02003159
paul718e3742002-12-13 20:15:29 +00003160int
3161peer_port_set (struct peer *peer, u_int16_t port)
3162{
3163 peer->port = port;
3164 return 0;
3165}
3166
3167int
3168peer_port_unset (struct peer *peer)
3169{
3170 peer->port = BGP_PORT_DEFAULT;
3171 return 0;
3172}
David Lamparter6b0655a2014-06-04 06:53:35 +02003173
paul718e3742002-12-13 20:15:29 +00003174/* neighbor weight. */
3175int
3176peer_weight_set (struct peer *peer, u_int16_t weight)
3177{
3178 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003179 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003180
3181 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3182 peer->weight = weight;
3183
3184 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3185 return 0;
3186
3187 /* peer-group member updates. */
3188 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003189 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003190 {
3191 peer->weight = group->conf->weight;
3192 }
3193 return 0;
3194}
3195
3196int
3197peer_weight_unset (struct peer *peer)
3198{
3199 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003200 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003201
3202 /* Set default weight. */
3203 if (peer_group_active (peer))
3204 peer->weight = peer->group->conf->weight;
3205 else
3206 peer->weight = 0;
3207
3208 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3209
3210 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3211 return 0;
3212
3213 /* peer-group member updates. */
3214 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003215 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003216 {
3217 peer->weight = 0;
3218 }
3219 return 0;
3220}
David Lamparter6b0655a2014-06-04 06:53:35 +02003221
paul718e3742002-12-13 20:15:29 +00003222int
3223peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3224{
3225 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003226 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003227
3228 /* Not for peer group memeber. */
3229 if (peer_group_active (peer))
3230 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3231
3232 /* keepalive value check. */
3233 if (keepalive > 65535)
3234 return BGP_ERR_INVALID_VALUE;
3235
3236 /* Holdtime value check. */
3237 if (holdtime > 65535)
3238 return BGP_ERR_INVALID_VALUE;
3239
3240 /* Holdtime value must be either 0 or greater than 3. */
3241 if (holdtime < 3 && holdtime != 0)
3242 return BGP_ERR_INVALID_VALUE;
3243
3244 /* Set value to the configuration. */
3245 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3246 peer->holdtime = holdtime;
3247 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3248
3249 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3250 return 0;
3251
3252 /* peer-group member updates. */
3253 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003254 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003255 {
3256 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3257 peer->holdtime = group->conf->holdtime;
3258 peer->keepalive = group->conf->keepalive;
3259 }
3260 return 0;
3261}
3262
3263int
3264peer_timers_unset (struct peer *peer)
3265{
3266 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003267 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003268
3269 if (peer_group_active (peer))
3270 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3271
3272 /* Clear configuration. */
3273 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3274 peer->keepalive = 0;
3275 peer->holdtime = 0;
3276
3277 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3278 return 0;
3279
3280 /* peer-group member updates. */
3281 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003282 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003283 {
3284 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3285 peer->holdtime = 0;
3286 peer->keepalive = 0;
3287 }
3288
3289 return 0;
3290}
David Lamparter6b0655a2014-06-04 06:53:35 +02003291
paul718e3742002-12-13 20:15:29 +00003292int
3293peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3294{
3295 if (peer_group_active (peer))
3296 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3297
3298 if (connect > 65535)
3299 return BGP_ERR_INVALID_VALUE;
3300
3301 /* Set value to the configuration. */
3302 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3303 peer->connect = connect;
3304
3305 /* Set value to timer setting. */
3306 peer->v_connect = connect;
3307
3308 return 0;
3309}
3310
3311int
3312peer_timers_connect_unset (struct peer *peer)
3313{
3314 if (peer_group_active (peer))
3315 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3316
3317 /* Clear configuration. */
3318 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3319 peer->connect = 0;
3320
3321 /* Set timer setting to default value. */
3322 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3323
3324 return 0;
3325}
David Lamparter6b0655a2014-06-04 06:53:35 +02003326
paul718e3742002-12-13 20:15:29 +00003327int
3328peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3329{
3330 if (peer_group_active (peer))
3331 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3332
3333 if (routeadv > 600)
3334 return BGP_ERR_INVALID_VALUE;
3335
3336 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3337 peer->routeadv = routeadv;
3338 peer->v_routeadv = routeadv;
3339
3340 return 0;
3341}
3342
3343int
3344peer_advertise_interval_unset (struct peer *peer)
3345{
3346 if (peer_group_active (peer))
3347 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3348
3349 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3350 peer->routeadv = 0;
3351
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003352 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003353 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3354 else
3355 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3356
3357 return 0;
3358}
David Lamparter6b0655a2014-06-04 06:53:35 +02003359
paul718e3742002-12-13 20:15:29 +00003360/* neighbor interface */
3361int
paulfd79ac92004-10-13 05:06:08 +00003362peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003363{
3364 if (peer->ifname)
3365 free (peer->ifname);
3366 peer->ifname = strdup (str);
3367
3368 return 0;
3369}
3370
3371int
3372peer_interface_unset (struct peer *peer)
3373{
3374 if (peer->ifname)
3375 free (peer->ifname);
3376 peer->ifname = NULL;
3377
3378 return 0;
3379}
David Lamparter6b0655a2014-06-04 06:53:35 +02003380
paul718e3742002-12-13 20:15:29 +00003381/* Allow-as in. */
3382int
3383peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3384{
3385 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003386 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003387
3388 if (allow_num < 1 || allow_num > 10)
3389 return BGP_ERR_INVALID_VALUE;
3390
3391 if (peer->allowas_in[afi][safi] != allow_num)
3392 {
3393 peer->allowas_in[afi][safi] = allow_num;
3394 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3395 peer_change_action (peer, afi, safi, peer_change_reset_in);
3396 }
3397
3398 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3399 return 0;
3400
3401 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003402 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003403 {
3404 if (peer->allowas_in[afi][safi] != allow_num)
3405 {
3406 peer->allowas_in[afi][safi] = allow_num;
3407 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3408 peer_change_action (peer, afi, safi, peer_change_reset_in);
3409 }
3410
3411 }
3412 return 0;
3413}
3414
3415int
3416peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3417{
3418 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003419 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003420
3421 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3422 {
3423 peer->allowas_in[afi][safi] = 0;
3424 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3425 }
3426
3427 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3428 return 0;
3429
3430 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003431 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003432 {
3433 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3434 {
3435 peer->allowas_in[afi][safi] = 0;
3436 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3437 }
3438 }
3439 return 0;
3440}
David Lamparter6b0655a2014-06-04 06:53:35 +02003441
paul718e3742002-12-13 20:15:29 +00003442int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003443peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003444{
3445 struct bgp *bgp = peer->bgp;
3446 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003447 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003448
3449 if (peer_sort (peer) != BGP_PEER_EBGP
3450 && peer_sort (peer) != BGP_PEER_INTERNAL)
3451 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3452
3453 if (bgp->as == as)
3454 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3455
3456 if (peer_group_active (peer))
3457 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3458
Andrew Certain9d3f9702012-11-07 23:50:07 +00003459 if (peer->as == as)
3460 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3461
paul718e3742002-12-13 20:15:29 +00003462 if (peer->change_local_as == as &&
3463 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003464 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3465 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3466 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003467 return 0;
3468
3469 peer->change_local_as = as;
3470 if (no_prepend)
3471 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3472 else
3473 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3474
Andrew Certain9d3f9702012-11-07 23:50:07 +00003475 if (replace_as)
3476 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3477 else
3478 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3479
paul718e3742002-12-13 20:15:29 +00003480 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3481 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003482 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003483 {
3484 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3485 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3486 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3487 }
paul718e3742002-12-13 20:15:29 +00003488 else
3489 BGP_EVENT_ADD (peer, BGP_Stop);
3490
3491 return 0;
3492 }
3493
3494 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003495 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003496 {
3497 peer->change_local_as = as;
3498 if (no_prepend)
3499 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3500 else
3501 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3502
Andrew Certain9d3f9702012-11-07 23:50:07 +00003503 if (replace_as)
3504 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3505 else
3506 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3507
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003508 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003509 {
3510 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3511 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3512 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3513 }
paul718e3742002-12-13 20:15:29 +00003514 else
3515 BGP_EVENT_ADD (peer, BGP_Stop);
3516 }
3517
3518 return 0;
3519}
3520
3521int
3522peer_local_as_unset (struct peer *peer)
3523{
3524 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003525 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003526
3527 if (peer_group_active (peer))
3528 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3529
3530 if (! peer->change_local_as)
3531 return 0;
3532
3533 peer->change_local_as = 0;
3534 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003535 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003536
3537 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3538 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003539 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003540 {
3541 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3542 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3543 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3544 }
paul718e3742002-12-13 20:15:29 +00003545 else
3546 BGP_EVENT_ADD (peer, BGP_Stop);
3547
3548 return 0;
3549 }
3550
3551 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003552 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003553 {
3554 peer->change_local_as = 0;
3555 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003556 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003557
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003558 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003559 {
3560 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3561 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3562 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3563 }
paul718e3742002-12-13 20:15:29 +00003564 else
3565 BGP_EVENT_ADD (peer, BGP_Stop);
3566 }
3567 return 0;
3568}
David Lamparter6b0655a2014-06-04 06:53:35 +02003569
Paul Jakma0df7c912008-07-21 21:02:49 +00003570/* Set password for authenticating with the peer. */
3571int
3572peer_password_set (struct peer *peer, const char *password)
3573{
3574 struct listnode *nn, *nnode;
3575 int len = password ? strlen(password) : 0;
3576 int ret = BGP_SUCCESS;
3577
3578 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3579 return BGP_ERR_INVALID_VALUE;
3580
3581 if (peer->password && strcmp (peer->password, password) == 0
3582 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3583 return 0;
3584
3585 if (peer->password)
3586 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3587
3588 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3589
3590 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3591 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003592 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3593 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
Paul Jakma0df7c912008-07-21 21:02:49 +00003594 else
3595 BGP_EVENT_ADD (peer, BGP_Stop);
3596
3597 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3598 }
3599
3600 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3601 {
3602 if (peer->password && strcmp (peer->password, password) == 0)
3603 continue;
3604
3605 if (peer->password)
3606 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3607
3608 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3609
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003610 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003611 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3612 else
3613 BGP_EVENT_ADD (peer, BGP_Stop);
3614
3615 if (bgp_md5_set (peer) < 0)
3616 ret = BGP_ERR_TCPSIG_FAILED;
3617 }
3618
3619 return ret;
3620}
3621
3622int
3623peer_password_unset (struct peer *peer)
3624{
3625 struct listnode *nn, *nnode;
3626
3627 if (!peer->password
3628 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3629 return 0;
3630
3631 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3632 {
3633 if (peer_group_active (peer)
3634 && peer->group->conf->password
3635 && strcmp (peer->group->conf->password, peer->password) == 0)
3636 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3637
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003638 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003639 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3640 else
3641 BGP_EVENT_ADD (peer, BGP_Stop);
3642
3643 if (peer->password)
3644 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3645
3646 peer->password = NULL;
3647
3648 bgp_md5_set (peer);
3649
3650 return 0;
3651 }
3652
3653 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3654 peer->password = NULL;
3655
3656 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3657 {
3658 if (!peer->password)
3659 continue;
3660
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003661 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003662 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3663 else
3664 BGP_EVENT_ADD (peer, BGP_Stop);
3665
3666 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3667 peer->password = NULL;
3668
3669 bgp_md5_set (peer);
3670 }
3671
3672 return 0;
3673}
David Lamparter6b0655a2014-06-04 06:53:35 +02003674
paul718e3742002-12-13 20:15:29 +00003675/* Set distribute list to the peer. */
3676int
3677peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003678 const char *name)
paul718e3742002-12-13 20:15:29 +00003679{
3680 struct bgp_filter *filter;
3681 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003682 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003683
3684 if (! peer->afc[afi][safi])
3685 return BGP_ERR_PEER_INACTIVE;
3686
3687 if (direct != FILTER_IN && direct != FILTER_OUT)
3688 return BGP_ERR_INVALID_VALUE;
3689
3690 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3691 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3692
3693 filter = &peer->filter[afi][safi];
3694
3695 if (filter->plist[direct].name)
3696 return BGP_ERR_PEER_FILTER_CONFLICT;
3697
3698 if (filter->dlist[direct].name)
3699 free (filter->dlist[direct].name);
3700 filter->dlist[direct].name = strdup (name);
3701 filter->dlist[direct].alist = access_list_lookup (afi, name);
3702
3703 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3704 return 0;
3705
3706 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003707 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003708 {
3709 filter = &peer->filter[afi][safi];
3710
3711 if (! peer->af_group[afi][safi])
3712 continue;
3713
3714 if (filter->dlist[direct].name)
3715 free (filter->dlist[direct].name);
3716 filter->dlist[direct].name = strdup (name);
3717 filter->dlist[direct].alist = access_list_lookup (afi, name);
3718 }
3719
3720 return 0;
3721}
3722
3723int
3724peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3725{
3726 struct bgp_filter *filter;
3727 struct bgp_filter *gfilter;
3728 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003729 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003730
3731 if (! peer->afc[afi][safi])
3732 return BGP_ERR_PEER_INACTIVE;
3733
3734 if (direct != FILTER_IN && direct != FILTER_OUT)
3735 return BGP_ERR_INVALID_VALUE;
3736
3737 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3738 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3739
3740 filter = &peer->filter[afi][safi];
3741
3742 /* apply peer-group filter */
3743 if (peer->af_group[afi][safi])
3744 {
3745 gfilter = &peer->group->conf->filter[afi][safi];
3746
3747 if (gfilter->dlist[direct].name)
3748 {
3749 if (filter->dlist[direct].name)
3750 free (filter->dlist[direct].name);
3751 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3752 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3753 return 0;
3754 }
3755 }
3756
3757 if (filter->dlist[direct].name)
3758 free (filter->dlist[direct].name);
3759 filter->dlist[direct].name = NULL;
3760 filter->dlist[direct].alist = NULL;
3761
3762 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3763 return 0;
3764
3765 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003766 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003767 {
3768 filter = &peer->filter[afi][safi];
3769
3770 if (! peer->af_group[afi][safi])
3771 continue;
3772
3773 if (filter->dlist[direct].name)
3774 free (filter->dlist[direct].name);
3775 filter->dlist[direct].name = NULL;
3776 filter->dlist[direct].alist = NULL;
3777 }
3778
3779 return 0;
3780}
3781
3782/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003783static void
paul718e3742002-12-13 20:15:29 +00003784peer_distribute_update (struct access_list *access)
3785{
3786 afi_t afi;
3787 safi_t safi;
3788 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003789 struct listnode *mnode, *mnnode;
3790 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003791 struct bgp *bgp;
3792 struct peer *peer;
3793 struct peer_group *group;
3794 struct bgp_filter *filter;
3795
paul1eb8ef22005-04-07 07:30:20 +00003796 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003797 {
paul1eb8ef22005-04-07 07:30:20 +00003798 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003799 {
3800 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3801 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3802 {
3803 filter = &peer->filter[afi][safi];
3804
3805 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3806 {
3807 if (filter->dlist[direct].name)
3808 filter->dlist[direct].alist =
3809 access_list_lookup (afi, filter->dlist[direct].name);
3810 else
3811 filter->dlist[direct].alist = NULL;
3812 }
3813 }
3814 }
paul1eb8ef22005-04-07 07:30:20 +00003815 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003816 {
3817 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3818 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3819 {
3820 filter = &group->conf->filter[afi][safi];
3821
3822 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3823 {
3824 if (filter->dlist[direct].name)
3825 filter->dlist[direct].alist =
3826 access_list_lookup (afi, filter->dlist[direct].name);
3827 else
3828 filter->dlist[direct].alist = NULL;
3829 }
3830 }
3831 }
3832 }
3833}
David Lamparter6b0655a2014-06-04 06:53:35 +02003834
paul718e3742002-12-13 20:15:29 +00003835/* Set prefix list to the peer. */
3836int
3837peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003838 const char *name)
paul718e3742002-12-13 20:15:29 +00003839{
3840 struct bgp_filter *filter;
3841 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003842 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003843
3844 if (! peer->afc[afi][safi])
3845 return BGP_ERR_PEER_INACTIVE;
3846
3847 if (direct != FILTER_IN && direct != FILTER_OUT)
3848 return BGP_ERR_INVALID_VALUE;
3849
3850 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3851 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3852
3853 filter = &peer->filter[afi][safi];
3854
3855 if (filter->dlist[direct].name)
3856 return BGP_ERR_PEER_FILTER_CONFLICT;
3857
3858 if (filter->plist[direct].name)
3859 free (filter->plist[direct].name);
3860 filter->plist[direct].name = strdup (name);
3861 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3862
3863 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3864 return 0;
3865
3866 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003867 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003868 {
3869 filter = &peer->filter[afi][safi];
3870
3871 if (! peer->af_group[afi][safi])
3872 continue;
3873
3874 if (filter->plist[direct].name)
3875 free (filter->plist[direct].name);
3876 filter->plist[direct].name = strdup (name);
3877 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3878 }
3879 return 0;
3880}
3881
3882int
3883peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3884{
3885 struct bgp_filter *filter;
3886 struct bgp_filter *gfilter;
3887 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003888 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003889
3890 if (! peer->afc[afi][safi])
3891 return BGP_ERR_PEER_INACTIVE;
3892
3893 if (direct != FILTER_IN && direct != FILTER_OUT)
3894 return BGP_ERR_INVALID_VALUE;
3895
3896 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3897 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3898
3899 filter = &peer->filter[afi][safi];
3900
3901 /* apply peer-group filter */
3902 if (peer->af_group[afi][safi])
3903 {
3904 gfilter = &peer->group->conf->filter[afi][safi];
3905
3906 if (gfilter->plist[direct].name)
3907 {
3908 if (filter->plist[direct].name)
3909 free (filter->plist[direct].name);
3910 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3911 filter->plist[direct].plist = gfilter->plist[direct].plist;
3912 return 0;
3913 }
3914 }
3915
3916 if (filter->plist[direct].name)
3917 free (filter->plist[direct].name);
3918 filter->plist[direct].name = NULL;
3919 filter->plist[direct].plist = NULL;
3920
3921 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3922 return 0;
3923
3924 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003925 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003926 {
3927 filter = &peer->filter[afi][safi];
3928
3929 if (! peer->af_group[afi][safi])
3930 continue;
3931
3932 if (filter->plist[direct].name)
3933 free (filter->plist[direct].name);
3934 filter->plist[direct].name = NULL;
3935 filter->plist[direct].plist = NULL;
3936 }
3937
3938 return 0;
3939}
3940
3941/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003942static void
paul718e3742002-12-13 20:15:29 +00003943peer_prefix_list_update (struct prefix_list *plist)
3944{
paul1eb8ef22005-04-07 07:30:20 +00003945 struct listnode *mnode, *mnnode;
3946 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003947 struct bgp *bgp;
3948 struct peer *peer;
3949 struct peer_group *group;
3950 struct bgp_filter *filter;
3951 afi_t afi;
3952 safi_t safi;
3953 int direct;
3954
paul1eb8ef22005-04-07 07:30:20 +00003955 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003956 {
paul1eb8ef22005-04-07 07:30:20 +00003957 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003958 {
3959 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3960 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3961 {
3962 filter = &peer->filter[afi][safi];
3963
3964 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3965 {
3966 if (filter->plist[direct].name)
3967 filter->plist[direct].plist =
3968 prefix_list_lookup (afi, filter->plist[direct].name);
3969 else
3970 filter->plist[direct].plist = NULL;
3971 }
3972 }
3973 }
paul1eb8ef22005-04-07 07:30:20 +00003974 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003975 {
3976 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3977 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3978 {
3979 filter = &group->conf->filter[afi][safi];
3980
3981 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3982 {
3983 if (filter->plist[direct].name)
3984 filter->plist[direct].plist =
3985 prefix_list_lookup (afi, filter->plist[direct].name);
3986 else
3987 filter->plist[direct].plist = NULL;
3988 }
3989 }
3990 }
3991 }
3992}
David Lamparter6b0655a2014-06-04 06:53:35 +02003993
paul718e3742002-12-13 20:15:29 +00003994int
3995peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003996 const char *name)
paul718e3742002-12-13 20:15:29 +00003997{
3998 struct bgp_filter *filter;
3999 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004000 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004001
4002 if (! peer->afc[afi][safi])
4003 return BGP_ERR_PEER_INACTIVE;
4004
4005 if (direct != FILTER_IN && direct != FILTER_OUT)
4006 return BGP_ERR_INVALID_VALUE;
4007
4008 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
4009 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4010
4011 filter = &peer->filter[afi][safi];
4012
4013 if (filter->aslist[direct].name)
4014 free (filter->aslist[direct].name);
4015 filter->aslist[direct].name = strdup (name);
4016 filter->aslist[direct].aslist = as_list_lookup (name);
4017
4018 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4019 return 0;
4020
4021 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004022 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004023 {
4024 filter = &peer->filter[afi][safi];
4025
4026 if (! peer->af_group[afi][safi])
4027 continue;
4028
4029 if (filter->aslist[direct].name)
4030 free (filter->aslist[direct].name);
4031 filter->aslist[direct].name = strdup (name);
4032 filter->aslist[direct].aslist = as_list_lookup (name);
4033 }
4034 return 0;
4035}
4036
4037int
4038peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4039{
4040 struct bgp_filter *filter;
4041 struct bgp_filter *gfilter;
4042 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004043 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004044
4045 if (! peer->afc[afi][safi])
4046 return BGP_ERR_PEER_INACTIVE;
4047
hassob5f29602005-05-25 21:00:28 +00004048 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004049 return BGP_ERR_INVALID_VALUE;
4050
hassob5f29602005-05-25 21:00:28 +00004051 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004052 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4053
4054 filter = &peer->filter[afi][safi];
4055
4056 /* apply peer-group filter */
4057 if (peer->af_group[afi][safi])
4058 {
4059 gfilter = &peer->group->conf->filter[afi][safi];
4060
4061 if (gfilter->aslist[direct].name)
4062 {
4063 if (filter->aslist[direct].name)
4064 free (filter->aslist[direct].name);
4065 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4066 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4067 return 0;
4068 }
4069 }
4070
4071 if (filter->aslist[direct].name)
4072 free (filter->aslist[direct].name);
4073 filter->aslist[direct].name = NULL;
4074 filter->aslist[direct].aslist = NULL;
4075
4076 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4077 return 0;
4078
4079 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004080 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004081 {
4082 filter = &peer->filter[afi][safi];
4083
4084 if (! peer->af_group[afi][safi])
4085 continue;
4086
4087 if (filter->aslist[direct].name)
4088 free (filter->aslist[direct].name);
4089 filter->aslist[direct].name = NULL;
4090 filter->aslist[direct].aslist = NULL;
4091 }
4092
4093 return 0;
4094}
4095
paul94f2b392005-06-28 12:44:16 +00004096static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004097peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004098{
4099 afi_t afi;
4100 safi_t safi;
4101 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004102 struct listnode *mnode, *mnnode;
4103 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004104 struct bgp *bgp;
4105 struct peer *peer;
4106 struct peer_group *group;
4107 struct bgp_filter *filter;
4108
paul1eb8ef22005-04-07 07:30:20 +00004109 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004110 {
paul1eb8ef22005-04-07 07:30:20 +00004111 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004112 {
4113 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4114 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4115 {
4116 filter = &peer->filter[afi][safi];
4117
4118 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4119 {
4120 if (filter->aslist[direct].name)
4121 filter->aslist[direct].aslist =
4122 as_list_lookup (filter->aslist[direct].name);
4123 else
4124 filter->aslist[direct].aslist = NULL;
4125 }
4126 }
4127 }
paul1eb8ef22005-04-07 07:30:20 +00004128 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004129 {
4130 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4131 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4132 {
4133 filter = &group->conf->filter[afi][safi];
4134
4135 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4136 {
4137 if (filter->aslist[direct].name)
4138 filter->aslist[direct].aslist =
4139 as_list_lookup (filter->aslist[direct].name);
4140 else
4141 filter->aslist[direct].aslist = NULL;
4142 }
4143 }
4144 }
4145 }
4146}
David Lamparter6b0655a2014-06-04 06:53:35 +02004147
paul718e3742002-12-13 20:15:29 +00004148/* Set route-map to the peer. */
4149int
4150peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004151 const char *name)
paul718e3742002-12-13 20:15:29 +00004152{
4153 struct bgp_filter *filter;
4154 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004155 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004156
4157 if (! peer->afc[afi][safi])
4158 return BGP_ERR_PEER_INACTIVE;
4159
paulfee0f4c2004-09-13 05:12:46 +00004160 if (direct != RMAP_IN && direct != RMAP_OUT &&
4161 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004162 return BGP_ERR_INVALID_VALUE;
4163
paulfee0f4c2004-09-13 05:12:46 +00004164 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4165 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004166 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4167
4168 filter = &peer->filter[afi][safi];
4169
4170 if (filter->map[direct].name)
4171 free (filter->map[direct].name);
4172
4173 filter->map[direct].name = strdup (name);
4174 filter->map[direct].map = route_map_lookup_by_name (name);
4175
4176 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4177 return 0;
4178
4179 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004180 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004181 {
4182 filter = &peer->filter[afi][safi];
4183
4184 if (! peer->af_group[afi][safi])
4185 continue;
4186
4187 if (filter->map[direct].name)
4188 free (filter->map[direct].name);
4189 filter->map[direct].name = strdup (name);
4190 filter->map[direct].map = route_map_lookup_by_name (name);
4191 }
4192 return 0;
4193}
4194
4195/* Unset route-map from the peer. */
4196int
4197peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4198{
4199 struct bgp_filter *filter;
4200 struct bgp_filter *gfilter;
4201 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004202 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004203
4204 if (! peer->afc[afi][safi])
4205 return BGP_ERR_PEER_INACTIVE;
4206
hassob5f29602005-05-25 21:00:28 +00004207 if (direct != RMAP_IN && direct != RMAP_OUT &&
4208 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004209 return BGP_ERR_INVALID_VALUE;
4210
hassob5f29602005-05-25 21:00:28 +00004211 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4212 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004213 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4214
4215 filter = &peer->filter[afi][safi];
4216
4217 /* apply peer-group filter */
4218 if (peer->af_group[afi][safi])
4219 {
4220 gfilter = &peer->group->conf->filter[afi][safi];
4221
4222 if (gfilter->map[direct].name)
4223 {
4224 if (filter->map[direct].name)
4225 free (filter->map[direct].name);
4226 filter->map[direct].name = strdup (gfilter->map[direct].name);
4227 filter->map[direct].map = gfilter->map[direct].map;
4228 return 0;
4229 }
4230 }
4231
4232 if (filter->map[direct].name)
4233 free (filter->map[direct].name);
4234 filter->map[direct].name = NULL;
4235 filter->map[direct].map = NULL;
4236
4237 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4238 return 0;
4239
4240 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004241 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004242 {
4243 filter = &peer->filter[afi][safi];
4244
4245 if (! peer->af_group[afi][safi])
4246 continue;
4247
4248 if (filter->map[direct].name)
4249 free (filter->map[direct].name);
4250 filter->map[direct].name = NULL;
4251 filter->map[direct].map = NULL;
4252 }
4253 return 0;
4254}
David Lamparter6b0655a2014-06-04 06:53:35 +02004255
paul718e3742002-12-13 20:15:29 +00004256/* Set unsuppress-map to the peer. */
4257int
paulfd79ac92004-10-13 05:06:08 +00004258peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4259 const char *name)
paul718e3742002-12-13 20:15:29 +00004260{
4261 struct bgp_filter *filter;
4262 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004263 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004264
4265 if (! peer->afc[afi][safi])
4266 return BGP_ERR_PEER_INACTIVE;
4267
4268 if (peer_is_group_member (peer, afi, safi))
4269 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4270
4271 filter = &peer->filter[afi][safi];
4272
4273 if (filter->usmap.name)
4274 free (filter->usmap.name);
4275
4276 filter->usmap.name = strdup (name);
4277 filter->usmap.map = route_map_lookup_by_name (name);
4278
4279 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4280 return 0;
4281
4282 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004283 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004284 {
4285 filter = &peer->filter[afi][safi];
4286
4287 if (! peer->af_group[afi][safi])
4288 continue;
4289
4290 if (filter->usmap.name)
4291 free (filter->usmap.name);
4292 filter->usmap.name = strdup (name);
4293 filter->usmap.map = route_map_lookup_by_name (name);
4294 }
4295 return 0;
4296}
4297
4298/* Unset route-map from the peer. */
4299int
4300peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4301{
4302 struct bgp_filter *filter;
4303 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004304 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004305
4306 if (! peer->afc[afi][safi])
4307 return BGP_ERR_PEER_INACTIVE;
4308
4309 if (peer_is_group_member (peer, afi, safi))
4310 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4311
4312 filter = &peer->filter[afi][safi];
4313
4314 if (filter->usmap.name)
4315 free (filter->usmap.name);
4316 filter->usmap.name = NULL;
4317 filter->usmap.map = NULL;
4318
4319 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4320 return 0;
4321
4322 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004323 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004324 {
4325 filter = &peer->filter[afi][safi];
4326
4327 if (! peer->af_group[afi][safi])
4328 continue;
4329
4330 if (filter->usmap.name)
4331 free (filter->usmap.name);
4332 filter->usmap.name = NULL;
4333 filter->usmap.map = NULL;
4334 }
4335 return 0;
4336}
David Lamparter6b0655a2014-06-04 06:53:35 +02004337
paul718e3742002-12-13 20:15:29 +00004338int
4339peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004340 u_int32_t max, u_char threshold,
4341 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004342{
4343 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004344 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004345
4346 if (! peer->afc[afi][safi])
4347 return BGP_ERR_PEER_INACTIVE;
4348
4349 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4350 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004351 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004352 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004353 if (warning)
4354 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4355 else
4356 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4357
4358 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4359 return 0;
4360
4361 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004362 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004363 {
4364 if (! peer->af_group[afi][safi])
4365 continue;
4366
4367 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4368 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004369 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004370 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004371 if (warning)
4372 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4373 else
4374 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4375 }
4376 return 0;
4377}
4378
4379int
4380peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4381{
4382 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004383 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004384
4385 if (! peer->afc[afi][safi])
4386 return BGP_ERR_PEER_INACTIVE;
4387
4388 /* apply peer-group config */
4389 if (peer->af_group[afi][safi])
4390 {
4391 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4392 PEER_FLAG_MAX_PREFIX))
4393 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4394 else
4395 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4396
4397 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4398 PEER_FLAG_MAX_PREFIX_WARNING))
4399 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4400 else
4401 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4402
4403 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004404 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004405 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004406 return 0;
4407 }
4408
4409 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4410 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4411 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004412 peer->pmax_threshold[afi][safi] = 0;
4413 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004414
4415 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4416 return 0;
4417
4418 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004419 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004420 {
4421 if (! peer->af_group[afi][safi])
4422 continue;
4423
4424 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4425 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4426 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004427 peer->pmax_threshold[afi][safi] = 0;
4428 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004429 }
4430 return 0;
4431}
David Lamparter5f9adb52014-05-19 23:15:02 +02004432
4433static int is_ebgp_multihop_configured (struct peer *peer)
4434{
4435 struct peer_group *group;
4436 struct listnode *node, *nnode;
4437 struct peer *peer1;
4438
4439 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4440 {
4441 group = peer->group;
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004442 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4443 (group->conf->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004444 return 1;
4445
4446 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4447 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004448 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
4449 (peer1->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004450 return 1;
4451 }
4452 }
4453 else
4454 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004455 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4456 (peer->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004457 return 1;
4458 }
4459 return 0;
4460}
4461
Nick Hilliardfa411a22011-03-23 15:33:17 +00004462/* Set # of hops between us and BGP peer. */
4463int
4464peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4465{
4466 struct peer_group *group;
4467 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004468 int ret;
4469
4470 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4471
Nick Hilliardfa411a22011-03-23 15:33:17 +00004472 /* We cannot configure ttl-security hops when ebgp-multihop is already
4473 set. For non peer-groups, the check is simple. For peer-groups, it's
4474 slightly messy, because we need to check both the peer-group structure
4475 and all peer-group members for any trace of ebgp-multihop configuration
4476 before actually applying the ttl-security rules. Cisco really made a
4477 mess of this configuration parameter, and OpenBGPD got it right.
4478 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004479
David Lamparter5f9adb52014-05-19 23:15:02 +02004480 if (peer->gtsm_hops == 0)
4481 {
4482 if (is_ebgp_multihop_configured (peer))
4483 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004484
David Lamparter5f9adb52014-05-19 23:15:02 +02004485 /* specify MAXTTL on outgoing packets */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004486 /* Routine handles iBGP peers correctly */
David Lamparter5f9adb52014-05-19 23:15:02 +02004487 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4488 if (ret != 0)
4489 return ret;
4490 }
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004491
Nick Hilliardfa411a22011-03-23 15:33:17 +00004492 peer->gtsm_hops = gtsm_hops;
4493
Nick Hilliardfa411a22011-03-23 15:33:17 +00004494 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4495 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004496 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004497 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4498 }
4499 else
4500 {
4501 group = peer->group;
4502 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4503 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004504 peer->gtsm_hops = group->conf->gtsm_hops;
4505
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004506 /* Change setting of existing peer
4507 * established then change value (may break connectivity)
4508 * not established yet (teardown session and restart)
4509 * no session then do nothing (will get handled by next connection)
4510 */
4511 if (peer->status == Established)
4512 {
4513 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4514 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4515 MAXTTL + 1 - peer->gtsm_hops);
4516 }
4517 else if (peer->status < Established)
4518 {
4519 if (BGP_DEBUG (events, EVENTS))
4520 zlog_debug ("%s Min-ttl changed", peer->host);
4521 BGP_EVENT_ADD (peer, BGP_Stop);
4522 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004523 }
4524 }
4525
4526 return 0;
4527}
4528
4529int
4530peer_ttl_security_hops_unset (struct peer *peer)
4531{
4532 struct peer_group *group;
4533 struct listnode *node, *nnode;
4534 struct peer *opeer;
4535
4536 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4537
Nick Hilliardfa411a22011-03-23 15:33:17 +00004538 /* if a peer-group member, then reset to peer-group default rather than 0 */
4539 if (peer_group_active (peer))
4540 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4541 else
4542 peer->gtsm_hops = 0;
4543
4544 opeer = peer;
4545 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4546 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004547 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004548 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4549 }
4550 else
4551 {
4552 group = peer->group;
4553 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4554 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004555 peer->gtsm_hops = 0;
4556
4557 if (peer->fd >= 0)
4558 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4559 }
4560 }
4561
4562 return peer_ebgp_multihop_unset (opeer);
4563}
David Lamparter6b0655a2014-06-04 06:53:35 +02004564
paul718e3742002-12-13 20:15:29 +00004565int
4566peer_clear (struct peer *peer)
4567{
4568 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4569 {
hasso0a486e52005-02-01 20:57:17 +00004570 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4571 {
4572 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4573 if (peer->t_pmax_restart)
4574 {
4575 BGP_TIMER_OFF (peer->t_pmax_restart);
4576 if (BGP_DEBUG (events, EVENTS))
4577 zlog_debug ("%s Maximum-prefix restart timer canceled",
4578 peer->host);
4579 }
4580 BGP_EVENT_ADD (peer, BGP_Start);
4581 return 0;
4582 }
4583
paul718e3742002-12-13 20:15:29 +00004584 peer->v_start = BGP_INIT_START_TIMER;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00004585 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00004586 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4587 BGP_NOTIFY_CEASE_ADMIN_RESET);
4588 else
4589 BGP_EVENT_ADD (peer, BGP_Stop);
4590 }
4591 return 0;
4592}
4593
4594int
4595peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4596 enum bgp_clear_type stype)
4597{
4598 if (peer->status != Established)
4599 return 0;
4600
4601 if (! peer->afc[afi][safi])
4602 return BGP_ERR_AF_UNCONFIGURED;
4603
paulfee0f4c2004-09-13 05:12:46 +00004604 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4605 {
4606 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4607 return 0;
4608 bgp_check_local_routes_rsclient (peer, afi, safi);
4609 bgp_soft_reconfig_rsclient (peer, afi, safi);
4610 }
4611
paul718e3742002-12-13 20:15:29 +00004612 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4613 bgp_announce_route (peer, afi, safi);
4614
4615 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4616 {
4617 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4618 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4619 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4620 {
4621 struct bgp_filter *filter = &peer->filter[afi][safi];
4622 u_char prefix_type;
4623
4624 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4625 prefix_type = ORF_TYPE_PREFIX;
4626 else
4627 prefix_type = ORF_TYPE_PREFIX_OLD;
4628
4629 if (filter->plist[FILTER_IN].plist)
4630 {
4631 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4632 bgp_route_refresh_send (peer, afi, safi,
4633 prefix_type, REFRESH_DEFER, 1);
4634 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4635 REFRESH_IMMEDIATE, 0);
4636 }
4637 else
4638 {
4639 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4640 bgp_route_refresh_send (peer, afi, safi,
4641 prefix_type, REFRESH_IMMEDIATE, 1);
4642 else
4643 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4644 }
4645 return 0;
4646 }
4647 }
4648
4649 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4650 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4651 {
4652 /* If neighbor has soft reconfiguration inbound flag.
4653 Use Adj-RIB-In database. */
4654 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4655 bgp_soft_reconfig_in (peer, afi, safi);
4656 else
4657 {
4658 /* If neighbor has route refresh capability, send route refresh
4659 message to the peer. */
4660 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4661 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4662 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4663 else
4664 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4665 }
4666 }
4667 return 0;
4668}
David Lamparter6b0655a2014-06-04 06:53:35 +02004669
paulfd79ac92004-10-13 05:06:08 +00004670/* Display peer uptime.*/
4671/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004672char *
4673peer_uptime (time_t uptime2, char *buf, size_t len)
4674{
4675 time_t uptime1;
4676 struct tm *tm;
4677
4678 /* Check buffer length. */
4679 if (len < BGP_UPTIME_LEN)
4680 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004681 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004682 /* XXX: should return status instead of buf... */
4683 snprintf (buf, len, "<error> ");
4684 return buf;
paul718e3742002-12-13 20:15:29 +00004685 }
4686
4687 /* If there is no connection has been done before print `never'. */
4688 if (uptime2 == 0)
4689 {
4690 snprintf (buf, len, "never ");
4691 return buf;
4692 }
4693
4694 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004695 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004696 uptime1 -= uptime2;
4697 tm = gmtime (&uptime1);
Paul Jakma84c38402015-05-26 15:19:38 +01004698
paul718e3742002-12-13 20:15:29 +00004699 /* Making formatted timer strings. */
4700#define ONE_DAY_SECOND 60*60*24
Paul Jakma84c38402015-05-26 15:19:38 +01004701#define ONE_WEEK_SECOND ONE_DAY_SECOND*7
4702#define ONE_YEAR_SECOND ONE_DAY_SECOND*365
paul718e3742002-12-13 20:15:29 +00004703
4704 if (uptime1 < ONE_DAY_SECOND)
4705 snprintf (buf, len, "%02d:%02d:%02d",
4706 tm->tm_hour, tm->tm_min, tm->tm_sec);
4707 else if (uptime1 < ONE_WEEK_SECOND)
4708 snprintf (buf, len, "%dd%02dh%02dm",
4709 tm->tm_yday, tm->tm_hour, tm->tm_min);
Paul Jakma84c38402015-05-26 15:19:38 +01004710 else if (uptime1 < ONE_YEAR_SECOND)
paul718e3742002-12-13 20:15:29 +00004711 snprintf (buf, len, "%02dw%dd%02dh",
4712 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
Paul Jakma84c38402015-05-26 15:19:38 +01004713 else
4714 snprintf (buf, len, "%02dy%02dw%dd",
4715 tm->tm_year - 70, tm->tm_yday/7,
4716 tm->tm_yday - ((tm->tm_yday/7) * 7));
paul718e3742002-12-13 20:15:29 +00004717 return buf;
4718}
David Lamparter6b0655a2014-06-04 06:53:35 +02004719
paul94f2b392005-06-28 12:44:16 +00004720static void
paul718e3742002-12-13 20:15:29 +00004721bgp_config_write_filter (struct vty *vty, struct peer *peer,
4722 afi_t afi, safi_t safi)
4723{
4724 struct bgp_filter *filter;
4725 struct bgp_filter *gfilter = NULL;
4726 char *addr;
4727 int in = FILTER_IN;
4728 int out = FILTER_OUT;
4729
4730 addr = peer->host;
4731 filter = &peer->filter[afi][safi];
4732 if (peer->af_group[afi][safi])
4733 gfilter = &peer->group->conf->filter[afi][safi];
4734
4735 /* distribute-list. */
4736 if (filter->dlist[in].name)
4737 if (! gfilter || ! gfilter->dlist[in].name
4738 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4739 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4740 filter->dlist[in].name, VTY_NEWLINE);
4741 if (filter->dlist[out].name && ! gfilter)
4742 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4743 filter->dlist[out].name, VTY_NEWLINE);
4744
4745 /* prefix-list. */
4746 if (filter->plist[in].name)
4747 if (! gfilter || ! gfilter->plist[in].name
4748 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4749 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4750 filter->plist[in].name, VTY_NEWLINE);
4751 if (filter->plist[out].name && ! gfilter)
4752 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4753 filter->plist[out].name, VTY_NEWLINE);
4754
4755 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004756 if (filter->map[RMAP_IN].name)
4757 if (! gfilter || ! gfilter->map[RMAP_IN].name
4758 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004759 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004760 filter->map[RMAP_IN].name, VTY_NEWLINE);
4761 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004762 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004763 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4764 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4765 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4766 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4767 if (filter->map[RMAP_EXPORT].name)
4768 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4769 || strcmp (filter->map[RMAP_EXPORT].name,
4770 gfilter->map[RMAP_EXPORT].name) != 0)
4771 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4772 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004773
4774 /* unsuppress-map */
4775 if (filter->usmap.name && ! gfilter)
4776 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4777 filter->usmap.name, VTY_NEWLINE);
4778
4779 /* filter-list. */
4780 if (filter->aslist[in].name)
4781 if (! gfilter || ! gfilter->aslist[in].name
4782 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4783 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4784 filter->aslist[in].name, VTY_NEWLINE);
4785 if (filter->aslist[out].name && ! gfilter)
4786 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4787 filter->aslist[out].name, VTY_NEWLINE);
4788}
4789
4790/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004791static void
paul718e3742002-12-13 20:15:29 +00004792bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4793 struct peer *peer, afi_t afi, safi_t safi)
4794{
paul718e3742002-12-13 20:15:29 +00004795 struct peer *g_peer = NULL;
4796 char buf[SU_ADDRSTRLEN];
4797 char *addr;
4798
paul718e3742002-12-13 20:15:29 +00004799 addr = peer->host;
4800 if (peer_group_active (peer))
4801 g_peer = peer->group->conf;
4802
4803 /************************************
4804 ****** Global to the neighbor ******
4805 ************************************/
4806 if (afi == AFI_IP && safi == SAFI_UNICAST)
4807 {
4808 /* remote-as. */
4809 if (! peer_group_active (peer))
4810 {
4811 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4812 vty_out (vty, " neighbor %s peer-group%s", addr,
4813 VTY_NEWLINE);
4814 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004815 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004816 VTY_NEWLINE);
4817 }
4818 else
4819 {
4820 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004821 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004822 VTY_NEWLINE);
4823 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4824 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4825 peer->group->name, VTY_NEWLINE);
4826 }
4827
4828 /* local-as. */
4829 if (peer->change_local_as)
4830 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00004831 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004832 peer->change_local_as,
4833 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00004834 " no-prepend" : "",
4835 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
4836 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004837
4838 /* Description. */
4839 if (peer->desc)
4840 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4841 VTY_NEWLINE);
4842
4843 /* Shutdown. */
4844 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4845 if (! peer_group_active (peer) ||
4846 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4847 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4848
Paul Jakma0df7c912008-07-21 21:02:49 +00004849 /* Password. */
4850 if (peer->password)
4851 if (!peer_group_active (peer)
4852 || ! g_peer->password
4853 || strcmp (peer->password, g_peer->password) != 0)
4854 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4855 VTY_NEWLINE);
4856
paul718e3742002-12-13 20:15:29 +00004857 /* BGP port. */
4858 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004859 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004860 VTY_NEWLINE);
4861
4862 /* Local interface name. */
4863 if (peer->ifname)
4864 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4865 VTY_NEWLINE);
4866
4867 /* Passive. */
4868 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4869 if (! peer_group_active (peer) ||
4870 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4871 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4872
4873 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004874 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00004875 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00004876 if (! peer_group_active (peer) ||
4877 g_peer->ttl != peer->ttl)
4878 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4879 VTY_NEWLINE);
4880
Nick Hilliardfa411a22011-03-23 15:33:17 +00004881 /* ttl-security hops */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004882 if (peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004883 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004884 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00004885 peer->gtsm_hops, VTY_NEWLINE);
4886
hasso6ffd2072005-02-02 14:50:11 +00004887 /* disable-connected-check. */
4888 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004889 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004890 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4891 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004892
4893 /* Update-source. */
4894 if (peer->update_if)
4895 if (! peer_group_active (peer) || ! g_peer->update_if
4896 || strcmp (g_peer->update_if, peer->update_if) != 0)
4897 vty_out (vty, " neighbor %s update-source %s%s", addr,
4898 peer->update_if, VTY_NEWLINE);
4899 if (peer->update_source)
4900 if (! peer_group_active (peer) || ! g_peer->update_source
4901 || sockunion_cmp (g_peer->update_source,
4902 peer->update_source) != 0)
4903 vty_out (vty, " neighbor %s update-source %s%s", addr,
4904 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4905 VTY_NEWLINE);
4906
paul718e3742002-12-13 20:15:29 +00004907 /* advertisement-interval */
4908 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4909 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4910 addr, peer->v_routeadv, VTY_NEWLINE);
4911
4912 /* timers. */
4913 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4914 && ! peer_group_active (peer))
4915 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4916 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4917
4918 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4919 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4920 peer->connect, VTY_NEWLINE);
4921
4922 /* Default weight. */
4923 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4924 if (! peer_group_active (peer) ||
4925 g_peer->weight != peer->weight)
4926 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4927 VTY_NEWLINE);
4928
paul718e3742002-12-13 20:15:29 +00004929 /* Dynamic capability. */
4930 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4931 if (! peer_group_active (peer) ||
4932 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4933 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4934 VTY_NEWLINE);
4935
4936 /* dont capability negotiation. */
4937 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4938 if (! peer_group_active (peer) ||
4939 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4940 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4941 VTY_NEWLINE);
4942
4943 /* override capability negotiation. */
4944 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4945 if (! peer_group_active (peer) ||
4946 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4947 vty_out (vty, " neighbor %s override-capability%s", addr,
4948 VTY_NEWLINE);
4949
4950 /* strict capability negotiation. */
4951 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4952 if (! peer_group_active (peer) ||
4953 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4954 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4955 VTY_NEWLINE);
4956
Christian Franke15c71342012-11-19 11:17:31 +00004957 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
paul718e3742002-12-13 20:15:29 +00004958 {
4959 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4960 {
4961 if (peer->afc[AFI_IP][SAFI_UNICAST])
4962 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4963 }
4964 else
4965 {
4966 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4967 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4968 }
4969 }
4970 }
4971
4972
4973 /************************************
4974 ****** Per AF to the neighbor ******
4975 ************************************/
4976
4977 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4978 {
4979 if (peer->af_group[afi][safi])
4980 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4981 peer->group->name, VTY_NEWLINE);
4982 else
4983 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4984 }
4985
4986 /* ORF capability. */
4987 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4988 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4989 if (! peer->af_group[afi][safi])
4990 {
4991 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4992
4993 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4994 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4995 vty_out (vty, " both");
4996 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4997 vty_out (vty, " send");
4998 else
4999 vty_out (vty, " receive");
5000 vty_out (vty, "%s", VTY_NEWLINE);
5001 }
5002
5003 /* Route reflector client. */
5004 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
5005 && ! peer->af_group[afi][safi])
5006 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
5007 VTY_NEWLINE);
5008
5009 /* Nexthop self. */
5010 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
5011 && ! peer->af_group[afi][safi])
Timo Teräs9e7a53c2014-04-24 10:22:37 +03005012 vty_out (vty, " neighbor %s next-hop-self%s%s", addr,
5013 peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ?
5014 " all" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005015
5016 /* Remove private AS. */
5017 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
5018 && ! peer->af_group[afi][safi])
5019 vty_out (vty, " neighbor %s remove-private-AS%s",
5020 addr, VTY_NEWLINE);
5021
5022 /* send-community print. */
5023 if (! peer->af_group[afi][safi])
5024 {
5025 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5026 {
5027 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5028 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5029 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
5030 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5031 vty_out (vty, " neighbor %s send-community extended%s",
5032 addr, VTY_NEWLINE);
5033 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5034 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
5035 }
5036 else
5037 {
5038 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5039 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5040 vty_out (vty, " no neighbor %s send-community both%s",
5041 addr, VTY_NEWLINE);
5042 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5043 vty_out (vty, " no neighbor %s send-community extended%s",
5044 addr, VTY_NEWLINE);
5045 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5046 vty_out (vty, " no neighbor %s send-community%s",
5047 addr, VTY_NEWLINE);
5048 }
5049 }
5050
5051 /* Default information */
5052 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5053 && ! peer->af_group[afi][safi])
5054 {
5055 vty_out (vty, " neighbor %s default-originate", addr);
5056 if (peer->default_rmap[afi][safi].name)
5057 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5058 vty_out (vty, "%s", VTY_NEWLINE);
5059 }
5060
5061 /* Soft reconfiguration inbound. */
5062 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5063 if (! peer->af_group[afi][safi] ||
5064 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5065 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5066 VTY_NEWLINE);
5067
5068 /* maximum-prefix. */
5069 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5070 if (! peer->af_group[afi][safi]
5071 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005072 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005073 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5074 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005075 {
hasso0a486e52005-02-01 20:57:17 +00005076 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5077 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5078 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5079 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5080 vty_out (vty, " warning-only");
5081 if (peer->pmax_restart[afi][safi])
5082 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5083 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005084 }
paul718e3742002-12-13 20:15:29 +00005085
5086 /* Route server client. */
5087 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5088 && ! peer->af_group[afi][safi])
5089 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5090
Dylan Hall3cf12882011-10-27 15:28:17 +04005091 /* Nexthop-local unchanged. */
5092 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5093 && ! peer->af_group[afi][safi])
5094 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5095
paul718e3742002-12-13 20:15:29 +00005096 /* Allow AS in. */
5097 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5098 if (! peer_group_active (peer)
5099 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5100 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5101 {
5102 if (peer->allowas_in[afi][safi] == 3)
5103 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5104 else
5105 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5106 peer->allowas_in[afi][safi], VTY_NEWLINE);
5107 }
5108
5109 /* Filter. */
5110 bgp_config_write_filter (vty, peer, afi, safi);
5111
5112 /* atribute-unchanged. */
5113 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5114 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5115 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5116 && ! peer->af_group[afi][safi])
5117 {
5118 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5119 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5120 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5121 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5122 else
5123 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5124 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5125 " as-path" : "",
5126 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5127 " next-hop" : "",
5128 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5129 " med" : "", VTY_NEWLINE);
5130 }
5131}
5132
5133/* Display "address-family" configuration header. */
5134void
5135bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5136 int *write)
5137{
5138 if (*write)
5139 return;
5140
5141 if (afi == AFI_IP && safi == SAFI_UNICAST)
5142 return;
5143
5144 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5145
5146 if (afi == AFI_IP)
5147 {
5148 if (safi == SAFI_MULTICAST)
5149 vty_out (vty, "ipv4 multicast");
5150 else if (safi == SAFI_MPLS_VPN)
5151 vty_out (vty, "vpnv4 unicast");
5152 }
5153 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005154 {
5155 vty_out (vty, "ipv6");
5156
5157 if (safi == SAFI_MULTICAST)
5158 vty_out (vty, " multicast");
5159 }
paul718e3742002-12-13 20:15:29 +00005160
5161 vty_out (vty, "%s", VTY_NEWLINE);
5162
5163 *write = 1;
5164}
5165
5166/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005167static int
paul718e3742002-12-13 20:15:29 +00005168bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5169 safi_t safi)
5170{
5171 int write = 0;
5172 struct peer *peer;
5173 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005174 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005175
5176 bgp_config_write_network (vty, bgp, afi, safi, &write);
5177
5178 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5179
paul1eb8ef22005-04-07 07:30:20 +00005180 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005181 {
5182 if (group->conf->afc[afi][safi])
5183 {
5184 bgp_config_write_family_header (vty, afi, safi, &write);
5185 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5186 }
5187 }
paul1eb8ef22005-04-07 07:30:20 +00005188 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005189 {
5190 if (peer->afc[afi][safi])
5191 {
5192 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5193 {
5194 bgp_config_write_family_header (vty, afi, safi, &write);
5195 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5196 }
5197 }
5198 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005199
5200 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5201
paul718e3742002-12-13 20:15:29 +00005202 if (write)
5203 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5204
5205 return write;
5206}
5207
5208int
5209bgp_config_write (struct vty *vty)
5210{
5211 int write = 0;
5212 struct bgp *bgp;
5213 struct peer_group *group;
5214 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005215 struct listnode *node, *nnode;
5216 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005217
5218 /* BGP Multiple instance. */
5219 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5220 {
5221 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5222 write++;
5223 }
5224
5225 /* BGP Config type. */
5226 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5227 {
5228 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5229 write++;
5230 }
5231
5232 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005233 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005234 {
5235 if (write)
5236 vty_out (vty, "!%s", VTY_NEWLINE);
5237
5238 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005239 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005240
5241 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5242 {
5243 if (bgp->name)
5244 vty_out (vty, " view %s", bgp->name);
5245 }
5246 vty_out (vty, "%s", VTY_NEWLINE);
5247
5248 /* No Synchronization */
5249 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5250 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5251
5252 /* BGP fast-external-failover. */
5253 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5254 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5255
5256 /* BGP router ID. */
5257 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5258 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5259 VTY_NEWLINE);
5260
paul848973c2003-08-13 00:32:49 +00005261 /* BGP log-neighbor-changes. */
5262 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5263 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
5264
paul718e3742002-12-13 20:15:29 +00005265 /* BGP configuration. */
5266 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5267 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5268
5269 /* BGP default ipv4-unicast. */
5270 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5271 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5272
5273 /* BGP default local-preference. */
5274 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5275 vty_out (vty, " bgp default local-preference %d%s",
5276 bgp->default_local_pref, VTY_NEWLINE);
5277
5278 /* BGP client-to-client reflection. */
5279 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5280 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5281
5282 /* BGP cluster ID. */
5283 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5284 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5285 VTY_NEWLINE);
5286
hassoe0701b72004-05-20 09:19:34 +00005287 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005288 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005289 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5290 VTY_NEWLINE);
5291
5292 /* Confederation peer */
5293 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005294 {
hassoe0701b72004-05-20 09:19:34 +00005295 int i;
paul718e3742002-12-13 20:15:29 +00005296
hassoe0701b72004-05-20 09:19:34 +00005297 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005298
hassoe0701b72004-05-20 09:19:34 +00005299 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005300 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005301
hassoe0701b72004-05-20 09:19:34 +00005302 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005303 }
5304
5305 /* BGP enforce-first-as. */
5306 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5307 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5308
5309 /* BGP deterministic-med. */
5310 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5311 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005312
5313 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005314 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5315 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5316 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005317 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5318 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5319
paul718e3742002-12-13 20:15:29 +00005320 /* BGP bestpath method. */
5321 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5322 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005323 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5324 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
Pradosh Mohapatra2fdd4552013-09-07 07:02:36 +00005325 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
5326 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
5327 }
paul718e3742002-12-13 20:15:29 +00005328 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5329 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5330 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5331 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5332 {
5333 vty_out (vty, " bgp bestpath med");
5334 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5335 vty_out (vty, " confed");
5336 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5337 vty_out (vty, " missing-as-worst");
5338 vty_out (vty, "%s", VTY_NEWLINE);
5339 }
5340
5341 /* BGP network import check. */
5342 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5343 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5344
5345 /* BGP scan interval. */
5346 bgp_config_write_scan_time (vty);
5347
5348 /* BGP flag dampening. */
5349 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5350 BGP_CONFIG_DAMPENING))
5351 bgp_config_write_damp (vty);
5352
5353 /* BGP static route configuration. */
5354 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5355
5356 /* BGP redistribute configuration. */
5357 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5358
5359 /* BGP timers configuration. */
5360 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5361 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5362 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5363 bgp->default_holdtime, VTY_NEWLINE);
5364
5365 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005366 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005367 {
5368 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5369 }
5370
5371 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005372 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005373 {
5374 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5375 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5376 }
5377
Josh Bailey165b5ff2011-07-20 20:43:22 -07005378 /* maximum-paths */
5379 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5380
paul718e3742002-12-13 20:15:29 +00005381 /* Distance configuration. */
5382 bgp_config_write_distance (vty, bgp);
5383
5384 /* No auto-summary */
5385 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5386 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5387
5388 /* IPv4 multicast configuration. */
5389 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5390
5391 /* IPv4 VPN configuration. */
5392 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5393
5394 /* IPv6 unicast configuration. */
5395 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5396
Paul Jakma37a217a2007-04-10 19:20:29 +00005397 /* IPv6 multicast configuration. */
5398 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5399
paul718e3742002-12-13 20:15:29 +00005400 write++;
5401 }
5402 return write;
5403}
5404
5405void
paul94f2b392005-06-28 12:44:16 +00005406bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005407{
5408 memset (&bgp_master, 0, sizeof (struct bgp_master));
5409
5410 bm = &bgp_master;
5411 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005412 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005413 bm->port = BGP_PORT_DEFAULT;
5414 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005415 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005416}
paul200df112005-06-01 11:17:05 +00005417
David Lamparter6b0655a2014-06-04 06:53:35 +02005418
paul718e3742002-12-13 20:15:29 +00005419void
paul94f2b392005-06-28 12:44:16 +00005420bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005421{
paul718e3742002-12-13 20:15:29 +00005422 /* BGP VTY commands installation. */
5423 bgp_vty_init ();
5424
paul718e3742002-12-13 20:15:29 +00005425 /* Init zebra. */
Donald Sharp774914f2015-10-14 08:50:39 -04005426 bgp_zebra_init (bm->master);
paul718e3742002-12-13 20:15:29 +00005427
5428 /* BGP inits. */
5429 bgp_attr_init ();
5430 bgp_debug_init ();
5431 bgp_dump_init ();
5432 bgp_route_init ();
5433 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005434 bgp_address_init ();
paul718e3742002-12-13 20:15:29 +00005435 bgp_scan_init ();
5436 bgp_mplsvpn_init ();
5437
5438 /* Access list initialize. */
5439 access_list_init ();
5440 access_list_add_hook (peer_distribute_update);
5441 access_list_delete_hook (peer_distribute_update);
5442
5443 /* Filter list initialize. */
5444 bgp_filter_init ();
5445 as_list_add_hook (peer_aslist_update);
5446 as_list_delete_hook (peer_aslist_update);
5447
5448 /* Prefix list initialize.*/
5449 prefix_list_init ();
5450 prefix_list_add_hook (peer_prefix_list_update);
5451 prefix_list_delete_hook (peer_prefix_list_update);
5452
5453 /* Community list initialize. */
5454 bgp_clist = community_list_init ();
5455
5456#ifdef HAVE_SNMP
5457 bgp_snmp_init ();
5458#endif /* HAVE_SNMP */
5459}
paul545acaf2004-04-20 15:13:15 +00005460
5461void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005462bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005463{
paul545acaf2004-04-20 15:13:15 +00005464 struct bgp *bgp;
5465 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005466 struct listnode *node, *nnode;
5467 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005468
paul1eb8ef22005-04-07 07:30:20 +00005469 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5470 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005471 if (peer->status == Established)
5472 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5473 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005474
paul545acaf2004-04-20 15:13:15 +00005475 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005476
paule210cf92005-06-15 19:15:35 +00005477 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005478 {
5479 work_queue_free (bm->process_main_queue);
5480 bm->process_main_queue = NULL;
5481 }
paule210cf92005-06-15 19:15:35 +00005482 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005483 {
5484 work_queue_free (bm->process_rsclient_queue);
5485 bm->process_rsclient_queue = NULL;
5486 }
paul545acaf2004-04-20 15:13:15 +00005487}