blob: 69c8c0a33dddae4aceb90a41344fe7683523f669 [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);
965 }
966}
967
968/* If peer does not exist, create new one. If peer already exists,
969 set AS number to the peer. */
970int
971peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
972 afi_t afi, safi_t safi)
973{
974 struct peer *peer;
975 as_t local_as;
976
977 peer = peer_lookup (bgp, su);
978
979 if (peer)
980 {
981 /* When this peer is a member of peer-group. */
982 if (peer->group)
983 {
984 if (peer->group->conf->as)
985 {
986 /* Return peer group's AS number. */
987 *as = peer->group->conf->as;
988 return BGP_ERR_PEER_GROUP_MEMBER;
989 }
990 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
991 {
992 if (bgp->as != *as)
993 {
994 *as = peer->as;
995 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
996 }
997 }
998 else
999 {
1000 if (bgp->as == *as)
1001 {
1002 *as = peer->as;
1003 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1004 }
1005 }
1006 }
1007
1008 /* Existing peer's AS number change. */
1009 if (peer->as != *as)
1010 peer_as_change (peer, *as);
1011 }
1012 else
1013 {
1014
1015 /* If the peer is not part of our confederation, and its not an
1016 iBGP peer then spoof the source AS */
1017 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
1018 && ! bgp_confederation_peers_check (bgp, *as)
1019 && bgp->as != *as)
1020 local_as = bgp->confed_id;
1021 else
1022 local_as = bgp->as;
1023
1024 /* If this is IPv4 unicast configuration and "no bgp default
1025 ipv4-unicast" is specified. */
1026
1027 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1028 && afi == AFI_IP && safi == SAFI_UNICAST)
1029 peer = peer_create (su, bgp, local_as, *as, 0, 0);
1030 else
1031 peer = peer_create (su, bgp, local_as, *as, afi, safi);
1032 }
1033
1034 return 0;
1035}
1036
1037/* Activate the peer or peer group for specified AFI and SAFI. */
1038int
1039peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1040{
1041 int active;
1042
1043 if (peer->afc[afi][safi])
1044 return 0;
1045
1046 /* Activate the address family configuration. */
1047 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1048 peer->afc[afi][safi] = 1;
1049 else
1050 {
1051 active = peer_active (peer);
1052
1053 peer->afc[afi][safi] = 1;
1054
1055 if (! active && peer_active (peer))
1056 bgp_timer_set (peer);
1057 else
1058 {
1059 if (peer->status == Established)
1060 {
1061 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1062 {
1063 peer->afc_adv[afi][safi] = 1;
1064 bgp_capability_send (peer, afi, safi,
1065 CAPABILITY_CODE_MP,
1066 CAPABILITY_ACTION_SET);
1067 if (peer->afc_recv[afi][safi])
1068 {
1069 peer->afc_nego[afi][safi] = 1;
1070 bgp_announce_route (peer, afi, safi);
1071 }
1072 }
1073 else
hassoe0701b72004-05-20 09:19:34 +00001074 {
1075 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1076 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1077 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1078 }
paul718e3742002-12-13 20:15:29 +00001079 }
1080 }
1081 }
1082 return 0;
1083}
1084
1085int
1086peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1087{
1088 struct peer_group *group;
1089 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001090 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001091
1092 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1093 {
1094 group = peer->group;
1095
paul1eb8ef22005-04-07 07:30:20 +00001096 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001097 {
1098 if (peer1->af_group[afi][safi])
1099 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1100 }
1101 }
1102 else
1103 {
1104 if (peer->af_group[afi][safi])
1105 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1106 }
1107
1108 if (! peer->afc[afi][safi])
1109 return 0;
1110
1111 /* De-activate the address family configuration. */
1112 peer->afc[afi][safi] = 0;
1113 peer_af_flag_reset (peer, afi, safi);
1114
1115 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1116 {
1117 if (peer->status == Established)
1118 {
1119 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1120 {
1121 peer->afc_adv[afi][safi] = 0;
1122 peer->afc_nego[afi][safi] = 0;
1123
1124 if (peer_active_nego (peer))
1125 {
1126 bgp_capability_send (peer, afi, safi,
1127 CAPABILITY_CODE_MP,
1128 CAPABILITY_ACTION_UNSET);
Chris Caputo228da422009-07-18 05:44:03 +00001129 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
paul718e3742002-12-13 20:15:29 +00001130 peer->pcount[afi][safi] = 0;
1131 }
1132 else
hassoe0701b72004-05-20 09:19:34 +00001133 {
1134 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1135 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1136 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1137 }
paul718e3742002-12-13 20:15:29 +00001138 }
1139 else
hassoe0701b72004-05-20 09:19:34 +00001140 {
1141 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1142 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1143 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1144 }
paul718e3742002-12-13 20:15:29 +00001145 }
1146 }
1147 return 0;
1148}
1149
Stephen Hemmingerda88ea82009-12-17 13:14:28 +03001150static void
hasso93406d82005-02-02 14:40:33 +00001151peer_nsf_stop (struct peer *peer)
1152{
1153 afi_t afi;
1154 safi_t safi;
1155
1156 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1157 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1158
1159 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
Denis Ovsienko0a281302011-07-17 19:33:21 +04001160 for (safi = SAFI_UNICAST ; safi < SAFI_RESERVED_3 ; safi++)
hasso93406d82005-02-02 14:40:33 +00001161 peer->nsf[afi][safi] = 0;
1162
1163 if (peer->t_gr_restart)
1164 {
1165 BGP_TIMER_OFF (peer->t_gr_restart);
1166 if (BGP_DEBUG (events, EVENTS))
1167 zlog_debug ("%s graceful restart timer stopped", peer->host);
1168 }
1169 if (peer->t_gr_stale)
1170 {
1171 BGP_TIMER_OFF (peer->t_gr_stale);
1172 if (BGP_DEBUG (events, EVENTS))
1173 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1174 }
1175 bgp_clear_route_all (peer);
1176}
1177
Paul Jakmaca058a32006-09-14 02:58:49 +00001178/* Delete peer from confguration.
1179 *
1180 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1181 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1182 *
1183 * This function /should/ take care to be idempotent, to guard against
1184 * it being called multiple times through stray events that come in
1185 * that happen to result in this function being called again. That
1186 * said, getting here for a "Deleted" peer is a bug in the neighbour
1187 * FSM.
1188 */
paul718e3742002-12-13 20:15:29 +00001189int
1190peer_delete (struct peer *peer)
1191{
1192 int i;
1193 afi_t afi;
1194 safi_t safi;
1195 struct bgp *bgp;
1196 struct bgp_filter *filter;
Chris Caputo228da422009-07-18 05:44:03 +00001197 struct listnode *pn;
paul718e3742002-12-13 20:15:29 +00001198
Paul Jakmaca058a32006-09-14 02:58:49 +00001199 assert (peer->status != Deleted);
1200
paul718e3742002-12-13 20:15:29 +00001201 bgp = peer->bgp;
1202
hasso93406d82005-02-02 14:40:33 +00001203 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1204 peer_nsf_stop (peer);
1205
Chris Caputo228da422009-07-18 05:44:03 +00001206 /* If this peer belongs to peer group, clear up the
paul718e3742002-12-13 20:15:29 +00001207 relationship. */
1208 if (peer->group)
1209 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001210 if ((pn = listnode_lookup (peer->group->peer, peer)))
1211 {
1212 peer = peer_unlock (peer); /* group->peer list reference */
1213 list_delete_node (peer->group->peer, pn);
1214 }
paul718e3742002-12-13 20:15:29 +00001215 peer->group = NULL;
1216 }
paul200df112005-06-01 11:17:05 +00001217
paul718e3742002-12-13 20:15:29 +00001218 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001219 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1220 * executed after peer structure is deleted.
1221 */
hassoe0701b72004-05-20 09:19:34 +00001222 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001223 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001224 bgp_fsm_change_status (peer, Deleted);
Paul Jakma0df7c912008-07-21 21:02:49 +00001225
1226 /* Password configuration */
1227 if (peer->password)
1228 {
1229 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1230 peer->password = NULL;
1231
1232 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1233 bgp_md5_set (peer);
1234 }
1235
Paul Jakmaca058a32006-09-14 02:58:49 +00001236 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001237
paul718e3742002-12-13 20:15:29 +00001238 /* Delete from all peer list. */
Chris Caputo228da422009-07-18 05:44:03 +00001239 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
1240 && (pn = listnode_lookup (bgp->peer, peer)))
paulfee0f4c2004-09-13 05:12:46 +00001241 {
Chris Caputo228da422009-07-18 05:44:03 +00001242 peer_unlock (peer); /* bgp peer list reference */
1243 list_delete_node (bgp->peer, pn);
1244 }
paul200df112005-06-01 11:17:05 +00001245
Chris Caputo228da422009-07-18 05:44:03 +00001246 if (peer_rsclient_active (peer)
1247 && (pn = listnode_lookup (bgp->rsclient, peer)))
1248 {
1249 peer_unlock (peer); /* rsclient list reference */
1250 list_delete_node (bgp->rsclient, pn);
1251
1252 /* Clear our own rsclient ribs. */
1253 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1254 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1255 if (CHECK_FLAG(peer->af_flags[afi][safi],
1256 PEER_FLAG_RSERVER_CLIENT))
1257 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paulfee0f4c2004-09-13 05:12:46 +00001258 }
1259
1260 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1261 member of a peer_group. */
1262 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1263 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1264 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
Paul Jakmab608d5b2008-07-02 02:12:07 +00001265 bgp_table_finish (&peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001266
paul200df112005-06-01 11:17:05 +00001267 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001268 if (peer->ibuf)
1269 stream_free (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001270 if (peer->obuf)
1271 stream_fifo_free (peer->obuf);
paul718e3742002-12-13 20:15:29 +00001272 if (peer->work)
1273 stream_free (peer->work);
Paul Jakma18937402006-07-27 19:05:12 +00001274 peer->obuf = NULL;
1275 peer->work = peer->ibuf = NULL;
1276
paul718e3742002-12-13 20:15:29 +00001277 /* Local and remote addresses. */
1278 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001279 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001280 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001281 sockunion_free (peer->su_remote);
Paul Jakma18937402006-07-27 19:05:12 +00001282 peer->su_local = peer->su_remote = NULL;
paul200df112005-06-01 11:17:05 +00001283
paul718e3742002-12-13 20:15:29 +00001284 /* Free filter related memory. */
1285 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1286 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1287 {
1288 filter = &peer->filter[afi][safi];
1289
1290 for (i = FILTER_IN; i < FILTER_MAX; i++)
1291 {
1292 if (filter->dlist[i].name)
1293 free (filter->dlist[i].name);
1294 if (filter->plist[i].name)
1295 free (filter->plist[i].name);
1296 if (filter->aslist[i].name)
1297 free (filter->aslist[i].name);
paul200df112005-06-01 11:17:05 +00001298
1299 filter->dlist[i].name = NULL;
1300 filter->plist[i].name = NULL;
1301 filter->aslist[i].name = NULL;
1302 }
1303 for (i = RMAP_IN; i < RMAP_MAX; i++)
1304 {
paul718e3742002-12-13 20:15:29 +00001305 if (filter->map[i].name)
1306 free (filter->map[i].name);
paul200df112005-06-01 11:17:05 +00001307 filter->map[i].name = NULL;
paul718e3742002-12-13 20:15:29 +00001308 }
1309
1310 if (filter->usmap.name)
1311 free (filter->usmap.name);
1312
1313 if (peer->default_rmap[afi][safi].name)
1314 free (peer->default_rmap[afi][safi].name);
paul200df112005-06-01 11:17:05 +00001315
1316 filter->usmap.name = NULL;
1317 peer->default_rmap[afi][safi].name = NULL;
paul718e3742002-12-13 20:15:29 +00001318 }
paul200df112005-06-01 11:17:05 +00001319
1320 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001321
1322 return 0;
1323}
1324
paul94f2b392005-06-28 12:44:16 +00001325static int
paul718e3742002-12-13 20:15:29 +00001326peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1327{
1328 return strcmp (g1->name, g2->name);
1329}
1330
1331/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001332static int
paul718e3742002-12-13 20:15:29 +00001333peer_group_active (struct peer *peer)
1334{
1335 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1336 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1337 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1338 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1339 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1340 return 1;
1341 return 0;
1342}
1343
1344/* Peer group cofiguration. */
1345static struct peer_group *
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08001346peer_group_new (void)
paul718e3742002-12-13 20:15:29 +00001347{
1348 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1349 sizeof (struct peer_group));
1350}
1351
paul94f2b392005-06-28 12:44:16 +00001352static void
paul718e3742002-12-13 20:15:29 +00001353peer_group_free (struct peer_group *group)
1354{
1355 XFREE (MTYPE_PEER_GROUP, group);
1356}
1357
1358struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001359peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001360{
1361 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001362 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001363
paul1eb8ef22005-04-07 07:30:20 +00001364 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001365 {
1366 if (strcmp (group->name, name) == 0)
1367 return group;
1368 }
1369 return NULL;
1370}
1371
1372struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001373peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001374{
1375 struct peer_group *group;
1376
1377 group = peer_group_lookup (bgp, name);
1378 if (group)
1379 return group;
1380
1381 group = peer_group_new ();
1382 group->bgp = bgp;
1383 group->name = strdup (name);
1384 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001385 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001386 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1387 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
Chris Caputo228da422009-07-18 05:44:03 +00001388 group->conf->host = XSTRDUP (MTYPE_BGP_PEER_HOST, name);
paul718e3742002-12-13 20:15:29 +00001389 group->conf->group = group;
1390 group->conf->as = 0;
1391 group->conf->ttl = 1;
Nick Hilliardfa411a22011-03-23 15:33:17 +00001392 group->conf->gtsm_hops = 0;
paul718e3742002-12-13 20:15:29 +00001393 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1394 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1395 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1396 group->conf->keepalive = 0;
1397 group->conf->holdtime = 0;
1398 group->conf->connect = 0;
1399 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1400 listnode_add_sort (bgp->group, group);
1401
1402 return 0;
1403}
1404
paul94f2b392005-06-28 12:44:16 +00001405static void
paul718e3742002-12-13 20:15:29 +00001406peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1407 afi_t afi, safi_t safi)
1408{
1409 int in = FILTER_IN;
1410 int out = FILTER_OUT;
1411 struct peer *conf;
1412 struct bgp_filter *pfilter;
1413 struct bgp_filter *gfilter;
1414
1415 conf = group->conf;
1416 pfilter = &peer->filter[afi][safi];
1417 gfilter = &conf->filter[afi][safi];
1418
1419 /* remote-as */
1420 if (conf->as)
1421 peer->as = conf->as;
1422
1423 /* remote-as */
1424 if (conf->change_local_as)
1425 peer->change_local_as = conf->change_local_as;
1426
1427 /* TTL */
1428 peer->ttl = conf->ttl;
1429
Nick Hilliardfa411a22011-03-23 15:33:17 +00001430 /* GTSM hops */
1431 peer->gtsm_hops = conf->gtsm_hops;
1432
paul718e3742002-12-13 20:15:29 +00001433 /* Weight */
1434 peer->weight = conf->weight;
1435
1436 /* peer flags apply */
1437 peer->flags = conf->flags;
1438 /* peer af_flags apply */
1439 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1440 /* peer config apply */
1441 peer->config = conf->config;
1442
1443 /* peer timers apply */
1444 peer->holdtime = conf->holdtime;
1445 peer->keepalive = conf->keepalive;
1446 peer->connect = conf->connect;
1447 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1448 peer->v_connect = conf->connect;
1449 else
1450 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1451
1452 /* advertisement-interval reset */
1453 if (peer_sort (peer) == BGP_PEER_IBGP)
1454 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1455 else
1456 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1457
Paul Jakma0df7c912008-07-21 21:02:49 +00001458 /* password apply */
1459 if (peer->password)
1460 XFREE (MTYPE_PEER_PASSWORD, peer->password);
1461
1462 if (conf->password)
1463 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, conf->password);
1464 else
1465 peer->password = NULL;
1466
1467 bgp_md5_set (peer);
1468
paul718e3742002-12-13 20:15:29 +00001469 /* maximum-prefix */
1470 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001471 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001472 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001473
1474 /* allowas-in */
1475 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1476
paulfee0f4c2004-09-13 05:12:46 +00001477 /* route-server-client */
1478 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1479 {
1480 /* Make peer's RIB point to group's RIB. */
1481 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1482
1483 /* Import policy. */
1484 if (pfilter->map[RMAP_IMPORT].name)
1485 free (pfilter->map[RMAP_IMPORT].name);
1486 if (gfilter->map[RMAP_IMPORT].name)
1487 {
1488 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1489 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1490 }
1491 else
1492 {
1493 pfilter->map[RMAP_IMPORT].name = NULL;
1494 pfilter->map[RMAP_IMPORT].map = NULL;
1495 }
1496
1497 /* Export policy. */
1498 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1499 {
1500 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1501 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1502 }
1503 }
1504
paul718e3742002-12-13 20:15:29 +00001505 /* default-originate route-map */
1506 if (conf->default_rmap[afi][safi].name)
1507 {
1508 if (peer->default_rmap[afi][safi].name)
1509 free (peer->default_rmap[afi][safi].name);
1510 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1511 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1512 }
1513
1514 /* update-source apply */
1515 if (conf->update_source)
1516 {
1517 if (peer->update_source)
1518 sockunion_free (peer->update_source);
1519 if (peer->update_if)
1520 {
1521 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1522 peer->update_if = NULL;
1523 }
1524 peer->update_source = sockunion_dup (conf->update_source);
1525 }
1526 else if (conf->update_if)
1527 {
1528 if (peer->update_if)
1529 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1530 if (peer->update_source)
1531 {
1532 sockunion_free (peer->update_source);
1533 peer->update_source = NULL;
1534 }
1535 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1536 }
1537
1538 /* inbound filter apply */
1539 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1540 {
1541 if (pfilter->dlist[in].name)
1542 free (pfilter->dlist[in].name);
1543 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1544 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1545 }
1546 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1547 {
1548 if (pfilter->plist[in].name)
1549 free (pfilter->plist[in].name);
1550 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1551 pfilter->plist[in].plist = gfilter->plist[in].plist;
1552 }
1553 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1554 {
1555 if (pfilter->aslist[in].name)
1556 free (pfilter->aslist[in].name);
1557 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1558 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1559 }
paulfee0f4c2004-09-13 05:12:46 +00001560 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001561 {
paulfee0f4c2004-09-13 05:12:46 +00001562 if (pfilter->map[RMAP_IN].name)
1563 free (pfilter->map[RMAP_IN].name);
1564 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1565 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001566 }
1567
1568 /* outbound filter apply */
1569 if (gfilter->dlist[out].name)
1570 {
1571 if (pfilter->dlist[out].name)
1572 free (pfilter->dlist[out].name);
1573 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1574 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1575 }
1576 else
1577 {
1578 if (pfilter->dlist[out].name)
1579 free (pfilter->dlist[out].name);
1580 pfilter->dlist[out].name = NULL;
1581 pfilter->dlist[out].alist = NULL;
1582 }
1583 if (gfilter->plist[out].name)
1584 {
1585 if (pfilter->plist[out].name)
1586 free (pfilter->plist[out].name);
1587 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1588 pfilter->plist[out].plist = gfilter->plist[out].plist;
1589 }
1590 else
1591 {
1592 if (pfilter->plist[out].name)
1593 free (pfilter->plist[out].name);
1594 pfilter->plist[out].name = NULL;
1595 pfilter->plist[out].plist = NULL;
1596 }
1597 if (gfilter->aslist[out].name)
1598 {
1599 if (pfilter->aslist[out].name)
1600 free (pfilter->aslist[out].name);
1601 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1602 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1603 }
1604 else
1605 {
1606 if (pfilter->aslist[out].name)
1607 free (pfilter->aslist[out].name);
1608 pfilter->aslist[out].name = NULL;
1609 pfilter->aslist[out].aslist = NULL;
1610 }
paulfee0f4c2004-09-13 05:12:46 +00001611 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001612 {
paulfee0f4c2004-09-13 05:12:46 +00001613 if (pfilter->map[RMAP_OUT].name)
1614 free (pfilter->map[RMAP_OUT].name);
1615 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1616 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001617 }
1618 else
1619 {
paulfee0f4c2004-09-13 05:12:46 +00001620 if (pfilter->map[RMAP_OUT].name)
1621 free (pfilter->map[RMAP_OUT].name);
1622 pfilter->map[RMAP_OUT].name = NULL;
1623 pfilter->map[RMAP_OUT].map = NULL;
1624 }
1625
1626 /* RS-client's import/export route-maps. */
1627 if (gfilter->map[RMAP_IMPORT].name)
1628 {
1629 if (pfilter->map[RMAP_IMPORT].name)
1630 free (pfilter->map[RMAP_IMPORT].name);
1631 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1632 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1633 }
1634 else
1635 {
1636 if (pfilter->map[RMAP_IMPORT].name)
1637 free (pfilter->map[RMAP_IMPORT].name);
1638 pfilter->map[RMAP_IMPORT].name = NULL;
1639 pfilter->map[RMAP_IMPORT].map = NULL;
1640 }
1641 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1642 {
1643 if (pfilter->map[RMAP_EXPORT].name)
1644 free (pfilter->map[RMAP_EXPORT].name);
1645 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1646 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001647 }
1648
1649 if (gfilter->usmap.name)
1650 {
1651 if (pfilter->usmap.name)
1652 free (pfilter->usmap.name);
1653 pfilter->usmap.name = strdup (gfilter->usmap.name);
1654 pfilter->usmap.map = gfilter->usmap.map;
1655 }
1656 else
1657 {
1658 if (pfilter->usmap.name)
1659 free (pfilter->usmap.name);
1660 pfilter->usmap.name = NULL;
1661 pfilter->usmap.map = NULL;
1662 }
1663}
1664
1665/* Peer group's remote AS configuration. */
1666int
paulfd79ac92004-10-13 05:06:08 +00001667peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001668{
1669 struct peer_group *group;
1670 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001671 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001672
1673 group = peer_group_lookup (bgp, group_name);
1674 if (! group)
1675 return -1;
1676
1677 if (group->conf->as == *as)
1678 return 0;
1679
1680 /* When we setup peer-group AS number all peer group member's AS
1681 number must be updated to same number. */
1682 peer_as_change (group->conf, *as);
1683
paul1eb8ef22005-04-07 07:30:20 +00001684 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001685 {
1686 if (peer->as != *as)
1687 peer_as_change (peer, *as);
1688 }
1689
1690 return 0;
1691}
1692
1693int
1694peer_group_delete (struct peer_group *group)
1695{
1696 struct bgp *bgp;
1697 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001698 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001699
1700 bgp = group->bgp;
1701
paul1eb8ef22005-04-07 07:30:20 +00001702 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001703 {
1704 peer->group = NULL;
1705 peer_delete (peer);
1706 }
1707 list_delete (group->peer);
1708
1709 free (group->name);
1710 group->name = NULL;
1711
1712 group->conf->group = NULL;
1713 peer_delete (group->conf);
1714
1715 /* Delete from all peer_group list. */
1716 listnode_delete (bgp->group, group);
1717
1718 peer_group_free (group);
1719
1720 return 0;
1721}
1722
1723int
1724peer_group_remote_as_delete (struct peer_group *group)
1725{
1726 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001727 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001728
1729 if (! group->conf->as)
1730 return 0;
1731
paul1eb8ef22005-04-07 07:30:20 +00001732 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001733 {
1734 peer->group = NULL;
1735 peer_delete (peer);
1736 }
1737 list_delete_all_node (group->peer);
1738
1739 group->conf->as = 0;
1740
1741 return 0;
1742}
1743
1744/* Bind specified peer to peer group. */
1745int
1746peer_group_bind (struct bgp *bgp, union sockunion *su,
1747 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1748{
1749 struct peer *peer;
1750 int first_member = 0;
1751
1752 /* Check peer group's address family. */
1753 if (! group->conf->afc[afi][safi])
1754 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1755
1756 /* Lookup the peer. */
1757 peer = peer_lookup (bgp, su);
1758
1759 /* Create a new peer. */
1760 if (! peer)
1761 {
1762 if (! group->conf->as)
1763 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1764
1765 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1766 peer->group = group;
1767 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001768
Paul Jakmaca058a32006-09-14 02:58:49 +00001769 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001770 listnode_add (group->peer, peer);
1771 peer_group2peer_config_copy (group, peer, afi, safi);
1772
1773 return 0;
1774 }
1775
1776 /* When the peer already belongs to peer group, check the consistency. */
1777 if (peer->af_group[afi][safi])
1778 {
1779 if (strcmp (peer->group->name, group->name) != 0)
1780 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1781
1782 return 0;
1783 }
1784
1785 /* Check current peer group configuration. */
1786 if (peer_group_active (peer)
1787 && strcmp (peer->group->name, group->name) != 0)
1788 return BGP_ERR_PEER_GROUP_MISMATCH;
1789
1790 if (! group->conf->as)
1791 {
1792 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1793 && peer_sort (group->conf) != peer_sort (peer))
1794 {
1795 if (as)
1796 *as = peer->as;
1797 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1798 }
1799
1800 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1801 first_member = 1;
1802 }
1803
1804 peer->af_group[afi][safi] = 1;
1805 peer->afc[afi][safi] = 1;
1806 if (! peer->group)
1807 {
1808 peer->group = group;
paul200df112005-06-01 11:17:05 +00001809
Paul Jakmaca058a32006-09-14 02:58:49 +00001810 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001811 listnode_add (group->peer, peer);
1812 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001813 else
1814 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001815
1816 if (first_member)
1817 {
1818 /* Advertisement-interval reset */
1819 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1820 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1821 else
1822 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1823
1824 /* ebgp-multihop reset */
1825 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1826 group->conf->ttl = 255;
1827
1828 /* local-as reset */
1829 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1830 {
1831 group->conf->change_local_as = 0;
1832 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1833 }
1834 }
paulfee0f4c2004-09-13 05:12:46 +00001835
1836 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1837 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001838 struct listnode *pn;
1839
paulfee0f4c2004-09-13 05:12:46 +00001840 /* If it's not configured as RSERVER_CLIENT in any other address
1841 family, without being member of a peer_group, remove it from
1842 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001843 if (! peer_rsclient_active (peer)
1844 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001845 {
1846 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001847 list_delete_node (bgp->rsclient, pn);
Chris Caputo228da422009-07-18 05:44:03 +00001848
1849 /* Clear our own rsclient rib for this afi/safi. */
1850 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_MY_RSCLIENT);
paul200df112005-06-01 11:17:05 +00001851 }
paulfee0f4c2004-09-13 05:12:46 +00001852
Paul Jakmab608d5b2008-07-02 02:12:07 +00001853 bgp_table_finish (&peer->rib[afi][safi]);
paulfee0f4c2004-09-13 05:12:46 +00001854
1855 /* Import policy. */
1856 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1857 {
1858 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1859 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1860 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1861 }
1862
1863 /* Export policy. */
1864 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1865 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1866 {
1867 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1868 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1869 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1870 }
1871 }
1872
paul718e3742002-12-13 20:15:29 +00001873 peer_group2peer_config_copy (group, peer, afi, safi);
1874
1875 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001876 {
1877 peer->last_reset = PEER_DOWN_RMAP_BIND;
1878 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1879 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1880 }
paul718e3742002-12-13 20:15:29 +00001881 else
1882 BGP_EVENT_ADD (peer, BGP_Stop);
1883
1884 return 0;
1885}
1886
1887int
1888peer_group_unbind (struct bgp *bgp, struct peer *peer,
1889 struct peer_group *group, afi_t afi, safi_t safi)
1890{
1891 if (! peer->af_group[afi][safi])
1892 return 0;
1893
1894 if (group != peer->group)
1895 return BGP_ERR_PEER_GROUP_MISMATCH;
1896
1897 peer->af_group[afi][safi] = 0;
1898 peer->afc[afi][safi] = 0;
1899 peer_af_flag_reset (peer, afi, safi);
1900
paulfee0f4c2004-09-13 05:12:46 +00001901 if (peer->rib[afi][safi])
1902 peer->rib[afi][safi] = NULL;
1903
paul718e3742002-12-13 20:15:29 +00001904 if (! peer_group_active (peer))
1905 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001906 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001907 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001908 listnode_delete (group->peer, peer);
1909 peer->group = NULL;
1910 if (group->conf->as)
1911 {
1912 peer_delete (peer);
1913 return 0;
1914 }
1915 peer_global_config_reset (peer);
1916 }
1917
1918 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001919 {
1920 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1921 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1922 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1923 }
paul718e3742002-12-13 20:15:29 +00001924 else
1925 BGP_EVENT_ADD (peer, BGP_Stop);
1926
1927 return 0;
1928}
1929
1930/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001931static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001932bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001933{
1934 struct bgp *bgp;
1935 afi_t afi;
1936 safi_t safi;
1937
paul200df112005-06-01 11:17:05 +00001938 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1939 return NULL;
1940
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07001941 bgp_lock (bgp);
Paul Jakma6f585442006-10-22 19:13:07 +00001942 bgp->peer_self = peer_new (bgp);
Chris Caputo228da422009-07-18 05:44:03 +00001943 bgp->peer_self->host = XSTRDUP (MTYPE_BGP_PEER_HOST, "Static announcement");
paul718e3742002-12-13 20:15:29 +00001944
1945 bgp->peer = list_new ();
1946 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1947
1948 bgp->group = list_new ();
1949 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1950
paulfee0f4c2004-09-13 05:12:46 +00001951 bgp->rsclient = list_new ();
1952 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1953
paul718e3742002-12-13 20:15:29 +00001954 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1955 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1956 {
Paul Jakma64e580a2006-02-21 01:09:01 +00001957 bgp->route[afi][safi] = bgp_table_init (afi, safi);
1958 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1959 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
Josh Bailey165b5ff2011-07-20 20:43:22 -07001960 bgp->maxpaths[afi][safi].maxpaths_ebgp = BGP_DEFAULT_MAXPATHS;
1961 bgp->maxpaths[afi][safi].maxpaths_ibgp = BGP_DEFAULT_MAXPATHS;
paul718e3742002-12-13 20:15:29 +00001962 }
1963
1964 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1965 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1966 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001967 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1968 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001969
1970 bgp->as = *as;
1971
1972 if (name)
1973 bgp->name = strdup (name);
1974
1975 return bgp;
1976}
1977
1978/* Return first entry of BGP. */
1979struct bgp *
paul94f2b392005-06-28 12:44:16 +00001980bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001981{
1982 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001983 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001984 return NULL;
1985}
1986
1987/* Lookup BGP entry. */
1988struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001989bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001990{
1991 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001992 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001993
paul1eb8ef22005-04-07 07:30:20 +00001994 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001995 if (bgp->as == as
1996 && ((bgp->name == NULL && name == NULL)
1997 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1998 return bgp;
1999 return NULL;
2000}
2001
2002/* Lookup BGP structure by view name. */
2003struct bgp *
paulfd79ac92004-10-13 05:06:08 +00002004bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00002005{
2006 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00002007 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002008
paul1eb8ef22005-04-07 07:30:20 +00002009 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00002010 if ((bgp->name == NULL && name == NULL)
2011 || (bgp->name && name && strcmp (bgp->name, name) == 0))
2012 return bgp;
2013 return NULL;
2014}
2015
2016/* Called from VTY commands. */
2017int
paulfd79ac92004-10-13 05:06:08 +00002018bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00002019{
2020 struct bgp *bgp;
2021
2022 /* Multiple instance check. */
2023 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
2024 {
2025 if (name)
2026 bgp = bgp_lookup_by_name (name);
2027 else
2028 bgp = bgp_get_default ();
2029
2030 /* Already exists. */
2031 if (bgp)
2032 {
2033 if (bgp->as != *as)
2034 {
2035 *as = bgp->as;
2036 return BGP_ERR_INSTANCE_MISMATCH;
2037 }
2038 *bgp_val = bgp;
2039 return 0;
2040 }
2041 }
2042 else
2043 {
2044 /* BGP instance name can not be specified for single instance. */
2045 if (name)
2046 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
2047
2048 /* Get default BGP structure if exists. */
2049 bgp = bgp_get_default ();
2050
2051 if (bgp)
2052 {
2053 if (bgp->as != *as)
2054 {
2055 *as = bgp->as;
2056 return BGP_ERR_AS_MISMATCH;
2057 }
2058 *bgp_val = bgp;
2059 return 0;
2060 }
2061 }
2062
Sergey Y. Afonin1758dba2011-10-27 17:01:11 +04002063 bgp = bgp_create (as, name);
2064 bgp_router_id_set(bgp, &router_id_zebra);
2065 *bgp_val = bgp;
2066
Paul Jakmaad12dde2012-06-13 22:50:07 +01002067 /* Create BGP server socket, if first instance. */
Paul Jakmacccbc012012-06-14 10:40:26 +01002068 if (list_isempty(bm->bgp)
2069 && !bgp_option_check (BGP_OPT_NO_LISTEN))
Paul Jakmaad12dde2012-06-13 22:50:07 +01002070 {
2071 if (bgp_socket (bm->port, bm->address) < 0)
2072 return BGP_ERR_INVALID_VALUE;
2073 }
2074
paul718e3742002-12-13 20:15:29 +00002075 listnode_add (bm->bgp, bgp);
paul718e3742002-12-13 20:15:29 +00002076
2077 return 0;
2078}
2079
2080/* Delete BGP instance. */
2081int
2082bgp_delete (struct bgp *bgp)
2083{
2084 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002085 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002086 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002087 struct listnode *next;
2088 afi_t afi;
paul718e3742002-12-13 20:15:29 +00002089 int i;
2090
2091 /* Delete static route. */
2092 bgp_static_delete (bgp);
2093
2094 /* Unset redistribution. */
2095 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2096 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2097 if (i != ZEBRA_ROUTE_BGP)
2098 bgp_redistribute_unset (bgp, afi, i);
2099
paul1eb8ef22005-04-07 07:30:20 +00002100 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2101 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002102
Chris Caputo228da422009-07-18 05:44:03 +00002103 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
2104 peer_group_delete (group);
2105
2106 assert (listcount (bgp->rsclient) == 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002107
2108 if (bgp->peer_self) {
2109 peer_delete(bgp->peer_self);
2110 bgp->peer_self = NULL;
2111 }
Paul Jakmafd35b942009-07-16 19:27:32 +01002112
2113 /* Remove visibility via the master list - there may however still be
2114 * routes to be processed still referencing the struct bgp.
2115 */
2116 listnode_delete (bm->bgp, bgp);
Stephen Hemmingerd023aec2009-07-21 16:27:21 -07002117 if (list_isempty(bm->bgp))
2118 bgp_close ();
2119
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002120 bgp_unlock(bgp); /* initial reference */
Paul Jakmafd35b942009-07-16 19:27:32 +01002121
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002122 return 0;
2123}
2124
2125static void bgp_free (struct bgp *);
2126
2127void
2128bgp_lock (struct bgp *bgp)
2129{
2130 ++bgp->lock;
2131}
2132
2133void
2134bgp_unlock(struct bgp *bgp)
2135{
Chris Caputo228da422009-07-18 05:44:03 +00002136 assert(bgp->lock > 0);
Stephen Hemminger0088b5d2009-05-21 08:51:03 -07002137 if (--bgp->lock == 0)
2138 bgp_free (bgp);
2139}
2140
2141static void
2142bgp_free (struct bgp *bgp)
2143{
2144 afi_t afi;
2145 safi_t safi;
2146
2147 list_delete (bgp->group);
2148 list_delete (bgp->peer);
paulfee0f4c2004-09-13 05:12:46 +00002149 list_delete (bgp->rsclient);
2150
paul718e3742002-12-13 20:15:29 +00002151 if (bgp->name)
2152 free (bgp->name);
2153
2154 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2155 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2156 {
2157 if (bgp->route[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002158 bgp_table_finish (&bgp->route[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002159 if (bgp->aggregate[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002160 bgp_table_finish (&bgp->aggregate[afi][safi]) ;
paul718e3742002-12-13 20:15:29 +00002161 if (bgp->rib[afi][safi])
Chris Caputo228da422009-07-18 05:44:03 +00002162 bgp_table_finish (&bgp->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00002163 }
2164 XFREE (MTYPE_BGP, bgp);
paul718e3742002-12-13 20:15:29 +00002165}
2166
2167struct peer *
2168peer_lookup (struct bgp *bgp, union sockunion *su)
2169{
2170 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002171 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002172
Steve Hillfc4dc592009-07-28 17:54:35 +01002173 if (bgp != NULL)
Steve Hillfc4dc592009-07-28 17:54:35 +01002174 {
Paul Jakma2158ad22009-07-28 18:10:55 +01002175 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2176 if (sockunion_same (&peer->su, su)
2177 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2178 return peer;
Steve Hillfc4dc592009-07-28 17:54:35 +01002179 }
Steve Hillfc4dc592009-07-28 17:54:35 +01002180 else if (bm->bgp != NULL)
Paul Jakma2158ad22009-07-28 18:10:55 +01002181 {
2182 struct listnode *bgpnode, *nbgpnode;
paul718e3742002-12-13 20:15:29 +00002183
Paul Jakma2158ad22009-07-28 18:10:55 +01002184 for (ALL_LIST_ELEMENTS (bm->bgp, bgpnode, nbgpnode, bgp))
2185 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
2186 if (sockunion_same (&peer->su, su)
2187 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2188 return peer;
paul718e3742002-12-13 20:15:29 +00002189 }
2190 return NULL;
2191}
2192
2193struct peer *
2194peer_lookup_with_open (union sockunion *su, as_t remote_as,
2195 struct in_addr *remote_id, int *as)
2196{
2197 struct peer *peer;
Paul Jakma9d878772009-08-05 16:25:16 +01002198 struct listnode *node;
2199 struct listnode *bgpnode;
paul718e3742002-12-13 20:15:29 +00002200 struct bgp *bgp;
2201
Steve Hillfc4dc592009-07-28 17:54:35 +01002202 if (! bm->bgp)
paul718e3742002-12-13 20:15:29 +00002203 return NULL;
2204
Paul Jakma9d878772009-08-05 16:25:16 +01002205 for (ALL_LIST_ELEMENTS_RO (bm->bgp, bgpnode, bgp))
paul718e3742002-12-13 20:15:29 +00002206 {
Paul Jakma9d878772009-08-05 16:25:16 +01002207 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2208 {
2209 if (sockunion_same (&peer->su, su)
2210 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2211 {
2212 if (peer->as == remote_as
2213 && peer->remote_id.s_addr == remote_id->s_addr)
2214 return peer;
2215 if (peer->as == remote_as)
2216 *as = 1;
2217 }
2218 }
2219
2220 for (ALL_LIST_ELEMENTS_RO (bgp->peer, node, peer))
2221 {
2222 if (sockunion_same (&peer->su, su)
2223 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2224 {
2225 if (peer->as == remote_as
2226 && peer->remote_id.s_addr == 0)
2227 return peer;
2228 if (peer->as == remote_as)
2229 *as = 1;
2230 }
2231 }
paul718e3742002-12-13 20:15:29 +00002232 }
2233 return NULL;
2234}
2235
2236/* If peer is configured at least one address family return 1. */
2237int
2238peer_active (struct peer *peer)
2239{
2240 if (peer->afc[AFI_IP][SAFI_UNICAST]
2241 || peer->afc[AFI_IP][SAFI_MULTICAST]
2242 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2243 || peer->afc[AFI_IP6][SAFI_UNICAST]
2244 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2245 return 1;
2246 return 0;
2247}
2248
2249/* If peer is negotiated at least one address family return 1. */
2250int
2251peer_active_nego (struct peer *peer)
2252{
2253 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2254 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2255 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2256 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2257 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2258 return 1;
2259 return 0;
2260}
2261
2262/* peer_flag_change_type. */
2263enum peer_change_type
2264{
2265 peer_change_none,
2266 peer_change_reset,
2267 peer_change_reset_in,
2268 peer_change_reset_out,
2269};
2270
paul94f2b392005-06-28 12:44:16 +00002271static void
paul718e3742002-12-13 20:15:29 +00002272peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2273 enum peer_change_type type)
2274{
2275 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2276 return;
2277
2278 if (type == peer_change_reset)
2279 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2280 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2281 else if (type == peer_change_reset_in)
2282 {
2283 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2284 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2285 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2286 else
2287 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2288 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2289 }
2290 else if (type == peer_change_reset_out)
2291 bgp_announce_route (peer, afi, safi);
2292}
2293
2294struct peer_flag_action
2295{
2296 /* Peer's flag. */
2297 u_int32_t flag;
2298
2299 /* This flag can be set for peer-group member. */
2300 u_char not_for_member;
2301
2302 /* Action when the flag is changed. */
2303 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002304
2305 /* Peer down cause */
2306 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002307};
2308
Stephen Hemminger03621952009-07-21 16:27:20 -07002309static const struct peer_flag_action peer_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002310 {
2311 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2312 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2313 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2314 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2315 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002316 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002317 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002318 { 0, 0, 0 }
2319 };
2320
Stephen Hemminger03621952009-07-21 16:27:20 -07002321static const struct peer_flag_action peer_af_flag_action_list[] =
paul718e3742002-12-13 20:15:29 +00002322 {
2323 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2324 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2325 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2326 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2327 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2328 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2329 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2330 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2331 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2332 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2333 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2334 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2335 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002336 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002337 { 0, 0, 0 }
2338 };
2339
2340/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002341static int
Stephen Hemminger03621952009-07-21 16:27:20 -07002342peer_flag_action_set (const struct peer_flag_action *action_list, int size,
paul718e3742002-12-13 20:15:29 +00002343 struct peer_flag_action *action, u_int32_t flag)
2344{
2345 int i;
2346 int found = 0;
2347 int reset_in = 0;
2348 int reset_out = 0;
Stephen Hemminger03621952009-07-21 16:27:20 -07002349 const struct peer_flag_action *match = NULL;
paul718e3742002-12-13 20:15:29 +00002350
2351 /* Check peer's frag action. */
2352 for (i = 0; i < size; i++)
2353 {
2354 match = &action_list[i];
2355
2356 if (match->flag == 0)
2357 break;
2358
2359 if (match->flag & flag)
2360 {
2361 found = 1;
2362
2363 if (match->type == peer_change_reset_in)
2364 reset_in = 1;
2365 if (match->type == peer_change_reset_out)
2366 reset_out = 1;
2367 if (match->type == peer_change_reset)
2368 {
2369 reset_in = 1;
2370 reset_out = 1;
2371 }
2372 if (match->not_for_member)
2373 action->not_for_member = 1;
2374 }
2375 }
2376
2377 /* Set peer clear type. */
2378 if (reset_in && reset_out)
2379 action->type = peer_change_reset;
2380 else if (reset_in)
2381 action->type = peer_change_reset_in;
2382 else if (reset_out)
2383 action->type = peer_change_reset_out;
2384 else
2385 action->type = peer_change_none;
2386
2387 return found;
2388}
2389
paul94f2b392005-06-28 12:44:16 +00002390static void
paul718e3742002-12-13 20:15:29 +00002391peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2392{
2393 if (flag == PEER_FLAG_SHUTDOWN)
2394 {
2395 if (CHECK_FLAG (peer->flags, flag))
2396 {
hasso93406d82005-02-02 14:40:33 +00002397 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2398 peer_nsf_stop (peer);
2399
hasso0a486e52005-02-01 20:57:17 +00002400 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2401 if (peer->t_pmax_restart)
2402 {
2403 BGP_TIMER_OFF (peer->t_pmax_restart);
2404 if (BGP_DEBUG (events, EVENTS))
2405 zlog_debug ("%s Maximum-prefix restart timer canceled",
2406 peer->host);
2407 }
2408
hasso93406d82005-02-02 14:40:33 +00002409 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2410 peer_nsf_stop (peer);
2411
paul718e3742002-12-13 20:15:29 +00002412 if (peer->status == Established)
2413 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2414 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2415 else
2416 BGP_EVENT_ADD (peer, BGP_Stop);
2417 }
2418 else
2419 {
2420 peer->v_start = BGP_INIT_START_TIMER;
2421 BGP_EVENT_ADD (peer, BGP_Stop);
2422 }
2423 }
2424 else if (peer->status == Established)
2425 {
hassoc9502432005-02-01 22:01:48 +00002426 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2427 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2428 else if (flag == PEER_FLAG_PASSIVE)
2429 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002430 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002431 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002432
hassoc9502432005-02-01 22:01:48 +00002433 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2434 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002435 }
2436 else
2437 BGP_EVENT_ADD (peer, BGP_Stop);
2438}
2439
2440/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002441static int
paul718e3742002-12-13 20:15:29 +00002442peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2443{
2444 int found;
2445 int size;
2446 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002447 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002448 struct peer_flag_action action;
2449
2450 memset (&action, 0, sizeof (struct peer_flag_action));
2451 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2452
2453 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2454
2455 /* No flag action is found. */
2456 if (! found)
2457 return BGP_ERR_INVALID_FLAG;
2458
2459 /* Not for peer-group member. */
2460 if (action.not_for_member && peer_group_active (peer))
2461 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2462
2463 /* When unset the peer-group member's flag we have to check
2464 peer-group configuration. */
2465 if (! set && peer_group_active (peer))
2466 if (CHECK_FLAG (peer->group->conf->flags, flag))
2467 {
2468 if (flag == PEER_FLAG_SHUTDOWN)
2469 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2470 else
2471 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2472 }
2473
2474 /* Flag conflict check. */
2475 if (set
2476 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2477 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2478 return BGP_ERR_PEER_FLAG_CONFLICT;
2479
2480 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2481 {
2482 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2483 return 0;
2484 if (! set && ! CHECK_FLAG (peer->flags, flag))
2485 return 0;
2486 }
2487
2488 if (set)
2489 SET_FLAG (peer->flags, flag);
2490 else
2491 UNSET_FLAG (peer->flags, flag);
2492
2493 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2494 {
2495 if (action.type == peer_change_reset)
2496 peer_flag_modify_action (peer, flag);
2497
2498 return 0;
2499 }
2500
2501 /* peer-group member updates. */
2502 group = peer->group;
2503
paul1eb8ef22005-04-07 07:30:20 +00002504 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002505 {
2506 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2507 continue;
2508
2509 if (! set && ! CHECK_FLAG (peer->flags, flag))
2510 continue;
2511
2512 if (set)
2513 SET_FLAG (peer->flags, flag);
2514 else
2515 UNSET_FLAG (peer->flags, flag);
2516
2517 if (action.type == peer_change_reset)
2518 peer_flag_modify_action (peer, flag);
2519 }
2520 return 0;
2521}
2522
2523int
2524peer_flag_set (struct peer *peer, u_int32_t flag)
2525{
2526 return peer_flag_modify (peer, flag, 1);
2527}
2528
2529int
2530peer_flag_unset (struct peer *peer, u_int32_t flag)
2531{
2532 return peer_flag_modify (peer, flag, 0);
2533}
2534
paul94f2b392005-06-28 12:44:16 +00002535static int
paul718e3742002-12-13 20:15:29 +00002536peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2537{
2538 if (peer->af_group[afi][safi])
2539 return 1;
2540 return 0;
2541}
2542
paul94f2b392005-06-28 12:44:16 +00002543static int
paul718e3742002-12-13 20:15:29 +00002544peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2545 int set)
2546{
2547 int found;
2548 int size;
paul1eb8ef22005-04-07 07:30:20 +00002549 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002550 struct peer_group *group;
2551 struct peer_flag_action action;
2552
2553 memset (&action, 0, sizeof (struct peer_flag_action));
2554 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2555
2556 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2557
2558 /* No flag action is found. */
2559 if (! found)
2560 return BGP_ERR_INVALID_FLAG;
2561
2562 /* Adress family must be activated. */
2563 if (! peer->afc[afi][safi])
2564 return BGP_ERR_PEER_INACTIVE;
2565
2566 /* Not for peer-group member. */
2567 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2568 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2569
2570 /* Spcecial check for reflector client. */
2571 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2572 && peer_sort (peer) != BGP_PEER_IBGP)
2573 return BGP_ERR_NOT_INTERNAL_PEER;
2574
2575 /* Spcecial check for remove-private-AS. */
2576 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2577 && peer_sort (peer) == BGP_PEER_IBGP)
2578 return BGP_ERR_REMOVE_PRIVATE_AS;
2579
2580 /* When unset the peer-group member's flag we have to check
2581 peer-group configuration. */
2582 if (! set && peer->af_group[afi][safi])
2583 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2584 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2585
2586 /* When current flag configuration is same as requested one. */
2587 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2588 {
2589 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2590 return 0;
2591 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2592 return 0;
2593 }
2594
2595 if (set)
2596 SET_FLAG (peer->af_flags[afi][safi], flag);
2597 else
2598 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2599
2600 /* Execute action when peer is established. */
2601 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2602 && peer->status == Established)
2603 {
2604 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2605 bgp_clear_adj_in (peer, afi, safi);
2606 else
hassoe0701b72004-05-20 09:19:34 +00002607 {
2608 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2609 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2610 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2611 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2612 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2613 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2614 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2615 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2616
2617 peer_change_action (peer, afi, safi, action.type);
2618 }
2619
paul718e3742002-12-13 20:15:29 +00002620 }
2621
2622 /* Peer group member updates. */
2623 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2624 {
2625 group = peer->group;
2626
paul1eb8ef22005-04-07 07:30:20 +00002627 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002628 {
2629 if (! peer->af_group[afi][safi])
2630 continue;
2631
2632 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2633 continue;
2634
2635 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2636 continue;
2637
2638 if (set)
2639 SET_FLAG (peer->af_flags[afi][safi], flag);
2640 else
2641 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2642
2643 if (peer->status == Established)
2644 {
2645 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2646 bgp_clear_adj_in (peer, afi, safi);
2647 else
hassoe0701b72004-05-20 09:19:34 +00002648 {
2649 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2650 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2651 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2652 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2653 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2654 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2655 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2656 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2657
2658 peer_change_action (peer, afi, safi, action.type);
2659 }
paul718e3742002-12-13 20:15:29 +00002660 }
2661 }
2662 }
2663 return 0;
2664}
2665
2666int
2667peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2668{
2669 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2670}
2671
2672int
2673peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2674{
2675 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2676}
2677
2678/* EBGP multihop configuration. */
2679int
2680peer_ebgp_multihop_set (struct peer *peer, int ttl)
2681{
2682 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002683 struct listnode *node, *nnode;
Nick Hilliardfa411a22011-03-23 15:33:17 +00002684 struct peer *peer1;
paul718e3742002-12-13 20:15:29 +00002685
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002686 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002687 return 0;
2688
Nick Hilliardfa411a22011-03-23 15:33:17 +00002689 /* see comment in peer_ttl_security_hops_set() */
2690 if (ttl != MAXTTL)
2691 {
2692 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2693 {
2694 group = peer->group;
2695 if (group->conf->gtsm_hops != 0)
2696 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2697
2698 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
2699 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002700 if (peer1->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00002701 continue;
2702
2703 if (peer1->gtsm_hops != 0)
2704 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2705 }
2706 }
2707 else
2708 {
2709 if (peer->gtsm_hops != 0)
2710 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2711 }
2712 }
2713
paul718e3742002-12-13 20:15:29 +00002714 peer->ttl = ttl;
2715
2716 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2717 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002718 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002719 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002720 }
2721 else
2722 {
2723 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002724 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002725 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002726 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002727 continue;
paul718e3742002-12-13 20:15:29 +00002728
pauleb821182004-05-01 08:44:08 +00002729 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002730
pauleb821182004-05-01 08:44:08 +00002731 if (peer->fd >= 0)
2732 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2733 }
paul718e3742002-12-13 20:15:29 +00002734 }
2735 return 0;
2736}
2737
2738int
2739peer_ebgp_multihop_unset (struct peer *peer)
2740{
2741 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002742 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002743
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002744 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00002745 return 0;
2746
Nick Hilliardfa411a22011-03-23 15:33:17 +00002747 if (peer->gtsm_hops != 0 && peer->ttl != MAXTTL)
2748 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
2749
paul718e3742002-12-13 20:15:29 +00002750 if (peer_group_active (peer))
2751 peer->ttl = peer->group->conf->ttl;
2752 else
2753 peer->ttl = 1;
2754
2755 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2756 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002757 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002758 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002759 }
2760 else
2761 {
2762 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002763 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002764 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00002765 if (peer->sort == BGP_PEER_IBGP)
pauleb821182004-05-01 08:44:08 +00002766 continue;
paul718e3742002-12-13 20:15:29 +00002767
pauleb821182004-05-01 08:44:08 +00002768 peer->ttl = 1;
2769
2770 if (peer->fd >= 0)
2771 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2772 }
paul718e3742002-12-13 20:15:29 +00002773 }
2774 return 0;
2775}
2776
2777/* Neighbor description. */
2778int
2779peer_description_set (struct peer *peer, char *desc)
2780{
2781 if (peer->desc)
2782 XFREE (MTYPE_PEER_DESC, peer->desc);
2783
2784 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2785
2786 return 0;
2787}
2788
2789int
2790peer_description_unset (struct peer *peer)
2791{
2792 if (peer->desc)
2793 XFREE (MTYPE_PEER_DESC, peer->desc);
2794
2795 peer->desc = NULL;
2796
2797 return 0;
2798}
2799
2800/* Neighbor update-source. */
2801int
paulfd79ac92004-10-13 05:06:08 +00002802peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002803{
2804 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002805 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002806
2807 if (peer->update_if)
2808 {
2809 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2810 && strcmp (peer->update_if, ifname) == 0)
2811 return 0;
2812
2813 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2814 peer->update_if = NULL;
2815 }
2816
2817 if (peer->update_source)
2818 {
2819 sockunion_free (peer->update_source);
2820 peer->update_source = NULL;
2821 }
2822
2823 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2824
2825 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2826 {
2827 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002828 {
2829 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2830 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2831 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2832 }
paul718e3742002-12-13 20:15:29 +00002833 else
2834 BGP_EVENT_ADD (peer, BGP_Stop);
2835 return 0;
2836 }
2837
2838 /* peer-group member updates. */
2839 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002840 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002841 {
2842 if (peer->update_if)
2843 {
2844 if (strcmp (peer->update_if, ifname) == 0)
2845 continue;
2846
2847 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2848 peer->update_if = NULL;
2849 }
2850
2851 if (peer->update_source)
2852 {
2853 sockunion_free (peer->update_source);
2854 peer->update_source = NULL;
2855 }
2856
2857 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2858
2859 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002860 {
2861 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2862 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2863 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2864 }
paul718e3742002-12-13 20:15:29 +00002865 else
2866 BGP_EVENT_ADD (peer, BGP_Stop);
2867 }
2868 return 0;
2869}
2870
2871int
2872peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2873{
2874 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002875 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002876
2877 if (peer->update_source)
2878 {
2879 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2880 && sockunion_cmp (peer->update_source, su) == 0)
2881 return 0;
2882 sockunion_free (peer->update_source);
2883 peer->update_source = NULL;
2884 }
2885
2886 if (peer->update_if)
2887 {
2888 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2889 peer->update_if = NULL;
2890 }
2891
2892 peer->update_source = sockunion_dup (su);
2893
2894 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2895 {
2896 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002897 {
2898 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2899 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2900 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2901 }
paul718e3742002-12-13 20:15:29 +00002902 else
2903 BGP_EVENT_ADD (peer, BGP_Stop);
2904 return 0;
2905 }
2906
2907 /* peer-group member updates. */
2908 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002909 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002910 {
2911 if (peer->update_source)
2912 {
2913 if (sockunion_cmp (peer->update_source, su) == 0)
2914 continue;
2915 sockunion_free (peer->update_source);
2916 peer->update_source = NULL;
2917 }
2918
2919 if (peer->update_if)
2920 {
2921 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2922 peer->update_if = NULL;
2923 }
2924
2925 peer->update_source = sockunion_dup (su);
2926
2927 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002928 {
2929 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2930 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2931 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2932 }
paul718e3742002-12-13 20:15:29 +00002933 else
2934 BGP_EVENT_ADD (peer, BGP_Stop);
2935 }
2936 return 0;
2937}
2938
2939int
2940peer_update_source_unset (struct peer *peer)
2941{
2942 union sockunion *su;
2943 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002944 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002945
2946 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2947 && ! peer->update_source
2948 && ! peer->update_if)
2949 return 0;
2950
2951 if (peer->update_source)
2952 {
2953 sockunion_free (peer->update_source);
2954 peer->update_source = NULL;
2955 }
2956 if (peer->update_if)
2957 {
2958 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2959 peer->update_if = NULL;
2960 }
2961
2962 if (peer_group_active (peer))
2963 {
2964 group = peer->group;
2965
2966 if (group->conf->update_source)
2967 {
2968 su = sockunion_dup (group->conf->update_source);
2969 peer->update_source = su;
2970 }
2971 else if (group->conf->update_if)
2972 peer->update_if =
2973 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2974 }
2975
2976 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2977 {
2978 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002979 {
2980 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2981 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2982 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2983 }
paul718e3742002-12-13 20:15:29 +00002984 else
2985 BGP_EVENT_ADD (peer, BGP_Stop);
2986 return 0;
2987 }
2988
2989 /* peer-group member updates. */
2990 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002991 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002992 {
2993 if (! peer->update_source && ! peer->update_if)
2994 continue;
2995
2996 if (peer->update_source)
2997 {
2998 sockunion_free (peer->update_source);
2999 peer->update_source = NULL;
3000 }
3001
3002 if (peer->update_if)
3003 {
3004 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
3005 peer->update_if = NULL;
3006 }
3007
3008 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003009 {
3010 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
3011 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3012 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3013 }
paul718e3742002-12-13 20:15:29 +00003014 else
3015 BGP_EVENT_ADD (peer, BGP_Stop);
3016 }
3017 return 0;
3018}
3019
3020int
3021peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00003022 const char *rmap)
paul718e3742002-12-13 20:15:29 +00003023{
3024 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003025 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003026
3027 /* Adress family must be activated. */
3028 if (! peer->afc[afi][safi])
3029 return BGP_ERR_PEER_INACTIVE;
3030
3031 /* Default originate can't be used for peer group memeber. */
3032 if (peer_is_group_member (peer, afi, safi))
3033 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3034
3035 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
3036 || (rmap && ! peer->default_rmap[afi][safi].name)
3037 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
3038 {
3039 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3040
3041 if (rmap)
3042 {
3043 if (peer->default_rmap[afi][safi].name)
3044 free (peer->default_rmap[afi][safi].name);
3045 peer->default_rmap[afi][safi].name = strdup (rmap);
3046 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3047 }
3048 }
3049
3050 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3051 {
3052 if (peer->status == Established && peer->afc_nego[afi][safi])
3053 bgp_default_originate (peer, afi, safi, 0);
3054 return 0;
3055 }
3056
3057 /* peer-group member updates. */
3058 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003059 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003060 {
3061 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3062
3063 if (rmap)
3064 {
3065 if (peer->default_rmap[afi][safi].name)
3066 free (peer->default_rmap[afi][safi].name);
3067 peer->default_rmap[afi][safi].name = strdup (rmap);
3068 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
3069 }
3070
3071 if (peer->status == Established && peer->afc_nego[afi][safi])
3072 bgp_default_originate (peer, afi, safi, 0);
3073 }
3074 return 0;
3075}
3076
3077int
3078peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
3079{
3080 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003081 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003082
3083 /* Adress family must be activated. */
3084 if (! peer->afc[afi][safi])
3085 return BGP_ERR_PEER_INACTIVE;
3086
3087 /* Default originate can't be used for peer group memeber. */
3088 if (peer_is_group_member (peer, afi, safi))
3089 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3090
3091 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
3092 {
3093 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3094
3095 if (peer->default_rmap[afi][safi].name)
3096 free (peer->default_rmap[afi][safi].name);
3097 peer->default_rmap[afi][safi].name = NULL;
3098 peer->default_rmap[afi][safi].map = NULL;
3099 }
3100
3101 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3102 {
3103 if (peer->status == Established && peer->afc_nego[afi][safi])
3104 bgp_default_originate (peer, afi, safi, 1);
3105 return 0;
3106 }
3107
3108 /* peer-group member updates. */
3109 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003110 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003111 {
3112 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
3113
3114 if (peer->default_rmap[afi][safi].name)
3115 free (peer->default_rmap[afi][safi].name);
3116 peer->default_rmap[afi][safi].name = NULL;
3117 peer->default_rmap[afi][safi].map = NULL;
3118
3119 if (peer->status == Established && peer->afc_nego[afi][safi])
3120 bgp_default_originate (peer, afi, safi, 1);
3121 }
3122 return 0;
3123}
3124
3125int
3126peer_port_set (struct peer *peer, u_int16_t port)
3127{
3128 peer->port = port;
3129 return 0;
3130}
3131
3132int
3133peer_port_unset (struct peer *peer)
3134{
3135 peer->port = BGP_PORT_DEFAULT;
3136 return 0;
3137}
3138
3139/* neighbor weight. */
3140int
3141peer_weight_set (struct peer *peer, u_int16_t weight)
3142{
3143 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003144 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003145
3146 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3147 peer->weight = weight;
3148
3149 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3150 return 0;
3151
3152 /* peer-group member updates. */
3153 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003154 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003155 {
3156 peer->weight = group->conf->weight;
3157 }
3158 return 0;
3159}
3160
3161int
3162peer_weight_unset (struct peer *peer)
3163{
3164 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003165 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003166
3167 /* Set default weight. */
3168 if (peer_group_active (peer))
3169 peer->weight = peer->group->conf->weight;
3170 else
3171 peer->weight = 0;
3172
3173 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3174
3175 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3176 return 0;
3177
3178 /* peer-group member updates. */
3179 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003180 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003181 {
3182 peer->weight = 0;
3183 }
3184 return 0;
3185}
3186
3187int
3188peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3189{
3190 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003191 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003192
3193 /* Not for peer group memeber. */
3194 if (peer_group_active (peer))
3195 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3196
3197 /* keepalive value check. */
3198 if (keepalive > 65535)
3199 return BGP_ERR_INVALID_VALUE;
3200
3201 /* Holdtime value check. */
3202 if (holdtime > 65535)
3203 return BGP_ERR_INVALID_VALUE;
3204
3205 /* Holdtime value must be either 0 or greater than 3. */
3206 if (holdtime < 3 && holdtime != 0)
3207 return BGP_ERR_INVALID_VALUE;
3208
3209 /* Set value to the configuration. */
3210 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3211 peer->holdtime = holdtime;
3212 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3213
3214 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3215 return 0;
3216
3217 /* peer-group member updates. */
3218 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003219 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003220 {
3221 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3222 peer->holdtime = group->conf->holdtime;
3223 peer->keepalive = group->conf->keepalive;
3224 }
3225 return 0;
3226}
3227
3228int
3229peer_timers_unset (struct peer *peer)
3230{
3231 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003232 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003233
3234 if (peer_group_active (peer))
3235 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3236
3237 /* Clear configuration. */
3238 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3239 peer->keepalive = 0;
3240 peer->holdtime = 0;
3241
3242 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3243 return 0;
3244
3245 /* peer-group member updates. */
3246 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003247 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003248 {
3249 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3250 peer->holdtime = 0;
3251 peer->keepalive = 0;
3252 }
3253
3254 return 0;
3255}
3256
3257int
3258peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3259{
3260 if (peer_group_active (peer))
3261 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3262
3263 if (connect > 65535)
3264 return BGP_ERR_INVALID_VALUE;
3265
3266 /* Set value to the configuration. */
3267 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3268 peer->connect = connect;
3269
3270 /* Set value to timer setting. */
3271 peer->v_connect = connect;
3272
3273 return 0;
3274}
3275
3276int
3277peer_timers_connect_unset (struct peer *peer)
3278{
3279 if (peer_group_active (peer))
3280 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3281
3282 /* Clear configuration. */
3283 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3284 peer->connect = 0;
3285
3286 /* Set timer setting to default value. */
3287 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3288
3289 return 0;
3290}
3291
3292int
3293peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3294{
3295 if (peer_group_active (peer))
3296 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3297
3298 if (routeadv > 600)
3299 return BGP_ERR_INVALID_VALUE;
3300
3301 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3302 peer->routeadv = routeadv;
3303 peer->v_routeadv = routeadv;
3304
3305 return 0;
3306}
3307
3308int
3309peer_advertise_interval_unset (struct peer *peer)
3310{
3311 if (peer_group_active (peer))
3312 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3313
3314 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3315 peer->routeadv = 0;
3316
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00003317 if (peer->sort == BGP_PEER_IBGP)
paul718e3742002-12-13 20:15:29 +00003318 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3319 else
3320 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3321
3322 return 0;
3323}
3324
paul718e3742002-12-13 20:15:29 +00003325/* neighbor interface */
3326int
paulfd79ac92004-10-13 05:06:08 +00003327peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003328{
3329 if (peer->ifname)
3330 free (peer->ifname);
3331 peer->ifname = strdup (str);
3332
3333 return 0;
3334}
3335
3336int
3337peer_interface_unset (struct peer *peer)
3338{
3339 if (peer->ifname)
3340 free (peer->ifname);
3341 peer->ifname = NULL;
3342
3343 return 0;
3344}
3345
3346/* Allow-as in. */
3347int
3348peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3349{
3350 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003351 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003352
3353 if (allow_num < 1 || allow_num > 10)
3354 return BGP_ERR_INVALID_VALUE;
3355
3356 if (peer->allowas_in[afi][safi] != allow_num)
3357 {
3358 peer->allowas_in[afi][safi] = allow_num;
3359 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3360 peer_change_action (peer, afi, safi, peer_change_reset_in);
3361 }
3362
3363 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3364 return 0;
3365
3366 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003367 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003368 {
3369 if (peer->allowas_in[afi][safi] != allow_num)
3370 {
3371 peer->allowas_in[afi][safi] = allow_num;
3372 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3373 peer_change_action (peer, afi, safi, peer_change_reset_in);
3374 }
3375
3376 }
3377 return 0;
3378}
3379
3380int
3381peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3382{
3383 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003384 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003385
3386 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3387 {
3388 peer->allowas_in[afi][safi] = 0;
3389 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3390 }
3391
3392 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3393 return 0;
3394
3395 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003396 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003397 {
3398 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3399 {
3400 peer->allowas_in[afi][safi] = 0;
3401 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3402 }
3403 }
3404 return 0;
3405}
3406
3407int
3408peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3409{
3410 struct bgp *bgp = peer->bgp;
3411 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003412 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003413
3414 if (peer_sort (peer) != BGP_PEER_EBGP
3415 && peer_sort (peer) != BGP_PEER_INTERNAL)
3416 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3417
3418 if (bgp->as == as)
3419 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3420
3421 if (peer_group_active (peer))
3422 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3423
3424 if (peer->change_local_as == as &&
3425 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3426 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3427 return 0;
3428
3429 peer->change_local_as = as;
3430 if (no_prepend)
3431 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3432 else
3433 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3434
3435 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3436 {
3437 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003438 {
3439 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3440 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3441 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3442 }
paul718e3742002-12-13 20:15:29 +00003443 else
3444 BGP_EVENT_ADD (peer, BGP_Stop);
3445
3446 return 0;
3447 }
3448
3449 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003450 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003451 {
3452 peer->change_local_as = as;
3453 if (no_prepend)
3454 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3455 else
3456 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3457
3458 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003459 {
3460 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3461 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3462 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3463 }
paul718e3742002-12-13 20:15:29 +00003464 else
3465 BGP_EVENT_ADD (peer, BGP_Stop);
3466 }
3467
3468 return 0;
3469}
3470
3471int
3472peer_local_as_unset (struct peer *peer)
3473{
3474 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003475 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003476
3477 if (peer_group_active (peer))
3478 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3479
3480 if (! peer->change_local_as)
3481 return 0;
3482
3483 peer->change_local_as = 0;
3484 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3485
3486 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3487 {
3488 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003489 {
3490 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3491 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3492 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3493 }
paul718e3742002-12-13 20:15:29 +00003494 else
3495 BGP_EVENT_ADD (peer, BGP_Stop);
3496
3497 return 0;
3498 }
3499
3500 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003501 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003502 {
3503 peer->change_local_as = 0;
3504 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
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
Paul Jakma0df7c912008-07-21 21:02:49 +00003518/* Set password for authenticating with the peer. */
3519int
3520peer_password_set (struct peer *peer, const char *password)
3521{
3522 struct listnode *nn, *nnode;
3523 int len = password ? strlen(password) : 0;
3524 int ret = BGP_SUCCESS;
3525
3526 if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
3527 return BGP_ERR_INVALID_VALUE;
3528
3529 if (peer->password && strcmp (peer->password, password) == 0
3530 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3531 return 0;
3532
3533 if (peer->password)
3534 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3535
3536 peer->password = XSTRDUP (MTYPE_PEER_PASSWORD, password);
3537
3538 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3539 {
3540 if (peer->status == Established)
3541 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3542 else
3543 BGP_EVENT_ADD (peer, BGP_Stop);
3544
3545 return (bgp_md5_set (peer) >= 0) ? BGP_SUCCESS : BGP_ERR_TCPSIG_FAILED;
3546 }
3547
3548 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3549 {
3550 if (peer->password && strcmp (peer->password, password) == 0)
3551 continue;
3552
3553 if (peer->password)
3554 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3555
3556 peer->password = XSTRDUP(MTYPE_PEER_PASSWORD, password);
3557
3558 if (peer->status == Established)
3559 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3560 else
3561 BGP_EVENT_ADD (peer, BGP_Stop);
3562
3563 if (bgp_md5_set (peer) < 0)
3564 ret = BGP_ERR_TCPSIG_FAILED;
3565 }
3566
3567 return ret;
3568}
3569
3570int
3571peer_password_unset (struct peer *peer)
3572{
3573 struct listnode *nn, *nnode;
3574
3575 if (!peer->password
3576 && !CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3577 return 0;
3578
3579 if (!CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3580 {
3581 if (peer_group_active (peer)
3582 && peer->group->conf->password
3583 && strcmp (peer->group->conf->password, peer->password) == 0)
3584 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
3585
3586 if (peer->status == Established)
3587 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3588 else
3589 BGP_EVENT_ADD (peer, BGP_Stop);
3590
3591 if (peer->password)
3592 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3593
3594 peer->password = NULL;
3595
3596 bgp_md5_set (peer);
3597
3598 return 0;
3599 }
3600
3601 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3602 peer->password = NULL;
3603
3604 for (ALL_LIST_ELEMENTS (peer->group->peer, nn, nnode, peer))
3605 {
3606 if (!peer->password)
3607 continue;
3608
3609 if (peer->status == Established)
3610 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3611 else
3612 BGP_EVENT_ADD (peer, BGP_Stop);
3613
3614 XFREE (MTYPE_PEER_PASSWORD, peer->password);
3615 peer->password = NULL;
3616
3617 bgp_md5_set (peer);
3618 }
3619
3620 return 0;
3621}
3622
paul718e3742002-12-13 20:15:29 +00003623/* Set distribute list to the peer. */
3624int
3625peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003626 const char *name)
paul718e3742002-12-13 20:15:29 +00003627{
3628 struct bgp_filter *filter;
3629 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003630 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003631
3632 if (! peer->afc[afi][safi])
3633 return BGP_ERR_PEER_INACTIVE;
3634
3635 if (direct != FILTER_IN && direct != FILTER_OUT)
3636 return BGP_ERR_INVALID_VALUE;
3637
3638 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3639 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3640
3641 filter = &peer->filter[afi][safi];
3642
3643 if (filter->plist[direct].name)
3644 return BGP_ERR_PEER_FILTER_CONFLICT;
3645
3646 if (filter->dlist[direct].name)
3647 free (filter->dlist[direct].name);
3648 filter->dlist[direct].name = strdup (name);
3649 filter->dlist[direct].alist = access_list_lookup (afi, name);
3650
3651 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3652 return 0;
3653
3654 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003655 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003656 {
3657 filter = &peer->filter[afi][safi];
3658
3659 if (! peer->af_group[afi][safi])
3660 continue;
3661
3662 if (filter->dlist[direct].name)
3663 free (filter->dlist[direct].name);
3664 filter->dlist[direct].name = strdup (name);
3665 filter->dlist[direct].alist = access_list_lookup (afi, name);
3666 }
3667
3668 return 0;
3669}
3670
3671int
3672peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3673{
3674 struct bgp_filter *filter;
3675 struct bgp_filter *gfilter;
3676 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003677 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003678
3679 if (! peer->afc[afi][safi])
3680 return BGP_ERR_PEER_INACTIVE;
3681
3682 if (direct != FILTER_IN && direct != FILTER_OUT)
3683 return BGP_ERR_INVALID_VALUE;
3684
3685 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3686 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3687
3688 filter = &peer->filter[afi][safi];
3689
3690 /* apply peer-group filter */
3691 if (peer->af_group[afi][safi])
3692 {
3693 gfilter = &peer->group->conf->filter[afi][safi];
3694
3695 if (gfilter->dlist[direct].name)
3696 {
3697 if (filter->dlist[direct].name)
3698 free (filter->dlist[direct].name);
3699 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3700 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3701 return 0;
3702 }
3703 }
3704
3705 if (filter->dlist[direct].name)
3706 free (filter->dlist[direct].name);
3707 filter->dlist[direct].name = NULL;
3708 filter->dlist[direct].alist = NULL;
3709
3710 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3711 return 0;
3712
3713 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003714 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003715 {
3716 filter = &peer->filter[afi][safi];
3717
3718 if (! peer->af_group[afi][safi])
3719 continue;
3720
3721 if (filter->dlist[direct].name)
3722 free (filter->dlist[direct].name);
3723 filter->dlist[direct].name = NULL;
3724 filter->dlist[direct].alist = NULL;
3725 }
3726
3727 return 0;
3728}
3729
3730/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003731static void
paul718e3742002-12-13 20:15:29 +00003732peer_distribute_update (struct access_list *access)
3733{
3734 afi_t afi;
3735 safi_t safi;
3736 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003737 struct listnode *mnode, *mnnode;
3738 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003739 struct bgp *bgp;
3740 struct peer *peer;
3741 struct peer_group *group;
3742 struct bgp_filter *filter;
3743
paul1eb8ef22005-04-07 07:30:20 +00003744 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003745 {
paul1eb8ef22005-04-07 07:30:20 +00003746 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003747 {
3748 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3749 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3750 {
3751 filter = &peer->filter[afi][safi];
3752
3753 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3754 {
3755 if (filter->dlist[direct].name)
3756 filter->dlist[direct].alist =
3757 access_list_lookup (afi, filter->dlist[direct].name);
3758 else
3759 filter->dlist[direct].alist = NULL;
3760 }
3761 }
3762 }
paul1eb8ef22005-04-07 07:30:20 +00003763 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003764 {
3765 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3766 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3767 {
3768 filter = &group->conf->filter[afi][safi];
3769
3770 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3771 {
3772 if (filter->dlist[direct].name)
3773 filter->dlist[direct].alist =
3774 access_list_lookup (afi, filter->dlist[direct].name);
3775 else
3776 filter->dlist[direct].alist = NULL;
3777 }
3778 }
3779 }
3780 }
3781}
3782
3783/* Set prefix list to the peer. */
3784int
3785peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003786 const char *name)
paul718e3742002-12-13 20:15:29 +00003787{
3788 struct bgp_filter *filter;
3789 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003790 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003791
3792 if (! peer->afc[afi][safi])
3793 return BGP_ERR_PEER_INACTIVE;
3794
3795 if (direct != FILTER_IN && direct != FILTER_OUT)
3796 return BGP_ERR_INVALID_VALUE;
3797
3798 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3799 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3800
3801 filter = &peer->filter[afi][safi];
3802
3803 if (filter->dlist[direct].name)
3804 return BGP_ERR_PEER_FILTER_CONFLICT;
3805
3806 if (filter->plist[direct].name)
3807 free (filter->plist[direct].name);
3808 filter->plist[direct].name = strdup (name);
3809 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3810
3811 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3812 return 0;
3813
3814 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003815 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003816 {
3817 filter = &peer->filter[afi][safi];
3818
3819 if (! peer->af_group[afi][safi])
3820 continue;
3821
3822 if (filter->plist[direct].name)
3823 free (filter->plist[direct].name);
3824 filter->plist[direct].name = strdup (name);
3825 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3826 }
3827 return 0;
3828}
3829
3830int
3831peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3832{
3833 struct bgp_filter *filter;
3834 struct bgp_filter *gfilter;
3835 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003836 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003837
3838 if (! peer->afc[afi][safi])
3839 return BGP_ERR_PEER_INACTIVE;
3840
3841 if (direct != FILTER_IN && direct != FILTER_OUT)
3842 return BGP_ERR_INVALID_VALUE;
3843
3844 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3845 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3846
3847 filter = &peer->filter[afi][safi];
3848
3849 /* apply peer-group filter */
3850 if (peer->af_group[afi][safi])
3851 {
3852 gfilter = &peer->group->conf->filter[afi][safi];
3853
3854 if (gfilter->plist[direct].name)
3855 {
3856 if (filter->plist[direct].name)
3857 free (filter->plist[direct].name);
3858 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3859 filter->plist[direct].plist = gfilter->plist[direct].plist;
3860 return 0;
3861 }
3862 }
3863
3864 if (filter->plist[direct].name)
3865 free (filter->plist[direct].name);
3866 filter->plist[direct].name = NULL;
3867 filter->plist[direct].plist = NULL;
3868
3869 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3870 return 0;
3871
3872 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003873 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003874 {
3875 filter = &peer->filter[afi][safi];
3876
3877 if (! peer->af_group[afi][safi])
3878 continue;
3879
3880 if (filter->plist[direct].name)
3881 free (filter->plist[direct].name);
3882 filter->plist[direct].name = NULL;
3883 filter->plist[direct].plist = NULL;
3884 }
3885
3886 return 0;
3887}
3888
3889/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003890static void
paul718e3742002-12-13 20:15:29 +00003891peer_prefix_list_update (struct prefix_list *plist)
3892{
paul1eb8ef22005-04-07 07:30:20 +00003893 struct listnode *mnode, *mnnode;
3894 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003895 struct bgp *bgp;
3896 struct peer *peer;
3897 struct peer_group *group;
3898 struct bgp_filter *filter;
3899 afi_t afi;
3900 safi_t safi;
3901 int direct;
3902
paul1eb8ef22005-04-07 07:30:20 +00003903 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003904 {
paul1eb8ef22005-04-07 07:30:20 +00003905 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003906 {
3907 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3908 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3909 {
3910 filter = &peer->filter[afi][safi];
3911
3912 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3913 {
3914 if (filter->plist[direct].name)
3915 filter->plist[direct].plist =
3916 prefix_list_lookup (afi, filter->plist[direct].name);
3917 else
3918 filter->plist[direct].plist = NULL;
3919 }
3920 }
3921 }
paul1eb8ef22005-04-07 07:30:20 +00003922 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003923 {
3924 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3925 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3926 {
3927 filter = &group->conf->filter[afi][safi];
3928
3929 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3930 {
3931 if (filter->plist[direct].name)
3932 filter->plist[direct].plist =
3933 prefix_list_lookup (afi, filter->plist[direct].name);
3934 else
3935 filter->plist[direct].plist = NULL;
3936 }
3937 }
3938 }
3939 }
3940}
3941
3942int
3943peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003944 const char *name)
paul718e3742002-12-13 20:15:29 +00003945{
3946 struct bgp_filter *filter;
3947 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003948 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003949
3950 if (! peer->afc[afi][safi])
3951 return BGP_ERR_PEER_INACTIVE;
3952
3953 if (direct != FILTER_IN && direct != FILTER_OUT)
3954 return BGP_ERR_INVALID_VALUE;
3955
3956 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3957 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3958
3959 filter = &peer->filter[afi][safi];
3960
3961 if (filter->aslist[direct].name)
3962 free (filter->aslist[direct].name);
3963 filter->aslist[direct].name = strdup (name);
3964 filter->aslist[direct].aslist = as_list_lookup (name);
3965
3966 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3967 return 0;
3968
3969 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003970 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003971 {
3972 filter = &peer->filter[afi][safi];
3973
3974 if (! peer->af_group[afi][safi])
3975 continue;
3976
3977 if (filter->aslist[direct].name)
3978 free (filter->aslist[direct].name);
3979 filter->aslist[direct].name = strdup (name);
3980 filter->aslist[direct].aslist = as_list_lookup (name);
3981 }
3982 return 0;
3983}
3984
3985int
3986peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3987{
3988 struct bgp_filter *filter;
3989 struct bgp_filter *gfilter;
3990 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003991 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003992
3993 if (! peer->afc[afi][safi])
3994 return BGP_ERR_PEER_INACTIVE;
3995
hassob5f29602005-05-25 21:00:28 +00003996 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00003997 return BGP_ERR_INVALID_VALUE;
3998
hassob5f29602005-05-25 21:00:28 +00003999 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004000 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4001
4002 filter = &peer->filter[afi][safi];
4003
4004 /* apply peer-group filter */
4005 if (peer->af_group[afi][safi])
4006 {
4007 gfilter = &peer->group->conf->filter[afi][safi];
4008
4009 if (gfilter->aslist[direct].name)
4010 {
4011 if (filter->aslist[direct].name)
4012 free (filter->aslist[direct].name);
4013 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
4014 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
4015 return 0;
4016 }
4017 }
4018
4019 if (filter->aslist[direct].name)
4020 free (filter->aslist[direct].name);
4021 filter->aslist[direct].name = NULL;
4022 filter->aslist[direct].aslist = NULL;
4023
4024 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4025 return 0;
4026
4027 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004028 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004029 {
4030 filter = &peer->filter[afi][safi];
4031
4032 if (! peer->af_group[afi][safi])
4033 continue;
4034
4035 if (filter->aslist[direct].name)
4036 free (filter->aslist[direct].name);
4037 filter->aslist[direct].name = NULL;
4038 filter->aslist[direct].aslist = NULL;
4039 }
4040
4041 return 0;
4042}
4043
paul94f2b392005-06-28 12:44:16 +00004044static void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08004045peer_aslist_update (void)
paul718e3742002-12-13 20:15:29 +00004046{
4047 afi_t afi;
4048 safi_t safi;
4049 int direct;
paul1eb8ef22005-04-07 07:30:20 +00004050 struct listnode *mnode, *mnnode;
4051 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004052 struct bgp *bgp;
4053 struct peer *peer;
4054 struct peer_group *group;
4055 struct bgp_filter *filter;
4056
paul1eb8ef22005-04-07 07:30:20 +00004057 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004058 {
paul1eb8ef22005-04-07 07:30:20 +00004059 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004060 {
4061 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4062 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4063 {
4064 filter = &peer->filter[afi][safi];
4065
4066 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4067 {
4068 if (filter->aslist[direct].name)
4069 filter->aslist[direct].aslist =
4070 as_list_lookup (filter->aslist[direct].name);
4071 else
4072 filter->aslist[direct].aslist = NULL;
4073 }
4074 }
4075 }
paul1eb8ef22005-04-07 07:30:20 +00004076 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004077 {
4078 for (afi = AFI_IP; afi < AFI_MAX; afi++)
4079 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
4080 {
4081 filter = &group->conf->filter[afi][safi];
4082
4083 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
4084 {
4085 if (filter->aslist[direct].name)
4086 filter->aslist[direct].aslist =
4087 as_list_lookup (filter->aslist[direct].name);
4088 else
4089 filter->aslist[direct].aslist = NULL;
4090 }
4091 }
4092 }
4093 }
4094}
4095
4096/* Set route-map to the peer. */
4097int
4098peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00004099 const char *name)
paul718e3742002-12-13 20:15:29 +00004100{
4101 struct bgp_filter *filter;
4102 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004103 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004104
4105 if (! peer->afc[afi][safi])
4106 return BGP_ERR_PEER_INACTIVE;
4107
paulfee0f4c2004-09-13 05:12:46 +00004108 if (direct != RMAP_IN && direct != RMAP_OUT &&
4109 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004110 return BGP_ERR_INVALID_VALUE;
4111
paulfee0f4c2004-09-13 05:12:46 +00004112 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4113 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004114 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4115
4116 filter = &peer->filter[afi][safi];
4117
4118 if (filter->map[direct].name)
4119 free (filter->map[direct].name);
4120
4121 filter->map[direct].name = strdup (name);
4122 filter->map[direct].map = route_map_lookup_by_name (name);
4123
4124 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4125 return 0;
4126
4127 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004128 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004129 {
4130 filter = &peer->filter[afi][safi];
4131
4132 if (! peer->af_group[afi][safi])
4133 continue;
4134
4135 if (filter->map[direct].name)
4136 free (filter->map[direct].name);
4137 filter->map[direct].name = strdup (name);
4138 filter->map[direct].map = route_map_lookup_by_name (name);
4139 }
4140 return 0;
4141}
4142
4143/* Unset route-map from the peer. */
4144int
4145peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
4146{
4147 struct bgp_filter *filter;
4148 struct bgp_filter *gfilter;
4149 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004150 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004151
4152 if (! peer->afc[afi][safi])
4153 return BGP_ERR_PEER_INACTIVE;
4154
hassob5f29602005-05-25 21:00:28 +00004155 if (direct != RMAP_IN && direct != RMAP_OUT &&
4156 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00004157 return BGP_ERR_INVALID_VALUE;
4158
hassob5f29602005-05-25 21:00:28 +00004159 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
4160 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00004161 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4162
4163 filter = &peer->filter[afi][safi];
4164
4165 /* apply peer-group filter */
4166 if (peer->af_group[afi][safi])
4167 {
4168 gfilter = &peer->group->conf->filter[afi][safi];
4169
4170 if (gfilter->map[direct].name)
4171 {
4172 if (filter->map[direct].name)
4173 free (filter->map[direct].name);
4174 filter->map[direct].name = strdup (gfilter->map[direct].name);
4175 filter->map[direct].map = gfilter->map[direct].map;
4176 return 0;
4177 }
4178 }
4179
4180 if (filter->map[direct].name)
4181 free (filter->map[direct].name);
4182 filter->map[direct].name = NULL;
4183 filter->map[direct].map = NULL;
4184
4185 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4186 return 0;
4187
4188 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004189 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004190 {
4191 filter = &peer->filter[afi][safi];
4192
4193 if (! peer->af_group[afi][safi])
4194 continue;
4195
4196 if (filter->map[direct].name)
4197 free (filter->map[direct].name);
4198 filter->map[direct].name = NULL;
4199 filter->map[direct].map = NULL;
4200 }
4201 return 0;
4202}
4203
4204/* Set unsuppress-map to the peer. */
4205int
paulfd79ac92004-10-13 05:06:08 +00004206peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
4207 const char *name)
paul718e3742002-12-13 20:15:29 +00004208{
4209 struct bgp_filter *filter;
4210 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004211 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004212
4213 if (! peer->afc[afi][safi])
4214 return BGP_ERR_PEER_INACTIVE;
4215
4216 if (peer_is_group_member (peer, afi, safi))
4217 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4218
4219 filter = &peer->filter[afi][safi];
4220
4221 if (filter->usmap.name)
4222 free (filter->usmap.name);
4223
4224 filter->usmap.name = strdup (name);
4225 filter->usmap.map = route_map_lookup_by_name (name);
4226
4227 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4228 return 0;
4229
4230 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004231 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004232 {
4233 filter = &peer->filter[afi][safi];
4234
4235 if (! peer->af_group[afi][safi])
4236 continue;
4237
4238 if (filter->usmap.name)
4239 free (filter->usmap.name);
4240 filter->usmap.name = strdup (name);
4241 filter->usmap.map = route_map_lookup_by_name (name);
4242 }
4243 return 0;
4244}
4245
4246/* Unset route-map from the peer. */
4247int
4248peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4249{
4250 struct bgp_filter *filter;
4251 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004252 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004253
4254 if (! peer->afc[afi][safi])
4255 return BGP_ERR_PEER_INACTIVE;
4256
4257 if (peer_is_group_member (peer, afi, safi))
4258 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4259
4260 filter = &peer->filter[afi][safi];
4261
4262 if (filter->usmap.name)
4263 free (filter->usmap.name);
4264 filter->usmap.name = NULL;
4265 filter->usmap.map = NULL;
4266
4267 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4268 return 0;
4269
4270 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004271 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004272 {
4273 filter = &peer->filter[afi][safi];
4274
4275 if (! peer->af_group[afi][safi])
4276 continue;
4277
4278 if (filter->usmap.name)
4279 free (filter->usmap.name);
4280 filter->usmap.name = NULL;
4281 filter->usmap.map = NULL;
4282 }
4283 return 0;
4284}
4285
4286int
4287peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004288 u_int32_t max, u_char threshold,
4289 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004290{
4291 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004292 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004293
4294 if (! peer->afc[afi][safi])
4295 return BGP_ERR_PEER_INACTIVE;
4296
4297 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4298 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004299 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004300 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004301 if (warning)
4302 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4303 else
4304 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4305
4306 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4307 return 0;
4308
4309 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004310 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004311 {
4312 if (! peer->af_group[afi][safi])
4313 continue;
4314
4315 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4316 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004317 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004318 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004319 if (warning)
4320 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4321 else
4322 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4323 }
4324 return 0;
4325}
4326
4327int
4328peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4329{
4330 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004331 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004332
4333 if (! peer->afc[afi][safi])
4334 return BGP_ERR_PEER_INACTIVE;
4335
4336 /* apply peer-group config */
4337 if (peer->af_group[afi][safi])
4338 {
4339 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4340 PEER_FLAG_MAX_PREFIX))
4341 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4342 else
4343 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4344
4345 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4346 PEER_FLAG_MAX_PREFIX_WARNING))
4347 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4348 else
4349 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4350
4351 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004352 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004353 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004354 return 0;
4355 }
4356
4357 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4358 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4359 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004360 peer->pmax_threshold[afi][safi] = 0;
4361 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004362
4363 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4364 return 0;
4365
4366 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004367 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004368 {
4369 if (! peer->af_group[afi][safi])
4370 continue;
4371
4372 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4373 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4374 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004375 peer->pmax_threshold[afi][safi] = 0;
4376 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004377 }
4378 return 0;
4379}
4380
Nick Hilliardfa411a22011-03-23 15:33:17 +00004381/* Set # of hops between us and BGP peer. */
4382int
4383peer_ttl_security_hops_set (struct peer *peer, int gtsm_hops)
4384{
4385 struct peer_group *group;
4386 struct listnode *node, *nnode;
4387 struct peer *peer1;
4388 int ret;
4389
4390 zlog_debug ("peer_ttl_security_hops_set: set gtsm_hops to %d for %s", gtsm_hops, peer->host);
4391
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004392 if (peer->sort == BGP_PEER_IBGP)
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004393 return BGP_ERR_NO_IBGP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004394
4395 /* We cannot configure ttl-security hops when ebgp-multihop is already
4396 set. For non peer-groups, the check is simple. For peer-groups, it's
4397 slightly messy, because we need to check both the peer-group structure
4398 and all peer-group members for any trace of ebgp-multihop configuration
4399 before actually applying the ttl-security rules. Cisco really made a
4400 mess of this configuration parameter, and OpenBGPD got it right.
4401 */
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004402
4403 if (peer->gtsm_hops == 0) {
4404 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4405 {
4406 group = peer->group;
4407 if (group->conf->ttl != 1)
4408 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004409
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004410 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
4411 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004412 if (peer1->sort == BGP_PEER_IBGP)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004413 continue;
Nick Hilliardfa411a22011-03-23 15:33:17 +00004414
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004415 if (peer1->ttl != 1)
4416 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4417 }
4418 }
4419 else
4420 {
4421 if (peer->ttl != 1)
4422 return BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK;
4423 }
4424 /* specify MAXTTL on outgoing packets */
4425 ret = peer_ebgp_multihop_set (peer, MAXTTL);
4426 if (ret != 0)
4427 return ret;
4428 }
4429
Nick Hilliardfa411a22011-03-23 15:33:17 +00004430 peer->gtsm_hops = gtsm_hops;
4431
Nick Hilliardfa411a22011-03-23 15:33:17 +00004432 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4433 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004434 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004435 sockopt_minttl (peer->su.sa.sa_family, peer->fd, MAXTTL + 1 - gtsm_hops);
4436 }
4437 else
4438 {
4439 group = peer->group;
4440 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4441 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004442 if (peer->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004443 continue;
4444
4445 peer->gtsm_hops = group->conf->gtsm_hops;
4446
Stephen Hemmingerf5a48272011-03-24 17:30:21 +00004447 /* Change setting of existing peer
4448 * established then change value (may break connectivity)
4449 * not established yet (teardown session and restart)
4450 * no session then do nothing (will get handled by next connection)
4451 */
4452 if (peer->status == Established)
4453 {
4454 if (peer->fd >= 0 && peer->gtsm_hops != 0)
4455 sockopt_minttl (peer->su.sa.sa_family, peer->fd,
4456 MAXTTL + 1 - peer->gtsm_hops);
4457 }
4458 else if (peer->status < Established)
4459 {
4460 if (BGP_DEBUG (events, EVENTS))
4461 zlog_debug ("%s Min-ttl changed", peer->host);
4462 BGP_EVENT_ADD (peer, BGP_Stop);
4463 }
Nick Hilliardfa411a22011-03-23 15:33:17 +00004464 }
4465 }
4466
4467 return 0;
4468}
4469
4470int
4471peer_ttl_security_hops_unset (struct peer *peer)
4472{
4473 struct peer_group *group;
4474 struct listnode *node, *nnode;
4475 struct peer *opeer;
4476
4477 zlog_debug ("peer_ttl_security_hops_unset: set gtsm_hops to zero for %s", peer->host);
4478
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004479 if (peer->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004480 return 0;
4481
4482 /* if a peer-group member, then reset to peer-group default rather than 0 */
4483 if (peer_group_active (peer))
4484 peer->gtsm_hops = peer->group->conf->gtsm_hops;
4485 else
4486 peer->gtsm_hops = 0;
4487
4488 opeer = peer;
4489 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4490 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004491 if (peer->fd >= 0 && peer->sort != BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004492 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4493 }
4494 else
4495 {
4496 group = peer->group;
4497 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
4498 {
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004499 if (peer->sort == BGP_PEER_IBGP)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004500 continue;
4501
4502 peer->gtsm_hops = 0;
4503
4504 if (peer->fd >= 0)
4505 sockopt_minttl (peer->su.sa.sa_family, peer->fd, 0);
4506 }
4507 }
4508
4509 return peer_ebgp_multihop_unset (opeer);
4510}
4511
paul718e3742002-12-13 20:15:29 +00004512int
4513peer_clear (struct peer *peer)
4514{
4515 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4516 {
hasso0a486e52005-02-01 20:57:17 +00004517 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4518 {
4519 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4520 if (peer->t_pmax_restart)
4521 {
4522 BGP_TIMER_OFF (peer->t_pmax_restart);
4523 if (BGP_DEBUG (events, EVENTS))
4524 zlog_debug ("%s Maximum-prefix restart timer canceled",
4525 peer->host);
4526 }
4527 BGP_EVENT_ADD (peer, BGP_Start);
4528 return 0;
4529 }
4530
paul718e3742002-12-13 20:15:29 +00004531 peer->v_start = BGP_INIT_START_TIMER;
4532 if (peer->status == Established)
4533 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4534 BGP_NOTIFY_CEASE_ADMIN_RESET);
4535 else
4536 BGP_EVENT_ADD (peer, BGP_Stop);
4537 }
4538 return 0;
4539}
4540
4541int
4542peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4543 enum bgp_clear_type stype)
4544{
4545 if (peer->status != Established)
4546 return 0;
4547
4548 if (! peer->afc[afi][safi])
4549 return BGP_ERR_AF_UNCONFIGURED;
4550
paulfee0f4c2004-09-13 05:12:46 +00004551 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4552 {
4553 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4554 return 0;
4555 bgp_check_local_routes_rsclient (peer, afi, safi);
4556 bgp_soft_reconfig_rsclient (peer, afi, safi);
4557 }
4558
paul718e3742002-12-13 20:15:29 +00004559 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4560 bgp_announce_route (peer, afi, safi);
4561
4562 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4563 {
4564 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4565 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4566 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4567 {
4568 struct bgp_filter *filter = &peer->filter[afi][safi];
4569 u_char prefix_type;
4570
4571 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4572 prefix_type = ORF_TYPE_PREFIX;
4573 else
4574 prefix_type = ORF_TYPE_PREFIX_OLD;
4575
4576 if (filter->plist[FILTER_IN].plist)
4577 {
4578 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4579 bgp_route_refresh_send (peer, afi, safi,
4580 prefix_type, REFRESH_DEFER, 1);
4581 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4582 REFRESH_IMMEDIATE, 0);
4583 }
4584 else
4585 {
4586 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4587 bgp_route_refresh_send (peer, afi, safi,
4588 prefix_type, REFRESH_IMMEDIATE, 1);
4589 else
4590 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4591 }
4592 return 0;
4593 }
4594 }
4595
4596 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4597 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4598 {
4599 /* If neighbor has soft reconfiguration inbound flag.
4600 Use Adj-RIB-In database. */
4601 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4602 bgp_soft_reconfig_in (peer, afi, safi);
4603 else
4604 {
4605 /* If neighbor has route refresh capability, send route refresh
4606 message to the peer. */
4607 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4608 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4609 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4610 else
4611 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4612 }
4613 }
4614 return 0;
4615}
4616
paulfd79ac92004-10-13 05:06:08 +00004617/* Display peer uptime.*/
4618/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004619char *
4620peer_uptime (time_t uptime2, char *buf, size_t len)
4621{
4622 time_t uptime1;
4623 struct tm *tm;
4624
4625 /* Check buffer length. */
4626 if (len < BGP_UPTIME_LEN)
4627 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004628 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004629 /* XXX: should return status instead of buf... */
4630 snprintf (buf, len, "<error> ");
4631 return buf;
paul718e3742002-12-13 20:15:29 +00004632 }
4633
4634 /* If there is no connection has been done before print `never'. */
4635 if (uptime2 == 0)
4636 {
4637 snprintf (buf, len, "never ");
4638 return buf;
4639 }
4640
4641 /* Get current time. */
Stephen Hemminger65957882010-01-15 16:22:10 +03004642 uptime1 = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00004643 uptime1 -= uptime2;
4644 tm = gmtime (&uptime1);
4645
4646 /* Making formatted timer strings. */
4647#define ONE_DAY_SECOND 60*60*24
4648#define ONE_WEEK_SECOND 60*60*24*7
4649
4650 if (uptime1 < ONE_DAY_SECOND)
4651 snprintf (buf, len, "%02d:%02d:%02d",
4652 tm->tm_hour, tm->tm_min, tm->tm_sec);
4653 else if (uptime1 < ONE_WEEK_SECOND)
4654 snprintf (buf, len, "%dd%02dh%02dm",
4655 tm->tm_yday, tm->tm_hour, tm->tm_min);
4656 else
4657 snprintf (buf, len, "%02dw%dd%02dh",
4658 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4659 return buf;
4660}
4661
paul94f2b392005-06-28 12:44:16 +00004662static void
paul718e3742002-12-13 20:15:29 +00004663bgp_config_write_filter (struct vty *vty, struct peer *peer,
4664 afi_t afi, safi_t safi)
4665{
4666 struct bgp_filter *filter;
4667 struct bgp_filter *gfilter = NULL;
4668 char *addr;
4669 int in = FILTER_IN;
4670 int out = FILTER_OUT;
4671
4672 addr = peer->host;
4673 filter = &peer->filter[afi][safi];
4674 if (peer->af_group[afi][safi])
4675 gfilter = &peer->group->conf->filter[afi][safi];
4676
4677 /* distribute-list. */
4678 if (filter->dlist[in].name)
4679 if (! gfilter || ! gfilter->dlist[in].name
4680 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4681 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4682 filter->dlist[in].name, VTY_NEWLINE);
4683 if (filter->dlist[out].name && ! gfilter)
4684 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4685 filter->dlist[out].name, VTY_NEWLINE);
4686
4687 /* prefix-list. */
4688 if (filter->plist[in].name)
4689 if (! gfilter || ! gfilter->plist[in].name
4690 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4691 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4692 filter->plist[in].name, VTY_NEWLINE);
4693 if (filter->plist[out].name && ! gfilter)
4694 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4695 filter->plist[out].name, VTY_NEWLINE);
4696
4697 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004698 if (filter->map[RMAP_IN].name)
4699 if (! gfilter || ! gfilter->map[RMAP_IN].name
4700 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004701 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004702 filter->map[RMAP_IN].name, VTY_NEWLINE);
4703 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004704 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004705 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4706 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4707 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4708 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4709 if (filter->map[RMAP_EXPORT].name)
4710 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4711 || strcmp (filter->map[RMAP_EXPORT].name,
4712 gfilter->map[RMAP_EXPORT].name) != 0)
4713 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4714 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004715
4716 /* unsuppress-map */
4717 if (filter->usmap.name && ! gfilter)
4718 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4719 filter->usmap.name, VTY_NEWLINE);
4720
4721 /* filter-list. */
4722 if (filter->aslist[in].name)
4723 if (! gfilter || ! gfilter->aslist[in].name
4724 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4725 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4726 filter->aslist[in].name, VTY_NEWLINE);
4727 if (filter->aslist[out].name && ! gfilter)
4728 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4729 filter->aslist[out].name, VTY_NEWLINE);
4730}
4731
4732/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004733static void
paul718e3742002-12-13 20:15:29 +00004734bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4735 struct peer *peer, afi_t afi, safi_t safi)
4736{
paul718e3742002-12-13 20:15:29 +00004737 struct peer *g_peer = NULL;
4738 char buf[SU_ADDRSTRLEN];
4739 char *addr;
4740
paul718e3742002-12-13 20:15:29 +00004741 addr = peer->host;
4742 if (peer_group_active (peer))
4743 g_peer = peer->group->conf;
4744
4745 /************************************
4746 ****** Global to the neighbor ******
4747 ************************************/
4748 if (afi == AFI_IP && safi == SAFI_UNICAST)
4749 {
4750 /* remote-as. */
4751 if (! peer_group_active (peer))
4752 {
4753 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4754 vty_out (vty, " neighbor %s peer-group%s", addr,
4755 VTY_NEWLINE);
4756 if (peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004757 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004758 VTY_NEWLINE);
4759 }
4760 else
4761 {
4762 if (! g_peer->as)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004763 vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as,
paul718e3742002-12-13 20:15:29 +00004764 VTY_NEWLINE);
4765 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4766 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4767 peer->group->name, VTY_NEWLINE);
4768 }
4769
4770 /* local-as. */
4771 if (peer->change_local_as)
4772 if (! peer_group_active (peer))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04004773 vty_out (vty, " neighbor %s local-as %u%s%s", addr,
paul718e3742002-12-13 20:15:29 +00004774 peer->change_local_as,
4775 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4776 " no-prepend" : "", VTY_NEWLINE);
4777
4778 /* Description. */
4779 if (peer->desc)
4780 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4781 VTY_NEWLINE);
4782
4783 /* Shutdown. */
4784 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4785 if (! peer_group_active (peer) ||
4786 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4787 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4788
Paul Jakma0df7c912008-07-21 21:02:49 +00004789 /* Password. */
4790 if (peer->password)
4791 if (!peer_group_active (peer)
4792 || ! g_peer->password
4793 || strcmp (peer->password, g_peer->password) != 0)
4794 vty_out (vty, " neighbor %s password %s%s", addr, peer->password,
4795 VTY_NEWLINE);
4796
paul718e3742002-12-13 20:15:29 +00004797 /* BGP port. */
4798 if (peer->port != BGP_PORT_DEFAULT)
Paul Jakma0df7c912008-07-21 21:02:49 +00004799 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
paul718e3742002-12-13 20:15:29 +00004800 VTY_NEWLINE);
4801
4802 /* Local interface name. */
4803 if (peer->ifname)
4804 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4805 VTY_NEWLINE);
4806
4807 /* Passive. */
4808 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4809 if (! peer_group_active (peer) ||
4810 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4811 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4812
4813 /* EBGP multihop. */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004814 if (peer->sort != BGP_PEER_IBGP && peer->ttl != 1 &&
Nick Hilliardfa411a22011-03-23 15:33:17 +00004815 !(peer->gtsm_hops != 0 && peer->ttl == MAXTTL))
paul718e3742002-12-13 20:15:29 +00004816 if (! peer_group_active (peer) ||
4817 g_peer->ttl != peer->ttl)
4818 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4819 VTY_NEWLINE);
4820
Nick Hilliardfa411a22011-03-23 15:33:17 +00004821 /* ttl-security hops */
Jorge Boncompte [DTI2]6d85b152012-05-07 16:52:54 +00004822 if (peer->sort != BGP_PEER_IBGP && peer->gtsm_hops != 0)
Nick Hilliardfa411a22011-03-23 15:33:17 +00004823 if (! peer_group_active (peer) || g_peer->gtsm_hops != peer->gtsm_hops)
Stephen Hemminger89b6d1f2011-03-24 10:51:59 +00004824 vty_out (vty, " neighbor %s ttl-security hops %d%s", addr,
Nick Hilliardfa411a22011-03-23 15:33:17 +00004825 peer->gtsm_hops, VTY_NEWLINE);
4826
hasso6ffd2072005-02-02 14:50:11 +00004827 /* disable-connected-check. */
4828 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004829 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004830 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4831 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004832
4833 /* Update-source. */
4834 if (peer->update_if)
4835 if (! peer_group_active (peer) || ! g_peer->update_if
4836 || strcmp (g_peer->update_if, peer->update_if) != 0)
4837 vty_out (vty, " neighbor %s update-source %s%s", addr,
4838 peer->update_if, VTY_NEWLINE);
4839 if (peer->update_source)
4840 if (! peer_group_active (peer) || ! g_peer->update_source
4841 || sockunion_cmp (g_peer->update_source,
4842 peer->update_source) != 0)
4843 vty_out (vty, " neighbor %s update-source %s%s", addr,
4844 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4845 VTY_NEWLINE);
4846
paul718e3742002-12-13 20:15:29 +00004847 /* advertisement-interval */
4848 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4849 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4850 addr, peer->v_routeadv, VTY_NEWLINE);
4851
4852 /* timers. */
4853 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4854 && ! peer_group_active (peer))
4855 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4856 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4857
4858 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4859 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4860 peer->connect, VTY_NEWLINE);
4861
4862 /* Default weight. */
4863 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4864 if (! peer_group_active (peer) ||
4865 g_peer->weight != peer->weight)
4866 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4867 VTY_NEWLINE);
4868
paul718e3742002-12-13 20:15:29 +00004869 /* Dynamic capability. */
4870 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4871 if (! peer_group_active (peer) ||
4872 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4873 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4874 VTY_NEWLINE);
4875
4876 /* dont capability negotiation. */
4877 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4878 if (! peer_group_active (peer) ||
4879 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4880 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4881 VTY_NEWLINE);
4882
4883 /* override capability negotiation. */
4884 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4885 if (! peer_group_active (peer) ||
4886 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4887 vty_out (vty, " neighbor %s override-capability%s", addr,
4888 VTY_NEWLINE);
4889
4890 /* strict capability negotiation. */
4891 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4892 if (! peer_group_active (peer) ||
4893 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4894 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4895 VTY_NEWLINE);
4896
4897 if (! peer_group_active (peer))
4898 {
4899 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4900 {
4901 if (peer->afc[AFI_IP][SAFI_UNICAST])
4902 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4903 }
4904 else
4905 {
4906 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4907 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4908 }
4909 }
4910 }
4911
4912
4913 /************************************
4914 ****** Per AF to the neighbor ******
4915 ************************************/
4916
4917 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4918 {
4919 if (peer->af_group[afi][safi])
4920 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4921 peer->group->name, VTY_NEWLINE);
4922 else
4923 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4924 }
4925
4926 /* ORF capability. */
4927 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4928 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4929 if (! peer->af_group[afi][safi])
4930 {
4931 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4932
4933 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4934 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4935 vty_out (vty, " both");
4936 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4937 vty_out (vty, " send");
4938 else
4939 vty_out (vty, " receive");
4940 vty_out (vty, "%s", VTY_NEWLINE);
4941 }
4942
4943 /* Route reflector client. */
4944 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4945 && ! peer->af_group[afi][safi])
4946 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4947 VTY_NEWLINE);
4948
4949 /* Nexthop self. */
4950 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4951 && ! peer->af_group[afi][safi])
4952 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4953
4954 /* Remove private AS. */
4955 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4956 && ! peer->af_group[afi][safi])
4957 vty_out (vty, " neighbor %s remove-private-AS%s",
4958 addr, VTY_NEWLINE);
4959
4960 /* send-community print. */
4961 if (! peer->af_group[afi][safi])
4962 {
4963 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4964 {
4965 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4966 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4967 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4968 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4969 vty_out (vty, " neighbor %s send-community extended%s",
4970 addr, VTY_NEWLINE);
4971 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4972 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4973 }
4974 else
4975 {
4976 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4977 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4978 vty_out (vty, " no neighbor %s send-community both%s",
4979 addr, VTY_NEWLINE);
4980 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4981 vty_out (vty, " no neighbor %s send-community extended%s",
4982 addr, VTY_NEWLINE);
4983 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4984 vty_out (vty, " no neighbor %s send-community%s",
4985 addr, VTY_NEWLINE);
4986 }
4987 }
4988
4989 /* Default information */
4990 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4991 && ! peer->af_group[afi][safi])
4992 {
4993 vty_out (vty, " neighbor %s default-originate", addr);
4994 if (peer->default_rmap[afi][safi].name)
4995 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4996 vty_out (vty, "%s", VTY_NEWLINE);
4997 }
4998
4999 /* Soft reconfiguration inbound. */
5000 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5001 if (! peer->af_group[afi][safi] ||
5002 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
5003 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
5004 VTY_NEWLINE);
5005
5006 /* maximum-prefix. */
5007 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
5008 if (! peer->af_group[afi][safi]
5009 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00005010 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00005011 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
5012 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00005013 {
hasso0a486e52005-02-01 20:57:17 +00005014 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
5015 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
5016 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
5017 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
5018 vty_out (vty, " warning-only");
5019 if (peer->pmax_restart[afi][safi])
5020 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
5021 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00005022 }
paul718e3742002-12-13 20:15:29 +00005023
5024 /* Route server client. */
5025 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
5026 && ! peer->af_group[afi][safi])
5027 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
5028
Dylan Hall3cf12882011-10-27 15:28:17 +04005029 /* Nexthop-local unchanged. */
5030 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED)
5031 && ! peer->af_group[afi][safi])
5032 vty_out (vty, " neighbor %s nexthop-local unchanged%s", addr, VTY_NEWLINE);
5033
paul718e3742002-12-13 20:15:29 +00005034 /* Allow AS in. */
5035 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
5036 if (! peer_group_active (peer)
5037 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
5038 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
5039 {
5040 if (peer->allowas_in[afi][safi] == 3)
5041 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
5042 else
5043 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
5044 peer->allowas_in[afi][safi], VTY_NEWLINE);
5045 }
5046
5047 /* Filter. */
5048 bgp_config_write_filter (vty, peer, afi, safi);
5049
5050 /* atribute-unchanged. */
5051 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5052 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5053 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5054 && ! peer->af_group[afi][safi])
5055 {
5056 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
5057 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
5058 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
5059 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
5060 else
5061 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
5062 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
5063 " as-path" : "",
5064 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
5065 " next-hop" : "",
5066 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
5067 " med" : "", VTY_NEWLINE);
5068 }
5069}
5070
5071/* Display "address-family" configuration header. */
5072void
5073bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
5074 int *write)
5075{
5076 if (*write)
5077 return;
5078
5079 if (afi == AFI_IP && safi == SAFI_UNICAST)
5080 return;
5081
5082 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
5083
5084 if (afi == AFI_IP)
5085 {
5086 if (safi == SAFI_MULTICAST)
5087 vty_out (vty, "ipv4 multicast");
5088 else if (safi == SAFI_MPLS_VPN)
5089 vty_out (vty, "vpnv4 unicast");
5090 }
5091 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00005092 {
5093 vty_out (vty, "ipv6");
5094
5095 if (safi == SAFI_MULTICAST)
5096 vty_out (vty, " multicast");
5097 }
paul718e3742002-12-13 20:15:29 +00005098
5099 vty_out (vty, "%s", VTY_NEWLINE);
5100
5101 *write = 1;
5102}
5103
5104/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00005105static int
paul718e3742002-12-13 20:15:29 +00005106bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
5107 safi_t safi)
5108{
5109 int write = 0;
5110 struct peer *peer;
5111 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00005112 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00005113
5114 bgp_config_write_network (vty, bgp, afi, safi, &write);
5115
5116 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
5117
paul1eb8ef22005-04-07 07:30:20 +00005118 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005119 {
5120 if (group->conf->afc[afi][safi])
5121 {
5122 bgp_config_write_family_header (vty, afi, safi, &write);
5123 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
5124 }
5125 }
paul1eb8ef22005-04-07 07:30:20 +00005126 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005127 {
5128 if (peer->afc[afi][safi])
5129 {
5130 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5131 {
5132 bgp_config_write_family_header (vty, afi, safi, &write);
5133 bgp_config_write_peer (vty, bgp, peer, afi, safi);
5134 }
5135 }
5136 }
Josh Bailey165b5ff2011-07-20 20:43:22 -07005137
5138 bgp_config_write_maxpaths (vty, bgp, afi, safi, &write);
5139
paul718e3742002-12-13 20:15:29 +00005140 if (write)
5141 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
5142
5143 return write;
5144}
5145
5146int
5147bgp_config_write (struct vty *vty)
5148{
5149 int write = 0;
5150 struct bgp *bgp;
5151 struct peer_group *group;
5152 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005153 struct listnode *node, *nnode;
5154 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00005155
5156 /* BGP Multiple instance. */
5157 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5158 {
5159 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
5160 write++;
5161 }
5162
5163 /* BGP Config type. */
5164 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5165 {
5166 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
5167 write++;
5168 }
5169
5170 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005171 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00005172 {
5173 if (write)
5174 vty_out (vty, "!%s", VTY_NEWLINE);
5175
5176 /* Router bgp ASN */
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005177 vty_out (vty, "router bgp %u", bgp->as);
paul718e3742002-12-13 20:15:29 +00005178
5179 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
5180 {
5181 if (bgp->name)
5182 vty_out (vty, " view %s", bgp->name);
5183 }
5184 vty_out (vty, "%s", VTY_NEWLINE);
5185
5186 /* No Synchronization */
5187 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5188 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
5189
5190 /* BGP fast-external-failover. */
5191 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
5192 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
5193
5194 /* BGP router ID. */
5195 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
5196 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
5197 VTY_NEWLINE);
5198
paul848973c2003-08-13 00:32:49 +00005199 /* BGP log-neighbor-changes. */
5200 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
5201 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
5202
paul718e3742002-12-13 20:15:29 +00005203 /* BGP configuration. */
5204 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
5205 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
5206
5207 /* BGP default ipv4-unicast. */
5208 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
5209 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
5210
5211 /* BGP default local-preference. */
5212 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
5213 vty_out (vty, " bgp default local-preference %d%s",
5214 bgp->default_local_pref, VTY_NEWLINE);
5215
5216 /* BGP client-to-client reflection. */
5217 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
5218 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
5219
5220 /* BGP cluster ID. */
5221 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
5222 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
5223 VTY_NEWLINE);
5224
hassoe0701b72004-05-20 09:19:34 +00005225 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00005226 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00005227 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
5228 VTY_NEWLINE);
5229
5230 /* Confederation peer */
5231 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00005232 {
hassoe0701b72004-05-20 09:19:34 +00005233 int i;
paul718e3742002-12-13 20:15:29 +00005234
hassoe0701b72004-05-20 09:19:34 +00005235 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00005236
hassoe0701b72004-05-20 09:19:34 +00005237 for (i = 0; i < bgp->confed_peers_cnt; i++)
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04005238 vty_out(vty, " %u", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00005239
hassoe0701b72004-05-20 09:19:34 +00005240 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005241 }
5242
5243 /* BGP enforce-first-as. */
5244 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
5245 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
5246
5247 /* BGP deterministic-med. */
5248 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
5249 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005250
5251 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00005252 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
5253 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
5254 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00005255 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
5256 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
5257
paul718e3742002-12-13 20:15:29 +00005258 /* BGP bestpath method. */
5259 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
5260 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00005261 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
5262 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00005263 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
5264 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
5265 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
5266 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5267 {
5268 vty_out (vty, " bgp bestpath med");
5269 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
5270 vty_out (vty, " confed");
5271 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
5272 vty_out (vty, " missing-as-worst");
5273 vty_out (vty, "%s", VTY_NEWLINE);
5274 }
5275
5276 /* BGP network import check. */
5277 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
5278 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
5279
5280 /* BGP scan interval. */
5281 bgp_config_write_scan_time (vty);
5282
5283 /* BGP flag dampening. */
5284 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
5285 BGP_CONFIG_DAMPENING))
5286 bgp_config_write_damp (vty);
5287
5288 /* BGP static route configuration. */
5289 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5290
5291 /* BGP redistribute configuration. */
5292 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5293
5294 /* BGP timers configuration. */
5295 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
5296 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
5297 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
5298 bgp->default_holdtime, VTY_NEWLINE);
5299
5300 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00005301 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00005302 {
5303 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
5304 }
5305
5306 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00005307 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00005308 {
5309 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
5310 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
5311 }
5312
Josh Bailey165b5ff2011-07-20 20:43:22 -07005313 /* maximum-paths */
5314 bgp_config_write_maxpaths (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
5315
paul718e3742002-12-13 20:15:29 +00005316 /* Distance configuration. */
5317 bgp_config_write_distance (vty, bgp);
5318
5319 /* No auto-summary */
5320 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
5321 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
5322
5323 /* IPv4 multicast configuration. */
5324 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
5325
5326 /* IPv4 VPN configuration. */
5327 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
5328
5329 /* IPv6 unicast configuration. */
5330 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
5331
Paul Jakma37a217a2007-04-10 19:20:29 +00005332 /* IPv6 multicast configuration. */
5333 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
5334
paul718e3742002-12-13 20:15:29 +00005335 write++;
5336 }
5337 return write;
5338}
5339
5340void
paul94f2b392005-06-28 12:44:16 +00005341bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00005342{
5343 memset (&bgp_master, 0, sizeof (struct bgp_master));
5344
5345 bm = &bgp_master;
5346 bm->bgp = list_new ();
Paul Jakma0df7c912008-07-21 21:02:49 +00005347 bm->listen_sockets = list_new ();
paul718e3742002-12-13 20:15:29 +00005348 bm->port = BGP_PORT_DEFAULT;
5349 bm->master = thread_master_create ();
Stephen Hemminger65957882010-01-15 16:22:10 +03005350 bm->start_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00005351}
paul200df112005-06-01 11:17:05 +00005352
paul718e3742002-12-13 20:15:29 +00005353
5354void
paul94f2b392005-06-28 12:44:16 +00005355bgp_init (void)
paul718e3742002-12-13 20:15:29 +00005356{
paul718e3742002-12-13 20:15:29 +00005357 /* BGP VTY commands installation. */
5358 bgp_vty_init ();
5359
paul718e3742002-12-13 20:15:29 +00005360 /* Init zebra. */
5361 bgp_zebra_init ();
5362
5363 /* BGP inits. */
5364 bgp_attr_init ();
5365 bgp_debug_init ();
5366 bgp_dump_init ();
5367 bgp_route_init ();
5368 bgp_route_map_init ();
Jorge Boncompte [DTI2]10f9bf32012-05-07 16:52:52 +00005369 bgp_address_init ();
paul718e3742002-12-13 20:15:29 +00005370 bgp_scan_init ();
5371 bgp_mplsvpn_init ();
5372
5373 /* Access list initialize. */
5374 access_list_init ();
5375 access_list_add_hook (peer_distribute_update);
5376 access_list_delete_hook (peer_distribute_update);
5377
5378 /* Filter list initialize. */
5379 bgp_filter_init ();
5380 as_list_add_hook (peer_aslist_update);
5381 as_list_delete_hook (peer_aslist_update);
5382
5383 /* Prefix list initialize.*/
5384 prefix_list_init ();
5385 prefix_list_add_hook (peer_prefix_list_update);
5386 prefix_list_delete_hook (peer_prefix_list_update);
5387
5388 /* Community list initialize. */
5389 bgp_clist = community_list_init ();
5390
5391#ifdef HAVE_SNMP
5392 bgp_snmp_init ();
5393#endif /* HAVE_SNMP */
5394}
paul545acaf2004-04-20 15:13:15 +00005395
5396void
Stephen Hemminger66e5cd82009-02-09 10:14:16 -08005397bgp_terminate (void)
paul545acaf2004-04-20 15:13:15 +00005398{
paul545acaf2004-04-20 15:13:15 +00005399 struct bgp *bgp;
5400 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005401 struct listnode *node, *nnode;
5402 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005403
paul1eb8ef22005-04-07 07:30:20 +00005404 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5405 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005406 if (peer->status == Established)
5407 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5408 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005409
paul545acaf2004-04-20 15:13:15 +00005410 bgp_cleanup_routes ();
Steve Hillacde4b82009-06-02 14:28:16 +01005411
paule210cf92005-06-15 19:15:35 +00005412 if (bm->process_main_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005413 {
5414 work_queue_free (bm->process_main_queue);
5415 bm->process_main_queue = NULL;
5416 }
paule210cf92005-06-15 19:15:35 +00005417 if (bm->process_rsclient_queue)
Steve Hillacde4b82009-06-02 14:28:16 +01005418 {
5419 work_queue_free (bm->process_rsclient_queue);
5420 bm->process_rsclient_queue = NULL;
5421 }
paul545acaf2004-04-20 15:13:15 +00005422}