blob: 733b33a6aa42c0d7b6c9be4bfb82808d5ee0fb27 [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);
698
paul200df112005-06-01 11:17:05 +0000699 if (peer->desc)
700 XFREE (MTYPE_PEER_DESC, peer->desc);
701
702 /* Free allocated host character. */
703 if (peer->host)
704 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
705
706 /* Update source configuration. */
707 if (peer->update_source)
708 sockunion_free (peer->update_source);
709
710 if (peer->update_if)
711 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
Paul Jakmaa625ca32006-03-30 14:12:38 +0000712
713 if (peer->clear_node_queue)
714 work_queue_free (peer->clear_node_queue);
715
Paul Jakmaca058a32006-09-14 02:58:49 +0000716 bgp_sync_delete (peer);
paul200df112005-06-01 11:17:05 +0000717 memset (peer, 0, sizeof (struct peer));
718
719 XFREE (MTYPE_BGP_PEER, peer);
720}
721
722/* increase reference count on a struct peer */
723struct peer *
724peer_lock (struct peer *peer)
725{
726 assert (peer && (peer->lock >= 0));
Paul Jakmaca058a32006-09-14 02:58:49 +0000727 assert (peer->status != Deleted);
728
paul200df112005-06-01 11:17:05 +0000729 peer->lock++;
730
731 return peer;
732}
733
734/* decrease reference count on a struct peer
735 * struct peer is freed and NULL returned if last reference
736 */
737struct peer *
738peer_unlock (struct peer *peer)
739{
740 assert (peer && (peer->lock > 0));
741
742 peer->lock--;
743
744 if (peer->lock == 0)
745 {
746#if 0
747 zlog_debug ("unlocked and freeing");
748 zlog_backtrace (LOG_DEBUG);
749#endif
750 peer_free (peer);
751 return NULL;
752 }
753
754#if 0
755 if (peer->lock == 1)
756 {
757 zlog_debug ("unlocked to 1");
758 zlog_backtrace (LOG_DEBUG);
759 }
760#endif
761
762 return peer;
763}
764
765/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000766static struct peer *
767peer_new ()
768{
769 afi_t afi;
770 safi_t safi;
771 struct peer *peer;
772 struct servent *sp;
773
774 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000775 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000776
777 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000778 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000779 peer->v_start = BGP_INIT_START_TIMER;
780 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
781 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
782 peer->status = Idle;
783 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000784 peer->weight = 0;
Paul Jakmaca058a32006-09-14 02:58:49 +0000785 peer = peer_lock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +0000786
787 /* Set default flags. */
788 for (afi = AFI_IP; afi < AFI_MAX; afi++)
789 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
790 {
791 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
792 {
793 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
794 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
795 }
796 peer->orf_plist[afi][safi] = NULL;
797 }
798 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
799
800 /* Create buffers. */
801 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
802 peer->obuf = stream_fifo_new ();
803 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
804
805 bgp_sync_init (peer);
806
807 /* Get service port number. */
808 sp = getservbyname ("bgp", "tcp");
809 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
810
811 return peer;
812}
813
814/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000815static struct peer *
paul718e3742002-12-13 20:15:29 +0000816peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
817 as_t remote_as, afi_t afi, safi_t safi)
818{
819 int active;
820 struct peer *peer;
821 char buf[SU_ADDRSTRLEN];
822
823 peer = peer_new ();
824 peer->bgp = bgp;
825 peer->su = *su;
826 peer->local_as = local_as;
827 peer->as = remote_as;
828 peer->local_id = bgp->router_id;
829 peer->v_holdtime = bgp->default_holdtime;
830 peer->v_keepalive = bgp->default_keepalive;
831 if (peer_sort (peer) == BGP_PEER_IBGP)
832 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
833 else
834 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000835
836 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000837 listnode_add_sort (bgp->peer, peer);
838
839 active = peer_active (peer);
840
841 if (afi && safi)
842 peer->afc[afi][safi] = 1;
843
844 /* Last read time set */
845 peer->readtime = time (NULL);
846
paul848973c2003-08-13 00:32:49 +0000847 /* Last reset time set */
848 peer->resettime = time (NULL);
849
paul718e3742002-12-13 20:15:29 +0000850 /* Default TTL set. */
851 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
852
853 /* Make peer's address string. */
854 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000855 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000856
857 /* Set up peer's events and timers. */
858 if (! active && peer_active (peer))
859 bgp_timer_set (peer);
860
861 return peer;
862}
863
pauleb821182004-05-01 08:44:08 +0000864/* Make accept BGP peer. Called from bgp_accept (). */
865struct peer *
866peer_create_accept (struct bgp *bgp)
867{
868 struct peer *peer;
869
870 peer = peer_new ();
871 peer->bgp = bgp;
paul200df112005-06-01 11:17:05 +0000872
873 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000874 listnode_add_sort (bgp->peer, peer);
875
876 return peer;
877}
878
paul718e3742002-12-13 20:15:29 +0000879/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000880static void
paul718e3742002-12-13 20:15:29 +0000881peer_as_change (struct peer *peer, as_t as)
882{
883 int type;
884
885 /* Stop peer. */
886 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
887 {
888 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000889 {
890 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
891 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
892 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
893 }
paul718e3742002-12-13 20:15:29 +0000894 else
895 BGP_EVENT_ADD (peer, BGP_Stop);
896 }
897 type = peer_sort (peer);
898 peer->as = as;
899
paul848973c2003-08-13 00:32:49 +0000900 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
901 && ! bgp_confederation_peers_check (peer->bgp, as)
902 && peer->bgp->as != as)
903 peer->local_as = peer->bgp->confed_id;
904 else
905 peer->local_as = peer->bgp->as;
906
paul718e3742002-12-13 20:15:29 +0000907 /* Advertisement-interval reset */
908 if (peer_sort (peer) == BGP_PEER_IBGP)
909 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
910 else
911 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
912
913 /* TTL reset */
914 if (peer_sort (peer) == BGP_PEER_IBGP)
915 peer->ttl = 255;
916 else if (type == BGP_PEER_IBGP)
917 peer->ttl = 1;
918
919 /* reflector-client reset */
920 if (peer_sort (peer) != BGP_PEER_IBGP)
921 {
922 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
923 PEER_FLAG_REFLECTOR_CLIENT);
924 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
925 PEER_FLAG_REFLECTOR_CLIENT);
926 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
927 PEER_FLAG_REFLECTOR_CLIENT);
928 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
929 PEER_FLAG_REFLECTOR_CLIENT);
930 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
931 PEER_FLAG_REFLECTOR_CLIENT);
932 }
933
934 /* local-as reset */
935 if (peer_sort (peer) != BGP_PEER_EBGP)
936 {
937 peer->change_local_as = 0;
938 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
939 }
940}
941
942/* If peer does not exist, create new one. If peer already exists,
943 set AS number to the peer. */
944int
945peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
946 afi_t afi, safi_t safi)
947{
948 struct peer *peer;
949 as_t local_as;
950
951 peer = peer_lookup (bgp, su);
952
953 if (peer)
954 {
955 /* When this peer is a member of peer-group. */
956 if (peer->group)
957 {
958 if (peer->group->conf->as)
959 {
960 /* Return peer group's AS number. */
961 *as = peer->group->conf->as;
962 return BGP_ERR_PEER_GROUP_MEMBER;
963 }
964 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
965 {
966 if (bgp->as != *as)
967 {
968 *as = peer->as;
969 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
970 }
971 }
972 else
973 {
974 if (bgp->as == *as)
975 {
976 *as = peer->as;
977 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
978 }
979 }
980 }
981
982 /* Existing peer's AS number change. */
983 if (peer->as != *as)
984 peer_as_change (peer, *as);
985 }
986 else
987 {
988
989 /* If the peer is not part of our confederation, and its not an
990 iBGP peer then spoof the source AS */
991 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
992 && ! bgp_confederation_peers_check (bgp, *as)
993 && bgp->as != *as)
994 local_as = bgp->confed_id;
995 else
996 local_as = bgp->as;
997
998 /* If this is IPv4 unicast configuration and "no bgp default
999 ipv4-unicast" is specified. */
1000
1001 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1002 && afi == AFI_IP && safi == SAFI_UNICAST)
1003 peer = peer_create (su, bgp, local_as, *as, 0, 0);
1004 else
1005 peer = peer_create (su, bgp, local_as, *as, afi, safi);
1006 }
1007
1008 return 0;
1009}
1010
1011/* Activate the peer or peer group for specified AFI and SAFI. */
1012int
1013peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1014{
1015 int active;
1016
1017 if (peer->afc[afi][safi])
1018 return 0;
1019
1020 /* Activate the address family configuration. */
1021 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1022 peer->afc[afi][safi] = 1;
1023 else
1024 {
1025 active = peer_active (peer);
1026
1027 peer->afc[afi][safi] = 1;
1028
1029 if (! active && peer_active (peer))
1030 bgp_timer_set (peer);
1031 else
1032 {
1033 if (peer->status == Established)
1034 {
1035 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1036 {
1037 peer->afc_adv[afi][safi] = 1;
1038 bgp_capability_send (peer, afi, safi,
1039 CAPABILITY_CODE_MP,
1040 CAPABILITY_ACTION_SET);
1041 if (peer->afc_recv[afi][safi])
1042 {
1043 peer->afc_nego[afi][safi] = 1;
1044 bgp_announce_route (peer, afi, safi);
1045 }
1046 }
1047 else
hassoe0701b72004-05-20 09:19:34 +00001048 {
1049 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1050 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1051 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1052 }
paul718e3742002-12-13 20:15:29 +00001053 }
1054 }
1055 }
1056 return 0;
1057}
1058
1059int
1060peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1061{
1062 struct peer_group *group;
1063 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001064 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001065
1066 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1067 {
1068 group = peer->group;
1069
paul1eb8ef22005-04-07 07:30:20 +00001070 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001071 {
1072 if (peer1->af_group[afi][safi])
1073 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1074 }
1075 }
1076 else
1077 {
1078 if (peer->af_group[afi][safi])
1079 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1080 }
1081
1082 if (! peer->afc[afi][safi])
1083 return 0;
1084
1085 /* De-activate the address family configuration. */
1086 peer->afc[afi][safi] = 0;
1087 peer_af_flag_reset (peer, afi, safi);
1088
1089 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1090 {
1091 if (peer->status == Established)
1092 {
1093 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1094 {
1095 peer->afc_adv[afi][safi] = 0;
1096 peer->afc_nego[afi][safi] = 0;
1097
1098 if (peer_active_nego (peer))
1099 {
1100 bgp_capability_send (peer, afi, safi,
1101 CAPABILITY_CODE_MP,
1102 CAPABILITY_ACTION_UNSET);
1103 bgp_clear_route (peer, afi, safi);
1104 peer->pcount[afi][safi] = 0;
1105 }
1106 else
hassoe0701b72004-05-20 09:19:34 +00001107 {
1108 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1109 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1110 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1111 }
paul718e3742002-12-13 20:15:29 +00001112 }
1113 else
hassoe0701b72004-05-20 09:19:34 +00001114 {
1115 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1116 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1117 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1118 }
paul718e3742002-12-13 20:15:29 +00001119 }
1120 }
1121 return 0;
1122}
1123
hasso93406d82005-02-02 14:40:33 +00001124void
1125peer_nsf_stop (struct peer *peer)
1126{
1127 afi_t afi;
1128 safi_t safi;
1129
1130 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1131 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1132
1133 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1134 for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
1135 peer->nsf[afi][safi] = 0;
1136
1137 if (peer->t_gr_restart)
1138 {
1139 BGP_TIMER_OFF (peer->t_gr_restart);
1140 if (BGP_DEBUG (events, EVENTS))
1141 zlog_debug ("%s graceful restart timer stopped", peer->host);
1142 }
1143 if (peer->t_gr_stale)
1144 {
1145 BGP_TIMER_OFF (peer->t_gr_stale);
1146 if (BGP_DEBUG (events, EVENTS))
1147 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1148 }
1149 bgp_clear_route_all (peer);
1150}
1151
Paul Jakmaca058a32006-09-14 02:58:49 +00001152/* Delete peer from confguration.
1153 *
1154 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1155 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1156 *
1157 * This function /should/ take care to be idempotent, to guard against
1158 * it being called multiple times through stray events that come in
1159 * that happen to result in this function being called again. That
1160 * said, getting here for a "Deleted" peer is a bug in the neighbour
1161 * FSM.
1162 */
paul718e3742002-12-13 20:15:29 +00001163int
1164peer_delete (struct peer *peer)
1165{
1166 int i;
1167 afi_t afi;
1168 safi_t safi;
1169 struct bgp *bgp;
1170 struct bgp_filter *filter;
1171
Paul Jakmaca058a32006-09-14 02:58:49 +00001172 assert (peer->status != Deleted);
1173
paul718e3742002-12-13 20:15:29 +00001174 bgp = peer->bgp;
1175
hasso93406d82005-02-02 14:40:33 +00001176 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1177 peer_nsf_stop (peer);
1178
paul718e3742002-12-13 20:15:29 +00001179 /* If this peer belongs to peer group. Clearn up the
1180 relationship. */
1181 if (peer->group)
1182 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001183 struct listnode *pn;
1184
1185 if ((pn = listnode_lookup (peer->group->peer, peer)))
1186 {
1187 peer = peer_unlock (peer); /* group->peer list reference */
1188 list_delete_node (peer->group->peer, pn);
1189 }
paul718e3742002-12-13 20:15:29 +00001190 peer->group = NULL;
1191 }
paul200df112005-06-01 11:17:05 +00001192
paul718e3742002-12-13 20:15:29 +00001193 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001194 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1195 * executed after peer structure is deleted.
1196 */
hassoe0701b72004-05-20 09:19:34 +00001197 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001198 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001199 bgp_fsm_change_status (peer, Deleted);
1200 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001201
paul718e3742002-12-13 20:15:29 +00001202 /* Delete from all peer list. */
1203 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
paulfee0f4c2004-09-13 05:12:46 +00001204 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001205 struct listnode *pn;
paul200df112005-06-01 11:17:05 +00001206
Paul Jakmaca058a32006-09-14 02:58:49 +00001207 if ((pn = listnode_lookup (bgp->peer, peer)))
1208 {
1209 peer_unlock (peer); /* bgp peer list reference */
1210 list_delete_node (bgp->peer, pn);
1211 }
1212
1213 if (peer_rsclient_active (peer)
1214 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001215 {
1216 peer_unlock (peer); /* rsclient list reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001217 list_delete_node (bgp->rsclient, pn);
paul200df112005-06-01 11:17:05 +00001218 }
paulfee0f4c2004-09-13 05:12:46 +00001219 }
1220
1221 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1222 member of a peer_group. */
1223 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1224 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1225 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
1226 bgp_table_finish (peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001227
paul200df112005-06-01 11:17:05 +00001228 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001229 if (peer->ibuf)
1230 stream_free (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001231 if (peer->obuf)
1232 stream_fifo_free (peer->obuf);
paul718e3742002-12-13 20:15:29 +00001233 if (peer->work)
1234 stream_free (peer->work);
Paul Jakma18937402006-07-27 19:05:12 +00001235 peer->obuf = NULL;
1236 peer->work = peer->ibuf = NULL;
1237
paul718e3742002-12-13 20:15:29 +00001238 /* Local and remote addresses. */
1239 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001240 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001241 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001242 sockunion_free (peer->su_remote);
Paul Jakma18937402006-07-27 19:05:12 +00001243 peer->su_local = peer->su_remote = NULL;
paul200df112005-06-01 11:17:05 +00001244
paul718e3742002-12-13 20:15:29 +00001245 /* Free filter related memory. */
1246 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1247 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1248 {
1249 filter = &peer->filter[afi][safi];
1250
1251 for (i = FILTER_IN; i < FILTER_MAX; i++)
1252 {
1253 if (filter->dlist[i].name)
1254 free (filter->dlist[i].name);
1255 if (filter->plist[i].name)
1256 free (filter->plist[i].name);
1257 if (filter->aslist[i].name)
1258 free (filter->aslist[i].name);
paul200df112005-06-01 11:17:05 +00001259
1260 filter->dlist[i].name = NULL;
1261 filter->plist[i].name = NULL;
1262 filter->aslist[i].name = NULL;
1263 }
1264 for (i = RMAP_IN; i < RMAP_MAX; i++)
1265 {
paul718e3742002-12-13 20:15:29 +00001266 if (filter->map[i].name)
1267 free (filter->map[i].name);
paul200df112005-06-01 11:17:05 +00001268 filter->map[i].name = NULL;
paul718e3742002-12-13 20:15:29 +00001269 }
1270
1271 if (filter->usmap.name)
1272 free (filter->usmap.name);
1273
1274 if (peer->default_rmap[afi][safi].name)
1275 free (peer->default_rmap[afi][safi].name);
paul200df112005-06-01 11:17:05 +00001276
1277 filter->usmap.name = NULL;
1278 peer->default_rmap[afi][safi].name = NULL;
paul718e3742002-12-13 20:15:29 +00001279 }
paul200df112005-06-01 11:17:05 +00001280
1281 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001282
1283 return 0;
1284}
1285
paul94f2b392005-06-28 12:44:16 +00001286static int
paul718e3742002-12-13 20:15:29 +00001287peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1288{
1289 return strcmp (g1->name, g2->name);
1290}
1291
1292/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001293static int
paul718e3742002-12-13 20:15:29 +00001294peer_group_active (struct peer *peer)
1295{
1296 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1297 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1298 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1299 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1300 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1301 return 1;
1302 return 0;
1303}
1304
1305/* Peer group cofiguration. */
1306static struct peer_group *
1307peer_group_new ()
1308{
1309 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1310 sizeof (struct peer_group));
1311}
1312
paul94f2b392005-06-28 12:44:16 +00001313static void
paul718e3742002-12-13 20:15:29 +00001314peer_group_free (struct peer_group *group)
1315{
1316 XFREE (MTYPE_PEER_GROUP, group);
1317}
1318
1319struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001320peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001321{
1322 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001323 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001324
paul1eb8ef22005-04-07 07:30:20 +00001325 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001326 {
1327 if (strcmp (group->name, name) == 0)
1328 return group;
1329 }
1330 return NULL;
1331}
1332
1333struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001334peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001335{
1336 struct peer_group *group;
1337
1338 group = peer_group_lookup (bgp, name);
1339 if (group)
1340 return group;
1341
1342 group = peer_group_new ();
1343 group->bgp = bgp;
1344 group->name = strdup (name);
1345 group->peer = list_new ();
1346 group->conf = peer_new ();
1347 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1348 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
1349 group->conf->host = strdup (name);
1350 group->conf->bgp = bgp;
1351 group->conf->group = group;
1352 group->conf->as = 0;
1353 group->conf->ttl = 1;
1354 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1355 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1356 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1357 group->conf->keepalive = 0;
1358 group->conf->holdtime = 0;
1359 group->conf->connect = 0;
1360 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1361 listnode_add_sort (bgp->group, group);
1362
1363 return 0;
1364}
1365
paul94f2b392005-06-28 12:44:16 +00001366static void
paul718e3742002-12-13 20:15:29 +00001367peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1368 afi_t afi, safi_t safi)
1369{
1370 int in = FILTER_IN;
1371 int out = FILTER_OUT;
1372 struct peer *conf;
1373 struct bgp_filter *pfilter;
1374 struct bgp_filter *gfilter;
1375
1376 conf = group->conf;
1377 pfilter = &peer->filter[afi][safi];
1378 gfilter = &conf->filter[afi][safi];
1379
1380 /* remote-as */
1381 if (conf->as)
1382 peer->as = conf->as;
1383
1384 /* remote-as */
1385 if (conf->change_local_as)
1386 peer->change_local_as = conf->change_local_as;
1387
1388 /* TTL */
1389 peer->ttl = conf->ttl;
1390
1391 /* Weight */
1392 peer->weight = conf->weight;
1393
1394 /* peer flags apply */
1395 peer->flags = conf->flags;
1396 /* peer af_flags apply */
1397 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1398 /* peer config apply */
1399 peer->config = conf->config;
1400
1401 /* peer timers apply */
1402 peer->holdtime = conf->holdtime;
1403 peer->keepalive = conf->keepalive;
1404 peer->connect = conf->connect;
1405 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1406 peer->v_connect = conf->connect;
1407 else
1408 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1409
1410 /* advertisement-interval reset */
1411 if (peer_sort (peer) == BGP_PEER_IBGP)
1412 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1413 else
1414 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1415
1416 /* maximum-prefix */
1417 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001418 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001419 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001420
1421 /* allowas-in */
1422 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1423
paulfee0f4c2004-09-13 05:12:46 +00001424 /* route-server-client */
1425 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1426 {
1427 /* Make peer's RIB point to group's RIB. */
1428 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1429
1430 /* Import policy. */
1431 if (pfilter->map[RMAP_IMPORT].name)
1432 free (pfilter->map[RMAP_IMPORT].name);
1433 if (gfilter->map[RMAP_IMPORT].name)
1434 {
1435 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1436 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1437 }
1438 else
1439 {
1440 pfilter->map[RMAP_IMPORT].name = NULL;
1441 pfilter->map[RMAP_IMPORT].map = NULL;
1442 }
1443
1444 /* Export policy. */
1445 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1446 {
1447 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1448 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1449 }
1450 }
1451
paul718e3742002-12-13 20:15:29 +00001452 /* default-originate route-map */
1453 if (conf->default_rmap[afi][safi].name)
1454 {
1455 if (peer->default_rmap[afi][safi].name)
1456 free (peer->default_rmap[afi][safi].name);
1457 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1458 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1459 }
1460
1461 /* update-source apply */
1462 if (conf->update_source)
1463 {
1464 if (peer->update_source)
1465 sockunion_free (peer->update_source);
1466 if (peer->update_if)
1467 {
1468 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1469 peer->update_if = NULL;
1470 }
1471 peer->update_source = sockunion_dup (conf->update_source);
1472 }
1473 else if (conf->update_if)
1474 {
1475 if (peer->update_if)
1476 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1477 if (peer->update_source)
1478 {
1479 sockunion_free (peer->update_source);
1480 peer->update_source = NULL;
1481 }
1482 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1483 }
1484
1485 /* inbound filter apply */
1486 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1487 {
1488 if (pfilter->dlist[in].name)
1489 free (pfilter->dlist[in].name);
1490 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1491 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1492 }
1493 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1494 {
1495 if (pfilter->plist[in].name)
1496 free (pfilter->plist[in].name);
1497 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1498 pfilter->plist[in].plist = gfilter->plist[in].plist;
1499 }
1500 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1501 {
1502 if (pfilter->aslist[in].name)
1503 free (pfilter->aslist[in].name);
1504 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1505 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1506 }
paulfee0f4c2004-09-13 05:12:46 +00001507 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001508 {
paulfee0f4c2004-09-13 05:12:46 +00001509 if (pfilter->map[RMAP_IN].name)
1510 free (pfilter->map[RMAP_IN].name);
1511 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1512 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001513 }
1514
1515 /* outbound filter apply */
1516 if (gfilter->dlist[out].name)
1517 {
1518 if (pfilter->dlist[out].name)
1519 free (pfilter->dlist[out].name);
1520 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1521 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1522 }
1523 else
1524 {
1525 if (pfilter->dlist[out].name)
1526 free (pfilter->dlist[out].name);
1527 pfilter->dlist[out].name = NULL;
1528 pfilter->dlist[out].alist = NULL;
1529 }
1530 if (gfilter->plist[out].name)
1531 {
1532 if (pfilter->plist[out].name)
1533 free (pfilter->plist[out].name);
1534 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1535 pfilter->plist[out].plist = gfilter->plist[out].plist;
1536 }
1537 else
1538 {
1539 if (pfilter->plist[out].name)
1540 free (pfilter->plist[out].name);
1541 pfilter->plist[out].name = NULL;
1542 pfilter->plist[out].plist = NULL;
1543 }
1544 if (gfilter->aslist[out].name)
1545 {
1546 if (pfilter->aslist[out].name)
1547 free (pfilter->aslist[out].name);
1548 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1549 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1550 }
1551 else
1552 {
1553 if (pfilter->aslist[out].name)
1554 free (pfilter->aslist[out].name);
1555 pfilter->aslist[out].name = NULL;
1556 pfilter->aslist[out].aslist = NULL;
1557 }
paulfee0f4c2004-09-13 05:12:46 +00001558 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001559 {
paulfee0f4c2004-09-13 05:12:46 +00001560 if (pfilter->map[RMAP_OUT].name)
1561 free (pfilter->map[RMAP_OUT].name);
1562 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1563 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001564 }
1565 else
1566 {
paulfee0f4c2004-09-13 05:12:46 +00001567 if (pfilter->map[RMAP_OUT].name)
1568 free (pfilter->map[RMAP_OUT].name);
1569 pfilter->map[RMAP_OUT].name = NULL;
1570 pfilter->map[RMAP_OUT].map = NULL;
1571 }
1572
1573 /* RS-client's import/export route-maps. */
1574 if (gfilter->map[RMAP_IMPORT].name)
1575 {
1576 if (pfilter->map[RMAP_IMPORT].name)
1577 free (pfilter->map[RMAP_IMPORT].name);
1578 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1579 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1580 }
1581 else
1582 {
1583 if (pfilter->map[RMAP_IMPORT].name)
1584 free (pfilter->map[RMAP_IMPORT].name);
1585 pfilter->map[RMAP_IMPORT].name = NULL;
1586 pfilter->map[RMAP_IMPORT].map = NULL;
1587 }
1588 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1589 {
1590 if (pfilter->map[RMAP_EXPORT].name)
1591 free (pfilter->map[RMAP_EXPORT].name);
1592 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1593 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001594 }
1595
1596 if (gfilter->usmap.name)
1597 {
1598 if (pfilter->usmap.name)
1599 free (pfilter->usmap.name);
1600 pfilter->usmap.name = strdup (gfilter->usmap.name);
1601 pfilter->usmap.map = gfilter->usmap.map;
1602 }
1603 else
1604 {
1605 if (pfilter->usmap.name)
1606 free (pfilter->usmap.name);
1607 pfilter->usmap.name = NULL;
1608 pfilter->usmap.map = NULL;
1609 }
1610}
1611
1612/* Peer group's remote AS configuration. */
1613int
paulfd79ac92004-10-13 05:06:08 +00001614peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001615{
1616 struct peer_group *group;
1617 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001618 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001619
1620 group = peer_group_lookup (bgp, group_name);
1621 if (! group)
1622 return -1;
1623
1624 if (group->conf->as == *as)
1625 return 0;
1626
1627 /* When we setup peer-group AS number all peer group member's AS
1628 number must be updated to same number. */
1629 peer_as_change (group->conf, *as);
1630
paul1eb8ef22005-04-07 07:30:20 +00001631 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001632 {
1633 if (peer->as != *as)
1634 peer_as_change (peer, *as);
1635 }
1636
1637 return 0;
1638}
1639
1640int
1641peer_group_delete (struct peer_group *group)
1642{
1643 struct bgp *bgp;
1644 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001645 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001646
1647 bgp = group->bgp;
1648
paul1eb8ef22005-04-07 07:30:20 +00001649 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001650 {
1651 peer->group = NULL;
1652 peer_delete (peer);
1653 }
1654 list_delete (group->peer);
1655
1656 free (group->name);
1657 group->name = NULL;
1658
1659 group->conf->group = NULL;
1660 peer_delete (group->conf);
1661
1662 /* Delete from all peer_group list. */
1663 listnode_delete (bgp->group, group);
1664
1665 peer_group_free (group);
1666
1667 return 0;
1668}
1669
1670int
1671peer_group_remote_as_delete (struct peer_group *group)
1672{
1673 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001674 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001675
1676 if (! group->conf->as)
1677 return 0;
1678
paul1eb8ef22005-04-07 07:30:20 +00001679 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001680 {
1681 peer->group = NULL;
1682 peer_delete (peer);
1683 }
1684 list_delete_all_node (group->peer);
1685
1686 group->conf->as = 0;
1687
1688 return 0;
1689}
1690
1691/* Bind specified peer to peer group. */
1692int
1693peer_group_bind (struct bgp *bgp, union sockunion *su,
1694 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1695{
1696 struct peer *peer;
1697 int first_member = 0;
1698
1699 /* Check peer group's address family. */
1700 if (! group->conf->afc[afi][safi])
1701 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1702
1703 /* Lookup the peer. */
1704 peer = peer_lookup (bgp, su);
1705
1706 /* Create a new peer. */
1707 if (! peer)
1708 {
1709 if (! group->conf->as)
1710 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1711
1712 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1713 peer->group = group;
1714 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001715
Paul Jakmaca058a32006-09-14 02:58:49 +00001716 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001717 listnode_add (group->peer, peer);
1718 peer_group2peer_config_copy (group, peer, afi, safi);
1719
1720 return 0;
1721 }
1722
1723 /* When the peer already belongs to peer group, check the consistency. */
1724 if (peer->af_group[afi][safi])
1725 {
1726 if (strcmp (peer->group->name, group->name) != 0)
1727 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1728
1729 return 0;
1730 }
1731
1732 /* Check current peer group configuration. */
1733 if (peer_group_active (peer)
1734 && strcmp (peer->group->name, group->name) != 0)
1735 return BGP_ERR_PEER_GROUP_MISMATCH;
1736
1737 if (! group->conf->as)
1738 {
1739 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1740 && peer_sort (group->conf) != peer_sort (peer))
1741 {
1742 if (as)
1743 *as = peer->as;
1744 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1745 }
1746
1747 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1748 first_member = 1;
1749 }
1750
1751 peer->af_group[afi][safi] = 1;
1752 peer->afc[afi][safi] = 1;
1753 if (! peer->group)
1754 {
1755 peer->group = group;
paul200df112005-06-01 11:17:05 +00001756
Paul Jakmaca058a32006-09-14 02:58:49 +00001757 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001758 listnode_add (group->peer, peer);
1759 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001760 else
1761 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001762
1763 if (first_member)
1764 {
1765 /* Advertisement-interval reset */
1766 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1767 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1768 else
1769 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1770
1771 /* ebgp-multihop reset */
1772 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1773 group->conf->ttl = 255;
1774
1775 /* local-as reset */
1776 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1777 {
1778 group->conf->change_local_as = 0;
1779 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1780 }
1781 }
paulfee0f4c2004-09-13 05:12:46 +00001782
1783 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1784 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001785 struct listnode *pn;
1786
paulfee0f4c2004-09-13 05:12:46 +00001787 /* If it's not configured as RSERVER_CLIENT in any other address
1788 family, without being member of a peer_group, remove it from
1789 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001790 if (! peer_rsclient_active (peer)
1791 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001792 {
1793 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001794 list_delete_node (bgp->rsclient, pn);
paul200df112005-06-01 11:17:05 +00001795 }
paulfee0f4c2004-09-13 05:12:46 +00001796
1797 bgp_table_finish (peer->rib[afi][safi]);
1798
1799 /* Import policy. */
1800 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1801 {
1802 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1803 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1804 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1805 }
1806
1807 /* Export policy. */
1808 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1809 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1810 {
1811 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1812 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1813 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1814 }
1815 }
1816
paul718e3742002-12-13 20:15:29 +00001817 peer_group2peer_config_copy (group, peer, afi, safi);
1818
1819 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001820 {
1821 peer->last_reset = PEER_DOWN_RMAP_BIND;
1822 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1823 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1824 }
paul718e3742002-12-13 20:15:29 +00001825 else
1826 BGP_EVENT_ADD (peer, BGP_Stop);
1827
1828 return 0;
1829}
1830
1831int
1832peer_group_unbind (struct bgp *bgp, struct peer *peer,
1833 struct peer_group *group, afi_t afi, safi_t safi)
1834{
1835 if (! peer->af_group[afi][safi])
1836 return 0;
1837
1838 if (group != peer->group)
1839 return BGP_ERR_PEER_GROUP_MISMATCH;
1840
1841 peer->af_group[afi][safi] = 0;
1842 peer->afc[afi][safi] = 0;
1843 peer_af_flag_reset (peer, afi, safi);
1844
paulfee0f4c2004-09-13 05:12:46 +00001845 if (peer->rib[afi][safi])
1846 peer->rib[afi][safi] = NULL;
1847
paul718e3742002-12-13 20:15:29 +00001848 if (! peer_group_active (peer))
1849 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001850 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001851 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001852 listnode_delete (group->peer, peer);
1853 peer->group = NULL;
1854 if (group->conf->as)
1855 {
1856 peer_delete (peer);
1857 return 0;
1858 }
1859 peer_global_config_reset (peer);
1860 }
1861
1862 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001863 {
1864 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1865 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1866 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1867 }
paul718e3742002-12-13 20:15:29 +00001868 else
1869 BGP_EVENT_ADD (peer, BGP_Stop);
1870
1871 return 0;
1872}
1873
1874/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001875static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001876bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001877{
1878 struct bgp *bgp;
1879 afi_t afi;
1880 safi_t safi;
1881
paul200df112005-06-01 11:17:05 +00001882 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1883 return NULL;
1884
paul718e3742002-12-13 20:15:29 +00001885 bgp->peer_self = peer_new ();
paulfd79ac92004-10-13 05:06:08 +00001886 bgp->peer_self->host = strdup ("Static announcement");
paul718e3742002-12-13 20:15:29 +00001887
1888 bgp->peer = list_new ();
1889 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1890
1891 bgp->group = list_new ();
1892 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1893
paulfee0f4c2004-09-13 05:12:46 +00001894 bgp->rsclient = list_new ();
1895 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1896
paul718e3742002-12-13 20:15:29 +00001897 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1898 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1899 {
Paul Jakma64e580a2006-02-21 01:09:01 +00001900 bgp->route[afi][safi] = bgp_table_init (afi, safi);
1901 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1902 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
paul718e3742002-12-13 20:15:29 +00001903 }
1904
1905 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1906 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1907 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001908 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1909 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001910
1911 bgp->as = *as;
1912
1913 if (name)
1914 bgp->name = strdup (name);
1915
1916 return bgp;
1917}
1918
1919/* Return first entry of BGP. */
1920struct bgp *
paul94f2b392005-06-28 12:44:16 +00001921bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001922{
1923 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001924 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001925 return NULL;
1926}
1927
1928/* Lookup BGP entry. */
1929struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001930bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001931{
1932 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001933 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001934
paul1eb8ef22005-04-07 07:30:20 +00001935 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001936 if (bgp->as == as
1937 && ((bgp->name == NULL && name == NULL)
1938 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1939 return bgp;
1940 return NULL;
1941}
1942
1943/* Lookup BGP structure by view name. */
1944struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001945bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00001946{
1947 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001948 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001949
paul1eb8ef22005-04-07 07:30:20 +00001950 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001951 if ((bgp->name == NULL && name == NULL)
1952 || (bgp->name && name && strcmp (bgp->name, name) == 0))
1953 return bgp;
1954 return NULL;
1955}
1956
1957/* Called from VTY commands. */
1958int
paulfd79ac92004-10-13 05:06:08 +00001959bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001960{
1961 struct bgp *bgp;
1962
1963 /* Multiple instance check. */
1964 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
1965 {
1966 if (name)
1967 bgp = bgp_lookup_by_name (name);
1968 else
1969 bgp = bgp_get_default ();
1970
1971 /* Already exists. */
1972 if (bgp)
1973 {
1974 if (bgp->as != *as)
1975 {
1976 *as = bgp->as;
1977 return BGP_ERR_INSTANCE_MISMATCH;
1978 }
1979 *bgp_val = bgp;
1980 return 0;
1981 }
1982 }
1983 else
1984 {
1985 /* BGP instance name can not be specified for single instance. */
1986 if (name)
1987 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
1988
1989 /* Get default BGP structure if exists. */
1990 bgp = bgp_get_default ();
1991
1992 if (bgp)
1993 {
1994 if (bgp->as != *as)
1995 {
1996 *as = bgp->as;
1997 return BGP_ERR_AS_MISMATCH;
1998 }
1999 *bgp_val = bgp;
2000 return 0;
2001 }
2002 }
2003
2004 bgp = bgp_create (as, name);
2005 listnode_add (bm->bgp, bgp);
hasso18a6dce2004-10-03 18:18:34 +00002006 bgp_router_id_set(bgp, &router_id_zebra);
paul718e3742002-12-13 20:15:29 +00002007 *bgp_val = bgp;
2008
2009 return 0;
2010}
2011
2012/* Delete BGP instance. */
2013int
2014bgp_delete (struct bgp *bgp)
2015{
2016 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002017 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002018 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002019 struct listnode *next;
2020 afi_t afi;
2021 safi_t safi;
2022 int i;
2023
2024 /* Delete static route. */
2025 bgp_static_delete (bgp);
2026
2027 /* Unset redistribution. */
2028 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2029 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2030 if (i != ZEBRA_ROUTE_BGP)
2031 bgp_redistribute_unset (bgp, afi, i);
2032
hassob6b7cff2005-05-26 08:29:07 +00002033 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
2034 peer_group_delete (group);
hasso54a6ed32005-05-26 22:12:33 +00002035 list_delete (bgp->group);
paul718e3742002-12-13 20:15:29 +00002036
paul1eb8ef22005-04-07 07:30:20 +00002037 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2038 peer_delete (peer);
hasso54a6ed32005-05-26 22:12:33 +00002039 list_delete (bgp->peer);
paul718e3742002-12-13 20:15:29 +00002040
hasso54a6ed32005-05-26 22:12:33 +00002041 for (ALL_LIST_ELEMENTS (bgp->rsclient, node, next, peer))
2042 peer_delete (peer);
paulfee0f4c2004-09-13 05:12:46 +00002043 list_delete (bgp->rsclient);
2044
paul718e3742002-12-13 20:15:29 +00002045 listnode_delete (bm->bgp, bgp);
paul200df112005-06-01 11:17:05 +00002046
paul718e3742002-12-13 20:15:29 +00002047 if (bgp->name)
2048 free (bgp->name);
2049
2050 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2051 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2052 {
2053 if (bgp->route[afi][safi])
2054 XFREE (MTYPE_ROUTE_TABLE, bgp->route[afi][safi]);
2055 if (bgp->aggregate[afi][safi])
2056 XFREE (MTYPE_ROUTE_TABLE,bgp->aggregate[afi][safi]) ;
2057 if (bgp->rib[afi][safi])
2058 XFREE (MTYPE_ROUTE_TABLE,bgp->rib[afi][safi]);
2059 }
2060 XFREE (MTYPE_BGP, bgp);
2061
2062 return 0;
2063}
2064
2065struct peer *
2066peer_lookup (struct bgp *bgp, union sockunion *su)
2067{
2068 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002069 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002070
2071 if (! bgp)
2072 bgp = bgp_get_default ();
2073
2074 if (! bgp)
2075 return NULL;
2076
paul1eb8ef22005-04-07 07:30:20 +00002077 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002078 {
pauleb821182004-05-01 08:44:08 +00002079 if (sockunion_same (&peer->su, su)
2080 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2081 return peer;
paul718e3742002-12-13 20:15:29 +00002082 }
2083 return NULL;
2084}
2085
2086struct peer *
2087peer_lookup_with_open (union sockunion *su, as_t remote_as,
2088 struct in_addr *remote_id, int *as)
2089{
2090 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002091 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002092 struct bgp *bgp;
2093
2094 bgp = bgp_get_default ();
2095 if (! bgp)
2096 return NULL;
2097
paul1eb8ef22005-04-07 07:30:20 +00002098 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002099 {
pauleb821182004-05-01 08:44:08 +00002100 if (sockunion_same (&peer->su, su)
2101 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2102 {
2103 if (peer->as == remote_as
2104 && peer->remote_id.s_addr == remote_id->s_addr)
2105 return peer;
2106 if (peer->as == remote_as)
2107 *as = 1;
2108 }
paul718e3742002-12-13 20:15:29 +00002109 }
paul1eb8ef22005-04-07 07:30:20 +00002110 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002111 {
pauleb821182004-05-01 08:44:08 +00002112 if (sockunion_same (&peer->su, su)
2113 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2114 {
2115 if (peer->as == remote_as
2116 && peer->remote_id.s_addr == 0)
2117 return peer;
2118 if (peer->as == remote_as)
2119 *as = 1;
2120 }
paul718e3742002-12-13 20:15:29 +00002121 }
2122 return NULL;
2123}
2124
2125/* If peer is configured at least one address family return 1. */
2126int
2127peer_active (struct peer *peer)
2128{
2129 if (peer->afc[AFI_IP][SAFI_UNICAST]
2130 || peer->afc[AFI_IP][SAFI_MULTICAST]
2131 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2132 || peer->afc[AFI_IP6][SAFI_UNICAST]
2133 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2134 return 1;
2135 return 0;
2136}
2137
2138/* If peer is negotiated at least one address family return 1. */
2139int
2140peer_active_nego (struct peer *peer)
2141{
2142 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2143 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2144 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2145 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2146 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2147 return 1;
2148 return 0;
2149}
2150
2151/* peer_flag_change_type. */
2152enum peer_change_type
2153{
2154 peer_change_none,
2155 peer_change_reset,
2156 peer_change_reset_in,
2157 peer_change_reset_out,
2158};
2159
paul94f2b392005-06-28 12:44:16 +00002160static void
paul718e3742002-12-13 20:15:29 +00002161peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2162 enum peer_change_type type)
2163{
2164 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2165 return;
2166
2167 if (type == peer_change_reset)
2168 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2169 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2170 else if (type == peer_change_reset_in)
2171 {
2172 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2173 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2174 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2175 else
2176 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2177 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2178 }
2179 else if (type == peer_change_reset_out)
2180 bgp_announce_route (peer, afi, safi);
2181}
2182
2183struct peer_flag_action
2184{
2185 /* Peer's flag. */
2186 u_int32_t flag;
2187
2188 /* This flag can be set for peer-group member. */
2189 u_char not_for_member;
2190
2191 /* Action when the flag is changed. */
2192 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002193
2194 /* Peer down cause */
2195 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002196};
2197
2198struct peer_flag_action peer_flag_action_list[] =
2199 {
2200 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2201 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2202 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2203 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2204 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002205 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002206 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002207 { 0, 0, 0 }
2208 };
2209
2210struct peer_flag_action peer_af_flag_action_list[] =
2211 {
2212 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2213 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2214 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2215 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2216 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2217 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2218 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2219 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2220 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2221 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2222 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2223 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2224 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002225 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002226 { 0, 0, 0 }
2227 };
2228
2229/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002230static int
paul718e3742002-12-13 20:15:29 +00002231peer_flag_action_set (struct peer_flag_action *action_list, int size,
2232 struct peer_flag_action *action, u_int32_t flag)
2233{
2234 int i;
2235 int found = 0;
2236 int reset_in = 0;
2237 int reset_out = 0;
2238 struct peer_flag_action *match = NULL;
2239
2240 /* Check peer's frag action. */
2241 for (i = 0; i < size; i++)
2242 {
2243 match = &action_list[i];
2244
2245 if (match->flag == 0)
2246 break;
2247
2248 if (match->flag & flag)
2249 {
2250 found = 1;
2251
2252 if (match->type == peer_change_reset_in)
2253 reset_in = 1;
2254 if (match->type == peer_change_reset_out)
2255 reset_out = 1;
2256 if (match->type == peer_change_reset)
2257 {
2258 reset_in = 1;
2259 reset_out = 1;
2260 }
2261 if (match->not_for_member)
2262 action->not_for_member = 1;
2263 }
2264 }
2265
2266 /* Set peer clear type. */
2267 if (reset_in && reset_out)
2268 action->type = peer_change_reset;
2269 else if (reset_in)
2270 action->type = peer_change_reset_in;
2271 else if (reset_out)
2272 action->type = peer_change_reset_out;
2273 else
2274 action->type = peer_change_none;
2275
2276 return found;
2277}
2278
paul94f2b392005-06-28 12:44:16 +00002279static void
paul718e3742002-12-13 20:15:29 +00002280peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2281{
2282 if (flag == PEER_FLAG_SHUTDOWN)
2283 {
2284 if (CHECK_FLAG (peer->flags, flag))
2285 {
hasso93406d82005-02-02 14:40:33 +00002286 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2287 peer_nsf_stop (peer);
2288
hasso0a486e52005-02-01 20:57:17 +00002289 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2290 if (peer->t_pmax_restart)
2291 {
2292 BGP_TIMER_OFF (peer->t_pmax_restart);
2293 if (BGP_DEBUG (events, EVENTS))
2294 zlog_debug ("%s Maximum-prefix restart timer canceled",
2295 peer->host);
2296 }
2297
hasso93406d82005-02-02 14:40:33 +00002298 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2299 peer_nsf_stop (peer);
2300
paul718e3742002-12-13 20:15:29 +00002301 if (peer->status == Established)
2302 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2303 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2304 else
2305 BGP_EVENT_ADD (peer, BGP_Stop);
2306 }
2307 else
2308 {
2309 peer->v_start = BGP_INIT_START_TIMER;
2310 BGP_EVENT_ADD (peer, BGP_Stop);
2311 }
2312 }
2313 else if (peer->status == Established)
2314 {
hassoc9502432005-02-01 22:01:48 +00002315 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2316 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2317 else if (flag == PEER_FLAG_PASSIVE)
2318 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002319 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002320 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002321
hassoc9502432005-02-01 22:01:48 +00002322 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2323 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002324 }
2325 else
2326 BGP_EVENT_ADD (peer, BGP_Stop);
2327}
2328
2329/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002330static int
paul718e3742002-12-13 20:15:29 +00002331peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2332{
2333 int found;
2334 int size;
2335 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002336 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002337 struct peer_flag_action action;
2338
2339 memset (&action, 0, sizeof (struct peer_flag_action));
2340 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2341
2342 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2343
2344 /* No flag action is found. */
2345 if (! found)
2346 return BGP_ERR_INVALID_FLAG;
2347
2348 /* Not for peer-group member. */
2349 if (action.not_for_member && peer_group_active (peer))
2350 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2351
2352 /* When unset the peer-group member's flag we have to check
2353 peer-group configuration. */
2354 if (! set && peer_group_active (peer))
2355 if (CHECK_FLAG (peer->group->conf->flags, flag))
2356 {
2357 if (flag == PEER_FLAG_SHUTDOWN)
2358 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2359 else
2360 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2361 }
2362
2363 /* Flag conflict check. */
2364 if (set
2365 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2366 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2367 return BGP_ERR_PEER_FLAG_CONFLICT;
2368
2369 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2370 {
2371 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2372 return 0;
2373 if (! set && ! CHECK_FLAG (peer->flags, flag))
2374 return 0;
2375 }
2376
2377 if (set)
2378 SET_FLAG (peer->flags, flag);
2379 else
2380 UNSET_FLAG (peer->flags, flag);
2381
2382 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2383 {
2384 if (action.type == peer_change_reset)
2385 peer_flag_modify_action (peer, flag);
2386
2387 return 0;
2388 }
2389
2390 /* peer-group member updates. */
2391 group = peer->group;
2392
paul1eb8ef22005-04-07 07:30:20 +00002393 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002394 {
2395 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2396 continue;
2397
2398 if (! set && ! CHECK_FLAG (peer->flags, flag))
2399 continue;
2400
2401 if (set)
2402 SET_FLAG (peer->flags, flag);
2403 else
2404 UNSET_FLAG (peer->flags, flag);
2405
2406 if (action.type == peer_change_reset)
2407 peer_flag_modify_action (peer, flag);
2408 }
2409 return 0;
2410}
2411
2412int
2413peer_flag_set (struct peer *peer, u_int32_t flag)
2414{
2415 return peer_flag_modify (peer, flag, 1);
2416}
2417
2418int
2419peer_flag_unset (struct peer *peer, u_int32_t flag)
2420{
2421 return peer_flag_modify (peer, flag, 0);
2422}
2423
paul94f2b392005-06-28 12:44:16 +00002424static int
paul718e3742002-12-13 20:15:29 +00002425peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2426{
2427 if (peer->af_group[afi][safi])
2428 return 1;
2429 return 0;
2430}
2431
paul94f2b392005-06-28 12:44:16 +00002432static int
paul718e3742002-12-13 20:15:29 +00002433peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2434 int set)
2435{
2436 int found;
2437 int size;
paul1eb8ef22005-04-07 07:30:20 +00002438 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002439 struct peer_group *group;
2440 struct peer_flag_action action;
2441
2442 memset (&action, 0, sizeof (struct peer_flag_action));
2443 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2444
2445 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2446
2447 /* No flag action is found. */
2448 if (! found)
2449 return BGP_ERR_INVALID_FLAG;
2450
2451 /* Adress family must be activated. */
2452 if (! peer->afc[afi][safi])
2453 return BGP_ERR_PEER_INACTIVE;
2454
2455 /* Not for peer-group member. */
2456 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2457 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2458
2459 /* Spcecial check for reflector client. */
2460 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2461 && peer_sort (peer) != BGP_PEER_IBGP)
2462 return BGP_ERR_NOT_INTERNAL_PEER;
2463
2464 /* Spcecial check for remove-private-AS. */
2465 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2466 && peer_sort (peer) == BGP_PEER_IBGP)
2467 return BGP_ERR_REMOVE_PRIVATE_AS;
2468
2469 /* When unset the peer-group member's flag we have to check
2470 peer-group configuration. */
2471 if (! set && peer->af_group[afi][safi])
2472 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2473 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2474
2475 /* When current flag configuration is same as requested one. */
2476 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2477 {
2478 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2479 return 0;
2480 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2481 return 0;
2482 }
2483
2484 if (set)
2485 SET_FLAG (peer->af_flags[afi][safi], flag);
2486 else
2487 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2488
2489 /* Execute action when peer is established. */
2490 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2491 && peer->status == Established)
2492 {
2493 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2494 bgp_clear_adj_in (peer, afi, safi);
2495 else
hassoe0701b72004-05-20 09:19:34 +00002496 {
2497 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2498 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2499 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2500 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2501 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2502 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2503 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2504 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2505
2506 peer_change_action (peer, afi, safi, action.type);
2507 }
2508
paul718e3742002-12-13 20:15:29 +00002509 }
2510
2511 /* Peer group member updates. */
2512 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2513 {
2514 group = peer->group;
2515
paul1eb8ef22005-04-07 07:30:20 +00002516 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002517 {
2518 if (! peer->af_group[afi][safi])
2519 continue;
2520
2521 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2522 continue;
2523
2524 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2525 continue;
2526
2527 if (set)
2528 SET_FLAG (peer->af_flags[afi][safi], flag);
2529 else
2530 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2531
2532 if (peer->status == Established)
2533 {
2534 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2535 bgp_clear_adj_in (peer, afi, safi);
2536 else
hassoe0701b72004-05-20 09:19:34 +00002537 {
2538 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2539 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2540 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2541 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2542 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2543 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2544 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2545 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2546
2547 peer_change_action (peer, afi, safi, action.type);
2548 }
paul718e3742002-12-13 20:15:29 +00002549 }
2550 }
2551 }
2552 return 0;
2553}
2554
2555int
2556peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2557{
2558 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2559}
2560
2561int
2562peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2563{
2564 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2565}
2566
2567/* EBGP multihop configuration. */
2568int
2569peer_ebgp_multihop_set (struct peer *peer, int ttl)
2570{
2571 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002572 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002573
2574 if (peer_sort (peer) == BGP_PEER_IBGP)
2575 return 0;
2576
2577 peer->ttl = ttl;
2578
2579 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2580 {
pauleb821182004-05-01 08:44:08 +00002581 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2582 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002583 }
2584 else
2585 {
2586 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002587 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002588 {
2589 if (peer_sort (peer) == BGP_PEER_IBGP)
2590 continue;
paul718e3742002-12-13 20:15:29 +00002591
pauleb821182004-05-01 08:44:08 +00002592 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002593
pauleb821182004-05-01 08:44:08 +00002594 if (peer->fd >= 0)
2595 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2596 }
paul718e3742002-12-13 20:15:29 +00002597 }
2598 return 0;
2599}
2600
2601int
2602peer_ebgp_multihop_unset (struct peer *peer)
2603{
2604 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002605 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002606
2607 if (peer_sort (peer) == BGP_PEER_IBGP)
2608 return 0;
2609
2610 if (peer_group_active (peer))
2611 peer->ttl = peer->group->conf->ttl;
2612 else
2613 peer->ttl = 1;
2614
2615 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2616 {
pauleb821182004-05-01 08:44:08 +00002617 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2618 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002619 }
2620 else
2621 {
2622 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002623 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002624 {
2625 if (peer_sort (peer) == BGP_PEER_IBGP)
2626 continue;
paul718e3742002-12-13 20:15:29 +00002627
pauleb821182004-05-01 08:44:08 +00002628 peer->ttl = 1;
2629
2630 if (peer->fd >= 0)
2631 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2632 }
paul718e3742002-12-13 20:15:29 +00002633 }
2634 return 0;
2635}
2636
2637/* Neighbor description. */
2638int
2639peer_description_set (struct peer *peer, char *desc)
2640{
2641 if (peer->desc)
2642 XFREE (MTYPE_PEER_DESC, peer->desc);
2643
2644 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2645
2646 return 0;
2647}
2648
2649int
2650peer_description_unset (struct peer *peer)
2651{
2652 if (peer->desc)
2653 XFREE (MTYPE_PEER_DESC, peer->desc);
2654
2655 peer->desc = NULL;
2656
2657 return 0;
2658}
2659
2660/* Neighbor update-source. */
2661int
paulfd79ac92004-10-13 05:06:08 +00002662peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002663{
2664 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002665 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002666
2667 if (peer->update_if)
2668 {
2669 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2670 && strcmp (peer->update_if, ifname) == 0)
2671 return 0;
2672
2673 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2674 peer->update_if = NULL;
2675 }
2676
2677 if (peer->update_source)
2678 {
2679 sockunion_free (peer->update_source);
2680 peer->update_source = NULL;
2681 }
2682
2683 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2684
2685 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2686 {
2687 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002688 {
2689 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2690 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2691 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2692 }
paul718e3742002-12-13 20:15:29 +00002693 else
2694 BGP_EVENT_ADD (peer, BGP_Stop);
2695 return 0;
2696 }
2697
2698 /* peer-group member updates. */
2699 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002700 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002701 {
2702 if (peer->update_if)
2703 {
2704 if (strcmp (peer->update_if, ifname) == 0)
2705 continue;
2706
2707 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2708 peer->update_if = NULL;
2709 }
2710
2711 if (peer->update_source)
2712 {
2713 sockunion_free (peer->update_source);
2714 peer->update_source = NULL;
2715 }
2716
2717 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2718
2719 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002720 {
2721 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2722 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2723 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2724 }
paul718e3742002-12-13 20:15:29 +00002725 else
2726 BGP_EVENT_ADD (peer, BGP_Stop);
2727 }
2728 return 0;
2729}
2730
2731int
2732peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2733{
2734 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002735 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002736
2737 if (peer->update_source)
2738 {
2739 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2740 && sockunion_cmp (peer->update_source, su) == 0)
2741 return 0;
2742 sockunion_free (peer->update_source);
2743 peer->update_source = NULL;
2744 }
2745
2746 if (peer->update_if)
2747 {
2748 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2749 peer->update_if = NULL;
2750 }
2751
2752 peer->update_source = sockunion_dup (su);
2753
2754 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2755 {
2756 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002757 {
2758 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2759 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2760 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2761 }
paul718e3742002-12-13 20:15:29 +00002762 else
2763 BGP_EVENT_ADD (peer, BGP_Stop);
2764 return 0;
2765 }
2766
2767 /* peer-group member updates. */
2768 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002769 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002770 {
2771 if (peer->update_source)
2772 {
2773 if (sockunion_cmp (peer->update_source, su) == 0)
2774 continue;
2775 sockunion_free (peer->update_source);
2776 peer->update_source = NULL;
2777 }
2778
2779 if (peer->update_if)
2780 {
2781 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2782 peer->update_if = NULL;
2783 }
2784
2785 peer->update_source = sockunion_dup (su);
2786
2787 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002788 {
2789 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2790 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2791 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2792 }
paul718e3742002-12-13 20:15:29 +00002793 else
2794 BGP_EVENT_ADD (peer, BGP_Stop);
2795 }
2796 return 0;
2797}
2798
2799int
2800peer_update_source_unset (struct peer *peer)
2801{
2802 union sockunion *su;
2803 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002804 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002805
2806 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2807 && ! peer->update_source
2808 && ! peer->update_if)
2809 return 0;
2810
2811 if (peer->update_source)
2812 {
2813 sockunion_free (peer->update_source);
2814 peer->update_source = NULL;
2815 }
2816 if (peer->update_if)
2817 {
2818 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2819 peer->update_if = NULL;
2820 }
2821
2822 if (peer_group_active (peer))
2823 {
2824 group = peer->group;
2825
2826 if (group->conf->update_source)
2827 {
2828 su = sockunion_dup (group->conf->update_source);
2829 peer->update_source = su;
2830 }
2831 else if (group->conf->update_if)
2832 peer->update_if =
2833 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2834 }
2835
2836 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2837 {
2838 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002839 {
2840 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2841 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2842 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2843 }
paul718e3742002-12-13 20:15:29 +00002844 else
2845 BGP_EVENT_ADD (peer, BGP_Stop);
2846 return 0;
2847 }
2848
2849 /* peer-group member updates. */
2850 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002851 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002852 {
2853 if (! peer->update_source && ! peer->update_if)
2854 continue;
2855
2856 if (peer->update_source)
2857 {
2858 sockunion_free (peer->update_source);
2859 peer->update_source = NULL;
2860 }
2861
2862 if (peer->update_if)
2863 {
2864 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2865 peer->update_if = NULL;
2866 }
2867
2868 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002869 {
2870 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2871 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2872 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2873 }
paul718e3742002-12-13 20:15:29 +00002874 else
2875 BGP_EVENT_ADD (peer, BGP_Stop);
2876 }
2877 return 0;
2878}
2879
2880int
2881peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00002882 const char *rmap)
paul718e3742002-12-13 20:15:29 +00002883{
2884 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002885 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002886
2887 /* Adress family must be activated. */
2888 if (! peer->afc[afi][safi])
2889 return BGP_ERR_PEER_INACTIVE;
2890
2891 /* Default originate can't be used for peer group memeber. */
2892 if (peer_is_group_member (peer, afi, safi))
2893 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2894
2895 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
2896 || (rmap && ! peer->default_rmap[afi][safi].name)
2897 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
2898 {
2899 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2900
2901 if (rmap)
2902 {
2903 if (peer->default_rmap[afi][safi].name)
2904 free (peer->default_rmap[afi][safi].name);
2905 peer->default_rmap[afi][safi].name = strdup (rmap);
2906 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2907 }
2908 }
2909
2910 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2911 {
2912 if (peer->status == Established && peer->afc_nego[afi][safi])
2913 bgp_default_originate (peer, afi, safi, 0);
2914 return 0;
2915 }
2916
2917 /* peer-group member updates. */
2918 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002919 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002920 {
2921 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2922
2923 if (rmap)
2924 {
2925 if (peer->default_rmap[afi][safi].name)
2926 free (peer->default_rmap[afi][safi].name);
2927 peer->default_rmap[afi][safi].name = strdup (rmap);
2928 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2929 }
2930
2931 if (peer->status == Established && peer->afc_nego[afi][safi])
2932 bgp_default_originate (peer, afi, safi, 0);
2933 }
2934 return 0;
2935}
2936
2937int
2938peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
2939{
2940 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002941 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002942
2943 /* Adress family must be activated. */
2944 if (! peer->afc[afi][safi])
2945 return BGP_ERR_PEER_INACTIVE;
2946
2947 /* Default originate can't be used for peer group memeber. */
2948 if (peer_is_group_member (peer, afi, safi))
2949 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2950
2951 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
2952 {
2953 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2954
2955 if (peer->default_rmap[afi][safi].name)
2956 free (peer->default_rmap[afi][safi].name);
2957 peer->default_rmap[afi][safi].name = NULL;
2958 peer->default_rmap[afi][safi].map = NULL;
2959 }
2960
2961 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2962 {
2963 if (peer->status == Established && peer->afc_nego[afi][safi])
2964 bgp_default_originate (peer, afi, safi, 1);
2965 return 0;
2966 }
2967
2968 /* peer-group member updates. */
2969 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002970 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002971 {
2972 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2973
2974 if (peer->default_rmap[afi][safi].name)
2975 free (peer->default_rmap[afi][safi].name);
2976 peer->default_rmap[afi][safi].name = NULL;
2977 peer->default_rmap[afi][safi].map = NULL;
2978
2979 if (peer->status == Established && peer->afc_nego[afi][safi])
2980 bgp_default_originate (peer, afi, safi, 1);
2981 }
2982 return 0;
2983}
2984
2985int
2986peer_port_set (struct peer *peer, u_int16_t port)
2987{
2988 peer->port = port;
2989 return 0;
2990}
2991
2992int
2993peer_port_unset (struct peer *peer)
2994{
2995 peer->port = BGP_PORT_DEFAULT;
2996 return 0;
2997}
2998
2999/* neighbor weight. */
3000int
3001peer_weight_set (struct peer *peer, u_int16_t weight)
3002{
3003 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003004 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003005
3006 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3007 peer->weight = weight;
3008
3009 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3010 return 0;
3011
3012 /* peer-group member updates. */
3013 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003014 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003015 {
3016 peer->weight = group->conf->weight;
3017 }
3018 return 0;
3019}
3020
3021int
3022peer_weight_unset (struct peer *peer)
3023{
3024 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003025 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003026
3027 /* Set default weight. */
3028 if (peer_group_active (peer))
3029 peer->weight = peer->group->conf->weight;
3030 else
3031 peer->weight = 0;
3032
3033 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3034
3035 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3036 return 0;
3037
3038 /* peer-group member updates. */
3039 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003040 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003041 {
3042 peer->weight = 0;
3043 }
3044 return 0;
3045}
3046
3047int
3048peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3049{
3050 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003051 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003052
3053 /* Not for peer group memeber. */
3054 if (peer_group_active (peer))
3055 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3056
3057 /* keepalive value check. */
3058 if (keepalive > 65535)
3059 return BGP_ERR_INVALID_VALUE;
3060
3061 /* Holdtime value check. */
3062 if (holdtime > 65535)
3063 return BGP_ERR_INVALID_VALUE;
3064
3065 /* Holdtime value must be either 0 or greater than 3. */
3066 if (holdtime < 3 && holdtime != 0)
3067 return BGP_ERR_INVALID_VALUE;
3068
3069 /* Set value to the configuration. */
3070 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3071 peer->holdtime = holdtime;
3072 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3073
3074 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3075 return 0;
3076
3077 /* peer-group member updates. */
3078 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003079 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003080 {
3081 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3082 peer->holdtime = group->conf->holdtime;
3083 peer->keepalive = group->conf->keepalive;
3084 }
3085 return 0;
3086}
3087
3088int
3089peer_timers_unset (struct peer *peer)
3090{
3091 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003092 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003093
3094 if (peer_group_active (peer))
3095 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3096
3097 /* Clear configuration. */
3098 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3099 peer->keepalive = 0;
3100 peer->holdtime = 0;
3101
3102 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3103 return 0;
3104
3105 /* peer-group member updates. */
3106 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003107 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003108 {
3109 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3110 peer->holdtime = 0;
3111 peer->keepalive = 0;
3112 }
3113
3114 return 0;
3115}
3116
3117int
3118peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3119{
3120 if (peer_group_active (peer))
3121 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3122
3123 if (connect > 65535)
3124 return BGP_ERR_INVALID_VALUE;
3125
3126 /* Set value to the configuration. */
3127 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3128 peer->connect = connect;
3129
3130 /* Set value to timer setting. */
3131 peer->v_connect = connect;
3132
3133 return 0;
3134}
3135
3136int
3137peer_timers_connect_unset (struct peer *peer)
3138{
3139 if (peer_group_active (peer))
3140 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3141
3142 /* Clear configuration. */
3143 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3144 peer->connect = 0;
3145
3146 /* Set timer setting to default value. */
3147 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3148
3149 return 0;
3150}
3151
3152int
3153peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3154{
3155 if (peer_group_active (peer))
3156 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3157
3158 if (routeadv > 600)
3159 return BGP_ERR_INVALID_VALUE;
3160
3161 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3162 peer->routeadv = routeadv;
3163 peer->v_routeadv = routeadv;
3164
3165 return 0;
3166}
3167
3168int
3169peer_advertise_interval_unset (struct peer *peer)
3170{
3171 if (peer_group_active (peer))
3172 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3173
3174 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3175 peer->routeadv = 0;
3176
3177 if (peer_sort (peer) == BGP_PEER_IBGP)
3178 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3179 else
3180 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3181
3182 return 0;
3183}
3184
paul718e3742002-12-13 20:15:29 +00003185/* neighbor interface */
3186int
paulfd79ac92004-10-13 05:06:08 +00003187peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003188{
3189 if (peer->ifname)
3190 free (peer->ifname);
3191 peer->ifname = strdup (str);
3192
3193 return 0;
3194}
3195
3196int
3197peer_interface_unset (struct peer *peer)
3198{
3199 if (peer->ifname)
3200 free (peer->ifname);
3201 peer->ifname = NULL;
3202
3203 return 0;
3204}
3205
3206/* Allow-as in. */
3207int
3208peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3209{
3210 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003211 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003212
3213 if (allow_num < 1 || allow_num > 10)
3214 return BGP_ERR_INVALID_VALUE;
3215
3216 if (peer->allowas_in[afi][safi] != allow_num)
3217 {
3218 peer->allowas_in[afi][safi] = allow_num;
3219 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3220 peer_change_action (peer, afi, safi, peer_change_reset_in);
3221 }
3222
3223 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3224 return 0;
3225
3226 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003227 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003228 {
3229 if (peer->allowas_in[afi][safi] != allow_num)
3230 {
3231 peer->allowas_in[afi][safi] = allow_num;
3232 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3233 peer_change_action (peer, afi, safi, peer_change_reset_in);
3234 }
3235
3236 }
3237 return 0;
3238}
3239
3240int
3241peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3242{
3243 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003244 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003245
3246 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3247 {
3248 peer->allowas_in[afi][safi] = 0;
3249 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3250 }
3251
3252 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3253 return 0;
3254
3255 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003256 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003257 {
3258 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3259 {
3260 peer->allowas_in[afi][safi] = 0;
3261 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3262 }
3263 }
3264 return 0;
3265}
3266
3267int
3268peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3269{
3270 struct bgp *bgp = peer->bgp;
3271 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003272 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003273
3274 if (peer_sort (peer) != BGP_PEER_EBGP
3275 && peer_sort (peer) != BGP_PEER_INTERNAL)
3276 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3277
3278 if (bgp->as == as)
3279 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3280
3281 if (peer_group_active (peer))
3282 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3283
3284 if (peer->change_local_as == as &&
3285 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3286 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3287 return 0;
3288
3289 peer->change_local_as = as;
3290 if (no_prepend)
3291 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3292 else
3293 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3294
3295 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3296 {
3297 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003298 {
3299 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3300 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3301 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3302 }
paul718e3742002-12-13 20:15:29 +00003303 else
3304 BGP_EVENT_ADD (peer, BGP_Stop);
3305
3306 return 0;
3307 }
3308
3309 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003310 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003311 {
3312 peer->change_local_as = as;
3313 if (no_prepend)
3314 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3315 else
3316 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3317
3318 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003319 {
3320 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3321 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3322 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3323 }
paul718e3742002-12-13 20:15:29 +00003324 else
3325 BGP_EVENT_ADD (peer, BGP_Stop);
3326 }
3327
3328 return 0;
3329}
3330
3331int
3332peer_local_as_unset (struct peer *peer)
3333{
3334 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003335 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003336
3337 if (peer_group_active (peer))
3338 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3339
3340 if (! peer->change_local_as)
3341 return 0;
3342
3343 peer->change_local_as = 0;
3344 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3345
3346 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3347 {
3348 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003349 {
3350 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3351 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3352 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3353 }
paul718e3742002-12-13 20:15:29 +00003354 else
3355 BGP_EVENT_ADD (peer, BGP_Stop);
3356
3357 return 0;
3358 }
3359
3360 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003361 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003362 {
3363 peer->change_local_as = 0;
3364 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3365
3366 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003367 {
3368 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3369 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3370 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3371 }
paul718e3742002-12-13 20:15:29 +00003372 else
3373 BGP_EVENT_ADD (peer, BGP_Stop);
3374 }
3375 return 0;
3376}
3377
3378/* Set distribute list to the peer. */
3379int
3380peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003381 const char *name)
paul718e3742002-12-13 20:15:29 +00003382{
3383 struct bgp_filter *filter;
3384 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003385 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003386
3387 if (! peer->afc[afi][safi])
3388 return BGP_ERR_PEER_INACTIVE;
3389
3390 if (direct != FILTER_IN && direct != FILTER_OUT)
3391 return BGP_ERR_INVALID_VALUE;
3392
3393 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3394 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3395
3396 filter = &peer->filter[afi][safi];
3397
3398 if (filter->plist[direct].name)
3399 return BGP_ERR_PEER_FILTER_CONFLICT;
3400
3401 if (filter->dlist[direct].name)
3402 free (filter->dlist[direct].name);
3403 filter->dlist[direct].name = strdup (name);
3404 filter->dlist[direct].alist = access_list_lookup (afi, name);
3405
3406 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3407 return 0;
3408
3409 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003410 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003411 {
3412 filter = &peer->filter[afi][safi];
3413
3414 if (! peer->af_group[afi][safi])
3415 continue;
3416
3417 if (filter->dlist[direct].name)
3418 free (filter->dlist[direct].name);
3419 filter->dlist[direct].name = strdup (name);
3420 filter->dlist[direct].alist = access_list_lookup (afi, name);
3421 }
3422
3423 return 0;
3424}
3425
3426int
3427peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3428{
3429 struct bgp_filter *filter;
3430 struct bgp_filter *gfilter;
3431 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003432 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003433
3434 if (! peer->afc[afi][safi])
3435 return BGP_ERR_PEER_INACTIVE;
3436
3437 if (direct != FILTER_IN && direct != FILTER_OUT)
3438 return BGP_ERR_INVALID_VALUE;
3439
3440 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3441 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3442
3443 filter = &peer->filter[afi][safi];
3444
3445 /* apply peer-group filter */
3446 if (peer->af_group[afi][safi])
3447 {
3448 gfilter = &peer->group->conf->filter[afi][safi];
3449
3450 if (gfilter->dlist[direct].name)
3451 {
3452 if (filter->dlist[direct].name)
3453 free (filter->dlist[direct].name);
3454 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3455 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3456 return 0;
3457 }
3458 }
3459
3460 if (filter->dlist[direct].name)
3461 free (filter->dlist[direct].name);
3462 filter->dlist[direct].name = NULL;
3463 filter->dlist[direct].alist = NULL;
3464
3465 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3466 return 0;
3467
3468 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003469 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003470 {
3471 filter = &peer->filter[afi][safi];
3472
3473 if (! peer->af_group[afi][safi])
3474 continue;
3475
3476 if (filter->dlist[direct].name)
3477 free (filter->dlist[direct].name);
3478 filter->dlist[direct].name = NULL;
3479 filter->dlist[direct].alist = NULL;
3480 }
3481
3482 return 0;
3483}
3484
3485/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003486static void
paul718e3742002-12-13 20:15:29 +00003487peer_distribute_update (struct access_list *access)
3488{
3489 afi_t afi;
3490 safi_t safi;
3491 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003492 struct listnode *mnode, *mnnode;
3493 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003494 struct bgp *bgp;
3495 struct peer *peer;
3496 struct peer_group *group;
3497 struct bgp_filter *filter;
3498
paul1eb8ef22005-04-07 07:30:20 +00003499 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003500 {
paul1eb8ef22005-04-07 07:30:20 +00003501 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003502 {
3503 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3504 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3505 {
3506 filter = &peer->filter[afi][safi];
3507
3508 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3509 {
3510 if (filter->dlist[direct].name)
3511 filter->dlist[direct].alist =
3512 access_list_lookup (afi, filter->dlist[direct].name);
3513 else
3514 filter->dlist[direct].alist = NULL;
3515 }
3516 }
3517 }
paul1eb8ef22005-04-07 07:30:20 +00003518 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003519 {
3520 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3521 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3522 {
3523 filter = &group->conf->filter[afi][safi];
3524
3525 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3526 {
3527 if (filter->dlist[direct].name)
3528 filter->dlist[direct].alist =
3529 access_list_lookup (afi, filter->dlist[direct].name);
3530 else
3531 filter->dlist[direct].alist = NULL;
3532 }
3533 }
3534 }
3535 }
3536}
3537
3538/* Set prefix list to the peer. */
3539int
3540peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003541 const char *name)
paul718e3742002-12-13 20:15:29 +00003542{
3543 struct bgp_filter *filter;
3544 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003545 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003546
3547 if (! peer->afc[afi][safi])
3548 return BGP_ERR_PEER_INACTIVE;
3549
3550 if (direct != FILTER_IN && direct != FILTER_OUT)
3551 return BGP_ERR_INVALID_VALUE;
3552
3553 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3554 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3555
3556 filter = &peer->filter[afi][safi];
3557
3558 if (filter->dlist[direct].name)
3559 return BGP_ERR_PEER_FILTER_CONFLICT;
3560
3561 if (filter->plist[direct].name)
3562 free (filter->plist[direct].name);
3563 filter->plist[direct].name = strdup (name);
3564 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3565
3566 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3567 return 0;
3568
3569 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003570 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003571 {
3572 filter = &peer->filter[afi][safi];
3573
3574 if (! peer->af_group[afi][safi])
3575 continue;
3576
3577 if (filter->plist[direct].name)
3578 free (filter->plist[direct].name);
3579 filter->plist[direct].name = strdup (name);
3580 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3581 }
3582 return 0;
3583}
3584
3585int
3586peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3587{
3588 struct bgp_filter *filter;
3589 struct bgp_filter *gfilter;
3590 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003591 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003592
3593 if (! peer->afc[afi][safi])
3594 return BGP_ERR_PEER_INACTIVE;
3595
3596 if (direct != FILTER_IN && direct != FILTER_OUT)
3597 return BGP_ERR_INVALID_VALUE;
3598
3599 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3600 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3601
3602 filter = &peer->filter[afi][safi];
3603
3604 /* apply peer-group filter */
3605 if (peer->af_group[afi][safi])
3606 {
3607 gfilter = &peer->group->conf->filter[afi][safi];
3608
3609 if (gfilter->plist[direct].name)
3610 {
3611 if (filter->plist[direct].name)
3612 free (filter->plist[direct].name);
3613 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3614 filter->plist[direct].plist = gfilter->plist[direct].plist;
3615 return 0;
3616 }
3617 }
3618
3619 if (filter->plist[direct].name)
3620 free (filter->plist[direct].name);
3621 filter->plist[direct].name = NULL;
3622 filter->plist[direct].plist = NULL;
3623
3624 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3625 return 0;
3626
3627 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003628 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003629 {
3630 filter = &peer->filter[afi][safi];
3631
3632 if (! peer->af_group[afi][safi])
3633 continue;
3634
3635 if (filter->plist[direct].name)
3636 free (filter->plist[direct].name);
3637 filter->plist[direct].name = NULL;
3638 filter->plist[direct].plist = NULL;
3639 }
3640
3641 return 0;
3642}
3643
3644/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003645static void
paul718e3742002-12-13 20:15:29 +00003646peer_prefix_list_update (struct prefix_list *plist)
3647{
paul1eb8ef22005-04-07 07:30:20 +00003648 struct listnode *mnode, *mnnode;
3649 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003650 struct bgp *bgp;
3651 struct peer *peer;
3652 struct peer_group *group;
3653 struct bgp_filter *filter;
3654 afi_t afi;
3655 safi_t safi;
3656 int direct;
3657
paul1eb8ef22005-04-07 07:30:20 +00003658 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003659 {
paul1eb8ef22005-04-07 07:30:20 +00003660 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003661 {
3662 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3663 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3664 {
3665 filter = &peer->filter[afi][safi];
3666
3667 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3668 {
3669 if (filter->plist[direct].name)
3670 filter->plist[direct].plist =
3671 prefix_list_lookup (afi, filter->plist[direct].name);
3672 else
3673 filter->plist[direct].plist = NULL;
3674 }
3675 }
3676 }
paul1eb8ef22005-04-07 07:30:20 +00003677 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003678 {
3679 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3680 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3681 {
3682 filter = &group->conf->filter[afi][safi];
3683
3684 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3685 {
3686 if (filter->plist[direct].name)
3687 filter->plist[direct].plist =
3688 prefix_list_lookup (afi, filter->plist[direct].name);
3689 else
3690 filter->plist[direct].plist = NULL;
3691 }
3692 }
3693 }
3694 }
3695}
3696
3697int
3698peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003699 const char *name)
paul718e3742002-12-13 20:15:29 +00003700{
3701 struct bgp_filter *filter;
3702 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003703 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003704
3705 if (! peer->afc[afi][safi])
3706 return BGP_ERR_PEER_INACTIVE;
3707
3708 if (direct != FILTER_IN && direct != FILTER_OUT)
3709 return BGP_ERR_INVALID_VALUE;
3710
3711 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3712 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3713
3714 filter = &peer->filter[afi][safi];
3715
3716 if (filter->aslist[direct].name)
3717 free (filter->aslist[direct].name);
3718 filter->aslist[direct].name = strdup (name);
3719 filter->aslist[direct].aslist = as_list_lookup (name);
3720
3721 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3722 return 0;
3723
3724 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003725 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003726 {
3727 filter = &peer->filter[afi][safi];
3728
3729 if (! peer->af_group[afi][safi])
3730 continue;
3731
3732 if (filter->aslist[direct].name)
3733 free (filter->aslist[direct].name);
3734 filter->aslist[direct].name = strdup (name);
3735 filter->aslist[direct].aslist = as_list_lookup (name);
3736 }
3737 return 0;
3738}
3739
3740int
3741peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3742{
3743 struct bgp_filter *filter;
3744 struct bgp_filter *gfilter;
3745 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003746 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003747
3748 if (! peer->afc[afi][safi])
3749 return BGP_ERR_PEER_INACTIVE;
3750
hassob5f29602005-05-25 21:00:28 +00003751 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00003752 return BGP_ERR_INVALID_VALUE;
3753
hassob5f29602005-05-25 21:00:28 +00003754 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003755 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3756
3757 filter = &peer->filter[afi][safi];
3758
3759 /* apply peer-group filter */
3760 if (peer->af_group[afi][safi])
3761 {
3762 gfilter = &peer->group->conf->filter[afi][safi];
3763
3764 if (gfilter->aslist[direct].name)
3765 {
3766 if (filter->aslist[direct].name)
3767 free (filter->aslist[direct].name);
3768 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
3769 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
3770 return 0;
3771 }
3772 }
3773
3774 if (filter->aslist[direct].name)
3775 free (filter->aslist[direct].name);
3776 filter->aslist[direct].name = NULL;
3777 filter->aslist[direct].aslist = NULL;
3778
3779 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3780 return 0;
3781
3782 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003783 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003784 {
3785 filter = &peer->filter[afi][safi];
3786
3787 if (! peer->af_group[afi][safi])
3788 continue;
3789
3790 if (filter->aslist[direct].name)
3791 free (filter->aslist[direct].name);
3792 filter->aslist[direct].name = NULL;
3793 filter->aslist[direct].aslist = NULL;
3794 }
3795
3796 return 0;
3797}
3798
paul94f2b392005-06-28 12:44:16 +00003799static void
paul718e3742002-12-13 20:15:29 +00003800peer_aslist_update ()
3801{
3802 afi_t afi;
3803 safi_t safi;
3804 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003805 struct listnode *mnode, *mnnode;
3806 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003807 struct bgp *bgp;
3808 struct peer *peer;
3809 struct peer_group *group;
3810 struct bgp_filter *filter;
3811
paul1eb8ef22005-04-07 07:30:20 +00003812 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003813 {
paul1eb8ef22005-04-07 07:30:20 +00003814 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003815 {
3816 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3817 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3818 {
3819 filter = &peer->filter[afi][safi];
3820
3821 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3822 {
3823 if (filter->aslist[direct].name)
3824 filter->aslist[direct].aslist =
3825 as_list_lookup (filter->aslist[direct].name);
3826 else
3827 filter->aslist[direct].aslist = NULL;
3828 }
3829 }
3830 }
paul1eb8ef22005-04-07 07:30:20 +00003831 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003832 {
3833 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3834 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3835 {
3836 filter = &group->conf->filter[afi][safi];
3837
3838 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3839 {
3840 if (filter->aslist[direct].name)
3841 filter->aslist[direct].aslist =
3842 as_list_lookup (filter->aslist[direct].name);
3843 else
3844 filter->aslist[direct].aslist = NULL;
3845 }
3846 }
3847 }
3848 }
3849}
3850
3851/* Set route-map to the peer. */
3852int
3853peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003854 const char *name)
paul718e3742002-12-13 20:15:29 +00003855{
3856 struct bgp_filter *filter;
3857 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003858 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003859
3860 if (! peer->afc[afi][safi])
3861 return BGP_ERR_PEER_INACTIVE;
3862
paulfee0f4c2004-09-13 05:12:46 +00003863 if (direct != RMAP_IN && direct != RMAP_OUT &&
3864 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003865 return BGP_ERR_INVALID_VALUE;
3866
paulfee0f4c2004-09-13 05:12:46 +00003867 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
3868 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003869 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3870
3871 filter = &peer->filter[afi][safi];
3872
3873 if (filter->map[direct].name)
3874 free (filter->map[direct].name);
3875
3876 filter->map[direct].name = strdup (name);
3877 filter->map[direct].map = route_map_lookup_by_name (name);
3878
3879 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3880 return 0;
3881
3882 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003883 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003884 {
3885 filter = &peer->filter[afi][safi];
3886
3887 if (! peer->af_group[afi][safi])
3888 continue;
3889
3890 if (filter->map[direct].name)
3891 free (filter->map[direct].name);
3892 filter->map[direct].name = strdup (name);
3893 filter->map[direct].map = route_map_lookup_by_name (name);
3894 }
3895 return 0;
3896}
3897
3898/* Unset route-map from the peer. */
3899int
3900peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3901{
3902 struct bgp_filter *filter;
3903 struct bgp_filter *gfilter;
3904 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003905 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003906
3907 if (! peer->afc[afi][safi])
3908 return BGP_ERR_PEER_INACTIVE;
3909
hassob5f29602005-05-25 21:00:28 +00003910 if (direct != RMAP_IN && direct != RMAP_OUT &&
3911 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003912 return BGP_ERR_INVALID_VALUE;
3913
hassob5f29602005-05-25 21:00:28 +00003914 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
3915 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003916 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3917
3918 filter = &peer->filter[afi][safi];
3919
3920 /* apply peer-group filter */
3921 if (peer->af_group[afi][safi])
3922 {
3923 gfilter = &peer->group->conf->filter[afi][safi];
3924
3925 if (gfilter->map[direct].name)
3926 {
3927 if (filter->map[direct].name)
3928 free (filter->map[direct].name);
3929 filter->map[direct].name = strdup (gfilter->map[direct].name);
3930 filter->map[direct].map = gfilter->map[direct].map;
3931 return 0;
3932 }
3933 }
3934
3935 if (filter->map[direct].name)
3936 free (filter->map[direct].name);
3937 filter->map[direct].name = NULL;
3938 filter->map[direct].map = NULL;
3939
3940 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3941 return 0;
3942
3943 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003944 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003945 {
3946 filter = &peer->filter[afi][safi];
3947
3948 if (! peer->af_group[afi][safi])
3949 continue;
3950
3951 if (filter->map[direct].name)
3952 free (filter->map[direct].name);
3953 filter->map[direct].name = NULL;
3954 filter->map[direct].map = NULL;
3955 }
3956 return 0;
3957}
3958
3959/* Set unsuppress-map to the peer. */
3960int
paulfd79ac92004-10-13 05:06:08 +00003961peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
3962 const char *name)
paul718e3742002-12-13 20:15:29 +00003963{
3964 struct bgp_filter *filter;
3965 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003966 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003967
3968 if (! peer->afc[afi][safi])
3969 return BGP_ERR_PEER_INACTIVE;
3970
3971 if (peer_is_group_member (peer, afi, safi))
3972 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3973
3974 filter = &peer->filter[afi][safi];
3975
3976 if (filter->usmap.name)
3977 free (filter->usmap.name);
3978
3979 filter->usmap.name = strdup (name);
3980 filter->usmap.map = route_map_lookup_by_name (name);
3981
3982 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3983 return 0;
3984
3985 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003986 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003987 {
3988 filter = &peer->filter[afi][safi];
3989
3990 if (! peer->af_group[afi][safi])
3991 continue;
3992
3993 if (filter->usmap.name)
3994 free (filter->usmap.name);
3995 filter->usmap.name = strdup (name);
3996 filter->usmap.map = route_map_lookup_by_name (name);
3997 }
3998 return 0;
3999}
4000
4001/* Unset route-map from the peer. */
4002int
4003peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4004{
4005 struct bgp_filter *filter;
4006 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004007 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004008
4009 if (! peer->afc[afi][safi])
4010 return BGP_ERR_PEER_INACTIVE;
4011
4012 if (peer_is_group_member (peer, afi, safi))
4013 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4014
4015 filter = &peer->filter[afi][safi];
4016
4017 if (filter->usmap.name)
4018 free (filter->usmap.name);
4019 filter->usmap.name = NULL;
4020 filter->usmap.map = NULL;
4021
4022 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4023 return 0;
4024
4025 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004026 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004027 {
4028 filter = &peer->filter[afi][safi];
4029
4030 if (! peer->af_group[afi][safi])
4031 continue;
4032
4033 if (filter->usmap.name)
4034 free (filter->usmap.name);
4035 filter->usmap.name = NULL;
4036 filter->usmap.map = NULL;
4037 }
4038 return 0;
4039}
4040
4041int
4042peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004043 u_int32_t max, u_char threshold,
4044 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004045{
4046 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004047 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004048
4049 if (! peer->afc[afi][safi])
4050 return BGP_ERR_PEER_INACTIVE;
4051
4052 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4053 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004054 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004055 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004056 if (warning)
4057 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4058 else
4059 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4060
4061 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4062 return 0;
4063
4064 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004065 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004066 {
4067 if (! peer->af_group[afi][safi])
4068 continue;
4069
4070 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4071 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004072 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004073 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004074 if (warning)
4075 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4076 else
4077 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4078 }
4079 return 0;
4080}
4081
4082int
4083peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4084{
4085 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004086 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004087
4088 if (! peer->afc[afi][safi])
4089 return BGP_ERR_PEER_INACTIVE;
4090
4091 /* apply peer-group config */
4092 if (peer->af_group[afi][safi])
4093 {
4094 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4095 PEER_FLAG_MAX_PREFIX))
4096 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4097 else
4098 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4099
4100 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4101 PEER_FLAG_MAX_PREFIX_WARNING))
4102 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4103 else
4104 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4105
4106 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004107 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004108 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004109 return 0;
4110 }
4111
4112 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4113 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4114 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004115 peer->pmax_threshold[afi][safi] = 0;
4116 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004117
4118 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4119 return 0;
4120
4121 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004122 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004123 {
4124 if (! peer->af_group[afi][safi])
4125 continue;
4126
4127 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4128 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4129 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004130 peer->pmax_threshold[afi][safi] = 0;
4131 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004132 }
4133 return 0;
4134}
4135
4136int
4137peer_clear (struct peer *peer)
4138{
4139 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4140 {
hasso0a486e52005-02-01 20:57:17 +00004141 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4142 {
4143 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4144 if (peer->t_pmax_restart)
4145 {
4146 BGP_TIMER_OFF (peer->t_pmax_restart);
4147 if (BGP_DEBUG (events, EVENTS))
4148 zlog_debug ("%s Maximum-prefix restart timer canceled",
4149 peer->host);
4150 }
4151 BGP_EVENT_ADD (peer, BGP_Start);
4152 return 0;
4153 }
4154
paul718e3742002-12-13 20:15:29 +00004155 peer->v_start = BGP_INIT_START_TIMER;
4156 if (peer->status == Established)
4157 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4158 BGP_NOTIFY_CEASE_ADMIN_RESET);
4159 else
4160 BGP_EVENT_ADD (peer, BGP_Stop);
4161 }
4162 return 0;
4163}
4164
4165int
4166peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4167 enum bgp_clear_type stype)
4168{
4169 if (peer->status != Established)
4170 return 0;
4171
4172 if (! peer->afc[afi][safi])
4173 return BGP_ERR_AF_UNCONFIGURED;
4174
paulfee0f4c2004-09-13 05:12:46 +00004175 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4176 {
4177 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4178 return 0;
4179 bgp_check_local_routes_rsclient (peer, afi, safi);
4180 bgp_soft_reconfig_rsclient (peer, afi, safi);
4181 }
4182
paul718e3742002-12-13 20:15:29 +00004183 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4184 bgp_announce_route (peer, afi, safi);
4185
4186 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4187 {
4188 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4189 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4190 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4191 {
4192 struct bgp_filter *filter = &peer->filter[afi][safi];
4193 u_char prefix_type;
4194
4195 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4196 prefix_type = ORF_TYPE_PREFIX;
4197 else
4198 prefix_type = ORF_TYPE_PREFIX_OLD;
4199
4200 if (filter->plist[FILTER_IN].plist)
4201 {
4202 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4203 bgp_route_refresh_send (peer, afi, safi,
4204 prefix_type, REFRESH_DEFER, 1);
4205 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4206 REFRESH_IMMEDIATE, 0);
4207 }
4208 else
4209 {
4210 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4211 bgp_route_refresh_send (peer, afi, safi,
4212 prefix_type, REFRESH_IMMEDIATE, 1);
4213 else
4214 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4215 }
4216 return 0;
4217 }
4218 }
4219
4220 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4221 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4222 {
4223 /* If neighbor has soft reconfiguration inbound flag.
4224 Use Adj-RIB-In database. */
4225 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4226 bgp_soft_reconfig_in (peer, afi, safi);
4227 else
4228 {
4229 /* If neighbor has route refresh capability, send route refresh
4230 message to the peer. */
4231 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4232 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4233 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4234 else
4235 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4236 }
4237 }
4238 return 0;
4239}
4240
paulfd79ac92004-10-13 05:06:08 +00004241/* Display peer uptime.*/
4242/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004243char *
4244peer_uptime (time_t uptime2, char *buf, size_t len)
4245{
4246 time_t uptime1;
4247 struct tm *tm;
4248
4249 /* Check buffer length. */
4250 if (len < BGP_UPTIME_LEN)
4251 {
gdtc29fdba2004-12-09 14:46:46 +00004252 /* XXX: warning: long int format, size_t arg (arg 2) */
paula2b1ecd2004-10-31 18:58:09 +00004253 zlog_warn ("peer_uptime (): buffer shortage %ld", len);
paulfd79ac92004-10-13 05:06:08 +00004254 /* XXX: should return status instead of buf... */
4255 snprintf (buf, len, "<error> ");
4256 return buf;
paul718e3742002-12-13 20:15:29 +00004257 }
4258
4259 /* If there is no connection has been done before print `never'. */
4260 if (uptime2 == 0)
4261 {
4262 snprintf (buf, len, "never ");
4263 return buf;
4264 }
4265
4266 /* Get current time. */
4267 uptime1 = time (NULL);
4268 uptime1 -= uptime2;
4269 tm = gmtime (&uptime1);
4270
4271 /* Making formatted timer strings. */
4272#define ONE_DAY_SECOND 60*60*24
4273#define ONE_WEEK_SECOND 60*60*24*7
4274
4275 if (uptime1 < ONE_DAY_SECOND)
4276 snprintf (buf, len, "%02d:%02d:%02d",
4277 tm->tm_hour, tm->tm_min, tm->tm_sec);
4278 else if (uptime1 < ONE_WEEK_SECOND)
4279 snprintf (buf, len, "%dd%02dh%02dm",
4280 tm->tm_yday, tm->tm_hour, tm->tm_min);
4281 else
4282 snprintf (buf, len, "%02dw%dd%02dh",
4283 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4284 return buf;
4285}
4286
paul94f2b392005-06-28 12:44:16 +00004287static void
paul718e3742002-12-13 20:15:29 +00004288bgp_config_write_filter (struct vty *vty, struct peer *peer,
4289 afi_t afi, safi_t safi)
4290{
4291 struct bgp_filter *filter;
4292 struct bgp_filter *gfilter = NULL;
4293 char *addr;
4294 int in = FILTER_IN;
4295 int out = FILTER_OUT;
4296
4297 addr = peer->host;
4298 filter = &peer->filter[afi][safi];
4299 if (peer->af_group[afi][safi])
4300 gfilter = &peer->group->conf->filter[afi][safi];
4301
4302 /* distribute-list. */
4303 if (filter->dlist[in].name)
4304 if (! gfilter || ! gfilter->dlist[in].name
4305 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4306 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4307 filter->dlist[in].name, VTY_NEWLINE);
4308 if (filter->dlist[out].name && ! gfilter)
4309 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4310 filter->dlist[out].name, VTY_NEWLINE);
4311
4312 /* prefix-list. */
4313 if (filter->plist[in].name)
4314 if (! gfilter || ! gfilter->plist[in].name
4315 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4316 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4317 filter->plist[in].name, VTY_NEWLINE);
4318 if (filter->plist[out].name && ! gfilter)
4319 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4320 filter->plist[out].name, VTY_NEWLINE);
4321
4322 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004323 if (filter->map[RMAP_IN].name)
4324 if (! gfilter || ! gfilter->map[RMAP_IN].name
4325 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004326 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004327 filter->map[RMAP_IN].name, VTY_NEWLINE);
4328 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004329 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004330 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4331 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4332 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4333 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4334 if (filter->map[RMAP_EXPORT].name)
4335 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4336 || strcmp (filter->map[RMAP_EXPORT].name,
4337 gfilter->map[RMAP_EXPORT].name) != 0)
4338 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4339 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004340
4341 /* unsuppress-map */
4342 if (filter->usmap.name && ! gfilter)
4343 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4344 filter->usmap.name, VTY_NEWLINE);
4345
4346 /* filter-list. */
4347 if (filter->aslist[in].name)
4348 if (! gfilter || ! gfilter->aslist[in].name
4349 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4350 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4351 filter->aslist[in].name, VTY_NEWLINE);
4352 if (filter->aslist[out].name && ! gfilter)
4353 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4354 filter->aslist[out].name, VTY_NEWLINE);
4355}
4356
4357/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004358static void
paul718e3742002-12-13 20:15:29 +00004359bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4360 struct peer *peer, afi_t afi, safi_t safi)
4361{
4362 struct bgp_filter *filter;
4363 struct peer *g_peer = NULL;
4364 char buf[SU_ADDRSTRLEN];
4365 char *addr;
4366
4367 filter = &peer->filter[afi][safi];
4368 addr = peer->host;
4369 if (peer_group_active (peer))
4370 g_peer = peer->group->conf;
4371
4372 /************************************
4373 ****** Global to the neighbor ******
4374 ************************************/
4375 if (afi == AFI_IP && safi == SAFI_UNICAST)
4376 {
4377 /* remote-as. */
4378 if (! peer_group_active (peer))
4379 {
4380 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4381 vty_out (vty, " neighbor %s peer-group%s", addr,
4382 VTY_NEWLINE);
4383 if (peer->as)
4384 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4385 VTY_NEWLINE);
4386 }
4387 else
4388 {
4389 if (! g_peer->as)
4390 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4391 VTY_NEWLINE);
4392 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4393 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4394 peer->group->name, VTY_NEWLINE);
4395 }
4396
4397 /* local-as. */
4398 if (peer->change_local_as)
4399 if (! peer_group_active (peer))
4400 vty_out (vty, " neighbor %s local-as %d%s%s", addr,
4401 peer->change_local_as,
4402 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4403 " no-prepend" : "", VTY_NEWLINE);
4404
4405 /* Description. */
4406 if (peer->desc)
4407 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4408 VTY_NEWLINE);
4409
4410 /* Shutdown. */
4411 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4412 if (! peer_group_active (peer) ||
4413 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4414 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4415
4416 /* BGP port. */
4417 if (peer->port != BGP_PORT_DEFAULT)
4418 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
4419 VTY_NEWLINE);
4420
4421 /* Local interface name. */
4422 if (peer->ifname)
4423 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4424 VTY_NEWLINE);
4425
4426 /* Passive. */
4427 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4428 if (! peer_group_active (peer) ||
4429 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4430 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4431
4432 /* EBGP multihop. */
4433 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
4434 if (! peer_group_active (peer) ||
4435 g_peer->ttl != peer->ttl)
4436 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4437 VTY_NEWLINE);
4438
hasso6ffd2072005-02-02 14:50:11 +00004439 /* disable-connected-check. */
4440 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004441 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004442 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4443 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004444
4445 /* Update-source. */
4446 if (peer->update_if)
4447 if (! peer_group_active (peer) || ! g_peer->update_if
4448 || strcmp (g_peer->update_if, peer->update_if) != 0)
4449 vty_out (vty, " neighbor %s update-source %s%s", addr,
4450 peer->update_if, VTY_NEWLINE);
4451 if (peer->update_source)
4452 if (! peer_group_active (peer) || ! g_peer->update_source
4453 || sockunion_cmp (g_peer->update_source,
4454 peer->update_source) != 0)
4455 vty_out (vty, " neighbor %s update-source %s%s", addr,
4456 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4457 VTY_NEWLINE);
4458
paul718e3742002-12-13 20:15:29 +00004459 /* advertisement-interval */
4460 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4461 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4462 addr, peer->v_routeadv, VTY_NEWLINE);
4463
4464 /* timers. */
4465 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4466 && ! peer_group_active (peer))
4467 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4468 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4469
4470 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4471 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4472 peer->connect, VTY_NEWLINE);
4473
4474 /* Default weight. */
4475 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4476 if (! peer_group_active (peer) ||
4477 g_peer->weight != peer->weight)
4478 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4479 VTY_NEWLINE);
4480
paul718e3742002-12-13 20:15:29 +00004481 /* Dynamic capability. */
4482 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4483 if (! peer_group_active (peer) ||
4484 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4485 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4486 VTY_NEWLINE);
4487
4488 /* dont capability negotiation. */
4489 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4490 if (! peer_group_active (peer) ||
4491 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4492 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4493 VTY_NEWLINE);
4494
4495 /* override capability negotiation. */
4496 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4497 if (! peer_group_active (peer) ||
4498 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4499 vty_out (vty, " neighbor %s override-capability%s", addr,
4500 VTY_NEWLINE);
4501
4502 /* strict capability negotiation. */
4503 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4504 if (! peer_group_active (peer) ||
4505 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4506 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4507 VTY_NEWLINE);
4508
4509 if (! peer_group_active (peer))
4510 {
4511 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4512 {
4513 if (peer->afc[AFI_IP][SAFI_UNICAST])
4514 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4515 }
4516 else
4517 {
4518 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4519 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4520 }
4521 }
4522 }
4523
4524
4525 /************************************
4526 ****** Per AF to the neighbor ******
4527 ************************************/
4528
4529 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4530 {
4531 if (peer->af_group[afi][safi])
4532 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4533 peer->group->name, VTY_NEWLINE);
4534 else
4535 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4536 }
4537
4538 /* ORF capability. */
4539 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4540 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4541 if (! peer->af_group[afi][safi])
4542 {
4543 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4544
4545 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4546 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4547 vty_out (vty, " both");
4548 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4549 vty_out (vty, " send");
4550 else
4551 vty_out (vty, " receive");
4552 vty_out (vty, "%s", VTY_NEWLINE);
4553 }
4554
4555 /* Route reflector client. */
4556 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4557 && ! peer->af_group[afi][safi])
4558 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4559 VTY_NEWLINE);
4560
4561 /* Nexthop self. */
4562 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4563 && ! peer->af_group[afi][safi])
4564 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4565
4566 /* Remove private AS. */
4567 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4568 && ! peer->af_group[afi][safi])
4569 vty_out (vty, " neighbor %s remove-private-AS%s",
4570 addr, VTY_NEWLINE);
4571
4572 /* send-community print. */
4573 if (! peer->af_group[afi][safi])
4574 {
4575 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4576 {
4577 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4578 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4579 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4580 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4581 vty_out (vty, " neighbor %s send-community extended%s",
4582 addr, VTY_NEWLINE);
4583 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4584 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4585 }
4586 else
4587 {
4588 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4589 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4590 vty_out (vty, " no neighbor %s send-community both%s",
4591 addr, VTY_NEWLINE);
4592 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4593 vty_out (vty, " no neighbor %s send-community extended%s",
4594 addr, VTY_NEWLINE);
4595 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4596 vty_out (vty, " no neighbor %s send-community%s",
4597 addr, VTY_NEWLINE);
4598 }
4599 }
4600
4601 /* Default information */
4602 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4603 && ! peer->af_group[afi][safi])
4604 {
4605 vty_out (vty, " neighbor %s default-originate", addr);
4606 if (peer->default_rmap[afi][safi].name)
4607 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4608 vty_out (vty, "%s", VTY_NEWLINE);
4609 }
4610
4611 /* Soft reconfiguration inbound. */
4612 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4613 if (! peer->af_group[afi][safi] ||
4614 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4615 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4616 VTY_NEWLINE);
4617
4618 /* maximum-prefix. */
4619 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4620 if (! peer->af_group[afi][safi]
4621 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004622 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004623 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4624 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00004625 {
hasso0a486e52005-02-01 20:57:17 +00004626 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
4627 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
4628 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
4629 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
4630 vty_out (vty, " warning-only");
4631 if (peer->pmax_restart[afi][safi])
4632 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
4633 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00004634 }
paul718e3742002-12-13 20:15:29 +00004635
4636 /* Route server client. */
4637 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
4638 && ! peer->af_group[afi][safi])
4639 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
4640
4641 /* Allow AS in. */
4642 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
4643 if (! peer_group_active (peer)
4644 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
4645 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
4646 {
4647 if (peer->allowas_in[afi][safi] == 3)
4648 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
4649 else
4650 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
4651 peer->allowas_in[afi][safi], VTY_NEWLINE);
4652 }
4653
4654 /* Filter. */
4655 bgp_config_write_filter (vty, peer, afi, safi);
4656
4657 /* atribute-unchanged. */
4658 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4659 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4660 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4661 && ! peer->af_group[afi][safi])
4662 {
4663 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4664 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4665 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4666 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
4667 else
4668 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
4669 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
4670 " as-path" : "",
4671 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
4672 " next-hop" : "",
4673 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
4674 " med" : "", VTY_NEWLINE);
4675 }
4676}
4677
4678/* Display "address-family" configuration header. */
4679void
4680bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
4681 int *write)
4682{
4683 if (*write)
4684 return;
4685
4686 if (afi == AFI_IP && safi == SAFI_UNICAST)
4687 return;
4688
4689 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
4690
4691 if (afi == AFI_IP)
4692 {
4693 if (safi == SAFI_MULTICAST)
4694 vty_out (vty, "ipv4 multicast");
4695 else if (safi == SAFI_MPLS_VPN)
4696 vty_out (vty, "vpnv4 unicast");
4697 }
4698 else if (afi == AFI_IP6)
4699 vty_out (vty, "ipv6");
4700
4701 vty_out (vty, "%s", VTY_NEWLINE);
4702
4703 *write = 1;
4704}
4705
4706/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00004707static int
paul718e3742002-12-13 20:15:29 +00004708bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
4709 safi_t safi)
4710{
4711 int write = 0;
4712 struct peer *peer;
4713 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004714 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004715
4716 bgp_config_write_network (vty, bgp, afi, safi, &write);
4717
4718 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
4719
paul1eb8ef22005-04-07 07:30:20 +00004720 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004721 {
4722 if (group->conf->afc[afi][safi])
4723 {
4724 bgp_config_write_family_header (vty, afi, safi, &write);
4725 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
4726 }
4727 }
paul1eb8ef22005-04-07 07:30:20 +00004728 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004729 {
4730 if (peer->afc[afi][safi])
4731 {
4732 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4733 {
4734 bgp_config_write_family_header (vty, afi, safi, &write);
4735 bgp_config_write_peer (vty, bgp, peer, afi, safi);
4736 }
4737 }
4738 }
4739 if (write)
4740 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
4741
4742 return write;
4743}
4744
4745int
4746bgp_config_write (struct vty *vty)
4747{
4748 int write = 0;
4749 struct bgp *bgp;
4750 struct peer_group *group;
4751 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004752 struct listnode *node, *nnode;
4753 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00004754
4755 /* BGP Multiple instance. */
4756 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4757 {
4758 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
4759 write++;
4760 }
4761
4762 /* BGP Config type. */
4763 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4764 {
4765 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
4766 write++;
4767 }
4768
4769 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004770 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004771 {
4772 if (write)
4773 vty_out (vty, "!%s", VTY_NEWLINE);
4774
4775 /* Router bgp ASN */
4776 vty_out (vty, "router bgp %d", bgp->as);
4777
4778 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4779 {
4780 if (bgp->name)
4781 vty_out (vty, " view %s", bgp->name);
4782 }
4783 vty_out (vty, "%s", VTY_NEWLINE);
4784
4785 /* No Synchronization */
4786 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4787 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
4788
4789 /* BGP fast-external-failover. */
4790 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
4791 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
4792
4793 /* BGP router ID. */
4794 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
4795 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
4796 VTY_NEWLINE);
4797
paul848973c2003-08-13 00:32:49 +00004798 /* BGP log-neighbor-changes. */
4799 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
4800 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
4801
paul718e3742002-12-13 20:15:29 +00004802 /* BGP configuration. */
4803 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
4804 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
4805
4806 /* BGP default ipv4-unicast. */
4807 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4808 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
4809
4810 /* BGP default local-preference. */
4811 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
4812 vty_out (vty, " bgp default local-preference %d%s",
4813 bgp->default_local_pref, VTY_NEWLINE);
4814
4815 /* BGP client-to-client reflection. */
4816 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
4817 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
4818
4819 /* BGP cluster ID. */
4820 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
4821 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
4822 VTY_NEWLINE);
4823
hassoe0701b72004-05-20 09:19:34 +00004824 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00004825 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00004826 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
4827 VTY_NEWLINE);
4828
4829 /* Confederation peer */
4830 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00004831 {
hassoe0701b72004-05-20 09:19:34 +00004832 int i;
paul718e3742002-12-13 20:15:29 +00004833
hassoe0701b72004-05-20 09:19:34 +00004834 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00004835
hassoe0701b72004-05-20 09:19:34 +00004836 for (i = 0; i < bgp->confed_peers_cnt; i++)
4837 vty_out(vty, " %d", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00004838
hassoe0701b72004-05-20 09:19:34 +00004839 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004840 }
4841
4842 /* BGP enforce-first-as. */
4843 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
4844 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
4845
4846 /* BGP deterministic-med. */
4847 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
4848 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00004849
4850 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00004851 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
4852 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
4853 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00004854 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
4855 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
4856
paul718e3742002-12-13 20:15:29 +00004857 /* BGP bestpath method. */
4858 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
4859 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00004860 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
4861 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004862 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
4863 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
4864 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
4865 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4866 {
4867 vty_out (vty, " bgp bestpath med");
4868 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
4869 vty_out (vty, " confed");
4870 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4871 vty_out (vty, " missing-as-worst");
4872 vty_out (vty, "%s", VTY_NEWLINE);
4873 }
4874
4875 /* BGP network import check. */
4876 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
4877 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
4878
4879 /* BGP scan interval. */
4880 bgp_config_write_scan_time (vty);
4881
4882 /* BGP flag dampening. */
4883 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
4884 BGP_CONFIG_DAMPENING))
4885 bgp_config_write_damp (vty);
4886
4887 /* BGP static route configuration. */
4888 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4889
4890 /* BGP redistribute configuration. */
4891 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4892
4893 /* BGP timers configuration. */
4894 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
4895 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
4896 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
4897 bgp->default_holdtime, VTY_NEWLINE);
4898
4899 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00004900 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004901 {
4902 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
4903 }
4904
4905 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004906 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004907 {
4908 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4909 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
4910 }
4911
4912 /* Distance configuration. */
4913 bgp_config_write_distance (vty, bgp);
4914
4915 /* No auto-summary */
4916 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4917 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
4918
4919 /* IPv4 multicast configuration. */
4920 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
4921
4922 /* IPv4 VPN configuration. */
4923 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
4924
4925 /* IPv6 unicast configuration. */
4926 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
4927
4928 write++;
4929 }
4930 return write;
4931}
4932
4933void
paul94f2b392005-06-28 12:44:16 +00004934bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00004935{
4936 memset (&bgp_master, 0, sizeof (struct bgp_master));
4937
4938 bm = &bgp_master;
4939 bm->bgp = list_new ();
4940 bm->port = BGP_PORT_DEFAULT;
4941 bm->master = thread_master_create ();
4942 bm->start_time = time (NULL);
4943}
paul200df112005-06-01 11:17:05 +00004944
paul718e3742002-12-13 20:15:29 +00004945
4946void
paul94f2b392005-06-28 12:44:16 +00004947bgp_init (void)
paul718e3742002-12-13 20:15:29 +00004948{
paul718e3742002-12-13 20:15:29 +00004949 /* BGP VTY commands installation. */
4950 bgp_vty_init ();
4951
4952 /* Create BGP server socket. */
4953 bgp_socket (NULL, bm->port);
4954
4955 /* Init zebra. */
4956 bgp_zebra_init ();
4957
4958 /* BGP inits. */
4959 bgp_attr_init ();
4960 bgp_debug_init ();
4961 bgp_dump_init ();
4962 bgp_route_init ();
4963 bgp_route_map_init ();
4964 bgp_scan_init ();
4965 bgp_mplsvpn_init ();
4966
4967 /* Access list initialize. */
4968 access_list_init ();
4969 access_list_add_hook (peer_distribute_update);
4970 access_list_delete_hook (peer_distribute_update);
4971
4972 /* Filter list initialize. */
4973 bgp_filter_init ();
4974 as_list_add_hook (peer_aslist_update);
4975 as_list_delete_hook (peer_aslist_update);
4976
4977 /* Prefix list initialize.*/
4978 prefix_list_init ();
4979 prefix_list_add_hook (peer_prefix_list_update);
4980 prefix_list_delete_hook (peer_prefix_list_update);
4981
4982 /* Community list initialize. */
4983 bgp_clist = community_list_init ();
4984
4985#ifdef HAVE_SNMP
4986 bgp_snmp_init ();
4987#endif /* HAVE_SNMP */
4988}
paul545acaf2004-04-20 15:13:15 +00004989
4990void
4991bgp_terminate ()
4992{
paul545acaf2004-04-20 15:13:15 +00004993 struct bgp *bgp;
4994 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004995 struct listnode *node, *nnode;
4996 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00004997
paul1eb8ef22005-04-07 07:30:20 +00004998 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
4999 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005000 if (peer->status == Established)
5001 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5002 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005003
paul545acaf2004-04-20 15:13:15 +00005004 bgp_cleanup_routes ();
paule210cf92005-06-15 19:15:35 +00005005 if (bm->process_main_queue)
5006 work_queue_free (bm->process_main_queue);
5007 if (bm->process_rsclient_queue)
5008 work_queue_free (bm->process_rsclient_queue);
paul545acaf2004-04-20 15:13:15 +00005009}
5010