blob: 3a9bc480a25d707e8d9d7a1d4725b7eacd53c1f1 [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);
598 prefix_bgp_orf_remove_all (orf_name);
599
600 /* Set default neighbor send-community. */
601 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
602 {
603 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
604 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
605 }
606
607 /* Clear neighbor default_originate_rmap */
608 if (peer->default_rmap[afi][safi].name)
609 free (peer->default_rmap[afi][safi].name);
610 peer->default_rmap[afi][safi].name = NULL;
611 peer->default_rmap[afi][safi].map = NULL;
612
613 /* Clear neighbor maximum-prefix */
614 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +0000615 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000616}
617
618/* peer global config reset */
paul94f2b392005-06-28 12:44:16 +0000619static void
paul718e3742002-12-13 20:15:29 +0000620peer_global_config_reset (struct peer *peer)
621{
622 peer->weight = 0;
623 peer->change_local_as = 0;
624 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
625 if (peer->update_source)
626 {
627 sockunion_free (peer->update_source);
628 peer->update_source = NULL;
629 }
630 if (peer->update_if)
631 {
632 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
633 peer->update_if = NULL;
634 }
635
636 if (peer_sort (peer) == BGP_PEER_IBGP)
637 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
638 else
639 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
640
641 peer->flags = 0;
642 peer->config = 0;
643 peer->holdtime = 0;
644 peer->keepalive = 0;
645 peer->connect = 0;
646 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
647}
648
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000649/* Check peer's AS number and determines if this peer is IBGP or EBGP */
650static bgp_peer_sort_t
651peer_calc_sort (struct peer *peer)
paul718e3742002-12-13 20:15:29 +0000652{
653 struct bgp *bgp;
654
655 bgp = peer->bgp;
656
657 /* Peer-group */
658 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
659 {
660 if (peer->as)
661 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
662 else
663 {
664 struct peer *peer1;
665 peer1 = listnode_head (peer->group->peer);
666 if (peer1)
667 return (peer1->local_as == peer1->as
668 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
669 }
670 return BGP_PEER_INTERNAL;
671 }
672
673 /* Normal peer */
674 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
675 {
676 if (peer->local_as == 0)
677 return BGP_PEER_INTERNAL;
678
679 if (peer->local_as == peer->as)
680 {
681 if (peer->local_as == bgp->confed_id)
682 return BGP_PEER_EBGP;
683 else
684 return BGP_PEER_IBGP;
685 }
686
687 if (bgp_confederation_peers_check (bgp, peer->as))
688 return BGP_PEER_CONFED;
689
690 return BGP_PEER_EBGP;
691 }
692 else
693 {
694 return (peer->local_as == 0
695 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
696 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
697 }
698}
699
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000700/* Calculate and cache the peer "sort" */
701bgp_peer_sort_t
702peer_sort (struct peer *peer)
703{
704 peer->sort = peer_calc_sort (peer);
705 return peer->sort;
706}
707
Paul Jakmaf63f06d2011-04-08 12:44:43 +0100708static void
paul200df112005-06-01 11:17:05 +0000709peer_free (struct peer *peer)
710{
Paul Jakmaca058a32006-09-14 02:58:49 +0000711 assert (peer->status == Deleted);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700712
713 bgp_unlock(peer->bgp);
714
Paul Jakmaca058a32006-09-14 02:58:49 +0000715 /* this /ought/ to have been done already through bgp_stop earlier,
716 * but just to be sure..
717 */
718 bgp_timer_set (peer);
719 BGP_READ_OFF (peer->t_read);
720 BGP_WRITE_OFF (peer->t_write);
Paul Jakma9fde6622006-09-14 03:02:02 +0000721 BGP_EVENT_FLUSH (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +0000722
paul200df112005-06-01 11:17:05 +0000723 if (peer->desc)
724 XFREE (MTYPE_PEER_DESC, peer->desc);
725
726 /* Free allocated host character. */
727 if (peer->host)
728 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
729
730 /* Update source configuration. */
731 if (peer->update_source)
732 sockunion_free (peer->update_source);
733
734 if (peer->update_if)
735 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
Paul Jakmaa625ca32006-03-30 14:12:38 +0000736
737 if (peer->clear_node_queue)
738 work_queue_free (peer->clear_node_queue);
739
Paul Jakmaca058a32006-09-14 02:58:49 +0000740 bgp_sync_delete (peer);
paul200df112005-06-01 11:17:05 +0000741 memset (peer, 0, sizeof (struct peer));
742
743 XFREE (MTYPE_BGP_PEER, peer);
744}
745
746/* increase reference count on a struct peer */
747struct peer *
748peer_lock (struct peer *peer)
749{
750 assert (peer && (peer->lock >= 0));
Paul Jakmaca058a32006-09-14 02:58:49 +0000751
paul200df112005-06-01 11:17:05 +0000752 peer->lock++;
753
754 return peer;
755}
756
757/* decrease reference count on a struct peer
758 * struct peer is freed and NULL returned if last reference
759 */
760struct peer *
761peer_unlock (struct peer *peer)
762{
763 assert (peer && (peer->lock > 0));
764
765 peer->lock--;
766
767 if (peer->lock == 0)
768 {
769#if 0
770 zlog_debug ("unlocked and freeing");
771 zlog_backtrace (LOG_DEBUG);
772#endif
773 peer_free (peer);
774 return NULL;
775 }
776
777#if 0
778 if (peer->lock == 1)
779 {
780 zlog_debug ("unlocked to 1");
781 zlog_backtrace (LOG_DEBUG);
782 }
783#endif
784
785 return peer;
786}
787
788/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000789static struct peer *
Paul Jakma6f585442006-10-22 19:13:07 +0000790peer_new (struct bgp *bgp)
paul718e3742002-12-13 20:15:29 +0000791{
792 afi_t afi;
793 safi_t safi;
794 struct peer *peer;
795 struct servent *sp;
Paul Jakma6f585442006-10-22 19:13:07 +0000796
797 /* bgp argument is absolutely required */
798 assert (bgp);
799 if (!bgp)
800 return NULL;
801
paul718e3742002-12-13 20:15:29 +0000802 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000803 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000804
805 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000806 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000807 peer->v_start = BGP_INIT_START_TIMER;
808 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
809 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
810 peer->status = Idle;
811 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000812 peer->weight = 0;
Paul Jakma0df7c912008-07-21 21:02:49 +0000813 peer->password = NULL;
Paul Jakma6f585442006-10-22 19:13:07 +0000814 peer->bgp = bgp;
Paul Jakmaca058a32006-09-14 02:58:49 +0000815 peer = peer_lock (peer); /* initial reference */
Stephen Hemminger0088b5d2009-05-21 08:51:03 -0700816 bgp_lock (bgp);
paul718e3742002-12-13 20:15:29 +0000817
818 /* Set default flags. */
819 for (afi = AFI_IP; afi < AFI_MAX; afi++)
820 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
821 {
822 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
823 {
824 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
825 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
826 }
827 peer->orf_plist[afi][safi] = NULL;
828 }
829 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
830
831 /* Create buffers. */
832 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
833 peer->obuf = stream_fifo_new ();
834 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000835 peer->scratch = stream_new (BGP_MAX_PACKET_SIZE);
paul718e3742002-12-13 20:15:29 +0000836
837 bgp_sync_init (peer);
838
839 /* Get service port number. */
840 sp = getservbyname ("bgp", "tcp");
841 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
842
843 return peer;
844}
845
846/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000847static struct peer *
paul718e3742002-12-13 20:15:29 +0000848peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
849 as_t remote_as, afi_t afi, safi_t safi)
850{
851 int active;
852 struct peer *peer;
853 char buf[SU_ADDRSTRLEN];
854
Paul Jakma6f585442006-10-22 19:13:07 +0000855 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000856 peer->su = *su;
857 peer->local_as = local_as;
858 peer->as = remote_as;
859 peer->local_id = bgp->router_id;
860 peer->v_holdtime = bgp->default_holdtime;
861 peer->v_keepalive = bgp->default_keepalive;
862 if (peer_sort (peer) == BGP_PEER_IBGP)
863 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
864 else
865 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000866
867 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000868 listnode_add_sort (bgp->peer, peer);
869
870 active = peer_active (peer);
871
872 if (afi && safi)
873 peer->afc[afi][safi] = 1;
874
Stephen Hemminger65957882010-01-15 16:22:10 +0300875 /* Last read and reset time set */
876 peer->readtime = peer->resettime = bgp_clock ();
paul848973c2003-08-13 00:32:49 +0000877
paul718e3742002-12-13 20:15:29 +0000878 /* Default TTL set. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000879 peer->ttl = (peer->sort == BGP_PEER_IBGP) ? 255 : 1;
paul718e3742002-12-13 20:15:29 +0000880
881 /* Make peer's address string. */
882 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000883 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000884
885 /* Set up peer's events and timers. */
886 if (! active && peer_active (peer))
887 bgp_timer_set (peer);
888
889 return peer;
890}
891
pauleb821182004-05-01 08:44:08 +0000892/* Make accept BGP peer. Called from bgp_accept (). */
893struct peer *
894peer_create_accept (struct bgp *bgp)
895{
896 struct peer *peer;
897
Paul Jakma6f585442006-10-22 19:13:07 +0000898 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000899
900 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000901 listnode_add_sort (bgp->peer, peer);
902
903 return peer;
904}
905
paul718e3742002-12-13 20:15:29 +0000906/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000907static void
paul718e3742002-12-13 20:15:29 +0000908peer_as_change (struct peer *peer, as_t as)
909{
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000910 bgp_peer_sort_t type;
paul718e3742002-12-13 20:15:29 +0000911
912 /* Stop peer. */
913 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
914 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +0000915 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +0000916 {
917 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
918 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
919 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
920 }
paul718e3742002-12-13 20:15:29 +0000921 else
922 BGP_EVENT_ADD (peer, BGP_Stop);
923 }
924 type = peer_sort (peer);
925 peer->as = as;
926
paul848973c2003-08-13 00:32:49 +0000927 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
928 && ! bgp_confederation_peers_check (peer->bgp, as)
929 && peer->bgp->as != as)
930 peer->local_as = peer->bgp->confed_id;
931 else
932 peer->local_as = peer->bgp->as;
933
paul718e3742002-12-13 20:15:29 +0000934 /* Advertisement-interval reset */
935 if (peer_sort (peer) == BGP_PEER_IBGP)
936 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
937 else
938 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
939
940 /* TTL reset */
941 if (peer_sort (peer) == BGP_PEER_IBGP)
942 peer->ttl = 255;
943 else if (type == BGP_PEER_IBGP)
944 peer->ttl = 1;
945
946 /* reflector-client reset */
947 if (peer_sort (peer) != BGP_PEER_IBGP)
948 {
949 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
950 PEER_FLAG_REFLECTOR_CLIENT);
951 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
952 PEER_FLAG_REFLECTOR_CLIENT);
953 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
954 PEER_FLAG_REFLECTOR_CLIENT);
955 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
956 PEER_FLAG_REFLECTOR_CLIENT);
957 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
958 PEER_FLAG_REFLECTOR_CLIENT);
959 }
960
961 /* local-as reset */
962 if (peer_sort (peer) != BGP_PEER_EBGP)
963 {
964 peer->change_local_as = 0;
965 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +0000966 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +0000967 }
968}
969
970/* If peer does not exist, create new one. If peer already exists,
971 set AS number to the peer. */
972int
973peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
974 afi_t afi, safi_t safi)
975{
976 struct peer *peer;
977 as_t local_as;
978
979 peer = peer_lookup (bgp, su);
980
981 if (peer)
982 {
983 /* When this peer is a member of peer-group. */
984 if (peer->group)
985 {
986 if (peer->group->conf->as)
987 {
988 /* Return peer group's AS number. */
989 *as = peer->group->conf->as;
990 return BGP_ERR_PEER_GROUP_MEMBER;
991 }
992 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
993 {
994 if (bgp->as != *as)
995 {
996 *as = peer->as;
997 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
998 }
999 }
1000 else
1001 {
1002 if (bgp->as == *as)
1003 {
1004 *as = peer->as;
1005 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1006 }
1007 }
1008 }
1009
1010 /* Existing peer's AS number change. */
1011 if (peer->as != *as)
1012 peer_as_change (peer, *as);
1013 }
1014 else
1015 {
1016
1017 /* If the peer is not part of our confederation, and its not an
1018 iBGP peer then spoof the source AS */
1019 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1020 && ! bgp_confederation_peers_check (bgp, *as)
1021 && bgp->as != *as)
1022 local_as = bgp->confed_id;
1023 else
1024 local_as = bgp->as;
1025
1026 /* If this is IPv4 unicast configuration and "no bgp default
1027 ipv4-unicast" is specified. */
1028
1029 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1030 && afi == AFI_IP && safi == SAFI_UNICAST)
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001031 peer_create (su, bgp, local_as, *as, 0, 0);
paul718e3742002-12-13 20:15:29 +00001032 else
Paul Jakmab2dd59e2014-09-19 15:34:48 +01001033 peer_create (su, bgp, local_as, *as, afi, safi);
paul718e3742002-12-13 20:15:29 +00001034 }
1035
1036 return 0;
1037}
1038
1039/* Activate the peer or peer group for specified AFI and SAFI. */
1040int
1041peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1042{
1043 int active;
1044
1045 if (peer->afc[afi][safi])
1046 return 0;
1047
1048 /* Activate the address family configuration. */
1049 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1050 peer->afc[afi][safi] = 1;
1051 else
1052 {
1053 active = peer_active (peer);
1054
1055 peer->afc[afi][safi] = 1;
1056
1057 if (! active && peer_active (peer))
1058 bgp_timer_set (peer);
1059 else
1060 {
1061 if (peer->status == Established)
1062 {
1063 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1064 {
1065 peer->afc_adv[afi][safi] = 1;
1066 bgp_capability_send (peer, afi, safi,
1067 CAPABILITY_CODE_MP,
1068 CAPABILITY_ACTION_SET);
1069 if (peer->afc_recv[afi][safi])
1070 {
1071 peer->afc_nego[afi][safi] = 1;
1072 bgp_announce_route (peer, afi, safi);
1073 }
1074 }
1075 else
hassoe0701b72004-05-20 09:19:34 +00001076 {
1077 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1078 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1079 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1080 }
paul718e3742002-12-13 20:15:29 +00001081 }
1082 }
1083 }
1084 return 0;
1085}
1086
1087int
1088peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1089{
1090 struct peer_group *group;
1091 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001092 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001093
1094 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1095 {
1096 group = peer->group;
1097
paul1eb8ef22005-04-07 07:30:20 +00001098 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001099 {
1100 if (peer1->af_group[afi][safi])
1101 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1102 }
1103 }
1104 else
1105 {
1106 if (peer->af_group[afi][safi])
1107 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1108 }
1109
1110 if (! peer->afc[afi][safi])
1111 return 0;
1112
1113 /* De-activate the address family configuration. */
1114 peer->afc[afi][safi] = 0;
1115 peer_af_flag_reset (peer, afi, safi);
1116
1117 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1118 {
1119 if (peer->status == Established)
1120 {
1121 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1122 {
1123 peer->afc_adv[afi][safi] = 0;
1124 peer->afc_nego[afi][safi] = 0;
1125
1126 if (peer_active_nego (peer))
1127 {
1128 bgp_capability_send (peer, afi, safi,
1129 CAPABILITY_CODE_MP,
1130 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001131 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001132 peer->pcount[afi][safi] = 0;
1133 }
1134 else
hassoe0701b72004-05-20 09:19:34 +00001135 {
1136 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1137 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1138 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1139 }
paul718e3742002-12-13 20:15:29 +00001140 }
1141 else
hassoe0701b72004-05-20 09:19:34 +00001142 {
1143 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1144 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1145 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1146 }
paul718e3742002-12-13 20:15:29 +00001147 }
1148 }
1149 return 0;
1150}
1151
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001152static void
hasso93406d82005-02-02 14:40:33 +00001153peer_nsf_stop (struct peer *peer)
1154{
1155 afi_t afi;
1156 safi_t safi;
1157
1158 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1159 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1160
1161 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +04001162 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +00001163 peer->nsf[afi][safi] = 0;
1164
1165 if (peer->t_gr_restart)
1166 {
1167 BGP_TIMER_OFF (peer->t_gr_restart);
1168 if (BGP_DEBUG (events, EVENTS))
1169 zlog_debug ("%s graceful restart timer stopped", peer->host);
1170 }
1171 if (peer->t_gr_stale)
1172 {
1173 BGP_TIMER_OFF (peer->t_gr_stale);
1174 if (BGP_DEBUG (events, EVENTS))
1175 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1176 }
1177 bgp_clear_route_all (peer);
1178}
1179
Paul Jakmaca058a32006-09-14 02:58:49 +00001180/* Delete peer from confguration.
1181 *
1182 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1183 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1184 *
1185 * This function /should/ take care to be idempotent, to guard against
1186 * it being called multiple times through stray events that come in
1187 * that happen to result in this function being called again. That
1188 * said, getting here for a "Deleted" peer is a bug in the neighbour
1189 * FSM.
1190 */
paul718e3742002-12-13 20:15:29 +00001191int
1192peer_delete (struct peer *peer)
1193{
1194 int i;
1195 afi_t afi;
1196 safi_t safi;
1197 struct bgp *bgp;
1198 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001199 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001200
Paul Jakmaca058a32006-09-14 02:58:49 +00001201 assert (peer->status != Deleted);
1202
paul718e3742002-12-13 20:15:29 +00001203 bgp = peer->bgp;
1204
hasso93406d82005-02-02 14:40:33 +00001205 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1206 peer_nsf_stop (peer);
1207
Chris Caputo228da422009-07-18 05:44:03 +00001208 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001209 relationship. */
1210 if (peer->group)
1211 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001212 if ((pn = listnode_lookup (peer->group->peer, peer)))
1213 {
1214 peer = peer_unlock (peer); /* group->peer list reference */
1215 list_delete_node (peer->group->peer, pn);
1216 }
paul718e3742002-12-13 20:15:29 +00001217 peer->group = NULL;
1218 }
paul200df112005-06-01 11:17:05 +00001219
paul718e3742002-12-13 20:15:29 +00001220 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001221 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1222 * executed after peer structure is deleted.
1223 */
hassoe0701b72004-05-20 09:19:34 +00001224 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001225 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001226 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001227
1228 /* Password configuration */
1229 if (peer->password)
1230 {
1231 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1232 peer->password = NULL;
1233
1234 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1235 bgp_md5_set (peer);
1236 }
1237
Paul Jakmaca058a32006-09-14 02:58:49 +00001238 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001239
paul718e3742002-12-13 20:15:29 +00001240 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001241 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1242 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001243 {
Chris Caputo228da422009-07-18 05:44:03 +00001244 peer_unlock (peer); /* bgp peer list reference */
1245 list_delete_node (bgp->peer, pn);
1246 }
paul200df112005-06-01 11:17:05 +00001247
Chris Caputo228da422009-07-18 05:44:03 +00001248 if (peer_rsclient_active (peer)
1249 && (pn = listnode_lookup (bgp->rsclient, peer)))
1250 {
1251 peer_unlock (peer); /* rsclient list reference */
1252 list_delete_node (bgp->rsclient, pn);
1253
1254 /* Clear our own rsclient ribs. */
1255 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1256 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1257 if (CHECK_FLAG(peer->af_flags[afi][safi],
1258 PEER_FLAG_RSERVER_CLIENT))
1259 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001260 }
1261
1262 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1263 member of a peer_group. */
1264 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1265 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1266 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001267 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001268
paul200df112005-06-01 11:17:05 +00001269 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001270 if (peer->ibuf)
1271 stream_free (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001272 if (peer->obuf)
1273 stream_fifo_free (peer->obuf);
paul718e3742002-12-13 20:15:29 +00001274 if (peer->work)
1275 stream_free (peer->work);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00001276 if (peer->scratch)
1277 stream_free(peer->scratch);
Paul Jakma18937402006-07-27 19:05:12 +00001278 peer->obuf = NULL;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +00001279 peer->work = peer->scratch = peer->ibuf = NULL;
Paul Jakma18937402006-07-27 19:05:12 +00001280
paul718e3742002-12-13 20:15:29 +00001281 /* Local and remote addresses. */
1282 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001283 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001284 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001285 sockunion_free (peer->su_remote);
Paul Jakma18937402006-07-27 19:05:12 +00001286 peer->su_local = peer->su_remote = NULL;
paul200df112005-06-01 11:17:05 +00001287
paul718e3742002-12-13 20:15:29 +00001288 /* Free filter related memory. */
1289 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1290 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1291 {
1292 filter = &peer->filter[afi][safi];
1293
1294 for (i = FILTER_IN; i < FILTER_MAX; i++)
1295 {
1296 if (filter->dlist[i].name)
1297 free (filter->dlist[i].name);
1298 if (filter->plist[i].name)
1299 free (filter->plist[i].name);
1300 if (filter->aslist[i].name)
1301 free (filter->aslist[i].name);
paul200df112005-06-01 11:17:05 +00001302
1303 filter->dlist[i].name = NULL;
1304 filter->plist[i].name = NULL;
1305 filter->aslist[i].name = NULL;
1306 }
1307 for (i = RMAP_IN; i < RMAP_MAX; i++)
1308 {
paul718e3742002-12-13 20:15:29 +00001309 if (filter->map[i].name)
1310 free (filter->map[i].name);
paul200df112005-06-01 11:17:05 +00001311 filter->map[i].name = NULL;
paul718e3742002-12-13 20:15:29 +00001312 }
1313
1314 if (filter->usmap.name)
1315 free (filter->usmap.name);
1316
1317 if (peer->default_rmap[afi][safi].name)
1318 free (peer->default_rmap[afi][safi].name);
paul200df112005-06-01 11:17:05 +00001319
1320 filter->usmap.name = NULL;
1321 peer->default_rmap[afi][safi].name = NULL;
paul718e3742002-12-13 20:15:29 +00001322 }
paul200df112005-06-01 11:17:05 +00001323
1324 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001325
1326 return 0;
1327}
David Lamparter6b0655a2014-06-04 06:53:35 +02001328
paul94f2b392005-06-28 12:44:16 +00001329static int
paul718e3742002-12-13 20:15:29 +00001330peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1331{
1332 return strcmp (g1->name, g2->name);
1333}
1334
1335/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001336static int
paul718e3742002-12-13 20:15:29 +00001337peer_group_active (struct peer *peer)
1338{
1339 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1340 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1341 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1342 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1343 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1344 return 1;
1345 return 0;
1346}
1347
1348/* Peer group cofiguration. */
1349static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001350peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001351{
1352 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1353 sizeof (struct peer_group));
1354}
1355
paul94f2b392005-06-28 12:44:16 +00001356static void
paul718e3742002-12-13 20:15:29 +00001357peer_group_free (struct peer_group *group)
1358{
1359 XFREE (MTYPE_PEER_GROUP, group);
1360}
1361
1362struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001363peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001364{
1365 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001366 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001367
paul1eb8ef22005-04-07 07:30:20 +00001368 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001369 {
1370 if (strcmp (group->name, name) == 0)
1371 return group;
1372 }
1373 return NULL;
1374}
1375
1376struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001377peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001378{
1379 struct peer_group *group;
1380
1381 group = peer_group_lookup (bgp, name);
1382 if (group)
1383 return group;
1384
1385 group = peer_group_new ();
1386 group->bgp = bgp;
1387 group->name = strdup (name);
1388 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001389 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001390 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1391 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001392 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001393 group->conf->group = group;
1394 group->conf->as = 0;
1395 group->conf->ttl = 1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001396 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001397 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1398 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1399 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1400 group->conf->keepalive = 0;
1401 group->conf->holdtime = 0;
1402 group->conf->connect = 0;
1403 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1404 listnode_add_sort (bgp->group, group);
1405
1406 return 0;
1407}
1408
paul94f2b392005-06-28 12:44:16 +00001409static void
paul718e3742002-12-13 20:15:29 +00001410peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1411 afi_t afi, safi_t safi)
1412{
1413 int in = FILTER_IN;
1414 int out = FILTER_OUT;
1415 struct peer *conf;
1416 struct bgp_filter *pfilter;
1417 struct bgp_filter *gfilter;
1418
1419 conf = group->conf;
1420 pfilter = &peer->filter[afi][safi];
1421 gfilter = &conf->filter[afi][safi];
1422
1423 /* remote-as */
1424 if (conf->as)
1425 peer->as = conf->as;
1426
1427 /* remote-as */
1428 if (conf->change_local_as)
1429 peer->change_local_as = conf->change_local_as;
1430
1431 /* TTL */
1432 peer->ttl = conf->ttl;
1433
Nick Hilliardfa411a22011-03-23 15:33:17 +00001434 /* GTSM hops */
1435 peer->gtsm_hops = conf->gtsm_hops;
1436
paul718e3742002-12-13 20:15:29 +00001437 /* Weight */
1438 peer->weight = conf->weight;
1439
1440 /* peer flags apply */
1441 peer->flags = conf->flags;
1442 /* peer af_flags apply */
1443 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1444 /* peer config apply */
1445 peer->config = conf->config;
1446
1447 /* peer timers apply */
1448 peer->holdtime = conf->holdtime;
1449 peer->keepalive = conf->keepalive;
1450 peer->connect = conf->connect;
1451 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1452 peer->v_connect = conf->connect;
1453 else
1454 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1455
1456 /* advertisement-interval reset */
1457 if (peer_sort (peer) == BGP_PEER_IBGP)
1458 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1459 else
1460 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1461
Paul Jakma0df7c912008-07-21 21:02:49 +00001462 /* password apply */
Roman Hoog Antink0e4303d2013-01-18 13:52:03 +01001463 if (conf->password && !peer->password)
Paul Jakma0df7c912008-07-21 21:02:49 +00001464 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
Paul Jakma0df7c912008-07-21 21:02:49 +00001465
1466 bgp_md5_set (peer);
1467
paul718e3742002-12-13 20:15:29 +00001468 /* maximum-prefix */
1469 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001470 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001471 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001472
1473 /* allowas-in */
1474 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1475
paulfee0f4c2004-09-13 05:12:46 +00001476 /* route-server-client */
1477 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1478 {
1479 /* Make peer's RIB point to group's RIB. */
1480 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1481
1482 /* Import policy. */
1483 if (pfilter->map[RMAP_IMPORT].name)
1484 free (pfilter->map[RMAP_IMPORT].name);
1485 if (gfilter->map[RMAP_IMPORT].name)
1486 {
1487 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1488 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1489 }
1490 else
1491 {
1492 pfilter->map[RMAP_IMPORT].name = NULL;
1493 pfilter->map[RMAP_IMPORT].map = NULL;
1494 }
1495
1496 /* Export policy. */
1497 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1498 {
1499 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1500 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1501 }
1502 }
1503
paul718e3742002-12-13 20:15:29 +00001504 /* default-originate route-map */
1505 if (conf->default_rmap[afi][safi].name)
1506 {
1507 if (peer->default_rmap[afi][safi].name)
1508 free (peer->default_rmap[afi][safi].name);
1509 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1510 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1511 }
1512
1513 /* update-source apply */
1514 if (conf->update_source)
1515 {
1516 if (peer->update_source)
1517 sockunion_free (peer->update_source);
1518 if (peer->update_if)
1519 {
1520 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1521 peer->update_if = NULL;
1522 }
1523 peer->update_source = sockunion_dup (conf->update_source);
1524 }
1525 else if (conf->update_if)
1526 {
1527 if (peer->update_if)
1528 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1529 if (peer->update_source)
1530 {
1531 sockunion_free (peer->update_source);
1532 peer->update_source = NULL;
1533 }
1534 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1535 }
1536
1537 /* inbound filter apply */
1538 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1539 {
1540 if (pfilter->dlist[in].name)
1541 free (pfilter->dlist[in].name);
1542 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1543 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1544 }
1545 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1546 {
1547 if (pfilter->plist[in].name)
1548 free (pfilter->plist[in].name);
1549 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1550 pfilter->plist[in].plist = gfilter->plist[in].plist;
1551 }
1552 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1553 {
1554 if (pfilter->aslist[in].name)
1555 free (pfilter->aslist[in].name);
1556 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1557 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1558 }
paulfee0f4c2004-09-13 05:12:46 +00001559 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001560 {
paulfee0f4c2004-09-13 05:12:46 +00001561 if (pfilter->map[RMAP_IN].name)
1562 free (pfilter->map[RMAP_IN].name);
1563 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1564 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001565 }
1566
1567 /* outbound filter apply */
1568 if (gfilter->dlist[out].name)
1569 {
1570 if (pfilter->dlist[out].name)
1571 free (pfilter->dlist[out].name);
1572 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1573 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1574 }
1575 else
1576 {
1577 if (pfilter->dlist[out].name)
1578 free (pfilter->dlist[out].name);
1579 pfilter->dlist[out].name = NULL;
1580 pfilter->dlist[out].alist = NULL;
1581 }
1582 if (gfilter->plist[out].name)
1583 {
1584 if (pfilter->plist[out].name)
1585 free (pfilter->plist[out].name);
1586 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1587 pfilter->plist[out].plist = gfilter->plist[out].plist;
1588 }
1589 else
1590 {
1591 if (pfilter->plist[out].name)
1592 free (pfilter->plist[out].name);
1593 pfilter->plist[out].name = NULL;
1594 pfilter->plist[out].plist = NULL;
1595 }
1596 if (gfilter->aslist[out].name)
1597 {
1598 if (pfilter->aslist[out].name)
1599 free (pfilter->aslist[out].name);
1600 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1601 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1602 }
1603 else
1604 {
1605 if (pfilter->aslist[out].name)
1606 free (pfilter->aslist[out].name);
1607 pfilter->aslist[out].name = NULL;
1608 pfilter->aslist[out].aslist = NULL;
1609 }
paulfee0f4c2004-09-13 05:12:46 +00001610 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001611 {
paulfee0f4c2004-09-13 05:12:46 +00001612 if (pfilter->map[RMAP_OUT].name)
1613 free (pfilter->map[RMAP_OUT].name);
1614 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1615 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001616 }
1617 else
1618 {
paulfee0f4c2004-09-13 05:12:46 +00001619 if (pfilter->map[RMAP_OUT].name)
1620 free (pfilter->map[RMAP_OUT].name);
1621 pfilter->map[RMAP_OUT].name = NULL;
1622 pfilter->map[RMAP_OUT].map = NULL;
1623 }
1624
1625 /* RS-client's import/export route-maps. */
1626 if (gfilter->map[RMAP_IMPORT].name)
1627 {
1628 if (pfilter->map[RMAP_IMPORT].name)
1629 free (pfilter->map[RMAP_IMPORT].name);
1630 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1631 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1632 }
1633 else
1634 {
1635 if (pfilter->map[RMAP_IMPORT].name)
1636 free (pfilter->map[RMAP_IMPORT].name);
1637 pfilter->map[RMAP_IMPORT].name = NULL;
1638 pfilter->map[RMAP_IMPORT].map = NULL;
1639 }
1640 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1641 {
1642 if (pfilter->map[RMAP_EXPORT].name)
1643 free (pfilter->map[RMAP_EXPORT].name);
1644 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1645 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001646 }
1647
1648 if (gfilter->usmap.name)
1649 {
1650 if (pfilter->usmap.name)
1651 free (pfilter->usmap.name);
1652 pfilter->usmap.name = strdup (gfilter->usmap.name);
1653 pfilter->usmap.map = gfilter->usmap.map;
1654 }
1655 else
1656 {
1657 if (pfilter->usmap.name)
1658 free (pfilter->usmap.name);
1659 pfilter->usmap.name = NULL;
1660 pfilter->usmap.map = NULL;
1661 }
1662}
1663
1664/* Peer group's remote AS configuration. */
1665int
paulfd79ac92004-10-13 05:06:08 +00001666peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001667{
1668 struct peer_group *group;
1669 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001670 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001671
1672 group = peer_group_lookup (bgp, group_name);
1673 if (! group)
1674 return -1;
1675
1676 if (group->conf->as == *as)
1677 return 0;
1678
1679 /* When we setup peer-group AS number all peer group member's AS
1680 number must be updated to same number. */
1681 peer_as_change (group->conf, *as);
1682
paul1eb8ef22005-04-07 07:30:20 +00001683 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001684 {
1685 if (peer->as != *as)
1686 peer_as_change (peer, *as);
1687 }
1688
1689 return 0;
1690}
1691
1692int
1693peer_group_delete (struct peer_group *group)
1694{
1695 struct bgp *bgp;
1696 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001697 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001698
1699 bgp = group->bgp;
1700
paul1eb8ef22005-04-07 07:30:20 +00001701 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001702 {
1703 peer->group = NULL;
1704 peer_delete (peer);
1705 }
1706 list_delete (group->peer);
1707
1708 free (group->name);
1709 group->name = NULL;
1710
1711 group->conf->group = NULL;
1712 peer_delete (group->conf);
1713
1714 /* Delete from all peer_group list. */
1715 listnode_delete (bgp->group, group);
1716
1717 peer_group_free (group);
1718
1719 return 0;
1720}
1721
1722int
1723peer_group_remote_as_delete (struct peer_group *group)
1724{
1725 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001726 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001727
1728 if (! group->conf->as)
1729 return 0;
1730
paul1eb8ef22005-04-07 07:30:20 +00001731 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001732 {
1733 peer->group = NULL;
1734 peer_delete (peer);
1735 }
1736 list_delete_all_node (group->peer);
1737
1738 group->conf->as = 0;
1739
1740 return 0;
1741}
1742
1743/* Bind specified peer to peer group. */
1744int
1745peer_group_bind (struct bgp *bgp, union sockunion *su,
1746 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1747{
1748 struct peer *peer;
1749 int first_member = 0;
1750
1751 /* Check peer group's address family. */
1752 if (! group->conf->afc[afi][safi])
1753 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1754
1755 /* Lookup the peer. */
1756 peer = peer_lookup (bgp, su);
1757
1758 /* Create a new peer. */
1759 if (! peer)
1760 {
1761 if (! group->conf->as)
1762 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1763
1764 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1765 peer->group = group;
1766 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001767
Paul Jakmaca058a32006-09-14 02:58:49 +00001768 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001769 listnode_add (group->peer, peer);
1770 peer_group2peer_config_copy (group, peer, afi, safi);
1771
1772 return 0;
1773 }
1774
1775 /* When the peer already belongs to peer group, check the consistency. */
1776 if (peer->af_group[afi][safi])
1777 {
1778 if (strcmp (peer->group->name, group->name) != 0)
1779 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1780
1781 return 0;
1782 }
1783
1784 /* Check current peer group configuration. */
1785 if (peer_group_active (peer)
1786 && strcmp (peer->group->name, group->name) != 0)
1787 return BGP_ERR_PEER_GROUP_MISMATCH;
1788
1789 if (! group->conf->as)
1790 {
1791 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1792 && peer_sort (group->conf) != peer_sort (peer))
1793 {
1794 if (as)
1795 *as = peer->as;
1796 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1797 }
1798
1799 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1800 first_member = 1;
1801 }
1802
1803 peer->af_group[afi][safi] = 1;
1804 peer->afc[afi][safi] = 1;
1805 if (! peer->group)
1806 {
1807 peer->group = group;
paul200df112005-06-01 11:17:05 +00001808
Paul Jakmaca058a32006-09-14 02:58:49 +00001809 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001810 listnode_add (group->peer, peer);
1811 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001812 else
1813 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001814
1815 if (first_member)
1816 {
1817 /* Advertisement-interval reset */
1818 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1819 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1820 else
1821 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1822
1823 /* ebgp-multihop reset */
1824 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1825 group->conf->ttl = 255;
1826
1827 /* local-as reset */
1828 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1829 {
1830 group->conf->change_local_as = 0;
1831 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001832 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001833 }
1834 }
paulfee0f4c2004-09-13 05:12:46 +00001835
1836 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1837 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001838 struct listnode *pn;
1839
paulfee0f4c2004-09-13 05:12:46 +00001840 /* If it's not configured as RSERVER_CLIENT in any other address
1841 family, without being member of a peer_group, remove it from
1842 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001843 if (! peer_rsclient_active (peer)
1844 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001845 {
1846 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001847 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001848
1849 /* Clear our own rsclient rib for this afi/safi. */
1850 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001851 }
paulfee0f4c2004-09-13 05:12:46 +00001852
Paul Jakmab608d5b2008-07-02 02:12:07 +00001853 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001854
1855 /* Import policy. */
1856 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1857 {
1858 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1859 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1860 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1861 }
1862
1863 /* Export policy. */
1864 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1865 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1866 {
1867 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1868 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1869 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1870 }
1871 }
1872
paul718e3742002-12-13 20:15:29 +00001873 peer_group2peer_config_copy (group, peer, afi, safi);
1874
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001875 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001876 {
1877 peer->last_reset = PEER_DOWN_RMAP_BIND;
1878 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1879 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1880 }
paul718e3742002-12-13 20:15:29 +00001881 else
1882 BGP_EVENT_ADD (peer, BGP_Stop);
1883
1884 return 0;
1885}
1886
1887int
1888peer_group_unbind (struct bgp *bgp, struct peer *peer,
1889 struct peer_group *group, afi_t afi, safi_t safi)
1890{
1891 if (! peer->af_group[afi][safi])
1892 return 0;
1893
1894 if (group != peer->group)
1895 return BGP_ERR_PEER_GROUP_MISMATCH;
1896
1897 peer->af_group[afi][safi] = 0;
1898 peer->afc[afi][safi] = 0;
1899 peer_af_flag_reset (peer, afi, safi);
1900
paulfee0f4c2004-09-13 05:12:46 +00001901 if (peer->rib[afi][safi])
1902 peer->rib[afi][safi] = NULL;
1903
paul718e3742002-12-13 20:15:29 +00001904 if (! peer_group_active (peer))
1905 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001906 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001907 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001908 listnode_delete (group->peer, peer);
1909 peer->group = NULL;
1910 if (group->conf->as)
1911 {
1912 peer_delete (peer);
1913 return 0;
1914 }
1915 peer_global_config_reset (peer);
1916 }
1917
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00001918 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00001919 {
1920 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1921 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1922 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1923 }
paul718e3742002-12-13 20:15:29 +00001924 else
1925 BGP_EVENT_ADD (peer, BGP_Stop);
1926
1927 return 0;
1928}
David Lamparter6b0655a2014-06-04 06:53:35 +02001929
paul718e3742002-12-13 20:15:29 +00001930/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001931static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001932bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001933{
1934 struct bgp *bgp;
1935 afi_t afi;
1936 safi_t safi;
1937
paul200df112005-06-01 11:17:05 +00001938 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1939 return NULL;
1940
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07001941 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00001942 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00001943 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00001944
1945 bgp->peer = list_new ();
1946 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1947
1948 bgp->group = list_new ();
1949 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1950
paulfee0f4c2004-09-13 05:12:46 +00001951 bgp->rsclient = list_new ();
1952 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1953
paul718e3742002-12-13 20:15:29 +00001954 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1955 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1956 {
Paul Jakma64e580a2006-02-21 01:09:01 +00001957 bgp->route[afi][safi] = bgp_table_init (afi, safi);
1958 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1959 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07001960 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
1961 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00001962 }
1963
1964 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1965 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1966 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001967 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1968 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001969
1970 bgp->as = *as;
1971
1972 if (name)
1973 bgp->name = strdup (name);
1974
1975 return bgp;
1976}
1977
1978/* Return first entry of BGP. */
1979struct bgp *
paul94f2b392005-06-28 12:44:16 +00001980bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001981{
1982 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001983 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001984 return NULL;
1985}
1986
1987/* Lookup BGP entry. */
1988struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001989bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001990{
1991 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001992 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001993
paul1eb8ef22005-04-07 07:30:20 +00001994 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001995 if (bgp->as == as
1996 && ((bgp->name == NULL && name == NULL)
1997 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1998 return bgp;
1999 return NULL;
2000}
2001
2002/* Lookup BGP structure by view name. */
2003struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002004bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002005{
2006 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002007 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002008
paul1eb8ef22005-04-07 07:30:20 +00002009 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002010 if ((bgp->name == NULL && name == NULL)
2011 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2012 return bgp;
2013 return NULL;
2014}
2015
2016/* Called from VTY commands. */
2017int
paulfd79ac92004-10-13 05:06:08 +00002018bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002019{
2020 struct bgp *bgp;
2021
2022 /* Multiple instance check. */
2023 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2024 {
2025 if (name)
2026 bgp = bgp_lookup_by_name (name);
2027 else
2028 bgp = bgp_get_default ();
2029
2030 /* Already exists. */
2031 if (bgp)
2032 {
2033 if (bgp->as != *as)
2034 {
2035 *as = bgp->as;
2036 return BGP_ERR_INSTANCE_MISMATCH;
2037 }
2038 *bgp_val = bgp;
2039 return 0;
2040 }
2041 }
2042 else
2043 {
2044 /* BGP instance name can not be specified for single instance. */
2045 if (name)
2046 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2047
2048 /* Get default BGP structure if exists. */
2049 bgp = bgp_get_default ();
2050
2051 if (bgp)
2052 {
2053 if (bgp->as != *as)
2054 {
2055 *as = bgp->as;
2056 return BGP_ERR_AS_MISMATCH;
2057 }
2058 *bgp_val = bgp;
2059 return 0;
2060 }
2061 }
2062
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002063 bgp = bgp_create (as, name);
2064 bgp_router_id_set(bgp, &router_id_zebra);
2065 *bgp_val = bgp;
2066
Paul Jakmaad12dde2012-06-13 22:50:07 +01002067 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002068 if (list_isempty(bm->bgp)
2069 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002070 {
2071 if (bgp_socket (bm->port, bm->address) < 0)
2072 return BGP_ERR_INVALID_VALUE;
2073 }
2074
paul718e3742002-12-13 20:15:29 +00002075 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002076
2077 return 0;
2078}
2079
2080/* Delete BGP instance. */
2081int
2082bgp_delete (struct bgp *bgp)
2083{
2084 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002085 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002086 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002087 struct listnode *next;
2088 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002089 int i;
2090
2091 /* Delete static route. */
2092 bgp_static_delete (bgp);
2093
2094 /* Unset redistribution. */
2095 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2096 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2097 if (i != ZEBRA_ROUTE_BGP)
2098 bgp_redistribute_unset (bgp, afi, i);
2099
paul1eb8ef22005-04-07 07:30:20 +00002100 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002101 {
2102 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
2103 {
2104 /* Send notify to remote peer. */
2105 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2106 }
2107
2108 peer_delete (peer);
2109 }
paul718e3742002-12-13 20:15:29 +00002110
Chris Caputo228da422009-07-18 05:44:03 +00002111 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002112 {
2113 for (ALL_LIST_ELEMENTS (group->peer, node, next, peer))
2114 {
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_group_delete (group);
2122 }
Chris Caputo228da422009-07-18 05:44:03 +00002123
2124 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002125
2126 if (bgp->peer_self) {
2127 peer_delete(bgp->peer_self);
2128 bgp->peer_self = NULL;
2129 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002130
2131 /* Remove visibility via the master list - there may however still be
2132 * routes to be processed still referencing the struct bgp.
2133 */
2134 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002135 if (list_isempty(bm->bgp))
2136 bgp_close ();
2137
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002138 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002139
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002140 return 0;
2141}
2142
2143static void bgp_free (struct bgp *);
2144
2145void
2146bgp_lock (struct bgp *bgp)
2147{
2148 ++bgp->lock;
2149}
2150
2151void
2152bgp_unlock(struct bgp *bgp)
2153{
Chris Caputo228da422009-07-18 05:44:03 +00002154 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002155 if (--bgp->lock == 0)
2156 bgp_free (bgp);
2157}
2158
2159static void
2160bgp_free (struct bgp *bgp)
2161{
2162 afi_t afi;
2163 safi_t safi;
2164
2165 list_delete (bgp->group);
2166 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002167 list_delete (bgp->rsclient);
2168
paul718e3742002-12-13 20:15:29 +00002169 if (bgp->name)
2170 free (bgp->name);
2171
2172 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2173 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2174 {
2175 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002176 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002177 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002178 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002179 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002180 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002181 }
2182 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002183}
David Lamparter6b0655a2014-06-04 06:53:35 +02002184
paul718e3742002-12-13 20:15:29 +00002185struct peer *
2186peer_lookup (struct bgp *bgp, union sockunion *su)
2187{
2188 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002189 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002190
Steve Hillfc4dc592009-07-28 17:54:35 +01002191 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002192 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002193 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2194 if (sockunion_same (&peer->su, su)
2195 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2196 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002197 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002198 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002199 {
2200 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002201
Paul Jakma2158ad22009-07-28 18:10:55 +01002202 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2203 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2204 if (sockunion_same (&peer->su, su)
2205 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2206 return peer;
paul718e3742002-12-13 20:15:29 +00002207 }
2208 return NULL;
2209}
2210
2211struct peer *
2212peer_lookup_with_open (union sockunion *su, as_t remote_as,
2213 struct in_addr *remote_id, int *as)
2214{
2215 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002216 struct listnode *node;
2217 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002218 struct bgp *bgp;
2219
Steve Hillfc4dc592009-07-28 17:54:35 +01002220 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002221 return NULL;
2222
Paul Jakma9d878772009-08-05 16:25:16 +01002223 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002224 {
Paul Jakma9d878772009-08-05 16:25:16 +01002225 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2226 {
2227 if (sockunion_same (&peer->su, su)
2228 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2229 {
2230 if (peer->as == remote_as
2231 && peer->remote_id.s_addr == remote_id->s_addr)
2232 return peer;
2233 if (peer->as == remote_as)
2234 *as = 1;
2235 }
2236 }
2237
2238 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 == 0)
2245 return peer;
2246 if (peer->as == remote_as)
2247 *as = 1;
2248 }
2249 }
paul718e3742002-12-13 20:15:29 +00002250 }
2251 return NULL;
2252}
David Lamparter6b0655a2014-06-04 06:53:35 +02002253
paul718e3742002-12-13 20:15:29 +00002254/* If peer is configured at least one address family return 1. */
2255int
2256peer_active (struct peer *peer)
2257{
2258 if (peer->afc[AFI_IP][SAFI_UNICAST]
2259 || peer->afc[AFI_IP][SAFI_MULTICAST]
2260 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2261 || peer->afc[AFI_IP6][SAFI_UNICAST]
2262 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2263 return 1;
2264 return 0;
2265}
2266
2267/* If peer is negotiated at least one address family return 1. */
2268int
2269peer_active_nego (struct peer *peer)
2270{
2271 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2272 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2273 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2274 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2275 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2276 return 1;
2277 return 0;
2278}
David Lamparter6b0655a2014-06-04 06:53:35 +02002279
paul718e3742002-12-13 20:15:29 +00002280/* peer_flag_change_type. */
2281enum peer_change_type
2282{
2283 peer_change_none,
2284 peer_change_reset,
2285 peer_change_reset_in,
2286 peer_change_reset_out,
2287};
2288
paul94f2b392005-06-28 12:44:16 +00002289static void
paul718e3742002-12-13 20:15:29 +00002290peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2291 enum peer_change_type type)
2292{
2293 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2294 return;
2295
Stephen Hemmingerd9d4ae52010-01-13 00:32:39 +00002296 if (peer->status != Established)
2297 return;
2298
paul718e3742002-12-13 20:15:29 +00002299 if (type == peer_change_reset)
2300 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2301 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2302 else if (type == peer_change_reset_in)
2303 {
2304 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2305 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2306 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2307 else
2308 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2309 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2310 }
2311 else if (type == peer_change_reset_out)
2312 bgp_announce_route (peer, afi, safi);
2313}
2314
2315struct peer_flag_action
2316{
2317 /* Peer's flag. */
2318 u_int32_t flag;
2319
2320 /* This flag can be set for peer-group member. */
2321 u_char not_for_member;
2322
2323 /* Action when the flag is changed. */
2324 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002325
2326 /* Peer down cause */
2327 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002328};
2329
Stephen Hemminger03621952009-07-21 16:27:20 -07002330static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002331 {
2332 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2333 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2334 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2335 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2336 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002337 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002338 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002339 { 0, 0, 0 }
2340 };
2341
Stephen Hemminger03621952009-07-21 16:27:20 -07002342static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002343 {
2344 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2345 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2346 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2347 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2348 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2349 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2350 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2351 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2352 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2353 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2354 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2355 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2356 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002357 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
Timo Teräs9e7a53c2014-04-24 10:22:37 +03002358 { PEER_FLAG_NEXTHOP_SELF_ALL, 1, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002359 { 0, 0, 0 }
2360 };
2361
2362/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002363static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002364peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002365 struct peer_flag_action *action, u_int32_t flag)
2366{
2367 int i;
2368 int found = 0;
2369 int reset_in = 0;
2370 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002371 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002372
2373 /* Check peer's frag action. */
2374 for (i = 0; i < size; i++)
2375 {
2376 match = &action_list[i];
2377
2378 if (match->flag == 0)
2379 break;
2380
2381 if (match->flag & flag)
2382 {
2383 found = 1;
2384
2385 if (match->type == peer_change_reset_in)
2386 reset_in = 1;
2387 if (match->type == peer_change_reset_out)
2388 reset_out = 1;
2389 if (match->type == peer_change_reset)
2390 {
2391 reset_in = 1;
2392 reset_out = 1;
2393 }
2394 if (match->not_for_member)
2395 action->not_for_member = 1;
2396 }
2397 }
2398
2399 /* Set peer clear type. */
2400 if (reset_in && reset_out)
2401 action->type = peer_change_reset;
2402 else if (reset_in)
2403 action->type = peer_change_reset_in;
2404 else if (reset_out)
2405 action->type = peer_change_reset_out;
2406 else
2407 action->type = peer_change_none;
2408
2409 return found;
2410}
2411
paul94f2b392005-06-28 12:44:16 +00002412static void
paul718e3742002-12-13 20:15:29 +00002413peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2414{
2415 if (flag == PEER_FLAG_SHUTDOWN)
2416 {
2417 if (CHECK_FLAG (peer->flags, flag))
2418 {
hasso93406d82005-02-02 14:40:33 +00002419 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2420 peer_nsf_stop (peer);
2421
hasso0a486e52005-02-01 20:57:17 +00002422 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2423 if (peer->t_pmax_restart)
2424 {
2425 BGP_TIMER_OFF (peer->t_pmax_restart);
2426 if (BGP_DEBUG (events, EVENTS))
2427 zlog_debug ("%s Maximum-prefix restart timer canceled",
2428 peer->host);
2429 }
2430
hasso93406d82005-02-02 14:40:33 +00002431 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2432 peer_nsf_stop (peer);
2433
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002434 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002435 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2436 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2437 else
2438 BGP_EVENT_ADD (peer, BGP_Stop);
2439 }
2440 else
2441 {
2442 peer->v_start = BGP_INIT_START_TIMER;
2443 BGP_EVENT_ADD (peer, BGP_Stop);
2444 }
2445 }
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002446 else if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00002447 {
hassoc9502432005-02-01 22:01:48 +00002448 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2449 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2450 else if (flag == PEER_FLAG_PASSIVE)
2451 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002452 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002453 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002454
hassoc9502432005-02-01 22:01:48 +00002455 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2456 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002457 }
2458 else
2459 BGP_EVENT_ADD (peer, BGP_Stop);
2460}
2461
2462/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002463static int
paul718e3742002-12-13 20:15:29 +00002464peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2465{
2466 int found;
2467 int size;
2468 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002469 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002470 struct peer_flag_action action;
2471
2472 memset (&action, 0, sizeof (struct peer_flag_action));
2473 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2474
2475 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2476
2477 /* No flag action is found. */
2478 if (! found)
2479 return BGP_ERR_INVALID_FLAG;
2480
2481 /* Not for peer-group member. */
2482 if (action.not_for_member && peer_group_active (peer))
2483 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2484
2485 /* When unset the peer-group member's flag we have to check
2486 peer-group configuration. */
2487 if (! set && peer_group_active (peer))
2488 if (CHECK_FLAG (peer->group->conf->flags, flag))
2489 {
2490 if (flag == PEER_FLAG_SHUTDOWN)
2491 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2492 else
2493 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2494 }
2495
2496 /* Flag conflict check. */
2497 if (set
2498 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2499 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2500 return BGP_ERR_PEER_FLAG_CONFLICT;
2501
2502 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2503 {
2504 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2505 return 0;
2506 if (! set && ! CHECK_FLAG (peer->flags, flag))
2507 return 0;
2508 }
2509
2510 if (set)
2511 SET_FLAG (peer->flags, flag);
2512 else
2513 UNSET_FLAG (peer->flags, flag);
2514
2515 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2516 {
2517 if (action.type == peer_change_reset)
2518 peer_flag_modify_action (peer, flag);
2519
2520 return 0;
2521 }
2522
2523 /* peer-group member updates. */
2524 group = peer->group;
2525
paul1eb8ef22005-04-07 07:30:20 +00002526 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002527 {
2528 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2529 continue;
2530
2531 if (! set && ! CHECK_FLAG (peer->flags, flag))
2532 continue;
2533
2534 if (set)
2535 SET_FLAG (peer->flags, flag);
2536 else
2537 UNSET_FLAG (peer->flags, flag);
2538
2539 if (action.type == peer_change_reset)
2540 peer_flag_modify_action (peer, flag);
2541 }
2542 return 0;
2543}
2544
2545int
2546peer_flag_set (struct peer *peer, u_int32_t flag)
2547{
2548 return peer_flag_modify (peer, flag, 1);
2549}
2550
2551int
2552peer_flag_unset (struct peer *peer, u_int32_t flag)
2553{
2554 return peer_flag_modify (peer, flag, 0);
2555}
2556
paul94f2b392005-06-28 12:44:16 +00002557static int
paul718e3742002-12-13 20:15:29 +00002558peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2559{
2560 if (peer->af_group[afi][safi])
2561 return 1;
2562 return 0;
2563}
2564
paul94f2b392005-06-28 12:44:16 +00002565static int
paul718e3742002-12-13 20:15:29 +00002566peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2567 int set)
2568{
2569 int found;
2570 int size;
paul1eb8ef22005-04-07 07:30:20 +00002571 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002572 struct peer_group *group;
2573 struct peer_flag_action action;
2574
2575 memset (&action, 0, sizeof (struct peer_flag_action));
2576 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2577
2578 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2579
2580 /* No flag action is found. */
2581 if (! found)
2582 return BGP_ERR_INVALID_FLAG;
2583
2584 /* Adress family must be activated. */
2585 if (! peer->afc[afi][safi])
2586 return BGP_ERR_PEER_INACTIVE;
2587
2588 /* Not for peer-group member. */
2589 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2590 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2591
2592 /* Spcecial check for reflector client. */
2593 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2594 && peer_sort (peer) != BGP_PEER_IBGP)
2595 return BGP_ERR_NOT_INTERNAL_PEER;
2596
2597 /* Spcecial check for remove-private-AS. */
2598 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2599 && peer_sort (peer) == BGP_PEER_IBGP)
2600 return BGP_ERR_REMOVE_PRIVATE_AS;
2601
2602 /* When unset the peer-group member's flag we have to check
2603 peer-group configuration. */
2604 if (! set && peer->af_group[afi][safi])
2605 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2606 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2607
2608 /* When current flag configuration is same as requested one. */
2609 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2610 {
2611 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2612 return 0;
2613 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2614 return 0;
2615 }
2616
2617 if (set)
2618 SET_FLAG (peer->af_flags[afi][safi], flag);
2619 else
2620 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2621
2622 /* Execute action when peer is established. */
2623 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2624 && peer->status == Established)
2625 {
2626 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2627 bgp_clear_adj_in (peer, afi, safi);
2628 else
hassoe0701b72004-05-20 09:19:34 +00002629 {
2630 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2631 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2632 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2633 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2634 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2635 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2636 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2637 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2638
2639 peer_change_action (peer, afi, safi, action.type);
2640 }
2641
paul718e3742002-12-13 20:15:29 +00002642 }
2643
2644 /* Peer group member updates. */
2645 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2646 {
2647 group = peer->group;
2648
paul1eb8ef22005-04-07 07:30:20 +00002649 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002650 {
2651 if (! peer->af_group[afi][safi])
2652 continue;
2653
2654 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2655 continue;
2656
2657 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2658 continue;
2659
2660 if (set)
2661 SET_FLAG (peer->af_flags[afi][safi], flag);
2662 else
2663 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2664
2665 if (peer->status == Established)
2666 {
2667 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2668 bgp_clear_adj_in (peer, afi, safi);
2669 else
hassoe0701b72004-05-20 09:19:34 +00002670 {
2671 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2672 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2673 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2674 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2675 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2676 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2677 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2678 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2679
2680 peer_change_action (peer, afi, safi, action.type);
2681 }
paul718e3742002-12-13 20:15:29 +00002682 }
2683 }
2684 }
2685 return 0;
2686}
2687
2688int
2689peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2690{
2691 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2692}
2693
2694int
2695peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2696{
2697 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2698}
David Lamparter6b0655a2014-06-04 06:53:35 +02002699
paul718e3742002-12-13 20:15:29 +00002700/* EBGP multihop configuration. */
2701int
2702peer_ebgp_multihop_set (struct peer *peer, int ttl)
2703{
2704 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002705 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002706 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002707
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002708 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002709 return 0;
2710
Nick Hilliardfa411a22011-03-23 15:33:17 +00002711 /* see comment in peer_ttl_security_hops_set() */
2712 if (ttl != MAXTTL)
2713 {
2714 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2715 {
2716 group = peer->group;
2717 if (group->conf->gtsm_hops != 0)
2718 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2719
2720 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2721 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002722 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002723 continue;
2724
2725 if (peer1->gtsm_hops != 0)
2726 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2727 }
2728 }
2729 else
2730 {
2731 if (peer->gtsm_hops != 0)
2732 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2733 }
2734 }
2735
paul718e3742002-12-13 20:15:29 +00002736 peer->ttl = ttl;
2737
2738 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2739 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002740 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002741 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002742 }
2743 else
2744 {
2745 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002746 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002747 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002748 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002749 continue;
paul718e3742002-12-13 20:15:29 +00002750
pauleb821182004-05-01 08:44:08 +00002751 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002752
pauleb821182004-05-01 08:44:08 +00002753 if (peer->fd >= 0)
2754 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2755 }
paul718e3742002-12-13 20:15:29 +00002756 }
2757 return 0;
2758}
2759
2760int
2761peer_ebgp_multihop_unset (struct peer *peer)
2762{
2763 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002764 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002765
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002766 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002767 return 0;
2768
Nick Hilliardfa411a22011-03-23 15:33:17 +00002769 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2770 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2771
paul718e3742002-12-13 20:15:29 +00002772 if (peer_group_active (peer))
2773 peer->ttl = peer->group->conf->ttl;
2774 else
2775 peer->ttl = 1;
2776
2777 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2778 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002779 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002780 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002781 }
2782 else
2783 {
2784 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002785 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002786 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002787 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002788 continue;
paul718e3742002-12-13 20:15:29 +00002789
pauleb821182004-05-01 08:44:08 +00002790 peer->ttl = 1;
2791
2792 if (peer->fd >= 0)
2793 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2794 }
paul718e3742002-12-13 20:15:29 +00002795 }
2796 return 0;
2797}
David Lamparter6b0655a2014-06-04 06:53:35 +02002798
paul718e3742002-12-13 20:15:29 +00002799/* Neighbor description. */
2800int
2801peer_description_set (struct peer *peer, char *desc)
2802{
2803 if (peer->desc)
2804 XFREE (MTYPE_PEER_DESC, peer->desc);
2805
2806 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2807
2808 return 0;
2809}
2810
2811int
2812peer_description_unset (struct peer *peer)
2813{
2814 if (peer->desc)
2815 XFREE (MTYPE_PEER_DESC, peer->desc);
2816
2817 peer->desc = NULL;
2818
2819 return 0;
2820}
David Lamparter6b0655a2014-06-04 06:53:35 +02002821
paul718e3742002-12-13 20:15:29 +00002822/* Neighbor update-source. */
2823int
paulfd79ac92004-10-13 05:06:08 +00002824peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002825{
2826 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002827 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002828
2829 if (peer->update_if)
2830 {
2831 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2832 && strcmp (peer->update_if, ifname) == 0)
2833 return 0;
2834
2835 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2836 peer->update_if = NULL;
2837 }
2838
2839 if (peer->update_source)
2840 {
2841 sockunion_free (peer->update_source);
2842 peer->update_source = NULL;
2843 }
2844
2845 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2846
2847 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2848 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002849 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002850 {
2851 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2852 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2853 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2854 }
paul718e3742002-12-13 20:15:29 +00002855 else
2856 BGP_EVENT_ADD (peer, BGP_Stop);
2857 return 0;
2858 }
2859
2860 /* peer-group member updates. */
2861 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002862 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002863 {
2864 if (peer->update_if)
2865 {
2866 if (strcmp (peer->update_if, ifname) == 0)
2867 continue;
2868
2869 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2870 peer->update_if = NULL;
2871 }
2872
2873 if (peer->update_source)
2874 {
2875 sockunion_free (peer->update_source);
2876 peer->update_source = NULL;
2877 }
2878
2879 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2880
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002881 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002882 {
2883 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2884 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2885 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2886 }
paul718e3742002-12-13 20:15:29 +00002887 else
2888 BGP_EVENT_ADD (peer, BGP_Stop);
2889 }
2890 return 0;
2891}
2892
2893int
2894peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2895{
2896 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002897 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002898
2899 if (peer->update_source)
2900 {
2901 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2902 && sockunion_cmp (peer->update_source, su) == 0)
2903 return 0;
2904 sockunion_free (peer->update_source);
2905 peer->update_source = NULL;
2906 }
2907
2908 if (peer->update_if)
2909 {
2910 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2911 peer->update_if = NULL;
2912 }
2913
2914 peer->update_source = sockunion_dup (su);
2915
2916 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2917 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002918 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002919 {
2920 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2921 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2922 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2923 }
paul718e3742002-12-13 20:15:29 +00002924 else
2925 BGP_EVENT_ADD (peer, BGP_Stop);
2926 return 0;
2927 }
2928
2929 /* peer-group member updates. */
2930 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002931 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002932 {
2933 if (peer->update_source)
2934 {
2935 if (sockunion_cmp (peer->update_source, su) == 0)
2936 continue;
2937 sockunion_free (peer->update_source);
2938 peer->update_source = NULL;
2939 }
2940
2941 if (peer->update_if)
2942 {
2943 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2944 peer->update_if = NULL;
2945 }
2946
2947 peer->update_source = sockunion_dup (su);
2948
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00002949 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00002950 {
2951 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2952 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2953 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2954 }
paul718e3742002-12-13 20:15:29 +00002955 else
2956 BGP_EVENT_ADD (peer, BGP_Stop);
2957 }
2958 return 0;
2959}
2960
2961int
2962peer_update_source_unset (struct peer *peer)
2963{
2964 union sockunion *su;
2965 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002966 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002967
2968 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2969 && ! peer->update_source
2970 && ! peer->update_if)
2971 return 0;
2972
2973 if (peer->update_source)
2974 {
2975 sockunion_free (peer->update_source);
2976 peer->update_source = NULL;
2977 }
2978 if (peer->update_if)
2979 {
2980 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2981 peer->update_if = NULL;
2982 }
2983
2984 if (peer_group_active (peer))
2985 {
2986 group = peer->group;
2987
2988 if (group->conf->update_source)
2989 {
2990 su = sockunion_dup (group->conf->update_source);
2991 peer->update_source = su;
2992 }
2993 else if (group->conf->update_if)
2994 peer->update_if =
2995 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2996 }
2997
2998 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2999 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003000 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003001 {
3002 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3003 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3004 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3005 }
paul718e3742002-12-13 20:15:29 +00003006 else
3007 BGP_EVENT_ADD (peer, BGP_Stop);
3008 return 0;
3009 }
3010
3011 /* peer-group member updates. */
3012 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003013 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003014 {
3015 if (! peer->update_source && ! peer->update_if)
3016 continue;
3017
3018 if (peer->update_source)
3019 {
3020 sockunion_free (peer->update_source);
3021 peer->update_source = NULL;
3022 }
3023
3024 if (peer->update_if)
3025 {
3026 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3027 peer->update_if = NULL;
3028 }
3029
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003030 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003031 {
3032 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3033 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3034 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3035 }
paul718e3742002-12-13 20:15:29 +00003036 else
3037 BGP_EVENT_ADD (peer, BGP_Stop);
3038 }
3039 return 0;
3040}
David Lamparter6b0655a2014-06-04 06:53:35 +02003041
paul718e3742002-12-13 20:15:29 +00003042int
3043peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003044 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003045{
3046 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003047 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003048
3049 /* Adress family must be activated. */
3050 if (! peer->afc[afi][safi])
3051 return BGP_ERR_PEER_INACTIVE;
3052
3053 /* Default originate can't be used for peer group memeber. */
3054 if (peer_is_group_member (peer, afi, safi))
3055 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3056
3057 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3058 || (rmap && ! peer->default_rmap[afi][safi].name)
3059 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3060 {
3061 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3062
3063 if (rmap)
3064 {
3065 if (peer->default_rmap[afi][safi].name)
3066 free (peer->default_rmap[afi][safi].name);
3067 peer->default_rmap[afi][safi].name = strdup (rmap);
3068 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3069 }
3070 }
3071
3072 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3073 {
3074 if (peer->status == Established && peer->afc_nego[afi][safi])
3075 bgp_default_originate (peer, afi, safi, 0);
3076 return 0;
3077 }
3078
3079 /* peer-group member updates. */
3080 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003081 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003082 {
3083 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3084
3085 if (rmap)
3086 {
3087 if (peer->default_rmap[afi][safi].name)
3088 free (peer->default_rmap[afi][safi].name);
3089 peer->default_rmap[afi][safi].name = strdup (rmap);
3090 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3091 }
3092
3093 if (peer->status == Established && peer->afc_nego[afi][safi])
3094 bgp_default_originate (peer, afi, safi, 0);
3095 }
3096 return 0;
3097}
3098
3099int
3100peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3101{
3102 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003103 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003104
3105 /* Adress family must be activated. */
3106 if (! peer->afc[afi][safi])
3107 return BGP_ERR_PEER_INACTIVE;
3108
3109 /* Default originate can't be used for peer group memeber. */
3110 if (peer_is_group_member (peer, afi, safi))
3111 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3112
3113 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3114 {
3115 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3116
3117 if (peer->default_rmap[afi][safi].name)
3118 free (peer->default_rmap[afi][safi].name);
3119 peer->default_rmap[afi][safi].name = NULL;
3120 peer->default_rmap[afi][safi].map = NULL;
3121 }
3122
3123 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3124 {
3125 if (peer->status == Established && peer->afc_nego[afi][safi])
3126 bgp_default_originate (peer, afi, safi, 1);
3127 return 0;
3128 }
3129
3130 /* peer-group member updates. */
3131 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003132 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003133 {
3134 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3135
3136 if (peer->default_rmap[afi][safi].name)
3137 free (peer->default_rmap[afi][safi].name);
3138 peer->default_rmap[afi][safi].name = NULL;
3139 peer->default_rmap[afi][safi].map = NULL;
3140
3141 if (peer->status == Established && peer->afc_nego[afi][safi])
3142 bgp_default_originate (peer, afi, safi, 1);
3143 }
3144 return 0;
3145}
David Lamparter6b0655a2014-06-04 06:53:35 +02003146
paul718e3742002-12-13 20:15:29 +00003147int
3148peer_port_set (struct peer *peer, u_int16_t port)
3149{
3150 peer->port = port;
3151 return 0;
3152}
3153
3154int
3155peer_port_unset (struct peer *peer)
3156{
3157 peer->port = BGP_PORT_DEFAULT;
3158 return 0;
3159}
David Lamparter6b0655a2014-06-04 06:53:35 +02003160
paul718e3742002-12-13 20:15:29 +00003161/* neighbor weight. */
3162int
3163peer_weight_set (struct peer *peer, u_int16_t weight)
3164{
3165 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003166 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003167
3168 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3169 peer->weight = weight;
3170
3171 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3172 return 0;
3173
3174 /* peer-group member updates. */
3175 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003176 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003177 {
3178 peer->weight = group->conf->weight;
3179 }
3180 return 0;
3181}
3182
3183int
3184peer_weight_unset (struct peer *peer)
3185{
3186 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003187 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003188
3189 /* Set default weight. */
3190 if (peer_group_active (peer))
3191 peer->weight = peer->group->conf->weight;
3192 else
3193 peer->weight = 0;
3194
3195 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3196
3197 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3198 return 0;
3199
3200 /* peer-group member updates. */
3201 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003202 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003203 {
3204 peer->weight = 0;
3205 }
3206 return 0;
3207}
David Lamparter6b0655a2014-06-04 06:53:35 +02003208
paul718e3742002-12-13 20:15:29 +00003209int
3210peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3211{
3212 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003213 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003214
3215 /* Not for peer group memeber. */
3216 if (peer_group_active (peer))
3217 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3218
3219 /* keepalive value check. */
3220 if (keepalive > 65535)
3221 return BGP_ERR_INVALID_VALUE;
3222
3223 /* Holdtime value check. */
3224 if (holdtime > 65535)
3225 return BGP_ERR_INVALID_VALUE;
3226
3227 /* Holdtime value must be either 0 or greater than 3. */
3228 if (holdtime < 3 && holdtime != 0)
3229 return BGP_ERR_INVALID_VALUE;
3230
3231 /* Set value to the configuration. */
3232 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3233 peer->holdtime = holdtime;
3234 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3235
3236 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3237 return 0;
3238
3239 /* peer-group member updates. */
3240 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003241 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003242 {
3243 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3244 peer->holdtime = group->conf->holdtime;
3245 peer->keepalive = group->conf->keepalive;
3246 }
3247 return 0;
3248}
3249
3250int
3251peer_timers_unset (struct peer *peer)
3252{
3253 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003254 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003255
3256 if (peer_group_active (peer))
3257 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3258
3259 /* Clear configuration. */
3260 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3261 peer->keepalive = 0;
3262 peer->holdtime = 0;
3263
3264 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3265 return 0;
3266
3267 /* peer-group member updates. */
3268 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003269 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003270 {
3271 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3272 peer->holdtime = 0;
3273 peer->keepalive = 0;
3274 }
3275
3276 return 0;
3277}
David Lamparter6b0655a2014-06-04 06:53:35 +02003278
paul718e3742002-12-13 20:15:29 +00003279int
3280peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3281{
3282 if (peer_group_active (peer))
3283 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3284
3285 if (connect > 65535)
3286 return BGP_ERR_INVALID_VALUE;
3287
3288 /* Set value to the configuration. */
3289 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3290 peer->connect = connect;
3291
3292 /* Set value to timer setting. */
3293 peer->v_connect = connect;
3294
3295 return 0;
3296}
3297
3298int
3299peer_timers_connect_unset (struct peer *peer)
3300{
3301 if (peer_group_active (peer))
3302 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3303
3304 /* Clear configuration. */
3305 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3306 peer->connect = 0;
3307
3308 /* Set timer setting to default value. */
3309 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3310
3311 return 0;
3312}
David Lamparter6b0655a2014-06-04 06:53:35 +02003313
paul718e3742002-12-13 20:15:29 +00003314int
3315peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3316{
3317 if (peer_group_active (peer))
3318 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3319
3320 if (routeadv > 600)
3321 return BGP_ERR_INVALID_VALUE;
3322
3323 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3324 peer->routeadv = routeadv;
3325 peer->v_routeadv = routeadv;
3326
3327 return 0;
3328}
3329
3330int
3331peer_advertise_interval_unset (struct peer *peer)
3332{
3333 if (peer_group_active (peer))
3334 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3335
3336 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3337 peer->routeadv = 0;
3338
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003339 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003340 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3341 else
3342 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3343
3344 return 0;
3345}
David Lamparter6b0655a2014-06-04 06:53:35 +02003346
paul718e3742002-12-13 20:15:29 +00003347/* neighbor interface */
3348int
paulfd79ac92004-10-13 05:06:08 +00003349peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003350{
3351 if (peer->ifname)
3352 free (peer->ifname);
3353 peer->ifname = strdup (str);
3354
3355 return 0;
3356}
3357
3358int
3359peer_interface_unset (struct peer *peer)
3360{
3361 if (peer->ifname)
3362 free (peer->ifname);
3363 peer->ifname = NULL;
3364
3365 return 0;
3366}
David Lamparter6b0655a2014-06-04 06:53:35 +02003367
paul718e3742002-12-13 20:15:29 +00003368/* Allow-as in. */
3369int
3370peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3371{
3372 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003373 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003374
3375 if (allow_num < 1 || allow_num > 10)
3376 return BGP_ERR_INVALID_VALUE;
3377
3378 if (peer->allowas_in[afi][safi] != allow_num)
3379 {
3380 peer->allowas_in[afi][safi] = allow_num;
3381 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3382 peer_change_action (peer, afi, safi, peer_change_reset_in);
3383 }
3384
3385 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3386 return 0;
3387
3388 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003389 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003390 {
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 }
3399 return 0;
3400}
3401
3402int
3403peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3404{
3405 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003406 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003407
3408 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3409 {
3410 peer->allowas_in[afi][safi] = 0;
3411 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3412 }
3413
3414 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3415 return 0;
3416
3417 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003418 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003419 {
3420 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3421 {
3422 peer->allowas_in[afi][safi] = 0;
3423 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3424 }
3425 }
3426 return 0;
3427}
David Lamparter6b0655a2014-06-04 06:53:35 +02003428
paul718e3742002-12-13 20:15:29 +00003429int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003430peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003431{
3432 struct bgp *bgp = peer->bgp;
3433 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003434 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003435
3436 if (peer_sort (peer) != BGP_PEER_EBGP
3437 && peer_sort (peer) != BGP_PEER_INTERNAL)
3438 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3439
3440 if (bgp->as == as)
3441 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3442
3443 if (peer_group_active (peer))
3444 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3445
Andrew Certain9d3f9702012-11-07 23:50:07 +00003446 if (peer->as == as)
3447 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3448
paul718e3742002-12-13 20:15:29 +00003449 if (peer->change_local_as == as &&
3450 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003451 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3452 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3453 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003454 return 0;
3455
3456 peer->change_local_as = as;
3457 if (no_prepend)
3458 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3459 else
3460 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3461
Andrew Certain9d3f9702012-11-07 23:50:07 +00003462 if (replace_as)
3463 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3464 else
3465 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3466
paul718e3742002-12-13 20:15:29 +00003467 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3468 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003469 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003470 {
3471 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3472 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3473 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3474 }
paul718e3742002-12-13 20:15:29 +00003475 else
3476 BGP_EVENT_ADD (peer, BGP_Stop);
3477
3478 return 0;
3479 }
3480
3481 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003482 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003483 {
3484 peer->change_local_as = as;
3485 if (no_prepend)
3486 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3487 else
3488 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3489
Andrew Certain9d3f9702012-11-07 23:50:07 +00003490 if (replace_as)
3491 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3492 else
3493 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3494
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003495 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003496 {
3497 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3498 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3499 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3500 }
paul718e3742002-12-13 20:15:29 +00003501 else
3502 BGP_EVENT_ADD (peer, BGP_Stop);
3503 }
3504
3505 return 0;
3506}
3507
3508int
3509peer_local_as_unset (struct peer *peer)
3510{
3511 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003512 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003513
3514 if (peer_group_active (peer))
3515 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3516
3517 if (! peer->change_local_as)
3518 return 0;
3519
3520 peer->change_local_as = 0;
3521 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003522 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003523
3524 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3525 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003526 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003527 {
3528 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3529 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3530 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3531 }
paul718e3742002-12-13 20:15:29 +00003532 else
3533 BGP_EVENT_ADD (peer, BGP_Stop);
3534
3535 return 0;
3536 }
3537
3538 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003539 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003540 {
3541 peer->change_local_as = 0;
3542 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003543 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003544
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003545 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
hassoe0701b72004-05-20 09:19:34 +00003546 {
3547 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3548 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3549 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3550 }
paul718e3742002-12-13 20:15:29 +00003551 else
3552 BGP_EVENT_ADD (peer, BGP_Stop);
3553 }
3554 return 0;
3555}
David Lamparter6b0655a2014-06-04 06:53:35 +02003556
Paul Jakma0df7c912008-07-21 21:02:49 +00003557/* Set password for authenticating with the peer. */
3558int
3559peer_password_set (struct peer *peer, const char *password)
3560{
3561 struct listnode *nn, *nnode;
3562 int len = password ? strlen(password) : 0;
3563 int ret = BGP_SUCCESS;
3564
3565 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3566 return BGP_ERR_INVALID_VALUE;
3567
3568 if (peer->password && strcmp (peer->password, password) == 0
3569 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3570 return 0;
3571
3572 if (peer->password)
3573 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3574
3575 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3576
3577 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3578 {
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003579 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
3580 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
Paul Jakma0df7c912008-07-21 21:02:49 +00003581 else
3582 BGP_EVENT_ADD (peer, BGP_Stop);
3583
3584 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3585 }
3586
3587 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3588 {
3589 if (peer->password && strcmp (peer->password, password) == 0)
3590 continue;
3591
3592 if (peer->password)
3593 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3594
3595 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3596
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003597 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003598 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3599 else
3600 BGP_EVENT_ADD (peer, BGP_Stop);
3601
3602 if (bgp_md5_set (peer) < 0)
3603 ret = BGP_ERR_TCPSIG_FAILED;
3604 }
3605
3606 return ret;
3607}
3608
3609int
3610peer_password_unset (struct peer *peer)
3611{
3612 struct listnode *nn, *nnode;
3613
3614 if (!peer->password
3615 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3616 return 0;
3617
3618 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3619 {
3620 if (peer_group_active (peer)
3621 && peer->group->conf->password
3622 && strcmp (peer->group->conf->password, peer->password) == 0)
3623 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3624
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003625 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003626 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3627 else
3628 BGP_EVENT_ADD (peer, BGP_Stop);
3629
3630 if (peer->password)
3631 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3632
3633 peer->password = NULL;
3634
3635 bgp_md5_set (peer);
3636
3637 return 0;
3638 }
3639
3640 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3641 peer->password = NULL;
3642
3643 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3644 {
3645 if (!peer->password)
3646 continue;
3647
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00003648 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
Paul Jakma0df7c912008-07-21 21:02:49 +00003649 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3650 else
3651 BGP_EVENT_ADD (peer, BGP_Stop);
3652
3653 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3654 peer->password = NULL;
3655
3656 bgp_md5_set (peer);
3657 }
3658
3659 return 0;
3660}
David Lamparter6b0655a2014-06-04 06:53:35 +02003661
paul718e3742002-12-13 20:15:29 +00003662/* Set distribute list to the peer. */
3663int
3664peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003665 const char *name)
paul718e3742002-12-13 20:15:29 +00003666{
3667 struct bgp_filter *filter;
3668 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003669 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003670
3671 if (! peer->afc[afi][safi])
3672 return BGP_ERR_PEER_INACTIVE;
3673
3674 if (direct != FILTER_IN && direct != FILTER_OUT)
3675 return BGP_ERR_INVALID_VALUE;
3676
3677 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3678 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3679
3680 filter = &peer->filter[afi][safi];
3681
3682 if (filter->plist[direct].name)
3683 return BGP_ERR_PEER_FILTER_CONFLICT;
3684
3685 if (filter->dlist[direct].name)
3686 free (filter->dlist[direct].name);
3687 filter->dlist[direct].name = strdup (name);
3688 filter->dlist[direct].alist = access_list_lookup (afi, name);
3689
3690 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3691 return 0;
3692
3693 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003694 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003695 {
3696 filter = &peer->filter[afi][safi];
3697
3698 if (! peer->af_group[afi][safi])
3699 continue;
3700
3701 if (filter->dlist[direct].name)
3702 free (filter->dlist[direct].name);
3703 filter->dlist[direct].name = strdup (name);
3704 filter->dlist[direct].alist = access_list_lookup (afi, name);
3705 }
3706
3707 return 0;
3708}
3709
3710int
3711peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3712{
3713 struct bgp_filter *filter;
3714 struct bgp_filter *gfilter;
3715 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003716 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003717
3718 if (! peer->afc[afi][safi])
3719 return BGP_ERR_PEER_INACTIVE;
3720
3721 if (direct != FILTER_IN && direct != FILTER_OUT)
3722 return BGP_ERR_INVALID_VALUE;
3723
3724 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3725 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3726
3727 filter = &peer->filter[afi][safi];
3728
3729 /* apply peer-group filter */
3730 if (peer->af_group[afi][safi])
3731 {
3732 gfilter = &peer->group->conf->filter[afi][safi];
3733
3734 if (gfilter->dlist[direct].name)
3735 {
3736 if (filter->dlist[direct].name)
3737 free (filter->dlist[direct].name);
3738 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3739 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3740 return 0;
3741 }
3742 }
3743
3744 if (filter->dlist[direct].name)
3745 free (filter->dlist[direct].name);
3746 filter->dlist[direct].name = NULL;
3747 filter->dlist[direct].alist = NULL;
3748
3749 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3750 return 0;
3751
3752 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003753 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003754 {
3755 filter = &peer->filter[afi][safi];
3756
3757 if (! peer->af_group[afi][safi])
3758 continue;
3759
3760 if (filter->dlist[direct].name)
3761 free (filter->dlist[direct].name);
3762 filter->dlist[direct].name = NULL;
3763 filter->dlist[direct].alist = NULL;
3764 }
3765
3766 return 0;
3767}
3768
3769/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003770static void
paul718e3742002-12-13 20:15:29 +00003771peer_distribute_update (struct access_list *access)
3772{
3773 afi_t afi;
3774 safi_t safi;
3775 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003776 struct listnode *mnode, *mnnode;
3777 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003778 struct bgp *bgp;
3779 struct peer *peer;
3780 struct peer_group *group;
3781 struct bgp_filter *filter;
3782
paul1eb8ef22005-04-07 07:30:20 +00003783 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003784 {
paul1eb8ef22005-04-07 07:30:20 +00003785 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003786 {
3787 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3788 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3789 {
3790 filter = &peer->filter[afi][safi];
3791
3792 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3793 {
3794 if (filter->dlist[direct].name)
3795 filter->dlist[direct].alist =
3796 access_list_lookup (afi, filter->dlist[direct].name);
3797 else
3798 filter->dlist[direct].alist = NULL;
3799 }
3800 }
3801 }
paul1eb8ef22005-04-07 07:30:20 +00003802 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003803 {
3804 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3805 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3806 {
3807 filter = &group->conf->filter[afi][safi];
3808
3809 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3810 {
3811 if (filter->dlist[direct].name)
3812 filter->dlist[direct].alist =
3813 access_list_lookup (afi, filter->dlist[direct].name);
3814 else
3815 filter->dlist[direct].alist = NULL;
3816 }
3817 }
3818 }
3819 }
3820}
David Lamparter6b0655a2014-06-04 06:53:35 +02003821
paul718e3742002-12-13 20:15:29 +00003822/* Set prefix list to the peer. */
3823int
3824peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003825 const char *name)
paul718e3742002-12-13 20:15:29 +00003826{
3827 struct bgp_filter *filter;
3828 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003829 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003830
3831 if (! peer->afc[afi][safi])
3832 return BGP_ERR_PEER_INACTIVE;
3833
3834 if (direct != FILTER_IN && direct != FILTER_OUT)
3835 return BGP_ERR_INVALID_VALUE;
3836
3837 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3838 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3839
3840 filter = &peer->filter[afi][safi];
3841
3842 if (filter->dlist[direct].name)
3843 return BGP_ERR_PEER_FILTER_CONFLICT;
3844
3845 if (filter->plist[direct].name)
3846 free (filter->plist[direct].name);
3847 filter->plist[direct].name = strdup (name);
3848 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3849
3850 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3851 return 0;
3852
3853 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003854 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003855 {
3856 filter = &peer->filter[afi][safi];
3857
3858 if (! peer->af_group[afi][safi])
3859 continue;
3860
3861 if (filter->plist[direct].name)
3862 free (filter->plist[direct].name);
3863 filter->plist[direct].name = strdup (name);
3864 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3865 }
3866 return 0;
3867}
3868
3869int
3870peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3871{
3872 struct bgp_filter *filter;
3873 struct bgp_filter *gfilter;
3874 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003875 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003876
3877 if (! peer->afc[afi][safi])
3878 return BGP_ERR_PEER_INACTIVE;
3879
3880 if (direct != FILTER_IN && direct != FILTER_OUT)
3881 return BGP_ERR_INVALID_VALUE;
3882
3883 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3884 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3885
3886 filter = &peer->filter[afi][safi];
3887
3888 /* apply peer-group filter */
3889 if (peer->af_group[afi][safi])
3890 {
3891 gfilter = &peer->group->conf->filter[afi][safi];
3892
3893 if (gfilter->plist[direct].name)
3894 {
3895 if (filter->plist[direct].name)
3896 free (filter->plist[direct].name);
3897 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3898 filter->plist[direct].plist = gfilter->plist[direct].plist;
3899 return 0;
3900 }
3901 }
3902
3903 if (filter->plist[direct].name)
3904 free (filter->plist[direct].name);
3905 filter->plist[direct].name = NULL;
3906 filter->plist[direct].plist = NULL;
3907
3908 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3909 return 0;
3910
3911 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003912 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003913 {
3914 filter = &peer->filter[afi][safi];
3915
3916 if (! peer->af_group[afi][safi])
3917 continue;
3918
3919 if (filter->plist[direct].name)
3920 free (filter->plist[direct].name);
3921 filter->plist[direct].name = NULL;
3922 filter->plist[direct].plist = NULL;
3923 }
3924
3925 return 0;
3926}
3927
3928/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003929static void
paul718e3742002-12-13 20:15:29 +00003930peer_prefix_list_update (struct prefix_list *plist)
3931{
paul1eb8ef22005-04-07 07:30:20 +00003932 struct listnode *mnode, *mnnode;
3933 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003934 struct bgp *bgp;
3935 struct peer *peer;
3936 struct peer_group *group;
3937 struct bgp_filter *filter;
3938 afi_t afi;
3939 safi_t safi;
3940 int direct;
3941
paul1eb8ef22005-04-07 07:30:20 +00003942 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003943 {
paul1eb8ef22005-04-07 07:30:20 +00003944 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003945 {
3946 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3947 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3948 {
3949 filter = &peer->filter[afi][safi];
3950
3951 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3952 {
3953 if (filter->plist[direct].name)
3954 filter->plist[direct].plist =
3955 prefix_list_lookup (afi, filter->plist[direct].name);
3956 else
3957 filter->plist[direct].plist = NULL;
3958 }
3959 }
3960 }
paul1eb8ef22005-04-07 07:30:20 +00003961 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003962 {
3963 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3964 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3965 {
3966 filter = &group->conf->filter[afi][safi];
3967
3968 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3969 {
3970 if (filter->plist[direct].name)
3971 filter->plist[direct].plist =
3972 prefix_list_lookup (afi, filter->plist[direct].name);
3973 else
3974 filter->plist[direct].plist = NULL;
3975 }
3976 }
3977 }
3978 }
3979}
David Lamparter6b0655a2014-06-04 06:53:35 +02003980
paul718e3742002-12-13 20:15:29 +00003981int
3982peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003983 const char *name)
paul718e3742002-12-13 20:15:29 +00003984{
3985 struct bgp_filter *filter;
3986 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003987 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003988
3989 if (! peer->afc[afi][safi])
3990 return BGP_ERR_PEER_INACTIVE;
3991
3992 if (direct != FILTER_IN && direct != FILTER_OUT)
3993 return BGP_ERR_INVALID_VALUE;
3994
3995 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3996 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3997
3998 filter = &peer->filter[afi][safi];
3999
4000 if (filter->aslist[direct].name)
4001 free (filter->aslist[direct].name);
4002 filter->aslist[direct].name = strdup (name);
4003 filter->aslist[direct].aslist = as_list_lookup (name);
4004
4005 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4006 return 0;
4007
4008 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004009 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004010 {
4011 filter = &peer->filter[afi][safi];
4012
4013 if (! peer->af_group[afi][safi])
4014 continue;
4015
4016 if (filter->aslist[direct].name)
4017 free (filter->aslist[direct].name);
4018 filter->aslist[direct].name = strdup (name);
4019 filter->aslist[direct].aslist = as_list_lookup (name);
4020 }
4021 return 0;
4022}
4023
4024int
4025peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4026{
4027 struct bgp_filter *filter;
4028 struct bgp_filter *gfilter;
4029 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004030 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004031
4032 if (! peer->afc[afi][safi])
4033 return BGP_ERR_PEER_INACTIVE;
4034
hassob5f29602005-05-25 21:00:28 +00004035 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004036 return BGP_ERR_INVALID_VALUE;
4037
hassob5f29602005-05-25 21:00:28 +00004038 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004039 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4040
4041 filter = &peer->filter[afi][safi];
4042
4043 /* apply peer-group filter */
4044 if (peer->af_group[afi][safi])
4045 {
4046 gfilter = &peer->group->conf->filter[afi][safi];
4047
4048 if (gfilter->aslist[direct].name)
4049 {
4050 if (filter->aslist[direct].name)
4051 free (filter->aslist[direct].name);
4052 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4053 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4054 return 0;
4055 }
4056 }
4057
4058 if (filter->aslist[direct].name)
4059 free (filter->aslist[direct].name);
4060 filter->aslist[direct].name = NULL;
4061 filter->aslist[direct].aslist = NULL;
4062
4063 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4064 return 0;
4065
4066 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004067 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004068 {
4069 filter = &peer->filter[afi][safi];
4070
4071 if (! peer->af_group[afi][safi])
4072 continue;
4073
4074 if (filter->aslist[direct].name)
4075 free (filter->aslist[direct].name);
4076 filter->aslist[direct].name = NULL;
4077 filter->aslist[direct].aslist = NULL;
4078 }
4079
4080 return 0;
4081}
4082
paul94f2b392005-06-28 12:44:16 +00004083static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004084peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004085{
4086 afi_t afi;
4087 safi_t safi;
4088 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004089 struct listnode *mnode, *mnnode;
4090 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004091 struct bgp *bgp;
4092 struct peer *peer;
4093 struct peer_group *group;
4094 struct bgp_filter *filter;
4095
paul1eb8ef22005-04-07 07:30:20 +00004096 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004097 {
paul1eb8ef22005-04-07 07:30:20 +00004098 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004099 {
4100 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4101 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4102 {
4103 filter = &peer->filter[afi][safi];
4104
4105 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4106 {
4107 if (filter->aslist[direct].name)
4108 filter->aslist[direct].aslist =
4109 as_list_lookup (filter->aslist[direct].name);
4110 else
4111 filter->aslist[direct].aslist = NULL;
4112 }
4113 }
4114 }
paul1eb8ef22005-04-07 07:30:20 +00004115 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004116 {
4117 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4118 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4119 {
4120 filter = &group->conf->filter[afi][safi];
4121
4122 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4123 {
4124 if (filter->aslist[direct].name)
4125 filter->aslist[direct].aslist =
4126 as_list_lookup (filter->aslist[direct].name);
4127 else
4128 filter->aslist[direct].aslist = NULL;
4129 }
4130 }
4131 }
4132 }
4133}
David Lamparter6b0655a2014-06-04 06:53:35 +02004134
paul718e3742002-12-13 20:15:29 +00004135/* Set route-map to the peer. */
4136int
4137peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004138 const char *name)
paul718e3742002-12-13 20:15:29 +00004139{
4140 struct bgp_filter *filter;
4141 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004142 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004143
4144 if (! peer->afc[afi][safi])
4145 return BGP_ERR_PEER_INACTIVE;
4146
paulfee0f4c2004-09-13 05:12:46 +00004147 if (direct != RMAP_IN && direct != RMAP_OUT &&
4148 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004149 return BGP_ERR_INVALID_VALUE;
4150
paulfee0f4c2004-09-13 05:12:46 +00004151 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4152 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004153 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4154
4155 filter = &peer->filter[afi][safi];
4156
4157 if (filter->map[direct].name)
4158 free (filter->map[direct].name);
4159
4160 filter->map[direct].name = strdup (name);
4161 filter->map[direct].map = route_map_lookup_by_name (name);
4162
4163 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4164 return 0;
4165
4166 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004167 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004168 {
4169 filter = &peer->filter[afi][safi];
4170
4171 if (! peer->af_group[afi][safi])
4172 continue;
4173
4174 if (filter->map[direct].name)
4175 free (filter->map[direct].name);
4176 filter->map[direct].name = strdup (name);
4177 filter->map[direct].map = route_map_lookup_by_name (name);
4178 }
4179 return 0;
4180}
4181
4182/* Unset route-map from the peer. */
4183int
4184peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4185{
4186 struct bgp_filter *filter;
4187 struct bgp_filter *gfilter;
4188 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004189 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004190
4191 if (! peer->afc[afi][safi])
4192 return BGP_ERR_PEER_INACTIVE;
4193
hassob5f29602005-05-25 21:00:28 +00004194 if (direct != RMAP_IN && direct != RMAP_OUT &&
4195 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004196 return BGP_ERR_INVALID_VALUE;
4197
hassob5f29602005-05-25 21:00:28 +00004198 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4199 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004200 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4201
4202 filter = &peer->filter[afi][safi];
4203
4204 /* apply peer-group filter */
4205 if (peer->af_group[afi][safi])
4206 {
4207 gfilter = &peer->group->conf->filter[afi][safi];
4208
4209 if (gfilter->map[direct].name)
4210 {
4211 if (filter->map[direct].name)
4212 free (filter->map[direct].name);
4213 filter->map[direct].name = strdup (gfilter->map[direct].name);
4214 filter->map[direct].map = gfilter->map[direct].map;
4215 return 0;
4216 }
4217 }
4218
4219 if (filter->map[direct].name)
4220 free (filter->map[direct].name);
4221 filter->map[direct].name = NULL;
4222 filter->map[direct].map = NULL;
4223
4224 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4225 return 0;
4226
4227 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004228 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004229 {
4230 filter = &peer->filter[afi][safi];
4231
4232 if (! peer->af_group[afi][safi])
4233 continue;
4234
4235 if (filter->map[direct].name)
4236 free (filter->map[direct].name);
4237 filter->map[direct].name = NULL;
4238 filter->map[direct].map = NULL;
4239 }
4240 return 0;
4241}
David Lamparter6b0655a2014-06-04 06:53:35 +02004242
paul718e3742002-12-13 20:15:29 +00004243/* Set unsuppress-map to the peer. */
4244int
paulfd79ac92004-10-13 05:06:08 +00004245peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4246 const char *name)
paul718e3742002-12-13 20:15:29 +00004247{
4248 struct bgp_filter *filter;
4249 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004250 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004251
4252 if (! peer->afc[afi][safi])
4253 return BGP_ERR_PEER_INACTIVE;
4254
4255 if (peer_is_group_member (peer, afi, safi))
4256 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4257
4258 filter = &peer->filter[afi][safi];
4259
4260 if (filter->usmap.name)
4261 free (filter->usmap.name);
4262
4263 filter->usmap.name = strdup (name);
4264 filter->usmap.map = route_map_lookup_by_name (name);
4265
4266 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4267 return 0;
4268
4269 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004270 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004271 {
4272 filter = &peer->filter[afi][safi];
4273
4274 if (! peer->af_group[afi][safi])
4275 continue;
4276
4277 if (filter->usmap.name)
4278 free (filter->usmap.name);
4279 filter->usmap.name = strdup (name);
4280 filter->usmap.map = route_map_lookup_by_name (name);
4281 }
4282 return 0;
4283}
4284
4285/* Unset route-map from the peer. */
4286int
4287peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4288{
4289 struct bgp_filter *filter;
4290 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004291 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004292
4293 if (! peer->afc[afi][safi])
4294 return BGP_ERR_PEER_INACTIVE;
4295
4296 if (peer_is_group_member (peer, afi, safi))
4297 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4298
4299 filter = &peer->filter[afi][safi];
4300
4301 if (filter->usmap.name)
4302 free (filter->usmap.name);
4303 filter->usmap.name = NULL;
4304 filter->usmap.map = NULL;
4305
4306 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4307 return 0;
4308
4309 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004310 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004311 {
4312 filter = &peer->filter[afi][safi];
4313
4314 if (! peer->af_group[afi][safi])
4315 continue;
4316
4317 if (filter->usmap.name)
4318 free (filter->usmap.name);
4319 filter->usmap.name = NULL;
4320 filter->usmap.map = NULL;
4321 }
4322 return 0;
4323}
David Lamparter6b0655a2014-06-04 06:53:35 +02004324
paul718e3742002-12-13 20:15:29 +00004325int
4326peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004327 u_int32_t max, u_char threshold,
4328 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004329{
4330 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004331 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004332
4333 if (! peer->afc[afi][safi])
4334 return BGP_ERR_PEER_INACTIVE;
4335
4336 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4337 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004338 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004339 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004340 if (warning)
4341 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4342 else
4343 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4344
4345 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4346 return 0;
4347
4348 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004349 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004350 {
4351 if (! peer->af_group[afi][safi])
4352 continue;
4353
4354 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4355 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004356 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004357 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004358 if (warning)
4359 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4360 else
4361 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4362 }
4363 return 0;
4364}
4365
4366int
4367peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4368{
4369 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004370 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004371
4372 if (! peer->afc[afi][safi])
4373 return BGP_ERR_PEER_INACTIVE;
4374
4375 /* apply peer-group config */
4376 if (peer->af_group[afi][safi])
4377 {
4378 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4379 PEER_FLAG_MAX_PREFIX))
4380 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4381 else
4382 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4383
4384 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4385 PEER_FLAG_MAX_PREFIX_WARNING))
4386 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4387 else
4388 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4389
4390 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004391 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004392 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004393 return 0;
4394 }
4395
4396 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4397 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4398 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004399 peer->pmax_threshold[afi][safi] = 0;
4400 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004401
4402 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4403 return 0;
4404
4405 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004406 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004407 {
4408 if (! peer->af_group[afi][safi])
4409 continue;
4410
4411 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4412 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4413 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004414 peer->pmax_threshold[afi][safi] = 0;
4415 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004416 }
4417 return 0;
4418}
David Lamparter5f9adb52014-05-19 23:15:02 +02004419
4420static int is_ebgp_multihop_configured (struct peer *peer)
4421{
4422 struct peer_group *group;
4423 struct listnode *node, *nnode;
4424 struct peer *peer1;
4425
4426 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4427 {
4428 group = peer->group;
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004429 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4430 (group->conf->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004431 return 1;
4432
4433 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4434 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004435 if ((peer_sort (peer1) != BGP_PEER_IBGP) &&
4436 (peer1->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004437 return 1;
4438 }
4439 }
4440 else
4441 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004442 if ((peer_sort(peer) != BGP_PEER_IBGP) &&
4443 (peer->ttl != 1))
David Lamparter5f9adb52014-05-19 23:15:02 +02004444 return 1;
4445 }
4446 return 0;
4447}
4448
Nick Hilliardfa411a22011-03-23 15:33:17 +00004449/* Set # of hops between us and BGP peer. */
4450int
4451peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4452{
4453 struct peer_group *group;
4454 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004455 int ret;
4456
4457 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4458
Nick Hilliardfa411a22011-03-23 15:33:17 +00004459 /* We cannot configure ttl-security hops when ebgp-multihop is already
4460 set. For non peer-groups, the check is simple. For peer-groups, it's
4461 slightly messy, because we need to check both the peer-group structure
4462 and all peer-group members for any trace of ebgp-multihop configuration
4463 before actually applying the ttl-security rules. Cisco really made a
4464 mess of this configuration parameter, and OpenBGPD got it right.
4465 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004466
David Lamparter5f9adb52014-05-19 23:15:02 +02004467 if (peer->gtsm_hops == 0)
4468 {
4469 if (is_ebgp_multihop_configured (peer))
4470 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004471
David Lamparter5f9adb52014-05-19 23:15:02 +02004472 /* specify MAXTTL on outgoing packets */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004473 /* Routine handles iBGP peers correctly */
David Lamparter5f9adb52014-05-19 23:15:02 +02004474 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4475 if (ret != 0)
4476 return ret;
4477 }
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004478
Nick Hilliardfa411a22011-03-23 15:33:17 +00004479 peer->gtsm_hops = gtsm_hops;
4480
Nick Hilliardfa411a22011-03-23 15:33:17 +00004481 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4482 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004483 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004484 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4485 }
4486 else
4487 {
4488 group = peer->group;
4489 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4490 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004491 peer->gtsm_hops = group->conf->gtsm_hops;
4492
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004493 /* Change setting of existing peer
4494 * established then change value (may break connectivity)
4495 * not established yet (teardown session and restart)
4496 * no session then do nothing (will get handled by next connection)
4497 */
4498 if (peer->status == Established)
4499 {
4500 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4501 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4502 MAXTTL + 1 - peer->gtsm_hops);
4503 }
4504 else if (peer->status < Established)
4505 {
4506 if (BGP_DEBUG (events, EVENTS))
4507 zlog_debug ("%s Min-ttl changed", peer->host);
4508 BGP_EVENT_ADD (peer, BGP_Stop);
4509 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004510 }
4511 }
4512
4513 return 0;
4514}
4515
4516int
4517peer_ttl_security_hops_unset (struct peer *peer)
4518{
4519 struct peer_group *group;
4520 struct listnode *node, *nnode;
4521 struct peer *opeer;
4522
4523 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4524
Nick Hilliardfa411a22011-03-23 15:33:17 +00004525 /* if a peer-group member, then reset to peer-group default rather than 0 */
4526 if (peer_group_active (peer))
4527 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4528 else
4529 peer->gtsm_hops = 0;
4530
4531 opeer = peer;
4532 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4533 {
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004534 if (peer->fd >= 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004535 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4536 }
4537 else
4538 {
4539 group = peer->group;
4540 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4541 {
Nick Hilliardfa411a22011-03-23 15:33:17 +00004542 peer->gtsm_hops = 0;
4543
4544 if (peer->fd >= 0)
4545 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4546 }
4547 }
4548
4549 return peer_ebgp_multihop_unset (opeer);
4550}
David Lamparter6b0655a2014-06-04 06:53:35 +02004551
paul718e3742002-12-13 20:15:29 +00004552int
4553peer_clear (struct peer *peer)
4554{
4555 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4556 {
hasso0a486e52005-02-01 20:57:17 +00004557 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4558 {
4559 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4560 if (peer->t_pmax_restart)
4561 {
4562 BGP_TIMER_OFF (peer->t_pmax_restart);
4563 if (BGP_DEBUG (events, EVENTS))
4564 zlog_debug ("%s Maximum-prefix restart timer canceled",
4565 peer->host);
4566 }
4567 BGP_EVENT_ADD (peer, BGP_Start);
4568 return 0;
4569 }
4570
paul718e3742002-12-13 20:15:29 +00004571 peer->v_start = BGP_INIT_START_TIMER;
Vitaliy Senchyshyn6aa136f2013-10-02 10:40:20 +00004572 if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
paul718e3742002-12-13 20:15:29 +00004573 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4574 BGP_NOTIFY_CEASE_ADMIN_RESET);
4575 else
4576 BGP_EVENT_ADD (peer, BGP_Stop);
4577 }
4578 return 0;
4579}
4580
4581int
4582peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4583 enum bgp_clear_type stype)
4584{
4585 if (peer->status != Established)
4586 return 0;
4587
4588 if (! peer->afc[afi][safi])
4589 return BGP_ERR_AF_UNCONFIGURED;
4590
paulfee0f4c2004-09-13 05:12:46 +00004591 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4592 {
4593 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4594 return 0;
4595 bgp_check_local_routes_rsclient (peer, afi, safi);
4596 bgp_soft_reconfig_rsclient (peer, afi, safi);
4597 }
4598
paul718e3742002-12-13 20:15:29 +00004599 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4600 bgp_announce_route (peer, afi, safi);
4601
4602 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4603 {
4604 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4605 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4606 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4607 {
4608 struct bgp_filter *filter = &peer->filter[afi][safi];
4609 u_char prefix_type;
4610
4611 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4612 prefix_type = ORF_TYPE_PREFIX;
4613 else
4614 prefix_type = ORF_TYPE_PREFIX_OLD;
4615
4616 if (filter->plist[FILTER_IN].plist)
4617 {
4618 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4619 bgp_route_refresh_send (peer, afi, safi,
4620 prefix_type, REFRESH_DEFER, 1);
4621 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4622 REFRESH_IMMEDIATE, 0);
4623 }
4624 else
4625 {
4626 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4627 bgp_route_refresh_send (peer, afi, safi,
4628 prefix_type, REFRESH_IMMEDIATE, 1);
4629 else
4630 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4631 }
4632 return 0;
4633 }
4634 }
4635
4636 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4637 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4638 {
4639 /* If neighbor has soft reconfiguration inbound flag.
4640 Use Adj-RIB-In database. */
4641 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4642 bgp_soft_reconfig_in (peer, afi, safi);
4643 else
4644 {
4645 /* If neighbor has route refresh capability, send route refresh
4646 message to the peer. */
4647 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4648 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4649 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4650 else
4651 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4652 }
4653 }
4654 return 0;
4655}
David Lamparter6b0655a2014-06-04 06:53:35 +02004656
paulfd79ac92004-10-13 05:06:08 +00004657/* Display peer uptime.*/
4658/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004659char *
4660peer_uptime (time_t uptime2, char *buf, size_t len)
4661{
4662 time_t uptime1;
4663 struct tm *tm;
4664
4665 /* Check buffer length. */
4666 if (len < BGP_UPTIME_LEN)
4667 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004668 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004669 /* XXX: should return status instead of buf... */
4670 snprintf (buf, len, "<error> ");
4671 return buf;
paul718e3742002-12-13 20:15:29 +00004672 }
4673
4674 /* If there is no connection has been done before print `never'. */
4675 if (uptime2 == 0)
4676 {
4677 snprintf (buf, len, "never ");
4678 return buf;
4679 }
4680
4681 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004682 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004683 uptime1 -= uptime2;
4684 tm = gmtime (&uptime1);
4685
4686 /* Making formatted timer strings. */
4687#define ONE_DAY_SECOND 60*60*24
4688#define ONE_WEEK_SECOND 60*60*24*7
4689
4690 if (uptime1 < ONE_DAY_SECOND)
4691 snprintf (buf, len, "%02d:%02d:%02d",
4692 tm->tm_hour, tm->tm_min, tm->tm_sec);
4693 else if (uptime1 < ONE_WEEK_SECOND)
4694 snprintf (buf, len, "%dd%02dh%02dm",
4695 tm->tm_yday, tm->tm_hour, tm->tm_min);
4696 else
4697 snprintf (buf, len, "%02dw%dd%02dh",
4698 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4699 return buf;
4700}
David Lamparter6b0655a2014-06-04 06:53:35 +02004701
paul94f2b392005-06-28 12:44:16 +00004702static void
paul718e3742002-12-13 20:15:29 +00004703bgp_config_write_filter (struct vty *vty, struct peer *peer,
4704 afi_t afi, safi_t safi)
4705{
4706 struct bgp_filter *filter;
4707 struct bgp_filter *gfilter = NULL;
4708 char *addr;
4709 int in = FILTER_IN;
4710 int out = FILTER_OUT;
4711
4712 addr = peer->host;
4713 filter = &peer->filter[afi][safi];
4714 if (peer->af_group[afi][safi])
4715 gfilter = &peer->group->conf->filter[afi][safi];
4716
4717 /* distribute-list. */
4718 if (filter->dlist[in].name)
4719 if (! gfilter || ! gfilter->dlist[in].name
4720 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4721 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4722 filter->dlist[in].name, VTY_NEWLINE);
4723 if (filter->dlist[out].name && ! gfilter)
4724 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4725 filter->dlist[out].name, VTY_NEWLINE);
4726
4727 /* prefix-list. */
4728 if (filter->plist[in].name)
4729 if (! gfilter || ! gfilter->plist[in].name
4730 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4731 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4732 filter->plist[in].name, VTY_NEWLINE);
4733 if (filter->plist[out].name && ! gfilter)
4734 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4735 filter->plist[out].name, VTY_NEWLINE);
4736
4737 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004738 if (filter->map[RMAP_IN].name)
4739 if (! gfilter || ! gfilter->map[RMAP_IN].name
4740 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004741 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004742 filter->map[RMAP_IN].name, VTY_NEWLINE);
4743 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004744 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004745 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4746 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4747 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4748 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4749 if (filter->map[RMAP_EXPORT].name)
4750 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4751 || strcmp (filter->map[RMAP_EXPORT].name,
4752 gfilter->map[RMAP_EXPORT].name) != 0)
4753 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4754 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004755
4756 /* unsuppress-map */
4757 if (filter->usmap.name && ! gfilter)
4758 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4759 filter->usmap.name, VTY_NEWLINE);
4760
4761 /* filter-list. */
4762 if (filter->aslist[in].name)
4763 if (! gfilter || ! gfilter->aslist[in].name
4764 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4765 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4766 filter->aslist[in].name, VTY_NEWLINE);
4767 if (filter->aslist[out].name && ! gfilter)
4768 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4769 filter->aslist[out].name, VTY_NEWLINE);
4770}
4771
4772/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004773static void
paul718e3742002-12-13 20:15:29 +00004774bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4775 struct peer *peer, afi_t afi, safi_t safi)
4776{
paul718e3742002-12-13 20:15:29 +00004777 struct peer *g_peer = NULL;
4778 char buf[SU_ADDRSTRLEN];
4779 char *addr;
4780
paul718e3742002-12-13 20:15:29 +00004781 addr = peer->host;
4782 if (peer_group_active (peer))
4783 g_peer = peer->group->conf;
4784
4785 /************************************
4786 ****** Global to the neighbor ******
4787 ************************************/
4788 if (afi == AFI_IP && safi == SAFI_UNICAST)
4789 {
4790 /* remote-as. */
4791 if (! peer_group_active (peer))
4792 {
4793 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4794 vty_out (vty, " neighbor %s peer-group%s", addr,
4795 VTY_NEWLINE);
4796 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004797 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004798 VTY_NEWLINE);
4799 }
4800 else
4801 {
4802 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004803 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004804 VTY_NEWLINE);
4805 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4806 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4807 peer->group->name, VTY_NEWLINE);
4808 }
4809
4810 /* local-as. */
4811 if (peer->change_local_as)
4812 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00004813 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004814 peer->change_local_as,
4815 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00004816 " no-prepend" : "",
4817 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
4818 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004819
4820 /* Description. */
4821 if (peer->desc)
4822 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4823 VTY_NEWLINE);
4824
4825 /* Shutdown. */
4826 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4827 if (! peer_group_active (peer) ||
4828 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4829 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4830
Paul Jakma0df7c912008-07-21 21:02:49 +00004831 /* Password. */
4832 if (peer->password)
4833 if (!peer_group_active (peer)
4834 || ! g_peer->password
4835 || strcmp (peer->password, g_peer->password) != 0)
4836 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4837 VTY_NEWLINE);
4838
paul718e3742002-12-13 20:15:29 +00004839 /* BGP port. */
4840 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004841 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004842 VTY_NEWLINE);
4843
4844 /* Local interface name. */
4845 if (peer->ifname)
4846 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4847 VTY_NEWLINE);
4848
4849 /* Passive. */
4850 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4851 if (! peer_group_active (peer) ||
4852 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4853 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4854
4855 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004856 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00004857 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00004858 if (! peer_group_active (peer) ||
4859 g_peer->ttl != peer->ttl)
4860 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4861 VTY_NEWLINE);
4862
Nick Hilliardfa411a22011-03-23 15:33:17 +00004863 /* ttl-security hops */
Pradosh Mohapatra5d804b42013-09-12 03:37:07 +00004864 if (peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004865 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004866 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00004867 peer->gtsm_hops, VTY_NEWLINE);
4868
hasso6ffd2072005-02-02 14:50:11 +00004869 /* disable-connected-check. */
4870 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004871 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004872 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4873 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004874
4875 /* Update-source. */
4876 if (peer->update_if)
4877 if (! peer_group_active (peer) || ! g_peer->update_if
4878 || strcmp (g_peer->update_if, peer->update_if) != 0)
4879 vty_out (vty, " neighbor %s update-source %s%s", addr,
4880 peer->update_if, VTY_NEWLINE);
4881 if (peer->update_source)
4882 if (! peer_group_active (peer) || ! g_peer->update_source
4883 || sockunion_cmp (g_peer->update_source,
4884 peer->update_source) != 0)
4885 vty_out (vty, " neighbor %s update-source %s%s", addr,
4886 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4887 VTY_NEWLINE);
4888
paul718e3742002-12-13 20:15:29 +00004889 /* advertisement-interval */
4890 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4891 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4892 addr, peer->v_routeadv, VTY_NEWLINE);
4893
4894 /* timers. */
4895 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4896 && ! peer_group_active (peer))
4897 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4898 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4899
4900 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4901 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4902 peer->connect, VTY_NEWLINE);
4903
4904 /* Default weight. */
4905 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4906 if (! peer_group_active (peer) ||
4907 g_peer->weight != peer->weight)
4908 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4909 VTY_NEWLINE);
4910
paul718e3742002-12-13 20:15:29 +00004911 /* Dynamic capability. */
4912 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4913 if (! peer_group_active (peer) ||
4914 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4915 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4916 VTY_NEWLINE);
4917
4918 /* dont capability negotiation. */
4919 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4920 if (! peer_group_active (peer) ||
4921 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4922 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4923 VTY_NEWLINE);
4924
4925 /* override capability negotiation. */
4926 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4927 if (! peer_group_active (peer) ||
4928 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4929 vty_out (vty, " neighbor %s override-capability%s", addr,
4930 VTY_NEWLINE);
4931
4932 /* strict capability negotiation. */
4933 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4934 if (! peer_group_active (peer) ||
4935 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4936 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4937 VTY_NEWLINE);
4938
Christian Franke15c71342012-11-19 11:17:31 +00004939 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
paul718e3742002-12-13 20:15:29 +00004940 {
4941 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4942 {
4943 if (peer->afc[AFI_IP][SAFI_UNICAST])
4944 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4945 }
4946 else
4947 {
4948 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4949 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4950 }
4951 }
4952 }
4953
4954
4955 /************************************
4956 ****** Per AF to the neighbor ******
4957 ************************************/
4958
4959 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4960 {
4961 if (peer->af_group[afi][safi])
4962 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4963 peer->group->name, VTY_NEWLINE);
4964 else
4965 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4966 }
4967
4968 /* ORF capability. */
4969 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4970 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4971 if (! peer->af_group[afi][safi])
4972 {
4973 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4974
4975 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4976 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4977 vty_out (vty, " both");
4978 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4979 vty_out (vty, " send");
4980 else
4981 vty_out (vty, " receive");
4982 vty_out (vty, "%s", VTY_NEWLINE);
4983 }
4984
4985 /* Route reflector client. */
4986 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4987 && ! peer->af_group[afi][safi])
4988 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4989 VTY_NEWLINE);
4990
4991 /* Nexthop self. */
4992 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4993 && ! peer->af_group[afi][safi])
Timo Teräs9e7a53c2014-04-24 10:22:37 +03004994 vty_out (vty, " neighbor %s next-hop-self%s%s", addr,
4995 peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF_ALL) ?
4996 " all" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004997
4998 /* Remove private AS. */
4999 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
5000 && ! peer->af_group[afi][safi])
5001 vty_out (vty, " neighbor %s remove-private-AS%s",
5002 addr, VTY_NEWLINE);
5003
5004 /* send-community print. */
5005 if (! peer->af_group[afi][safi])
5006 {
5007 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5008 {
5009 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5010 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5011 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
5012 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5013 vty_out (vty, " neighbor %s send-community extended%s",
5014 addr, VTY_NEWLINE);
5015 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5016 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
5017 }
5018 else
5019 {
5020 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
5021 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5022 vty_out (vty, " no neighbor %s send-community both%s",
5023 addr, VTY_NEWLINE);
5024 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5025 vty_out (vty, " no neighbor %s send-community extended%s",
5026 addr, VTY_NEWLINE);
5027 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5028 vty_out (vty, " no neighbor %s send-community%s",
5029 addr, VTY_NEWLINE);
5030 }
5031 }
5032
5033 /* Default information */
5034 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5035 && ! peer->af_group[afi][safi])
5036 {
5037 vty_out (vty, " neighbor %s default-originate", addr);
5038 if (peer->default_rmap[afi][safi].name)
5039 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5040 vty_out (vty, "%s", VTY_NEWLINE);
5041 }
5042
5043 /* Soft reconfiguration inbound. */
5044 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5045 if (! peer->af_group[afi][safi] ||
5046 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5047 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5048 VTY_NEWLINE);
5049
5050 /* maximum-prefix. */
5051 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5052 if (! peer->af_group[afi][safi]
5053 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005054 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005055 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5056 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005057 {
hasso0a486e52005-02-01 20:57:17 +00005058 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5059 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5060 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5061 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5062 vty_out (vty, " warning-only");
5063 if (peer->pmax_restart[afi][safi])
5064 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5065 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005066 }
paul718e3742002-12-13 20:15:29 +00005067
5068 /* Route server client. */
5069 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5070 && ! peer->af_group[afi][safi])
5071 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5072
Dylan Hall3cf12882011-10-27 15:28:17 +04005073 /* Nexthop-local unchanged. */
5074 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5075 && ! peer->af_group[afi][safi])
5076 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5077
paul718e3742002-12-13 20:15:29 +00005078 /* Allow AS in. */
5079 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5080 if (! peer_group_active (peer)
5081 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5082 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5083 {
5084 if (peer->allowas_in[afi][safi] == 3)
5085 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5086 else
5087 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5088 peer->allowas_in[afi][safi], VTY_NEWLINE);
5089 }
5090
5091 /* Filter. */
5092 bgp_config_write_filter (vty, peer, afi, safi);
5093
5094 /* atribute-unchanged. */
5095 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5096 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5097 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5098 && ! peer->af_group[afi][safi])
5099 {
5100 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5101 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5102 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5103 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5104 else
5105 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5106 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5107 " as-path" : "",
5108 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5109 " next-hop" : "",
5110 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5111 " med" : "", VTY_NEWLINE);
5112 }
5113}
5114
5115/* Display "address-family" configuration header. */
5116void
5117bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5118 int *write)
5119{
5120 if (*write)
5121 return;
5122
5123 if (afi == AFI_IP && safi == SAFI_UNICAST)
5124 return;
5125
5126 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5127
5128 if (afi == AFI_IP)
5129 {
5130 if (safi == SAFI_MULTICAST)
5131 vty_out (vty, "ipv4 multicast");
5132 else if (safi == SAFI_MPLS_VPN)
5133 vty_out (vty, "vpnv4 unicast");
5134 }
5135 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005136 {
5137 vty_out (vty, "ipv6");
5138
5139 if (safi == SAFI_MULTICAST)
5140 vty_out (vty, " multicast");
5141 }
paul718e3742002-12-13 20:15:29 +00005142
5143 vty_out (vty, "%s", VTY_NEWLINE);
5144
5145 *write = 1;
5146}
5147
5148/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005149static int
paul718e3742002-12-13 20:15:29 +00005150bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5151 safi_t safi)
5152{
5153 int write = 0;
5154 struct peer *peer;
5155 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005156 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005157
5158 bgp_config_write_network (vty, bgp, afi, safi, &write);
5159
5160 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5161
paul1eb8ef22005-04-07 07:30:20 +00005162 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005163 {
5164 if (group->conf->afc[afi][safi])
5165 {
5166 bgp_config_write_family_header (vty, afi, safi, &write);
5167 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5168 }
5169 }
paul1eb8ef22005-04-07 07:30:20 +00005170 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005171 {
5172 if (peer->afc[afi][safi])
5173 {
5174 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5175 {
5176 bgp_config_write_family_header (vty, afi, safi, &write);
5177 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5178 }
5179 }
5180 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005181
5182 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5183
paul718e3742002-12-13 20:15:29 +00005184 if (write)
5185 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5186
5187 return write;
5188}
5189
5190int
5191bgp_config_write (struct vty *vty)
5192{
5193 int write = 0;
5194 struct bgp *bgp;
5195 struct peer_group *group;
5196 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005197 struct listnode *node, *nnode;
5198 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005199
5200 /* BGP Multiple instance. */
5201 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5202 {
5203 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5204 write++;
5205 }
5206
5207 /* BGP Config type. */
5208 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5209 {
5210 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5211 write++;
5212 }
5213
5214 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005215 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005216 {
5217 if (write)
5218 vty_out (vty, "!%s", VTY_NEWLINE);
5219
5220 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005221 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005222
5223 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5224 {
5225 if (bgp->name)
5226 vty_out (vty, " view %s", bgp->name);
5227 }
5228 vty_out (vty, "%s", VTY_NEWLINE);
5229
5230 /* No Synchronization */
5231 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5232 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5233
5234 /* BGP fast-external-failover. */
5235 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5236 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5237
5238 /* BGP router ID. */
5239 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5240 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5241 VTY_NEWLINE);
5242
paul848973c2003-08-13 00:32:49 +00005243 /* BGP log-neighbor-changes. */
5244 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5245 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
5246
paul718e3742002-12-13 20:15:29 +00005247 /* BGP configuration. */
5248 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5249 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5250
5251 /* BGP default ipv4-unicast. */
5252 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5253 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5254
5255 /* BGP default local-preference. */
5256 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5257 vty_out (vty, " bgp default local-preference %d%s",
5258 bgp->default_local_pref, VTY_NEWLINE);
5259
5260 /* BGP client-to-client reflection. */
5261 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5262 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5263
5264 /* BGP cluster ID. */
5265 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5266 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5267 VTY_NEWLINE);
5268
hassoe0701b72004-05-20 09:19:34 +00005269 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005270 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005271 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5272 VTY_NEWLINE);
5273
5274 /* Confederation peer */
5275 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005276 {
hassoe0701b72004-05-20 09:19:34 +00005277 int i;
paul718e3742002-12-13 20:15:29 +00005278
hassoe0701b72004-05-20 09:19:34 +00005279 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005280
hassoe0701b72004-05-20 09:19:34 +00005281 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005282 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005283
hassoe0701b72004-05-20 09:19:34 +00005284 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005285 }
5286
5287 /* BGP enforce-first-as. */
5288 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5289 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5290
5291 /* BGP deterministic-med. */
5292 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5293 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005294
5295 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005296 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5297 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5298 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005299 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5300 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5301
paul718e3742002-12-13 20:15:29 +00005302 /* BGP bestpath method. */
5303 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5304 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005305 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5306 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
Pradosh Mohapatra2fdd4552013-09-07 07:02:36 +00005307 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
5308 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
5309 }
paul718e3742002-12-13 20:15:29 +00005310 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5311 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5312 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5313 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5314 {
5315 vty_out (vty, " bgp bestpath med");
5316 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5317 vty_out (vty, " confed");
5318 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5319 vty_out (vty, " missing-as-worst");
5320 vty_out (vty, "%s", VTY_NEWLINE);
5321 }
5322
5323 /* BGP network import check. */
5324 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5325 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5326
5327 /* BGP scan interval. */
5328 bgp_config_write_scan_time (vty);
5329
5330 /* BGP flag dampening. */
5331 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5332 BGP_CONFIG_DAMPENING))
5333 bgp_config_write_damp (vty);
5334
5335 /* BGP static route configuration. */
5336 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5337
5338 /* BGP redistribute configuration. */
5339 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5340
5341 /* BGP timers configuration. */
5342 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5343 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5344 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5345 bgp->default_holdtime, VTY_NEWLINE);
5346
5347 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005348 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005349 {
5350 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5351 }
5352
5353 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005354 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005355 {
5356 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5357 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5358 }
5359
Josh Bailey165b5ff2011-07-20 20:43:22 -07005360 /* maximum-paths */
5361 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5362
paul718e3742002-12-13 20:15:29 +00005363 /* Distance configuration. */
5364 bgp_config_write_distance (vty, bgp);
5365
5366 /* No auto-summary */
5367 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5368 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5369
5370 /* IPv4 multicast configuration. */
5371 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5372
5373 /* IPv4 VPN configuration. */
5374 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5375
5376 /* IPv6 unicast configuration. */
5377 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5378
Paul Jakma37a217a2007-04-10 19:20:29 +00005379 /* IPv6 multicast configuration. */
5380 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5381
paul718e3742002-12-13 20:15:29 +00005382 write++;
5383 }
5384 return write;
5385}
5386
5387void
paul94f2b392005-06-28 12:44:16 +00005388bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005389{
5390 memset (&bgp_master, 0, sizeof (struct bgp_master));
5391
5392 bm = &bgp_master;
5393 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005394 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005395 bm->port = BGP_PORT_DEFAULT;
5396 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005397 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005398}
paul200df112005-06-01 11:17:05 +00005399
David Lamparter6b0655a2014-06-04 06:53:35 +02005400
paul718e3742002-12-13 20:15:29 +00005401void
paul94f2b392005-06-28 12:44:16 +00005402bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005403{
paul718e3742002-12-13 20:15:29 +00005404 /* BGP VTY commands installation. */
5405 bgp_vty_init ();
5406
paul718e3742002-12-13 20:15:29 +00005407 /* Init zebra. */
5408 bgp_zebra_init ();
5409
5410 /* BGP inits. */
5411 bgp_attr_init ();
5412 bgp_debug_init ();
5413 bgp_dump_init ();
5414 bgp_route_init ();
5415 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005416 bgp_address_init ();
paul718e3742002-12-13 20:15:29 +00005417 bgp_scan_init ();
5418 bgp_mplsvpn_init ();
5419
5420 /* Access list initialize. */
5421 access_list_init ();
5422 access_list_add_hook (peer_distribute_update);
5423 access_list_delete_hook (peer_distribute_update);
5424
5425 /* Filter list initialize. */
5426 bgp_filter_init ();
5427 as_list_add_hook (peer_aslist_update);
5428 as_list_delete_hook (peer_aslist_update);
5429
5430 /* Prefix list initialize.*/
5431 prefix_list_init ();
5432 prefix_list_add_hook (peer_prefix_list_update);
5433 prefix_list_delete_hook (peer_prefix_list_update);
5434
5435 /* Community list initialize. */
5436 bgp_clist = community_list_init ();
5437
5438#ifdef HAVE_SNMP
5439 bgp_snmp_init ();
5440#endif /* HAVE_SNMP */
5441}
paul545acaf2004-04-20 15:13:15 +00005442
5443void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005444bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005445{
paul545acaf2004-04-20 15:13:15 +00005446 struct bgp *bgp;
5447 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005448 struct listnode *node, *nnode;
5449 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005450
paul1eb8ef22005-04-07 07:30:20 +00005451 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5452 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005453 if (peer->status == Established)
5454 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5455 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005456
paul545acaf2004-04-20 15:13:15 +00005457 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005458
paule210cf92005-06-15 19:15:35 +00005459 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005460 {
5461 work_queue_free (bm->process_main_queue);
5462 bm->process_main_queue = NULL;
5463 }
paule210cf92005-06-15 19:15:35 +00005464 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005465 {
5466 work_queue_free (bm->process_rsclient_queue);
5467 bm->process_rsclient_queue = NULL;
5468 }
paul545acaf2004-04-20 15:13:15 +00005469}