blob: 908bdd94f88b392105b4dca887ca5579f3840e3d [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 */
1460 if (peer->password)
1461 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1462
1463 if (conf->password)
1464 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
1465 else
1466 peer->password = NULL;
1467
1468 bgp_md5_set (peer);
1469
paul718e3742002-12-13 20:15:29 +00001470 /* maximum-prefix */
1471 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001472 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001473 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001474
1475 /* allowas-in */
1476 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1477
paulfee0f4c2004-09-13 05:12:46 +00001478 /* route-server-client */
1479 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1480 {
1481 /* Make peer's RIB point to group's RIB. */
1482 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1483
1484 /* Import policy. */
1485 if (pfilter->map[RMAP_IMPORT].name)
1486 free (pfilter->map[RMAP_IMPORT].name);
1487 if (gfilter->map[RMAP_IMPORT].name)
1488 {
1489 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1490 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1491 }
1492 else
1493 {
1494 pfilter->map[RMAP_IMPORT].name = NULL;
1495 pfilter->map[RMAP_IMPORT].map = NULL;
1496 }
1497
1498 /* Export policy. */
1499 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1500 {
1501 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1502 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1503 }
1504 }
1505
paul718e3742002-12-13 20:15:29 +00001506 /* default-originate route-map */
1507 if (conf->default_rmap[afi][safi].name)
1508 {
1509 if (peer->default_rmap[afi][safi].name)
1510 free (peer->default_rmap[afi][safi].name);
1511 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1512 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1513 }
1514
1515 /* update-source apply */
1516 if (conf->update_source)
1517 {
1518 if (peer->update_source)
1519 sockunion_free (peer->update_source);
1520 if (peer->update_if)
1521 {
1522 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1523 peer->update_if = NULL;
1524 }
1525 peer->update_source = sockunion_dup (conf->update_source);
1526 }
1527 else if (conf->update_if)
1528 {
1529 if (peer->update_if)
1530 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1531 if (peer->update_source)
1532 {
1533 sockunion_free (peer->update_source);
1534 peer->update_source = NULL;
1535 }
1536 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1537 }
1538
1539 /* inbound filter apply */
1540 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1541 {
1542 if (pfilter->dlist[in].name)
1543 free (pfilter->dlist[in].name);
1544 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1545 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1546 }
1547 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1548 {
1549 if (pfilter->plist[in].name)
1550 free (pfilter->plist[in].name);
1551 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1552 pfilter->plist[in].plist = gfilter->plist[in].plist;
1553 }
1554 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1555 {
1556 if (pfilter->aslist[in].name)
1557 free (pfilter->aslist[in].name);
1558 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1559 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1560 }
paulfee0f4c2004-09-13 05:12:46 +00001561 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001562 {
paulfee0f4c2004-09-13 05:12:46 +00001563 if (pfilter->map[RMAP_IN].name)
1564 free (pfilter->map[RMAP_IN].name);
1565 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1566 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001567 }
1568
1569 /* outbound filter apply */
1570 if (gfilter->dlist[out].name)
1571 {
1572 if (pfilter->dlist[out].name)
1573 free (pfilter->dlist[out].name);
1574 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1575 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1576 }
1577 else
1578 {
1579 if (pfilter->dlist[out].name)
1580 free (pfilter->dlist[out].name);
1581 pfilter->dlist[out].name = NULL;
1582 pfilter->dlist[out].alist = NULL;
1583 }
1584 if (gfilter->plist[out].name)
1585 {
1586 if (pfilter->plist[out].name)
1587 free (pfilter->plist[out].name);
1588 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1589 pfilter->plist[out].plist = gfilter->plist[out].plist;
1590 }
1591 else
1592 {
1593 if (pfilter->plist[out].name)
1594 free (pfilter->plist[out].name);
1595 pfilter->plist[out].name = NULL;
1596 pfilter->plist[out].plist = NULL;
1597 }
1598 if (gfilter->aslist[out].name)
1599 {
1600 if (pfilter->aslist[out].name)
1601 free (pfilter->aslist[out].name);
1602 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1603 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1604 }
1605 else
1606 {
1607 if (pfilter->aslist[out].name)
1608 free (pfilter->aslist[out].name);
1609 pfilter->aslist[out].name = NULL;
1610 pfilter->aslist[out].aslist = NULL;
1611 }
paulfee0f4c2004-09-13 05:12:46 +00001612 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001613 {
paulfee0f4c2004-09-13 05:12:46 +00001614 if (pfilter->map[RMAP_OUT].name)
1615 free (pfilter->map[RMAP_OUT].name);
1616 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1617 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001618 }
1619 else
1620 {
paulfee0f4c2004-09-13 05:12:46 +00001621 if (pfilter->map[RMAP_OUT].name)
1622 free (pfilter->map[RMAP_OUT].name);
1623 pfilter->map[RMAP_OUT].name = NULL;
1624 pfilter->map[RMAP_OUT].map = NULL;
1625 }
1626
1627 /* RS-client's import/export route-maps. */
1628 if (gfilter->map[RMAP_IMPORT].name)
1629 {
1630 if (pfilter->map[RMAP_IMPORT].name)
1631 free (pfilter->map[RMAP_IMPORT].name);
1632 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1633 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1634 }
1635 else
1636 {
1637 if (pfilter->map[RMAP_IMPORT].name)
1638 free (pfilter->map[RMAP_IMPORT].name);
1639 pfilter->map[RMAP_IMPORT].name = NULL;
1640 pfilter->map[RMAP_IMPORT].map = NULL;
1641 }
1642 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1643 {
1644 if (pfilter->map[RMAP_EXPORT].name)
1645 free (pfilter->map[RMAP_EXPORT].name);
1646 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1647 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001648 }
1649
1650 if (gfilter->usmap.name)
1651 {
1652 if (pfilter->usmap.name)
1653 free (pfilter->usmap.name);
1654 pfilter->usmap.name = strdup (gfilter->usmap.name);
1655 pfilter->usmap.map = gfilter->usmap.map;
1656 }
1657 else
1658 {
1659 if (pfilter->usmap.name)
1660 free (pfilter->usmap.name);
1661 pfilter->usmap.name = NULL;
1662 pfilter->usmap.map = NULL;
1663 }
1664}
1665
1666/* Peer group's remote AS configuration. */
1667int
paulfd79ac92004-10-13 05:06:08 +00001668peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001669{
1670 struct peer_group *group;
1671 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001672 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001673
1674 group = peer_group_lookup (bgp, group_name);
1675 if (! group)
1676 return -1;
1677
1678 if (group->conf->as == *as)
1679 return 0;
1680
1681 /* When we setup peer-group AS number all peer group member's AS
1682 number must be updated to same number. */
1683 peer_as_change (group->conf, *as);
1684
paul1eb8ef22005-04-07 07:30:20 +00001685 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001686 {
1687 if (peer->as != *as)
1688 peer_as_change (peer, *as);
1689 }
1690
1691 return 0;
1692}
1693
1694int
1695peer_group_delete (struct peer_group *group)
1696{
1697 struct bgp *bgp;
1698 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001699 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001700
1701 bgp = group->bgp;
1702
paul1eb8ef22005-04-07 07:30:20 +00001703 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001704 {
1705 peer->group = NULL;
1706 peer_delete (peer);
1707 }
1708 list_delete (group->peer);
1709
1710 free (group->name);
1711 group->name = NULL;
1712
1713 group->conf->group = NULL;
1714 peer_delete (group->conf);
1715
1716 /* Delete from all peer_group list. */
1717 listnode_delete (bgp->group, group);
1718
1719 peer_group_free (group);
1720
1721 return 0;
1722}
1723
1724int
1725peer_group_remote_as_delete (struct peer_group *group)
1726{
1727 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001728 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001729
1730 if (! group->conf->as)
1731 return 0;
1732
paul1eb8ef22005-04-07 07:30:20 +00001733 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001734 {
1735 peer->group = NULL;
1736 peer_delete (peer);
1737 }
1738 list_delete_all_node (group->peer);
1739
1740 group->conf->as = 0;
1741
1742 return 0;
1743}
1744
1745/* Bind specified peer to peer group. */
1746int
1747peer_group_bind (struct bgp *bgp, union sockunion *su,
1748 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1749{
1750 struct peer *peer;
1751 int first_member = 0;
1752
1753 /* Check peer group's address family. */
1754 if (! group->conf->afc[afi][safi])
1755 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1756
1757 /* Lookup the peer. */
1758 peer = peer_lookup (bgp, su);
1759
1760 /* Create a new peer. */
1761 if (! peer)
1762 {
1763 if (! group->conf->as)
1764 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1765
1766 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1767 peer->group = group;
1768 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001769
Paul Jakmaca058a32006-09-14 02:58:49 +00001770 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001771 listnode_add (group->peer, peer);
1772 peer_group2peer_config_copy (group, peer, afi, safi);
1773
1774 return 0;
1775 }
1776
1777 /* When the peer already belongs to peer group, check the consistency. */
1778 if (peer->af_group[afi][safi])
1779 {
1780 if (strcmp (peer->group->name, group->name) != 0)
1781 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1782
1783 return 0;
1784 }
1785
1786 /* Check current peer group configuration. */
1787 if (peer_group_active (peer)
1788 && strcmp (peer->group->name, group->name) != 0)
1789 return BGP_ERR_PEER_GROUP_MISMATCH;
1790
1791 if (! group->conf->as)
1792 {
1793 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1794 && peer_sort (group->conf) != peer_sort (peer))
1795 {
1796 if (as)
1797 *as = peer->as;
1798 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1799 }
1800
1801 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1802 first_member = 1;
1803 }
1804
1805 peer->af_group[afi][safi] = 1;
1806 peer->afc[afi][safi] = 1;
1807 if (! peer->group)
1808 {
1809 peer->group = group;
paul200df112005-06-01 11:17:05 +00001810
Paul Jakmaca058a32006-09-14 02:58:49 +00001811 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001812 listnode_add (group->peer, peer);
1813 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001814 else
1815 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001816
1817 if (first_member)
1818 {
1819 /* Advertisement-interval reset */
1820 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1821 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1822 else
1823 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1824
1825 /* ebgp-multihop reset */
1826 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1827 group->conf->ttl = 255;
1828
1829 /* local-as reset */
1830 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1831 {
1832 group->conf->change_local_as = 0;
1833 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00001834 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00001835 }
1836 }
paulfee0f4c2004-09-13 05:12:46 +00001837
1838 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1839 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001840 struct listnode *pn;
1841
paulfee0f4c2004-09-13 05:12:46 +00001842 /* If it's not configured as RSERVER_CLIENT in any other address
1843 family, without being member of a peer_group, remove it from
1844 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001845 if (! peer_rsclient_active (peer)
1846 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001847 {
1848 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001849 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001850
1851 /* Clear our own rsclient rib for this afi/safi. */
1852 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001853 }
paulfee0f4c2004-09-13 05:12:46 +00001854
Paul Jakmab608d5b2008-07-02 02:12:07 +00001855 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001856
1857 /* Import policy. */
1858 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1859 {
1860 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1861 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1862 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1863 }
1864
1865 /* Export policy. */
1866 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1867 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1868 {
1869 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1870 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1871 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1872 }
1873 }
1874
paul718e3742002-12-13 20:15:29 +00001875 peer_group2peer_config_copy (group, peer, afi, safi);
1876
1877 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001878 {
1879 peer->last_reset = PEER_DOWN_RMAP_BIND;
1880 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1881 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1882 }
paul718e3742002-12-13 20:15:29 +00001883 else
1884 BGP_EVENT_ADD (peer, BGP_Stop);
1885
1886 return 0;
1887}
1888
1889int
1890peer_group_unbind (struct bgp *bgp, struct peer *peer,
1891 struct peer_group *group, afi_t afi, safi_t safi)
1892{
1893 if (! peer->af_group[afi][safi])
1894 return 0;
1895
1896 if (group != peer->group)
1897 return BGP_ERR_PEER_GROUP_MISMATCH;
1898
1899 peer->af_group[afi][safi] = 0;
1900 peer->afc[afi][safi] = 0;
1901 peer_af_flag_reset (peer, afi, safi);
1902
paulfee0f4c2004-09-13 05:12:46 +00001903 if (peer->rib[afi][safi])
1904 peer->rib[afi][safi] = NULL;
1905
paul718e3742002-12-13 20:15:29 +00001906 if (! peer_group_active (peer))
1907 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001908 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001909 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001910 listnode_delete (group->peer, peer);
1911 peer->group = NULL;
1912 if (group->conf->as)
1913 {
1914 peer_delete (peer);
1915 return 0;
1916 }
1917 peer_global_config_reset (peer);
1918 }
1919
1920 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001921 {
1922 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1923 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1924 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1925 }
paul718e3742002-12-13 20:15:29 +00001926 else
1927 BGP_EVENT_ADD (peer, BGP_Stop);
1928
1929 return 0;
1930}
1931
1932/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001933static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001934bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001935{
1936 struct bgp *bgp;
1937 afi_t afi;
1938 safi_t safi;
1939
paul200df112005-06-01 11:17:05 +00001940 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1941 return NULL;
1942
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07001943 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00001944 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00001945 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00001946
1947 bgp->peer = list_new ();
1948 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1949
1950 bgp->group = list_new ();
1951 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1952
paulfee0f4c2004-09-13 05:12:46 +00001953 bgp->rsclient = list_new ();
1954 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1955
paul718e3742002-12-13 20:15:29 +00001956 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1957 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1958 {
Paul Jakma64e580a2006-02-21 01:09:01 +00001959 bgp->route[afi][safi] = bgp_table_init (afi, safi);
1960 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1961 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07001962 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
1963 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00001964 }
1965
1966 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1967 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1968 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001969 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1970 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001971
1972 bgp->as = *as;
1973
1974 if (name)
1975 bgp->name = strdup (name);
1976
1977 return bgp;
1978}
1979
1980/* Return first entry of BGP. */
1981struct bgp *
paul94f2b392005-06-28 12:44:16 +00001982bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001983{
1984 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001985 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001986 return NULL;
1987}
1988
1989/* Lookup BGP entry. */
1990struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001991bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001992{
1993 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001994 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001995
paul1eb8ef22005-04-07 07:30:20 +00001996 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001997 if (bgp->as == as
1998 && ((bgp->name == NULL && name == NULL)
1999 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
2000 return bgp;
2001 return NULL;
2002}
2003
2004/* Lookup BGP structure by view name. */
2005struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002006bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002007{
2008 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002009 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002010
paul1eb8ef22005-04-07 07:30:20 +00002011 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002012 if ((bgp->name == NULL && name == NULL)
2013 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2014 return bgp;
2015 return NULL;
2016}
2017
2018/* Called from VTY commands. */
2019int
paulfd79ac92004-10-13 05:06:08 +00002020bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002021{
2022 struct bgp *bgp;
2023
2024 /* Multiple instance check. */
2025 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2026 {
2027 if (name)
2028 bgp = bgp_lookup_by_name (name);
2029 else
2030 bgp = bgp_get_default ();
2031
2032 /* Already exists. */
2033 if (bgp)
2034 {
2035 if (bgp->as != *as)
2036 {
2037 *as = bgp->as;
2038 return BGP_ERR_INSTANCE_MISMATCH;
2039 }
2040 *bgp_val = bgp;
2041 return 0;
2042 }
2043 }
2044 else
2045 {
2046 /* BGP instance name can not be specified for single instance. */
2047 if (name)
2048 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2049
2050 /* Get default BGP structure if exists. */
2051 bgp = bgp_get_default ();
2052
2053 if (bgp)
2054 {
2055 if (bgp->as != *as)
2056 {
2057 *as = bgp->as;
2058 return BGP_ERR_AS_MISMATCH;
2059 }
2060 *bgp_val = bgp;
2061 return 0;
2062 }
2063 }
2064
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002065 bgp = bgp_create (as, name);
2066 bgp_router_id_set(bgp, &router_id_zebra);
2067 *bgp_val = bgp;
2068
Paul Jakmaad12dde2012-06-13 22:50:07 +01002069 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002070 if (list_isempty(bm->bgp)
2071 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002072 {
2073 if (bgp_socket (bm->port, bm->address) < 0)
2074 return BGP_ERR_INVALID_VALUE;
2075 }
2076
paul718e3742002-12-13 20:15:29 +00002077 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002078
2079 return 0;
2080}
2081
2082/* Delete BGP instance. */
2083int
2084bgp_delete (struct bgp *bgp)
2085{
2086 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002087 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002088 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002089 struct listnode *next;
2090 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002091 int i;
2092
2093 /* Delete static route. */
2094 bgp_static_delete (bgp);
2095
2096 /* Unset redistribution. */
2097 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2098 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2099 if (i != ZEBRA_ROUTE_BGP)
2100 bgp_redistribute_unset (bgp, afi, i);
2101
paul1eb8ef22005-04-07 07:30:20 +00002102 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2103 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002104
Chris Caputo228da422009-07-18 05:44:03 +00002105 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
2106 peer_group_delete (group);
2107
2108 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002109
2110 if (bgp->peer_self) {
2111 peer_delete(bgp->peer_self);
2112 bgp->peer_self = NULL;
2113 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002114
2115 /* Remove visibility via the master list - there may however still be
2116 * routes to be processed still referencing the struct bgp.
2117 */
2118 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002119 if (list_isempty(bm->bgp))
2120 bgp_close ();
2121
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002122 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002123
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002124 return 0;
2125}
2126
2127static void bgp_free (struct bgp *);
2128
2129void
2130bgp_lock (struct bgp *bgp)
2131{
2132 ++bgp->lock;
2133}
2134
2135void
2136bgp_unlock(struct bgp *bgp)
2137{
Chris Caputo228da422009-07-18 05:44:03 +00002138 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002139 if (--bgp->lock == 0)
2140 bgp_free (bgp);
2141}
2142
2143static void
2144bgp_free (struct bgp *bgp)
2145{
2146 afi_t afi;
2147 safi_t safi;
2148
2149 list_delete (bgp->group);
2150 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002151 list_delete (bgp->rsclient);
2152
paul718e3742002-12-13 20:15:29 +00002153 if (bgp->name)
2154 free (bgp->name);
2155
2156 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2157 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2158 {
2159 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002160 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002161 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002162 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002163 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002164 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002165 }
2166 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002167}
2168
2169struct peer *
2170peer_lookup (struct bgp *bgp, union sockunion *su)
2171{
2172 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002173 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002174
Steve Hillfc4dc592009-07-28 17:54:35 +01002175 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002176 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002177 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2178 if (sockunion_same (&peer->su, su)
2179 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2180 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002181 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002182 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002183 {
2184 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002185
Paul Jakma2158ad22009-07-28 18:10:55 +01002186 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2187 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2188 if (sockunion_same (&peer->su, su)
2189 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2190 return peer;
paul718e3742002-12-13 20:15:29 +00002191 }
2192 return NULL;
2193}
2194
2195struct peer *
2196peer_lookup_with_open (union sockunion *su, as_t remote_as,
2197 struct in_addr *remote_id, int *as)
2198{
2199 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002200 struct listnode *node;
2201 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002202 struct bgp *bgp;
2203
Steve Hillfc4dc592009-07-28 17:54:35 +01002204 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002205 return NULL;
2206
Paul Jakma9d878772009-08-05 16:25:16 +01002207 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002208 {
Paul Jakma9d878772009-08-05 16:25:16 +01002209 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2210 {
2211 if (sockunion_same (&peer->su, su)
2212 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2213 {
2214 if (peer->as == remote_as
2215 && peer->remote_id.s_addr == remote_id->s_addr)
2216 return peer;
2217 if (peer->as == remote_as)
2218 *as = 1;
2219 }
2220 }
2221
2222 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2223 {
2224 if (sockunion_same (&peer->su, su)
2225 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2226 {
2227 if (peer->as == remote_as
2228 && peer->remote_id.s_addr == 0)
2229 return peer;
2230 if (peer->as == remote_as)
2231 *as = 1;
2232 }
2233 }
paul718e3742002-12-13 20:15:29 +00002234 }
2235 return NULL;
2236}
2237
2238/* If peer is configured at least one address family return 1. */
2239int
2240peer_active (struct peer *peer)
2241{
2242 if (peer->afc[AFI_IP][SAFI_UNICAST]
2243 || peer->afc[AFI_IP][SAFI_MULTICAST]
2244 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2245 || peer->afc[AFI_IP6][SAFI_UNICAST]
2246 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2247 return 1;
2248 return 0;
2249}
2250
2251/* If peer is negotiated at least one address family return 1. */
2252int
2253peer_active_nego (struct peer *peer)
2254{
2255 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2256 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2257 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2258 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2259 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2260 return 1;
2261 return 0;
2262}
2263
2264/* peer_flag_change_type. */
2265enum peer_change_type
2266{
2267 peer_change_none,
2268 peer_change_reset,
2269 peer_change_reset_in,
2270 peer_change_reset_out,
2271};
2272
paul94f2b392005-06-28 12:44:16 +00002273static void
paul718e3742002-12-13 20:15:29 +00002274peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2275 enum peer_change_type type)
2276{
2277 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2278 return;
2279
2280 if (type == peer_change_reset)
2281 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2282 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2283 else if (type == peer_change_reset_in)
2284 {
2285 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2286 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2287 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2288 else
2289 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2290 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2291 }
2292 else if (type == peer_change_reset_out)
2293 bgp_announce_route (peer, afi, safi);
2294}
2295
2296struct peer_flag_action
2297{
2298 /* Peer's flag. */
2299 u_int32_t flag;
2300
2301 /* This flag can be set for peer-group member. */
2302 u_char not_for_member;
2303
2304 /* Action when the flag is changed. */
2305 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002306
2307 /* Peer down cause */
2308 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002309};
2310
Stephen Hemminger03621952009-07-21 16:27:20 -07002311static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002312 {
2313 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2314 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2315 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2316 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2317 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002318 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002319 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002320 { 0, 0, 0 }
2321 };
2322
Stephen Hemminger03621952009-07-21 16:27:20 -07002323static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002324 {
2325 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2326 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2327 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2328 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2329 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2330 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2331 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2332 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2333 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2334 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2335 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2336 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2337 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002338 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002339 { 0, 0, 0 }
2340 };
2341
2342/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002343static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002344peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002345 struct peer_flag_action *action, u_int32_t flag)
2346{
2347 int i;
2348 int found = 0;
2349 int reset_in = 0;
2350 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002351 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002352
2353 /* Check peer's frag action. */
2354 for (i = 0; i < size; i++)
2355 {
2356 match = &action_list[i];
2357
2358 if (match->flag == 0)
2359 break;
2360
2361 if (match->flag & flag)
2362 {
2363 found = 1;
2364
2365 if (match->type == peer_change_reset_in)
2366 reset_in = 1;
2367 if (match->type == peer_change_reset_out)
2368 reset_out = 1;
2369 if (match->type == peer_change_reset)
2370 {
2371 reset_in = 1;
2372 reset_out = 1;
2373 }
2374 if (match->not_for_member)
2375 action->not_for_member = 1;
2376 }
2377 }
2378
2379 /* Set peer clear type. */
2380 if (reset_in && reset_out)
2381 action->type = peer_change_reset;
2382 else if (reset_in)
2383 action->type = peer_change_reset_in;
2384 else if (reset_out)
2385 action->type = peer_change_reset_out;
2386 else
2387 action->type = peer_change_none;
2388
2389 return found;
2390}
2391
paul94f2b392005-06-28 12:44:16 +00002392static void
paul718e3742002-12-13 20:15:29 +00002393peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2394{
2395 if (flag == PEER_FLAG_SHUTDOWN)
2396 {
2397 if (CHECK_FLAG (peer->flags, flag))
2398 {
hasso93406d82005-02-02 14:40:33 +00002399 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2400 peer_nsf_stop (peer);
2401
hasso0a486e52005-02-01 20:57:17 +00002402 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2403 if (peer->t_pmax_restart)
2404 {
2405 BGP_TIMER_OFF (peer->t_pmax_restart);
2406 if (BGP_DEBUG (events, EVENTS))
2407 zlog_debug ("%s Maximum-prefix restart timer canceled",
2408 peer->host);
2409 }
2410
hasso93406d82005-02-02 14:40:33 +00002411 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2412 peer_nsf_stop (peer);
2413
paul718e3742002-12-13 20:15:29 +00002414 if (peer->status == Established)
2415 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2416 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2417 else
2418 BGP_EVENT_ADD (peer, BGP_Stop);
2419 }
2420 else
2421 {
2422 peer->v_start = BGP_INIT_START_TIMER;
2423 BGP_EVENT_ADD (peer, BGP_Stop);
2424 }
2425 }
2426 else if (peer->status == Established)
2427 {
hassoc9502432005-02-01 22:01:48 +00002428 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2429 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2430 else if (flag == PEER_FLAG_PASSIVE)
2431 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002432 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002433 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002434
hassoc9502432005-02-01 22:01:48 +00002435 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2436 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002437 }
2438 else
2439 BGP_EVENT_ADD (peer, BGP_Stop);
2440}
2441
2442/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002443static int
paul718e3742002-12-13 20:15:29 +00002444peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2445{
2446 int found;
2447 int size;
2448 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002449 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002450 struct peer_flag_action action;
2451
2452 memset (&action, 0, sizeof (struct peer_flag_action));
2453 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2454
2455 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2456
2457 /* No flag action is found. */
2458 if (! found)
2459 return BGP_ERR_INVALID_FLAG;
2460
2461 /* Not for peer-group member. */
2462 if (action.not_for_member && peer_group_active (peer))
2463 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2464
2465 /* When unset the peer-group member's flag we have to check
2466 peer-group configuration. */
2467 if (! set && peer_group_active (peer))
2468 if (CHECK_FLAG (peer->group->conf->flags, flag))
2469 {
2470 if (flag == PEER_FLAG_SHUTDOWN)
2471 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2472 else
2473 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2474 }
2475
2476 /* Flag conflict check. */
2477 if (set
2478 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2479 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2480 return BGP_ERR_PEER_FLAG_CONFLICT;
2481
2482 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2483 {
2484 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2485 return 0;
2486 if (! set && ! CHECK_FLAG (peer->flags, flag))
2487 return 0;
2488 }
2489
2490 if (set)
2491 SET_FLAG (peer->flags, flag);
2492 else
2493 UNSET_FLAG (peer->flags, flag);
2494
2495 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2496 {
2497 if (action.type == peer_change_reset)
2498 peer_flag_modify_action (peer, flag);
2499
2500 return 0;
2501 }
2502
2503 /* peer-group member updates. */
2504 group = peer->group;
2505
paul1eb8ef22005-04-07 07:30:20 +00002506 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002507 {
2508 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2509 continue;
2510
2511 if (! set && ! CHECK_FLAG (peer->flags, flag))
2512 continue;
2513
2514 if (set)
2515 SET_FLAG (peer->flags, flag);
2516 else
2517 UNSET_FLAG (peer->flags, flag);
2518
2519 if (action.type == peer_change_reset)
2520 peer_flag_modify_action (peer, flag);
2521 }
2522 return 0;
2523}
2524
2525int
2526peer_flag_set (struct peer *peer, u_int32_t flag)
2527{
2528 return peer_flag_modify (peer, flag, 1);
2529}
2530
2531int
2532peer_flag_unset (struct peer *peer, u_int32_t flag)
2533{
2534 return peer_flag_modify (peer, flag, 0);
2535}
2536
paul94f2b392005-06-28 12:44:16 +00002537static int
paul718e3742002-12-13 20:15:29 +00002538peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2539{
2540 if (peer->af_group[afi][safi])
2541 return 1;
2542 return 0;
2543}
2544
paul94f2b392005-06-28 12:44:16 +00002545static int
paul718e3742002-12-13 20:15:29 +00002546peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2547 int set)
2548{
2549 int found;
2550 int size;
paul1eb8ef22005-04-07 07:30:20 +00002551 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002552 struct peer_group *group;
2553 struct peer_flag_action action;
2554
2555 memset (&action, 0, sizeof (struct peer_flag_action));
2556 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2557
2558 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2559
2560 /* No flag action is found. */
2561 if (! found)
2562 return BGP_ERR_INVALID_FLAG;
2563
2564 /* Adress family must be activated. */
2565 if (! peer->afc[afi][safi])
2566 return BGP_ERR_PEER_INACTIVE;
2567
2568 /* Not for peer-group member. */
2569 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2570 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2571
2572 /* Spcecial check for reflector client. */
2573 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2574 && peer_sort (peer) != BGP_PEER_IBGP)
2575 return BGP_ERR_NOT_INTERNAL_PEER;
2576
2577 /* Spcecial check for remove-private-AS. */
2578 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2579 && peer_sort (peer) == BGP_PEER_IBGP)
2580 return BGP_ERR_REMOVE_PRIVATE_AS;
2581
2582 /* When unset the peer-group member's flag we have to check
2583 peer-group configuration. */
2584 if (! set && peer->af_group[afi][safi])
2585 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2586 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2587
2588 /* When current flag configuration is same as requested one. */
2589 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2590 {
2591 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2592 return 0;
2593 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2594 return 0;
2595 }
2596
2597 if (set)
2598 SET_FLAG (peer->af_flags[afi][safi], flag);
2599 else
2600 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2601
2602 /* Execute action when peer is established. */
2603 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2604 && peer->status == Established)
2605 {
2606 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2607 bgp_clear_adj_in (peer, afi, safi);
2608 else
hassoe0701b72004-05-20 09:19:34 +00002609 {
2610 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2611 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2612 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2613 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2614 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2615 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2616 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2617 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2618
2619 peer_change_action (peer, afi, safi, action.type);
2620 }
2621
paul718e3742002-12-13 20:15:29 +00002622 }
2623
2624 /* Peer group member updates. */
2625 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2626 {
2627 group = peer->group;
2628
paul1eb8ef22005-04-07 07:30:20 +00002629 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002630 {
2631 if (! peer->af_group[afi][safi])
2632 continue;
2633
2634 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2635 continue;
2636
2637 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2638 continue;
2639
2640 if (set)
2641 SET_FLAG (peer->af_flags[afi][safi], flag);
2642 else
2643 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2644
2645 if (peer->status == Established)
2646 {
2647 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2648 bgp_clear_adj_in (peer, afi, safi);
2649 else
hassoe0701b72004-05-20 09:19:34 +00002650 {
2651 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2652 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2653 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2654 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2655 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2656 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2657 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2658 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2659
2660 peer_change_action (peer, afi, safi, action.type);
2661 }
paul718e3742002-12-13 20:15:29 +00002662 }
2663 }
2664 }
2665 return 0;
2666}
2667
2668int
2669peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2670{
2671 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2672}
2673
2674int
2675peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2676{
2677 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2678}
2679
2680/* EBGP multihop configuration. */
2681int
2682peer_ebgp_multihop_set (struct peer *peer, int ttl)
2683{
2684 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002685 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002686 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002687
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002688 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002689 return 0;
2690
Nick Hilliardfa411a22011-03-23 15:33:17 +00002691 /* see comment in peer_ttl_security_hops_set() */
2692 if (ttl != MAXTTL)
2693 {
2694 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2695 {
2696 group = peer->group;
2697 if (group->conf->gtsm_hops != 0)
2698 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2699
2700 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2701 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002702 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002703 continue;
2704
2705 if (peer1->gtsm_hops != 0)
2706 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2707 }
2708 }
2709 else
2710 {
2711 if (peer->gtsm_hops != 0)
2712 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2713 }
2714 }
2715
paul718e3742002-12-13 20:15:29 +00002716 peer->ttl = ttl;
2717
2718 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2719 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002720 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002721 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002722 }
2723 else
2724 {
2725 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002726 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002727 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002728 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002729 continue;
paul718e3742002-12-13 20:15:29 +00002730
pauleb821182004-05-01 08:44:08 +00002731 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002732
pauleb821182004-05-01 08:44:08 +00002733 if (peer->fd >= 0)
2734 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2735 }
paul718e3742002-12-13 20:15:29 +00002736 }
2737 return 0;
2738}
2739
2740int
2741peer_ebgp_multihop_unset (struct peer *peer)
2742{
2743 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002744 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002745
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002746 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002747 return 0;
2748
Nick Hilliardfa411a22011-03-23 15:33:17 +00002749 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2750 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2751
paul718e3742002-12-13 20:15:29 +00002752 if (peer_group_active (peer))
2753 peer->ttl = peer->group->conf->ttl;
2754 else
2755 peer->ttl = 1;
2756
2757 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2758 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002759 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002760 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002761 }
2762 else
2763 {
2764 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002765 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002766 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002767 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002768 continue;
paul718e3742002-12-13 20:15:29 +00002769
pauleb821182004-05-01 08:44:08 +00002770 peer->ttl = 1;
2771
2772 if (peer->fd >= 0)
2773 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2774 }
paul718e3742002-12-13 20:15:29 +00002775 }
2776 return 0;
2777}
2778
2779/* Neighbor description. */
2780int
2781peer_description_set (struct peer *peer, char *desc)
2782{
2783 if (peer->desc)
2784 XFREE (MTYPE_PEER_DESC, peer->desc);
2785
2786 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2787
2788 return 0;
2789}
2790
2791int
2792peer_description_unset (struct peer *peer)
2793{
2794 if (peer->desc)
2795 XFREE (MTYPE_PEER_DESC, peer->desc);
2796
2797 peer->desc = NULL;
2798
2799 return 0;
2800}
2801
2802/* Neighbor update-source. */
2803int
paulfd79ac92004-10-13 05:06:08 +00002804peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002805{
2806 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002807 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002808
2809 if (peer->update_if)
2810 {
2811 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2812 && strcmp (peer->update_if, ifname) == 0)
2813 return 0;
2814
2815 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2816 peer->update_if = NULL;
2817 }
2818
2819 if (peer->update_source)
2820 {
2821 sockunion_free (peer->update_source);
2822 peer->update_source = NULL;
2823 }
2824
2825 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2826
2827 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2828 {
2829 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002830 {
2831 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2832 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2833 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2834 }
paul718e3742002-12-13 20:15:29 +00002835 else
2836 BGP_EVENT_ADD (peer, BGP_Stop);
2837 return 0;
2838 }
2839
2840 /* peer-group member updates. */
2841 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002842 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002843 {
2844 if (peer->update_if)
2845 {
2846 if (strcmp (peer->update_if, ifname) == 0)
2847 continue;
2848
2849 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2850 peer->update_if = NULL;
2851 }
2852
2853 if (peer->update_source)
2854 {
2855 sockunion_free (peer->update_source);
2856 peer->update_source = NULL;
2857 }
2858
2859 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2860
2861 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002862 {
2863 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2864 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2865 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2866 }
paul718e3742002-12-13 20:15:29 +00002867 else
2868 BGP_EVENT_ADD (peer, BGP_Stop);
2869 }
2870 return 0;
2871}
2872
2873int
2874peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2875{
2876 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002877 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002878
2879 if (peer->update_source)
2880 {
2881 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2882 && sockunion_cmp (peer->update_source, su) == 0)
2883 return 0;
2884 sockunion_free (peer->update_source);
2885 peer->update_source = NULL;
2886 }
2887
2888 if (peer->update_if)
2889 {
2890 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2891 peer->update_if = NULL;
2892 }
2893
2894 peer->update_source = sockunion_dup (su);
2895
2896 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2897 {
2898 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002899 {
2900 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2901 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2902 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2903 }
paul718e3742002-12-13 20:15:29 +00002904 else
2905 BGP_EVENT_ADD (peer, BGP_Stop);
2906 return 0;
2907 }
2908
2909 /* peer-group member updates. */
2910 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002911 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002912 {
2913 if (peer->update_source)
2914 {
2915 if (sockunion_cmp (peer->update_source, su) == 0)
2916 continue;
2917 sockunion_free (peer->update_source);
2918 peer->update_source = NULL;
2919 }
2920
2921 if (peer->update_if)
2922 {
2923 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2924 peer->update_if = NULL;
2925 }
2926
2927 peer->update_source = sockunion_dup (su);
2928
2929 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002930 {
2931 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2932 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2933 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2934 }
paul718e3742002-12-13 20:15:29 +00002935 else
2936 BGP_EVENT_ADD (peer, BGP_Stop);
2937 }
2938 return 0;
2939}
2940
2941int
2942peer_update_source_unset (struct peer *peer)
2943{
2944 union sockunion *su;
2945 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002946 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002947
2948 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2949 && ! peer->update_source
2950 && ! peer->update_if)
2951 return 0;
2952
2953 if (peer->update_source)
2954 {
2955 sockunion_free (peer->update_source);
2956 peer->update_source = NULL;
2957 }
2958 if (peer->update_if)
2959 {
2960 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2961 peer->update_if = NULL;
2962 }
2963
2964 if (peer_group_active (peer))
2965 {
2966 group = peer->group;
2967
2968 if (group->conf->update_source)
2969 {
2970 su = sockunion_dup (group->conf->update_source);
2971 peer->update_source = su;
2972 }
2973 else if (group->conf->update_if)
2974 peer->update_if =
2975 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2976 }
2977
2978 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2979 {
2980 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002981 {
2982 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2983 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2984 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2985 }
paul718e3742002-12-13 20:15:29 +00002986 else
2987 BGP_EVENT_ADD (peer, BGP_Stop);
2988 return 0;
2989 }
2990
2991 /* peer-group member updates. */
2992 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002993 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002994 {
2995 if (! peer->update_source && ! peer->update_if)
2996 continue;
2997
2998 if (peer->update_source)
2999 {
3000 sockunion_free (peer->update_source);
3001 peer->update_source = NULL;
3002 }
3003
3004 if (peer->update_if)
3005 {
3006 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3007 peer->update_if = NULL;
3008 }
3009
3010 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003011 {
3012 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3013 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3014 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3015 }
paul718e3742002-12-13 20:15:29 +00003016 else
3017 BGP_EVENT_ADD (peer, BGP_Stop);
3018 }
3019 return 0;
3020}
3021
3022int
3023peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003024 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003025{
3026 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003027 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003028
3029 /* Adress family must be activated. */
3030 if (! peer->afc[afi][safi])
3031 return BGP_ERR_PEER_INACTIVE;
3032
3033 /* Default originate can't be used for peer group memeber. */
3034 if (peer_is_group_member (peer, afi, safi))
3035 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3036
3037 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3038 || (rmap && ! peer->default_rmap[afi][safi].name)
3039 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3040 {
3041 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3042
3043 if (rmap)
3044 {
3045 if (peer->default_rmap[afi][safi].name)
3046 free (peer->default_rmap[afi][safi].name);
3047 peer->default_rmap[afi][safi].name = strdup (rmap);
3048 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3049 }
3050 }
3051
3052 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3053 {
3054 if (peer->status == Established && peer->afc_nego[afi][safi])
3055 bgp_default_originate (peer, afi, safi, 0);
3056 return 0;
3057 }
3058
3059 /* peer-group member updates. */
3060 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003061 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003062 {
3063 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3064
3065 if (rmap)
3066 {
3067 if (peer->default_rmap[afi][safi].name)
3068 free (peer->default_rmap[afi][safi].name);
3069 peer->default_rmap[afi][safi].name = strdup (rmap);
3070 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3071 }
3072
3073 if (peer->status == Established && peer->afc_nego[afi][safi])
3074 bgp_default_originate (peer, afi, safi, 0);
3075 }
3076 return 0;
3077}
3078
3079int
3080peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3081{
3082 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003083 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003084
3085 /* Adress family must be activated. */
3086 if (! peer->afc[afi][safi])
3087 return BGP_ERR_PEER_INACTIVE;
3088
3089 /* Default originate can't be used for peer group memeber. */
3090 if (peer_is_group_member (peer, afi, safi))
3091 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3092
3093 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3094 {
3095 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3096
3097 if (peer->default_rmap[afi][safi].name)
3098 free (peer->default_rmap[afi][safi].name);
3099 peer->default_rmap[afi][safi].name = NULL;
3100 peer->default_rmap[afi][safi].map = NULL;
3101 }
3102
3103 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3104 {
3105 if (peer->status == Established && peer->afc_nego[afi][safi])
3106 bgp_default_originate (peer, afi, safi, 1);
3107 return 0;
3108 }
3109
3110 /* peer-group member updates. */
3111 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003112 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003113 {
3114 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3115
3116 if (peer->default_rmap[afi][safi].name)
3117 free (peer->default_rmap[afi][safi].name);
3118 peer->default_rmap[afi][safi].name = NULL;
3119 peer->default_rmap[afi][safi].map = NULL;
3120
3121 if (peer->status == Established && peer->afc_nego[afi][safi])
3122 bgp_default_originate (peer, afi, safi, 1);
3123 }
3124 return 0;
3125}
3126
3127int
3128peer_port_set (struct peer *peer, u_int16_t port)
3129{
3130 peer->port = port;
3131 return 0;
3132}
3133
3134int
3135peer_port_unset (struct peer *peer)
3136{
3137 peer->port = BGP_PORT_DEFAULT;
3138 return 0;
3139}
3140
3141/* neighbor weight. */
3142int
3143peer_weight_set (struct peer *peer, u_int16_t weight)
3144{
3145 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003146 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003147
3148 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3149 peer->weight = weight;
3150
3151 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3152 return 0;
3153
3154 /* peer-group member updates. */
3155 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003156 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003157 {
3158 peer->weight = group->conf->weight;
3159 }
3160 return 0;
3161}
3162
3163int
3164peer_weight_unset (struct peer *peer)
3165{
3166 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003167 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003168
3169 /* Set default weight. */
3170 if (peer_group_active (peer))
3171 peer->weight = peer->group->conf->weight;
3172 else
3173 peer->weight = 0;
3174
3175 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3176
3177 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3178 return 0;
3179
3180 /* peer-group member updates. */
3181 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003182 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003183 {
3184 peer->weight = 0;
3185 }
3186 return 0;
3187}
3188
3189int
3190peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3191{
3192 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003193 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003194
3195 /* Not for peer group memeber. */
3196 if (peer_group_active (peer))
3197 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3198
3199 /* keepalive value check. */
3200 if (keepalive > 65535)
3201 return BGP_ERR_INVALID_VALUE;
3202
3203 /* Holdtime value check. */
3204 if (holdtime > 65535)
3205 return BGP_ERR_INVALID_VALUE;
3206
3207 /* Holdtime value must be either 0 or greater than 3. */
3208 if (holdtime < 3 && holdtime != 0)
3209 return BGP_ERR_INVALID_VALUE;
3210
3211 /* Set value to the configuration. */
3212 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3213 peer->holdtime = holdtime;
3214 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3215
3216 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3217 return 0;
3218
3219 /* peer-group member updates. */
3220 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003221 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003222 {
3223 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3224 peer->holdtime = group->conf->holdtime;
3225 peer->keepalive = group->conf->keepalive;
3226 }
3227 return 0;
3228}
3229
3230int
3231peer_timers_unset (struct peer *peer)
3232{
3233 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003234 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003235
3236 if (peer_group_active (peer))
3237 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3238
3239 /* Clear configuration. */
3240 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3241 peer->keepalive = 0;
3242 peer->holdtime = 0;
3243
3244 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3245 return 0;
3246
3247 /* peer-group member updates. */
3248 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003249 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003250 {
3251 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3252 peer->holdtime = 0;
3253 peer->keepalive = 0;
3254 }
3255
3256 return 0;
3257}
3258
3259int
3260peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3261{
3262 if (peer_group_active (peer))
3263 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3264
3265 if (connect > 65535)
3266 return BGP_ERR_INVALID_VALUE;
3267
3268 /* Set value to the configuration. */
3269 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3270 peer->connect = connect;
3271
3272 /* Set value to timer setting. */
3273 peer->v_connect = connect;
3274
3275 return 0;
3276}
3277
3278int
3279peer_timers_connect_unset (struct peer *peer)
3280{
3281 if (peer_group_active (peer))
3282 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3283
3284 /* Clear configuration. */
3285 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3286 peer->connect = 0;
3287
3288 /* Set timer setting to default value. */
3289 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3290
3291 return 0;
3292}
3293
3294int
3295peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3296{
3297 if (peer_group_active (peer))
3298 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3299
3300 if (routeadv > 600)
3301 return BGP_ERR_INVALID_VALUE;
3302
3303 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3304 peer->routeadv = routeadv;
3305 peer->v_routeadv = routeadv;
3306
3307 return 0;
3308}
3309
3310int
3311peer_advertise_interval_unset (struct peer *peer)
3312{
3313 if (peer_group_active (peer))
3314 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3315
3316 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3317 peer->routeadv = 0;
3318
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003319 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003320 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3321 else
3322 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3323
3324 return 0;
3325}
3326
paul718e3742002-12-13 20:15:29 +00003327/* neighbor interface */
3328int
paulfd79ac92004-10-13 05:06:08 +00003329peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003330{
3331 if (peer->ifname)
3332 free (peer->ifname);
3333 peer->ifname = strdup (str);
3334
3335 return 0;
3336}
3337
3338int
3339peer_interface_unset (struct peer *peer)
3340{
3341 if (peer->ifname)
3342 free (peer->ifname);
3343 peer->ifname = NULL;
3344
3345 return 0;
3346}
3347
3348/* Allow-as in. */
3349int
3350peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3351{
3352 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003353 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003354
3355 if (allow_num < 1 || allow_num > 10)
3356 return BGP_ERR_INVALID_VALUE;
3357
3358 if (peer->allowas_in[afi][safi] != allow_num)
3359 {
3360 peer->allowas_in[afi][safi] = allow_num;
3361 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3362 peer_change_action (peer, afi, safi, peer_change_reset_in);
3363 }
3364
3365 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3366 return 0;
3367
3368 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003369 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003370 {
3371 if (peer->allowas_in[afi][safi] != allow_num)
3372 {
3373 peer->allowas_in[afi][safi] = allow_num;
3374 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3375 peer_change_action (peer, afi, safi, peer_change_reset_in);
3376 }
3377
3378 }
3379 return 0;
3380}
3381
3382int
3383peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3384{
3385 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003386 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003387
3388 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3389 {
3390 peer->allowas_in[afi][safi] = 0;
3391 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3392 }
3393
3394 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3395 return 0;
3396
3397 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003398 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003399 {
3400 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3401 {
3402 peer->allowas_in[afi][safi] = 0;
3403 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3404 }
3405 }
3406 return 0;
3407}
3408
3409int
Andrew Certain9d3f9702012-11-07 23:50:07 +00003410peer_local_as_set (struct peer *peer, as_t as, int no_prepend, int replace_as)
paul718e3742002-12-13 20:15:29 +00003411{
3412 struct bgp *bgp = peer->bgp;
3413 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003414 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003415
3416 if (peer_sort (peer) != BGP_PEER_EBGP
3417 && peer_sort (peer) != BGP_PEER_INTERNAL)
3418 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3419
3420 if (bgp->as == as)
3421 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3422
3423 if (peer_group_active (peer))
3424 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3425
Andrew Certain9d3f9702012-11-07 23:50:07 +00003426 if (peer->as == as)
3427 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
3428
paul718e3742002-12-13 20:15:29 +00003429 if (peer->change_local_as == as &&
3430 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
Andrew Certain9d3f9702012-11-07 23:50:07 +00003431 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)) &&
3432 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && replace_as)
3433 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) && ! replace_as)))
paul718e3742002-12-13 20:15:29 +00003434 return 0;
3435
3436 peer->change_local_as = as;
3437 if (no_prepend)
3438 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3439 else
3440 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3441
Andrew Certain9d3f9702012-11-07 23:50:07 +00003442 if (replace_as)
3443 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3444 else
3445 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3446
paul718e3742002-12-13 20:15:29 +00003447 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3448 {
3449 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003450 {
3451 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3452 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3453 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3454 }
paul718e3742002-12-13 20:15:29 +00003455 else
3456 BGP_EVENT_ADD (peer, BGP_Stop);
3457
3458 return 0;
3459 }
3460
3461 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003462 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003463 {
3464 peer->change_local_as = as;
3465 if (no_prepend)
3466 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3467 else
3468 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3469
Andrew Certain9d3f9702012-11-07 23:50:07 +00003470 if (replace_as)
3471 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3472 else
3473 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
3474
paul718e3742002-12-13 20:15:29 +00003475 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003476 {
3477 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3478 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3479 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3480 }
paul718e3742002-12-13 20:15:29 +00003481 else
3482 BGP_EVENT_ADD (peer, BGP_Stop);
3483 }
3484
3485 return 0;
3486}
3487
3488int
3489peer_local_as_unset (struct peer *peer)
3490{
3491 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003492 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003493
3494 if (peer_group_active (peer))
3495 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3496
3497 if (! peer->change_local_as)
3498 return 0;
3499
3500 peer->change_local_as = 0;
3501 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003502 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003503
3504 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3505 {
3506 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003507 {
3508 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3509 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3510 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3511 }
paul718e3742002-12-13 20:15:29 +00003512 else
3513 BGP_EVENT_ADD (peer, BGP_Stop);
3514
3515 return 0;
3516 }
3517
3518 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003519 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003520 {
3521 peer->change_local_as = 0;
3522 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
Andrew Certain9d3f9702012-11-07 23:50:07 +00003523 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS);
paul718e3742002-12-13 20:15:29 +00003524
3525 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003526 {
3527 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3528 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3529 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3530 }
paul718e3742002-12-13 20:15:29 +00003531 else
3532 BGP_EVENT_ADD (peer, BGP_Stop);
3533 }
3534 return 0;
3535}
3536
Paul Jakma0df7c912008-07-21 21:02:49 +00003537/* Set password for authenticating with the peer. */
3538int
3539peer_password_set (struct peer *peer, const char *password)
3540{
3541 struct listnode *nn, *nnode;
3542 int len = password ? strlen(password) : 0;
3543 int ret = BGP_SUCCESS;
3544
3545 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3546 return BGP_ERR_INVALID_VALUE;
3547
3548 if (peer->password && strcmp (peer->password, password) == 0
3549 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3550 return 0;
3551
3552 if (peer->password)
3553 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3554
3555 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3556
3557 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3558 {
3559 if (peer->status == Established)
3560 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3561 else
3562 BGP_EVENT_ADD (peer, BGP_Stop);
3563
3564 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3565 }
3566
3567 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3568 {
3569 if (peer->password && strcmp (peer->password, password) == 0)
3570 continue;
3571
3572 if (peer->password)
3573 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3574
3575 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3576
3577 if (peer->status == Established)
3578 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3579 else
3580 BGP_EVENT_ADD (peer, BGP_Stop);
3581
3582 if (bgp_md5_set (peer) < 0)
3583 ret = BGP_ERR_TCPSIG_FAILED;
3584 }
3585
3586 return ret;
3587}
3588
3589int
3590peer_password_unset (struct peer *peer)
3591{
3592 struct listnode *nn, *nnode;
3593
3594 if (!peer->password
3595 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3596 return 0;
3597
3598 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3599 {
3600 if (peer_group_active (peer)
3601 && peer->group->conf->password
3602 && strcmp (peer->group->conf->password, peer->password) == 0)
3603 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3604
3605 if (peer->status == Established)
3606 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3607 else
3608 BGP_EVENT_ADD (peer, BGP_Stop);
3609
3610 if (peer->password)
3611 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3612
3613 peer->password = NULL;
3614
3615 bgp_md5_set (peer);
3616
3617 return 0;
3618 }
3619
3620 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3621 peer->password = NULL;
3622
3623 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3624 {
3625 if (!peer->password)
3626 continue;
3627
3628 if (peer->status == Established)
3629 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3630 else
3631 BGP_EVENT_ADD (peer, BGP_Stop);
3632
3633 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3634 peer->password = NULL;
3635
3636 bgp_md5_set (peer);
3637 }
3638
3639 return 0;
3640}
3641
paul718e3742002-12-13 20:15:29 +00003642/* Set distribute list to the peer. */
3643int
3644peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003645 const char *name)
paul718e3742002-12-13 20:15:29 +00003646{
3647 struct bgp_filter *filter;
3648 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003649 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003650
3651 if (! peer->afc[afi][safi])
3652 return BGP_ERR_PEER_INACTIVE;
3653
3654 if (direct != FILTER_IN && direct != FILTER_OUT)
3655 return BGP_ERR_INVALID_VALUE;
3656
3657 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3658 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3659
3660 filter = &peer->filter[afi][safi];
3661
3662 if (filter->plist[direct].name)
3663 return BGP_ERR_PEER_FILTER_CONFLICT;
3664
3665 if (filter->dlist[direct].name)
3666 free (filter->dlist[direct].name);
3667 filter->dlist[direct].name = strdup (name);
3668 filter->dlist[direct].alist = access_list_lookup (afi, name);
3669
3670 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3671 return 0;
3672
3673 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003674 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003675 {
3676 filter = &peer->filter[afi][safi];
3677
3678 if (! peer->af_group[afi][safi])
3679 continue;
3680
3681 if (filter->dlist[direct].name)
3682 free (filter->dlist[direct].name);
3683 filter->dlist[direct].name = strdup (name);
3684 filter->dlist[direct].alist = access_list_lookup (afi, name);
3685 }
3686
3687 return 0;
3688}
3689
3690int
3691peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3692{
3693 struct bgp_filter *filter;
3694 struct bgp_filter *gfilter;
3695 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003696 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003697
3698 if (! peer->afc[afi][safi])
3699 return BGP_ERR_PEER_INACTIVE;
3700
3701 if (direct != FILTER_IN && direct != FILTER_OUT)
3702 return BGP_ERR_INVALID_VALUE;
3703
3704 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3705 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3706
3707 filter = &peer->filter[afi][safi];
3708
3709 /* apply peer-group filter */
3710 if (peer->af_group[afi][safi])
3711 {
3712 gfilter = &peer->group->conf->filter[afi][safi];
3713
3714 if (gfilter->dlist[direct].name)
3715 {
3716 if (filter->dlist[direct].name)
3717 free (filter->dlist[direct].name);
3718 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3719 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3720 return 0;
3721 }
3722 }
3723
3724 if (filter->dlist[direct].name)
3725 free (filter->dlist[direct].name);
3726 filter->dlist[direct].name = NULL;
3727 filter->dlist[direct].alist = NULL;
3728
3729 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3730 return 0;
3731
3732 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003733 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003734 {
3735 filter = &peer->filter[afi][safi];
3736
3737 if (! peer->af_group[afi][safi])
3738 continue;
3739
3740 if (filter->dlist[direct].name)
3741 free (filter->dlist[direct].name);
3742 filter->dlist[direct].name = NULL;
3743 filter->dlist[direct].alist = NULL;
3744 }
3745
3746 return 0;
3747}
3748
3749/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003750static void
paul718e3742002-12-13 20:15:29 +00003751peer_distribute_update (struct access_list *access)
3752{
3753 afi_t afi;
3754 safi_t safi;
3755 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003756 struct listnode *mnode, *mnnode;
3757 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003758 struct bgp *bgp;
3759 struct peer *peer;
3760 struct peer_group *group;
3761 struct bgp_filter *filter;
3762
paul1eb8ef22005-04-07 07:30:20 +00003763 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003764 {
paul1eb8ef22005-04-07 07:30:20 +00003765 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003766 {
3767 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3768 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3769 {
3770 filter = &peer->filter[afi][safi];
3771
3772 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3773 {
3774 if (filter->dlist[direct].name)
3775 filter->dlist[direct].alist =
3776 access_list_lookup (afi, filter->dlist[direct].name);
3777 else
3778 filter->dlist[direct].alist = NULL;
3779 }
3780 }
3781 }
paul1eb8ef22005-04-07 07:30:20 +00003782 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003783 {
3784 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3785 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3786 {
3787 filter = &group->conf->filter[afi][safi];
3788
3789 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3790 {
3791 if (filter->dlist[direct].name)
3792 filter->dlist[direct].alist =
3793 access_list_lookup (afi, filter->dlist[direct].name);
3794 else
3795 filter->dlist[direct].alist = NULL;
3796 }
3797 }
3798 }
3799 }
3800}
3801
3802/* Set prefix list to the peer. */
3803int
3804peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003805 const char *name)
paul718e3742002-12-13 20:15:29 +00003806{
3807 struct bgp_filter *filter;
3808 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003809 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003810
3811 if (! peer->afc[afi][safi])
3812 return BGP_ERR_PEER_INACTIVE;
3813
3814 if (direct != FILTER_IN && direct != FILTER_OUT)
3815 return BGP_ERR_INVALID_VALUE;
3816
3817 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3818 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3819
3820 filter = &peer->filter[afi][safi];
3821
3822 if (filter->dlist[direct].name)
3823 return BGP_ERR_PEER_FILTER_CONFLICT;
3824
3825 if (filter->plist[direct].name)
3826 free (filter->plist[direct].name);
3827 filter->plist[direct].name = strdup (name);
3828 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3829
3830 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3831 return 0;
3832
3833 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003834 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003835 {
3836 filter = &peer->filter[afi][safi];
3837
3838 if (! peer->af_group[afi][safi])
3839 continue;
3840
3841 if (filter->plist[direct].name)
3842 free (filter->plist[direct].name);
3843 filter->plist[direct].name = strdup (name);
3844 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3845 }
3846 return 0;
3847}
3848
3849int
3850peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3851{
3852 struct bgp_filter *filter;
3853 struct bgp_filter *gfilter;
3854 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003855 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003856
3857 if (! peer->afc[afi][safi])
3858 return BGP_ERR_PEER_INACTIVE;
3859
3860 if (direct != FILTER_IN && direct != FILTER_OUT)
3861 return BGP_ERR_INVALID_VALUE;
3862
3863 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3864 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3865
3866 filter = &peer->filter[afi][safi];
3867
3868 /* apply peer-group filter */
3869 if (peer->af_group[afi][safi])
3870 {
3871 gfilter = &peer->group->conf->filter[afi][safi];
3872
3873 if (gfilter->plist[direct].name)
3874 {
3875 if (filter->plist[direct].name)
3876 free (filter->plist[direct].name);
3877 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3878 filter->plist[direct].plist = gfilter->plist[direct].plist;
3879 return 0;
3880 }
3881 }
3882
3883 if (filter->plist[direct].name)
3884 free (filter->plist[direct].name);
3885 filter->plist[direct].name = NULL;
3886 filter->plist[direct].plist = NULL;
3887
3888 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3889 return 0;
3890
3891 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003892 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003893 {
3894 filter = &peer->filter[afi][safi];
3895
3896 if (! peer->af_group[afi][safi])
3897 continue;
3898
3899 if (filter->plist[direct].name)
3900 free (filter->plist[direct].name);
3901 filter->plist[direct].name = NULL;
3902 filter->plist[direct].plist = NULL;
3903 }
3904
3905 return 0;
3906}
3907
3908/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003909static void
paul718e3742002-12-13 20:15:29 +00003910peer_prefix_list_update (struct prefix_list *plist)
3911{
paul1eb8ef22005-04-07 07:30:20 +00003912 struct listnode *mnode, *mnnode;
3913 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003914 struct bgp *bgp;
3915 struct peer *peer;
3916 struct peer_group *group;
3917 struct bgp_filter *filter;
3918 afi_t afi;
3919 safi_t safi;
3920 int direct;
3921
paul1eb8ef22005-04-07 07:30:20 +00003922 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003923 {
paul1eb8ef22005-04-07 07:30:20 +00003924 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003925 {
3926 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3927 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3928 {
3929 filter = &peer->filter[afi][safi];
3930
3931 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3932 {
3933 if (filter->plist[direct].name)
3934 filter->plist[direct].plist =
3935 prefix_list_lookup (afi, filter->plist[direct].name);
3936 else
3937 filter->plist[direct].plist = NULL;
3938 }
3939 }
3940 }
paul1eb8ef22005-04-07 07:30:20 +00003941 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003942 {
3943 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3944 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3945 {
3946 filter = &group->conf->filter[afi][safi];
3947
3948 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3949 {
3950 if (filter->plist[direct].name)
3951 filter->plist[direct].plist =
3952 prefix_list_lookup (afi, filter->plist[direct].name);
3953 else
3954 filter->plist[direct].plist = NULL;
3955 }
3956 }
3957 }
3958 }
3959}
3960
3961int
3962peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003963 const char *name)
paul718e3742002-12-13 20:15:29 +00003964{
3965 struct bgp_filter *filter;
3966 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003967 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003968
3969 if (! peer->afc[afi][safi])
3970 return BGP_ERR_PEER_INACTIVE;
3971
3972 if (direct != FILTER_IN && direct != FILTER_OUT)
3973 return BGP_ERR_INVALID_VALUE;
3974
3975 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3976 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3977
3978 filter = &peer->filter[afi][safi];
3979
3980 if (filter->aslist[direct].name)
3981 free (filter->aslist[direct].name);
3982 filter->aslist[direct].name = strdup (name);
3983 filter->aslist[direct].aslist = as_list_lookup (name);
3984
3985 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3986 return 0;
3987
3988 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003989 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003990 {
3991 filter = &peer->filter[afi][safi];
3992
3993 if (! peer->af_group[afi][safi])
3994 continue;
3995
3996 if (filter->aslist[direct].name)
3997 free (filter->aslist[direct].name);
3998 filter->aslist[direct].name = strdup (name);
3999 filter->aslist[direct].aslist = as_list_lookup (name);
4000 }
4001 return 0;
4002}
4003
4004int
4005peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
4006{
4007 struct bgp_filter *filter;
4008 struct bgp_filter *gfilter;
4009 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004010 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004011
4012 if (! peer->afc[afi][safi])
4013 return BGP_ERR_PEER_INACTIVE;
4014
hassob5f29602005-05-25 21:00:28 +00004015 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00004016 return BGP_ERR_INVALID_VALUE;
4017
hassob5f29602005-05-25 21:00:28 +00004018 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004019 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4020
4021 filter = &peer->filter[afi][safi];
4022
4023 /* apply peer-group filter */
4024 if (peer->af_group[afi][safi])
4025 {
4026 gfilter = &peer->group->conf->filter[afi][safi];
4027
4028 if (gfilter->aslist[direct].name)
4029 {
4030 if (filter->aslist[direct].name)
4031 free (filter->aslist[direct].name);
4032 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4033 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4034 return 0;
4035 }
4036 }
4037
4038 if (filter->aslist[direct].name)
4039 free (filter->aslist[direct].name);
4040 filter->aslist[direct].name = NULL;
4041 filter->aslist[direct].aslist = NULL;
4042
4043 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4044 return 0;
4045
4046 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004047 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004048 {
4049 filter = &peer->filter[afi][safi];
4050
4051 if (! peer->af_group[afi][safi])
4052 continue;
4053
4054 if (filter->aslist[direct].name)
4055 free (filter->aslist[direct].name);
4056 filter->aslist[direct].name = NULL;
4057 filter->aslist[direct].aslist = NULL;
4058 }
4059
4060 return 0;
4061}
4062
paul94f2b392005-06-28 12:44:16 +00004063static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004064peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004065{
4066 afi_t afi;
4067 safi_t safi;
4068 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004069 struct listnode *mnode, *mnnode;
4070 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004071 struct bgp *bgp;
4072 struct peer *peer;
4073 struct peer_group *group;
4074 struct bgp_filter *filter;
4075
paul1eb8ef22005-04-07 07:30:20 +00004076 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004077 {
paul1eb8ef22005-04-07 07:30:20 +00004078 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004079 {
4080 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4081 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4082 {
4083 filter = &peer->filter[afi][safi];
4084
4085 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4086 {
4087 if (filter->aslist[direct].name)
4088 filter->aslist[direct].aslist =
4089 as_list_lookup (filter->aslist[direct].name);
4090 else
4091 filter->aslist[direct].aslist = NULL;
4092 }
4093 }
4094 }
paul1eb8ef22005-04-07 07:30:20 +00004095 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004096 {
4097 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4098 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4099 {
4100 filter = &group->conf->filter[afi][safi];
4101
4102 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4103 {
4104 if (filter->aslist[direct].name)
4105 filter->aslist[direct].aslist =
4106 as_list_lookup (filter->aslist[direct].name);
4107 else
4108 filter->aslist[direct].aslist = NULL;
4109 }
4110 }
4111 }
4112 }
4113}
4114
4115/* Set route-map to the peer. */
4116int
4117peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004118 const char *name)
paul718e3742002-12-13 20:15:29 +00004119{
4120 struct bgp_filter *filter;
4121 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004122 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004123
4124 if (! peer->afc[afi][safi])
4125 return BGP_ERR_PEER_INACTIVE;
4126
paulfee0f4c2004-09-13 05:12:46 +00004127 if (direct != RMAP_IN && direct != RMAP_OUT &&
4128 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004129 return BGP_ERR_INVALID_VALUE;
4130
paulfee0f4c2004-09-13 05:12:46 +00004131 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4132 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004133 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4134
4135 filter = &peer->filter[afi][safi];
4136
4137 if (filter->map[direct].name)
4138 free (filter->map[direct].name);
4139
4140 filter->map[direct].name = strdup (name);
4141 filter->map[direct].map = route_map_lookup_by_name (name);
4142
4143 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4144 return 0;
4145
4146 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004147 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004148 {
4149 filter = &peer->filter[afi][safi];
4150
4151 if (! peer->af_group[afi][safi])
4152 continue;
4153
4154 if (filter->map[direct].name)
4155 free (filter->map[direct].name);
4156 filter->map[direct].name = strdup (name);
4157 filter->map[direct].map = route_map_lookup_by_name (name);
4158 }
4159 return 0;
4160}
4161
4162/* Unset route-map from the peer. */
4163int
4164peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4165{
4166 struct bgp_filter *filter;
4167 struct bgp_filter *gfilter;
4168 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004169 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004170
4171 if (! peer->afc[afi][safi])
4172 return BGP_ERR_PEER_INACTIVE;
4173
hassob5f29602005-05-25 21:00:28 +00004174 if (direct != RMAP_IN && direct != RMAP_OUT &&
4175 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004176 return BGP_ERR_INVALID_VALUE;
4177
hassob5f29602005-05-25 21:00:28 +00004178 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4179 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004180 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4181
4182 filter = &peer->filter[afi][safi];
4183
4184 /* apply peer-group filter */
4185 if (peer->af_group[afi][safi])
4186 {
4187 gfilter = &peer->group->conf->filter[afi][safi];
4188
4189 if (gfilter->map[direct].name)
4190 {
4191 if (filter->map[direct].name)
4192 free (filter->map[direct].name);
4193 filter->map[direct].name = strdup (gfilter->map[direct].name);
4194 filter->map[direct].map = gfilter->map[direct].map;
4195 return 0;
4196 }
4197 }
4198
4199 if (filter->map[direct].name)
4200 free (filter->map[direct].name);
4201 filter->map[direct].name = NULL;
4202 filter->map[direct].map = NULL;
4203
4204 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4205 return 0;
4206
4207 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004208 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004209 {
4210 filter = &peer->filter[afi][safi];
4211
4212 if (! peer->af_group[afi][safi])
4213 continue;
4214
4215 if (filter->map[direct].name)
4216 free (filter->map[direct].name);
4217 filter->map[direct].name = NULL;
4218 filter->map[direct].map = NULL;
4219 }
4220 return 0;
4221}
4222
4223/* Set unsuppress-map to the peer. */
4224int
paulfd79ac92004-10-13 05:06:08 +00004225peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4226 const char *name)
paul718e3742002-12-13 20:15:29 +00004227{
4228 struct bgp_filter *filter;
4229 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004230 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004231
4232 if (! peer->afc[afi][safi])
4233 return BGP_ERR_PEER_INACTIVE;
4234
4235 if (peer_is_group_member (peer, afi, safi))
4236 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4237
4238 filter = &peer->filter[afi][safi];
4239
4240 if (filter->usmap.name)
4241 free (filter->usmap.name);
4242
4243 filter->usmap.name = strdup (name);
4244 filter->usmap.map = route_map_lookup_by_name (name);
4245
4246 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4247 return 0;
4248
4249 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004250 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004251 {
4252 filter = &peer->filter[afi][safi];
4253
4254 if (! peer->af_group[afi][safi])
4255 continue;
4256
4257 if (filter->usmap.name)
4258 free (filter->usmap.name);
4259 filter->usmap.name = strdup (name);
4260 filter->usmap.map = route_map_lookup_by_name (name);
4261 }
4262 return 0;
4263}
4264
4265/* Unset route-map from the peer. */
4266int
4267peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4268{
4269 struct bgp_filter *filter;
4270 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004271 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004272
4273 if (! peer->afc[afi][safi])
4274 return BGP_ERR_PEER_INACTIVE;
4275
4276 if (peer_is_group_member (peer, afi, safi))
4277 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4278
4279 filter = &peer->filter[afi][safi];
4280
4281 if (filter->usmap.name)
4282 free (filter->usmap.name);
4283 filter->usmap.name = NULL;
4284 filter->usmap.map = NULL;
4285
4286 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4287 return 0;
4288
4289 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004290 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004291 {
4292 filter = &peer->filter[afi][safi];
4293
4294 if (! peer->af_group[afi][safi])
4295 continue;
4296
4297 if (filter->usmap.name)
4298 free (filter->usmap.name);
4299 filter->usmap.name = NULL;
4300 filter->usmap.map = NULL;
4301 }
4302 return 0;
4303}
4304
4305int
4306peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004307 u_int32_t max, u_char threshold,
4308 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004309{
4310 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004311 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004312
4313 if (! peer->afc[afi][safi])
4314 return BGP_ERR_PEER_INACTIVE;
4315
4316 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4317 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004318 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004319 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004320 if (warning)
4321 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4322 else
4323 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4324
4325 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4326 return 0;
4327
4328 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004329 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004330 {
4331 if (! peer->af_group[afi][safi])
4332 continue;
4333
4334 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4335 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004336 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004337 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004338 if (warning)
4339 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4340 else
4341 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4342 }
4343 return 0;
4344}
4345
4346int
4347peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4348{
4349 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004350 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004351
4352 if (! peer->afc[afi][safi])
4353 return BGP_ERR_PEER_INACTIVE;
4354
4355 /* apply peer-group config */
4356 if (peer->af_group[afi][safi])
4357 {
4358 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4359 PEER_FLAG_MAX_PREFIX))
4360 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4361 else
4362 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4363
4364 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4365 PEER_FLAG_MAX_PREFIX_WARNING))
4366 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4367 else
4368 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4369
4370 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004371 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004372 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004373 return 0;
4374 }
4375
4376 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4377 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4378 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004379 peer->pmax_threshold[afi][safi] = 0;
4380 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004381
4382 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4383 return 0;
4384
4385 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004386 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004387 {
4388 if (! peer->af_group[afi][safi])
4389 continue;
4390
4391 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4392 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4393 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004394 peer->pmax_threshold[afi][safi] = 0;
4395 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004396 }
4397 return 0;
4398}
4399
Nick Hilliardfa411a22011-03-23 15:33:17 +00004400/* Set # of hops between us and BGP peer. */
4401int
4402peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4403{
4404 struct peer_group *group;
4405 struct listnode *node, *nnode;
4406 struct peer *peer1;
4407 int ret;
4408
4409 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4410
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004411 if (peer->sort == BGP_PEER_IBGP)
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004412 return BGP_ERR_NO_IBGP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004413
4414 /* We cannot configure ttl-security hops when ebgp-multihop is already
4415 set. For non peer-groups, the check is simple. For peer-groups, it's
4416 slightly messy, because we need to check both the peer-group structure
4417 and all peer-group members for any trace of ebgp-multihop configuration
4418 before actually applying the ttl-security rules. Cisco really made a
4419 mess of this configuration parameter, and OpenBGPD got it right.
4420 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004421
4422 if (peer->gtsm_hops == 0) {
4423 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4424 {
4425 group = peer->group;
4426 if (group->conf->ttl != 1)
4427 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004428
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004429 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4430 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004431 if (peer1->sort == BGP_PEER_IBGP)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004432 continue;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004433
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004434 if (peer1->ttl != 1)
4435 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4436 }
4437 }
4438 else
4439 {
4440 if (peer->ttl != 1)
4441 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4442 }
4443 /* specify MAXTTL on outgoing packets */
4444 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4445 if (ret != 0)
4446 return ret;
4447 }
4448
Nick Hilliardfa411a22011-03-23 15:33:17 +00004449 peer->gtsm_hops = gtsm_hops;
4450
Nick Hilliardfa411a22011-03-23 15:33:17 +00004451 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4452 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004453 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004454 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4455 }
4456 else
4457 {
4458 group = peer->group;
4459 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4460 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004461 if (peer->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004462 continue;
4463
4464 peer->gtsm_hops = group->conf->gtsm_hops;
4465
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004466 /* Change setting of existing peer
4467 * established then change value (may break connectivity)
4468 * not established yet (teardown session and restart)
4469 * no session then do nothing (will get handled by next connection)
4470 */
4471 if (peer->status == Established)
4472 {
4473 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4474 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4475 MAXTTL + 1 - peer->gtsm_hops);
4476 }
4477 else if (peer->status < Established)
4478 {
4479 if (BGP_DEBUG (events, EVENTS))
4480 zlog_debug ("%s Min-ttl changed", peer->host);
4481 BGP_EVENT_ADD (peer, BGP_Stop);
4482 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004483 }
4484 }
4485
4486 return 0;
4487}
4488
4489int
4490peer_ttl_security_hops_unset (struct peer *peer)
4491{
4492 struct peer_group *group;
4493 struct listnode *node, *nnode;
4494 struct peer *opeer;
4495
4496 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4497
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004498 if (peer->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004499 return 0;
4500
4501 /* if a peer-group member, then reset to peer-group default rather than 0 */
4502 if (peer_group_active (peer))
4503 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4504 else
4505 peer->gtsm_hops = 0;
4506
4507 opeer = peer;
4508 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4509 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004510 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004511 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4512 }
4513 else
4514 {
4515 group = peer->group;
4516 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4517 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004518 if (peer->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004519 continue;
4520
4521 peer->gtsm_hops = 0;
4522
4523 if (peer->fd >= 0)
4524 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4525 }
4526 }
4527
4528 return peer_ebgp_multihop_unset (opeer);
4529}
4530
paul718e3742002-12-13 20:15:29 +00004531int
4532peer_clear (struct peer *peer)
4533{
4534 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4535 {
hasso0a486e52005-02-01 20:57:17 +00004536 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4537 {
4538 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4539 if (peer->t_pmax_restart)
4540 {
4541 BGP_TIMER_OFF (peer->t_pmax_restart);
4542 if (BGP_DEBUG (events, EVENTS))
4543 zlog_debug ("%s Maximum-prefix restart timer canceled",
4544 peer->host);
4545 }
4546 BGP_EVENT_ADD (peer, BGP_Start);
4547 return 0;
4548 }
4549
paul718e3742002-12-13 20:15:29 +00004550 peer->v_start = BGP_INIT_START_TIMER;
4551 if (peer->status == Established)
4552 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4553 BGP_NOTIFY_CEASE_ADMIN_RESET);
4554 else
4555 BGP_EVENT_ADD (peer, BGP_Stop);
4556 }
4557 return 0;
4558}
4559
4560int
4561peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4562 enum bgp_clear_type stype)
4563{
4564 if (peer->status != Established)
4565 return 0;
4566
4567 if (! peer->afc[afi][safi])
4568 return BGP_ERR_AF_UNCONFIGURED;
4569
paulfee0f4c2004-09-13 05:12:46 +00004570 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4571 {
4572 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4573 return 0;
4574 bgp_check_local_routes_rsclient (peer, afi, safi);
4575 bgp_soft_reconfig_rsclient (peer, afi, safi);
4576 }
4577
paul718e3742002-12-13 20:15:29 +00004578 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4579 bgp_announce_route (peer, afi, safi);
4580
4581 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4582 {
4583 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4584 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4585 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4586 {
4587 struct bgp_filter *filter = &peer->filter[afi][safi];
4588 u_char prefix_type;
4589
4590 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4591 prefix_type = ORF_TYPE_PREFIX;
4592 else
4593 prefix_type = ORF_TYPE_PREFIX_OLD;
4594
4595 if (filter->plist[FILTER_IN].plist)
4596 {
4597 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4598 bgp_route_refresh_send (peer, afi, safi,
4599 prefix_type, REFRESH_DEFER, 1);
4600 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4601 REFRESH_IMMEDIATE, 0);
4602 }
4603 else
4604 {
4605 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4606 bgp_route_refresh_send (peer, afi, safi,
4607 prefix_type, REFRESH_IMMEDIATE, 1);
4608 else
4609 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4610 }
4611 return 0;
4612 }
4613 }
4614
4615 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4616 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4617 {
4618 /* If neighbor has soft reconfiguration inbound flag.
4619 Use Adj-RIB-In database. */
4620 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4621 bgp_soft_reconfig_in (peer, afi, safi);
4622 else
4623 {
4624 /* If neighbor has route refresh capability, send route refresh
4625 message to the peer. */
4626 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4627 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4628 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4629 else
4630 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4631 }
4632 }
4633 return 0;
4634}
4635
paulfd79ac92004-10-13 05:06:08 +00004636/* Display peer uptime.*/
4637/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004638char *
4639peer_uptime (time_t uptime2, char *buf, size_t len)
4640{
4641 time_t uptime1;
4642 struct tm *tm;
4643
4644 /* Check buffer length. */
4645 if (len < BGP_UPTIME_LEN)
4646 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004647 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004648 /* XXX: should return status instead of buf... */
4649 snprintf (buf, len, "<error> ");
4650 return buf;
paul718e3742002-12-13 20:15:29 +00004651 }
4652
4653 /* If there is no connection has been done before print `never'. */
4654 if (uptime2 == 0)
4655 {
4656 snprintf (buf, len, "never ");
4657 return buf;
4658 }
4659
4660 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004661 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004662 uptime1 -= uptime2;
4663 tm = gmtime (&uptime1);
4664
4665 /* Making formatted timer strings. */
4666#define ONE_DAY_SECOND 60*60*24
4667#define ONE_WEEK_SECOND 60*60*24*7
4668
4669 if (uptime1 < ONE_DAY_SECOND)
4670 snprintf (buf, len, "%02d:%02d:%02d",
4671 tm->tm_hour, tm->tm_min, tm->tm_sec);
4672 else if (uptime1 < ONE_WEEK_SECOND)
4673 snprintf (buf, len, "%dd%02dh%02dm",
4674 tm->tm_yday, tm->tm_hour, tm->tm_min);
4675 else
4676 snprintf (buf, len, "%02dw%dd%02dh",
4677 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4678 return buf;
4679}
4680
paul94f2b392005-06-28 12:44:16 +00004681static void
paul718e3742002-12-13 20:15:29 +00004682bgp_config_write_filter (struct vty *vty, struct peer *peer,
4683 afi_t afi, safi_t safi)
4684{
4685 struct bgp_filter *filter;
4686 struct bgp_filter *gfilter = NULL;
4687 char *addr;
4688 int in = FILTER_IN;
4689 int out = FILTER_OUT;
4690
4691 addr = peer->host;
4692 filter = &peer->filter[afi][safi];
4693 if (peer->af_group[afi][safi])
4694 gfilter = &peer->group->conf->filter[afi][safi];
4695
4696 /* distribute-list. */
4697 if (filter->dlist[in].name)
4698 if (! gfilter || ! gfilter->dlist[in].name
4699 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4700 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4701 filter->dlist[in].name, VTY_NEWLINE);
4702 if (filter->dlist[out].name && ! gfilter)
4703 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4704 filter->dlist[out].name, VTY_NEWLINE);
4705
4706 /* prefix-list. */
4707 if (filter->plist[in].name)
4708 if (! gfilter || ! gfilter->plist[in].name
4709 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4710 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4711 filter->plist[in].name, VTY_NEWLINE);
4712 if (filter->plist[out].name && ! gfilter)
4713 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4714 filter->plist[out].name, VTY_NEWLINE);
4715
4716 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004717 if (filter->map[RMAP_IN].name)
4718 if (! gfilter || ! gfilter->map[RMAP_IN].name
4719 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004720 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004721 filter->map[RMAP_IN].name, VTY_NEWLINE);
4722 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004723 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004724 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4725 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4726 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4727 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4728 if (filter->map[RMAP_EXPORT].name)
4729 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4730 || strcmp (filter->map[RMAP_EXPORT].name,
4731 gfilter->map[RMAP_EXPORT].name) != 0)
4732 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4733 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004734
4735 /* unsuppress-map */
4736 if (filter->usmap.name && ! gfilter)
4737 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4738 filter->usmap.name, VTY_NEWLINE);
4739
4740 /* filter-list. */
4741 if (filter->aslist[in].name)
4742 if (! gfilter || ! gfilter->aslist[in].name
4743 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4744 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4745 filter->aslist[in].name, VTY_NEWLINE);
4746 if (filter->aslist[out].name && ! gfilter)
4747 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4748 filter->aslist[out].name, VTY_NEWLINE);
4749}
4750
4751/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004752static void
paul718e3742002-12-13 20:15:29 +00004753bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4754 struct peer *peer, afi_t afi, safi_t safi)
4755{
paul718e3742002-12-13 20:15:29 +00004756 struct peer *g_peer = NULL;
4757 char buf[SU_ADDRSTRLEN];
4758 char *addr;
4759
paul718e3742002-12-13 20:15:29 +00004760 addr = peer->host;
4761 if (peer_group_active (peer))
4762 g_peer = peer->group->conf;
4763
4764 /************************************
4765 ****** Global to the neighbor ******
4766 ************************************/
4767 if (afi == AFI_IP && safi == SAFI_UNICAST)
4768 {
4769 /* remote-as. */
4770 if (! peer_group_active (peer))
4771 {
4772 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4773 vty_out (vty, " neighbor %s peer-group%s", addr,
4774 VTY_NEWLINE);
4775 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004776 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004777 VTY_NEWLINE);
4778 }
4779 else
4780 {
4781 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004782 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004783 VTY_NEWLINE);
4784 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4785 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4786 peer->group->name, VTY_NEWLINE);
4787 }
4788
4789 /* local-as. */
4790 if (peer->change_local_as)
4791 if (! peer_group_active (peer))
Andrew Certain9d3f9702012-11-07 23:50:07 +00004792 vty_out (vty, " neighbor %s local-as %u%s%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004793 peer->change_local_as,
4794 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
Andrew Certain9d3f9702012-11-07 23:50:07 +00004795 " no-prepend" : "",
4796 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ?
4797 " replace-as" : "", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004798
4799 /* Description. */
4800 if (peer->desc)
4801 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4802 VTY_NEWLINE);
4803
4804 /* Shutdown. */
4805 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4806 if (! peer_group_active (peer) ||
4807 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4808 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4809
Paul Jakma0df7c912008-07-21 21:02:49 +00004810 /* Password. */
4811 if (peer->password)
4812 if (!peer_group_active (peer)
4813 || ! g_peer->password
4814 || strcmp (peer->password, g_peer->password) != 0)
4815 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4816 VTY_NEWLINE);
4817
paul718e3742002-12-13 20:15:29 +00004818 /* BGP port. */
4819 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004820 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004821 VTY_NEWLINE);
4822
4823 /* Local interface name. */
4824 if (peer->ifname)
4825 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4826 VTY_NEWLINE);
4827
4828 /* Passive. */
4829 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4830 if (! peer_group_active (peer) ||
4831 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4832 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4833
4834 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004835 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00004836 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00004837 if (! peer_group_active (peer) ||
4838 g_peer->ttl != peer->ttl)
4839 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4840 VTY_NEWLINE);
4841
Nick Hilliardfa411a22011-03-23 15:33:17 +00004842 /* ttl-security hops */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004843 if (peer->sort != BGP_PEER_IBGP && peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004844 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004845 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00004846 peer->gtsm_hops, VTY_NEWLINE);
4847
hasso6ffd2072005-02-02 14:50:11 +00004848 /* disable-connected-check. */
4849 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004850 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004851 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4852 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004853
4854 /* Update-source. */
4855 if (peer->update_if)
4856 if (! peer_group_active (peer) || ! g_peer->update_if
4857 || strcmp (g_peer->update_if, peer->update_if) != 0)
4858 vty_out (vty, " neighbor %s update-source %s%s", addr,
4859 peer->update_if, VTY_NEWLINE);
4860 if (peer->update_source)
4861 if (! peer_group_active (peer) || ! g_peer->update_source
4862 || sockunion_cmp (g_peer->update_source,
4863 peer->update_source) != 0)
4864 vty_out (vty, " neighbor %s update-source %s%s", addr,
4865 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4866 VTY_NEWLINE);
4867
paul718e3742002-12-13 20:15:29 +00004868 /* advertisement-interval */
4869 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4870 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4871 addr, peer->v_routeadv, VTY_NEWLINE);
4872
4873 /* timers. */
4874 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4875 && ! peer_group_active (peer))
4876 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4877 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4878
4879 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4880 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4881 peer->connect, VTY_NEWLINE);
4882
4883 /* Default weight. */
4884 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4885 if (! peer_group_active (peer) ||
4886 g_peer->weight != peer->weight)
4887 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4888 VTY_NEWLINE);
4889
paul718e3742002-12-13 20:15:29 +00004890 /* Dynamic capability. */
4891 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4892 if (! peer_group_active (peer) ||
4893 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4894 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4895 VTY_NEWLINE);
4896
4897 /* dont capability negotiation. */
4898 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4899 if (! peer_group_active (peer) ||
4900 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4901 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4902 VTY_NEWLINE);
4903
4904 /* override capability negotiation. */
4905 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4906 if (! peer_group_active (peer) ||
4907 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4908 vty_out (vty, " neighbor %s override-capability%s", addr,
4909 VTY_NEWLINE);
4910
4911 /* strict capability negotiation. */
4912 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4913 if (! peer_group_active (peer) ||
4914 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4915 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4916 VTY_NEWLINE);
4917
4918 if (! peer_group_active (peer))
4919 {
4920 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4921 {
4922 if (peer->afc[AFI_IP][SAFI_UNICAST])
4923 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4924 }
4925 else
4926 {
4927 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4928 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4929 }
4930 }
4931 }
4932
4933
4934 /************************************
4935 ****** Per AF to the neighbor ******
4936 ************************************/
4937
4938 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4939 {
4940 if (peer->af_group[afi][safi])
4941 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4942 peer->group->name, VTY_NEWLINE);
4943 else
4944 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4945 }
4946
4947 /* ORF capability. */
4948 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4949 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4950 if (! peer->af_group[afi][safi])
4951 {
4952 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4953
4954 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4955 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4956 vty_out (vty, " both");
4957 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4958 vty_out (vty, " send");
4959 else
4960 vty_out (vty, " receive");
4961 vty_out (vty, "%s", VTY_NEWLINE);
4962 }
4963
4964 /* Route reflector client. */
4965 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4966 && ! peer->af_group[afi][safi])
4967 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4968 VTY_NEWLINE);
4969
4970 /* Nexthop self. */
4971 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4972 && ! peer->af_group[afi][safi])
4973 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4974
4975 /* Remove private AS. */
4976 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4977 && ! peer->af_group[afi][safi])
4978 vty_out (vty, " neighbor %s remove-private-AS%s",
4979 addr, VTY_NEWLINE);
4980
4981 /* send-community print. */
4982 if (! peer->af_group[afi][safi])
4983 {
4984 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4985 {
4986 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4987 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4988 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4989 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4990 vty_out (vty, " neighbor %s send-community extended%s",
4991 addr, VTY_NEWLINE);
4992 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4993 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4994 }
4995 else
4996 {
4997 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4998 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4999 vty_out (vty, " no neighbor %s send-community both%s",
5000 addr, VTY_NEWLINE);
5001 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
5002 vty_out (vty, " no neighbor %s send-community extended%s",
5003 addr, VTY_NEWLINE);
5004 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
5005 vty_out (vty, " no neighbor %s send-community%s",
5006 addr, VTY_NEWLINE);
5007 }
5008 }
5009
5010 /* Default information */
5011 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
5012 && ! peer->af_group[afi][safi])
5013 {
5014 vty_out (vty, " neighbor %s default-originate", addr);
5015 if (peer->default_rmap[afi][safi].name)
5016 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
5017 vty_out (vty, "%s", VTY_NEWLINE);
5018 }
5019
5020 /* Soft reconfiguration inbound. */
5021 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5022 if (! peer->af_group[afi][safi] ||
5023 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5024 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5025 VTY_NEWLINE);
5026
5027 /* maximum-prefix. */
5028 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5029 if (! peer->af_group[afi][safi]
5030 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005031 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005032 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5033 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005034 {
hasso0a486e52005-02-01 20:57:17 +00005035 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5036 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5037 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5038 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5039 vty_out (vty, " warning-only");
5040 if (peer->pmax_restart[afi][safi])
5041 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5042 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005043 }
paul718e3742002-12-13 20:15:29 +00005044
5045 /* Route server client. */
5046 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5047 && ! peer->af_group[afi][safi])
5048 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5049
Dylan Hall3cf12882011-10-27 15:28:17 +04005050 /* Nexthop-local unchanged. */
5051 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5052 && ! peer->af_group[afi][safi])
5053 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5054
paul718e3742002-12-13 20:15:29 +00005055 /* Allow AS in. */
5056 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5057 if (! peer_group_active (peer)
5058 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5059 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5060 {
5061 if (peer->allowas_in[afi][safi] == 3)
5062 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5063 else
5064 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5065 peer->allowas_in[afi][safi], VTY_NEWLINE);
5066 }
5067
5068 /* Filter. */
5069 bgp_config_write_filter (vty, peer, afi, safi);
5070
5071 /* atribute-unchanged. */
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 && ! peer->af_group[afi][safi])
5076 {
5077 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5078 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5079 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5080 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5081 else
5082 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5083 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5084 " as-path" : "",
5085 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5086 " next-hop" : "",
5087 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5088 " med" : "", VTY_NEWLINE);
5089 }
5090}
5091
5092/* Display "address-family" configuration header. */
5093void
5094bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5095 int *write)
5096{
5097 if (*write)
5098 return;
5099
5100 if (afi == AFI_IP && safi == SAFI_UNICAST)
5101 return;
5102
5103 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5104
5105 if (afi == AFI_IP)
5106 {
5107 if (safi == SAFI_MULTICAST)
5108 vty_out (vty, "ipv4 multicast");
5109 else if (safi == SAFI_MPLS_VPN)
5110 vty_out (vty, "vpnv4 unicast");
5111 }
5112 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005113 {
5114 vty_out (vty, "ipv6");
5115
5116 if (safi == SAFI_MULTICAST)
5117 vty_out (vty, " multicast");
5118 }
paul718e3742002-12-13 20:15:29 +00005119
5120 vty_out (vty, "%s", VTY_NEWLINE);
5121
5122 *write = 1;
5123}
5124
5125/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005126static int
paul718e3742002-12-13 20:15:29 +00005127bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5128 safi_t safi)
5129{
5130 int write = 0;
5131 struct peer *peer;
5132 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005133 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005134
5135 bgp_config_write_network (vty, bgp, afi, safi, &write);
5136
5137 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5138
paul1eb8ef22005-04-07 07:30:20 +00005139 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005140 {
5141 if (group->conf->afc[afi][safi])
5142 {
5143 bgp_config_write_family_header (vty, afi, safi, &write);
5144 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5145 }
5146 }
paul1eb8ef22005-04-07 07:30:20 +00005147 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005148 {
5149 if (peer->afc[afi][safi])
5150 {
5151 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5152 {
5153 bgp_config_write_family_header (vty, afi, safi, &write);
5154 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5155 }
5156 }
5157 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005158
5159 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5160
paul718e3742002-12-13 20:15:29 +00005161 if (write)
5162 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5163
5164 return write;
5165}
5166
5167int
5168bgp_config_write (struct vty *vty)
5169{
5170 int write = 0;
5171 struct bgp *bgp;
5172 struct peer_group *group;
5173 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005174 struct listnode *node, *nnode;
5175 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005176
5177 /* BGP Multiple instance. */
5178 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5179 {
5180 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5181 write++;
5182 }
5183
5184 /* BGP Config type. */
5185 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5186 {
5187 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5188 write++;
5189 }
5190
5191 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005192 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005193 {
5194 if (write)
5195 vty_out (vty, "!%s", VTY_NEWLINE);
5196
5197 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005198 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005199
5200 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5201 {
5202 if (bgp->name)
5203 vty_out (vty, " view %s", bgp->name);
5204 }
5205 vty_out (vty, "%s", VTY_NEWLINE);
5206
5207 /* No Synchronization */
5208 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5209 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5210
5211 /* BGP fast-external-failover. */
5212 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5213 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5214
5215 /* BGP router ID. */
5216 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5217 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5218 VTY_NEWLINE);
5219
paul848973c2003-08-13 00:32:49 +00005220 /* BGP log-neighbor-changes. */
5221 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5222 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
5223
paul718e3742002-12-13 20:15:29 +00005224 /* BGP configuration. */
5225 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5226 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5227
5228 /* BGP default ipv4-unicast. */
5229 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5230 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5231
5232 /* BGP default local-preference. */
5233 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5234 vty_out (vty, " bgp default local-preference %d%s",
5235 bgp->default_local_pref, VTY_NEWLINE);
5236
5237 /* BGP client-to-client reflection. */
5238 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5239 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5240
5241 /* BGP cluster ID. */
5242 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5243 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5244 VTY_NEWLINE);
5245
hassoe0701b72004-05-20 09:19:34 +00005246 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005247 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005248 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5249 VTY_NEWLINE);
5250
5251 /* Confederation peer */
5252 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005253 {
hassoe0701b72004-05-20 09:19:34 +00005254 int i;
paul718e3742002-12-13 20:15:29 +00005255
hassoe0701b72004-05-20 09:19:34 +00005256 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005257
hassoe0701b72004-05-20 09:19:34 +00005258 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005259 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005260
hassoe0701b72004-05-20 09:19:34 +00005261 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005262 }
5263
5264 /* BGP enforce-first-as. */
5265 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5266 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5267
5268 /* BGP deterministic-med. */
5269 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5270 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005271
5272 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005273 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5274 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5275 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005276 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5277 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5278
paul718e3742002-12-13 20:15:29 +00005279 /* BGP bestpath method. */
5280 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5281 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005282 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5283 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005284 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5285 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5286 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5287 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5288 {
5289 vty_out (vty, " bgp bestpath med");
5290 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5291 vty_out (vty, " confed");
5292 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5293 vty_out (vty, " missing-as-worst");
5294 vty_out (vty, "%s", VTY_NEWLINE);
5295 }
5296
5297 /* BGP network import check. */
5298 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5299 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5300
5301 /* BGP scan interval. */
5302 bgp_config_write_scan_time (vty);
5303
5304 /* BGP flag dampening. */
5305 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5306 BGP_CONFIG_DAMPENING))
5307 bgp_config_write_damp (vty);
5308
5309 /* BGP static route configuration. */
5310 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5311
5312 /* BGP redistribute configuration. */
5313 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5314
5315 /* BGP timers configuration. */
5316 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5317 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5318 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5319 bgp->default_holdtime, VTY_NEWLINE);
5320
5321 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005322 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005323 {
5324 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5325 }
5326
5327 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005328 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005329 {
5330 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5331 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5332 }
5333
Josh Bailey165b5ff2011-07-20 20:43:22 -07005334 /* maximum-paths */
5335 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5336
paul718e3742002-12-13 20:15:29 +00005337 /* Distance configuration. */
5338 bgp_config_write_distance (vty, bgp);
5339
5340 /* No auto-summary */
5341 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5342 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5343
5344 /* IPv4 multicast configuration. */
5345 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5346
5347 /* IPv4 VPN configuration. */
5348 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5349
5350 /* IPv6 unicast configuration. */
5351 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5352
Paul Jakma37a217a2007-04-10 19:20:29 +00005353 /* IPv6 multicast configuration. */
5354 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5355
paul718e3742002-12-13 20:15:29 +00005356 write++;
5357 }
5358 return write;
5359}
5360
5361void
paul94f2b392005-06-28 12:44:16 +00005362bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005363{
5364 memset (&bgp_master, 0, sizeof (struct bgp_master));
5365
5366 bm = &bgp_master;
5367 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005368 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005369 bm->port = BGP_PORT_DEFAULT;
5370 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005371 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005372}
paul200df112005-06-01 11:17:05 +00005373
paul718e3742002-12-13 20:15:29 +00005374
5375void
paul94f2b392005-06-28 12:44:16 +00005376bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005377{
paul718e3742002-12-13 20:15:29 +00005378 /* BGP VTY commands installation. */
5379 bgp_vty_init ();
5380
paul718e3742002-12-13 20:15:29 +00005381 /* Init zebra. */
5382 bgp_zebra_init ();
5383
5384 /* BGP inits. */
5385 bgp_attr_init ();
5386 bgp_debug_init ();
5387 bgp_dump_init ();
5388 bgp_route_init ();
5389 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005390 bgp_address_init ();
paul718e3742002-12-13 20:15:29 +00005391 bgp_scan_init ();
5392 bgp_mplsvpn_init ();
5393
5394 /* Access list initialize. */
5395 access_list_init ();
5396 access_list_add_hook (peer_distribute_update);
5397 access_list_delete_hook (peer_distribute_update);
5398
5399 /* Filter list initialize. */
5400 bgp_filter_init ();
5401 as_list_add_hook (peer_aslist_update);
5402 as_list_delete_hook (peer_aslist_update);
5403
5404 /* Prefix list initialize.*/
5405 prefix_list_init ();
5406 prefix_list_add_hook (peer_prefix_list_update);
5407 prefix_list_delete_hook (peer_prefix_list_update);
5408
5409 /* Community list initialize. */
5410 bgp_clist = community_list_init ();
5411
5412#ifdef HAVE_SNMP
5413 bgp_snmp_init ();
5414#endif /* HAVE_SNMP */
5415}
paul545acaf2004-04-20 15:13:15 +00005416
5417void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005418bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005419{
paul545acaf2004-04-20 15:13:15 +00005420 struct bgp *bgp;
5421 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005422 struct listnode *node, *nnode;
5423 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005424
paul1eb8ef22005-04-07 07:30:20 +00005425 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5426 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005427 if (peer->status == Established)
5428 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5429 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005430
paul545acaf2004-04-20 15:13:15 +00005431 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005432
paule210cf92005-06-15 19:15:35 +00005433 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005434 {
5435 work_queue_free (bm->process_main_queue);
5436 bm->process_main_queue = NULL;
5437 }
paule210cf92005-06-15 19:15:35 +00005438 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005439 {
5440 work_queue_free (bm->process_rsclient_queue);
5441 bm->process_rsclient_queue = NULL;
5442 }
paul545acaf2004-04-20 15:13:15 +00005443}