blob: 89f82628a30475972aa23df84b4631b0874860ff [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"
60#ifdef HAVE_SNMP
61#include "bgpd/bgp_snmp.h"
62#endif /* HAVE_SNMP */
63
64/* BGP process wide configuration. */
65static struct bgp_master bgp_master;
66
hasso18a6dce2004-10-03 18:18:34 +000067extern struct in_addr router_id_zebra;
68
paul718e3742002-12-13 20:15:29 +000069/* BGP process wide configuration pointer to export. */
70struct bgp_master *bm;
71
72/* BGP community-list. */
73struct community_list_handler *bgp_clist;
74
75/* BGP global flag manipulation. */
76int
77bgp_option_set (int flag)
78{
79 switch (flag)
80 {
81 case BGP_OPT_NO_FIB:
82 case BGP_OPT_MULTIPLE_INSTANCE:
83 case BGP_OPT_CONFIG_CISCO:
84 SET_FLAG (bm->options, flag);
85 break;
86 default:
87 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +000088 }
89 return 0;
90}
91
92int
93bgp_option_unset (int flag)
94{
95 switch (flag)
96 {
97 case BGP_OPT_MULTIPLE_INSTANCE:
98 if (listcount (bm->bgp) > 1)
99 return BGP_ERR_MULTIPLE_INSTANCE_USED;
100 /* Fall through. */
101 case BGP_OPT_NO_FIB:
102 case BGP_OPT_CONFIG_CISCO:
103 UNSET_FLAG (bm->options, flag);
104 break;
105 default:
106 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +0000107 }
108 return 0;
109}
110
111int
112bgp_option_check (int flag)
113{
114 return CHECK_FLAG (bm->options, flag);
115}
116
117/* BGP flag manipulation. */
118int
119bgp_flag_set (struct bgp *bgp, int flag)
120{
121 SET_FLAG (bgp->flags, flag);
122 return 0;
123}
124
125int
126bgp_flag_unset (struct bgp *bgp, int flag)
127{
128 UNSET_FLAG (bgp->flags, flag);
129 return 0;
130}
131
132int
133bgp_flag_check (struct bgp *bgp, int flag)
134{
135 return CHECK_FLAG (bgp->flags, flag);
136}
137
138/* Internal function to set BGP structure configureation flag. */
139static void
140bgp_config_set (struct bgp *bgp, int config)
141{
142 SET_FLAG (bgp->config, config);
143}
144
145static void
146bgp_config_unset (struct bgp *bgp, int config)
147{
148 UNSET_FLAG (bgp->config, config);
149}
150
151static int
152bgp_config_check (struct bgp *bgp, int config)
153{
154 return CHECK_FLAG (bgp->config, config);
155}
156
157/* Set BGP router identifier. */
158int
159bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
160{
161 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000162 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000163
164 if (bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID)
165 && IPV4_ADDR_SAME (&bgp->router_id, id))
166 return 0;
167
168 IPV4_ADDR_COPY (&bgp->router_id, id);
169 bgp_config_set (bgp, BGP_CONFIG_ROUTER_ID);
170
171 /* Set all peer's local identifier with this value. */
paul1eb8ef22005-04-07 07:30:20 +0000172 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000173 {
174 IPV4_ADDR_COPY (&peer->local_id, id);
175
176 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000177 {
178 peer->last_reset = PEER_DOWN_RID_CHANGE;
179 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
180 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
181 }
paul718e3742002-12-13 20:15:29 +0000182 }
183 return 0;
184}
185
paul718e3742002-12-13 20:15:29 +0000186/* BGP's cluster-id control. */
187int
188bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
189{
190 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000191 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000192
193 if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)
194 && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id))
195 return 0;
196
197 IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id);
198 bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID);
199
200 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000201 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000202 {
203 if (peer_sort (peer) != BGP_PEER_IBGP)
204 continue;
205
206 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000207 {
208 peer->last_reset = PEER_DOWN_CLID_CHANGE;
209 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
210 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
211 }
paul718e3742002-12-13 20:15:29 +0000212 }
213 return 0;
214}
215
216int
217bgp_cluster_id_unset (struct bgp *bgp)
218{
219 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000220 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000221
222 if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID))
223 return 0;
224
225 bgp->cluster_id.s_addr = 0;
226 bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID);
227
228 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000229 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000230 {
231 if (peer_sort (peer) != BGP_PEER_IBGP)
232 continue;
233
234 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000235 {
236 peer->last_reset = PEER_DOWN_CLID_CHANGE;
237 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
238 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
239 }
paul718e3742002-12-13 20:15:29 +0000240 }
241 return 0;
242}
243
244/* BGP timer configuration. */
245int
246bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
247{
248 bgp->default_keepalive = (keepalive < holdtime / 3
249 ? keepalive : holdtime / 3);
250 bgp->default_holdtime = holdtime;
251
252 return 0;
253}
254
255int
256bgp_timers_unset (struct bgp *bgp)
257{
258 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
259 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
260
261 return 0;
262}
263
264/* BGP confederation configuration. */
265int
266bgp_confederation_id_set (struct bgp *bgp, as_t as)
267{
268 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000269 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000270 int already_confed;
271
272 if (as == 0)
273 return BGP_ERR_INVALID_AS;
274
275 /* Remember - were we doing confederation before? */
276 already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);
277 bgp->confed_id = as;
278 bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);
279
280 /* If we were doing confederation already, this is just an external
281 AS change. Just Reset EBGP sessions, not CONFED sessions. If we
282 were not doing confederation before, reset all EBGP sessions. */
paul1eb8ef22005-04-07 07:30:20 +0000283 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000284 {
285 /* We're looking for peers who's AS is not local or part of our
286 confederation. */
287 if (already_confed)
288 {
289 if (peer_sort (peer) == BGP_PEER_EBGP)
290 {
291 peer->local_as = as;
292 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000293 {
294 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
295 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
296 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
297 }
298
paul718e3742002-12-13 20:15:29 +0000299 else
300 BGP_EVENT_ADD (peer, BGP_Stop);
301 }
302 }
303 else
304 {
305 /* Not doign confederation before, so reset every non-local
306 session */
307 if (peer_sort (peer) != BGP_PEER_IBGP)
308 {
309 /* Reset the local_as to be our EBGP one */
310 if (peer_sort (peer) == BGP_PEER_EBGP)
311 peer->local_as = as;
312 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000313 {
314 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
315 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
316 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
317 }
paul718e3742002-12-13 20:15:29 +0000318 else
319 BGP_EVENT_ADD (peer, BGP_Stop);
320 }
321 }
322 }
323 return 0;
324}
325
326int
327bgp_confederation_id_unset (struct bgp *bgp)
328{
329 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000330 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000331
332 bgp->confed_id = 0;
333 bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
334
paul1eb8ef22005-04-07 07:30:20 +0000335 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000336 {
337 /* We're looking for peers who's AS is not local */
338 if (peer_sort (peer) != BGP_PEER_IBGP)
339 {
340 peer->local_as = bgp->as;
341 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000342 {
343 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
344 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
345 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
346 }
347
paul718e3742002-12-13 20:15:29 +0000348 else
349 BGP_EVENT_ADD (peer, BGP_Stop);
350 }
351 }
352 return 0;
353}
354
355/* Is an AS part of the confed or not? */
356int
357bgp_confederation_peers_check (struct bgp *bgp, as_t as)
358{
359 int i;
360
361 if (! bgp)
362 return 0;
363
364 for (i = 0; i < bgp->confed_peers_cnt; i++)
365 if (bgp->confed_peers[i] == as)
366 return 1;
367
368 return 0;
369}
370
371/* Add an AS to the confederation set. */
372int
373bgp_confederation_peers_add (struct bgp *bgp, as_t as)
374{
375 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000376 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000377
378 if (! bgp)
379 return BGP_ERR_INVALID_BGP;
380
381 if (bgp->as == as)
382 return BGP_ERR_INVALID_AS;
383
384 if (bgp_confederation_peers_check (bgp, as))
385 return -1;
386
387 if (bgp->confed_peers)
388 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
389 bgp->confed_peers,
390 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
391 else
392 bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST,
393 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
394
395 bgp->confed_peers[bgp->confed_peers_cnt] = as;
396 bgp->confed_peers_cnt++;
397
398 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
399 {
paul1eb8ef22005-04-07 07:30:20 +0000400 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000401 {
402 if (peer->as == as)
403 {
404 peer->local_as = bgp->as;
405 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000406 {
407 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
408 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
409 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
410 }
paul718e3742002-12-13 20:15:29 +0000411 else
412 BGP_EVENT_ADD (peer, BGP_Stop);
413 }
414 }
415 }
416 return 0;
417}
418
419/* Delete an AS from the confederation set. */
420int
421bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
422{
423 int i;
424 int j;
425 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000426 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000427
428 if (! bgp)
429 return -1;
430
431 if (! bgp_confederation_peers_check (bgp, as))
432 return -1;
433
434 for (i = 0; i < bgp->confed_peers_cnt; i++)
435 if (bgp->confed_peers[i] == as)
436 for(j = i + 1; j < bgp->confed_peers_cnt; j++)
437 bgp->confed_peers[j - 1] = bgp->confed_peers[j];
438
439 bgp->confed_peers_cnt--;
440
441 if (bgp->confed_peers_cnt == 0)
442 {
443 if (bgp->confed_peers)
444 XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
445 bgp->confed_peers = NULL;
446 }
447 else
448 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
449 bgp->confed_peers,
450 bgp->confed_peers_cnt * sizeof (as_t));
451
452 /* Now reset any peer who's remote AS has just been removed from the
453 CONFED */
454 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
455 {
paul1eb8ef22005-04-07 07:30:20 +0000456 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000457 {
458 if (peer->as == as)
459 {
460 peer->local_as = bgp->confed_id;
461 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000462 {
463 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
464 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
465 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
466 }
paul718e3742002-12-13 20:15:29 +0000467 else
468 BGP_EVENT_ADD (peer, BGP_Stop);
469 }
470 }
471 }
472
473 return 0;
474}
475
476/* Local preference configuration. */
477int
478bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
479{
480 if (! bgp)
481 return -1;
482
paul718e3742002-12-13 20:15:29 +0000483 bgp->default_local_pref = local_pref;
484
485 return 0;
486}
487
488int
489bgp_default_local_preference_unset (struct bgp *bgp)
490{
491 if (! bgp)
492 return -1;
493
paul718e3742002-12-13 20:15:29 +0000494 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
495
496 return 0;
497}
498
paulfee0f4c2004-09-13 05:12:46 +0000499/* If peer is RSERVER_CLIENT in at least one address family and is not member
500 of a peer_group for that family, return 1.
501 Used to check wether the peer is included in list bgp->rsclient. */
502int
503peer_rsclient_active (struct peer *peer)
504{
505 int i;
506 int j;
507
508 for (i=AFI_IP; i < AFI_MAX; i++)
509 for (j=SAFI_UNICAST; j < SAFI_MAX; j++)
510 if (CHECK_FLAG(peer->af_flags[i][j], PEER_FLAG_RSERVER_CLIENT)
511 && ! peer->af_group[i][j])
512 return 1;
513 return 0;
514}
515
pauleb821182004-05-01 08:44:08 +0000516/* Peer comparison function for sorting. */
paul718e3742002-12-13 20:15:29 +0000517static int
518peer_cmp (struct peer *p1, struct peer *p2)
519{
pauleb821182004-05-01 08:44:08 +0000520 return sockunion_cmp (&p1->su, &p2->su);
paul718e3742002-12-13 20:15:29 +0000521}
522
523int
524peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
525{
526 return CHECK_FLAG (peer->af_flags[afi][safi], flag);
527}
528
529/* Reset all address family specific configuration. */
530static void
531peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
532{
533 int i;
534 struct bgp_filter *filter;
535 char orf_name[BUFSIZ];
536
537 filter = &peer->filter[afi][safi];
538
539 /* Clear neighbor filter and route-map */
540 for (i = FILTER_IN; i < FILTER_MAX; i++)
541 {
542 if (filter->dlist[i].name)
543 {
544 free (filter->dlist[i].name);
545 filter->dlist[i].name = NULL;
546 }
547 if (filter->plist[i].name)
548 {
549 free (filter->plist[i].name);
550 filter->plist[i].name = NULL;
551 }
552 if (filter->aslist[i].name)
553 {
554 free (filter->aslist[i].name);
555 filter->aslist[i].name = NULL;
556 }
paulfee0f4c2004-09-13 05:12:46 +0000557 }
558 for (i = RMAP_IN; i < RMAP_MAX; i++)
559 {
paul718e3742002-12-13 20:15:29 +0000560 if (filter->map[i].name)
561 {
562 free (filter->map[i].name);
563 filter->map[i].name = NULL;
564 }
565 }
566
567 /* Clear unsuppress map. */
568 if (filter->usmap.name)
569 free (filter->usmap.name);
570 filter->usmap.name = NULL;
571 filter->usmap.map = NULL;
572
573 /* Clear neighbor's all address family flags. */
574 peer->af_flags[afi][safi] = 0;
575
576 /* Clear neighbor's all address family sflags. */
577 peer->af_sflags[afi][safi] = 0;
578
579 /* Clear neighbor's all address family capabilities. */
580 peer->af_cap[afi][safi] = 0;
581
582 /* Clear ORF info */
583 peer->orf_plist[afi][safi] = NULL;
584 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
585 prefix_bgp_orf_remove_all (orf_name);
586
587 /* Set default neighbor send-community. */
588 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
589 {
590 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
591 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
592 }
593
594 /* Clear neighbor default_originate_rmap */
595 if (peer->default_rmap[afi][safi].name)
596 free (peer->default_rmap[afi][safi].name);
597 peer->default_rmap[afi][safi].name = NULL;
598 peer->default_rmap[afi][safi].map = NULL;
599
600 /* Clear neighbor maximum-prefix */
601 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +0000602 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000603}
604
605/* peer global config reset */
paul94f2b392005-06-28 12:44:16 +0000606static void
paul718e3742002-12-13 20:15:29 +0000607peer_global_config_reset (struct peer *peer)
608{
609 peer->weight = 0;
610 peer->change_local_as = 0;
611 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
612 if (peer->update_source)
613 {
614 sockunion_free (peer->update_source);
615 peer->update_source = NULL;
616 }
617 if (peer->update_if)
618 {
619 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
620 peer->update_if = NULL;
621 }
622
623 if (peer_sort (peer) == BGP_PEER_IBGP)
624 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
625 else
626 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
627
628 peer->flags = 0;
629 peer->config = 0;
630 peer->holdtime = 0;
631 peer->keepalive = 0;
632 peer->connect = 0;
633 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
634}
635
636/* Check peer's AS number and determin is this peer IBGP or EBGP */
637int
638peer_sort (struct peer *peer)
639{
640 struct bgp *bgp;
641
642 bgp = peer->bgp;
643
644 /* Peer-group */
645 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
646 {
647 if (peer->as)
648 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
649 else
650 {
651 struct peer *peer1;
652 peer1 = listnode_head (peer->group->peer);
653 if (peer1)
654 return (peer1->local_as == peer1->as
655 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
656 }
657 return BGP_PEER_INTERNAL;
658 }
659
660 /* Normal peer */
661 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
662 {
663 if (peer->local_as == 0)
664 return BGP_PEER_INTERNAL;
665
666 if (peer->local_as == peer->as)
667 {
668 if (peer->local_as == bgp->confed_id)
669 return BGP_PEER_EBGP;
670 else
671 return BGP_PEER_IBGP;
672 }
673
674 if (bgp_confederation_peers_check (bgp, peer->as))
675 return BGP_PEER_CONFED;
676
677 return BGP_PEER_EBGP;
678 }
679 else
680 {
681 return (peer->local_as == 0
682 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
683 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
684 }
685}
686
paul200df112005-06-01 11:17:05 +0000687static inline void
688peer_free (struct peer *peer)
689{
Paul Jakmaca058a32006-09-14 02:58:49 +0000690 assert (peer->status == Deleted);
691
692 /* this /ought/ to have been done already through bgp_stop earlier,
693 * but just to be sure..
694 */
695 bgp_timer_set (peer);
696 BGP_READ_OFF (peer->t_read);
697 BGP_WRITE_OFF (peer->t_write);
Paul Jakma9fde6622006-09-14 03:02:02 +0000698 BGP_EVENT_FLUSH (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +0000699
paul200df112005-06-01 11:17:05 +0000700 if (peer->desc)
701 XFREE (MTYPE_PEER_DESC, peer->desc);
702
703 /* Free allocated host character. */
704 if (peer->host)
705 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
706
707 /* Update source configuration. */
708 if (peer->update_source)
709 sockunion_free (peer->update_source);
710
711 if (peer->update_if)
712 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
Paul Jakmaa625ca32006-03-30 14:12:38 +0000713
714 if (peer->clear_node_queue)
715 work_queue_free (peer->clear_node_queue);
716
Paul Jakmaca058a32006-09-14 02:58:49 +0000717 bgp_sync_delete (peer);
paul200df112005-06-01 11:17:05 +0000718 memset (peer, 0, sizeof (struct peer));
719
720 XFREE (MTYPE_BGP_PEER, peer);
721}
722
723/* increase reference count on a struct peer */
724struct peer *
725peer_lock (struct peer *peer)
726{
727 assert (peer && (peer->lock >= 0));
Paul Jakmaca058a32006-09-14 02:58:49 +0000728 assert (peer->status != Deleted);
729
paul200df112005-06-01 11:17:05 +0000730 peer->lock++;
731
732 return peer;
733}
734
735/* decrease reference count on a struct peer
736 * struct peer is freed and NULL returned if last reference
737 */
738struct peer *
739peer_unlock (struct peer *peer)
740{
741 assert (peer && (peer->lock > 0));
742
743 peer->lock--;
744
745 if (peer->lock == 0)
746 {
747#if 0
748 zlog_debug ("unlocked and freeing");
749 zlog_backtrace (LOG_DEBUG);
750#endif
751 peer_free (peer);
752 return NULL;
753 }
754
755#if 0
756 if (peer->lock == 1)
757 {
758 zlog_debug ("unlocked to 1");
759 zlog_backtrace (LOG_DEBUG);
760 }
761#endif
762
763 return peer;
764}
765
766/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000767static struct peer *
768peer_new ()
769{
770 afi_t afi;
771 safi_t safi;
772 struct peer *peer;
773 struct servent *sp;
774
775 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000776 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000777
778 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000779 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000780 peer->v_start = BGP_INIT_START_TIMER;
781 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
782 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
783 peer->status = Idle;
784 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000785 peer->weight = 0;
Paul Jakmaca058a32006-09-14 02:58:49 +0000786 peer = peer_lock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +0000787
788 /* Set default flags. */
789 for (afi = AFI_IP; afi < AFI_MAX; afi++)
790 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
791 {
792 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
793 {
794 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
795 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
796 }
797 peer->orf_plist[afi][safi] = NULL;
798 }
799 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
800
801 /* Create buffers. */
802 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
803 peer->obuf = stream_fifo_new ();
804 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
805
806 bgp_sync_init (peer);
807
808 /* Get service port number. */
809 sp = getservbyname ("bgp", "tcp");
810 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
811
812 return peer;
813}
814
815/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000816static struct peer *
paul718e3742002-12-13 20:15:29 +0000817peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
818 as_t remote_as, afi_t afi, safi_t safi)
819{
820 int active;
821 struct peer *peer;
822 char buf[SU_ADDRSTRLEN];
823
824 peer = peer_new ();
825 peer->bgp = bgp;
826 peer->su = *su;
827 peer->local_as = local_as;
828 peer->as = remote_as;
829 peer->local_id = bgp->router_id;
830 peer->v_holdtime = bgp->default_holdtime;
831 peer->v_keepalive = bgp->default_keepalive;
832 if (peer_sort (peer) == BGP_PEER_IBGP)
833 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
834 else
835 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000836
837 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000838 listnode_add_sort (bgp->peer, peer);
839
840 active = peer_active (peer);
841
842 if (afi && safi)
843 peer->afc[afi][safi] = 1;
844
845 /* Last read time set */
846 peer->readtime = time (NULL);
847
paul848973c2003-08-13 00:32:49 +0000848 /* Last reset time set */
849 peer->resettime = time (NULL);
850
paul718e3742002-12-13 20:15:29 +0000851 /* Default TTL set. */
852 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
853
854 /* Make peer's address string. */
855 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000856 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000857
858 /* Set up peer's events and timers. */
859 if (! active && peer_active (peer))
860 bgp_timer_set (peer);
861
862 return peer;
863}
864
pauleb821182004-05-01 08:44:08 +0000865/* Make accept BGP peer. Called from bgp_accept (). */
866struct peer *
867peer_create_accept (struct bgp *bgp)
868{
869 struct peer *peer;
870
871 peer = peer_new ();
872 peer->bgp = bgp;
paul200df112005-06-01 11:17:05 +0000873
874 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000875 listnode_add_sort (bgp->peer, peer);
876
877 return peer;
878}
879
paul718e3742002-12-13 20:15:29 +0000880/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000881static void
paul718e3742002-12-13 20:15:29 +0000882peer_as_change (struct peer *peer, as_t as)
883{
884 int type;
885
886 /* Stop peer. */
887 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
888 {
889 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000890 {
891 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
892 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
893 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
894 }
paul718e3742002-12-13 20:15:29 +0000895 else
896 BGP_EVENT_ADD (peer, BGP_Stop);
897 }
898 type = peer_sort (peer);
899 peer->as = as;
900
paul848973c2003-08-13 00:32:49 +0000901 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
902 && ! bgp_confederation_peers_check (peer->bgp, as)
903 && peer->bgp->as != as)
904 peer->local_as = peer->bgp->confed_id;
905 else
906 peer->local_as = peer->bgp->as;
907
paul718e3742002-12-13 20:15:29 +0000908 /* Advertisement-interval reset */
909 if (peer_sort (peer) == BGP_PEER_IBGP)
910 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
911 else
912 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
913
914 /* TTL reset */
915 if (peer_sort (peer) == BGP_PEER_IBGP)
916 peer->ttl = 255;
917 else if (type == BGP_PEER_IBGP)
918 peer->ttl = 1;
919
920 /* reflector-client reset */
921 if (peer_sort (peer) != BGP_PEER_IBGP)
922 {
923 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
924 PEER_FLAG_REFLECTOR_CLIENT);
925 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
926 PEER_FLAG_REFLECTOR_CLIENT);
927 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
928 PEER_FLAG_REFLECTOR_CLIENT);
929 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
930 PEER_FLAG_REFLECTOR_CLIENT);
931 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
932 PEER_FLAG_REFLECTOR_CLIENT);
933 }
934
935 /* local-as reset */
936 if (peer_sort (peer) != BGP_PEER_EBGP)
937 {
938 peer->change_local_as = 0;
939 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
940 }
941}
942
943/* If peer does not exist, create new one. If peer already exists,
944 set AS number to the peer. */
945int
946peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
947 afi_t afi, safi_t safi)
948{
949 struct peer *peer;
950 as_t local_as;
951
952 peer = peer_lookup (bgp, su);
953
954 if (peer)
955 {
956 /* When this peer is a member of peer-group. */
957 if (peer->group)
958 {
959 if (peer->group->conf->as)
960 {
961 /* Return peer group's AS number. */
962 *as = peer->group->conf->as;
963 return BGP_ERR_PEER_GROUP_MEMBER;
964 }
965 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
966 {
967 if (bgp->as != *as)
968 {
969 *as = peer->as;
970 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
971 }
972 }
973 else
974 {
975 if (bgp->as == *as)
976 {
977 *as = peer->as;
978 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
979 }
980 }
981 }
982
983 /* Existing peer's AS number change. */
984 if (peer->as != *as)
985 peer_as_change (peer, *as);
986 }
987 else
988 {
989
990 /* If the peer is not part of our confederation, and its not an
991 iBGP peer then spoof the source AS */
992 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
993 && ! bgp_confederation_peers_check (bgp, *as)
994 && bgp->as != *as)
995 local_as = bgp->confed_id;
996 else
997 local_as = bgp->as;
998
999 /* If this is IPv4 unicast configuration and "no bgp default
1000 ipv4-unicast" is specified. */
1001
1002 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1003 && afi == AFI_IP && safi == SAFI_UNICAST)
1004 peer = peer_create (su, bgp, local_as, *as, 0, 0);
1005 else
1006 peer = peer_create (su, bgp, local_as, *as, afi, safi);
1007 }
1008
1009 return 0;
1010}
1011
1012/* Activate the peer or peer group for specified AFI and SAFI. */
1013int
1014peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1015{
1016 int active;
1017
1018 if (peer->afc[afi][safi])
1019 return 0;
1020
1021 /* Activate the address family configuration. */
1022 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1023 peer->afc[afi][safi] = 1;
1024 else
1025 {
1026 active = peer_active (peer);
1027
1028 peer->afc[afi][safi] = 1;
1029
1030 if (! active && peer_active (peer))
1031 bgp_timer_set (peer);
1032 else
1033 {
1034 if (peer->status == Established)
1035 {
1036 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1037 {
1038 peer->afc_adv[afi][safi] = 1;
1039 bgp_capability_send (peer, afi, safi,
1040 CAPABILITY_CODE_MP,
1041 CAPABILITY_ACTION_SET);
1042 if (peer->afc_recv[afi][safi])
1043 {
1044 peer->afc_nego[afi][safi] = 1;
1045 bgp_announce_route (peer, afi, safi);
1046 }
1047 }
1048 else
hassoe0701b72004-05-20 09:19:34 +00001049 {
1050 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1051 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1052 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1053 }
paul718e3742002-12-13 20:15:29 +00001054 }
1055 }
1056 }
1057 return 0;
1058}
1059
1060int
1061peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1062{
1063 struct peer_group *group;
1064 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001065 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001066
1067 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1068 {
1069 group = peer->group;
1070
paul1eb8ef22005-04-07 07:30:20 +00001071 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001072 {
1073 if (peer1->af_group[afi][safi])
1074 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1075 }
1076 }
1077 else
1078 {
1079 if (peer->af_group[afi][safi])
1080 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1081 }
1082
1083 if (! peer->afc[afi][safi])
1084 return 0;
1085
1086 /* De-activate the address family configuration. */
1087 peer->afc[afi][safi] = 0;
1088 peer_af_flag_reset (peer, afi, safi);
1089
1090 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1091 {
1092 if (peer->status == Established)
1093 {
1094 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1095 {
1096 peer->afc_adv[afi][safi] = 0;
1097 peer->afc_nego[afi][safi] = 0;
1098
1099 if (peer_active_nego (peer))
1100 {
1101 bgp_capability_send (peer, afi, safi,
1102 CAPABILITY_CODE_MP,
1103 CAPABILITY_ACTION_UNSET);
1104 bgp_clear_route (peer, afi, safi);
1105 peer->pcount[afi][safi] = 0;
1106 }
1107 else
hassoe0701b72004-05-20 09:19:34 +00001108 {
1109 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1110 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1111 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1112 }
paul718e3742002-12-13 20:15:29 +00001113 }
1114 else
hassoe0701b72004-05-20 09:19:34 +00001115 {
1116 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1117 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1118 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1119 }
paul718e3742002-12-13 20:15:29 +00001120 }
1121 }
1122 return 0;
1123}
1124
hasso93406d82005-02-02 14:40:33 +00001125void
1126peer_nsf_stop (struct peer *peer)
1127{
1128 afi_t afi;
1129 safi_t safi;
1130
1131 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1132 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1133
1134 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1135 for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
1136 peer->nsf[afi][safi] = 0;
1137
1138 if (peer->t_gr_restart)
1139 {
1140 BGP_TIMER_OFF (peer->t_gr_restart);
1141 if (BGP_DEBUG (events, EVENTS))
1142 zlog_debug ("%s graceful restart timer stopped", peer->host);
1143 }
1144 if (peer->t_gr_stale)
1145 {
1146 BGP_TIMER_OFF (peer->t_gr_stale);
1147 if (BGP_DEBUG (events, EVENTS))
1148 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1149 }
1150 bgp_clear_route_all (peer);
1151}
1152
Paul Jakmaca058a32006-09-14 02:58:49 +00001153/* Delete peer from confguration.
1154 *
1155 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1156 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1157 *
1158 * This function /should/ take care to be idempotent, to guard against
1159 * it being called multiple times through stray events that come in
1160 * that happen to result in this function being called again. That
1161 * said, getting here for a "Deleted" peer is a bug in the neighbour
1162 * FSM.
1163 */
paul718e3742002-12-13 20:15:29 +00001164int
1165peer_delete (struct peer *peer)
1166{
1167 int i;
1168 afi_t afi;
1169 safi_t safi;
1170 struct bgp *bgp;
1171 struct bgp_filter *filter;
1172
Paul Jakmaca058a32006-09-14 02:58:49 +00001173 assert (peer->status != Deleted);
1174
paul718e3742002-12-13 20:15:29 +00001175 bgp = peer->bgp;
1176
hasso93406d82005-02-02 14:40:33 +00001177 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1178 peer_nsf_stop (peer);
1179
paul718e3742002-12-13 20:15:29 +00001180 /* If this peer belongs to peer group. Clearn up the
1181 relationship. */
1182 if (peer->group)
1183 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001184 struct listnode *pn;
1185
1186 if ((pn = listnode_lookup (peer->group->peer, peer)))
1187 {
1188 peer = peer_unlock (peer); /* group->peer list reference */
1189 list_delete_node (peer->group->peer, pn);
1190 }
paul718e3742002-12-13 20:15:29 +00001191 peer->group = NULL;
1192 }
paul200df112005-06-01 11:17:05 +00001193
paul718e3742002-12-13 20:15:29 +00001194 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001195 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1196 * executed after peer structure is deleted.
1197 */
hassoe0701b72004-05-20 09:19:34 +00001198 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001199 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001200 bgp_fsm_change_status (peer, Deleted);
1201 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001202
paul718e3742002-12-13 20:15:29 +00001203 /* Delete from all peer list. */
1204 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
paulfee0f4c2004-09-13 05:12:46 +00001205 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001206 struct listnode *pn;
paul200df112005-06-01 11:17:05 +00001207
Paul Jakmaca058a32006-09-14 02:58:49 +00001208 if ((pn = listnode_lookup (bgp->peer, peer)))
1209 {
1210 peer_unlock (peer); /* bgp peer list reference */
1211 list_delete_node (bgp->peer, pn);
1212 }
1213
1214 if (peer_rsclient_active (peer)
1215 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001216 {
1217 peer_unlock (peer); /* rsclient list reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001218 list_delete_node (bgp->rsclient, pn);
paul200df112005-06-01 11:17:05 +00001219 }
paulfee0f4c2004-09-13 05:12:46 +00001220 }
1221
1222 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1223 member of a peer_group. */
1224 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1225 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1226 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
1227 bgp_table_finish (peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001228
paul200df112005-06-01 11:17:05 +00001229 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001230 if (peer->ibuf)
1231 stream_free (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001232 if (peer->obuf)
1233 stream_fifo_free (peer->obuf);
paul718e3742002-12-13 20:15:29 +00001234 if (peer->work)
1235 stream_free (peer->work);
Paul Jakma18937402006-07-27 19:05:12 +00001236 peer->obuf = NULL;
1237 peer->work = peer->ibuf = NULL;
1238
paul718e3742002-12-13 20:15:29 +00001239 /* Local and remote addresses. */
1240 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001241 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001242 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001243 sockunion_free (peer->su_remote);
Paul Jakma18937402006-07-27 19:05:12 +00001244 peer->su_local = peer->su_remote = NULL;
paul200df112005-06-01 11:17:05 +00001245
paul718e3742002-12-13 20:15:29 +00001246 /* Free filter related memory. */
1247 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1248 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1249 {
1250 filter = &peer->filter[afi][safi];
1251
1252 for (i = FILTER_IN; i < FILTER_MAX; i++)
1253 {
1254 if (filter->dlist[i].name)
1255 free (filter->dlist[i].name);
1256 if (filter->plist[i].name)
1257 free (filter->plist[i].name);
1258 if (filter->aslist[i].name)
1259 free (filter->aslist[i].name);
paul200df112005-06-01 11:17:05 +00001260
1261 filter->dlist[i].name = NULL;
1262 filter->plist[i].name = NULL;
1263 filter->aslist[i].name = NULL;
1264 }
1265 for (i = RMAP_IN; i < RMAP_MAX; i++)
1266 {
paul718e3742002-12-13 20:15:29 +00001267 if (filter->map[i].name)
1268 free (filter->map[i].name);
paul200df112005-06-01 11:17:05 +00001269 filter->map[i].name = NULL;
paul718e3742002-12-13 20:15:29 +00001270 }
1271
1272 if (filter->usmap.name)
1273 free (filter->usmap.name);
1274
1275 if (peer->default_rmap[afi][safi].name)
1276 free (peer->default_rmap[afi][safi].name);
paul200df112005-06-01 11:17:05 +00001277
1278 filter->usmap.name = NULL;
1279 peer->default_rmap[afi][safi].name = NULL;
paul718e3742002-12-13 20:15:29 +00001280 }
paul200df112005-06-01 11:17:05 +00001281
1282 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001283
1284 return 0;
1285}
1286
paul94f2b392005-06-28 12:44:16 +00001287static int
paul718e3742002-12-13 20:15:29 +00001288peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1289{
1290 return strcmp (g1->name, g2->name);
1291}
1292
1293/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001294static int
paul718e3742002-12-13 20:15:29 +00001295peer_group_active (struct peer *peer)
1296{
1297 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1298 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1299 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1300 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1301 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1302 return 1;
1303 return 0;
1304}
1305
1306/* Peer group cofiguration. */
1307static struct peer_group *
1308peer_group_new ()
1309{
1310 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1311 sizeof (struct peer_group));
1312}
1313
paul94f2b392005-06-28 12:44:16 +00001314static void
paul718e3742002-12-13 20:15:29 +00001315peer_group_free (struct peer_group *group)
1316{
1317 XFREE (MTYPE_PEER_GROUP, group);
1318}
1319
1320struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001321peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001322{
1323 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001324 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001325
paul1eb8ef22005-04-07 07:30:20 +00001326 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001327 {
1328 if (strcmp (group->name, name) == 0)
1329 return group;
1330 }
1331 return NULL;
1332}
1333
1334struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001335peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001336{
1337 struct peer_group *group;
1338
1339 group = peer_group_lookup (bgp, name);
1340 if (group)
1341 return group;
1342
1343 group = peer_group_new ();
1344 group->bgp = bgp;
1345 group->name = strdup (name);
1346 group->peer = list_new ();
1347 group->conf = peer_new ();
1348 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1349 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
1350 group->conf->host = strdup (name);
1351 group->conf->bgp = bgp;
1352 group->conf->group = group;
1353 group->conf->as = 0;
1354 group->conf->ttl = 1;
1355 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1356 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1357 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1358 group->conf->keepalive = 0;
1359 group->conf->holdtime = 0;
1360 group->conf->connect = 0;
1361 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1362 listnode_add_sort (bgp->group, group);
1363
1364 return 0;
1365}
1366
paul94f2b392005-06-28 12:44:16 +00001367static void
paul718e3742002-12-13 20:15:29 +00001368peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1369 afi_t afi, safi_t safi)
1370{
1371 int in = FILTER_IN;
1372 int out = FILTER_OUT;
1373 struct peer *conf;
1374 struct bgp_filter *pfilter;
1375 struct bgp_filter *gfilter;
1376
1377 conf = group->conf;
1378 pfilter = &peer->filter[afi][safi];
1379 gfilter = &conf->filter[afi][safi];
1380
1381 /* remote-as */
1382 if (conf->as)
1383 peer->as = conf->as;
1384
1385 /* remote-as */
1386 if (conf->change_local_as)
1387 peer->change_local_as = conf->change_local_as;
1388
1389 /* TTL */
1390 peer->ttl = conf->ttl;
1391
1392 /* Weight */
1393 peer->weight = conf->weight;
1394
1395 /* peer flags apply */
1396 peer->flags = conf->flags;
1397 /* peer af_flags apply */
1398 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1399 /* peer config apply */
1400 peer->config = conf->config;
1401
1402 /* peer timers apply */
1403 peer->holdtime = conf->holdtime;
1404 peer->keepalive = conf->keepalive;
1405 peer->connect = conf->connect;
1406 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1407 peer->v_connect = conf->connect;
1408 else
1409 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1410
1411 /* advertisement-interval reset */
1412 if (peer_sort (peer) == BGP_PEER_IBGP)
1413 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1414 else
1415 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1416
1417 /* maximum-prefix */
1418 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001419 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001420 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001421
1422 /* allowas-in */
1423 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1424
paulfee0f4c2004-09-13 05:12:46 +00001425 /* route-server-client */
1426 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1427 {
1428 /* Make peer's RIB point to group's RIB. */
1429 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1430
1431 /* Import policy. */
1432 if (pfilter->map[RMAP_IMPORT].name)
1433 free (pfilter->map[RMAP_IMPORT].name);
1434 if (gfilter->map[RMAP_IMPORT].name)
1435 {
1436 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1437 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1438 }
1439 else
1440 {
1441 pfilter->map[RMAP_IMPORT].name = NULL;
1442 pfilter->map[RMAP_IMPORT].map = NULL;
1443 }
1444
1445 /* Export policy. */
1446 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1447 {
1448 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1449 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1450 }
1451 }
1452
paul718e3742002-12-13 20:15:29 +00001453 /* default-originate route-map */
1454 if (conf->default_rmap[afi][safi].name)
1455 {
1456 if (peer->default_rmap[afi][safi].name)
1457 free (peer->default_rmap[afi][safi].name);
1458 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1459 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1460 }
1461
1462 /* update-source apply */
1463 if (conf->update_source)
1464 {
1465 if (peer->update_source)
1466 sockunion_free (peer->update_source);
1467 if (peer->update_if)
1468 {
1469 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1470 peer->update_if = NULL;
1471 }
1472 peer->update_source = sockunion_dup (conf->update_source);
1473 }
1474 else if (conf->update_if)
1475 {
1476 if (peer->update_if)
1477 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1478 if (peer->update_source)
1479 {
1480 sockunion_free (peer->update_source);
1481 peer->update_source = NULL;
1482 }
1483 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1484 }
1485
1486 /* inbound filter apply */
1487 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1488 {
1489 if (pfilter->dlist[in].name)
1490 free (pfilter->dlist[in].name);
1491 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1492 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1493 }
1494 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1495 {
1496 if (pfilter->plist[in].name)
1497 free (pfilter->plist[in].name);
1498 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1499 pfilter->plist[in].plist = gfilter->plist[in].plist;
1500 }
1501 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1502 {
1503 if (pfilter->aslist[in].name)
1504 free (pfilter->aslist[in].name);
1505 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1506 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1507 }
paulfee0f4c2004-09-13 05:12:46 +00001508 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001509 {
paulfee0f4c2004-09-13 05:12:46 +00001510 if (pfilter->map[RMAP_IN].name)
1511 free (pfilter->map[RMAP_IN].name);
1512 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1513 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001514 }
1515
1516 /* outbound filter apply */
1517 if (gfilter->dlist[out].name)
1518 {
1519 if (pfilter->dlist[out].name)
1520 free (pfilter->dlist[out].name);
1521 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1522 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1523 }
1524 else
1525 {
1526 if (pfilter->dlist[out].name)
1527 free (pfilter->dlist[out].name);
1528 pfilter->dlist[out].name = NULL;
1529 pfilter->dlist[out].alist = NULL;
1530 }
1531 if (gfilter->plist[out].name)
1532 {
1533 if (pfilter->plist[out].name)
1534 free (pfilter->plist[out].name);
1535 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1536 pfilter->plist[out].plist = gfilter->plist[out].plist;
1537 }
1538 else
1539 {
1540 if (pfilter->plist[out].name)
1541 free (pfilter->plist[out].name);
1542 pfilter->plist[out].name = NULL;
1543 pfilter->plist[out].plist = NULL;
1544 }
1545 if (gfilter->aslist[out].name)
1546 {
1547 if (pfilter->aslist[out].name)
1548 free (pfilter->aslist[out].name);
1549 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1550 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1551 }
1552 else
1553 {
1554 if (pfilter->aslist[out].name)
1555 free (pfilter->aslist[out].name);
1556 pfilter->aslist[out].name = NULL;
1557 pfilter->aslist[out].aslist = NULL;
1558 }
paulfee0f4c2004-09-13 05:12:46 +00001559 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001560 {
paulfee0f4c2004-09-13 05:12:46 +00001561 if (pfilter->map[RMAP_OUT].name)
1562 free (pfilter->map[RMAP_OUT].name);
1563 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1564 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001565 }
1566 else
1567 {
paulfee0f4c2004-09-13 05:12:46 +00001568 if (pfilter->map[RMAP_OUT].name)
1569 free (pfilter->map[RMAP_OUT].name);
1570 pfilter->map[RMAP_OUT].name = NULL;
1571 pfilter->map[RMAP_OUT].map = NULL;
1572 }
1573
1574 /* RS-client's import/export route-maps. */
1575 if (gfilter->map[RMAP_IMPORT].name)
1576 {
1577 if (pfilter->map[RMAP_IMPORT].name)
1578 free (pfilter->map[RMAP_IMPORT].name);
1579 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1580 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1581 }
1582 else
1583 {
1584 if (pfilter->map[RMAP_IMPORT].name)
1585 free (pfilter->map[RMAP_IMPORT].name);
1586 pfilter->map[RMAP_IMPORT].name = NULL;
1587 pfilter->map[RMAP_IMPORT].map = NULL;
1588 }
1589 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1590 {
1591 if (pfilter->map[RMAP_EXPORT].name)
1592 free (pfilter->map[RMAP_EXPORT].name);
1593 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1594 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001595 }
1596
1597 if (gfilter->usmap.name)
1598 {
1599 if (pfilter->usmap.name)
1600 free (pfilter->usmap.name);
1601 pfilter->usmap.name = strdup (gfilter->usmap.name);
1602 pfilter->usmap.map = gfilter->usmap.map;
1603 }
1604 else
1605 {
1606 if (pfilter->usmap.name)
1607 free (pfilter->usmap.name);
1608 pfilter->usmap.name = NULL;
1609 pfilter->usmap.map = NULL;
1610 }
1611}
1612
1613/* Peer group's remote AS configuration. */
1614int
paulfd79ac92004-10-13 05:06:08 +00001615peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001616{
1617 struct peer_group *group;
1618 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001619 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001620
1621 group = peer_group_lookup (bgp, group_name);
1622 if (! group)
1623 return -1;
1624
1625 if (group->conf->as == *as)
1626 return 0;
1627
1628 /* When we setup peer-group AS number all peer group member's AS
1629 number must be updated to same number. */
1630 peer_as_change (group->conf, *as);
1631
paul1eb8ef22005-04-07 07:30:20 +00001632 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001633 {
1634 if (peer->as != *as)
1635 peer_as_change (peer, *as);
1636 }
1637
1638 return 0;
1639}
1640
1641int
1642peer_group_delete (struct peer_group *group)
1643{
1644 struct bgp *bgp;
1645 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001646 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001647
1648 bgp = group->bgp;
1649
paul1eb8ef22005-04-07 07:30:20 +00001650 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001651 {
1652 peer->group = NULL;
1653 peer_delete (peer);
1654 }
1655 list_delete (group->peer);
1656
1657 free (group->name);
1658 group->name = NULL;
1659
1660 group->conf->group = NULL;
1661 peer_delete (group->conf);
1662
1663 /* Delete from all peer_group list. */
1664 listnode_delete (bgp->group, group);
1665
1666 peer_group_free (group);
1667
1668 return 0;
1669}
1670
1671int
1672peer_group_remote_as_delete (struct peer_group *group)
1673{
1674 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001675 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001676
1677 if (! group->conf->as)
1678 return 0;
1679
paul1eb8ef22005-04-07 07:30:20 +00001680 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001681 {
1682 peer->group = NULL;
1683 peer_delete (peer);
1684 }
1685 list_delete_all_node (group->peer);
1686
1687 group->conf->as = 0;
1688
1689 return 0;
1690}
1691
1692/* Bind specified peer to peer group. */
1693int
1694peer_group_bind (struct bgp *bgp, union sockunion *su,
1695 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1696{
1697 struct peer *peer;
1698 int first_member = 0;
1699
1700 /* Check peer group's address family. */
1701 if (! group->conf->afc[afi][safi])
1702 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1703
1704 /* Lookup the peer. */
1705 peer = peer_lookup (bgp, su);
1706
1707 /* Create a new peer. */
1708 if (! peer)
1709 {
1710 if (! group->conf->as)
1711 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1712
1713 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1714 peer->group = group;
1715 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001716
Paul Jakmaca058a32006-09-14 02:58:49 +00001717 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001718 listnode_add (group->peer, peer);
1719 peer_group2peer_config_copy (group, peer, afi, safi);
1720
1721 return 0;
1722 }
1723
1724 /* When the peer already belongs to peer group, check the consistency. */
1725 if (peer->af_group[afi][safi])
1726 {
1727 if (strcmp (peer->group->name, group->name) != 0)
1728 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1729
1730 return 0;
1731 }
1732
1733 /* Check current peer group configuration. */
1734 if (peer_group_active (peer)
1735 && strcmp (peer->group->name, group->name) != 0)
1736 return BGP_ERR_PEER_GROUP_MISMATCH;
1737
1738 if (! group->conf->as)
1739 {
1740 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1741 && peer_sort (group->conf) != peer_sort (peer))
1742 {
1743 if (as)
1744 *as = peer->as;
1745 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1746 }
1747
1748 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1749 first_member = 1;
1750 }
1751
1752 peer->af_group[afi][safi] = 1;
1753 peer->afc[afi][safi] = 1;
1754 if (! peer->group)
1755 {
1756 peer->group = group;
paul200df112005-06-01 11:17:05 +00001757
Paul Jakmaca058a32006-09-14 02:58:49 +00001758 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001759 listnode_add (group->peer, peer);
1760 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001761 else
1762 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001763
1764 if (first_member)
1765 {
1766 /* Advertisement-interval reset */
1767 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1768 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1769 else
1770 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1771
1772 /* ebgp-multihop reset */
1773 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1774 group->conf->ttl = 255;
1775
1776 /* local-as reset */
1777 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1778 {
1779 group->conf->change_local_as = 0;
1780 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1781 }
1782 }
paulfee0f4c2004-09-13 05:12:46 +00001783
1784 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1785 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001786 struct listnode *pn;
1787
paulfee0f4c2004-09-13 05:12:46 +00001788 /* If it's not configured as RSERVER_CLIENT in any other address
1789 family, without being member of a peer_group, remove it from
1790 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001791 if (! peer_rsclient_active (peer)
1792 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001793 {
1794 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001795 list_delete_node (bgp->rsclient, pn);
paul200df112005-06-01 11:17:05 +00001796 }
paulfee0f4c2004-09-13 05:12:46 +00001797
1798 bgp_table_finish (peer->rib[afi][safi]);
1799
1800 /* Import policy. */
1801 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1802 {
1803 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1804 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1805 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1806 }
1807
1808 /* Export policy. */
1809 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1810 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1811 {
1812 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1813 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1814 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1815 }
1816 }
1817
paul718e3742002-12-13 20:15:29 +00001818 peer_group2peer_config_copy (group, peer, afi, safi);
1819
1820 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001821 {
1822 peer->last_reset = PEER_DOWN_RMAP_BIND;
1823 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1824 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1825 }
paul718e3742002-12-13 20:15:29 +00001826 else
1827 BGP_EVENT_ADD (peer, BGP_Stop);
1828
1829 return 0;
1830}
1831
1832int
1833peer_group_unbind (struct bgp *bgp, struct peer *peer,
1834 struct peer_group *group, afi_t afi, safi_t safi)
1835{
1836 if (! peer->af_group[afi][safi])
1837 return 0;
1838
1839 if (group != peer->group)
1840 return BGP_ERR_PEER_GROUP_MISMATCH;
1841
1842 peer->af_group[afi][safi] = 0;
1843 peer->afc[afi][safi] = 0;
1844 peer_af_flag_reset (peer, afi, safi);
1845
paulfee0f4c2004-09-13 05:12:46 +00001846 if (peer->rib[afi][safi])
1847 peer->rib[afi][safi] = NULL;
1848
paul718e3742002-12-13 20:15:29 +00001849 if (! peer_group_active (peer))
1850 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001851 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001852 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001853 listnode_delete (group->peer, peer);
1854 peer->group = NULL;
1855 if (group->conf->as)
1856 {
1857 peer_delete (peer);
1858 return 0;
1859 }
1860 peer_global_config_reset (peer);
1861 }
1862
1863 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001864 {
1865 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1866 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1867 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1868 }
paul718e3742002-12-13 20:15:29 +00001869 else
1870 BGP_EVENT_ADD (peer, BGP_Stop);
1871
1872 return 0;
1873}
1874
1875/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001876static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001877bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001878{
1879 struct bgp *bgp;
1880 afi_t afi;
1881 safi_t safi;
1882
paul200df112005-06-01 11:17:05 +00001883 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1884 return NULL;
1885
paul718e3742002-12-13 20:15:29 +00001886 bgp->peer_self = peer_new ();
paulfd79ac92004-10-13 05:06:08 +00001887 bgp->peer_self->host = strdup ("Static announcement");
paul718e3742002-12-13 20:15:29 +00001888
1889 bgp->peer = list_new ();
1890 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1891
1892 bgp->group = list_new ();
1893 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1894
paulfee0f4c2004-09-13 05:12:46 +00001895 bgp->rsclient = list_new ();
1896 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1897
paul718e3742002-12-13 20:15:29 +00001898 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1899 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1900 {
Paul Jakma64e580a2006-02-21 01:09:01 +00001901 bgp->route[afi][safi] = bgp_table_init (afi, safi);
1902 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1903 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
paul718e3742002-12-13 20:15:29 +00001904 }
1905
1906 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1907 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1908 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001909 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1910 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001911
1912 bgp->as = *as;
1913
1914 if (name)
1915 bgp->name = strdup (name);
1916
1917 return bgp;
1918}
1919
1920/* Return first entry of BGP. */
1921struct bgp *
paul94f2b392005-06-28 12:44:16 +00001922bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001923{
1924 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001925 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001926 return NULL;
1927}
1928
1929/* Lookup BGP entry. */
1930struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001931bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001932{
1933 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001934 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001935
paul1eb8ef22005-04-07 07:30:20 +00001936 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001937 if (bgp->as == as
1938 && ((bgp->name == NULL && name == NULL)
1939 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1940 return bgp;
1941 return NULL;
1942}
1943
1944/* Lookup BGP structure by view name. */
1945struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001946bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00001947{
1948 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001949 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001950
paul1eb8ef22005-04-07 07:30:20 +00001951 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001952 if ((bgp->name == NULL && name == NULL)
1953 || (bgp->name && name && strcmp (bgp->name, name) == 0))
1954 return bgp;
1955 return NULL;
1956}
1957
1958/* Called from VTY commands. */
1959int
paulfd79ac92004-10-13 05:06:08 +00001960bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001961{
1962 struct bgp *bgp;
1963
1964 /* Multiple instance check. */
1965 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
1966 {
1967 if (name)
1968 bgp = bgp_lookup_by_name (name);
1969 else
1970 bgp = bgp_get_default ();
1971
1972 /* Already exists. */
1973 if (bgp)
1974 {
1975 if (bgp->as != *as)
1976 {
1977 *as = bgp->as;
1978 return BGP_ERR_INSTANCE_MISMATCH;
1979 }
1980 *bgp_val = bgp;
1981 return 0;
1982 }
1983 }
1984 else
1985 {
1986 /* BGP instance name can not be specified for single instance. */
1987 if (name)
1988 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
1989
1990 /* Get default BGP structure if exists. */
1991 bgp = bgp_get_default ();
1992
1993 if (bgp)
1994 {
1995 if (bgp->as != *as)
1996 {
1997 *as = bgp->as;
1998 return BGP_ERR_AS_MISMATCH;
1999 }
2000 *bgp_val = bgp;
2001 return 0;
2002 }
2003 }
2004
2005 bgp = bgp_create (as, name);
2006 listnode_add (bm->bgp, bgp);
hasso18a6dce2004-10-03 18:18:34 +00002007 bgp_router_id_set(bgp, &router_id_zebra);
paul718e3742002-12-13 20:15:29 +00002008 *bgp_val = bgp;
2009
2010 return 0;
2011}
2012
2013/* Delete BGP instance. */
2014int
2015bgp_delete (struct bgp *bgp)
2016{
2017 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002018 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002019 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002020 struct listnode *next;
2021 afi_t afi;
2022 safi_t safi;
2023 int i;
2024
2025 /* Delete static route. */
2026 bgp_static_delete (bgp);
2027
2028 /* Unset redistribution. */
2029 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2030 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2031 if (i != ZEBRA_ROUTE_BGP)
2032 bgp_redistribute_unset (bgp, afi, i);
2033
hassob6b7cff2005-05-26 08:29:07 +00002034 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
2035 peer_group_delete (group);
hasso54a6ed32005-05-26 22:12:33 +00002036 list_delete (bgp->group);
paul718e3742002-12-13 20:15:29 +00002037
paul1eb8ef22005-04-07 07:30:20 +00002038 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2039 peer_delete (peer);
hasso54a6ed32005-05-26 22:12:33 +00002040 list_delete (bgp->peer);
paul718e3742002-12-13 20:15:29 +00002041
hasso54a6ed32005-05-26 22:12:33 +00002042 for (ALL_LIST_ELEMENTS (bgp->rsclient, node, next, peer))
2043 peer_delete (peer);
paulfee0f4c2004-09-13 05:12:46 +00002044 list_delete (bgp->rsclient);
2045
paul718e3742002-12-13 20:15:29 +00002046 listnode_delete (bm->bgp, bgp);
paul200df112005-06-01 11:17:05 +00002047
paul718e3742002-12-13 20:15:29 +00002048 if (bgp->name)
2049 free (bgp->name);
2050
2051 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2052 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2053 {
2054 if (bgp->route[afi][safi])
2055 XFREE (MTYPE_ROUTE_TABLE, bgp->route[afi][safi]);
2056 if (bgp->aggregate[afi][safi])
2057 XFREE (MTYPE_ROUTE_TABLE,bgp->aggregate[afi][safi]) ;
2058 if (bgp->rib[afi][safi])
2059 XFREE (MTYPE_ROUTE_TABLE,bgp->rib[afi][safi]);
2060 }
2061 XFREE (MTYPE_BGP, bgp);
2062
2063 return 0;
2064}
2065
2066struct peer *
2067peer_lookup (struct bgp *bgp, union sockunion *su)
2068{
2069 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002070 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002071
2072 if (! bgp)
2073 bgp = bgp_get_default ();
2074
2075 if (! bgp)
2076 return NULL;
2077
paul1eb8ef22005-04-07 07:30:20 +00002078 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002079 {
pauleb821182004-05-01 08:44:08 +00002080 if (sockunion_same (&peer->su, su)
2081 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2082 return peer;
paul718e3742002-12-13 20:15:29 +00002083 }
2084 return NULL;
2085}
2086
2087struct peer *
2088peer_lookup_with_open (union sockunion *su, as_t remote_as,
2089 struct in_addr *remote_id, int *as)
2090{
2091 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002092 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002093 struct bgp *bgp;
2094
2095 bgp = bgp_get_default ();
2096 if (! bgp)
2097 return NULL;
2098
paul1eb8ef22005-04-07 07:30:20 +00002099 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002100 {
pauleb821182004-05-01 08:44:08 +00002101 if (sockunion_same (&peer->su, su)
2102 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2103 {
2104 if (peer->as == remote_as
2105 && peer->remote_id.s_addr == remote_id->s_addr)
2106 return peer;
2107 if (peer->as == remote_as)
2108 *as = 1;
2109 }
paul718e3742002-12-13 20:15:29 +00002110 }
paul1eb8ef22005-04-07 07:30:20 +00002111 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002112 {
pauleb821182004-05-01 08:44:08 +00002113 if (sockunion_same (&peer->su, su)
2114 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2115 {
2116 if (peer->as == remote_as
2117 && peer->remote_id.s_addr == 0)
2118 return peer;
2119 if (peer->as == remote_as)
2120 *as = 1;
2121 }
paul718e3742002-12-13 20:15:29 +00002122 }
2123 return NULL;
2124}
2125
2126/* If peer is configured at least one address family return 1. */
2127int
2128peer_active (struct peer *peer)
2129{
2130 if (peer->afc[AFI_IP][SAFI_UNICAST]
2131 || peer->afc[AFI_IP][SAFI_MULTICAST]
2132 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2133 || peer->afc[AFI_IP6][SAFI_UNICAST]
2134 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2135 return 1;
2136 return 0;
2137}
2138
2139/* If peer is negotiated at least one address family return 1. */
2140int
2141peer_active_nego (struct peer *peer)
2142{
2143 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2144 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2145 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2146 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2147 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2148 return 1;
2149 return 0;
2150}
2151
2152/* peer_flag_change_type. */
2153enum peer_change_type
2154{
2155 peer_change_none,
2156 peer_change_reset,
2157 peer_change_reset_in,
2158 peer_change_reset_out,
2159};
2160
paul94f2b392005-06-28 12:44:16 +00002161static void
paul718e3742002-12-13 20:15:29 +00002162peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2163 enum peer_change_type type)
2164{
2165 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2166 return;
2167
2168 if (type == peer_change_reset)
2169 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2170 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2171 else if (type == peer_change_reset_in)
2172 {
2173 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2174 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2175 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2176 else
2177 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2178 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2179 }
2180 else if (type == peer_change_reset_out)
2181 bgp_announce_route (peer, afi, safi);
2182}
2183
2184struct peer_flag_action
2185{
2186 /* Peer's flag. */
2187 u_int32_t flag;
2188
2189 /* This flag can be set for peer-group member. */
2190 u_char not_for_member;
2191
2192 /* Action when the flag is changed. */
2193 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002194
2195 /* Peer down cause */
2196 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002197};
2198
2199struct peer_flag_action peer_flag_action_list[] =
2200 {
2201 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2202 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2203 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2204 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2205 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002206 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002207 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002208 { 0, 0, 0 }
2209 };
2210
2211struct peer_flag_action peer_af_flag_action_list[] =
2212 {
2213 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2214 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2215 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2216 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2217 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2218 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2219 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2220 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2221 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2222 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2223 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2224 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2225 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002226 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002227 { 0, 0, 0 }
2228 };
2229
2230/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002231static int
paul718e3742002-12-13 20:15:29 +00002232peer_flag_action_set (struct peer_flag_action *action_list, int size,
2233 struct peer_flag_action *action, u_int32_t flag)
2234{
2235 int i;
2236 int found = 0;
2237 int reset_in = 0;
2238 int reset_out = 0;
2239 struct peer_flag_action *match = NULL;
2240
2241 /* Check peer's frag action. */
2242 for (i = 0; i < size; i++)
2243 {
2244 match = &action_list[i];
2245
2246 if (match->flag == 0)
2247 break;
2248
2249 if (match->flag & flag)
2250 {
2251 found = 1;
2252
2253 if (match->type == peer_change_reset_in)
2254 reset_in = 1;
2255 if (match->type == peer_change_reset_out)
2256 reset_out = 1;
2257 if (match->type == peer_change_reset)
2258 {
2259 reset_in = 1;
2260 reset_out = 1;
2261 }
2262 if (match->not_for_member)
2263 action->not_for_member = 1;
2264 }
2265 }
2266
2267 /* Set peer clear type. */
2268 if (reset_in && reset_out)
2269 action->type = peer_change_reset;
2270 else if (reset_in)
2271 action->type = peer_change_reset_in;
2272 else if (reset_out)
2273 action->type = peer_change_reset_out;
2274 else
2275 action->type = peer_change_none;
2276
2277 return found;
2278}
2279
paul94f2b392005-06-28 12:44:16 +00002280static void
paul718e3742002-12-13 20:15:29 +00002281peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2282{
2283 if (flag == PEER_FLAG_SHUTDOWN)
2284 {
2285 if (CHECK_FLAG (peer->flags, flag))
2286 {
hasso93406d82005-02-02 14:40:33 +00002287 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2288 peer_nsf_stop (peer);
2289
hasso0a486e52005-02-01 20:57:17 +00002290 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2291 if (peer->t_pmax_restart)
2292 {
2293 BGP_TIMER_OFF (peer->t_pmax_restart);
2294 if (BGP_DEBUG (events, EVENTS))
2295 zlog_debug ("%s Maximum-prefix restart timer canceled",
2296 peer->host);
2297 }
2298
hasso93406d82005-02-02 14:40:33 +00002299 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2300 peer_nsf_stop (peer);
2301
paul718e3742002-12-13 20:15:29 +00002302 if (peer->status == Established)
2303 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2304 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2305 else
2306 BGP_EVENT_ADD (peer, BGP_Stop);
2307 }
2308 else
2309 {
2310 peer->v_start = BGP_INIT_START_TIMER;
2311 BGP_EVENT_ADD (peer, BGP_Stop);
2312 }
2313 }
2314 else if (peer->status == Established)
2315 {
hassoc9502432005-02-01 22:01:48 +00002316 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2317 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2318 else if (flag == PEER_FLAG_PASSIVE)
2319 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002320 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002321 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002322
hassoc9502432005-02-01 22:01:48 +00002323 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2324 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002325 }
2326 else
2327 BGP_EVENT_ADD (peer, BGP_Stop);
2328}
2329
2330/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002331static int
paul718e3742002-12-13 20:15:29 +00002332peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2333{
2334 int found;
2335 int size;
2336 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002337 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002338 struct peer_flag_action action;
2339
2340 memset (&action, 0, sizeof (struct peer_flag_action));
2341 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2342
2343 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2344
2345 /* No flag action is found. */
2346 if (! found)
2347 return BGP_ERR_INVALID_FLAG;
2348
2349 /* Not for peer-group member. */
2350 if (action.not_for_member && peer_group_active (peer))
2351 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2352
2353 /* When unset the peer-group member's flag we have to check
2354 peer-group configuration. */
2355 if (! set && peer_group_active (peer))
2356 if (CHECK_FLAG (peer->group->conf->flags, flag))
2357 {
2358 if (flag == PEER_FLAG_SHUTDOWN)
2359 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2360 else
2361 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2362 }
2363
2364 /* Flag conflict check. */
2365 if (set
2366 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2367 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2368 return BGP_ERR_PEER_FLAG_CONFLICT;
2369
2370 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2371 {
2372 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2373 return 0;
2374 if (! set && ! CHECK_FLAG (peer->flags, flag))
2375 return 0;
2376 }
2377
2378 if (set)
2379 SET_FLAG (peer->flags, flag);
2380 else
2381 UNSET_FLAG (peer->flags, flag);
2382
2383 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2384 {
2385 if (action.type == peer_change_reset)
2386 peer_flag_modify_action (peer, flag);
2387
2388 return 0;
2389 }
2390
2391 /* peer-group member updates. */
2392 group = peer->group;
2393
paul1eb8ef22005-04-07 07:30:20 +00002394 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002395 {
2396 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2397 continue;
2398
2399 if (! set && ! CHECK_FLAG (peer->flags, flag))
2400 continue;
2401
2402 if (set)
2403 SET_FLAG (peer->flags, flag);
2404 else
2405 UNSET_FLAG (peer->flags, flag);
2406
2407 if (action.type == peer_change_reset)
2408 peer_flag_modify_action (peer, flag);
2409 }
2410 return 0;
2411}
2412
2413int
2414peer_flag_set (struct peer *peer, u_int32_t flag)
2415{
2416 return peer_flag_modify (peer, flag, 1);
2417}
2418
2419int
2420peer_flag_unset (struct peer *peer, u_int32_t flag)
2421{
2422 return peer_flag_modify (peer, flag, 0);
2423}
2424
paul94f2b392005-06-28 12:44:16 +00002425static int
paul718e3742002-12-13 20:15:29 +00002426peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2427{
2428 if (peer->af_group[afi][safi])
2429 return 1;
2430 return 0;
2431}
2432
paul94f2b392005-06-28 12:44:16 +00002433static int
paul718e3742002-12-13 20:15:29 +00002434peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2435 int set)
2436{
2437 int found;
2438 int size;
paul1eb8ef22005-04-07 07:30:20 +00002439 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002440 struct peer_group *group;
2441 struct peer_flag_action action;
2442
2443 memset (&action, 0, sizeof (struct peer_flag_action));
2444 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2445
2446 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2447
2448 /* No flag action is found. */
2449 if (! found)
2450 return BGP_ERR_INVALID_FLAG;
2451
2452 /* Adress family must be activated. */
2453 if (! peer->afc[afi][safi])
2454 return BGP_ERR_PEER_INACTIVE;
2455
2456 /* Not for peer-group member. */
2457 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2458 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2459
2460 /* Spcecial check for reflector client. */
2461 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2462 && peer_sort (peer) != BGP_PEER_IBGP)
2463 return BGP_ERR_NOT_INTERNAL_PEER;
2464
2465 /* Spcecial check for remove-private-AS. */
2466 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2467 && peer_sort (peer) == BGP_PEER_IBGP)
2468 return BGP_ERR_REMOVE_PRIVATE_AS;
2469
2470 /* When unset the peer-group member's flag we have to check
2471 peer-group configuration. */
2472 if (! set && peer->af_group[afi][safi])
2473 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2474 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2475
2476 /* When current flag configuration is same as requested one. */
2477 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2478 {
2479 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2480 return 0;
2481 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2482 return 0;
2483 }
2484
2485 if (set)
2486 SET_FLAG (peer->af_flags[afi][safi], flag);
2487 else
2488 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2489
2490 /* Execute action when peer is established. */
2491 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2492 && peer->status == Established)
2493 {
2494 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2495 bgp_clear_adj_in (peer, afi, safi);
2496 else
hassoe0701b72004-05-20 09:19:34 +00002497 {
2498 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2499 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2500 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2501 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2502 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2503 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2504 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2505 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2506
2507 peer_change_action (peer, afi, safi, action.type);
2508 }
2509
paul718e3742002-12-13 20:15:29 +00002510 }
2511
2512 /* Peer group member updates. */
2513 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2514 {
2515 group = peer->group;
2516
paul1eb8ef22005-04-07 07:30:20 +00002517 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002518 {
2519 if (! peer->af_group[afi][safi])
2520 continue;
2521
2522 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2523 continue;
2524
2525 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2526 continue;
2527
2528 if (set)
2529 SET_FLAG (peer->af_flags[afi][safi], flag);
2530 else
2531 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2532
2533 if (peer->status == Established)
2534 {
2535 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2536 bgp_clear_adj_in (peer, afi, safi);
2537 else
hassoe0701b72004-05-20 09:19:34 +00002538 {
2539 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2540 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2541 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2542 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2543 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2544 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2545 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2546 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2547
2548 peer_change_action (peer, afi, safi, action.type);
2549 }
paul718e3742002-12-13 20:15:29 +00002550 }
2551 }
2552 }
2553 return 0;
2554}
2555
2556int
2557peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2558{
2559 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2560}
2561
2562int
2563peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2564{
2565 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2566}
2567
2568/* EBGP multihop configuration. */
2569int
2570peer_ebgp_multihop_set (struct peer *peer, int ttl)
2571{
2572 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002573 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002574
2575 if (peer_sort (peer) == BGP_PEER_IBGP)
2576 return 0;
2577
2578 peer->ttl = ttl;
2579
2580 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2581 {
pauleb821182004-05-01 08:44:08 +00002582 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2583 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002584 }
2585 else
2586 {
2587 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002588 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002589 {
2590 if (peer_sort (peer) == BGP_PEER_IBGP)
2591 continue;
paul718e3742002-12-13 20:15:29 +00002592
pauleb821182004-05-01 08:44:08 +00002593 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002594
pauleb821182004-05-01 08:44:08 +00002595 if (peer->fd >= 0)
2596 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2597 }
paul718e3742002-12-13 20:15:29 +00002598 }
2599 return 0;
2600}
2601
2602int
2603peer_ebgp_multihop_unset (struct peer *peer)
2604{
2605 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002606 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002607
2608 if (peer_sort (peer) == BGP_PEER_IBGP)
2609 return 0;
2610
2611 if (peer_group_active (peer))
2612 peer->ttl = peer->group->conf->ttl;
2613 else
2614 peer->ttl = 1;
2615
2616 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2617 {
pauleb821182004-05-01 08:44:08 +00002618 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2619 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002620 }
2621 else
2622 {
2623 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002624 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002625 {
2626 if (peer_sort (peer) == BGP_PEER_IBGP)
2627 continue;
paul718e3742002-12-13 20:15:29 +00002628
pauleb821182004-05-01 08:44:08 +00002629 peer->ttl = 1;
2630
2631 if (peer->fd >= 0)
2632 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2633 }
paul718e3742002-12-13 20:15:29 +00002634 }
2635 return 0;
2636}
2637
2638/* Neighbor description. */
2639int
2640peer_description_set (struct peer *peer, char *desc)
2641{
2642 if (peer->desc)
2643 XFREE (MTYPE_PEER_DESC, peer->desc);
2644
2645 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2646
2647 return 0;
2648}
2649
2650int
2651peer_description_unset (struct peer *peer)
2652{
2653 if (peer->desc)
2654 XFREE (MTYPE_PEER_DESC, peer->desc);
2655
2656 peer->desc = NULL;
2657
2658 return 0;
2659}
2660
2661/* Neighbor update-source. */
2662int
paulfd79ac92004-10-13 05:06:08 +00002663peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002664{
2665 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002666 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002667
2668 if (peer->update_if)
2669 {
2670 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2671 && strcmp (peer->update_if, ifname) == 0)
2672 return 0;
2673
2674 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2675 peer->update_if = NULL;
2676 }
2677
2678 if (peer->update_source)
2679 {
2680 sockunion_free (peer->update_source);
2681 peer->update_source = NULL;
2682 }
2683
2684 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2685
2686 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2687 {
2688 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002689 {
2690 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2691 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2692 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2693 }
paul718e3742002-12-13 20:15:29 +00002694 else
2695 BGP_EVENT_ADD (peer, BGP_Stop);
2696 return 0;
2697 }
2698
2699 /* peer-group member updates. */
2700 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002701 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002702 {
2703 if (peer->update_if)
2704 {
2705 if (strcmp (peer->update_if, ifname) == 0)
2706 continue;
2707
2708 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2709 peer->update_if = NULL;
2710 }
2711
2712 if (peer->update_source)
2713 {
2714 sockunion_free (peer->update_source);
2715 peer->update_source = NULL;
2716 }
2717
2718 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2719
2720 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002721 {
2722 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2723 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2724 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2725 }
paul718e3742002-12-13 20:15:29 +00002726 else
2727 BGP_EVENT_ADD (peer, BGP_Stop);
2728 }
2729 return 0;
2730}
2731
2732int
2733peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2734{
2735 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002736 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002737
2738 if (peer->update_source)
2739 {
2740 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2741 && sockunion_cmp (peer->update_source, su) == 0)
2742 return 0;
2743 sockunion_free (peer->update_source);
2744 peer->update_source = NULL;
2745 }
2746
2747 if (peer->update_if)
2748 {
2749 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2750 peer->update_if = NULL;
2751 }
2752
2753 peer->update_source = sockunion_dup (su);
2754
2755 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2756 {
2757 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002758 {
2759 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2760 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2761 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2762 }
paul718e3742002-12-13 20:15:29 +00002763 else
2764 BGP_EVENT_ADD (peer, BGP_Stop);
2765 return 0;
2766 }
2767
2768 /* peer-group member updates. */
2769 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002770 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002771 {
2772 if (peer->update_source)
2773 {
2774 if (sockunion_cmp (peer->update_source, su) == 0)
2775 continue;
2776 sockunion_free (peer->update_source);
2777 peer->update_source = NULL;
2778 }
2779
2780 if (peer->update_if)
2781 {
2782 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2783 peer->update_if = NULL;
2784 }
2785
2786 peer->update_source = sockunion_dup (su);
2787
2788 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002789 {
2790 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2791 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2792 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2793 }
paul718e3742002-12-13 20:15:29 +00002794 else
2795 BGP_EVENT_ADD (peer, BGP_Stop);
2796 }
2797 return 0;
2798}
2799
2800int
2801peer_update_source_unset (struct peer *peer)
2802{
2803 union sockunion *su;
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 (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2808 && ! peer->update_source
2809 && ! peer->update_if)
2810 return 0;
2811
2812 if (peer->update_source)
2813 {
2814 sockunion_free (peer->update_source);
2815 peer->update_source = NULL;
2816 }
2817 if (peer->update_if)
2818 {
2819 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2820 peer->update_if = NULL;
2821 }
2822
2823 if (peer_group_active (peer))
2824 {
2825 group = peer->group;
2826
2827 if (group->conf->update_source)
2828 {
2829 su = sockunion_dup (group->conf->update_source);
2830 peer->update_source = su;
2831 }
2832 else if (group->conf->update_if)
2833 peer->update_if =
2834 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2835 }
2836
2837 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2838 {
2839 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002840 {
2841 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2842 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2843 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2844 }
paul718e3742002-12-13 20:15:29 +00002845 else
2846 BGP_EVENT_ADD (peer, BGP_Stop);
2847 return 0;
2848 }
2849
2850 /* peer-group member updates. */
2851 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002852 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002853 {
2854 if (! peer->update_source && ! peer->update_if)
2855 continue;
2856
2857 if (peer->update_source)
2858 {
2859 sockunion_free (peer->update_source);
2860 peer->update_source = NULL;
2861 }
2862
2863 if (peer->update_if)
2864 {
2865 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2866 peer->update_if = NULL;
2867 }
2868
2869 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002870 {
2871 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2872 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2873 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2874 }
paul718e3742002-12-13 20:15:29 +00002875 else
2876 BGP_EVENT_ADD (peer, BGP_Stop);
2877 }
2878 return 0;
2879}
2880
2881int
2882peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00002883 const char *rmap)
paul718e3742002-12-13 20:15:29 +00002884{
2885 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002886 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002887
2888 /* Adress family must be activated. */
2889 if (! peer->afc[afi][safi])
2890 return BGP_ERR_PEER_INACTIVE;
2891
2892 /* Default originate can't be used for peer group memeber. */
2893 if (peer_is_group_member (peer, afi, safi))
2894 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2895
2896 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
2897 || (rmap && ! peer->default_rmap[afi][safi].name)
2898 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
2899 {
2900 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2901
2902 if (rmap)
2903 {
2904 if (peer->default_rmap[afi][safi].name)
2905 free (peer->default_rmap[afi][safi].name);
2906 peer->default_rmap[afi][safi].name = strdup (rmap);
2907 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2908 }
2909 }
2910
2911 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2912 {
2913 if (peer->status == Established && peer->afc_nego[afi][safi])
2914 bgp_default_originate (peer, afi, safi, 0);
2915 return 0;
2916 }
2917
2918 /* peer-group member updates. */
2919 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002920 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002921 {
2922 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2923
2924 if (rmap)
2925 {
2926 if (peer->default_rmap[afi][safi].name)
2927 free (peer->default_rmap[afi][safi].name);
2928 peer->default_rmap[afi][safi].name = strdup (rmap);
2929 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2930 }
2931
2932 if (peer->status == Established && peer->afc_nego[afi][safi])
2933 bgp_default_originate (peer, afi, safi, 0);
2934 }
2935 return 0;
2936}
2937
2938int
2939peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
2940{
2941 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002942 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002943
2944 /* Adress family must be activated. */
2945 if (! peer->afc[afi][safi])
2946 return BGP_ERR_PEER_INACTIVE;
2947
2948 /* Default originate can't be used for peer group memeber. */
2949 if (peer_is_group_member (peer, afi, safi))
2950 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2951
2952 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
2953 {
2954 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2955
2956 if (peer->default_rmap[afi][safi].name)
2957 free (peer->default_rmap[afi][safi].name);
2958 peer->default_rmap[afi][safi].name = NULL;
2959 peer->default_rmap[afi][safi].map = NULL;
2960 }
2961
2962 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2963 {
2964 if (peer->status == Established && peer->afc_nego[afi][safi])
2965 bgp_default_originate (peer, afi, safi, 1);
2966 return 0;
2967 }
2968
2969 /* peer-group member updates. */
2970 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002971 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002972 {
2973 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2974
2975 if (peer->default_rmap[afi][safi].name)
2976 free (peer->default_rmap[afi][safi].name);
2977 peer->default_rmap[afi][safi].name = NULL;
2978 peer->default_rmap[afi][safi].map = NULL;
2979
2980 if (peer->status == Established && peer->afc_nego[afi][safi])
2981 bgp_default_originate (peer, afi, safi, 1);
2982 }
2983 return 0;
2984}
2985
2986int
2987peer_port_set (struct peer *peer, u_int16_t port)
2988{
2989 peer->port = port;
2990 return 0;
2991}
2992
2993int
2994peer_port_unset (struct peer *peer)
2995{
2996 peer->port = BGP_PORT_DEFAULT;
2997 return 0;
2998}
2999
3000/* neighbor weight. */
3001int
3002peer_weight_set (struct peer *peer, u_int16_t weight)
3003{
3004 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003005 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003006
3007 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3008 peer->weight = weight;
3009
3010 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3011 return 0;
3012
3013 /* peer-group member updates. */
3014 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003015 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003016 {
3017 peer->weight = group->conf->weight;
3018 }
3019 return 0;
3020}
3021
3022int
3023peer_weight_unset (struct peer *peer)
3024{
3025 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003026 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003027
3028 /* Set default weight. */
3029 if (peer_group_active (peer))
3030 peer->weight = peer->group->conf->weight;
3031 else
3032 peer->weight = 0;
3033
3034 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3035
3036 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3037 return 0;
3038
3039 /* peer-group member updates. */
3040 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003041 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003042 {
3043 peer->weight = 0;
3044 }
3045 return 0;
3046}
3047
3048int
3049peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3050{
3051 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003052 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003053
3054 /* Not for peer group memeber. */
3055 if (peer_group_active (peer))
3056 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3057
3058 /* keepalive value check. */
3059 if (keepalive > 65535)
3060 return BGP_ERR_INVALID_VALUE;
3061
3062 /* Holdtime value check. */
3063 if (holdtime > 65535)
3064 return BGP_ERR_INVALID_VALUE;
3065
3066 /* Holdtime value must be either 0 or greater than 3. */
3067 if (holdtime < 3 && holdtime != 0)
3068 return BGP_ERR_INVALID_VALUE;
3069
3070 /* Set value to the configuration. */
3071 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3072 peer->holdtime = holdtime;
3073 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3074
3075 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3076 return 0;
3077
3078 /* peer-group member updates. */
3079 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003080 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003081 {
3082 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3083 peer->holdtime = group->conf->holdtime;
3084 peer->keepalive = group->conf->keepalive;
3085 }
3086 return 0;
3087}
3088
3089int
3090peer_timers_unset (struct peer *peer)
3091{
3092 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003093 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003094
3095 if (peer_group_active (peer))
3096 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3097
3098 /* Clear configuration. */
3099 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3100 peer->keepalive = 0;
3101 peer->holdtime = 0;
3102
3103 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3104 return 0;
3105
3106 /* peer-group member updates. */
3107 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003108 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003109 {
3110 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3111 peer->holdtime = 0;
3112 peer->keepalive = 0;
3113 }
3114
3115 return 0;
3116}
3117
3118int
3119peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3120{
3121 if (peer_group_active (peer))
3122 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3123
3124 if (connect > 65535)
3125 return BGP_ERR_INVALID_VALUE;
3126
3127 /* Set value to the configuration. */
3128 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3129 peer->connect = connect;
3130
3131 /* Set value to timer setting. */
3132 peer->v_connect = connect;
3133
3134 return 0;
3135}
3136
3137int
3138peer_timers_connect_unset (struct peer *peer)
3139{
3140 if (peer_group_active (peer))
3141 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3142
3143 /* Clear configuration. */
3144 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3145 peer->connect = 0;
3146
3147 /* Set timer setting to default value. */
3148 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3149
3150 return 0;
3151}
3152
3153int
3154peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3155{
3156 if (peer_group_active (peer))
3157 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3158
3159 if (routeadv > 600)
3160 return BGP_ERR_INVALID_VALUE;
3161
3162 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3163 peer->routeadv = routeadv;
3164 peer->v_routeadv = routeadv;
3165
3166 return 0;
3167}
3168
3169int
3170peer_advertise_interval_unset (struct peer *peer)
3171{
3172 if (peer_group_active (peer))
3173 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3174
3175 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3176 peer->routeadv = 0;
3177
3178 if (peer_sort (peer) == BGP_PEER_IBGP)
3179 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3180 else
3181 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3182
3183 return 0;
3184}
3185
paul718e3742002-12-13 20:15:29 +00003186/* neighbor interface */
3187int
paulfd79ac92004-10-13 05:06:08 +00003188peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003189{
3190 if (peer->ifname)
3191 free (peer->ifname);
3192 peer->ifname = strdup (str);
3193
3194 return 0;
3195}
3196
3197int
3198peer_interface_unset (struct peer *peer)
3199{
3200 if (peer->ifname)
3201 free (peer->ifname);
3202 peer->ifname = NULL;
3203
3204 return 0;
3205}
3206
3207/* Allow-as in. */
3208int
3209peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3210{
3211 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003212 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003213
3214 if (allow_num < 1 || allow_num > 10)
3215 return BGP_ERR_INVALID_VALUE;
3216
3217 if (peer->allowas_in[afi][safi] != allow_num)
3218 {
3219 peer->allowas_in[afi][safi] = allow_num;
3220 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3221 peer_change_action (peer, afi, safi, peer_change_reset_in);
3222 }
3223
3224 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3225 return 0;
3226
3227 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003228 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003229 {
3230 if (peer->allowas_in[afi][safi] != allow_num)
3231 {
3232 peer->allowas_in[afi][safi] = allow_num;
3233 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3234 peer_change_action (peer, afi, safi, peer_change_reset_in);
3235 }
3236
3237 }
3238 return 0;
3239}
3240
3241int
3242peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3243{
3244 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003245 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003246
3247 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3248 {
3249 peer->allowas_in[afi][safi] = 0;
3250 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3251 }
3252
3253 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3254 return 0;
3255
3256 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003257 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003258 {
3259 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3260 {
3261 peer->allowas_in[afi][safi] = 0;
3262 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3263 }
3264 }
3265 return 0;
3266}
3267
3268int
3269peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3270{
3271 struct bgp *bgp = peer->bgp;
3272 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003273 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003274
3275 if (peer_sort (peer) != BGP_PEER_EBGP
3276 && peer_sort (peer) != BGP_PEER_INTERNAL)
3277 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3278
3279 if (bgp->as == as)
3280 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3281
3282 if (peer_group_active (peer))
3283 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3284
3285 if (peer->change_local_as == as &&
3286 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3287 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3288 return 0;
3289
3290 peer->change_local_as = as;
3291 if (no_prepend)
3292 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3293 else
3294 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3295
3296 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3297 {
3298 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003299 {
3300 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3301 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3302 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3303 }
paul718e3742002-12-13 20:15:29 +00003304 else
3305 BGP_EVENT_ADD (peer, BGP_Stop);
3306
3307 return 0;
3308 }
3309
3310 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003311 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003312 {
3313 peer->change_local_as = as;
3314 if (no_prepend)
3315 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3316 else
3317 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3318
3319 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003320 {
3321 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3322 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3323 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3324 }
paul718e3742002-12-13 20:15:29 +00003325 else
3326 BGP_EVENT_ADD (peer, BGP_Stop);
3327 }
3328
3329 return 0;
3330}
3331
3332int
3333peer_local_as_unset (struct peer *peer)
3334{
3335 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003336 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003337
3338 if (peer_group_active (peer))
3339 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3340
3341 if (! peer->change_local_as)
3342 return 0;
3343
3344 peer->change_local_as = 0;
3345 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3346
3347 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3348 {
3349 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003350 {
3351 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3352 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3353 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3354 }
paul718e3742002-12-13 20:15:29 +00003355 else
3356 BGP_EVENT_ADD (peer, BGP_Stop);
3357
3358 return 0;
3359 }
3360
3361 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003362 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003363 {
3364 peer->change_local_as = 0;
3365 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3366
3367 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003368 {
3369 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3370 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3371 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3372 }
paul718e3742002-12-13 20:15:29 +00003373 else
3374 BGP_EVENT_ADD (peer, BGP_Stop);
3375 }
3376 return 0;
3377}
3378
3379/* Set distribute list to the peer. */
3380int
3381peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003382 const char *name)
paul718e3742002-12-13 20:15:29 +00003383{
3384 struct bgp_filter *filter;
3385 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003386 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003387
3388 if (! peer->afc[afi][safi])
3389 return BGP_ERR_PEER_INACTIVE;
3390
3391 if (direct != FILTER_IN && direct != FILTER_OUT)
3392 return BGP_ERR_INVALID_VALUE;
3393
3394 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3395 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3396
3397 filter = &peer->filter[afi][safi];
3398
3399 if (filter->plist[direct].name)
3400 return BGP_ERR_PEER_FILTER_CONFLICT;
3401
3402 if (filter->dlist[direct].name)
3403 free (filter->dlist[direct].name);
3404 filter->dlist[direct].name = strdup (name);
3405 filter->dlist[direct].alist = access_list_lookup (afi, name);
3406
3407 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3408 return 0;
3409
3410 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003411 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003412 {
3413 filter = &peer->filter[afi][safi];
3414
3415 if (! peer->af_group[afi][safi])
3416 continue;
3417
3418 if (filter->dlist[direct].name)
3419 free (filter->dlist[direct].name);
3420 filter->dlist[direct].name = strdup (name);
3421 filter->dlist[direct].alist = access_list_lookup (afi, name);
3422 }
3423
3424 return 0;
3425}
3426
3427int
3428peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3429{
3430 struct bgp_filter *filter;
3431 struct bgp_filter *gfilter;
3432 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003433 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003434
3435 if (! peer->afc[afi][safi])
3436 return BGP_ERR_PEER_INACTIVE;
3437
3438 if (direct != FILTER_IN && direct != FILTER_OUT)
3439 return BGP_ERR_INVALID_VALUE;
3440
3441 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3442 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3443
3444 filter = &peer->filter[afi][safi];
3445
3446 /* apply peer-group filter */
3447 if (peer->af_group[afi][safi])
3448 {
3449 gfilter = &peer->group->conf->filter[afi][safi];
3450
3451 if (gfilter->dlist[direct].name)
3452 {
3453 if (filter->dlist[direct].name)
3454 free (filter->dlist[direct].name);
3455 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3456 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3457 return 0;
3458 }
3459 }
3460
3461 if (filter->dlist[direct].name)
3462 free (filter->dlist[direct].name);
3463 filter->dlist[direct].name = NULL;
3464 filter->dlist[direct].alist = NULL;
3465
3466 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3467 return 0;
3468
3469 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003470 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003471 {
3472 filter = &peer->filter[afi][safi];
3473
3474 if (! peer->af_group[afi][safi])
3475 continue;
3476
3477 if (filter->dlist[direct].name)
3478 free (filter->dlist[direct].name);
3479 filter->dlist[direct].name = NULL;
3480 filter->dlist[direct].alist = NULL;
3481 }
3482
3483 return 0;
3484}
3485
3486/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003487static void
paul718e3742002-12-13 20:15:29 +00003488peer_distribute_update (struct access_list *access)
3489{
3490 afi_t afi;
3491 safi_t safi;
3492 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003493 struct listnode *mnode, *mnnode;
3494 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003495 struct bgp *bgp;
3496 struct peer *peer;
3497 struct peer_group *group;
3498 struct bgp_filter *filter;
3499
paul1eb8ef22005-04-07 07:30:20 +00003500 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003501 {
paul1eb8ef22005-04-07 07:30:20 +00003502 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003503 {
3504 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3505 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3506 {
3507 filter = &peer->filter[afi][safi];
3508
3509 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3510 {
3511 if (filter->dlist[direct].name)
3512 filter->dlist[direct].alist =
3513 access_list_lookup (afi, filter->dlist[direct].name);
3514 else
3515 filter->dlist[direct].alist = NULL;
3516 }
3517 }
3518 }
paul1eb8ef22005-04-07 07:30:20 +00003519 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003520 {
3521 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3522 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3523 {
3524 filter = &group->conf->filter[afi][safi];
3525
3526 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3527 {
3528 if (filter->dlist[direct].name)
3529 filter->dlist[direct].alist =
3530 access_list_lookup (afi, filter->dlist[direct].name);
3531 else
3532 filter->dlist[direct].alist = NULL;
3533 }
3534 }
3535 }
3536 }
3537}
3538
3539/* Set prefix list to the peer. */
3540int
3541peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003542 const char *name)
paul718e3742002-12-13 20:15:29 +00003543{
3544 struct bgp_filter *filter;
3545 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003546 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003547
3548 if (! peer->afc[afi][safi])
3549 return BGP_ERR_PEER_INACTIVE;
3550
3551 if (direct != FILTER_IN && direct != FILTER_OUT)
3552 return BGP_ERR_INVALID_VALUE;
3553
3554 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3555 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3556
3557 filter = &peer->filter[afi][safi];
3558
3559 if (filter->dlist[direct].name)
3560 return BGP_ERR_PEER_FILTER_CONFLICT;
3561
3562 if (filter->plist[direct].name)
3563 free (filter->plist[direct].name);
3564 filter->plist[direct].name = strdup (name);
3565 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3566
3567 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3568 return 0;
3569
3570 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003571 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003572 {
3573 filter = &peer->filter[afi][safi];
3574
3575 if (! peer->af_group[afi][safi])
3576 continue;
3577
3578 if (filter->plist[direct].name)
3579 free (filter->plist[direct].name);
3580 filter->plist[direct].name = strdup (name);
3581 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3582 }
3583 return 0;
3584}
3585
3586int
3587peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3588{
3589 struct bgp_filter *filter;
3590 struct bgp_filter *gfilter;
3591 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003592 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003593
3594 if (! peer->afc[afi][safi])
3595 return BGP_ERR_PEER_INACTIVE;
3596
3597 if (direct != FILTER_IN && direct != FILTER_OUT)
3598 return BGP_ERR_INVALID_VALUE;
3599
3600 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3601 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3602
3603 filter = &peer->filter[afi][safi];
3604
3605 /* apply peer-group filter */
3606 if (peer->af_group[afi][safi])
3607 {
3608 gfilter = &peer->group->conf->filter[afi][safi];
3609
3610 if (gfilter->plist[direct].name)
3611 {
3612 if (filter->plist[direct].name)
3613 free (filter->plist[direct].name);
3614 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3615 filter->plist[direct].plist = gfilter->plist[direct].plist;
3616 return 0;
3617 }
3618 }
3619
3620 if (filter->plist[direct].name)
3621 free (filter->plist[direct].name);
3622 filter->plist[direct].name = NULL;
3623 filter->plist[direct].plist = NULL;
3624
3625 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3626 return 0;
3627
3628 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003629 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003630 {
3631 filter = &peer->filter[afi][safi];
3632
3633 if (! peer->af_group[afi][safi])
3634 continue;
3635
3636 if (filter->plist[direct].name)
3637 free (filter->plist[direct].name);
3638 filter->plist[direct].name = NULL;
3639 filter->plist[direct].plist = NULL;
3640 }
3641
3642 return 0;
3643}
3644
3645/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003646static void
paul718e3742002-12-13 20:15:29 +00003647peer_prefix_list_update (struct prefix_list *plist)
3648{
paul1eb8ef22005-04-07 07:30:20 +00003649 struct listnode *mnode, *mnnode;
3650 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003651 struct bgp *bgp;
3652 struct peer *peer;
3653 struct peer_group *group;
3654 struct bgp_filter *filter;
3655 afi_t afi;
3656 safi_t safi;
3657 int direct;
3658
paul1eb8ef22005-04-07 07:30:20 +00003659 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003660 {
paul1eb8ef22005-04-07 07:30:20 +00003661 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003662 {
3663 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3664 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3665 {
3666 filter = &peer->filter[afi][safi];
3667
3668 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3669 {
3670 if (filter->plist[direct].name)
3671 filter->plist[direct].plist =
3672 prefix_list_lookup (afi, filter->plist[direct].name);
3673 else
3674 filter->plist[direct].plist = NULL;
3675 }
3676 }
3677 }
paul1eb8ef22005-04-07 07:30:20 +00003678 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003679 {
3680 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3681 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3682 {
3683 filter = &group->conf->filter[afi][safi];
3684
3685 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3686 {
3687 if (filter->plist[direct].name)
3688 filter->plist[direct].plist =
3689 prefix_list_lookup (afi, filter->plist[direct].name);
3690 else
3691 filter->plist[direct].plist = NULL;
3692 }
3693 }
3694 }
3695 }
3696}
3697
3698int
3699peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003700 const char *name)
paul718e3742002-12-13 20:15:29 +00003701{
3702 struct bgp_filter *filter;
3703 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003704 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003705
3706 if (! peer->afc[afi][safi])
3707 return BGP_ERR_PEER_INACTIVE;
3708
3709 if (direct != FILTER_IN && direct != FILTER_OUT)
3710 return BGP_ERR_INVALID_VALUE;
3711
3712 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3713 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3714
3715 filter = &peer->filter[afi][safi];
3716
3717 if (filter->aslist[direct].name)
3718 free (filter->aslist[direct].name);
3719 filter->aslist[direct].name = strdup (name);
3720 filter->aslist[direct].aslist = as_list_lookup (name);
3721
3722 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3723 return 0;
3724
3725 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003726 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003727 {
3728 filter = &peer->filter[afi][safi];
3729
3730 if (! peer->af_group[afi][safi])
3731 continue;
3732
3733 if (filter->aslist[direct].name)
3734 free (filter->aslist[direct].name);
3735 filter->aslist[direct].name = strdup (name);
3736 filter->aslist[direct].aslist = as_list_lookup (name);
3737 }
3738 return 0;
3739}
3740
3741int
3742peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3743{
3744 struct bgp_filter *filter;
3745 struct bgp_filter *gfilter;
3746 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003747 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003748
3749 if (! peer->afc[afi][safi])
3750 return BGP_ERR_PEER_INACTIVE;
3751
hassob5f29602005-05-25 21:00:28 +00003752 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00003753 return BGP_ERR_INVALID_VALUE;
3754
hassob5f29602005-05-25 21:00:28 +00003755 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003756 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3757
3758 filter = &peer->filter[afi][safi];
3759
3760 /* apply peer-group filter */
3761 if (peer->af_group[afi][safi])
3762 {
3763 gfilter = &peer->group->conf->filter[afi][safi];
3764
3765 if (gfilter->aslist[direct].name)
3766 {
3767 if (filter->aslist[direct].name)
3768 free (filter->aslist[direct].name);
3769 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
3770 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
3771 return 0;
3772 }
3773 }
3774
3775 if (filter->aslist[direct].name)
3776 free (filter->aslist[direct].name);
3777 filter->aslist[direct].name = NULL;
3778 filter->aslist[direct].aslist = NULL;
3779
3780 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3781 return 0;
3782
3783 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003784 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003785 {
3786 filter = &peer->filter[afi][safi];
3787
3788 if (! peer->af_group[afi][safi])
3789 continue;
3790
3791 if (filter->aslist[direct].name)
3792 free (filter->aslist[direct].name);
3793 filter->aslist[direct].name = NULL;
3794 filter->aslist[direct].aslist = NULL;
3795 }
3796
3797 return 0;
3798}
3799
paul94f2b392005-06-28 12:44:16 +00003800static void
paul718e3742002-12-13 20:15:29 +00003801peer_aslist_update ()
3802{
3803 afi_t afi;
3804 safi_t safi;
3805 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003806 struct listnode *mnode, *mnnode;
3807 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003808 struct bgp *bgp;
3809 struct peer *peer;
3810 struct peer_group *group;
3811 struct bgp_filter *filter;
3812
paul1eb8ef22005-04-07 07:30:20 +00003813 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003814 {
paul1eb8ef22005-04-07 07:30:20 +00003815 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003816 {
3817 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3818 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3819 {
3820 filter = &peer->filter[afi][safi];
3821
3822 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3823 {
3824 if (filter->aslist[direct].name)
3825 filter->aslist[direct].aslist =
3826 as_list_lookup (filter->aslist[direct].name);
3827 else
3828 filter->aslist[direct].aslist = NULL;
3829 }
3830 }
3831 }
paul1eb8ef22005-04-07 07:30:20 +00003832 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003833 {
3834 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3835 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3836 {
3837 filter = &group->conf->filter[afi][safi];
3838
3839 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3840 {
3841 if (filter->aslist[direct].name)
3842 filter->aslist[direct].aslist =
3843 as_list_lookup (filter->aslist[direct].name);
3844 else
3845 filter->aslist[direct].aslist = NULL;
3846 }
3847 }
3848 }
3849 }
3850}
3851
3852/* Set route-map to the peer. */
3853int
3854peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003855 const char *name)
paul718e3742002-12-13 20:15:29 +00003856{
3857 struct bgp_filter *filter;
3858 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003859 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003860
3861 if (! peer->afc[afi][safi])
3862 return BGP_ERR_PEER_INACTIVE;
3863
paulfee0f4c2004-09-13 05:12:46 +00003864 if (direct != RMAP_IN && direct != RMAP_OUT &&
3865 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003866 return BGP_ERR_INVALID_VALUE;
3867
paulfee0f4c2004-09-13 05:12:46 +00003868 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
3869 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003870 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3871
3872 filter = &peer->filter[afi][safi];
3873
3874 if (filter->map[direct].name)
3875 free (filter->map[direct].name);
3876
3877 filter->map[direct].name = strdup (name);
3878 filter->map[direct].map = route_map_lookup_by_name (name);
3879
3880 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3881 return 0;
3882
3883 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003884 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003885 {
3886 filter = &peer->filter[afi][safi];
3887
3888 if (! peer->af_group[afi][safi])
3889 continue;
3890
3891 if (filter->map[direct].name)
3892 free (filter->map[direct].name);
3893 filter->map[direct].name = strdup (name);
3894 filter->map[direct].map = route_map_lookup_by_name (name);
3895 }
3896 return 0;
3897}
3898
3899/* Unset route-map from the peer. */
3900int
3901peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3902{
3903 struct bgp_filter *filter;
3904 struct bgp_filter *gfilter;
3905 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003906 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003907
3908 if (! peer->afc[afi][safi])
3909 return BGP_ERR_PEER_INACTIVE;
3910
hassob5f29602005-05-25 21:00:28 +00003911 if (direct != RMAP_IN && direct != RMAP_OUT &&
3912 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003913 return BGP_ERR_INVALID_VALUE;
3914
hassob5f29602005-05-25 21:00:28 +00003915 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
3916 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003917 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3918
3919 filter = &peer->filter[afi][safi];
3920
3921 /* apply peer-group filter */
3922 if (peer->af_group[afi][safi])
3923 {
3924 gfilter = &peer->group->conf->filter[afi][safi];
3925
3926 if (gfilter->map[direct].name)
3927 {
3928 if (filter->map[direct].name)
3929 free (filter->map[direct].name);
3930 filter->map[direct].name = strdup (gfilter->map[direct].name);
3931 filter->map[direct].map = gfilter->map[direct].map;
3932 return 0;
3933 }
3934 }
3935
3936 if (filter->map[direct].name)
3937 free (filter->map[direct].name);
3938 filter->map[direct].name = NULL;
3939 filter->map[direct].map = NULL;
3940
3941 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3942 return 0;
3943
3944 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003945 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003946 {
3947 filter = &peer->filter[afi][safi];
3948
3949 if (! peer->af_group[afi][safi])
3950 continue;
3951
3952 if (filter->map[direct].name)
3953 free (filter->map[direct].name);
3954 filter->map[direct].name = NULL;
3955 filter->map[direct].map = NULL;
3956 }
3957 return 0;
3958}
3959
3960/* Set unsuppress-map to the peer. */
3961int
paulfd79ac92004-10-13 05:06:08 +00003962peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
3963 const char *name)
paul718e3742002-12-13 20:15:29 +00003964{
3965 struct bgp_filter *filter;
3966 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003967 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003968
3969 if (! peer->afc[afi][safi])
3970 return BGP_ERR_PEER_INACTIVE;
3971
3972 if (peer_is_group_member (peer, afi, safi))
3973 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3974
3975 filter = &peer->filter[afi][safi];
3976
3977 if (filter->usmap.name)
3978 free (filter->usmap.name);
3979
3980 filter->usmap.name = strdup (name);
3981 filter->usmap.map = route_map_lookup_by_name (name);
3982
3983 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3984 return 0;
3985
3986 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003987 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003988 {
3989 filter = &peer->filter[afi][safi];
3990
3991 if (! peer->af_group[afi][safi])
3992 continue;
3993
3994 if (filter->usmap.name)
3995 free (filter->usmap.name);
3996 filter->usmap.name = strdup (name);
3997 filter->usmap.map = route_map_lookup_by_name (name);
3998 }
3999 return 0;
4000}
4001
4002/* Unset route-map from the peer. */
4003int
4004peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4005{
4006 struct bgp_filter *filter;
4007 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004008 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004009
4010 if (! peer->afc[afi][safi])
4011 return BGP_ERR_PEER_INACTIVE;
4012
4013 if (peer_is_group_member (peer, afi, safi))
4014 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4015
4016 filter = &peer->filter[afi][safi];
4017
4018 if (filter->usmap.name)
4019 free (filter->usmap.name);
4020 filter->usmap.name = NULL;
4021 filter->usmap.map = NULL;
4022
4023 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4024 return 0;
4025
4026 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004027 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004028 {
4029 filter = &peer->filter[afi][safi];
4030
4031 if (! peer->af_group[afi][safi])
4032 continue;
4033
4034 if (filter->usmap.name)
4035 free (filter->usmap.name);
4036 filter->usmap.name = NULL;
4037 filter->usmap.map = NULL;
4038 }
4039 return 0;
4040}
4041
4042int
4043peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004044 u_int32_t max, u_char threshold,
4045 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004046{
4047 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004048 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004049
4050 if (! peer->afc[afi][safi])
4051 return BGP_ERR_PEER_INACTIVE;
4052
4053 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4054 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004055 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004056 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004057 if (warning)
4058 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4059 else
4060 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4061
4062 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4063 return 0;
4064
4065 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004066 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004067 {
4068 if (! peer->af_group[afi][safi])
4069 continue;
4070
4071 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4072 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004073 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004074 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004075 if (warning)
4076 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4077 else
4078 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4079 }
4080 return 0;
4081}
4082
4083int
4084peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4085{
4086 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004087 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004088
4089 if (! peer->afc[afi][safi])
4090 return BGP_ERR_PEER_INACTIVE;
4091
4092 /* apply peer-group config */
4093 if (peer->af_group[afi][safi])
4094 {
4095 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4096 PEER_FLAG_MAX_PREFIX))
4097 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4098 else
4099 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4100
4101 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4102 PEER_FLAG_MAX_PREFIX_WARNING))
4103 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4104 else
4105 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4106
4107 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004108 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004109 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004110 return 0;
4111 }
4112
4113 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4114 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4115 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004116 peer->pmax_threshold[afi][safi] = 0;
4117 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004118
4119 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4120 return 0;
4121
4122 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004123 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004124 {
4125 if (! peer->af_group[afi][safi])
4126 continue;
4127
4128 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4129 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4130 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004131 peer->pmax_threshold[afi][safi] = 0;
4132 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004133 }
4134 return 0;
4135}
4136
4137int
4138peer_clear (struct peer *peer)
4139{
4140 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4141 {
hasso0a486e52005-02-01 20:57:17 +00004142 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4143 {
4144 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4145 if (peer->t_pmax_restart)
4146 {
4147 BGP_TIMER_OFF (peer->t_pmax_restart);
4148 if (BGP_DEBUG (events, EVENTS))
4149 zlog_debug ("%s Maximum-prefix restart timer canceled",
4150 peer->host);
4151 }
4152 BGP_EVENT_ADD (peer, BGP_Start);
4153 return 0;
4154 }
4155
paul718e3742002-12-13 20:15:29 +00004156 peer->v_start = BGP_INIT_START_TIMER;
4157 if (peer->status == Established)
4158 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4159 BGP_NOTIFY_CEASE_ADMIN_RESET);
4160 else
4161 BGP_EVENT_ADD (peer, BGP_Stop);
4162 }
4163 return 0;
4164}
4165
4166int
4167peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4168 enum bgp_clear_type stype)
4169{
4170 if (peer->status != Established)
4171 return 0;
4172
4173 if (! peer->afc[afi][safi])
4174 return BGP_ERR_AF_UNCONFIGURED;
4175
paulfee0f4c2004-09-13 05:12:46 +00004176 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4177 {
4178 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4179 return 0;
4180 bgp_check_local_routes_rsclient (peer, afi, safi);
4181 bgp_soft_reconfig_rsclient (peer, afi, safi);
4182 }
4183
paul718e3742002-12-13 20:15:29 +00004184 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4185 bgp_announce_route (peer, afi, safi);
4186
4187 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4188 {
4189 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4190 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4191 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4192 {
4193 struct bgp_filter *filter = &peer->filter[afi][safi];
4194 u_char prefix_type;
4195
4196 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4197 prefix_type = ORF_TYPE_PREFIX;
4198 else
4199 prefix_type = ORF_TYPE_PREFIX_OLD;
4200
4201 if (filter->plist[FILTER_IN].plist)
4202 {
4203 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4204 bgp_route_refresh_send (peer, afi, safi,
4205 prefix_type, REFRESH_DEFER, 1);
4206 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4207 REFRESH_IMMEDIATE, 0);
4208 }
4209 else
4210 {
4211 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4212 bgp_route_refresh_send (peer, afi, safi,
4213 prefix_type, REFRESH_IMMEDIATE, 1);
4214 else
4215 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4216 }
4217 return 0;
4218 }
4219 }
4220
4221 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4222 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4223 {
4224 /* If neighbor has soft reconfiguration inbound flag.
4225 Use Adj-RIB-In database. */
4226 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4227 bgp_soft_reconfig_in (peer, afi, safi);
4228 else
4229 {
4230 /* If neighbor has route refresh capability, send route refresh
4231 message to the peer. */
4232 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4233 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4234 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4235 else
4236 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4237 }
4238 }
4239 return 0;
4240}
4241
paulfd79ac92004-10-13 05:06:08 +00004242/* Display peer uptime.*/
4243/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004244char *
4245peer_uptime (time_t uptime2, char *buf, size_t len)
4246{
4247 time_t uptime1;
4248 struct tm *tm;
4249
4250 /* Check buffer length. */
4251 if (len < BGP_UPTIME_LEN)
4252 {
gdtc29fdba2004-12-09 14:46:46 +00004253 /* XXX: warning: long int format, size_t arg (arg 2) */
paula2b1ecd2004-10-31 18:58:09 +00004254 zlog_warn ("peer_uptime (): buffer shortage %ld", len);
paulfd79ac92004-10-13 05:06:08 +00004255 /* XXX: should return status instead of buf... */
4256 snprintf (buf, len, "<error> ");
4257 return buf;
paul718e3742002-12-13 20:15:29 +00004258 }
4259
4260 /* If there is no connection has been done before print `never'. */
4261 if (uptime2 == 0)
4262 {
4263 snprintf (buf, len, "never ");
4264 return buf;
4265 }
4266
4267 /* Get current time. */
4268 uptime1 = time (NULL);
4269 uptime1 -= uptime2;
4270 tm = gmtime (&uptime1);
4271
4272 /* Making formatted timer strings. */
4273#define ONE_DAY_SECOND 60*60*24
4274#define ONE_WEEK_SECOND 60*60*24*7
4275
4276 if (uptime1 < ONE_DAY_SECOND)
4277 snprintf (buf, len, "%02d:%02d:%02d",
4278 tm->tm_hour, tm->tm_min, tm->tm_sec);
4279 else if (uptime1 < ONE_WEEK_SECOND)
4280 snprintf (buf, len, "%dd%02dh%02dm",
4281 tm->tm_yday, tm->tm_hour, tm->tm_min);
4282 else
4283 snprintf (buf, len, "%02dw%dd%02dh",
4284 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4285 return buf;
4286}
4287
paul94f2b392005-06-28 12:44:16 +00004288static void
paul718e3742002-12-13 20:15:29 +00004289bgp_config_write_filter (struct vty *vty, struct peer *peer,
4290 afi_t afi, safi_t safi)
4291{
4292 struct bgp_filter *filter;
4293 struct bgp_filter *gfilter = NULL;
4294 char *addr;
4295 int in = FILTER_IN;
4296 int out = FILTER_OUT;
4297
4298 addr = peer->host;
4299 filter = &peer->filter[afi][safi];
4300 if (peer->af_group[afi][safi])
4301 gfilter = &peer->group->conf->filter[afi][safi];
4302
4303 /* distribute-list. */
4304 if (filter->dlist[in].name)
4305 if (! gfilter || ! gfilter->dlist[in].name
4306 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4307 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4308 filter->dlist[in].name, VTY_NEWLINE);
4309 if (filter->dlist[out].name && ! gfilter)
4310 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4311 filter->dlist[out].name, VTY_NEWLINE);
4312
4313 /* prefix-list. */
4314 if (filter->plist[in].name)
4315 if (! gfilter || ! gfilter->plist[in].name
4316 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4317 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4318 filter->plist[in].name, VTY_NEWLINE);
4319 if (filter->plist[out].name && ! gfilter)
4320 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4321 filter->plist[out].name, VTY_NEWLINE);
4322
4323 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004324 if (filter->map[RMAP_IN].name)
4325 if (! gfilter || ! gfilter->map[RMAP_IN].name
4326 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004327 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004328 filter->map[RMAP_IN].name, VTY_NEWLINE);
4329 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004330 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004331 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4332 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4333 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4334 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4335 if (filter->map[RMAP_EXPORT].name)
4336 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4337 || strcmp (filter->map[RMAP_EXPORT].name,
4338 gfilter->map[RMAP_EXPORT].name) != 0)
4339 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4340 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004341
4342 /* unsuppress-map */
4343 if (filter->usmap.name && ! gfilter)
4344 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4345 filter->usmap.name, VTY_NEWLINE);
4346
4347 /* filter-list. */
4348 if (filter->aslist[in].name)
4349 if (! gfilter || ! gfilter->aslist[in].name
4350 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4351 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4352 filter->aslist[in].name, VTY_NEWLINE);
4353 if (filter->aslist[out].name && ! gfilter)
4354 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4355 filter->aslist[out].name, VTY_NEWLINE);
4356}
4357
4358/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004359static void
paul718e3742002-12-13 20:15:29 +00004360bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4361 struct peer *peer, afi_t afi, safi_t safi)
4362{
4363 struct bgp_filter *filter;
4364 struct peer *g_peer = NULL;
4365 char buf[SU_ADDRSTRLEN];
4366 char *addr;
4367
4368 filter = &peer->filter[afi][safi];
4369 addr = peer->host;
4370 if (peer_group_active (peer))
4371 g_peer = peer->group->conf;
4372
4373 /************************************
4374 ****** Global to the neighbor ******
4375 ************************************/
4376 if (afi == AFI_IP && safi == SAFI_UNICAST)
4377 {
4378 /* remote-as. */
4379 if (! peer_group_active (peer))
4380 {
4381 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4382 vty_out (vty, " neighbor %s peer-group%s", addr,
4383 VTY_NEWLINE);
4384 if (peer->as)
4385 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4386 VTY_NEWLINE);
4387 }
4388 else
4389 {
4390 if (! g_peer->as)
4391 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4392 VTY_NEWLINE);
4393 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4394 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4395 peer->group->name, VTY_NEWLINE);
4396 }
4397
4398 /* local-as. */
4399 if (peer->change_local_as)
4400 if (! peer_group_active (peer))
4401 vty_out (vty, " neighbor %s local-as %d%s%s", addr,
4402 peer->change_local_as,
4403 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4404 " no-prepend" : "", VTY_NEWLINE);
4405
4406 /* Description. */
4407 if (peer->desc)
4408 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4409 VTY_NEWLINE);
4410
4411 /* Shutdown. */
4412 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4413 if (! peer_group_active (peer) ||
4414 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4415 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4416
4417 /* BGP port. */
4418 if (peer->port != BGP_PORT_DEFAULT)
4419 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
4420 VTY_NEWLINE);
4421
4422 /* Local interface name. */
4423 if (peer->ifname)
4424 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4425 VTY_NEWLINE);
4426
4427 /* Passive. */
4428 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4429 if (! peer_group_active (peer) ||
4430 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4431 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4432
4433 /* EBGP multihop. */
4434 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
4435 if (! peer_group_active (peer) ||
4436 g_peer->ttl != peer->ttl)
4437 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4438 VTY_NEWLINE);
4439
hasso6ffd2072005-02-02 14:50:11 +00004440 /* disable-connected-check. */
4441 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004442 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004443 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4444 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004445
4446 /* Update-source. */
4447 if (peer->update_if)
4448 if (! peer_group_active (peer) || ! g_peer->update_if
4449 || strcmp (g_peer->update_if, peer->update_if) != 0)
4450 vty_out (vty, " neighbor %s update-source %s%s", addr,
4451 peer->update_if, VTY_NEWLINE);
4452 if (peer->update_source)
4453 if (! peer_group_active (peer) || ! g_peer->update_source
4454 || sockunion_cmp (g_peer->update_source,
4455 peer->update_source) != 0)
4456 vty_out (vty, " neighbor %s update-source %s%s", addr,
4457 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4458 VTY_NEWLINE);
4459
paul718e3742002-12-13 20:15:29 +00004460 /* advertisement-interval */
4461 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4462 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4463 addr, peer->v_routeadv, VTY_NEWLINE);
4464
4465 /* timers. */
4466 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4467 && ! peer_group_active (peer))
4468 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4469 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4470
4471 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4472 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4473 peer->connect, VTY_NEWLINE);
4474
4475 /* Default weight. */
4476 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4477 if (! peer_group_active (peer) ||
4478 g_peer->weight != peer->weight)
4479 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4480 VTY_NEWLINE);
4481
paul718e3742002-12-13 20:15:29 +00004482 /* Dynamic capability. */
4483 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4484 if (! peer_group_active (peer) ||
4485 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4486 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4487 VTY_NEWLINE);
4488
4489 /* dont capability negotiation. */
4490 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4491 if (! peer_group_active (peer) ||
4492 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4493 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4494 VTY_NEWLINE);
4495
4496 /* override capability negotiation. */
4497 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4498 if (! peer_group_active (peer) ||
4499 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4500 vty_out (vty, " neighbor %s override-capability%s", addr,
4501 VTY_NEWLINE);
4502
4503 /* strict capability negotiation. */
4504 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4505 if (! peer_group_active (peer) ||
4506 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4507 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4508 VTY_NEWLINE);
4509
4510 if (! peer_group_active (peer))
4511 {
4512 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4513 {
4514 if (peer->afc[AFI_IP][SAFI_UNICAST])
4515 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4516 }
4517 else
4518 {
4519 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4520 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4521 }
4522 }
4523 }
4524
4525
4526 /************************************
4527 ****** Per AF to the neighbor ******
4528 ************************************/
4529
4530 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4531 {
4532 if (peer->af_group[afi][safi])
4533 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4534 peer->group->name, VTY_NEWLINE);
4535 else
4536 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4537 }
4538
4539 /* ORF capability. */
4540 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4541 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4542 if (! peer->af_group[afi][safi])
4543 {
4544 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4545
4546 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4547 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4548 vty_out (vty, " both");
4549 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4550 vty_out (vty, " send");
4551 else
4552 vty_out (vty, " receive");
4553 vty_out (vty, "%s", VTY_NEWLINE);
4554 }
4555
4556 /* Route reflector client. */
4557 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4558 && ! peer->af_group[afi][safi])
4559 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4560 VTY_NEWLINE);
4561
4562 /* Nexthop self. */
4563 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4564 && ! peer->af_group[afi][safi])
4565 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4566
4567 /* Remove private AS. */
4568 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4569 && ! peer->af_group[afi][safi])
4570 vty_out (vty, " neighbor %s remove-private-AS%s",
4571 addr, VTY_NEWLINE);
4572
4573 /* send-community print. */
4574 if (! peer->af_group[afi][safi])
4575 {
4576 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4577 {
4578 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4579 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4580 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4581 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4582 vty_out (vty, " neighbor %s send-community extended%s",
4583 addr, VTY_NEWLINE);
4584 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4585 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4586 }
4587 else
4588 {
4589 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4590 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4591 vty_out (vty, " no neighbor %s send-community both%s",
4592 addr, VTY_NEWLINE);
4593 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4594 vty_out (vty, " no neighbor %s send-community extended%s",
4595 addr, VTY_NEWLINE);
4596 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4597 vty_out (vty, " no neighbor %s send-community%s",
4598 addr, VTY_NEWLINE);
4599 }
4600 }
4601
4602 /* Default information */
4603 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4604 && ! peer->af_group[afi][safi])
4605 {
4606 vty_out (vty, " neighbor %s default-originate", addr);
4607 if (peer->default_rmap[afi][safi].name)
4608 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4609 vty_out (vty, "%s", VTY_NEWLINE);
4610 }
4611
4612 /* Soft reconfiguration inbound. */
4613 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4614 if (! peer->af_group[afi][safi] ||
4615 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4616 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4617 VTY_NEWLINE);
4618
4619 /* maximum-prefix. */
4620 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4621 if (! peer->af_group[afi][safi]
4622 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004623 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004624 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4625 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00004626 {
hasso0a486e52005-02-01 20:57:17 +00004627 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
4628 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
4629 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
4630 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
4631 vty_out (vty, " warning-only");
4632 if (peer->pmax_restart[afi][safi])
4633 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
4634 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00004635 }
paul718e3742002-12-13 20:15:29 +00004636
4637 /* Route server client. */
4638 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
4639 && ! peer->af_group[afi][safi])
4640 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
4641
4642 /* Allow AS in. */
4643 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
4644 if (! peer_group_active (peer)
4645 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
4646 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
4647 {
4648 if (peer->allowas_in[afi][safi] == 3)
4649 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
4650 else
4651 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
4652 peer->allowas_in[afi][safi], VTY_NEWLINE);
4653 }
4654
4655 /* Filter. */
4656 bgp_config_write_filter (vty, peer, afi, safi);
4657
4658 /* atribute-unchanged. */
4659 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4660 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4661 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4662 && ! peer->af_group[afi][safi])
4663 {
4664 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4665 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4666 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4667 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
4668 else
4669 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
4670 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
4671 " as-path" : "",
4672 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
4673 " next-hop" : "",
4674 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
4675 " med" : "", VTY_NEWLINE);
4676 }
4677}
4678
4679/* Display "address-family" configuration header. */
4680void
4681bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
4682 int *write)
4683{
4684 if (*write)
4685 return;
4686
4687 if (afi == AFI_IP && safi == SAFI_UNICAST)
4688 return;
4689
4690 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
4691
4692 if (afi == AFI_IP)
4693 {
4694 if (safi == SAFI_MULTICAST)
4695 vty_out (vty, "ipv4 multicast");
4696 else if (safi == SAFI_MPLS_VPN)
4697 vty_out (vty, "vpnv4 unicast");
4698 }
4699 else if (afi == AFI_IP6)
4700 vty_out (vty, "ipv6");
4701
4702 vty_out (vty, "%s", VTY_NEWLINE);
4703
4704 *write = 1;
4705}
4706
4707/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00004708static int
paul718e3742002-12-13 20:15:29 +00004709bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
4710 safi_t safi)
4711{
4712 int write = 0;
4713 struct peer *peer;
4714 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004715 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004716
4717 bgp_config_write_network (vty, bgp, afi, safi, &write);
4718
4719 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
4720
paul1eb8ef22005-04-07 07:30:20 +00004721 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004722 {
4723 if (group->conf->afc[afi][safi])
4724 {
4725 bgp_config_write_family_header (vty, afi, safi, &write);
4726 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
4727 }
4728 }
paul1eb8ef22005-04-07 07:30:20 +00004729 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004730 {
4731 if (peer->afc[afi][safi])
4732 {
4733 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4734 {
4735 bgp_config_write_family_header (vty, afi, safi, &write);
4736 bgp_config_write_peer (vty, bgp, peer, afi, safi);
4737 }
4738 }
4739 }
4740 if (write)
4741 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
4742
4743 return write;
4744}
4745
4746int
4747bgp_config_write (struct vty *vty)
4748{
4749 int write = 0;
4750 struct bgp *bgp;
4751 struct peer_group *group;
4752 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004753 struct listnode *node, *nnode;
4754 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00004755
4756 /* BGP Multiple instance. */
4757 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4758 {
4759 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
4760 write++;
4761 }
4762
4763 /* BGP Config type. */
4764 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4765 {
4766 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
4767 write++;
4768 }
4769
4770 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004771 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004772 {
4773 if (write)
4774 vty_out (vty, "!%s", VTY_NEWLINE);
4775
4776 /* Router bgp ASN */
4777 vty_out (vty, "router bgp %d", bgp->as);
4778
4779 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4780 {
4781 if (bgp->name)
4782 vty_out (vty, " view %s", bgp->name);
4783 }
4784 vty_out (vty, "%s", VTY_NEWLINE);
4785
4786 /* No Synchronization */
4787 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4788 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
4789
4790 /* BGP fast-external-failover. */
4791 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
4792 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
4793
4794 /* BGP router ID. */
4795 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
4796 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
4797 VTY_NEWLINE);
4798
paul848973c2003-08-13 00:32:49 +00004799 /* BGP log-neighbor-changes. */
4800 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
4801 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
4802
paul718e3742002-12-13 20:15:29 +00004803 /* BGP configuration. */
4804 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
4805 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
4806
4807 /* BGP default ipv4-unicast. */
4808 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4809 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
4810
4811 /* BGP default local-preference. */
4812 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
4813 vty_out (vty, " bgp default local-preference %d%s",
4814 bgp->default_local_pref, VTY_NEWLINE);
4815
4816 /* BGP client-to-client reflection. */
4817 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
4818 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
4819
4820 /* BGP cluster ID. */
4821 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
4822 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
4823 VTY_NEWLINE);
4824
hassoe0701b72004-05-20 09:19:34 +00004825 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00004826 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00004827 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
4828 VTY_NEWLINE);
4829
4830 /* Confederation peer */
4831 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00004832 {
hassoe0701b72004-05-20 09:19:34 +00004833 int i;
paul718e3742002-12-13 20:15:29 +00004834
hassoe0701b72004-05-20 09:19:34 +00004835 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00004836
hassoe0701b72004-05-20 09:19:34 +00004837 for (i = 0; i < bgp->confed_peers_cnt; i++)
4838 vty_out(vty, " %d", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00004839
hassoe0701b72004-05-20 09:19:34 +00004840 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004841 }
4842
4843 /* BGP enforce-first-as. */
4844 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
4845 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
4846
4847 /* BGP deterministic-med. */
4848 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
4849 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00004850
4851 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00004852 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
4853 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
4854 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00004855 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
4856 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
4857
paul718e3742002-12-13 20:15:29 +00004858 /* BGP bestpath method. */
4859 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
4860 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00004861 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
4862 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004863 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
4864 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
4865 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
4866 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4867 {
4868 vty_out (vty, " bgp bestpath med");
4869 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
4870 vty_out (vty, " confed");
4871 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4872 vty_out (vty, " missing-as-worst");
4873 vty_out (vty, "%s", VTY_NEWLINE);
4874 }
4875
4876 /* BGP network import check. */
4877 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
4878 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
4879
4880 /* BGP scan interval. */
4881 bgp_config_write_scan_time (vty);
4882
4883 /* BGP flag dampening. */
4884 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
4885 BGP_CONFIG_DAMPENING))
4886 bgp_config_write_damp (vty);
4887
4888 /* BGP static route configuration. */
4889 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4890
4891 /* BGP redistribute configuration. */
4892 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4893
4894 /* BGP timers configuration. */
4895 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
4896 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
4897 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
4898 bgp->default_holdtime, VTY_NEWLINE);
4899
4900 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00004901 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004902 {
4903 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
4904 }
4905
4906 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004907 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004908 {
4909 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4910 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
4911 }
4912
4913 /* Distance configuration. */
4914 bgp_config_write_distance (vty, bgp);
4915
4916 /* No auto-summary */
4917 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4918 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
4919
4920 /* IPv4 multicast configuration. */
4921 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
4922
4923 /* IPv4 VPN configuration. */
4924 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
4925
4926 /* IPv6 unicast configuration. */
4927 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
4928
4929 write++;
4930 }
4931 return write;
4932}
4933
4934void
paul94f2b392005-06-28 12:44:16 +00004935bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00004936{
4937 memset (&bgp_master, 0, sizeof (struct bgp_master));
4938
4939 bm = &bgp_master;
4940 bm->bgp = list_new ();
4941 bm->port = BGP_PORT_DEFAULT;
4942 bm->master = thread_master_create ();
4943 bm->start_time = time (NULL);
4944}
paul200df112005-06-01 11:17:05 +00004945
paul718e3742002-12-13 20:15:29 +00004946
4947void
paul94f2b392005-06-28 12:44:16 +00004948bgp_init (void)
paul718e3742002-12-13 20:15:29 +00004949{
paul718e3742002-12-13 20:15:29 +00004950 /* BGP VTY commands installation. */
4951 bgp_vty_init ();
4952
4953 /* Create BGP server socket. */
4954 bgp_socket (NULL, bm->port);
4955
4956 /* Init zebra. */
4957 bgp_zebra_init ();
4958
4959 /* BGP inits. */
4960 bgp_attr_init ();
4961 bgp_debug_init ();
4962 bgp_dump_init ();
4963 bgp_route_init ();
4964 bgp_route_map_init ();
4965 bgp_scan_init ();
4966 bgp_mplsvpn_init ();
4967
4968 /* Access list initialize. */
4969 access_list_init ();
4970 access_list_add_hook (peer_distribute_update);
4971 access_list_delete_hook (peer_distribute_update);
4972
4973 /* Filter list initialize. */
4974 bgp_filter_init ();
4975 as_list_add_hook (peer_aslist_update);
4976 as_list_delete_hook (peer_aslist_update);
4977
4978 /* Prefix list initialize.*/
4979 prefix_list_init ();
4980 prefix_list_add_hook (peer_prefix_list_update);
4981 prefix_list_delete_hook (peer_prefix_list_update);
4982
4983 /* Community list initialize. */
4984 bgp_clist = community_list_init ();
4985
4986#ifdef HAVE_SNMP
4987 bgp_snmp_init ();
4988#endif /* HAVE_SNMP */
4989}
paul545acaf2004-04-20 15:13:15 +00004990
4991void
4992bgp_terminate ()
4993{
paul545acaf2004-04-20 15:13:15 +00004994 struct bgp *bgp;
4995 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004996 struct listnode *node, *nnode;
4997 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00004998
paul1eb8ef22005-04-07 07:30:20 +00004999 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5000 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005001 if (peer->status == Established)
5002 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5003 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005004
paul545acaf2004-04-20 15:13:15 +00005005 bgp_cleanup_routes ();
paule210cf92005-06-15 19:15:35 +00005006 if (bm->process_main_queue)
5007 work_queue_free (bm->process_main_queue);
5008 if (bm->process_rsclient_queue)
5009 work_queue_free (bm->process_rsclient_queue);
paul545acaf2004-04-20 15:13:15 +00005010}
5011