blob: 4b26993e73b21bc85ef8694d5abecbc522d97a2d [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 */
64
65/* 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;
75
76/* 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}
118
119/* 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}
139
140/* 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}
158
159/* 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
178 if (peer->status == Established)
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
208 if (peer->status == Established)
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
236 if (peer->status == Established)
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}
245
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}
276
277/* 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;
305 if (peer->status == Established)
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;
325 if (peer->status == Established)
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;
354 if (peer->status == Established)
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;
418 if (peer->status == Established)
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;
474 if (peer->status == Established)
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}
488
489/* 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}
511
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);
835
836 bgp_sync_init (peer);
837
838 /* Get service port number. */
839 sp = getservbyname ("bgp", "tcp");
840 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
841
842 return peer;
843}
844
845/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000846static struct peer *
paul718e3742002-12-13 20:15:29 +0000847peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
848 as_t remote_as, afi_t afi, safi_t safi)
849{
850 int active;
851 struct peer *peer;
852 char buf[SU_ADDRSTRLEN];
853
Paul Jakma6f585442006-10-22 19:13:07 +0000854 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000855 peer->su = *su;
856 peer->local_as = local_as;
857 peer->as = remote_as;
858 peer->local_id = bgp->router_id;
859 peer->v_holdtime = bgp->default_holdtime;
860 peer->v_keepalive = bgp->default_keepalive;
861 if (peer_sort (peer) == BGP_PEER_IBGP)
862 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
863 else
864 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000865
866 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000867 listnode_add_sort (bgp->peer, peer);
868
869 active = peer_active (peer);
870
871 if (afi && safi)
872 peer->afc[afi][safi] = 1;
873
Stephen Hemminger65957882010-01-15 16:22:10 +0300874 /* Last read and reset time set */
875 peer->readtime = peer->resettime = bgp_clock ();
paul848973c2003-08-13 00:32:49 +0000876
paul718e3742002-12-13 20:15:29 +0000877 /* Default TTL set. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000878 peer->ttl = (peer->sort == BGP_PEER_IBGP) ? 255 : 1;
paul718e3742002-12-13 20:15:29 +0000879
880 /* Make peer's address string. */
881 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000882 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000883
884 /* Set up peer's events and timers. */
885 if (! active && peer_active (peer))
886 bgp_timer_set (peer);
887
888 return peer;
889}
890
pauleb821182004-05-01 08:44:08 +0000891/* Make accept BGP peer. Called from bgp_accept (). */
892struct peer *
893peer_create_accept (struct bgp *bgp)
894{
895 struct peer *peer;
896
Paul Jakma6f585442006-10-22 19:13:07 +0000897 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000898
899 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000900 listnode_add_sort (bgp->peer, peer);
901
902 return peer;
903}
904
paul718e3742002-12-13 20:15:29 +0000905/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000906static void
paul718e3742002-12-13 20:15:29 +0000907peer_as_change (struct peer *peer, as_t as)
908{
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +0000909 bgp_peer_sort_t type;
paul718e3742002-12-13 20:15:29 +0000910
911 /* Stop peer. */
912 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
913 {
914 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000915 {
916 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
917 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
918 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
919 }
paul718e3742002-12-13 20:15:29 +0000920 else
921 BGP_EVENT_ADD (peer, BGP_Stop);
922 }
923 type = peer_sort (peer);
924 peer->as = as;
925
paul848973c2003-08-13 00:32:49 +0000926 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
927 && ! bgp_confederation_peers_check (peer->bgp, as)
928 && peer->bgp->as != as)
929 peer->local_as = peer->bgp->confed_id;
930 else
931 peer->local_as = peer->bgp->as;
932
paul718e3742002-12-13 20:15:29 +0000933 /* Advertisement-interval reset */
934 if (peer_sort (peer) == BGP_PEER_IBGP)
935 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
936 else
937 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
938
939 /* TTL reset */
940 if (peer_sort (peer) == BGP_PEER_IBGP)
941 peer->ttl = 255;
942 else if (type == BGP_PEER_IBGP)
943 peer->ttl = 1;
944
945 /* reflector-client reset */
946 if (peer_sort (peer) != BGP_PEER_IBGP)
947 {
948 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
949 PEER_FLAG_REFLECTOR_CLIENT);
950 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
951 PEER_FLAG_REFLECTOR_CLIENT);
952 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
953 PEER_FLAG_REFLECTOR_CLIENT);
954 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
955 PEER_FLAG_REFLECTOR_CLIENT);
956 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
957 PEER_FLAG_REFLECTOR_CLIENT);
958 }
959
960 /* local-as reset */
961 if (peer_sort (peer) != BGP_PEER_EBGP)
962 {
963 peer->change_local_as = 0;
964 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +0000965 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +0000966 }
967}
968
969/* If peer does not exist, create new one. If peer already exists,
970 set AS number to the peer. */
971int
972peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
973 afi_t afi, safi_t safi)
974{
975 struct peer *peer;
976 as_t local_as;
977
978 peer = peer_lookup (bgp, su);
979
980 if (peer)
981 {
982 /* When this peer is a member of peer-group. */
983 if (peer->group)
984 {
985 if (peer->group->conf->as)
986 {
987 /* Return peer group's AS number. */
988 *as = peer->group->conf->as;
989 return BGP_ERR_PEER_GROUP_MEMBER;
990 }
991 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
992 {
993 if (bgp->as != *as)
994 {
995 *as = peer->as;
996 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
997 }
998 }
999 else
1000 {
1001 if (bgp->as == *as)
1002 {
1003 *as = peer->as;
1004 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1005 }
1006 }
1007 }
1008
1009 /* Existing peer's AS number change. */
1010 if (peer->as != *as)
1011 peer_as_change (peer, *as);
1012 }
1013 else
1014 {
1015
1016 /* If the peer is not part of our confederation, and its not an
1017 iBGP peer then spoof the source AS */
1018 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1019 && ! bgp_confederation_peers_check (bgp, *as)
1020 && bgp->as != *as)
1021 local_as = bgp->confed_id;
1022 else
1023 local_as = bgp->as;
1024
1025 /* If this is IPv4 unicast configuration and "no bgp default
1026 ipv4-unicast" is specified. */
1027
1028 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1029 && afi == AFI_IP && safi == SAFI_UNICAST)
1030 peer = peer_create (su, bgp, local_as, *as, 0, 0);
1031 else
1032 peer = peer_create (su, bgp, local_as, *as, afi, safi);
1033 }
1034
1035 return 0;
1036}
1037
1038/* Activate the peer or peer group for specified AFI and SAFI. */
1039int
1040peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1041{
1042 int active;
1043
1044 if (peer->afc[afi][safi])
1045 return 0;
1046
1047 /* Activate the address family configuration. */
1048 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1049 peer->afc[afi][safi] = 1;
1050 else
1051 {
1052 active = peer_active (peer);
1053
1054 peer->afc[afi][safi] = 1;
1055
1056 if (! active && peer_active (peer))
1057 bgp_timer_set (peer);
1058 else
1059 {
1060 if (peer->status == Established)
1061 {
1062 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1063 {
1064 peer->afc_adv[afi][safi] = 1;
1065 bgp_capability_send (peer, afi, safi,
1066 CAPABILITY_CODE_MP,
1067 CAPABILITY_ACTION_SET);
1068 if (peer->afc_recv[afi][safi])
1069 {
1070 peer->afc_nego[afi][safi] = 1;
1071 bgp_announce_route (peer, afi, safi);
1072 }
1073 }
1074 else
hassoe0701b72004-05-20 09:19:34 +00001075 {
1076 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1077 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1078 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1079 }
paul718e3742002-12-13 20:15:29 +00001080 }
1081 }
1082 }
1083 return 0;
1084}
1085
1086int
1087peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1088{
1089 struct peer_group *group;
1090 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001091 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001092
1093 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1094 {
1095 group = peer->group;
1096
paul1eb8ef22005-04-07 07:30:20 +00001097 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001098 {
1099 if (peer1->af_group[afi][safi])
1100 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1101 }
1102 }
1103 else
1104 {
1105 if (peer->af_group[afi][safi])
1106 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1107 }
1108
1109 if (! peer->afc[afi][safi])
1110 return 0;
1111
1112 /* De-activate the address family configuration. */
1113 peer->afc[afi][safi] = 0;
1114 peer_af_flag_reset (peer, afi, safi);
1115
1116 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1117 {
1118 if (peer->status == Established)
1119 {
1120 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1121 {
1122 peer->afc_adv[afi][safi] = 0;
1123 peer->afc_nego[afi][safi] = 0;
1124
1125 if (peer_active_nego (peer))
1126 {
1127 bgp_capability_send (peer, afi, safi,
1128 CAPABILITY_CODE_MP,
1129 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001130 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001131 peer->pcount[afi][safi] = 0;
1132 }
1133 else
hassoe0701b72004-05-20 09:19:34 +00001134 {
1135 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1136 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1137 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1138 }
paul718e3742002-12-13 20:15:29 +00001139 }
1140 else
hassoe0701b72004-05-20 09:19:34 +00001141 {
1142 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1143 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1144 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1145 }
paul718e3742002-12-13 20:15:29 +00001146 }
1147 }
1148 return 0;
1149}
1150
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001151static void
hasso93406d82005-02-02 14:40:33 +00001152peer_nsf_stop (struct peer *peer)
1153{
1154 afi_t afi;
1155 safi_t safi;
1156
1157 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1158 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1159
1160 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +04001161 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +00001162 peer->nsf[afi][safi] = 0;
1163
1164 if (peer->t_gr_restart)
1165 {
1166 BGP_TIMER_OFF (peer->t_gr_restart);
1167 if (BGP_DEBUG (events, EVENTS))
1168 zlog_debug ("%s graceful restart timer stopped", peer->host);
1169 }
1170 if (peer->t_gr_stale)
1171 {
1172 BGP_TIMER_OFF (peer->t_gr_stale);
1173 if (BGP_DEBUG (events, EVENTS))
1174 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1175 }
1176 bgp_clear_route_all (peer);
1177}
1178
Paul Jakmaca058a32006-09-14 02:58:49 +00001179/* Delete peer from confguration.
1180 *
1181 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1182 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1183 *
1184 * This function /should/ take care to be idempotent, to guard against
1185 * it being called multiple times through stray events that come in
1186 * that happen to result in this function being called again. That
1187 * said, getting here for a "Deleted" peer is a bug in the neighbour
1188 * FSM.
1189 */
paul718e3742002-12-13 20:15:29 +00001190int
1191peer_delete (struct peer *peer)
1192{
1193 int i;
1194 afi_t afi;
1195 safi_t safi;
1196 struct bgp *bgp;
1197 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001198 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001199
Paul Jakmaca058a32006-09-14 02:58:49 +00001200 assert (peer->status != Deleted);
1201
paul718e3742002-12-13 20:15:29 +00001202 bgp = peer->bgp;
1203
hasso93406d82005-02-02 14:40:33 +00001204 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1205 peer_nsf_stop (peer);
1206
Chris Caputo228da422009-07-18 05:44:03 +00001207 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001208 relationship. */
1209 if (peer->group)
1210 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001211 if ((pn = listnode_lookup (peer->group->peer, peer)))
1212 {
1213 peer = peer_unlock (peer); /* group->peer list reference */
1214 list_delete_node (peer->group->peer, pn);
1215 }
paul718e3742002-12-13 20:15:29 +00001216 peer->group = NULL;
1217 }
paul200df112005-06-01 11:17:05 +00001218
paul718e3742002-12-13 20:15:29 +00001219 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001220 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1221 * executed after peer structure is deleted.
1222 */
hassoe0701b72004-05-20 09:19:34 +00001223 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001224 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001225 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001226
1227 /* Password configuration */
1228 if (peer->password)
1229 {
1230 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1231 peer->password = NULL;
1232
1233 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1234 bgp_md5_set (peer);
1235 }
1236
Paul Jakmaca058a32006-09-14 02:58:49 +00001237 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001238
paul718e3742002-12-13 20:15:29 +00001239 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001240 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1241 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001242 {
Chris Caputo228da422009-07-18 05:44:03 +00001243 peer_unlock (peer); /* bgp peer list reference */
1244 list_delete_node (bgp->peer, pn);
1245 }
paul200df112005-06-01 11:17:05 +00001246
Chris Caputo228da422009-07-18 05:44:03 +00001247 if (peer_rsclient_active (peer)
1248 && (pn = listnode_lookup (bgp->rsclient, peer)))
1249 {
1250 peer_unlock (peer); /* rsclient list reference */
1251 list_delete_node (bgp->rsclient, pn);
1252
1253 /* Clear our own rsclient ribs. */
1254 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1255 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1256 if (CHECK_FLAG(peer->af_flags[afi][safi],
1257 PEER_FLAG_RSERVER_CLIENT))
1258 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001259 }
1260
1261 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1262 member of a peer_group. */
1263 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1264 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1265 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001266 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001267
paul200df112005-06-01 11:17:05 +00001268 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001269 if (peer->ibuf)
1270 stream_free (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001271 if (peer->obuf)
1272 stream_fifo_free (peer->obuf);
paul718e3742002-12-13 20:15:29 +00001273 if (peer->work)
1274 stream_free (peer->work);
Paul Jakma18937402006-07-27 19:05:12 +00001275 peer->obuf = NULL;
1276 peer->work = peer->ibuf = NULL;
1277
paul718e3742002-12-13 20:15:29 +00001278 /* Local and remote addresses. */
1279 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001280 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001281 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001282 sockunion_free (peer->su_remote);
Paul Jakma18937402006-07-27 19:05:12 +00001283 peer->su_local = peer->su_remote = NULL;
paul200df112005-06-01 11:17:05 +00001284
paul718e3742002-12-13 20:15:29 +00001285 /* Free filter related memory. */
1286 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1287 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1288 {
1289 filter = &peer->filter[afi][safi];
1290
1291 for (i = FILTER_IN; i < FILTER_MAX; i++)
1292 {
1293 if (filter->dlist[i].name)
1294 free (filter->dlist[i].name);
1295 if (filter->plist[i].name)
1296 free (filter->plist[i].name);
1297 if (filter->aslist[i].name)
1298 free (filter->aslist[i].name);
paul200df112005-06-01 11:17:05 +00001299
1300 filter->dlist[i].name = NULL;
1301 filter->plist[i].name = NULL;
1302 filter->aslist[i].name = NULL;
1303 }
1304 for (i = RMAP_IN; i < RMAP_MAX; i++)
1305 {
paul718e3742002-12-13 20:15:29 +00001306 if (filter->map[i].name)
1307 free (filter->map[i].name);
paul200df112005-06-01 11:17:05 +00001308 filter->map[i].name = NULL;
paul718e3742002-12-13 20:15:29 +00001309 }
1310
1311 if (filter->usmap.name)
1312 free (filter->usmap.name);
1313
1314 if (peer->default_rmap[afi][safi].name)
1315 free (peer->default_rmap[afi][safi].name);
paul200df112005-06-01 11:17:05 +00001316
1317 filter->usmap.name = NULL;
1318 peer->default_rmap[afi][safi].name = NULL;
paul718e3742002-12-13 20:15:29 +00001319 }
paul200df112005-06-01 11:17:05 +00001320
1321 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001322
1323 return 0;
1324}
1325
paul94f2b392005-06-28 12:44:16 +00001326static int
paul718e3742002-12-13 20:15:29 +00001327peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1328{
1329 return strcmp (g1->name, g2->name);
1330}
1331
1332/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001333static int
paul718e3742002-12-13 20:15:29 +00001334peer_group_active (struct peer *peer)
1335{
1336 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1337 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1338 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1339 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1340 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1341 return 1;
1342 return 0;
1343}
1344
1345/* Peer group cofiguration. */
1346static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001347peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001348{
1349 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1350 sizeof (struct peer_group));
1351}
1352
paul94f2b392005-06-28 12:44:16 +00001353static void
paul718e3742002-12-13 20:15:29 +00001354peer_group_free (struct peer_group *group)
1355{
1356 XFREE (MTYPE_PEER_GROUP, group);
1357}
1358
1359struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001360peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001361{
1362 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001363 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001364
paul1eb8ef22005-04-07 07:30:20 +00001365 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001366 {
1367 if (strcmp (group->name, name) == 0)
1368 return group;
1369 }
1370 return NULL;
1371}
1372
1373struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001374peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001375{
1376 struct peer_group *group;
1377
1378 group = peer_group_lookup (bgp, name);
1379 if (group)
1380 return group;
1381
1382 group = peer_group_new ();
1383 group->bgp = bgp;
1384 group->name = strdup (name);
1385 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001386 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001387 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1388 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001389 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001390 group->conf->group = group;
1391 group->conf->as = 0;
1392 group->conf->ttl = 1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001393 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001394 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1395 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1396 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1397 group->conf->keepalive = 0;
1398 group->conf->holdtime = 0;
1399 group->conf->connect = 0;
1400 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1401 listnode_add_sort (bgp->group, group);
1402
1403 return 0;
1404}
1405
paul94f2b392005-06-28 12:44:16 +00001406static void
paul718e3742002-12-13 20:15:29 +00001407peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1408 afi_t afi, safi_t safi)
1409{
1410 int in = FILTER_IN;
1411 int out = FILTER_OUT;
1412 struct peer *conf;
1413 struct bgp_filter *pfilter;
1414 struct bgp_filter *gfilter;
1415
1416 conf = group->conf;
1417 pfilter = &peer->filter[afi][safi];
1418 gfilter = &conf->filter[afi][safi];
1419
1420 /* remote-as */
1421 if (conf->as)
1422 peer->as = conf->as;
1423
1424 /* remote-as */
1425 if (conf->change_local_as)
1426 peer->change_local_as = conf->change_local_as;
1427
1428 /* TTL */
1429 peer->ttl = conf->ttl;
1430
Nick Hilliardfa411a22011-03-23 15:33:17 +00001431 /* GTSM hops */
1432 peer->gtsm_hops = conf->gtsm_hops;
1433
paul718e3742002-12-13 20:15:29 +00001434 /* Weight */
1435 peer->weight = conf->weight;
1436
1437 /* peer flags apply */
1438 peer->flags = conf->flags;
1439 /* peer af_flags apply */
1440 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1441 /* peer config apply */
1442 peer->config = conf->config;
1443
1444 /* peer timers apply */
1445 peer->holdtime = conf->holdtime;
1446 peer->keepalive = conf->keepalive;
1447 peer->connect = conf->connect;
1448 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1449 peer->v_connect = conf->connect;
1450 else
1451 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1452
1453 /* advertisement-interval reset */
1454 if (peer_sort (peer) == BGP_PEER_IBGP)
1455 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1456 else
1457 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1458
Paul Jakma0df7c912008-07-21 21:02:49 +00001459 /* password apply */
Roman Hoog Antink0e4303d2013-01-18 13:52:03 +01001460 if (conf->password && !peer->password)
Paul Jakma0df7c912008-07-21 21:02:49 +00001461 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
Paul Jakma0df7c912008-07-21 21:02:49 +00001462
1463 bgp_md5_set (peer);
1464
paul718e3742002-12-13 20:15:29 +00001465 /* maximum-prefix */
1466 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001467 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001468 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001469
1470 /* allowas-in */
1471 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1472
paulfee0f4c2004-09-13 05:12:46 +00001473 /* route-server-client */
1474 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1475 {
1476 /* Make peer's RIB point to group's RIB. */
1477 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1478
1479 /* Import policy. */
1480 if (pfilter->map[RMAP_IMPORT].name)
1481 free (pfilter->map[RMAP_IMPORT].name);
1482 if (gfilter->map[RMAP_IMPORT].name)
1483 {
1484 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1485 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1486 }
1487 else
1488 {
1489 pfilter->map[RMAP_IMPORT].name = NULL;
1490 pfilter->map[RMAP_IMPORT].map = NULL;
1491 }
1492
1493 /* Export policy. */
1494 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1495 {
1496 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1497 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1498 }
1499 }
1500
paul718e3742002-12-13 20:15:29 +00001501 /* default-originate route-map */
1502 if (conf->default_rmap[afi][safi].name)
1503 {
1504 if (peer->default_rmap[afi][safi].name)
1505 free (peer->default_rmap[afi][safi].name);
1506 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1507 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1508 }
1509
1510 /* update-source apply */
1511 if (conf->update_source)
1512 {
1513 if (peer->update_source)
1514 sockunion_free (peer->update_source);
1515 if (peer->update_if)
1516 {
1517 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1518 peer->update_if = NULL;
1519 }
1520 peer->update_source = sockunion_dup (conf->update_source);
1521 }
1522 else if (conf->update_if)
1523 {
1524 if (peer->update_if)
1525 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1526 if (peer->update_source)
1527 {
1528 sockunion_free (peer->update_source);
1529 peer->update_source = NULL;
1530 }
1531 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1532 }
1533
1534 /* inbound filter apply */
1535 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1536 {
1537 if (pfilter->dlist[in].name)
1538 free (pfilter->dlist[in].name);
1539 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1540 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1541 }
1542 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1543 {
1544 if (pfilter->plist[in].name)
1545 free (pfilter->plist[in].name);
1546 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1547 pfilter->plist[in].plist = gfilter->plist[in].plist;
1548 }
1549 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1550 {
1551 if (pfilter->aslist[in].name)
1552 free (pfilter->aslist[in].name);
1553 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1554 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1555 }
paulfee0f4c2004-09-13 05:12:46 +00001556 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001557 {
paulfee0f4c2004-09-13 05:12:46 +00001558 if (pfilter->map[RMAP_IN].name)
1559 free (pfilter->map[RMAP_IN].name);
1560 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1561 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001562 }
1563
1564 /* outbound filter apply */
1565 if (gfilter->dlist[out].name)
1566 {
1567 if (pfilter->dlist[out].name)
1568 free (pfilter->dlist[out].name);
1569 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1570 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1571 }
1572 else
1573 {
1574 if (pfilter->dlist[out].name)
1575 free (pfilter->dlist[out].name);
1576 pfilter->dlist[out].name = NULL;
1577 pfilter->dlist[out].alist = NULL;
1578 }
1579 if (gfilter->plist[out].name)
1580 {
1581 if (pfilter->plist[out].name)
1582 free (pfilter->plist[out].name);
1583 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1584 pfilter->plist[out].plist = gfilter->plist[out].plist;
1585 }
1586 else
1587 {
1588 if (pfilter->plist[out].name)
1589 free (pfilter->plist[out].name);
1590 pfilter->plist[out].name = NULL;
1591 pfilter->plist[out].plist = NULL;
1592 }
1593 if (gfilter->aslist[out].name)
1594 {
1595 if (pfilter->aslist[out].name)
1596 free (pfilter->aslist[out].name);
1597 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1598 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1599 }
1600 else
1601 {
1602 if (pfilter->aslist[out].name)
1603 free (pfilter->aslist[out].name);
1604 pfilter->aslist[out].name = NULL;
1605 pfilter->aslist[out].aslist = NULL;
1606 }
paulfee0f4c2004-09-13 05:12:46 +00001607 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001608 {
paulfee0f4c2004-09-13 05:12:46 +00001609 if (pfilter->map[RMAP_OUT].name)
1610 free (pfilter->map[RMAP_OUT].name);
1611 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1612 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001613 }
1614 else
1615 {
paulfee0f4c2004-09-13 05:12:46 +00001616 if (pfilter->map[RMAP_OUT].name)
1617 free (pfilter->map[RMAP_OUT].name);
1618 pfilter->map[RMAP_OUT].name = NULL;
1619 pfilter->map[RMAP_OUT].map = NULL;
1620 }
1621
1622 /* RS-client's import/export route-maps. */
1623 if (gfilter->map[RMAP_IMPORT].name)
1624 {
1625 if (pfilter->map[RMAP_IMPORT].name)
1626 free (pfilter->map[RMAP_IMPORT].name);
1627 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1628 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1629 }
1630 else
1631 {
1632 if (pfilter->map[RMAP_IMPORT].name)
1633 free (pfilter->map[RMAP_IMPORT].name);
1634 pfilter->map[RMAP_IMPORT].name = NULL;
1635 pfilter->map[RMAP_IMPORT].map = NULL;
1636 }
1637 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1638 {
1639 if (pfilter->map[RMAP_EXPORT].name)
1640 free (pfilter->map[RMAP_EXPORT].name);
1641 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1642 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001643 }
1644
1645 if (gfilter->usmap.name)
1646 {
1647 if (pfilter->usmap.name)
1648 free (pfilter->usmap.name);
1649 pfilter->usmap.name = strdup (gfilter->usmap.name);
1650 pfilter->usmap.map = gfilter->usmap.map;
1651 }
1652 else
1653 {
1654 if (pfilter->usmap.name)
1655 free (pfilter->usmap.name);
1656 pfilter->usmap.name = NULL;
1657 pfilter->usmap.map = NULL;
1658 }
1659}
1660
1661/* Peer group's remote AS configuration. */
1662int
paulfd79ac92004-10-13 05:06:08 +00001663peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001664{
1665 struct peer_group *group;
1666 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001667 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001668
1669 group = peer_group_lookup (bgp, group_name);
1670 if (! group)
1671 return -1;
1672
1673 if (group->conf->as == *as)
1674 return 0;
1675
1676 /* When we setup peer-group AS number all peer group member's AS
1677 number must be updated to same number. */
1678 peer_as_change (group->conf, *as);
1679
paul1eb8ef22005-04-07 07:30:20 +00001680 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001681 {
1682 if (peer->as != *as)
1683 peer_as_change (peer, *as);
1684 }
1685
1686 return 0;
1687}
1688
1689int
1690peer_group_delete (struct peer_group *group)
1691{
1692 struct bgp *bgp;
1693 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001694 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001695
1696 bgp = group->bgp;
1697
paul1eb8ef22005-04-07 07:30:20 +00001698 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001699 {
1700 peer->group = NULL;
1701 peer_delete (peer);
1702 }
1703 list_delete (group->peer);
1704
1705 free (group->name);
1706 group->name = NULL;
1707
1708 group->conf->group = NULL;
1709 peer_delete (group->conf);
1710
1711 /* Delete from all peer_group list. */
1712 listnode_delete (bgp->group, group);
1713
1714 peer_group_free (group);
1715
1716 return 0;
1717}
1718
1719int
1720peer_group_remote_as_delete (struct peer_group *group)
1721{
1722 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001723 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001724
1725 if (! group->conf->as)
1726 return 0;
1727
paul1eb8ef22005-04-07 07:30:20 +00001728 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001729 {
1730 peer->group = NULL;
1731 peer_delete (peer);
1732 }
1733 list_delete_all_node (group->peer);
1734
1735 group->conf->as = 0;
1736
1737 return 0;
1738}
1739
1740/* Bind specified peer to peer group. */
1741int
1742peer_group_bind (struct bgp *bgp, union sockunion *su,
1743 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1744{
1745 struct peer *peer;
1746 int first_member = 0;
1747
1748 /* Check peer group's address family. */
1749 if (! group->conf->afc[afi][safi])
1750 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1751
1752 /* Lookup the peer. */
1753 peer = peer_lookup (bgp, su);
1754
1755 /* Create a new peer. */
1756 if (! peer)
1757 {
1758 if (! group->conf->as)
1759 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1760
1761 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1762 peer->group = group;
1763 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001764
Paul Jakmaca058a32006-09-14 02:58:49 +00001765 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001766 listnode_add (group->peer, peer);
1767 peer_group2peer_config_copy (group, peer, afi, safi);
1768
1769 return 0;
1770 }
1771
1772 /* When the peer already belongs to peer group, check the consistency. */
1773 if (peer->af_group[afi][safi])
1774 {
1775 if (strcmp (peer->group->name, group->name) != 0)
1776 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1777
1778 return 0;
1779 }
1780
1781 /* Check current peer group configuration. */
1782 if (peer_group_active (peer)
1783 && strcmp (peer->group->name, group->name) != 0)
1784 return BGP_ERR_PEER_GROUP_MISMATCH;
1785
1786 if (! group->conf->as)
1787 {
1788 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1789 && peer_sort (group->conf) != peer_sort (peer))
1790 {
1791 if (as)
1792 *as = peer->as;
1793 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1794 }
1795
1796 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1797 first_member = 1;
1798 }
1799
1800 peer->af_group[afi][safi] = 1;
1801 peer->afc[afi][safi] = 1;
1802 if (! peer->group)
1803 {
1804 peer->group = group;
paul200df112005-06-01 11:17:05 +00001805
Paul Jakmaca058a32006-09-14 02:58:49 +00001806 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001807 listnode_add (group->peer, peer);
1808 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001809 else
1810 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001811
1812 if (first_member)
1813 {
1814 /* Advertisement-interval reset */
1815 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1816 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1817 else
1818 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1819
1820 /* ebgp-multihop reset */
1821 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1822 group->conf->ttl = 255;
1823
1824 /* local-as reset */
1825 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1826 {
1827 group->conf->change_local_as = 0;
1828 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001829 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001830 }
1831 }
paulfee0f4c2004-09-13 05:12:46 +00001832
1833 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1834 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001835 struct listnode *pn;
1836
paulfee0f4c2004-09-13 05:12:46 +00001837 /* If it's not configured as RSERVER_CLIENT in any other address
1838 family, without being member of a peer_group, remove it from
1839 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001840 if (! peer_rsclient_active (peer)
1841 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001842 {
1843 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001844 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001845
1846 /* Clear our own rsclient rib for this afi/safi. */
1847 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001848 }
paulfee0f4c2004-09-13 05:12:46 +00001849
Paul Jakmab608d5b2008-07-02 02:12:07 +00001850 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001851
1852 /* Import policy. */
1853 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1854 {
1855 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1856 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1857 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1858 }
1859
1860 /* Export policy. */
1861 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1862 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1863 {
1864 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1865 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1866 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1867 }
1868 }
1869
paul718e3742002-12-13 20:15:29 +00001870 peer_group2peer_config_copy (group, peer, afi, safi);
1871
1872 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001873 {
1874 peer->last_reset = PEER_DOWN_RMAP_BIND;
1875 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1876 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1877 }
paul718e3742002-12-13 20:15:29 +00001878 else
1879 BGP_EVENT_ADD (peer, BGP_Stop);
1880
1881 return 0;
1882}
1883
1884int
1885peer_group_unbind (struct bgp *bgp, struct peer *peer,
1886 struct peer_group *group, afi_t afi, safi_t safi)
1887{
1888 if (! peer->af_group[afi][safi])
1889 return 0;
1890
1891 if (group != peer->group)
1892 return BGP_ERR_PEER_GROUP_MISMATCH;
1893
1894 peer->af_group[afi][safi] = 0;
1895 peer->afc[afi][safi] = 0;
1896 peer_af_flag_reset (peer, afi, safi);
1897
paulfee0f4c2004-09-13 05:12:46 +00001898 if (peer->rib[afi][safi])
1899 peer->rib[afi][safi] = NULL;
1900
paul718e3742002-12-13 20:15:29 +00001901 if (! peer_group_active (peer))
1902 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001903 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001904 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001905 listnode_delete (group->peer, peer);
1906 peer->group = NULL;
1907 if (group->conf->as)
1908 {
1909 peer_delete (peer);
1910 return 0;
1911 }
1912 peer_global_config_reset (peer);
1913 }
1914
1915 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001916 {
1917 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1918 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1919 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1920 }
paul718e3742002-12-13 20:15:29 +00001921 else
1922 BGP_EVENT_ADD (peer, BGP_Stop);
1923
1924 return 0;
1925}
1926
1927/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001928static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001929bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001930{
1931 struct bgp *bgp;
1932 afi_t afi;
1933 safi_t safi;
1934
paul200df112005-06-01 11:17:05 +00001935 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1936 return NULL;
1937
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07001938 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00001939 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00001940 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00001941
1942 bgp->peer = list_new ();
1943 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1944
1945 bgp->group = list_new ();
1946 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1947
paulfee0f4c2004-09-13 05:12:46 +00001948 bgp->rsclient = list_new ();
1949 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1950
paul718e3742002-12-13 20:15:29 +00001951 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1952 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1953 {
Paul Jakma64e580a2006-02-21 01:09:01 +00001954 bgp->route[afi][safi] = bgp_table_init (afi, safi);
1955 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1956 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07001957 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
1958 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00001959 }
1960
1961 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1962 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1963 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001964 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1965 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001966
1967 bgp->as = *as;
1968
1969 if (name)
1970 bgp->name = strdup (name);
1971
1972 return bgp;
1973}
1974
1975/* Return first entry of BGP. */
1976struct bgp *
paul94f2b392005-06-28 12:44:16 +00001977bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001978{
1979 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001980 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001981 return NULL;
1982}
1983
1984/* Lookup BGP entry. */
1985struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001986bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001987{
1988 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001989 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001990
paul1eb8ef22005-04-07 07:30:20 +00001991 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001992 if (bgp->as == as
1993 && ((bgp->name == NULL && name == NULL)
1994 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1995 return bgp;
1996 return NULL;
1997}
1998
1999/* Lookup BGP structure by view name. */
2000struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002001bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002002{
2003 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002004 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002005
paul1eb8ef22005-04-07 07:30:20 +00002006 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002007 if ((bgp->name == NULL && name == NULL)
2008 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2009 return bgp;
2010 return NULL;
2011}
2012
2013/* Called from VTY commands. */
2014int
paulfd79ac92004-10-13 05:06:08 +00002015bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002016{
2017 struct bgp *bgp;
2018
2019 /* Multiple instance check. */
2020 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2021 {
2022 if (name)
2023 bgp = bgp_lookup_by_name (name);
2024 else
2025 bgp = bgp_get_default ();
2026
2027 /* Already exists. */
2028 if (bgp)
2029 {
2030 if (bgp->as != *as)
2031 {
2032 *as = bgp->as;
2033 return BGP_ERR_INSTANCE_MISMATCH;
2034 }
2035 *bgp_val = bgp;
2036 return 0;
2037 }
2038 }
2039 else
2040 {
2041 /* BGP instance name can not be specified for single instance. */
2042 if (name)
2043 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2044
2045 /* Get default BGP structure if exists. */
2046 bgp = bgp_get_default ();
2047
2048 if (bgp)
2049 {
2050 if (bgp->as != *as)
2051 {
2052 *as = bgp->as;
2053 return BGP_ERR_AS_MISMATCH;
2054 }
2055 *bgp_val = bgp;
2056 return 0;
2057 }
2058 }
2059
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002060 bgp = bgp_create (as, name);
2061 bgp_router_id_set(bgp, &router_id_zebra);
2062 *bgp_val = bgp;
2063
Paul Jakmaad12dde2012-06-13 22:50:07 +01002064 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002065 if (list_isempty(bm->bgp)
2066 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002067 {
2068 if (bgp_socket (bm->port, bm->address) < 0)
2069 return BGP_ERR_INVALID_VALUE;
2070 }
2071
paul718e3742002-12-13 20:15:29 +00002072 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002073
2074 return 0;
2075}
2076
2077/* Delete BGP instance. */
2078int
2079bgp_delete (struct bgp *bgp)
2080{
2081 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002082 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002083 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002084 struct listnode *next;
2085 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002086 int i;
2087
2088 /* Delete static route. */
2089 bgp_static_delete (bgp);
2090
2091 /* Unset redistribution. */
2092 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2093 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2094 if (i != ZEBRA_ROUTE_BGP)
2095 bgp_redistribute_unset (bgp, afi, i);
2096
paul1eb8ef22005-04-07 07:30:20 +00002097 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2098 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002099
Chris Caputo228da422009-07-18 05:44:03 +00002100 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
2101 peer_group_delete (group);
2102
2103 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002104
2105 if (bgp->peer_self) {
2106 peer_delete(bgp->peer_self);
2107 bgp->peer_self = NULL;
2108 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002109
2110 /* Remove visibility via the master list - there may however still be
2111 * routes to be processed still referencing the struct bgp.
2112 */
2113 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002114 if (list_isempty(bm->bgp))
2115 bgp_close ();
2116
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002117 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002118
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002119 return 0;
2120}
2121
2122static void bgp_free (struct bgp *);
2123
2124void
2125bgp_lock (struct bgp *bgp)
2126{
2127 ++bgp->lock;
2128}
2129
2130void
2131bgp_unlock(struct bgp *bgp)
2132{
Chris Caputo228da422009-07-18 05:44:03 +00002133 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002134 if (--bgp->lock == 0)
2135 bgp_free (bgp);
2136}
2137
2138static void
2139bgp_free (struct bgp *bgp)
2140{
2141 afi_t afi;
2142 safi_t safi;
2143
2144 list_delete (bgp->group);
2145 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002146 list_delete (bgp->rsclient);
2147
paul718e3742002-12-13 20:15:29 +00002148 if (bgp->name)
2149 free (bgp->name);
2150
2151 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2152 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2153 {
2154 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002155 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002156 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002157 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002158 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002159 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002160 }
2161 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002162}
2163
2164struct peer *
2165peer_lookup (struct bgp *bgp, union sockunion *su)
2166{
2167 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002168 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002169
Steve Hillfc4dc592009-07-28 17:54:35 +01002170 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002171 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002172 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2173 if (sockunion_same (&peer->su, su)
2174 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2175 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002176 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002177 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002178 {
2179 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002180
Paul Jakma2158ad22009-07-28 18:10:55 +01002181 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2182 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2183 if (sockunion_same (&peer->su, su)
2184 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2185 return peer;
paul718e3742002-12-13 20:15:29 +00002186 }
2187 return NULL;
2188}
2189
2190struct peer *
2191peer_lookup_with_open (union sockunion *su, as_t remote_as,
2192 struct in_addr *remote_id, int *as)
2193{
2194 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002195 struct listnode *node;
2196 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002197 struct bgp *bgp;
2198
Steve Hillfc4dc592009-07-28 17:54:35 +01002199 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002200 return NULL;
2201
Paul Jakma9d878772009-08-05 16:25:16 +01002202 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002203 {
Paul Jakma9d878772009-08-05 16:25:16 +01002204 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2205 {
2206 if (sockunion_same (&peer->su, su)
2207 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2208 {
2209 if (peer->as == remote_as
2210 && peer->remote_id.s_addr == remote_id->s_addr)
2211 return peer;
2212 if (peer->as == remote_as)
2213 *as = 1;
2214 }
2215 }
2216
2217 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2218 {
2219 if (sockunion_same (&peer->su, su)
2220 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2221 {
2222 if (peer->as == remote_as
2223 && peer->remote_id.s_addr == 0)
2224 return peer;
2225 if (peer->as == remote_as)
2226 *as = 1;
2227 }
2228 }
paul718e3742002-12-13 20:15:29 +00002229 }
2230 return NULL;
2231}
2232
2233/* If peer is configured at least one address family return 1. */
2234int
2235peer_active (struct peer *peer)
2236{
2237 if (peer->afc[AFI_IP][SAFI_UNICAST]
2238 || peer->afc[AFI_IP][SAFI_MULTICAST]
2239 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2240 || peer->afc[AFI_IP6][SAFI_UNICAST]
2241 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2242 return 1;
2243 return 0;
2244}
2245
2246/* If peer is negotiated at least one address family return 1. */
2247int
2248peer_active_nego (struct peer *peer)
2249{
2250 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2251 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2252 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2253 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2254 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2255 return 1;
2256 return 0;
2257}
2258
2259/* peer_flag_change_type. */
2260enum peer_change_type
2261{
2262 peer_change_none,
2263 peer_change_reset,
2264 peer_change_reset_in,
2265 peer_change_reset_out,
2266};
2267
paul94f2b392005-06-28 12:44:16 +00002268static void
paul718e3742002-12-13 20:15:29 +00002269peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2270 enum peer_change_type type)
2271{
2272 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2273 return;
2274
2275 if (type == peer_change_reset)
2276 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2277 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2278 else if (type == peer_change_reset_in)
2279 {
2280 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2281 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2282 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2283 else
2284 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2285 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2286 }
2287 else if (type == peer_change_reset_out)
2288 bgp_announce_route (peer, afi, safi);
2289}
2290
2291struct peer_flag_action
2292{
2293 /* Peer's flag. */
2294 u_int32_t flag;
2295
2296 /* This flag can be set for peer-group member. */
2297 u_char not_for_member;
2298
2299 /* Action when the flag is changed. */
2300 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002301
2302 /* Peer down cause */
2303 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002304};
2305
Stephen Hemminger03621952009-07-21 16:27:20 -07002306static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002307 {
2308 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2309 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2310 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2311 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2312 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002313 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002314 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002315 { 0, 0, 0 }
2316 };
2317
Stephen Hemminger03621952009-07-21 16:27:20 -07002318static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002319 {
2320 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2321 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2322 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2323 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2324 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2325 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2326 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2327 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2328 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2329 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2330 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2331 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2332 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002333 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002334 { 0, 0, 0 }
2335 };
2336
2337/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002338static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002339peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002340 struct peer_flag_action *action, u_int32_t flag)
2341{
2342 int i;
2343 int found = 0;
2344 int reset_in = 0;
2345 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002346 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002347
2348 /* Check peer's frag action. */
2349 for (i = 0; i < size; i++)
2350 {
2351 match = &action_list[i];
2352
2353 if (match->flag == 0)
2354 break;
2355
2356 if (match->flag & flag)
2357 {
2358 found = 1;
2359
2360 if (match->type == peer_change_reset_in)
2361 reset_in = 1;
2362 if (match->type == peer_change_reset_out)
2363 reset_out = 1;
2364 if (match->type == peer_change_reset)
2365 {
2366 reset_in = 1;
2367 reset_out = 1;
2368 }
2369 if (match->not_for_member)
2370 action->not_for_member = 1;
2371 }
2372 }
2373
2374 /* Set peer clear type. */
2375 if (reset_in && reset_out)
2376 action->type = peer_change_reset;
2377 else if (reset_in)
2378 action->type = peer_change_reset_in;
2379 else if (reset_out)
2380 action->type = peer_change_reset_out;
2381 else
2382 action->type = peer_change_none;
2383
2384 return found;
2385}
2386
paul94f2b392005-06-28 12:44:16 +00002387static void
paul718e3742002-12-13 20:15:29 +00002388peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2389{
2390 if (flag == PEER_FLAG_SHUTDOWN)
2391 {
2392 if (CHECK_FLAG (peer->flags, flag))
2393 {
hasso93406d82005-02-02 14:40:33 +00002394 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2395 peer_nsf_stop (peer);
2396
hasso0a486e52005-02-01 20:57:17 +00002397 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2398 if (peer->t_pmax_restart)
2399 {
2400 BGP_TIMER_OFF (peer->t_pmax_restart);
2401 if (BGP_DEBUG (events, EVENTS))
2402 zlog_debug ("%s Maximum-prefix restart timer canceled",
2403 peer->host);
2404 }
2405
hasso93406d82005-02-02 14:40:33 +00002406 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2407 peer_nsf_stop (peer);
2408
paul718e3742002-12-13 20:15:29 +00002409 if (peer->status == Established)
2410 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2411 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2412 else
2413 BGP_EVENT_ADD (peer, BGP_Stop);
2414 }
2415 else
2416 {
2417 peer->v_start = BGP_INIT_START_TIMER;
2418 BGP_EVENT_ADD (peer, BGP_Stop);
2419 }
2420 }
2421 else if (peer->status == Established)
2422 {
hassoc9502432005-02-01 22:01:48 +00002423 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2424 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2425 else if (flag == PEER_FLAG_PASSIVE)
2426 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002427 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002428 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002429
hassoc9502432005-02-01 22:01:48 +00002430 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2431 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002432 }
2433 else
2434 BGP_EVENT_ADD (peer, BGP_Stop);
2435}
2436
2437/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002438static int
paul718e3742002-12-13 20:15:29 +00002439peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2440{
2441 int found;
2442 int size;
2443 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002444 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002445 struct peer_flag_action action;
2446
2447 memset (&action, 0, sizeof (struct peer_flag_action));
2448 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2449
2450 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2451
2452 /* No flag action is found. */
2453 if (! found)
2454 return BGP_ERR_INVALID_FLAG;
2455
2456 /* Not for peer-group member. */
2457 if (action.not_for_member && peer_group_active (peer))
2458 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2459
2460 /* When unset the peer-group member's flag we have to check
2461 peer-group configuration. */
2462 if (! set && peer_group_active (peer))
2463 if (CHECK_FLAG (peer->group->conf->flags, flag))
2464 {
2465 if (flag == PEER_FLAG_SHUTDOWN)
2466 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2467 else
2468 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2469 }
2470
2471 /* Flag conflict check. */
2472 if (set
2473 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2474 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2475 return BGP_ERR_PEER_FLAG_CONFLICT;
2476
2477 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2478 {
2479 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2480 return 0;
2481 if (! set && ! CHECK_FLAG (peer->flags, flag))
2482 return 0;
2483 }
2484
2485 if (set)
2486 SET_FLAG (peer->flags, flag);
2487 else
2488 UNSET_FLAG (peer->flags, flag);
2489
2490 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2491 {
2492 if (action.type == peer_change_reset)
2493 peer_flag_modify_action (peer, flag);
2494
2495 return 0;
2496 }
2497
2498 /* peer-group member updates. */
2499 group = peer->group;
2500
paul1eb8ef22005-04-07 07:30:20 +00002501 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002502 {
2503 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2504 continue;
2505
2506 if (! set && ! CHECK_FLAG (peer->flags, flag))
2507 continue;
2508
2509 if (set)
2510 SET_FLAG (peer->flags, flag);
2511 else
2512 UNSET_FLAG (peer->flags, flag);
2513
2514 if (action.type == peer_change_reset)
2515 peer_flag_modify_action (peer, flag);
2516 }
2517 return 0;
2518}
2519
2520int
2521peer_flag_set (struct peer *peer, u_int32_t flag)
2522{
2523 return peer_flag_modify (peer, flag, 1);
2524}
2525
2526int
2527peer_flag_unset (struct peer *peer, u_int32_t flag)
2528{
2529 return peer_flag_modify (peer, flag, 0);
2530}
2531
paul94f2b392005-06-28 12:44:16 +00002532static int
paul718e3742002-12-13 20:15:29 +00002533peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2534{
2535 if (peer->af_group[afi][safi])
2536 return 1;
2537 return 0;
2538}
2539
paul94f2b392005-06-28 12:44:16 +00002540static int
paul718e3742002-12-13 20:15:29 +00002541peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2542 int set)
2543{
2544 int found;
2545 int size;
paul1eb8ef22005-04-07 07:30:20 +00002546 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002547 struct peer_group *group;
2548 struct peer_flag_action action;
2549
2550 memset (&action, 0, sizeof (struct peer_flag_action));
2551 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2552
2553 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2554
2555 /* No flag action is found. */
2556 if (! found)
2557 return BGP_ERR_INVALID_FLAG;
2558
2559 /* Adress family must be activated. */
2560 if (! peer->afc[afi][safi])
2561 return BGP_ERR_PEER_INACTIVE;
2562
2563 /* Not for peer-group member. */
2564 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2565 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2566
2567 /* Spcecial check for reflector client. */
2568 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2569 && peer_sort (peer) != BGP_PEER_IBGP)
2570 return BGP_ERR_NOT_INTERNAL_PEER;
2571
2572 /* Spcecial check for remove-private-AS. */
2573 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2574 && peer_sort (peer) == BGP_PEER_IBGP)
2575 return BGP_ERR_REMOVE_PRIVATE_AS;
2576
2577 /* When unset the peer-group member's flag we have to check
2578 peer-group configuration. */
2579 if (! set && peer->af_group[afi][safi])
2580 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2581 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2582
2583 /* When current flag configuration is same as requested one. */
2584 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2585 {
2586 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2587 return 0;
2588 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2589 return 0;
2590 }
2591
2592 if (set)
2593 SET_FLAG (peer->af_flags[afi][safi], flag);
2594 else
2595 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2596
2597 /* Execute action when peer is established. */
2598 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2599 && peer->status == Established)
2600 {
2601 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2602 bgp_clear_adj_in (peer, afi, safi);
2603 else
hassoe0701b72004-05-20 09:19:34 +00002604 {
2605 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2606 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2607 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2608 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2609 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2610 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2611 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2612 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2613
2614 peer_change_action (peer, afi, safi, action.type);
2615 }
2616
paul718e3742002-12-13 20:15:29 +00002617 }
2618
2619 /* Peer group member updates. */
2620 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2621 {
2622 group = peer->group;
2623
paul1eb8ef22005-04-07 07:30:20 +00002624 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002625 {
2626 if (! peer->af_group[afi][safi])
2627 continue;
2628
2629 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2630 continue;
2631
2632 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2633 continue;
2634
2635 if (set)
2636 SET_FLAG (peer->af_flags[afi][safi], flag);
2637 else
2638 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2639
2640 if (peer->status == Established)
2641 {
2642 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2643 bgp_clear_adj_in (peer, afi, safi);
2644 else
hassoe0701b72004-05-20 09:19:34 +00002645 {
2646 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2647 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2648 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2649 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2650 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2651 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2652 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2653 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2654
2655 peer_change_action (peer, afi, safi, action.type);
2656 }
paul718e3742002-12-13 20:15:29 +00002657 }
2658 }
2659 }
2660 return 0;
2661}
2662
2663int
2664peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2665{
2666 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2667}
2668
2669int
2670peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2671{
2672 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2673}
2674
2675/* EBGP multihop configuration. */
2676int
2677peer_ebgp_multihop_set (struct peer *peer, int ttl)
2678{
2679 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002680 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002681 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002682
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002683 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002684 return 0;
2685
Nick Hilliardfa411a22011-03-23 15:33:17 +00002686 /* see comment in peer_ttl_security_hops_set() */
2687 if (ttl != MAXTTL)
2688 {
2689 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2690 {
2691 group = peer->group;
2692 if (group->conf->gtsm_hops != 0)
2693 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2694
2695 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2696 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002697 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002698 continue;
2699
2700 if (peer1->gtsm_hops != 0)
2701 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2702 }
2703 }
2704 else
2705 {
2706 if (peer->gtsm_hops != 0)
2707 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2708 }
2709 }
2710
paul718e3742002-12-13 20:15:29 +00002711 peer->ttl = ttl;
2712
2713 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2714 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002715 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002716 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002717 }
2718 else
2719 {
2720 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002721 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002722 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002723 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002724 continue;
paul718e3742002-12-13 20:15:29 +00002725
pauleb821182004-05-01 08:44:08 +00002726 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002727
pauleb821182004-05-01 08:44:08 +00002728 if (peer->fd >= 0)
2729 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2730 }
paul718e3742002-12-13 20:15:29 +00002731 }
2732 return 0;
2733}
2734
2735int
2736peer_ebgp_multihop_unset (struct peer *peer)
2737{
2738 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002739 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002740
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002741 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002742 return 0;
2743
Nick Hilliardfa411a22011-03-23 15:33:17 +00002744 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2745 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2746
paul718e3742002-12-13 20:15:29 +00002747 if (peer_group_active (peer))
2748 peer->ttl = peer->group->conf->ttl;
2749 else
2750 peer->ttl = 1;
2751
2752 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2753 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002754 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002755 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002756 }
2757 else
2758 {
2759 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002760 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002761 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002762 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002763 continue;
paul718e3742002-12-13 20:15:29 +00002764
pauleb821182004-05-01 08:44:08 +00002765 peer->ttl = 1;
2766
2767 if (peer->fd >= 0)
2768 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2769 }
paul718e3742002-12-13 20:15:29 +00002770 }
2771 return 0;
2772}
2773
2774/* Neighbor description. */
2775int
2776peer_description_set (struct peer *peer, char *desc)
2777{
2778 if (peer->desc)
2779 XFREE (MTYPE_PEER_DESC, peer->desc);
2780
2781 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2782
2783 return 0;
2784}
2785
2786int
2787peer_description_unset (struct peer *peer)
2788{
2789 if (peer->desc)
2790 XFREE (MTYPE_PEER_DESC, peer->desc);
2791
2792 peer->desc = NULL;
2793
2794 return 0;
2795}
2796
2797/* Neighbor update-source. */
2798int
paulfd79ac92004-10-13 05:06:08 +00002799peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002800{
2801 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002802 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002803
2804 if (peer->update_if)
2805 {
2806 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2807 && strcmp (peer->update_if, ifname) == 0)
2808 return 0;
2809
2810 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2811 peer->update_if = NULL;
2812 }
2813
2814 if (peer->update_source)
2815 {
2816 sockunion_free (peer->update_source);
2817 peer->update_source = NULL;
2818 }
2819
2820 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2821
2822 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2823 {
2824 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002825 {
2826 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2827 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2828 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2829 }
paul718e3742002-12-13 20:15:29 +00002830 else
2831 BGP_EVENT_ADD (peer, BGP_Stop);
2832 return 0;
2833 }
2834
2835 /* peer-group member updates. */
2836 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002837 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002838 {
2839 if (peer->update_if)
2840 {
2841 if (strcmp (peer->update_if, ifname) == 0)
2842 continue;
2843
2844 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2845 peer->update_if = NULL;
2846 }
2847
2848 if (peer->update_source)
2849 {
2850 sockunion_free (peer->update_source);
2851 peer->update_source = NULL;
2852 }
2853
2854 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2855
2856 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002857 {
2858 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2859 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2860 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2861 }
paul718e3742002-12-13 20:15:29 +00002862 else
2863 BGP_EVENT_ADD (peer, BGP_Stop);
2864 }
2865 return 0;
2866}
2867
2868int
2869peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2870{
2871 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002872 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002873
2874 if (peer->update_source)
2875 {
2876 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2877 && sockunion_cmp (peer->update_source, su) == 0)
2878 return 0;
2879 sockunion_free (peer->update_source);
2880 peer->update_source = NULL;
2881 }
2882
2883 if (peer->update_if)
2884 {
2885 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2886 peer->update_if = NULL;
2887 }
2888
2889 peer->update_source = sockunion_dup (su);
2890
2891 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2892 {
2893 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002894 {
2895 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2896 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2897 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2898 }
paul718e3742002-12-13 20:15:29 +00002899 else
2900 BGP_EVENT_ADD (peer, BGP_Stop);
2901 return 0;
2902 }
2903
2904 /* peer-group member updates. */
2905 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002906 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002907 {
2908 if (peer->update_source)
2909 {
2910 if (sockunion_cmp (peer->update_source, su) == 0)
2911 continue;
2912 sockunion_free (peer->update_source);
2913 peer->update_source = NULL;
2914 }
2915
2916 if (peer->update_if)
2917 {
2918 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2919 peer->update_if = NULL;
2920 }
2921
2922 peer->update_source = sockunion_dup (su);
2923
2924 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002925 {
2926 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2927 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2928 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2929 }
paul718e3742002-12-13 20:15:29 +00002930 else
2931 BGP_EVENT_ADD (peer, BGP_Stop);
2932 }
2933 return 0;
2934}
2935
2936int
2937peer_update_source_unset (struct peer *peer)
2938{
2939 union sockunion *su;
2940 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002941 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002942
2943 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2944 && ! peer->update_source
2945 && ! peer->update_if)
2946 return 0;
2947
2948 if (peer->update_source)
2949 {
2950 sockunion_free (peer->update_source);
2951 peer->update_source = NULL;
2952 }
2953 if (peer->update_if)
2954 {
2955 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2956 peer->update_if = NULL;
2957 }
2958
2959 if (peer_group_active (peer))
2960 {
2961 group = peer->group;
2962
2963 if (group->conf->update_source)
2964 {
2965 su = sockunion_dup (group->conf->update_source);
2966 peer->update_source = su;
2967 }
2968 else if (group->conf->update_if)
2969 peer->update_if =
2970 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2971 }
2972
2973 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2974 {
2975 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002976 {
2977 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2978 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2979 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2980 }
paul718e3742002-12-13 20:15:29 +00002981 else
2982 BGP_EVENT_ADD (peer, BGP_Stop);
2983 return 0;
2984 }
2985
2986 /* peer-group member updates. */
2987 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002988 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002989 {
2990 if (! peer->update_source && ! peer->update_if)
2991 continue;
2992
2993 if (peer->update_source)
2994 {
2995 sockunion_free (peer->update_source);
2996 peer->update_source = NULL;
2997 }
2998
2999 if (peer->update_if)
3000 {
3001 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3002 peer->update_if = NULL;
3003 }
3004
3005 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003006 {
3007 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3008 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3009 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3010 }
paul718e3742002-12-13 20:15:29 +00003011 else
3012 BGP_EVENT_ADD (peer, BGP_Stop);
3013 }
3014 return 0;
3015}
3016
3017int
3018peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003019 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003020{
3021 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003022 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003023
3024 /* Adress family must be activated. */
3025 if (! peer->afc[afi][safi])
3026 return BGP_ERR_PEER_INACTIVE;
3027
3028 /* Default originate can't be used for peer group memeber. */
3029 if (peer_is_group_member (peer, afi, safi))
3030 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3031
3032 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3033 || (rmap && ! peer->default_rmap[afi][safi].name)
3034 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3035 {
3036 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3037
3038 if (rmap)
3039 {
3040 if (peer->default_rmap[afi][safi].name)
3041 free (peer->default_rmap[afi][safi].name);
3042 peer->default_rmap[afi][safi].name = strdup (rmap);
3043 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3044 }
3045 }
3046
3047 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3048 {
3049 if (peer->status == Established && peer->afc_nego[afi][safi])
3050 bgp_default_originate (peer, afi, safi, 0);
3051 return 0;
3052 }
3053
3054 /* peer-group member updates. */
3055 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003056 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003057 {
3058 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3059
3060 if (rmap)
3061 {
3062 if (peer->default_rmap[afi][safi].name)
3063 free (peer->default_rmap[afi][safi].name);
3064 peer->default_rmap[afi][safi].name = strdup (rmap);
3065 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3066 }
3067
3068 if (peer->status == Established && peer->afc_nego[afi][safi])
3069 bgp_default_originate (peer, afi, safi, 0);
3070 }
3071 return 0;
3072}
3073
3074int
3075peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3076{
3077 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003078 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003079
3080 /* Adress family must be activated. */
3081 if (! peer->afc[afi][safi])
3082 return BGP_ERR_PEER_INACTIVE;
3083
3084 /* Default originate can't be used for peer group memeber. */
3085 if (peer_is_group_member (peer, afi, safi))
3086 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3087
3088 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3089 {
3090 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3091
3092 if (peer->default_rmap[afi][safi].name)
3093 free (peer->default_rmap[afi][safi].name);
3094 peer->default_rmap[afi][safi].name = NULL;
3095 peer->default_rmap[afi][safi].map = NULL;
3096 }
3097
3098 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3099 {
3100 if (peer->status == Established && peer->afc_nego[afi][safi])
3101 bgp_default_originate (peer, afi, safi, 1);
3102 return 0;
3103 }
3104
3105 /* peer-group member updates. */
3106 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003107 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003108 {
3109 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3110
3111 if (peer->default_rmap[afi][safi].name)
3112 free (peer->default_rmap[afi][safi].name);
3113 peer->default_rmap[afi][safi].name = NULL;
3114 peer->default_rmap[afi][safi].map = NULL;
3115
3116 if (peer->status == Established && peer->afc_nego[afi][safi])
3117 bgp_default_originate (peer, afi, safi, 1);
3118 }
3119 return 0;
3120}
3121
3122int
3123peer_port_set (struct peer *peer, u_int16_t port)
3124{
3125 peer->port = port;
3126 return 0;
3127}
3128
3129int
3130peer_port_unset (struct peer *peer)
3131{
3132 peer->port = BGP_PORT_DEFAULT;
3133 return 0;
3134}
3135
3136/* neighbor weight. */
3137int
3138peer_weight_set (struct peer *peer, u_int16_t weight)
3139{
3140 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003141 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003142
3143 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3144 peer->weight = weight;
3145
3146 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3147 return 0;
3148
3149 /* peer-group member updates. */
3150 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003151 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003152 {
3153 peer->weight = group->conf->weight;
3154 }
3155 return 0;
3156}
3157
3158int
3159peer_weight_unset (struct peer *peer)
3160{
3161 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003162 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003163
3164 /* Set default weight. */
3165 if (peer_group_active (peer))
3166 peer->weight = peer->group->conf->weight;
3167 else
3168 peer->weight = 0;
3169
3170 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3171
3172 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3173 return 0;
3174
3175 /* peer-group member updates. */
3176 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003177 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003178 {
3179 peer->weight = 0;
3180 }
3181 return 0;
3182}
3183
3184int
3185peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3186{
3187 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003188 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003189
3190 /* Not for peer group memeber. */
3191 if (peer_group_active (peer))
3192 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3193
3194 /* keepalive value check. */
3195 if (keepalive > 65535)
3196 return BGP_ERR_INVALID_VALUE;
3197
3198 /* Holdtime value check. */
3199 if (holdtime > 65535)
3200 return BGP_ERR_INVALID_VALUE;
3201
3202 /* Holdtime value must be either 0 or greater than 3. */
3203 if (holdtime < 3 && holdtime != 0)
3204 return BGP_ERR_INVALID_VALUE;
3205
3206 /* Set value to the configuration. */
3207 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3208 peer->holdtime = holdtime;
3209 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3210
3211 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3212 return 0;
3213
3214 /* peer-group member updates. */
3215 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003216 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003217 {
3218 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3219 peer->holdtime = group->conf->holdtime;
3220 peer->keepalive = group->conf->keepalive;
3221 }
3222 return 0;
3223}
3224
3225int
3226peer_timers_unset (struct peer *peer)
3227{
3228 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003229 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003230
3231 if (peer_group_active (peer))
3232 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3233
3234 /* Clear configuration. */
3235 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3236 peer->keepalive = 0;
3237 peer->holdtime = 0;
3238
3239 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3240 return 0;
3241
3242 /* peer-group member updates. */
3243 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003244 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003245 {
3246 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3247 peer->holdtime = 0;
3248 peer->keepalive = 0;
3249 }
3250
3251 return 0;
3252}
3253
3254int
3255peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3256{
3257 if (peer_group_active (peer))
3258 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3259
3260 if (connect > 65535)
3261 return BGP_ERR_INVALID_VALUE;
3262
3263 /* Set value to the configuration. */
3264 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3265 peer->connect = connect;
3266
3267 /* Set value to timer setting. */
3268 peer->v_connect = connect;
3269
3270 return 0;
3271}
3272
3273int
3274peer_timers_connect_unset (struct peer *peer)
3275{
3276 if (peer_group_active (peer))
3277 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3278
3279 /* Clear configuration. */
3280 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3281 peer->connect = 0;
3282
3283 /* Set timer setting to default value. */
3284 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3285
3286 return 0;
3287}
3288
3289int
3290peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3291{
3292 if (peer_group_active (peer))
3293 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3294
3295 if (routeadv > 600)
3296 return BGP_ERR_INVALID_VALUE;
3297
3298 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3299 peer->routeadv = routeadv;
3300 peer->v_routeadv = routeadv;
3301
3302 return 0;
3303}
3304
3305int
3306peer_advertise_interval_unset (struct peer *peer)
3307{
3308 if (peer_group_active (peer))
3309 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3310
3311 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3312 peer->routeadv = 0;
3313
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003314 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003315 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3316 else
3317 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3318
3319 return 0;
3320}
3321
paul718e3742002-12-13 20:15:29 +00003322/* neighbor interface */
3323int
paulfd79ac92004-10-13 05:06:08 +00003324peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003325{
3326 if (peer->ifname)
3327 free (peer->ifname);
3328 peer->ifname = strdup (str);
3329
3330 return 0;
3331}
3332
3333int
3334peer_interface_unset (struct peer *peer)
3335{
3336 if (peer->ifname)
3337 free (peer->ifname);
3338 peer->ifname = NULL;
3339
3340 return 0;
3341}
3342
3343/* Allow-as in. */
3344int
3345peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3346{
3347 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003348 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003349
3350 if (allow_num < 1 || allow_num > 10)
3351 return BGP_ERR_INVALID_VALUE;
3352
3353 if (peer->allowas_in[afi][safi] != allow_num)
3354 {
3355 peer->allowas_in[afi][safi] = allow_num;
3356 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3357 peer_change_action (peer, afi, safi, peer_change_reset_in);
3358 }
3359
3360 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3361 return 0;
3362
3363 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003364 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003365 {
3366 if (peer->allowas_in[afi][safi] != allow_num)
3367 {
3368 peer->allowas_in[afi][safi] = allow_num;
3369 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3370 peer_change_action (peer, afi, safi, peer_change_reset_in);
3371 }
3372
3373 }
3374 return 0;
3375}
3376
3377int
3378peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3379{
3380 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003381 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003382
3383 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3384 {
3385 peer->allowas_in[afi][safi] = 0;
3386 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3387 }
3388
3389 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3390 return 0;
3391
3392 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003393 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003394 {
3395 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3396 {
3397 peer->allowas_in[afi][safi] = 0;
3398 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3399 }
3400 }
3401 return 0;
3402}
3403
3404int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003405peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003406{
3407 struct bgp *bgp = peer->bgp;
3408 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003409 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003410
3411 if (peer_sort (peer) != BGP_PEER_EBGP
3412 && peer_sort (peer) != BGP_PEER_INTERNAL)
3413 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3414
3415 if (bgp->as == as)
3416 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3417
3418 if (peer_group_active (peer))
3419 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3420
Andrew Certain9d3f9702012-11-07 23:50:07 +00003421 if (peer->as == as)
3422 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3423
paul718e3742002-12-13 20:15:29 +00003424 if (peer->change_local_as == as &&
3425 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003426 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3427 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3428 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003429 return 0;
3430
3431 peer->change_local_as = as;
3432 if (no_prepend)
3433 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3434 else
3435 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3436
Andrew Certain9d3f9702012-11-07 23:50:07 +00003437 if (replace_as)
3438 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3439 else
3440 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3441
paul718e3742002-12-13 20:15:29 +00003442 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3443 {
3444 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003445 {
3446 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3447 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3448 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3449 }
paul718e3742002-12-13 20:15:29 +00003450 else
3451 BGP_EVENT_ADD (peer, BGP_Stop);
3452
3453 return 0;
3454 }
3455
3456 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003457 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003458 {
3459 peer->change_local_as = as;
3460 if (no_prepend)
3461 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3462 else
3463 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3464
Andrew Certain9d3f9702012-11-07 23:50:07 +00003465 if (replace_as)
3466 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3467 else
3468 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3469
paul718e3742002-12-13 20:15:29 +00003470 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003471 {
3472 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3473 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3474 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3475 }
paul718e3742002-12-13 20:15:29 +00003476 else
3477 BGP_EVENT_ADD (peer, BGP_Stop);
3478 }
3479
3480 return 0;
3481}
3482
3483int
3484peer_local_as_unset (struct peer *peer)
3485{
3486 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003487 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003488
3489 if (peer_group_active (peer))
3490 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3491
3492 if (! peer->change_local_as)
3493 return 0;
3494
3495 peer->change_local_as = 0;
3496 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003497 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003498
3499 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3500 {
3501 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003502 {
3503 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3504 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3505 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3506 }
paul718e3742002-12-13 20:15:29 +00003507 else
3508 BGP_EVENT_ADD (peer, BGP_Stop);
3509
3510 return 0;
3511 }
3512
3513 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003514 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003515 {
3516 peer->change_local_as = 0;
3517 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003518 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003519
3520 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003521 {
3522 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3523 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3524 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3525 }
paul718e3742002-12-13 20:15:29 +00003526 else
3527 BGP_EVENT_ADD (peer, BGP_Stop);
3528 }
3529 return 0;
3530}
3531
Paul Jakma0df7c912008-07-21 21:02:49 +00003532/* Set password for authenticating with the peer. */
3533int
3534peer_password_set (struct peer *peer, const char *password)
3535{
3536 struct listnode *nn, *nnode;
3537 int len = password ? strlen(password) : 0;
3538 int ret = BGP_SUCCESS;
3539
3540 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3541 return BGP_ERR_INVALID_VALUE;
3542
3543 if (peer->password && strcmp (peer->password, password) == 0
3544 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3545 return 0;
3546
3547 if (peer->password)
3548 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3549
3550 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3551
3552 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3553 {
3554 if (peer->status == Established)
3555 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3556 else
3557 BGP_EVENT_ADD (peer, BGP_Stop);
3558
3559 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3560 }
3561
3562 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3563 {
3564 if (peer->password && strcmp (peer->password, password) == 0)
3565 continue;
3566
3567 if (peer->password)
3568 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3569
3570 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3571
3572 if (peer->status == Established)
3573 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3574 else
3575 BGP_EVENT_ADD (peer, BGP_Stop);
3576
3577 if (bgp_md5_set (peer) < 0)
3578 ret = BGP_ERR_TCPSIG_FAILED;
3579 }
3580
3581 return ret;
3582}
3583
3584int
3585peer_password_unset (struct peer *peer)
3586{
3587 struct listnode *nn, *nnode;
3588
3589 if (!peer->password
3590 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3591 return 0;
3592
3593 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3594 {
3595 if (peer_group_active (peer)
3596 && peer->group->conf->password
3597 && strcmp (peer->group->conf->password, peer->password) == 0)
3598 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3599
3600 if (peer->status == Established)
3601 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3602 else
3603 BGP_EVENT_ADD (peer, BGP_Stop);
3604
3605 if (peer->password)
3606 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3607
3608 peer->password = NULL;
3609
3610 bgp_md5_set (peer);
3611
3612 return 0;
3613 }
3614
3615 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3616 peer->password = NULL;
3617
3618 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3619 {
3620 if (!peer->password)
3621 continue;
3622
3623 if (peer->status == Established)
3624 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3625 else
3626 BGP_EVENT_ADD (peer, BGP_Stop);
3627
3628 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3629 peer->password = NULL;
3630
3631 bgp_md5_set (peer);
3632 }
3633
3634 return 0;
3635}
3636
paul718e3742002-12-13 20:15:29 +00003637/* Set distribute list to the peer. */
3638int
3639peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003640 const char *name)
paul718e3742002-12-13 20:15:29 +00003641{
3642 struct bgp_filter *filter;
3643 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003644 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003645
3646 if (! peer->afc[afi][safi])
3647 return BGP_ERR_PEER_INACTIVE;
3648
3649 if (direct != FILTER_IN && direct != FILTER_OUT)
3650 return BGP_ERR_INVALID_VALUE;
3651
3652 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3653 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3654
3655 filter = &peer->filter[afi][safi];
3656
3657 if (filter->plist[direct].name)
3658 return BGP_ERR_PEER_FILTER_CONFLICT;
3659
3660 if (filter->dlist[direct].name)
3661 free (filter->dlist[direct].name);
3662 filter->dlist[direct].name = strdup (name);
3663 filter->dlist[direct].alist = access_list_lookup (afi, name);
3664
3665 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3666 return 0;
3667
3668 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003669 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003670 {
3671 filter = &peer->filter[afi][safi];
3672
3673 if (! peer->af_group[afi][safi])
3674 continue;
3675
3676 if (filter->dlist[direct].name)
3677 free (filter->dlist[direct].name);
3678 filter->dlist[direct].name = strdup (name);
3679 filter->dlist[direct].alist = access_list_lookup (afi, name);
3680 }
3681
3682 return 0;
3683}
3684
3685int
3686peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3687{
3688 struct bgp_filter *filter;
3689 struct bgp_filter *gfilter;
3690 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003691 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003692
3693 if (! peer->afc[afi][safi])
3694 return BGP_ERR_PEER_INACTIVE;
3695
3696 if (direct != FILTER_IN && direct != FILTER_OUT)
3697 return BGP_ERR_INVALID_VALUE;
3698
3699 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3700 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3701
3702 filter = &peer->filter[afi][safi];
3703
3704 /* apply peer-group filter */
3705 if (peer->af_group[afi][safi])
3706 {
3707 gfilter = &peer->group->conf->filter[afi][safi];
3708
3709 if (gfilter->dlist[direct].name)
3710 {
3711 if (filter->dlist[direct].name)
3712 free (filter->dlist[direct].name);
3713 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3714 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3715 return 0;
3716 }
3717 }
3718
3719 if (filter->dlist[direct].name)
3720 free (filter->dlist[direct].name);
3721 filter->dlist[direct].name = NULL;
3722 filter->dlist[direct].alist = NULL;
3723
3724 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3725 return 0;
3726
3727 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003728 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003729 {
3730 filter = &peer->filter[afi][safi];
3731
3732 if (! peer->af_group[afi][safi])
3733 continue;
3734
3735 if (filter->dlist[direct].name)
3736 free (filter->dlist[direct].name);
3737 filter->dlist[direct].name = NULL;
3738 filter->dlist[direct].alist = NULL;
3739 }
3740
3741 return 0;
3742}
3743
3744/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003745static void
paul718e3742002-12-13 20:15:29 +00003746peer_distribute_update (struct access_list *access)
3747{
3748 afi_t afi;
3749 safi_t safi;
3750 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003751 struct listnode *mnode, *mnnode;
3752 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003753 struct bgp *bgp;
3754 struct peer *peer;
3755 struct peer_group *group;
3756 struct bgp_filter *filter;
3757
paul1eb8ef22005-04-07 07:30:20 +00003758 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003759 {
paul1eb8ef22005-04-07 07:30:20 +00003760 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003761 {
3762 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3763 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3764 {
3765 filter = &peer->filter[afi][safi];
3766
3767 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3768 {
3769 if (filter->dlist[direct].name)
3770 filter->dlist[direct].alist =
3771 access_list_lookup (afi, filter->dlist[direct].name);
3772 else
3773 filter->dlist[direct].alist = NULL;
3774 }
3775 }
3776 }
paul1eb8ef22005-04-07 07:30:20 +00003777 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003778 {
3779 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3780 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3781 {
3782 filter = &group->conf->filter[afi][safi];
3783
3784 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3785 {
3786 if (filter->dlist[direct].name)
3787 filter->dlist[direct].alist =
3788 access_list_lookup (afi, filter->dlist[direct].name);
3789 else
3790 filter->dlist[direct].alist = NULL;
3791 }
3792 }
3793 }
3794 }
3795}
3796
3797/* Set prefix list to the peer. */
3798int
3799peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003800 const char *name)
paul718e3742002-12-13 20:15:29 +00003801{
3802 struct bgp_filter *filter;
3803 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003804 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003805
3806 if (! peer->afc[afi][safi])
3807 return BGP_ERR_PEER_INACTIVE;
3808
3809 if (direct != FILTER_IN && direct != FILTER_OUT)
3810 return BGP_ERR_INVALID_VALUE;
3811
3812 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3813 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3814
3815 filter = &peer->filter[afi][safi];
3816
3817 if (filter->dlist[direct].name)
3818 return BGP_ERR_PEER_FILTER_CONFLICT;
3819
3820 if (filter->plist[direct].name)
3821 free (filter->plist[direct].name);
3822 filter->plist[direct].name = strdup (name);
3823 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3824
3825 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3826 return 0;
3827
3828 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003829 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003830 {
3831 filter = &peer->filter[afi][safi];
3832
3833 if (! peer->af_group[afi][safi])
3834 continue;
3835
3836 if (filter->plist[direct].name)
3837 free (filter->plist[direct].name);
3838 filter->plist[direct].name = strdup (name);
3839 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3840 }
3841 return 0;
3842}
3843
3844int
3845peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3846{
3847 struct bgp_filter *filter;
3848 struct bgp_filter *gfilter;
3849 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003850 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003851
3852 if (! peer->afc[afi][safi])
3853 return BGP_ERR_PEER_INACTIVE;
3854
3855 if (direct != FILTER_IN && direct != FILTER_OUT)
3856 return BGP_ERR_INVALID_VALUE;
3857
3858 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3859 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3860
3861 filter = &peer->filter[afi][safi];
3862
3863 /* apply peer-group filter */
3864 if (peer->af_group[afi][safi])
3865 {
3866 gfilter = &peer->group->conf->filter[afi][safi];
3867
3868 if (gfilter->plist[direct].name)
3869 {
3870 if (filter->plist[direct].name)
3871 free (filter->plist[direct].name);
3872 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3873 filter->plist[direct].plist = gfilter->plist[direct].plist;
3874 return 0;
3875 }
3876 }
3877
3878 if (filter->plist[direct].name)
3879 free (filter->plist[direct].name);
3880 filter->plist[direct].name = NULL;
3881 filter->plist[direct].plist = NULL;
3882
3883 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3884 return 0;
3885
3886 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003887 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003888 {
3889 filter = &peer->filter[afi][safi];
3890
3891 if (! peer->af_group[afi][safi])
3892 continue;
3893
3894 if (filter->plist[direct].name)
3895 free (filter->plist[direct].name);
3896 filter->plist[direct].name = NULL;
3897 filter->plist[direct].plist = NULL;
3898 }
3899
3900 return 0;
3901}
3902
3903/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003904static void
paul718e3742002-12-13 20:15:29 +00003905peer_prefix_list_update (struct prefix_list *plist)
3906{
paul1eb8ef22005-04-07 07:30:20 +00003907 struct listnode *mnode, *mnnode;
3908 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003909 struct bgp *bgp;
3910 struct peer *peer;
3911 struct peer_group *group;
3912 struct bgp_filter *filter;
3913 afi_t afi;
3914 safi_t safi;
3915 int direct;
3916
paul1eb8ef22005-04-07 07:30:20 +00003917 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003918 {
paul1eb8ef22005-04-07 07:30:20 +00003919 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003920 {
3921 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3922 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3923 {
3924 filter = &peer->filter[afi][safi];
3925
3926 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3927 {
3928 if (filter->plist[direct].name)
3929 filter->plist[direct].plist =
3930 prefix_list_lookup (afi, filter->plist[direct].name);
3931 else
3932 filter->plist[direct].plist = NULL;
3933 }
3934 }
3935 }
paul1eb8ef22005-04-07 07:30:20 +00003936 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003937 {
3938 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3939 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3940 {
3941 filter = &group->conf->filter[afi][safi];
3942
3943 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3944 {
3945 if (filter->plist[direct].name)
3946 filter->plist[direct].plist =
3947 prefix_list_lookup (afi, filter->plist[direct].name);
3948 else
3949 filter->plist[direct].plist = NULL;
3950 }
3951 }
3952 }
3953 }
3954}
3955
3956int
3957peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003958 const char *name)
paul718e3742002-12-13 20:15:29 +00003959{
3960 struct bgp_filter *filter;
3961 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003962 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003963
3964 if (! peer->afc[afi][safi])
3965 return BGP_ERR_PEER_INACTIVE;
3966
3967 if (direct != FILTER_IN && direct != FILTER_OUT)
3968 return BGP_ERR_INVALID_VALUE;
3969
3970 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3971 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3972
3973 filter = &peer->filter[afi][safi];
3974
3975 if (filter->aslist[direct].name)
3976 free (filter->aslist[direct].name);
3977 filter->aslist[direct].name = strdup (name);
3978 filter->aslist[direct].aslist = as_list_lookup (name);
3979
3980 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3981 return 0;
3982
3983 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003984 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003985 {
3986 filter = &peer->filter[afi][safi];
3987
3988 if (! peer->af_group[afi][safi])
3989 continue;
3990
3991 if (filter->aslist[direct].name)
3992 free (filter->aslist[direct].name);
3993 filter->aslist[direct].name = strdup (name);
3994 filter->aslist[direct].aslist = as_list_lookup (name);
3995 }
3996 return 0;
3997}
3998
3999int
4000peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4001{
4002 struct bgp_filter *filter;
4003 struct bgp_filter *gfilter;
4004 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004005 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004006
4007 if (! peer->afc[afi][safi])
4008 return BGP_ERR_PEER_INACTIVE;
4009
hassob5f29602005-05-25 21:00:28 +00004010 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004011 return BGP_ERR_INVALID_VALUE;
4012
hassob5f29602005-05-25 21:00:28 +00004013 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004014 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4015
4016 filter = &peer->filter[afi][safi];
4017
4018 /* apply peer-group filter */
4019 if (peer->af_group[afi][safi])
4020 {
4021 gfilter = &peer->group->conf->filter[afi][safi];
4022
4023 if (gfilter->aslist[direct].name)
4024 {
4025 if (filter->aslist[direct].name)
4026 free (filter->aslist[direct].name);
4027 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4028 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4029 return 0;
4030 }
4031 }
4032
4033 if (filter->aslist[direct].name)
4034 free (filter->aslist[direct].name);
4035 filter->aslist[direct].name = NULL;
4036 filter->aslist[direct].aslist = NULL;
4037
4038 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4039 return 0;
4040
4041 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004042 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004043 {
4044 filter = &peer->filter[afi][safi];
4045
4046 if (! peer->af_group[afi][safi])
4047 continue;
4048
4049 if (filter->aslist[direct].name)
4050 free (filter->aslist[direct].name);
4051 filter->aslist[direct].name = NULL;
4052 filter->aslist[direct].aslist = NULL;
4053 }
4054
4055 return 0;
4056}
4057
paul94f2b392005-06-28 12:44:16 +00004058static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004059peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004060{
4061 afi_t afi;
4062 safi_t safi;
4063 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004064 struct listnode *mnode, *mnnode;
4065 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004066 struct bgp *bgp;
4067 struct peer *peer;
4068 struct peer_group *group;
4069 struct bgp_filter *filter;
4070
paul1eb8ef22005-04-07 07:30:20 +00004071 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004072 {
paul1eb8ef22005-04-07 07:30:20 +00004073 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004074 {
4075 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4076 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4077 {
4078 filter = &peer->filter[afi][safi];
4079
4080 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4081 {
4082 if (filter->aslist[direct].name)
4083 filter->aslist[direct].aslist =
4084 as_list_lookup (filter->aslist[direct].name);
4085 else
4086 filter->aslist[direct].aslist = NULL;
4087 }
4088 }
4089 }
paul1eb8ef22005-04-07 07:30:20 +00004090 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004091 {
4092 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4093 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4094 {
4095 filter = &group->conf->filter[afi][safi];
4096
4097 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4098 {
4099 if (filter->aslist[direct].name)
4100 filter->aslist[direct].aslist =
4101 as_list_lookup (filter->aslist[direct].name);
4102 else
4103 filter->aslist[direct].aslist = NULL;
4104 }
4105 }
4106 }
4107 }
4108}
4109
4110/* Set route-map to the peer. */
4111int
4112peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004113 const char *name)
paul718e3742002-12-13 20:15:29 +00004114{
4115 struct bgp_filter *filter;
4116 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004117 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004118
4119 if (! peer->afc[afi][safi])
4120 return BGP_ERR_PEER_INACTIVE;
4121
paulfee0f4c2004-09-13 05:12:46 +00004122 if (direct != RMAP_IN && direct != RMAP_OUT &&
4123 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004124 return BGP_ERR_INVALID_VALUE;
4125
paulfee0f4c2004-09-13 05:12:46 +00004126 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4127 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004128 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4129
4130 filter = &peer->filter[afi][safi];
4131
4132 if (filter->map[direct].name)
4133 free (filter->map[direct].name);
4134
4135 filter->map[direct].name = strdup (name);
4136 filter->map[direct].map = route_map_lookup_by_name (name);
4137
4138 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4139 return 0;
4140
4141 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004142 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004143 {
4144 filter = &peer->filter[afi][safi];
4145
4146 if (! peer->af_group[afi][safi])
4147 continue;
4148
4149 if (filter->map[direct].name)
4150 free (filter->map[direct].name);
4151 filter->map[direct].name = strdup (name);
4152 filter->map[direct].map = route_map_lookup_by_name (name);
4153 }
4154 return 0;
4155}
4156
4157/* Unset route-map from the peer. */
4158int
4159peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4160{
4161 struct bgp_filter *filter;
4162 struct bgp_filter *gfilter;
4163 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004164 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004165
4166 if (! peer->afc[afi][safi])
4167 return BGP_ERR_PEER_INACTIVE;
4168
hassob5f29602005-05-25 21:00:28 +00004169 if (direct != RMAP_IN && direct != RMAP_OUT &&
4170 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004171 return BGP_ERR_INVALID_VALUE;
4172
hassob5f29602005-05-25 21:00:28 +00004173 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4174 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004175 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4176
4177 filter = &peer->filter[afi][safi];
4178
4179 /* apply peer-group filter */
4180 if (peer->af_group[afi][safi])
4181 {
4182 gfilter = &peer->group->conf->filter[afi][safi];
4183
4184 if (gfilter->map[direct].name)
4185 {
4186 if (filter->map[direct].name)
4187 free (filter->map[direct].name);
4188 filter->map[direct].name = strdup (gfilter->map[direct].name);
4189 filter->map[direct].map = gfilter->map[direct].map;
4190 return 0;
4191 }
4192 }
4193
4194 if (filter->map[direct].name)
4195 free (filter->map[direct].name);
4196 filter->map[direct].name = NULL;
4197 filter->map[direct].map = NULL;
4198
4199 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4200 return 0;
4201
4202 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004203 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004204 {
4205 filter = &peer->filter[afi][safi];
4206
4207 if (! peer->af_group[afi][safi])
4208 continue;
4209
4210 if (filter->map[direct].name)
4211 free (filter->map[direct].name);
4212 filter->map[direct].name = NULL;
4213 filter->map[direct].map = NULL;
4214 }
4215 return 0;
4216}
4217
4218/* Set unsuppress-map to the peer. */
4219int
paulfd79ac92004-10-13 05:06:08 +00004220peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4221 const char *name)
paul718e3742002-12-13 20:15:29 +00004222{
4223 struct bgp_filter *filter;
4224 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004225 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004226
4227 if (! peer->afc[afi][safi])
4228 return BGP_ERR_PEER_INACTIVE;
4229
4230 if (peer_is_group_member (peer, afi, safi))
4231 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4232
4233 filter = &peer->filter[afi][safi];
4234
4235 if (filter->usmap.name)
4236 free (filter->usmap.name);
4237
4238 filter->usmap.name = strdup (name);
4239 filter->usmap.map = route_map_lookup_by_name (name);
4240
4241 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4242 return 0;
4243
4244 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004245 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004246 {
4247 filter = &peer->filter[afi][safi];
4248
4249 if (! peer->af_group[afi][safi])
4250 continue;
4251
4252 if (filter->usmap.name)
4253 free (filter->usmap.name);
4254 filter->usmap.name = strdup (name);
4255 filter->usmap.map = route_map_lookup_by_name (name);
4256 }
4257 return 0;
4258}
4259
4260/* Unset route-map from the peer. */
4261int
4262peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4263{
4264 struct bgp_filter *filter;
4265 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004266 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004267
4268 if (! peer->afc[afi][safi])
4269 return BGP_ERR_PEER_INACTIVE;
4270
4271 if (peer_is_group_member (peer, afi, safi))
4272 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4273
4274 filter = &peer->filter[afi][safi];
4275
4276 if (filter->usmap.name)
4277 free (filter->usmap.name);
4278 filter->usmap.name = NULL;
4279 filter->usmap.map = NULL;
4280
4281 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4282 return 0;
4283
4284 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004285 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004286 {
4287 filter = &peer->filter[afi][safi];
4288
4289 if (! peer->af_group[afi][safi])
4290 continue;
4291
4292 if (filter->usmap.name)
4293 free (filter->usmap.name);
4294 filter->usmap.name = NULL;
4295 filter->usmap.map = NULL;
4296 }
4297 return 0;
4298}
4299
4300int
4301peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004302 u_int32_t max, u_char threshold,
4303 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004304{
4305 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004306 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004307
4308 if (! peer->afc[afi][safi])
4309 return BGP_ERR_PEER_INACTIVE;
4310
4311 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4312 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004313 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004314 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004315 if (warning)
4316 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4317 else
4318 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4319
4320 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4321 return 0;
4322
4323 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004324 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004325 {
4326 if (! peer->af_group[afi][safi])
4327 continue;
4328
4329 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4330 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004331 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004332 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004333 if (warning)
4334 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4335 else
4336 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4337 }
4338 return 0;
4339}
4340
4341int
4342peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4343{
4344 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004345 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004346
4347 if (! peer->afc[afi][safi])
4348 return BGP_ERR_PEER_INACTIVE;
4349
4350 /* apply peer-group config */
4351 if (peer->af_group[afi][safi])
4352 {
4353 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4354 PEER_FLAG_MAX_PREFIX))
4355 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4356 else
4357 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4358
4359 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4360 PEER_FLAG_MAX_PREFIX_WARNING))
4361 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4362 else
4363 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4364
4365 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004366 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004367 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004368 return 0;
4369 }
4370
4371 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4372 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4373 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004374 peer->pmax_threshold[afi][safi] = 0;
4375 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004376
4377 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4378 return 0;
4379
4380 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004381 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004382 {
4383 if (! peer->af_group[afi][safi])
4384 continue;
4385
4386 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4387 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4388 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004389 peer->pmax_threshold[afi][safi] = 0;
4390 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004391 }
4392 return 0;
4393}
4394
Nick Hilliardfa411a22011-03-23 15:33:17 +00004395/* Set # of hops between us and BGP peer. */
4396int
4397peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4398{
4399 struct peer_group *group;
4400 struct listnode *node, *nnode;
4401 struct peer *peer1;
4402 int ret;
4403
4404 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4405
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004406 if (peer->sort == BGP_PEER_IBGP)
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004407 return BGP_ERR_NO_IBGP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004408
4409 /* We cannot configure ttl-security hops when ebgp-multihop is already
4410 set. For non peer-groups, the check is simple. For peer-groups, it's
4411 slightly messy, because we need to check both the peer-group structure
4412 and all peer-group members for any trace of ebgp-multihop configuration
4413 before actually applying the ttl-security rules. Cisco really made a
4414 mess of this configuration parameter, and OpenBGPD got it right.
4415 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004416
4417 if (peer->gtsm_hops == 0) {
4418 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4419 {
4420 group = peer->group;
4421 if (group->conf->ttl != 1)
4422 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004423
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004424 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4425 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004426 if (peer1->sort == BGP_PEER_IBGP)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004427 continue;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004428
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004429 if (peer1->ttl != 1)
4430 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4431 }
4432 }
4433 else
4434 {
4435 if (peer->ttl != 1)
4436 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4437 }
4438 /* specify MAXTTL on outgoing packets */
4439 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4440 if (ret != 0)
4441 return ret;
4442 }
4443
Nick Hilliardfa411a22011-03-23 15:33:17 +00004444 peer->gtsm_hops = gtsm_hops;
4445
Nick Hilliardfa411a22011-03-23 15:33:17 +00004446 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4447 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004448 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004449 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4450 }
4451 else
4452 {
4453 group = peer->group;
4454 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4455 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004456 if (peer->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004457 continue;
4458
4459 peer->gtsm_hops = group->conf->gtsm_hops;
4460
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004461 /* Change setting of existing peer
4462 * established then change value (may break connectivity)
4463 * not established yet (teardown session and restart)
4464 * no session then do nothing (will get handled by next connection)
4465 */
4466 if (peer->status == Established)
4467 {
4468 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4469 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4470 MAXTTL + 1 - peer->gtsm_hops);
4471 }
4472 else if (peer->status < Established)
4473 {
4474 if (BGP_DEBUG (events, EVENTS))
4475 zlog_debug ("%s Min-ttl changed", peer->host);
4476 BGP_EVENT_ADD (peer, BGP_Stop);
4477 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004478 }
4479 }
4480
4481 return 0;
4482}
4483
4484int
4485peer_ttl_security_hops_unset (struct peer *peer)
4486{
4487 struct peer_group *group;
4488 struct listnode *node, *nnode;
4489 struct peer *opeer;
4490
4491 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4492
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004493 if (peer->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004494 return 0;
4495
4496 /* if a peer-group member, then reset to peer-group default rather than 0 */
4497 if (peer_group_active (peer))
4498 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4499 else
4500 peer->gtsm_hops = 0;
4501
4502 opeer = peer;
4503 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4504 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004505 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004506 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4507 }
4508 else
4509 {
4510 group = peer->group;
4511 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4512 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004513 if (peer->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004514 continue;
4515
4516 peer->gtsm_hops = 0;
4517
4518 if (peer->fd >= 0)
4519 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4520 }
4521 }
4522
4523 return peer_ebgp_multihop_unset (opeer);
4524}
4525
paul718e3742002-12-13 20:15:29 +00004526int
4527peer_clear (struct peer *peer)
4528{
4529 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4530 {
hasso0a486e52005-02-01 20:57:17 +00004531 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4532 {
4533 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4534 if (peer->t_pmax_restart)
4535 {
4536 BGP_TIMER_OFF (peer->t_pmax_restart);
4537 if (BGP_DEBUG (events, EVENTS))
4538 zlog_debug ("%s Maximum-prefix restart timer canceled",
4539 peer->host);
4540 }
4541 BGP_EVENT_ADD (peer, BGP_Start);
4542 return 0;
4543 }
4544
paul718e3742002-12-13 20:15:29 +00004545 peer->v_start = BGP_INIT_START_TIMER;
4546 if (peer->status == Established)
4547 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4548 BGP_NOTIFY_CEASE_ADMIN_RESET);
4549 else
4550 BGP_EVENT_ADD (peer, BGP_Stop);
4551 }
4552 return 0;
4553}
4554
4555int
4556peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4557 enum bgp_clear_type stype)
4558{
4559 if (peer->status != Established)
4560 return 0;
4561
4562 if (! peer->afc[afi][safi])
4563 return BGP_ERR_AF_UNCONFIGURED;
4564
paulfee0f4c2004-09-13 05:12:46 +00004565 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4566 {
4567 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4568 return 0;
4569 bgp_check_local_routes_rsclient (peer, afi, safi);
4570 bgp_soft_reconfig_rsclient (peer, afi, safi);
4571 }
4572
paul718e3742002-12-13 20:15:29 +00004573 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4574 bgp_announce_route (peer, afi, safi);
4575
4576 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4577 {
4578 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4579 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4580 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4581 {
4582 struct bgp_filter *filter = &peer->filter[afi][safi];
4583 u_char prefix_type;
4584
4585 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4586 prefix_type = ORF_TYPE_PREFIX;
4587 else
4588 prefix_type = ORF_TYPE_PREFIX_OLD;
4589
4590 if (filter->plist[FILTER_IN].plist)
4591 {
4592 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4593 bgp_route_refresh_send (peer, afi, safi,
4594 prefix_type, REFRESH_DEFER, 1);
4595 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4596 REFRESH_IMMEDIATE, 0);
4597 }
4598 else
4599 {
4600 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4601 bgp_route_refresh_send (peer, afi, safi,
4602 prefix_type, REFRESH_IMMEDIATE, 1);
4603 else
4604 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4605 }
4606 return 0;
4607 }
4608 }
4609
4610 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4611 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4612 {
4613 /* If neighbor has soft reconfiguration inbound flag.
4614 Use Adj-RIB-In database. */
4615 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4616 bgp_soft_reconfig_in (peer, afi, safi);
4617 else
4618 {
4619 /* If neighbor has route refresh capability, send route refresh
4620 message to the peer. */
4621 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4622 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4623 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4624 else
4625 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4626 }
4627 }
4628 return 0;
4629}
4630
paulfd79ac92004-10-13 05:06:08 +00004631/* Display peer uptime.*/
4632/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004633char *
4634peer_uptime (time_t uptime2, char *buf, size_t len)
4635{
4636 time_t uptime1;
4637 struct tm *tm;
4638
4639 /* Check buffer length. */
4640 if (len < BGP_UPTIME_LEN)
4641 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004642 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004643 /* XXX: should return status instead of buf... */
4644 snprintf (buf, len, "<error> ");
4645 return buf;
paul718e3742002-12-13 20:15:29 +00004646 }
4647
4648 /* If there is no connection has been done before print `never'. */
4649 if (uptime2 == 0)
4650 {
4651 snprintf (buf, len, "never ");
4652 return buf;
4653 }
4654
4655 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004656 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004657 uptime1 -= uptime2;
4658 tm = gmtime (&uptime1);
4659
4660 /* Making formatted timer strings. */
4661#define ONE_DAY_SECOND 60*60*24
4662#define ONE_WEEK_SECOND 60*60*24*7
4663
4664 if (uptime1 < ONE_DAY_SECOND)
4665 snprintf (buf, len, "%02d:%02d:%02d",
4666 tm->tm_hour, tm->tm_min, tm->tm_sec);
4667 else if (uptime1 < ONE_WEEK_SECOND)
4668 snprintf (buf, len, "%dd%02dh%02dm",
4669 tm->tm_yday, tm->tm_hour, tm->tm_min);
4670 else
4671 snprintf (buf, len, "%02dw%dd%02dh",
4672 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4673 return buf;
4674}
4675
paul94f2b392005-06-28 12:44:16 +00004676static void
paul718e3742002-12-13 20:15:29 +00004677bgp_config_write_filter (struct vty *vty, struct peer *peer,
4678 afi_t afi, safi_t safi)
4679{
4680 struct bgp_filter *filter;
4681 struct bgp_filter *gfilter = NULL;
4682 char *addr;
4683 int in = FILTER_IN;
4684 int out = FILTER_OUT;
4685
4686 addr = peer->host;
4687 filter = &peer->filter[afi][safi];
4688 if (peer->af_group[afi][safi])
4689 gfilter = &peer->group->conf->filter[afi][safi];
4690
4691 /* distribute-list. */
4692 if (filter->dlist[in].name)
4693 if (! gfilter || ! gfilter->dlist[in].name
4694 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4695 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4696 filter->dlist[in].name, VTY_NEWLINE);
4697 if (filter->dlist[out].name && ! gfilter)
4698 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4699 filter->dlist[out].name, VTY_NEWLINE);
4700
4701 /* prefix-list. */
4702 if (filter->plist[in].name)
4703 if (! gfilter || ! gfilter->plist[in].name
4704 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4705 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4706 filter->plist[in].name, VTY_NEWLINE);
4707 if (filter->plist[out].name && ! gfilter)
4708 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4709 filter->plist[out].name, VTY_NEWLINE);
4710
4711 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004712 if (filter->map[RMAP_IN].name)
4713 if (! gfilter || ! gfilter->map[RMAP_IN].name
4714 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004715 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004716 filter->map[RMAP_IN].name, VTY_NEWLINE);
4717 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004718 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004719 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4720 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4721 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4722 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4723 if (filter->map[RMAP_EXPORT].name)
4724 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4725 || strcmp (filter->map[RMAP_EXPORT].name,
4726 gfilter->map[RMAP_EXPORT].name) != 0)
4727 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4728 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004729
4730 /* unsuppress-map */
4731 if (filter->usmap.name && ! gfilter)
4732 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4733 filter->usmap.name, VTY_NEWLINE);
4734
4735 /* filter-list. */
4736 if (filter->aslist[in].name)
4737 if (! gfilter || ! gfilter->aslist[in].name
4738 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4739 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4740 filter->aslist[in].name, VTY_NEWLINE);
4741 if (filter->aslist[out].name && ! gfilter)
4742 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4743 filter->aslist[out].name, VTY_NEWLINE);
4744}
4745
4746/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004747static void
paul718e3742002-12-13 20:15:29 +00004748bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4749 struct peer *peer, afi_t afi, safi_t safi)
4750{
paul718e3742002-12-13 20:15:29 +00004751 struct peer *g_peer = NULL;
4752 char buf[SU_ADDRSTRLEN];
4753 char *addr;
4754
paul718e3742002-12-13 20:15:29 +00004755 addr = peer->host;
4756 if (peer_group_active (peer))
4757 g_peer = peer->group->conf;
4758
4759 /************************************
4760 ****** Global to the neighbor ******
4761 ************************************/
4762 if (afi == AFI_IP && safi == SAFI_UNICAST)
4763 {
4764 /* remote-as. */
4765 if (! peer_group_active (peer))
4766 {
4767 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4768 vty_out (vty, " neighbor %s peer-group%s", addr,
4769 VTY_NEWLINE);
4770 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004771 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004772 VTY_NEWLINE);
4773 }
4774 else
4775 {
4776 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004777 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004778 VTY_NEWLINE);
4779 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4780 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4781 peer->group->name, VTY_NEWLINE);
4782 }
4783
4784 /* local-as. */
4785 if (peer->change_local_as)
4786 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00004787 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004788 peer->change_local_as,
4789 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00004790 " no-prepend" : "",
4791 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
4792 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004793
4794 /* Description. */
4795 if (peer->desc)
4796 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4797 VTY_NEWLINE);
4798
4799 /* Shutdown. */
4800 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4801 if (! peer_group_active (peer) ||
4802 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4803 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4804
Paul Jakma0df7c912008-07-21 21:02:49 +00004805 /* Password. */
4806 if (peer->password)
4807 if (!peer_group_active (peer)
4808 || ! g_peer->password
4809 || strcmp (peer->password, g_peer->password) != 0)
4810 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4811 VTY_NEWLINE);
4812
paul718e3742002-12-13 20:15:29 +00004813 /* BGP port. */
4814 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004815 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004816 VTY_NEWLINE);
4817
4818 /* Local interface name. */
4819 if (peer->ifname)
4820 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4821 VTY_NEWLINE);
4822
4823 /* Passive. */
4824 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4825 if (! peer_group_active (peer) ||
4826 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4827 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4828
4829 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004830 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00004831 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00004832 if (! peer_group_active (peer) ||
4833 g_peer->ttl != peer->ttl)
4834 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4835 VTY_NEWLINE);
4836
Nick Hilliardfa411a22011-03-23 15:33:17 +00004837 /* ttl-security hops */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004838 if (peer->sort != BGP_PEER_IBGP && peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004839 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004840 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00004841 peer->gtsm_hops, VTY_NEWLINE);
4842
hasso6ffd2072005-02-02 14:50:11 +00004843 /* disable-connected-check. */
4844 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004845 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004846 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4847 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004848
4849 /* Update-source. */
4850 if (peer->update_if)
4851 if (! peer_group_active (peer) || ! g_peer->update_if
4852 || strcmp (g_peer->update_if, peer->update_if) != 0)
4853 vty_out (vty, " neighbor %s update-source %s%s", addr,
4854 peer->update_if, VTY_NEWLINE);
4855 if (peer->update_source)
4856 if (! peer_group_active (peer) || ! g_peer->update_source
4857 || sockunion_cmp (g_peer->update_source,
4858 peer->update_source) != 0)
4859 vty_out (vty, " neighbor %s update-source %s%s", addr,
4860 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4861 VTY_NEWLINE);
4862
paul718e3742002-12-13 20:15:29 +00004863 /* advertisement-interval */
4864 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4865 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4866 addr, peer->v_routeadv, VTY_NEWLINE);
4867
4868 /* timers. */
4869 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4870 && ! peer_group_active (peer))
4871 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4872 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4873
4874 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4875 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4876 peer->connect, VTY_NEWLINE);
4877
4878 /* Default weight. */
4879 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4880 if (! peer_group_active (peer) ||
4881 g_peer->weight != peer->weight)
4882 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4883 VTY_NEWLINE);
4884
paul718e3742002-12-13 20:15:29 +00004885 /* Dynamic capability. */
4886 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4887 if (! peer_group_active (peer) ||
4888 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4889 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4890 VTY_NEWLINE);
4891
4892 /* dont capability negotiation. */
4893 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4894 if (! peer_group_active (peer) ||
4895 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4896 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4897 VTY_NEWLINE);
4898
4899 /* override capability negotiation. */
4900 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4901 if (! peer_group_active (peer) ||
4902 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4903 vty_out (vty, " neighbor %s override-capability%s", addr,
4904 VTY_NEWLINE);
4905
4906 /* strict capability negotiation. */
4907 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4908 if (! peer_group_active (peer) ||
4909 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4910 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4911 VTY_NEWLINE);
4912
Christian Franke15c71342012-11-19 11:17:31 +00004913 if (! peer->af_group[AFI_IP][SAFI_UNICAST])
paul718e3742002-12-13 20:15:29 +00004914 {
4915 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4916 {
4917 if (peer->afc[AFI_IP][SAFI_UNICAST])
4918 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4919 }
4920 else
4921 {
4922 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4923 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4924 }
4925 }
4926 }
4927
4928
4929 /************************************
4930 ****** Per AF to the neighbor ******
4931 ************************************/
4932
4933 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4934 {
4935 if (peer->af_group[afi][safi])
4936 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4937 peer->group->name, VTY_NEWLINE);
4938 else
4939 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4940 }
4941
4942 /* ORF capability. */
4943 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4944 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4945 if (! peer->af_group[afi][safi])
4946 {
4947 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4948
4949 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4950 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4951 vty_out (vty, " both");
4952 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4953 vty_out (vty, " send");
4954 else
4955 vty_out (vty, " receive");
4956 vty_out (vty, "%s", VTY_NEWLINE);
4957 }
4958
4959 /* Route reflector client. */
4960 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4961 && ! peer->af_group[afi][safi])
4962 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4963 VTY_NEWLINE);
4964
4965 /* Nexthop self. */
4966 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4967 && ! peer->af_group[afi][safi])
4968 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4969
4970 /* Remove private AS. */
4971 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4972 && ! peer->af_group[afi][safi])
4973 vty_out (vty, " neighbor %s remove-private-AS%s",
4974 addr, VTY_NEWLINE);
4975
4976 /* send-community print. */
4977 if (! peer->af_group[afi][safi])
4978 {
4979 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4980 {
4981 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4982 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4983 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4984 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4985 vty_out (vty, " neighbor %s send-community extended%s",
4986 addr, VTY_NEWLINE);
4987 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4988 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4989 }
4990 else
4991 {
4992 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4993 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4994 vty_out (vty, " no neighbor %s send-community both%s",
4995 addr, VTY_NEWLINE);
4996 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4997 vty_out (vty, " no neighbor %s send-community extended%s",
4998 addr, VTY_NEWLINE);
4999 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5000 vty_out (vty, " no neighbor %s send-community%s",
5001 addr, VTY_NEWLINE);
5002 }
5003 }
5004
5005 /* Default information */
5006 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5007 && ! peer->af_group[afi][safi])
5008 {
5009 vty_out (vty, " neighbor %s default-originate", addr);
5010 if (peer->default_rmap[afi][safi].name)
5011 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5012 vty_out (vty, "%s", VTY_NEWLINE);
5013 }
5014
5015 /* Soft reconfiguration inbound. */
5016 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5017 if (! peer->af_group[afi][safi] ||
5018 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5019 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5020 VTY_NEWLINE);
5021
5022 /* maximum-prefix. */
5023 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5024 if (! peer->af_group[afi][safi]
5025 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005026 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005027 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5028 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005029 {
hasso0a486e52005-02-01 20:57:17 +00005030 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5031 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5032 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5033 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5034 vty_out (vty, " warning-only");
5035 if (peer->pmax_restart[afi][safi])
5036 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5037 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005038 }
paul718e3742002-12-13 20:15:29 +00005039
5040 /* Route server client. */
5041 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5042 && ! peer->af_group[afi][safi])
5043 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5044
Dylan Hall3cf12882011-10-27 15:28:17 +04005045 /* Nexthop-local unchanged. */
5046 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5047 && ! peer->af_group[afi][safi])
5048 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5049
paul718e3742002-12-13 20:15:29 +00005050 /* Allow AS in. */
5051 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5052 if (! peer_group_active (peer)
5053 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5054 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5055 {
5056 if (peer->allowas_in[afi][safi] == 3)
5057 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5058 else
5059 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5060 peer->allowas_in[afi][safi], VTY_NEWLINE);
5061 }
5062
5063 /* Filter. */
5064 bgp_config_write_filter (vty, peer, afi, safi);
5065
5066 /* atribute-unchanged. */
5067 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5068 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5069 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5070 && ! peer->af_group[afi][safi])
5071 {
5072 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5073 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5074 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5075 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5076 else
5077 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5078 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5079 " as-path" : "",
5080 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5081 " next-hop" : "",
5082 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5083 " med" : "", VTY_NEWLINE);
5084 }
5085}
5086
5087/* Display "address-family" configuration header. */
5088void
5089bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5090 int *write)
5091{
5092 if (*write)
5093 return;
5094
5095 if (afi == AFI_IP && safi == SAFI_UNICAST)
5096 return;
5097
5098 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5099
5100 if (afi == AFI_IP)
5101 {
5102 if (safi == SAFI_MULTICAST)
5103 vty_out (vty, "ipv4 multicast");
5104 else if (safi == SAFI_MPLS_VPN)
5105 vty_out (vty, "vpnv4 unicast");
5106 }
5107 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005108 {
5109 vty_out (vty, "ipv6");
5110
5111 if (safi == SAFI_MULTICAST)
5112 vty_out (vty, " multicast");
5113 }
paul718e3742002-12-13 20:15:29 +00005114
5115 vty_out (vty, "%s", VTY_NEWLINE);
5116
5117 *write = 1;
5118}
5119
5120/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005121static int
paul718e3742002-12-13 20:15:29 +00005122bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5123 safi_t safi)
5124{
5125 int write = 0;
5126 struct peer *peer;
5127 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005128 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005129
5130 bgp_config_write_network (vty, bgp, afi, safi, &write);
5131
5132 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5133
paul1eb8ef22005-04-07 07:30:20 +00005134 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005135 {
5136 if (group->conf->afc[afi][safi])
5137 {
5138 bgp_config_write_family_header (vty, afi, safi, &write);
5139 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5140 }
5141 }
paul1eb8ef22005-04-07 07:30:20 +00005142 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005143 {
5144 if (peer->afc[afi][safi])
5145 {
5146 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5147 {
5148 bgp_config_write_family_header (vty, afi, safi, &write);
5149 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5150 }
5151 }
5152 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005153
5154 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5155
paul718e3742002-12-13 20:15:29 +00005156 if (write)
5157 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5158
5159 return write;
5160}
5161
5162int
5163bgp_config_write (struct vty *vty)
5164{
5165 int write = 0;
5166 struct bgp *bgp;
5167 struct peer_group *group;
5168 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005169 struct listnode *node, *nnode;
5170 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005171
5172 /* BGP Multiple instance. */
5173 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5174 {
5175 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5176 write++;
5177 }
5178
5179 /* BGP Config type. */
5180 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5181 {
5182 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5183 write++;
5184 }
5185
5186 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005187 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005188 {
5189 if (write)
5190 vty_out (vty, "!%s", VTY_NEWLINE);
5191
5192 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005193 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005194
5195 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5196 {
5197 if (bgp->name)
5198 vty_out (vty, " view %s", bgp->name);
5199 }
5200 vty_out (vty, "%s", VTY_NEWLINE);
5201
5202 /* No Synchronization */
5203 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5204 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5205
5206 /* BGP fast-external-failover. */
5207 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5208 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5209
5210 /* BGP router ID. */
5211 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5212 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5213 VTY_NEWLINE);
5214
paul848973c2003-08-13 00:32:49 +00005215 /* BGP log-neighbor-changes. */
5216 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5217 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
5218
paul718e3742002-12-13 20:15:29 +00005219 /* BGP configuration. */
5220 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5221 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5222
5223 /* BGP default ipv4-unicast. */
5224 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5225 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5226
5227 /* BGP default local-preference. */
5228 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5229 vty_out (vty, " bgp default local-preference %d%s",
5230 bgp->default_local_pref, VTY_NEWLINE);
5231
5232 /* BGP client-to-client reflection. */
5233 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5234 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5235
5236 /* BGP cluster ID. */
5237 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5238 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5239 VTY_NEWLINE);
5240
hassoe0701b72004-05-20 09:19:34 +00005241 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005242 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005243 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5244 VTY_NEWLINE);
5245
5246 /* Confederation peer */
5247 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005248 {
hassoe0701b72004-05-20 09:19:34 +00005249 int i;
paul718e3742002-12-13 20:15:29 +00005250
hassoe0701b72004-05-20 09:19:34 +00005251 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005252
hassoe0701b72004-05-20 09:19:34 +00005253 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005254 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005255
hassoe0701b72004-05-20 09:19:34 +00005256 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005257 }
5258
5259 /* BGP enforce-first-as. */
5260 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5261 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5262
5263 /* BGP deterministic-med. */
5264 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5265 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005266
5267 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005268 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5269 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5270 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005271 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5272 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5273
paul718e3742002-12-13 20:15:29 +00005274 /* BGP bestpath method. */
5275 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5276 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005277 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5278 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
Pradosh Mohapatra2fdd4552013-09-07 07:02:36 +00005279 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
5280 vty_out (vty, " bgp bestpath as-path multipath-relax%s", VTY_NEWLINE);
5281 }
paul718e3742002-12-13 20:15:29 +00005282 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5283 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5284 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5285 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5286 {
5287 vty_out (vty, " bgp bestpath med");
5288 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5289 vty_out (vty, " confed");
5290 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5291 vty_out (vty, " missing-as-worst");
5292 vty_out (vty, "%s", VTY_NEWLINE);
5293 }
5294
5295 /* BGP network import check. */
5296 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5297 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5298
5299 /* BGP scan interval. */
5300 bgp_config_write_scan_time (vty);
5301
5302 /* BGP flag dampening. */
5303 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5304 BGP_CONFIG_DAMPENING))
5305 bgp_config_write_damp (vty);
5306
5307 /* BGP static route configuration. */
5308 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5309
5310 /* BGP redistribute configuration. */
5311 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5312
5313 /* BGP timers configuration. */
5314 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5315 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5316 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5317 bgp->default_holdtime, VTY_NEWLINE);
5318
5319 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005320 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005321 {
5322 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5323 }
5324
5325 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005326 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005327 {
5328 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5329 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5330 }
5331
Josh Bailey165b5ff2011-07-20 20:43:22 -07005332 /* maximum-paths */
5333 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5334
paul718e3742002-12-13 20:15:29 +00005335 /* Distance configuration. */
5336 bgp_config_write_distance (vty, bgp);
5337
5338 /* No auto-summary */
5339 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5340 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5341
5342 /* IPv4 multicast configuration. */
5343 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5344
5345 /* IPv4 VPN configuration. */
5346 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5347
5348 /* IPv6 unicast configuration. */
5349 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5350
Paul Jakma37a217a2007-04-10 19:20:29 +00005351 /* IPv6 multicast configuration. */
5352 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5353
paul718e3742002-12-13 20:15:29 +00005354 write++;
5355 }
5356 return write;
5357}
5358
5359void
paul94f2b392005-06-28 12:44:16 +00005360bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005361{
5362 memset (&bgp_master, 0, sizeof (struct bgp_master));
5363
5364 bm = &bgp_master;
5365 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005366 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005367 bm->port = BGP_PORT_DEFAULT;
5368 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005369 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005370}
paul200df112005-06-01 11:17:05 +00005371
paul718e3742002-12-13 20:15:29 +00005372
5373void
paul94f2b392005-06-28 12:44:16 +00005374bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005375{
paul718e3742002-12-13 20:15:29 +00005376 /* BGP VTY commands installation. */
5377 bgp_vty_init ();
5378
paul718e3742002-12-13 20:15:29 +00005379 /* Init zebra. */
5380 bgp_zebra_init ();
5381
5382 /* BGP inits. */
5383 bgp_attr_init ();
5384 bgp_debug_init ();
5385 bgp_dump_init ();
5386 bgp_route_init ();
5387 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005388 bgp_address_init ();
paul718e3742002-12-13 20:15:29 +00005389 bgp_scan_init ();
5390 bgp_mplsvpn_init ();
5391
5392 /* Access list initialize. */
5393 access_list_init ();
5394 access_list_add_hook (peer_distribute_update);
5395 access_list_delete_hook (peer_distribute_update);
5396
5397 /* Filter list initialize. */
5398 bgp_filter_init ();
5399 as_list_add_hook (peer_aslist_update);
5400 as_list_delete_hook (peer_aslist_update);
5401
5402 /* Prefix list initialize.*/
5403 prefix_list_init ();
5404 prefix_list_add_hook (peer_prefix_list_update);
5405 prefix_list_delete_hook (peer_prefix_list_update);
5406
5407 /* Community list initialize. */
5408 bgp_clist = community_list_init ();
5409
5410#ifdef HAVE_SNMP
5411 bgp_snmp_init ();
5412#endif /* HAVE_SNMP */
5413}
paul545acaf2004-04-20 15:13:15 +00005414
5415void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005416bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005417{
paul545acaf2004-04-20 15:13:15 +00005418 struct bgp *bgp;
5419 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005420 struct listnode *node, *nnode;
5421 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005422
paul1eb8ef22005-04-07 07:30:20 +00005423 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5424 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005425 if (peer->status == Established)
5426 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5427 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005428
paul545acaf2004-04-20 15:13:15 +00005429 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005430
paule210cf92005-06-15 19:15:35 +00005431 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005432 {
5433 work_queue_free (bm->process_main_queue);
5434 bm->process_main_queue = NULL;
5435 }
paule210cf92005-06-15 19:15:35 +00005436 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005437 {
5438 work_queue_free (bm->process_rsclient_queue);
5439 bm->process_rsclient_queue = NULL;
5440 }
paul545acaf2004-04-20 15:13:15 +00005441}