blob: 374c4c5281531de5991a0f4a11e104fb206f1be3 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* BGP-4, BGP-4+ daemon program
2 Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "prefix.h"
24#include "thread.h"
25#include "buffer.h"
26#include "stream.h"
27#include "command.h"
28#include "sockunion.h"
29#include "network.h"
30#include "memory.h"
31#include "filter.h"
32#include "routemap.h"
33#include "str.h"
34#include "log.h"
35#include "plist.h"
36#include "linklist.h"
paul200df112005-06-01 11:17:05 +000037#include "workqueue.h"
paul718e3742002-12-13 20:15:29 +000038
39#include "bgpd/bgpd.h"
40#include "bgpd/bgp_table.h"
41#include "bgpd/bgp_aspath.h"
42#include "bgpd/bgp_route.h"
43#include "bgpd/bgp_dump.h"
44#include "bgpd/bgp_debug.h"
45#include "bgpd/bgp_community.h"
46#include "bgpd/bgp_attr.h"
47#include "bgpd/bgp_regex.h"
48#include "bgpd/bgp_clist.h"
49#include "bgpd/bgp_fsm.h"
50#include "bgpd/bgp_packet.h"
51#include "bgpd/bgp_zebra.h"
52#include "bgpd/bgp_open.h"
53#include "bgpd/bgp_filter.h"
54#include "bgpd/bgp_nexthop.h"
55#include "bgpd/bgp_damp.h"
56#include "bgpd/bgp_mplsvpn.h"
57#include "bgpd/bgp_advertise.h"
58#include "bgpd/bgp_network.h"
59#include "bgpd/bgp_vty.h"
60#ifdef HAVE_SNMP
61#include "bgpd/bgp_snmp.h"
62#endif /* HAVE_SNMP */
63
64/* BGP process wide configuration. */
65static struct bgp_master bgp_master;
66
hasso18a6dce2004-10-03 18:18:34 +000067extern struct in_addr router_id_zebra;
68
paul718e3742002-12-13 20:15:29 +000069/* BGP process wide configuration pointer to export. */
70struct bgp_master *bm;
71
72/* BGP community-list. */
73struct community_list_handler *bgp_clist;
74
75/* BGP global flag manipulation. */
76int
77bgp_option_set (int flag)
78{
79 switch (flag)
80 {
81 case BGP_OPT_NO_FIB:
82 case BGP_OPT_MULTIPLE_INSTANCE:
83 case BGP_OPT_CONFIG_CISCO:
84 SET_FLAG (bm->options, flag);
85 break;
86 default:
87 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +000088 }
89 return 0;
90}
91
92int
93bgp_option_unset (int flag)
94{
95 switch (flag)
96 {
97 case BGP_OPT_MULTIPLE_INSTANCE:
98 if (listcount (bm->bgp) > 1)
99 return BGP_ERR_MULTIPLE_INSTANCE_USED;
100 /* Fall through. */
101 case BGP_OPT_NO_FIB:
102 case BGP_OPT_CONFIG_CISCO:
103 UNSET_FLAG (bm->options, flag);
104 break;
105 default:
106 return BGP_ERR_INVALID_FLAG;
paul718e3742002-12-13 20:15:29 +0000107 }
108 return 0;
109}
110
111int
112bgp_option_check (int flag)
113{
114 return CHECK_FLAG (bm->options, flag);
115}
116
117/* BGP flag manipulation. */
118int
119bgp_flag_set (struct bgp *bgp, int flag)
120{
121 SET_FLAG (bgp->flags, flag);
122 return 0;
123}
124
125int
126bgp_flag_unset (struct bgp *bgp, int flag)
127{
128 UNSET_FLAG (bgp->flags, flag);
129 return 0;
130}
131
132int
133bgp_flag_check (struct bgp *bgp, int flag)
134{
135 return CHECK_FLAG (bgp->flags, flag);
136}
137
138/* Internal function to set BGP structure configureation flag. */
139static void
140bgp_config_set (struct bgp *bgp, int config)
141{
142 SET_FLAG (bgp->config, config);
143}
144
145static void
146bgp_config_unset (struct bgp *bgp, int config)
147{
148 UNSET_FLAG (bgp->config, config);
149}
150
151static int
152bgp_config_check (struct bgp *bgp, int config)
153{
154 return CHECK_FLAG (bgp->config, config);
155}
156
157/* Set BGP router identifier. */
158int
159bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
160{
161 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000162 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000163
164 if (bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID)
165 && IPV4_ADDR_SAME (&bgp->router_id, id))
166 return 0;
167
168 IPV4_ADDR_COPY (&bgp->router_id, id);
169 bgp_config_set (bgp, BGP_CONFIG_ROUTER_ID);
170
171 /* Set all peer's local identifier with this value. */
paul1eb8ef22005-04-07 07:30:20 +0000172 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000173 {
174 IPV4_ADDR_COPY (&peer->local_id, id);
175
176 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000177 {
178 peer->last_reset = PEER_DOWN_RID_CHANGE;
179 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
180 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
181 }
paul718e3742002-12-13 20:15:29 +0000182 }
183 return 0;
184}
185
paul718e3742002-12-13 20:15:29 +0000186/* BGP's cluster-id control. */
187int
188bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
189{
190 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000191 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000192
193 if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)
194 && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id))
195 return 0;
196
197 IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id);
198 bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID);
199
200 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000201 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000202 {
203 if (peer_sort (peer) != BGP_PEER_IBGP)
204 continue;
205
206 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000207 {
208 peer->last_reset = PEER_DOWN_CLID_CHANGE;
209 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
210 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
211 }
paul718e3742002-12-13 20:15:29 +0000212 }
213 return 0;
214}
215
216int
217bgp_cluster_id_unset (struct bgp *bgp)
218{
219 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000220 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000221
222 if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID))
223 return 0;
224
225 bgp->cluster_id.s_addr = 0;
226 bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID);
227
228 /* Clear all IBGP peer. */
paul1eb8ef22005-04-07 07:30:20 +0000229 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000230 {
231 if (peer_sort (peer) != BGP_PEER_IBGP)
232 continue;
233
234 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000235 {
236 peer->last_reset = PEER_DOWN_CLID_CHANGE;
237 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
238 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
239 }
paul718e3742002-12-13 20:15:29 +0000240 }
241 return 0;
242}
243
244/* BGP timer configuration. */
245int
246bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
247{
248 bgp->default_keepalive = (keepalive < holdtime / 3
249 ? keepalive : holdtime / 3);
250 bgp->default_holdtime = holdtime;
251
252 return 0;
253}
254
255int
256bgp_timers_unset (struct bgp *bgp)
257{
258 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
259 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
260
261 return 0;
262}
263
264/* BGP confederation configuration. */
265int
266bgp_confederation_id_set (struct bgp *bgp, as_t as)
267{
268 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000269 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000270 int already_confed;
271
272 if (as == 0)
273 return BGP_ERR_INVALID_AS;
274
275 /* Remember - were we doing confederation before? */
276 already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);
277 bgp->confed_id = as;
278 bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);
279
280 /* If we were doing confederation already, this is just an external
281 AS change. Just Reset EBGP sessions, not CONFED sessions. If we
282 were not doing confederation before, reset all EBGP sessions. */
paul1eb8ef22005-04-07 07:30:20 +0000283 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000284 {
285 /* We're looking for peers who's AS is not local or part of our
286 confederation. */
287 if (already_confed)
288 {
289 if (peer_sort (peer) == BGP_PEER_EBGP)
290 {
291 peer->local_as = as;
292 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000293 {
294 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
295 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
296 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
297 }
298
paul718e3742002-12-13 20:15:29 +0000299 else
300 BGP_EVENT_ADD (peer, BGP_Stop);
301 }
302 }
303 else
304 {
305 /* Not doign confederation before, so reset every non-local
306 session */
307 if (peer_sort (peer) != BGP_PEER_IBGP)
308 {
309 /* Reset the local_as to be our EBGP one */
310 if (peer_sort (peer) == BGP_PEER_EBGP)
311 peer->local_as = as;
312 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000313 {
314 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
315 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
316 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
317 }
paul718e3742002-12-13 20:15:29 +0000318 else
319 BGP_EVENT_ADD (peer, BGP_Stop);
320 }
321 }
322 }
323 return 0;
324}
325
326int
327bgp_confederation_id_unset (struct bgp *bgp)
328{
329 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000330 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000331
332 bgp->confed_id = 0;
333 bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
334
paul1eb8ef22005-04-07 07:30:20 +0000335 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000336 {
337 /* We're looking for peers who's AS is not local */
338 if (peer_sort (peer) != BGP_PEER_IBGP)
339 {
340 peer->local_as = bgp->as;
341 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000342 {
343 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
344 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
345 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
346 }
347
paul718e3742002-12-13 20:15:29 +0000348 else
349 BGP_EVENT_ADD (peer, BGP_Stop);
350 }
351 }
352 return 0;
353}
354
355/* Is an AS part of the confed or not? */
356int
357bgp_confederation_peers_check (struct bgp *bgp, as_t as)
358{
359 int i;
360
361 if (! bgp)
362 return 0;
363
364 for (i = 0; i < bgp->confed_peers_cnt; i++)
365 if (bgp->confed_peers[i] == as)
366 return 1;
367
368 return 0;
369}
370
371/* Add an AS to the confederation set. */
372int
373bgp_confederation_peers_add (struct bgp *bgp, as_t as)
374{
375 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000376 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000377
378 if (! bgp)
379 return BGP_ERR_INVALID_BGP;
380
381 if (bgp->as == as)
382 return BGP_ERR_INVALID_AS;
383
384 if (bgp_confederation_peers_check (bgp, as))
385 return -1;
386
387 if (bgp->confed_peers)
388 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
389 bgp->confed_peers,
390 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
391 else
392 bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST,
393 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
394
395 bgp->confed_peers[bgp->confed_peers_cnt] = as;
396 bgp->confed_peers_cnt++;
397
398 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
399 {
paul1eb8ef22005-04-07 07:30:20 +0000400 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000401 {
402 if (peer->as == as)
403 {
404 peer->local_as = bgp->as;
405 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000406 {
407 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
408 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
409 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
410 }
paul718e3742002-12-13 20:15:29 +0000411 else
412 BGP_EVENT_ADD (peer, BGP_Stop);
413 }
414 }
415 }
416 return 0;
417}
418
419/* Delete an AS from the confederation set. */
420int
421bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
422{
423 int i;
424 int j;
425 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000426 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000427
428 if (! bgp)
429 return -1;
430
431 if (! bgp_confederation_peers_check (bgp, as))
432 return -1;
433
434 for (i = 0; i < bgp->confed_peers_cnt; i++)
435 if (bgp->confed_peers[i] == as)
436 for(j = i + 1; j < bgp->confed_peers_cnt; j++)
437 bgp->confed_peers[j - 1] = bgp->confed_peers[j];
438
439 bgp->confed_peers_cnt--;
440
441 if (bgp->confed_peers_cnt == 0)
442 {
443 if (bgp->confed_peers)
444 XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
445 bgp->confed_peers = NULL;
446 }
447 else
448 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
449 bgp->confed_peers,
450 bgp->confed_peers_cnt * sizeof (as_t));
451
452 /* Now reset any peer who's remote AS has just been removed from the
453 CONFED */
454 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
455 {
paul1eb8ef22005-04-07 07:30:20 +0000456 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000457 {
458 if (peer->as == as)
459 {
460 peer->local_as = bgp->confed_id;
461 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000462 {
463 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
464 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
465 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
466 }
paul718e3742002-12-13 20:15:29 +0000467 else
468 BGP_EVENT_ADD (peer, BGP_Stop);
469 }
470 }
471 }
472
473 return 0;
474}
475
476/* Local preference configuration. */
477int
478bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
479{
480 if (! bgp)
481 return -1;
482
paul718e3742002-12-13 20:15:29 +0000483 bgp->default_local_pref = local_pref;
484
485 return 0;
486}
487
488int
489bgp_default_local_preference_unset (struct bgp *bgp)
490{
491 if (! bgp)
492 return -1;
493
paul718e3742002-12-13 20:15:29 +0000494 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
495
496 return 0;
497}
498
paulfee0f4c2004-09-13 05:12:46 +0000499/* If peer is RSERVER_CLIENT in at least one address family and is not member
500 of a peer_group for that family, return 1.
501 Used to check wether the peer is included in list bgp->rsclient. */
502int
503peer_rsclient_active (struct peer *peer)
504{
505 int i;
506 int j;
507
508 for (i=AFI_IP; i < AFI_MAX; i++)
509 for (j=SAFI_UNICAST; j < SAFI_MAX; j++)
510 if (CHECK_FLAG(peer->af_flags[i][j], PEER_FLAG_RSERVER_CLIENT)
511 && ! peer->af_group[i][j])
512 return 1;
513 return 0;
514}
515
pauleb821182004-05-01 08:44:08 +0000516/* Peer comparison function for sorting. */
paul718e3742002-12-13 20:15:29 +0000517static int
518peer_cmp (struct peer *p1, struct peer *p2)
519{
pauleb821182004-05-01 08:44:08 +0000520 return sockunion_cmp (&p1->su, &p2->su);
paul718e3742002-12-13 20:15:29 +0000521}
522
523int
524peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
525{
526 return CHECK_FLAG (peer->af_flags[afi][safi], flag);
527}
528
529/* Reset all address family specific configuration. */
530static void
531peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
532{
533 int i;
534 struct bgp_filter *filter;
535 char orf_name[BUFSIZ];
536
537 filter = &peer->filter[afi][safi];
538
539 /* Clear neighbor filter and route-map */
540 for (i = FILTER_IN; i < FILTER_MAX; i++)
541 {
542 if (filter->dlist[i].name)
543 {
544 free (filter->dlist[i].name);
545 filter->dlist[i].name = NULL;
546 }
547 if (filter->plist[i].name)
548 {
549 free (filter->plist[i].name);
550 filter->plist[i].name = NULL;
551 }
552 if (filter->aslist[i].name)
553 {
554 free (filter->aslist[i].name);
555 filter->aslist[i].name = NULL;
556 }
paulfee0f4c2004-09-13 05:12:46 +0000557 }
558 for (i = RMAP_IN; i < RMAP_MAX; i++)
559 {
paul718e3742002-12-13 20:15:29 +0000560 if (filter->map[i].name)
561 {
562 free (filter->map[i].name);
563 filter->map[i].name = NULL;
564 }
565 }
566
567 /* Clear unsuppress map. */
568 if (filter->usmap.name)
569 free (filter->usmap.name);
570 filter->usmap.name = NULL;
571 filter->usmap.map = NULL;
572
573 /* Clear neighbor's all address family flags. */
574 peer->af_flags[afi][safi] = 0;
575
576 /* Clear neighbor's all address family sflags. */
577 peer->af_sflags[afi][safi] = 0;
578
579 /* Clear neighbor's all address family capabilities. */
580 peer->af_cap[afi][safi] = 0;
581
582 /* Clear ORF info */
583 peer->orf_plist[afi][safi] = NULL;
584 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
585 prefix_bgp_orf_remove_all (orf_name);
586
587 /* Set default neighbor send-community. */
588 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
589 {
590 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
591 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
592 }
593
594 /* Clear neighbor default_originate_rmap */
595 if (peer->default_rmap[afi][safi].name)
596 free (peer->default_rmap[afi][safi].name);
597 peer->default_rmap[afi][safi].name = NULL;
598 peer->default_rmap[afi][safi].map = NULL;
599
600 /* Clear neighbor maximum-prefix */
601 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +0000602 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000603}
604
605/* peer global config reset */
paul94f2b392005-06-28 12:44:16 +0000606static void
paul718e3742002-12-13 20:15:29 +0000607peer_global_config_reset (struct peer *peer)
608{
609 peer->weight = 0;
610 peer->change_local_as = 0;
611 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
612 if (peer->update_source)
613 {
614 sockunion_free (peer->update_source);
615 peer->update_source = NULL;
616 }
617 if (peer->update_if)
618 {
619 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
620 peer->update_if = NULL;
621 }
622
623 if (peer_sort (peer) == BGP_PEER_IBGP)
624 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
625 else
626 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
627
628 peer->flags = 0;
629 peer->config = 0;
630 peer->holdtime = 0;
631 peer->keepalive = 0;
632 peer->connect = 0;
633 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
634}
635
636/* Check peer's AS number and determin is this peer IBGP or EBGP */
637int
638peer_sort (struct peer *peer)
639{
640 struct bgp *bgp;
641
642 bgp = peer->bgp;
643
644 /* Peer-group */
645 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
646 {
647 if (peer->as)
648 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
649 else
650 {
651 struct peer *peer1;
652 peer1 = listnode_head (peer->group->peer);
653 if (peer1)
654 return (peer1->local_as == peer1->as
655 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
656 }
657 return BGP_PEER_INTERNAL;
658 }
659
660 /* Normal peer */
661 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
662 {
663 if (peer->local_as == 0)
664 return BGP_PEER_INTERNAL;
665
666 if (peer->local_as == peer->as)
667 {
668 if (peer->local_as == bgp->confed_id)
669 return BGP_PEER_EBGP;
670 else
671 return BGP_PEER_IBGP;
672 }
673
674 if (bgp_confederation_peers_check (bgp, peer->as))
675 return BGP_PEER_CONFED;
676
677 return BGP_PEER_EBGP;
678 }
679 else
680 {
681 return (peer->local_as == 0
682 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
683 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
684 }
685}
686
paul200df112005-06-01 11:17:05 +0000687static inline void
688peer_free (struct peer *peer)
689{
Paul Jakmaca058a32006-09-14 02:58:49 +0000690 assert (peer->status == Deleted);
691
692 /* this /ought/ to have been done already through bgp_stop earlier,
693 * but just to be sure..
694 */
695 bgp_timer_set (peer);
696 BGP_READ_OFF (peer->t_read);
697 BGP_WRITE_OFF (peer->t_write);
Paul Jakma9fde6622006-09-14 03:02:02 +0000698 BGP_EVENT_FLUSH (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +0000699
paul200df112005-06-01 11:17:05 +0000700 if (peer->desc)
701 XFREE (MTYPE_PEER_DESC, peer->desc);
702
703 /* Free allocated host character. */
704 if (peer->host)
705 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
706
707 /* Update source configuration. */
708 if (peer->update_source)
709 sockunion_free (peer->update_source);
710
711 if (peer->update_if)
712 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
Paul Jakmaa625ca32006-03-30 14:12:38 +0000713
714 if (peer->clear_node_queue)
715 work_queue_free (peer->clear_node_queue);
716
Paul Jakmaca058a32006-09-14 02:58:49 +0000717 bgp_sync_delete (peer);
paul200df112005-06-01 11:17:05 +0000718 memset (peer, 0, sizeof (struct peer));
719
720 XFREE (MTYPE_BGP_PEER, peer);
721}
722
723/* increase reference count on a struct peer */
724struct peer *
725peer_lock (struct peer *peer)
726{
727 assert (peer && (peer->lock >= 0));
Paul Jakmaca058a32006-09-14 02:58:49 +0000728 assert (peer->status != Deleted);
729
paul200df112005-06-01 11:17:05 +0000730 peer->lock++;
731
732 return peer;
733}
734
735/* decrease reference count on a struct peer
736 * struct peer is freed and NULL returned if last reference
737 */
738struct peer *
739peer_unlock (struct peer *peer)
740{
741 assert (peer && (peer->lock > 0));
742
743 peer->lock--;
744
745 if (peer->lock == 0)
746 {
747#if 0
748 zlog_debug ("unlocked and freeing");
749 zlog_backtrace (LOG_DEBUG);
750#endif
751 peer_free (peer);
752 return NULL;
753 }
754
755#if 0
756 if (peer->lock == 1)
757 {
758 zlog_debug ("unlocked to 1");
759 zlog_backtrace (LOG_DEBUG);
760 }
761#endif
762
763 return peer;
764}
765
766/* Allocate new peer object, implicitely locked. */
paul718e3742002-12-13 20:15:29 +0000767static struct peer *
Paul Jakma6f585442006-10-22 19:13:07 +0000768peer_new (struct bgp *bgp)
paul718e3742002-12-13 20:15:29 +0000769{
770 afi_t afi;
771 safi_t safi;
772 struct peer *peer;
773 struct servent *sp;
Paul Jakma6f585442006-10-22 19:13:07 +0000774
775 /* bgp argument is absolutely required */
776 assert (bgp);
777 if (!bgp)
778 return NULL;
779
paul718e3742002-12-13 20:15:29 +0000780 /* Allocate new peer. */
Paul Jakmaca058a32006-09-14 02:58:49 +0000781 peer = XCALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
paul718e3742002-12-13 20:15:29 +0000782
783 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000784 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000785 peer->v_start = BGP_INIT_START_TIMER;
786 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
787 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
788 peer->status = Idle;
789 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000790 peer->weight = 0;
Paul Jakma6f585442006-10-22 19:13:07 +0000791 peer->bgp = bgp;
Paul Jakmaca058a32006-09-14 02:58:49 +0000792 peer = peer_lock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +0000793
794 /* Set default flags. */
795 for (afi = AFI_IP; afi < AFI_MAX; afi++)
796 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
797 {
798 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
799 {
800 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
801 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
802 }
803 peer->orf_plist[afi][safi] = NULL;
804 }
805 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
806
807 /* Create buffers. */
808 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
809 peer->obuf = stream_fifo_new ();
810 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
811
812 bgp_sync_init (peer);
813
814 /* Get service port number. */
815 sp = getservbyname ("bgp", "tcp");
816 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
817
818 return peer;
819}
820
821/* Create new BGP peer. */
paul94f2b392005-06-28 12:44:16 +0000822static struct peer *
paul718e3742002-12-13 20:15:29 +0000823peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
824 as_t remote_as, afi_t afi, safi_t safi)
825{
826 int active;
827 struct peer *peer;
828 char buf[SU_ADDRSTRLEN];
829
Paul Jakma6f585442006-10-22 19:13:07 +0000830 peer = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +0000831 peer->su = *su;
832 peer->local_as = local_as;
833 peer->as = remote_as;
834 peer->local_id = bgp->router_id;
835 peer->v_holdtime = bgp->default_holdtime;
836 peer->v_keepalive = bgp->default_keepalive;
837 if (peer_sort (peer) == BGP_PEER_IBGP)
838 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
839 else
840 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
paul200df112005-06-01 11:17:05 +0000841
842 peer = peer_lock (peer); /* bgp peer list reference */
paul718e3742002-12-13 20:15:29 +0000843 listnode_add_sort (bgp->peer, peer);
844
845 active = peer_active (peer);
846
847 if (afi && safi)
848 peer->afc[afi][safi] = 1;
849
850 /* Last read time set */
851 peer->readtime = time (NULL);
852
paul848973c2003-08-13 00:32:49 +0000853 /* Last reset time set */
854 peer->resettime = time (NULL);
855
paul718e3742002-12-13 20:15:29 +0000856 /* Default TTL set. */
857 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
858
859 /* Make peer's address string. */
860 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000861 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000862
863 /* Set up peer's events and timers. */
864 if (! active && peer_active (peer))
865 bgp_timer_set (peer);
866
867 return peer;
868}
869
pauleb821182004-05-01 08:44:08 +0000870/* Make accept BGP peer. Called from bgp_accept (). */
871struct peer *
872peer_create_accept (struct bgp *bgp)
873{
874 struct peer *peer;
875
Paul Jakma6f585442006-10-22 19:13:07 +0000876 peer = peer_new (bgp);
paul200df112005-06-01 11:17:05 +0000877
878 peer = peer_lock (peer); /* bgp peer list reference */
pauleb821182004-05-01 08:44:08 +0000879 listnode_add_sort (bgp->peer, peer);
880
881 return peer;
882}
883
paul718e3742002-12-13 20:15:29 +0000884/* Change peer's AS number. */
paul94f2b392005-06-28 12:44:16 +0000885static void
paul718e3742002-12-13 20:15:29 +0000886peer_as_change (struct peer *peer, as_t as)
887{
888 int type;
889
890 /* Stop peer. */
891 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
892 {
893 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000894 {
895 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
896 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
897 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
898 }
paul718e3742002-12-13 20:15:29 +0000899 else
900 BGP_EVENT_ADD (peer, BGP_Stop);
901 }
902 type = peer_sort (peer);
903 peer->as = as;
904
paul848973c2003-08-13 00:32:49 +0000905 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
906 && ! bgp_confederation_peers_check (peer->bgp, as)
907 && peer->bgp->as != as)
908 peer->local_as = peer->bgp->confed_id;
909 else
910 peer->local_as = peer->bgp->as;
911
paul718e3742002-12-13 20:15:29 +0000912 /* Advertisement-interval reset */
913 if (peer_sort (peer) == BGP_PEER_IBGP)
914 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
915 else
916 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
917
918 /* TTL reset */
919 if (peer_sort (peer) == BGP_PEER_IBGP)
920 peer->ttl = 255;
921 else if (type == BGP_PEER_IBGP)
922 peer->ttl = 1;
923
924 /* reflector-client reset */
925 if (peer_sort (peer) != BGP_PEER_IBGP)
926 {
927 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
928 PEER_FLAG_REFLECTOR_CLIENT);
929 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
930 PEER_FLAG_REFLECTOR_CLIENT);
931 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
932 PEER_FLAG_REFLECTOR_CLIENT);
933 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
934 PEER_FLAG_REFLECTOR_CLIENT);
935 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
936 PEER_FLAG_REFLECTOR_CLIENT);
937 }
938
939 /* local-as reset */
940 if (peer_sort (peer) != BGP_PEER_EBGP)
941 {
942 peer->change_local_as = 0;
943 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
944 }
945}
946
947/* If peer does not exist, create new one. If peer already exists,
948 set AS number to the peer. */
949int
950peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
951 afi_t afi, safi_t safi)
952{
953 struct peer *peer;
954 as_t local_as;
955
956 peer = peer_lookup (bgp, su);
957
958 if (peer)
959 {
960 /* When this peer is a member of peer-group. */
961 if (peer->group)
962 {
963 if (peer->group->conf->as)
964 {
965 /* Return peer group's AS number. */
966 *as = peer->group->conf->as;
967 return BGP_ERR_PEER_GROUP_MEMBER;
968 }
969 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
970 {
971 if (bgp->as != *as)
972 {
973 *as = peer->as;
974 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
975 }
976 }
977 else
978 {
979 if (bgp->as == *as)
980 {
981 *as = peer->as;
982 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
983 }
984 }
985 }
986
987 /* Existing peer's AS number change. */
988 if (peer->as != *as)
989 peer_as_change (peer, *as);
990 }
991 else
992 {
993
994 /* If the peer is not part of our confederation, and its not an
995 iBGP peer then spoof the source AS */
996 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
997 && ! bgp_confederation_peers_check (bgp, *as)
998 && bgp->as != *as)
999 local_as = bgp->confed_id;
1000 else
1001 local_as = bgp->as;
1002
1003 /* If this is IPv4 unicast configuration and "no bgp default
1004 ipv4-unicast" is specified. */
1005
1006 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
1007 && afi == AFI_IP && safi == SAFI_UNICAST)
1008 peer = peer_create (su, bgp, local_as, *as, 0, 0);
1009 else
1010 peer = peer_create (su, bgp, local_as, *as, afi, safi);
1011 }
1012
1013 return 0;
1014}
1015
1016/* Activate the peer or peer group for specified AFI and SAFI. */
1017int
1018peer_activate (struct peer *peer, afi_t afi, safi_t safi)
1019{
1020 int active;
1021
1022 if (peer->afc[afi][safi])
1023 return 0;
1024
1025 /* Activate the address family configuration. */
1026 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1027 peer->afc[afi][safi] = 1;
1028 else
1029 {
1030 active = peer_active (peer);
1031
1032 peer->afc[afi][safi] = 1;
1033
1034 if (! active && peer_active (peer))
1035 bgp_timer_set (peer);
1036 else
1037 {
1038 if (peer->status == Established)
1039 {
1040 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1041 {
1042 peer->afc_adv[afi][safi] = 1;
1043 bgp_capability_send (peer, afi, safi,
1044 CAPABILITY_CODE_MP,
1045 CAPABILITY_ACTION_SET);
1046 if (peer->afc_recv[afi][safi])
1047 {
1048 peer->afc_nego[afi][safi] = 1;
1049 bgp_announce_route (peer, afi, safi);
1050 }
1051 }
1052 else
hassoe0701b72004-05-20 09:19:34 +00001053 {
1054 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
1055 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1056 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1057 }
paul718e3742002-12-13 20:15:29 +00001058 }
1059 }
1060 }
1061 return 0;
1062}
1063
1064int
1065peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
1066{
1067 struct peer_group *group;
1068 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +00001069 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001070
1071 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1072 {
1073 group = peer->group;
1074
paul1eb8ef22005-04-07 07:30:20 +00001075 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +00001076 {
1077 if (peer1->af_group[afi][safi])
1078 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1079 }
1080 }
1081 else
1082 {
1083 if (peer->af_group[afi][safi])
1084 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1085 }
1086
1087 if (! peer->afc[afi][safi])
1088 return 0;
1089
1090 /* De-activate the address family configuration. */
1091 peer->afc[afi][safi] = 0;
1092 peer_af_flag_reset (peer, afi, safi);
1093
1094 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1095 {
1096 if (peer->status == Established)
1097 {
1098 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1099 {
1100 peer->afc_adv[afi][safi] = 0;
1101 peer->afc_nego[afi][safi] = 0;
1102
1103 if (peer_active_nego (peer))
1104 {
1105 bgp_capability_send (peer, afi, safi,
1106 CAPABILITY_CODE_MP,
1107 CAPABILITY_ACTION_UNSET);
1108 bgp_clear_route (peer, afi, safi);
1109 peer->pcount[afi][safi] = 0;
1110 }
1111 else
hassoe0701b72004-05-20 09:19:34 +00001112 {
1113 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1114 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1115 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1116 }
paul718e3742002-12-13 20:15:29 +00001117 }
1118 else
hassoe0701b72004-05-20 09:19:34 +00001119 {
1120 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1121 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1122 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1123 }
paul718e3742002-12-13 20:15:29 +00001124 }
1125 }
1126 return 0;
1127}
1128
hasso93406d82005-02-02 14:40:33 +00001129void
1130peer_nsf_stop (struct peer *peer)
1131{
1132 afi_t afi;
1133 safi_t safi;
1134
1135 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1136 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1137
1138 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1139 for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
1140 peer->nsf[afi][safi] = 0;
1141
1142 if (peer->t_gr_restart)
1143 {
1144 BGP_TIMER_OFF (peer->t_gr_restart);
1145 if (BGP_DEBUG (events, EVENTS))
1146 zlog_debug ("%s graceful restart timer stopped", peer->host);
1147 }
1148 if (peer->t_gr_stale)
1149 {
1150 BGP_TIMER_OFF (peer->t_gr_stale);
1151 if (BGP_DEBUG (events, EVENTS))
1152 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1153 }
1154 bgp_clear_route_all (peer);
1155}
1156
Paul Jakmaca058a32006-09-14 02:58:49 +00001157/* Delete peer from confguration.
1158 *
1159 * The peer is moved to a dead-end "Deleted" neighbour-state, to allow
1160 * it to "cool off" and refcounts to hit 0, at which state it is freed.
1161 *
1162 * This function /should/ take care to be idempotent, to guard against
1163 * it being called multiple times through stray events that come in
1164 * that happen to result in this function being called again. That
1165 * said, getting here for a "Deleted" peer is a bug in the neighbour
1166 * FSM.
1167 */
paul718e3742002-12-13 20:15:29 +00001168int
1169peer_delete (struct peer *peer)
1170{
1171 int i;
1172 afi_t afi;
1173 safi_t safi;
1174 struct bgp *bgp;
1175 struct bgp_filter *filter;
1176
Paul Jakmaca058a32006-09-14 02:58:49 +00001177 assert (peer->status != Deleted);
1178
paul718e3742002-12-13 20:15:29 +00001179 bgp = peer->bgp;
1180
hasso93406d82005-02-02 14:40:33 +00001181 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1182 peer_nsf_stop (peer);
1183
paul718e3742002-12-13 20:15:29 +00001184 /* If this peer belongs to peer group. Clearn up the
1185 relationship. */
1186 if (peer->group)
1187 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001188 struct listnode *pn;
1189
1190 if ((pn = listnode_lookup (peer->group->peer, peer)))
1191 {
1192 peer = peer_unlock (peer); /* group->peer list reference */
1193 list_delete_node (peer->group->peer, pn);
1194 }
paul718e3742002-12-13 20:15:29 +00001195 peer->group = NULL;
1196 }
paul200df112005-06-01 11:17:05 +00001197
paul718e3742002-12-13 20:15:29 +00001198 /* Withdraw all information from routing table. We can not use
paul200df112005-06-01 11:17:05 +00001199 * BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1200 * executed after peer structure is deleted.
1201 */
hassoe0701b72004-05-20 09:19:34 +00001202 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001203 bgp_stop (peer);
Paul Jakmaca058a32006-09-14 02:58:49 +00001204 bgp_fsm_change_status (peer, Deleted);
1205 bgp_timer_set (peer); /* stops all timers for Deleted */
paul200df112005-06-01 11:17:05 +00001206
paul718e3742002-12-13 20:15:29 +00001207 /* Delete from all peer list. */
1208 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
paulfee0f4c2004-09-13 05:12:46 +00001209 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001210 struct listnode *pn;
paul200df112005-06-01 11:17:05 +00001211
Paul Jakmaca058a32006-09-14 02:58:49 +00001212 if ((pn = listnode_lookup (bgp->peer, peer)))
1213 {
1214 peer_unlock (peer); /* bgp peer list reference */
1215 list_delete_node (bgp->peer, pn);
1216 }
1217
1218 if (peer_rsclient_active (peer)
1219 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001220 {
1221 peer_unlock (peer); /* rsclient list reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001222 list_delete_node (bgp->rsclient, pn);
paul200df112005-06-01 11:17:05 +00001223 }
paulfee0f4c2004-09-13 05:12:46 +00001224 }
1225
1226 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1227 member of a peer_group. */
1228 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1229 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1230 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
1231 bgp_table_finish (peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001232
paul200df112005-06-01 11:17:05 +00001233 /* Buffers. */
paul718e3742002-12-13 20:15:29 +00001234 if (peer->ibuf)
1235 stream_free (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00001236 if (peer->obuf)
1237 stream_fifo_free (peer->obuf);
paul718e3742002-12-13 20:15:29 +00001238 if (peer->work)
1239 stream_free (peer->work);
Paul Jakma18937402006-07-27 19:05:12 +00001240 peer->obuf = NULL;
1241 peer->work = peer->ibuf = NULL;
1242
paul718e3742002-12-13 20:15:29 +00001243 /* Local and remote addresses. */
1244 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001245 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001246 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001247 sockunion_free (peer->su_remote);
Paul Jakma18937402006-07-27 19:05:12 +00001248 peer->su_local = peer->su_remote = NULL;
paul200df112005-06-01 11:17:05 +00001249
paul718e3742002-12-13 20:15:29 +00001250 /* Free filter related memory. */
1251 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1252 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1253 {
1254 filter = &peer->filter[afi][safi];
1255
1256 for (i = FILTER_IN; i < FILTER_MAX; i++)
1257 {
1258 if (filter->dlist[i].name)
1259 free (filter->dlist[i].name);
1260 if (filter->plist[i].name)
1261 free (filter->plist[i].name);
1262 if (filter->aslist[i].name)
1263 free (filter->aslist[i].name);
paul200df112005-06-01 11:17:05 +00001264
1265 filter->dlist[i].name = NULL;
1266 filter->plist[i].name = NULL;
1267 filter->aslist[i].name = NULL;
1268 }
1269 for (i = RMAP_IN; i < RMAP_MAX; i++)
1270 {
paul718e3742002-12-13 20:15:29 +00001271 if (filter->map[i].name)
1272 free (filter->map[i].name);
paul200df112005-06-01 11:17:05 +00001273 filter->map[i].name = NULL;
paul718e3742002-12-13 20:15:29 +00001274 }
1275
1276 if (filter->usmap.name)
1277 free (filter->usmap.name);
1278
1279 if (peer->default_rmap[afi][safi].name)
1280 free (peer->default_rmap[afi][safi].name);
paul200df112005-06-01 11:17:05 +00001281
1282 filter->usmap.name = NULL;
1283 peer->default_rmap[afi][safi].name = NULL;
paul718e3742002-12-13 20:15:29 +00001284 }
paul200df112005-06-01 11:17:05 +00001285
1286 peer_unlock (peer); /* initial reference */
paul718e3742002-12-13 20:15:29 +00001287
1288 return 0;
1289}
1290
paul94f2b392005-06-28 12:44:16 +00001291static int
paul718e3742002-12-13 20:15:29 +00001292peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1293{
1294 return strcmp (g1->name, g2->name);
1295}
1296
1297/* If peer is configured at least one address family return 1. */
paul94f2b392005-06-28 12:44:16 +00001298static int
paul718e3742002-12-13 20:15:29 +00001299peer_group_active (struct peer *peer)
1300{
1301 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1302 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1303 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1304 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1305 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1306 return 1;
1307 return 0;
1308}
1309
1310/* Peer group cofiguration. */
1311static struct peer_group *
1312peer_group_new ()
1313{
1314 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1315 sizeof (struct peer_group));
1316}
1317
paul94f2b392005-06-28 12:44:16 +00001318static void
paul718e3742002-12-13 20:15:29 +00001319peer_group_free (struct peer_group *group)
1320{
1321 XFREE (MTYPE_PEER_GROUP, group);
1322}
1323
1324struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001325peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001326{
1327 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001328 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001329
paul1eb8ef22005-04-07 07:30:20 +00001330 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001331 {
1332 if (strcmp (group->name, name) == 0)
1333 return group;
1334 }
1335 return NULL;
1336}
1337
1338struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001339peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001340{
1341 struct peer_group *group;
1342
1343 group = peer_group_lookup (bgp, name);
1344 if (group)
1345 return group;
1346
1347 group = peer_group_new ();
1348 group->bgp = bgp;
1349 group->name = strdup (name);
1350 group->peer = list_new ();
Paul Jakma6f585442006-10-22 19:13:07 +00001351 group->conf = peer_new (bgp);
paul718e3742002-12-13 20:15:29 +00001352 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1353 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
1354 group->conf->host = strdup (name);
paul718e3742002-12-13 20:15:29 +00001355 group->conf->group = group;
1356 group->conf->as = 0;
1357 group->conf->ttl = 1;
1358 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1359 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1360 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1361 group->conf->keepalive = 0;
1362 group->conf->holdtime = 0;
1363 group->conf->connect = 0;
1364 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1365 listnode_add_sort (bgp->group, group);
1366
1367 return 0;
1368}
1369
paul94f2b392005-06-28 12:44:16 +00001370static void
paul718e3742002-12-13 20:15:29 +00001371peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1372 afi_t afi, safi_t safi)
1373{
1374 int in = FILTER_IN;
1375 int out = FILTER_OUT;
1376 struct peer *conf;
1377 struct bgp_filter *pfilter;
1378 struct bgp_filter *gfilter;
1379
1380 conf = group->conf;
1381 pfilter = &peer->filter[afi][safi];
1382 gfilter = &conf->filter[afi][safi];
1383
1384 /* remote-as */
1385 if (conf->as)
1386 peer->as = conf->as;
1387
1388 /* remote-as */
1389 if (conf->change_local_as)
1390 peer->change_local_as = conf->change_local_as;
1391
1392 /* TTL */
1393 peer->ttl = conf->ttl;
1394
1395 /* Weight */
1396 peer->weight = conf->weight;
1397
1398 /* peer flags apply */
1399 peer->flags = conf->flags;
1400 /* peer af_flags apply */
1401 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1402 /* peer config apply */
1403 peer->config = conf->config;
1404
1405 /* peer timers apply */
1406 peer->holdtime = conf->holdtime;
1407 peer->keepalive = conf->keepalive;
1408 peer->connect = conf->connect;
1409 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1410 peer->v_connect = conf->connect;
1411 else
1412 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1413
1414 /* advertisement-interval reset */
1415 if (peer_sort (peer) == BGP_PEER_IBGP)
1416 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1417 else
1418 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1419
1420 /* maximum-prefix */
1421 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001422 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001423 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001424
1425 /* allowas-in */
1426 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1427
paulfee0f4c2004-09-13 05:12:46 +00001428 /* route-server-client */
1429 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1430 {
1431 /* Make peer's RIB point to group's RIB. */
1432 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1433
1434 /* Import policy. */
1435 if (pfilter->map[RMAP_IMPORT].name)
1436 free (pfilter->map[RMAP_IMPORT].name);
1437 if (gfilter->map[RMAP_IMPORT].name)
1438 {
1439 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1440 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1441 }
1442 else
1443 {
1444 pfilter->map[RMAP_IMPORT].name = NULL;
1445 pfilter->map[RMAP_IMPORT].map = NULL;
1446 }
1447
1448 /* Export policy. */
1449 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1450 {
1451 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1452 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1453 }
1454 }
1455
paul718e3742002-12-13 20:15:29 +00001456 /* default-originate route-map */
1457 if (conf->default_rmap[afi][safi].name)
1458 {
1459 if (peer->default_rmap[afi][safi].name)
1460 free (peer->default_rmap[afi][safi].name);
1461 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1462 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1463 }
1464
1465 /* update-source apply */
1466 if (conf->update_source)
1467 {
1468 if (peer->update_source)
1469 sockunion_free (peer->update_source);
1470 if (peer->update_if)
1471 {
1472 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1473 peer->update_if = NULL;
1474 }
1475 peer->update_source = sockunion_dup (conf->update_source);
1476 }
1477 else if (conf->update_if)
1478 {
1479 if (peer->update_if)
1480 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1481 if (peer->update_source)
1482 {
1483 sockunion_free (peer->update_source);
1484 peer->update_source = NULL;
1485 }
1486 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1487 }
1488
1489 /* inbound filter apply */
1490 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1491 {
1492 if (pfilter->dlist[in].name)
1493 free (pfilter->dlist[in].name);
1494 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1495 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1496 }
1497 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1498 {
1499 if (pfilter->plist[in].name)
1500 free (pfilter->plist[in].name);
1501 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1502 pfilter->plist[in].plist = gfilter->plist[in].plist;
1503 }
1504 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1505 {
1506 if (pfilter->aslist[in].name)
1507 free (pfilter->aslist[in].name);
1508 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1509 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1510 }
paulfee0f4c2004-09-13 05:12:46 +00001511 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001512 {
paulfee0f4c2004-09-13 05:12:46 +00001513 if (pfilter->map[RMAP_IN].name)
1514 free (pfilter->map[RMAP_IN].name);
1515 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1516 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001517 }
1518
1519 /* outbound filter apply */
1520 if (gfilter->dlist[out].name)
1521 {
1522 if (pfilter->dlist[out].name)
1523 free (pfilter->dlist[out].name);
1524 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1525 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1526 }
1527 else
1528 {
1529 if (pfilter->dlist[out].name)
1530 free (pfilter->dlist[out].name);
1531 pfilter->dlist[out].name = NULL;
1532 pfilter->dlist[out].alist = NULL;
1533 }
1534 if (gfilter->plist[out].name)
1535 {
1536 if (pfilter->plist[out].name)
1537 free (pfilter->plist[out].name);
1538 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1539 pfilter->plist[out].plist = gfilter->plist[out].plist;
1540 }
1541 else
1542 {
1543 if (pfilter->plist[out].name)
1544 free (pfilter->plist[out].name);
1545 pfilter->plist[out].name = NULL;
1546 pfilter->plist[out].plist = NULL;
1547 }
1548 if (gfilter->aslist[out].name)
1549 {
1550 if (pfilter->aslist[out].name)
1551 free (pfilter->aslist[out].name);
1552 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1553 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1554 }
1555 else
1556 {
1557 if (pfilter->aslist[out].name)
1558 free (pfilter->aslist[out].name);
1559 pfilter->aslist[out].name = NULL;
1560 pfilter->aslist[out].aslist = NULL;
1561 }
paulfee0f4c2004-09-13 05:12:46 +00001562 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001563 {
paulfee0f4c2004-09-13 05:12:46 +00001564 if (pfilter->map[RMAP_OUT].name)
1565 free (pfilter->map[RMAP_OUT].name);
1566 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1567 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001568 }
1569 else
1570 {
paulfee0f4c2004-09-13 05:12:46 +00001571 if (pfilter->map[RMAP_OUT].name)
1572 free (pfilter->map[RMAP_OUT].name);
1573 pfilter->map[RMAP_OUT].name = NULL;
1574 pfilter->map[RMAP_OUT].map = NULL;
1575 }
1576
1577 /* RS-client's import/export route-maps. */
1578 if (gfilter->map[RMAP_IMPORT].name)
1579 {
1580 if (pfilter->map[RMAP_IMPORT].name)
1581 free (pfilter->map[RMAP_IMPORT].name);
1582 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1583 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1584 }
1585 else
1586 {
1587 if (pfilter->map[RMAP_IMPORT].name)
1588 free (pfilter->map[RMAP_IMPORT].name);
1589 pfilter->map[RMAP_IMPORT].name = NULL;
1590 pfilter->map[RMAP_IMPORT].map = NULL;
1591 }
1592 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1593 {
1594 if (pfilter->map[RMAP_EXPORT].name)
1595 free (pfilter->map[RMAP_EXPORT].name);
1596 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1597 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001598 }
1599
1600 if (gfilter->usmap.name)
1601 {
1602 if (pfilter->usmap.name)
1603 free (pfilter->usmap.name);
1604 pfilter->usmap.name = strdup (gfilter->usmap.name);
1605 pfilter->usmap.map = gfilter->usmap.map;
1606 }
1607 else
1608 {
1609 if (pfilter->usmap.name)
1610 free (pfilter->usmap.name);
1611 pfilter->usmap.name = NULL;
1612 pfilter->usmap.map = NULL;
1613 }
1614}
1615
1616/* Peer group's remote AS configuration. */
1617int
paulfd79ac92004-10-13 05:06:08 +00001618peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001619{
1620 struct peer_group *group;
1621 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001622 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001623
1624 group = peer_group_lookup (bgp, group_name);
1625 if (! group)
1626 return -1;
1627
1628 if (group->conf->as == *as)
1629 return 0;
1630
1631 /* When we setup peer-group AS number all peer group member's AS
1632 number must be updated to same number. */
1633 peer_as_change (group->conf, *as);
1634
paul1eb8ef22005-04-07 07:30:20 +00001635 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001636 {
1637 if (peer->as != *as)
1638 peer_as_change (peer, *as);
1639 }
1640
1641 return 0;
1642}
1643
1644int
1645peer_group_delete (struct peer_group *group)
1646{
1647 struct bgp *bgp;
1648 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001649 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001650
1651 bgp = group->bgp;
1652
paul1eb8ef22005-04-07 07:30:20 +00001653 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001654 {
1655 peer->group = NULL;
1656 peer_delete (peer);
1657 }
1658 list_delete (group->peer);
1659
1660 free (group->name);
1661 group->name = NULL;
1662
1663 group->conf->group = NULL;
1664 peer_delete (group->conf);
1665
1666 /* Delete from all peer_group list. */
1667 listnode_delete (bgp->group, group);
1668
1669 peer_group_free (group);
1670
1671 return 0;
1672}
1673
1674int
1675peer_group_remote_as_delete (struct peer_group *group)
1676{
1677 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001678 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001679
1680 if (! group->conf->as)
1681 return 0;
1682
paul1eb8ef22005-04-07 07:30:20 +00001683 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001684 {
1685 peer->group = NULL;
1686 peer_delete (peer);
1687 }
1688 list_delete_all_node (group->peer);
1689
1690 group->conf->as = 0;
1691
1692 return 0;
1693}
1694
1695/* Bind specified peer to peer group. */
1696int
1697peer_group_bind (struct bgp *bgp, union sockunion *su,
1698 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1699{
1700 struct peer *peer;
1701 int first_member = 0;
1702
1703 /* Check peer group's address family. */
1704 if (! group->conf->afc[afi][safi])
1705 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1706
1707 /* Lookup the peer. */
1708 peer = peer_lookup (bgp, su);
1709
1710 /* Create a new peer. */
1711 if (! peer)
1712 {
1713 if (! group->conf->as)
1714 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1715
1716 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1717 peer->group = group;
1718 peer->af_group[afi][safi] = 1;
paul200df112005-06-01 11:17:05 +00001719
Paul Jakmaca058a32006-09-14 02:58:49 +00001720 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001721 listnode_add (group->peer, peer);
1722 peer_group2peer_config_copy (group, peer, afi, safi);
1723
1724 return 0;
1725 }
1726
1727 /* When the peer already belongs to peer group, check the consistency. */
1728 if (peer->af_group[afi][safi])
1729 {
1730 if (strcmp (peer->group->name, group->name) != 0)
1731 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1732
1733 return 0;
1734 }
1735
1736 /* Check current peer group configuration. */
1737 if (peer_group_active (peer)
1738 && strcmp (peer->group->name, group->name) != 0)
1739 return BGP_ERR_PEER_GROUP_MISMATCH;
1740
1741 if (! group->conf->as)
1742 {
1743 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1744 && peer_sort (group->conf) != peer_sort (peer))
1745 {
1746 if (as)
1747 *as = peer->as;
1748 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1749 }
1750
1751 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1752 first_member = 1;
1753 }
1754
1755 peer->af_group[afi][safi] = 1;
1756 peer->afc[afi][safi] = 1;
1757 if (! peer->group)
1758 {
1759 peer->group = group;
paul200df112005-06-01 11:17:05 +00001760
Paul Jakmaca058a32006-09-14 02:58:49 +00001761 peer = peer_lock (peer); /* group->peer list reference */
paul718e3742002-12-13 20:15:29 +00001762 listnode_add (group->peer, peer);
1763 }
Paul Jakmaca058a32006-09-14 02:58:49 +00001764 else
1765 assert (group && peer->group == group);
paul718e3742002-12-13 20:15:29 +00001766
1767 if (first_member)
1768 {
1769 /* Advertisement-interval reset */
1770 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1771 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1772 else
1773 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1774
1775 /* ebgp-multihop reset */
1776 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1777 group->conf->ttl = 255;
1778
1779 /* local-as reset */
1780 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1781 {
1782 group->conf->change_local_as = 0;
1783 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1784 }
1785 }
paulfee0f4c2004-09-13 05:12:46 +00001786
1787 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1788 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001789 struct listnode *pn;
1790
paulfee0f4c2004-09-13 05:12:46 +00001791 /* If it's not configured as RSERVER_CLIENT in any other address
1792 family, without being member of a peer_group, remove it from
1793 list bgp->rsclient.*/
Paul Jakmaca058a32006-09-14 02:58:49 +00001794 if (! peer_rsclient_active (peer)
1795 && (pn = listnode_lookup (bgp->rsclient, peer)))
paul200df112005-06-01 11:17:05 +00001796 {
1797 peer_unlock (peer); /* peer rsclient reference */
Paul Jakmaca058a32006-09-14 02:58:49 +00001798 list_delete_node (bgp->rsclient, pn);
paul200df112005-06-01 11:17:05 +00001799 }
paulfee0f4c2004-09-13 05:12:46 +00001800
1801 bgp_table_finish (peer->rib[afi][safi]);
1802
1803 /* Import policy. */
1804 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1805 {
1806 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1807 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1808 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1809 }
1810
1811 /* Export policy. */
1812 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1813 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1814 {
1815 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1816 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1817 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1818 }
1819 }
1820
paul718e3742002-12-13 20:15:29 +00001821 peer_group2peer_config_copy (group, peer, afi, safi);
1822
1823 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001824 {
1825 peer->last_reset = PEER_DOWN_RMAP_BIND;
1826 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1827 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1828 }
paul718e3742002-12-13 20:15:29 +00001829 else
1830 BGP_EVENT_ADD (peer, BGP_Stop);
1831
1832 return 0;
1833}
1834
1835int
1836peer_group_unbind (struct bgp *bgp, struct peer *peer,
1837 struct peer_group *group, afi_t afi, safi_t safi)
1838{
1839 if (! peer->af_group[afi][safi])
1840 return 0;
1841
1842 if (group != peer->group)
1843 return BGP_ERR_PEER_GROUP_MISMATCH;
1844
1845 peer->af_group[afi][safi] = 0;
1846 peer->afc[afi][safi] = 0;
1847 peer_af_flag_reset (peer, afi, safi);
1848
paulfee0f4c2004-09-13 05:12:46 +00001849 if (peer->rib[afi][safi])
1850 peer->rib[afi][safi] = NULL;
1851
paul718e3742002-12-13 20:15:29 +00001852 if (! peer_group_active (peer))
1853 {
Paul Jakmaca058a32006-09-14 02:58:49 +00001854 assert (listnode_lookup (group->peer, peer));
paul200df112005-06-01 11:17:05 +00001855 peer_unlock (peer); /* peer group list reference */
paul718e3742002-12-13 20:15:29 +00001856 listnode_delete (group->peer, peer);
1857 peer->group = NULL;
1858 if (group->conf->as)
1859 {
1860 peer_delete (peer);
1861 return 0;
1862 }
1863 peer_global_config_reset (peer);
1864 }
1865
1866 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001867 {
1868 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1869 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1870 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1871 }
paul718e3742002-12-13 20:15:29 +00001872 else
1873 BGP_EVENT_ADD (peer, BGP_Stop);
1874
1875 return 0;
1876}
1877
1878/* BGP instance creation by `router bgp' commands. */
paul94f2b392005-06-28 12:44:16 +00001879static struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001880bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001881{
1882 struct bgp *bgp;
1883 afi_t afi;
1884 safi_t safi;
1885
paul200df112005-06-01 11:17:05 +00001886 if ( (bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp))) == NULL)
1887 return NULL;
1888
Paul Jakma6f585442006-10-22 19:13:07 +00001889 bgp->peer_self = peer_new (bgp);
paulfd79ac92004-10-13 05:06:08 +00001890 bgp->peer_self->host = strdup ("Static announcement");
paul718e3742002-12-13 20:15:29 +00001891
1892 bgp->peer = list_new ();
1893 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1894
1895 bgp->group = list_new ();
1896 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1897
paulfee0f4c2004-09-13 05:12:46 +00001898 bgp->rsclient = list_new ();
1899 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1900
paul718e3742002-12-13 20:15:29 +00001901 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1902 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1903 {
Paul Jakma64e580a2006-02-21 01:09:01 +00001904 bgp->route[afi][safi] = bgp_table_init (afi, safi);
1905 bgp->aggregate[afi][safi] = bgp_table_init (afi, safi);
1906 bgp->rib[afi][safi] = bgp_table_init (afi, safi);
paul718e3742002-12-13 20:15:29 +00001907 }
1908
1909 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1910 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1911 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001912 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1913 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001914
1915 bgp->as = *as;
1916
1917 if (name)
1918 bgp->name = strdup (name);
1919
1920 return bgp;
1921}
1922
1923/* Return first entry of BGP. */
1924struct bgp *
paul94f2b392005-06-28 12:44:16 +00001925bgp_get_default (void)
paul718e3742002-12-13 20:15:29 +00001926{
1927 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001928 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001929 return NULL;
1930}
1931
1932/* Lookup BGP entry. */
1933struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001934bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001935{
1936 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001937 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001938
paul1eb8ef22005-04-07 07:30:20 +00001939 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001940 if (bgp->as == as
1941 && ((bgp->name == NULL && name == NULL)
1942 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1943 return bgp;
1944 return NULL;
1945}
1946
1947/* Lookup BGP structure by view name. */
1948struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001949bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00001950{
1951 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001952 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001953
paul1eb8ef22005-04-07 07:30:20 +00001954 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001955 if ((bgp->name == NULL && name == NULL)
1956 || (bgp->name && name && strcmp (bgp->name, name) == 0))
1957 return bgp;
1958 return NULL;
1959}
1960
1961/* Called from VTY commands. */
1962int
paulfd79ac92004-10-13 05:06:08 +00001963bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001964{
1965 struct bgp *bgp;
1966
1967 /* Multiple instance check. */
1968 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
1969 {
1970 if (name)
1971 bgp = bgp_lookup_by_name (name);
1972 else
1973 bgp = bgp_get_default ();
1974
1975 /* Already exists. */
1976 if (bgp)
1977 {
1978 if (bgp->as != *as)
1979 {
1980 *as = bgp->as;
1981 return BGP_ERR_INSTANCE_MISMATCH;
1982 }
1983 *bgp_val = bgp;
1984 return 0;
1985 }
1986 }
1987 else
1988 {
1989 /* BGP instance name can not be specified for single instance. */
1990 if (name)
1991 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
1992
1993 /* Get default BGP structure if exists. */
1994 bgp = bgp_get_default ();
1995
1996 if (bgp)
1997 {
1998 if (bgp->as != *as)
1999 {
2000 *as = bgp->as;
2001 return BGP_ERR_AS_MISMATCH;
2002 }
2003 *bgp_val = bgp;
2004 return 0;
2005 }
2006 }
2007
2008 bgp = bgp_create (as, name);
2009 listnode_add (bm->bgp, bgp);
hasso18a6dce2004-10-03 18:18:34 +00002010 bgp_router_id_set(bgp, &router_id_zebra);
paul718e3742002-12-13 20:15:29 +00002011 *bgp_val = bgp;
2012
2013 return 0;
2014}
2015
2016/* Delete BGP instance. */
2017int
2018bgp_delete (struct bgp *bgp)
2019{
2020 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00002021 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002022 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00002023 struct listnode *next;
2024 afi_t afi;
2025 safi_t safi;
2026 int i;
2027
2028 /* Delete static route. */
2029 bgp_static_delete (bgp);
2030
2031 /* Unset redistribution. */
2032 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2033 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
2034 if (i != ZEBRA_ROUTE_BGP)
2035 bgp_redistribute_unset (bgp, afi, i);
2036
hassob6b7cff2005-05-26 08:29:07 +00002037 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
2038 peer_group_delete (group);
hasso54a6ed32005-05-26 22:12:33 +00002039 list_delete (bgp->group);
paul718e3742002-12-13 20:15:29 +00002040
paul1eb8ef22005-04-07 07:30:20 +00002041 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
2042 peer_delete (peer);
hasso54a6ed32005-05-26 22:12:33 +00002043 list_delete (bgp->peer);
paul718e3742002-12-13 20:15:29 +00002044
hasso54a6ed32005-05-26 22:12:33 +00002045 for (ALL_LIST_ELEMENTS (bgp->rsclient, node, next, peer))
2046 peer_delete (peer);
paulfee0f4c2004-09-13 05:12:46 +00002047 list_delete (bgp->rsclient);
2048
paul718e3742002-12-13 20:15:29 +00002049 listnode_delete (bm->bgp, bgp);
paul200df112005-06-01 11:17:05 +00002050
paul718e3742002-12-13 20:15:29 +00002051 if (bgp->name)
2052 free (bgp->name);
2053
2054 for (afi = AFI_IP; afi < AFI_MAX; afi++)
2055 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
2056 {
2057 if (bgp->route[afi][safi])
2058 XFREE (MTYPE_ROUTE_TABLE, bgp->route[afi][safi]);
2059 if (bgp->aggregate[afi][safi])
2060 XFREE (MTYPE_ROUTE_TABLE,bgp->aggregate[afi][safi]) ;
2061 if (bgp->rib[afi][safi])
2062 XFREE (MTYPE_ROUTE_TABLE,bgp->rib[afi][safi]);
2063 }
2064 XFREE (MTYPE_BGP, bgp);
2065
2066 return 0;
2067}
2068
2069struct peer *
2070peer_lookup (struct bgp *bgp, union sockunion *su)
2071{
2072 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002073 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002074
2075 if (! bgp)
2076 bgp = bgp_get_default ();
2077
2078 if (! bgp)
2079 return NULL;
2080
paul1eb8ef22005-04-07 07:30:20 +00002081 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002082 {
pauleb821182004-05-01 08:44:08 +00002083 if (sockunion_same (&peer->su, su)
2084 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2085 return peer;
paul718e3742002-12-13 20:15:29 +00002086 }
2087 return NULL;
2088}
2089
2090struct peer *
2091peer_lookup_with_open (union sockunion *su, as_t remote_as,
2092 struct in_addr *remote_id, int *as)
2093{
2094 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00002095 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002096 struct bgp *bgp;
2097
2098 bgp = bgp_get_default ();
2099 if (! bgp)
2100 return NULL;
2101
paul1eb8ef22005-04-07 07:30:20 +00002102 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002103 {
pauleb821182004-05-01 08:44:08 +00002104 if (sockunion_same (&peer->su, su)
2105 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2106 {
2107 if (peer->as == remote_as
2108 && peer->remote_id.s_addr == remote_id->s_addr)
2109 return peer;
2110 if (peer->as == remote_as)
2111 *as = 1;
2112 }
paul718e3742002-12-13 20:15:29 +00002113 }
paul1eb8ef22005-04-07 07:30:20 +00002114 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002115 {
pauleb821182004-05-01 08:44:08 +00002116 if (sockunion_same (&peer->su, su)
2117 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2118 {
2119 if (peer->as == remote_as
2120 && peer->remote_id.s_addr == 0)
2121 return peer;
2122 if (peer->as == remote_as)
2123 *as = 1;
2124 }
paul718e3742002-12-13 20:15:29 +00002125 }
2126 return NULL;
2127}
2128
2129/* If peer is configured at least one address family return 1. */
2130int
2131peer_active (struct peer *peer)
2132{
2133 if (peer->afc[AFI_IP][SAFI_UNICAST]
2134 || peer->afc[AFI_IP][SAFI_MULTICAST]
2135 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2136 || peer->afc[AFI_IP6][SAFI_UNICAST]
2137 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2138 return 1;
2139 return 0;
2140}
2141
2142/* If peer is negotiated at least one address family return 1. */
2143int
2144peer_active_nego (struct peer *peer)
2145{
2146 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2147 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2148 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2149 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2150 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2151 return 1;
2152 return 0;
2153}
2154
2155/* peer_flag_change_type. */
2156enum peer_change_type
2157{
2158 peer_change_none,
2159 peer_change_reset,
2160 peer_change_reset_in,
2161 peer_change_reset_out,
2162};
2163
paul94f2b392005-06-28 12:44:16 +00002164static void
paul718e3742002-12-13 20:15:29 +00002165peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2166 enum peer_change_type type)
2167{
2168 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2169 return;
2170
2171 if (type == peer_change_reset)
2172 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2173 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2174 else if (type == peer_change_reset_in)
2175 {
2176 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2177 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2178 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2179 else
2180 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2181 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2182 }
2183 else if (type == peer_change_reset_out)
2184 bgp_announce_route (peer, afi, safi);
2185}
2186
2187struct peer_flag_action
2188{
2189 /* Peer's flag. */
2190 u_int32_t flag;
2191
2192 /* This flag can be set for peer-group member. */
2193 u_char not_for_member;
2194
2195 /* Action when the flag is changed. */
2196 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002197
2198 /* Peer down cause */
2199 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002200};
2201
2202struct peer_flag_action peer_flag_action_list[] =
2203 {
2204 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2205 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2206 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2207 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2208 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002209 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002210 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002211 { 0, 0, 0 }
2212 };
2213
2214struct peer_flag_action peer_af_flag_action_list[] =
2215 {
2216 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2217 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2218 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2219 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2220 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2221 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2222 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2223 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2224 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2225 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2226 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2227 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2228 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002229 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002230 { 0, 0, 0 }
2231 };
2232
2233/* Proper action set. */
paul94f2b392005-06-28 12:44:16 +00002234static int
paul718e3742002-12-13 20:15:29 +00002235peer_flag_action_set (struct peer_flag_action *action_list, int size,
2236 struct peer_flag_action *action, u_int32_t flag)
2237{
2238 int i;
2239 int found = 0;
2240 int reset_in = 0;
2241 int reset_out = 0;
2242 struct peer_flag_action *match = NULL;
2243
2244 /* Check peer's frag action. */
2245 for (i = 0; i < size; i++)
2246 {
2247 match = &action_list[i];
2248
2249 if (match->flag == 0)
2250 break;
2251
2252 if (match->flag & flag)
2253 {
2254 found = 1;
2255
2256 if (match->type == peer_change_reset_in)
2257 reset_in = 1;
2258 if (match->type == peer_change_reset_out)
2259 reset_out = 1;
2260 if (match->type == peer_change_reset)
2261 {
2262 reset_in = 1;
2263 reset_out = 1;
2264 }
2265 if (match->not_for_member)
2266 action->not_for_member = 1;
2267 }
2268 }
2269
2270 /* Set peer clear type. */
2271 if (reset_in && reset_out)
2272 action->type = peer_change_reset;
2273 else if (reset_in)
2274 action->type = peer_change_reset_in;
2275 else if (reset_out)
2276 action->type = peer_change_reset_out;
2277 else
2278 action->type = peer_change_none;
2279
2280 return found;
2281}
2282
paul94f2b392005-06-28 12:44:16 +00002283static void
paul718e3742002-12-13 20:15:29 +00002284peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2285{
2286 if (flag == PEER_FLAG_SHUTDOWN)
2287 {
2288 if (CHECK_FLAG (peer->flags, flag))
2289 {
hasso93406d82005-02-02 14:40:33 +00002290 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2291 peer_nsf_stop (peer);
2292
hasso0a486e52005-02-01 20:57:17 +00002293 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2294 if (peer->t_pmax_restart)
2295 {
2296 BGP_TIMER_OFF (peer->t_pmax_restart);
2297 if (BGP_DEBUG (events, EVENTS))
2298 zlog_debug ("%s Maximum-prefix restart timer canceled",
2299 peer->host);
2300 }
2301
hasso93406d82005-02-02 14:40:33 +00002302 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2303 peer_nsf_stop (peer);
2304
paul718e3742002-12-13 20:15:29 +00002305 if (peer->status == Established)
2306 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2307 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2308 else
2309 BGP_EVENT_ADD (peer, BGP_Stop);
2310 }
2311 else
2312 {
2313 peer->v_start = BGP_INIT_START_TIMER;
2314 BGP_EVENT_ADD (peer, BGP_Stop);
2315 }
2316 }
2317 else if (peer->status == Established)
2318 {
hassoc9502432005-02-01 22:01:48 +00002319 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2320 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2321 else if (flag == PEER_FLAG_PASSIVE)
2322 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002323 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002324 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002325
hassoc9502432005-02-01 22:01:48 +00002326 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2327 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002328 }
2329 else
2330 BGP_EVENT_ADD (peer, BGP_Stop);
2331}
2332
2333/* Change specified peer flag. */
paul94f2b392005-06-28 12:44:16 +00002334static int
paul718e3742002-12-13 20:15:29 +00002335peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2336{
2337 int found;
2338 int size;
2339 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002340 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002341 struct peer_flag_action action;
2342
2343 memset (&action, 0, sizeof (struct peer_flag_action));
2344 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2345
2346 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2347
2348 /* No flag action is found. */
2349 if (! found)
2350 return BGP_ERR_INVALID_FLAG;
2351
2352 /* Not for peer-group member. */
2353 if (action.not_for_member && peer_group_active (peer))
2354 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2355
2356 /* When unset the peer-group member's flag we have to check
2357 peer-group configuration. */
2358 if (! set && peer_group_active (peer))
2359 if (CHECK_FLAG (peer->group->conf->flags, flag))
2360 {
2361 if (flag == PEER_FLAG_SHUTDOWN)
2362 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2363 else
2364 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2365 }
2366
2367 /* Flag conflict check. */
2368 if (set
2369 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2370 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2371 return BGP_ERR_PEER_FLAG_CONFLICT;
2372
2373 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2374 {
2375 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2376 return 0;
2377 if (! set && ! CHECK_FLAG (peer->flags, flag))
2378 return 0;
2379 }
2380
2381 if (set)
2382 SET_FLAG (peer->flags, flag);
2383 else
2384 UNSET_FLAG (peer->flags, flag);
2385
2386 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2387 {
2388 if (action.type == peer_change_reset)
2389 peer_flag_modify_action (peer, flag);
2390
2391 return 0;
2392 }
2393
2394 /* peer-group member updates. */
2395 group = peer->group;
2396
paul1eb8ef22005-04-07 07:30:20 +00002397 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002398 {
2399 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2400 continue;
2401
2402 if (! set && ! CHECK_FLAG (peer->flags, flag))
2403 continue;
2404
2405 if (set)
2406 SET_FLAG (peer->flags, flag);
2407 else
2408 UNSET_FLAG (peer->flags, flag);
2409
2410 if (action.type == peer_change_reset)
2411 peer_flag_modify_action (peer, flag);
2412 }
2413 return 0;
2414}
2415
2416int
2417peer_flag_set (struct peer *peer, u_int32_t flag)
2418{
2419 return peer_flag_modify (peer, flag, 1);
2420}
2421
2422int
2423peer_flag_unset (struct peer *peer, u_int32_t flag)
2424{
2425 return peer_flag_modify (peer, flag, 0);
2426}
2427
paul94f2b392005-06-28 12:44:16 +00002428static int
paul718e3742002-12-13 20:15:29 +00002429peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2430{
2431 if (peer->af_group[afi][safi])
2432 return 1;
2433 return 0;
2434}
2435
paul94f2b392005-06-28 12:44:16 +00002436static int
paul718e3742002-12-13 20:15:29 +00002437peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2438 int set)
2439{
2440 int found;
2441 int size;
paul1eb8ef22005-04-07 07:30:20 +00002442 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002443 struct peer_group *group;
2444 struct peer_flag_action action;
2445
2446 memset (&action, 0, sizeof (struct peer_flag_action));
2447 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2448
2449 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2450
2451 /* No flag action is found. */
2452 if (! found)
2453 return BGP_ERR_INVALID_FLAG;
2454
2455 /* Adress family must be activated. */
2456 if (! peer->afc[afi][safi])
2457 return BGP_ERR_PEER_INACTIVE;
2458
2459 /* Not for peer-group member. */
2460 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2461 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2462
2463 /* Spcecial check for reflector client. */
2464 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2465 && peer_sort (peer) != BGP_PEER_IBGP)
2466 return BGP_ERR_NOT_INTERNAL_PEER;
2467
2468 /* Spcecial check for remove-private-AS. */
2469 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2470 && peer_sort (peer) == BGP_PEER_IBGP)
2471 return BGP_ERR_REMOVE_PRIVATE_AS;
2472
2473 /* When unset the peer-group member's flag we have to check
2474 peer-group configuration. */
2475 if (! set && peer->af_group[afi][safi])
2476 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2477 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2478
2479 /* When current flag configuration is same as requested one. */
2480 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2481 {
2482 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2483 return 0;
2484 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2485 return 0;
2486 }
2487
2488 if (set)
2489 SET_FLAG (peer->af_flags[afi][safi], flag);
2490 else
2491 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2492
2493 /* Execute action when peer is established. */
2494 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2495 && peer->status == Established)
2496 {
2497 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2498 bgp_clear_adj_in (peer, afi, safi);
2499 else
hassoe0701b72004-05-20 09:19:34 +00002500 {
2501 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2502 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2503 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2504 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2505 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2506 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2507 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2508 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2509
2510 peer_change_action (peer, afi, safi, action.type);
2511 }
2512
paul718e3742002-12-13 20:15:29 +00002513 }
2514
2515 /* Peer group member updates. */
2516 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2517 {
2518 group = peer->group;
2519
paul1eb8ef22005-04-07 07:30:20 +00002520 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002521 {
2522 if (! peer->af_group[afi][safi])
2523 continue;
2524
2525 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2526 continue;
2527
2528 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2529 continue;
2530
2531 if (set)
2532 SET_FLAG (peer->af_flags[afi][safi], flag);
2533 else
2534 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2535
2536 if (peer->status == Established)
2537 {
2538 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2539 bgp_clear_adj_in (peer, afi, safi);
2540 else
hassoe0701b72004-05-20 09:19:34 +00002541 {
2542 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2543 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2544 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2545 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2546 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2547 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2548 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2549 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2550
2551 peer_change_action (peer, afi, safi, action.type);
2552 }
paul718e3742002-12-13 20:15:29 +00002553 }
2554 }
2555 }
2556 return 0;
2557}
2558
2559int
2560peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2561{
2562 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2563}
2564
2565int
2566peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2567{
2568 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2569}
2570
2571/* EBGP multihop configuration. */
2572int
2573peer_ebgp_multihop_set (struct peer *peer, int ttl)
2574{
2575 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002576 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002577
2578 if (peer_sort (peer) == BGP_PEER_IBGP)
2579 return 0;
2580
2581 peer->ttl = ttl;
2582
2583 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2584 {
pauleb821182004-05-01 08:44:08 +00002585 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2586 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002587 }
2588 else
2589 {
2590 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002591 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002592 {
2593 if (peer_sort (peer) == BGP_PEER_IBGP)
2594 continue;
paul718e3742002-12-13 20:15:29 +00002595
pauleb821182004-05-01 08:44:08 +00002596 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002597
pauleb821182004-05-01 08:44:08 +00002598 if (peer->fd >= 0)
2599 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2600 }
paul718e3742002-12-13 20:15:29 +00002601 }
2602 return 0;
2603}
2604
2605int
2606peer_ebgp_multihop_unset (struct peer *peer)
2607{
2608 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002609 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002610
2611 if (peer_sort (peer) == BGP_PEER_IBGP)
2612 return 0;
2613
2614 if (peer_group_active (peer))
2615 peer->ttl = peer->group->conf->ttl;
2616 else
2617 peer->ttl = 1;
2618
2619 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2620 {
pauleb821182004-05-01 08:44:08 +00002621 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2622 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002623 }
2624 else
2625 {
2626 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002627 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002628 {
2629 if (peer_sort (peer) == BGP_PEER_IBGP)
2630 continue;
paul718e3742002-12-13 20:15:29 +00002631
pauleb821182004-05-01 08:44:08 +00002632 peer->ttl = 1;
2633
2634 if (peer->fd >= 0)
2635 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2636 }
paul718e3742002-12-13 20:15:29 +00002637 }
2638 return 0;
2639}
2640
2641/* Neighbor description. */
2642int
2643peer_description_set (struct peer *peer, char *desc)
2644{
2645 if (peer->desc)
2646 XFREE (MTYPE_PEER_DESC, peer->desc);
2647
2648 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2649
2650 return 0;
2651}
2652
2653int
2654peer_description_unset (struct peer *peer)
2655{
2656 if (peer->desc)
2657 XFREE (MTYPE_PEER_DESC, peer->desc);
2658
2659 peer->desc = NULL;
2660
2661 return 0;
2662}
2663
2664/* Neighbor update-source. */
2665int
paulfd79ac92004-10-13 05:06:08 +00002666peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002667{
2668 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002669 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002670
2671 if (peer->update_if)
2672 {
2673 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2674 && strcmp (peer->update_if, ifname) == 0)
2675 return 0;
2676
2677 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2678 peer->update_if = NULL;
2679 }
2680
2681 if (peer->update_source)
2682 {
2683 sockunion_free (peer->update_source);
2684 peer->update_source = NULL;
2685 }
2686
2687 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2688
2689 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2690 {
2691 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002692 {
2693 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2694 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2695 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2696 }
paul718e3742002-12-13 20:15:29 +00002697 else
2698 BGP_EVENT_ADD (peer, BGP_Stop);
2699 return 0;
2700 }
2701
2702 /* peer-group member updates. */
2703 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002704 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002705 {
2706 if (peer->update_if)
2707 {
2708 if (strcmp (peer->update_if, ifname) == 0)
2709 continue;
2710
2711 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2712 peer->update_if = NULL;
2713 }
2714
2715 if (peer->update_source)
2716 {
2717 sockunion_free (peer->update_source);
2718 peer->update_source = NULL;
2719 }
2720
2721 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2722
2723 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002724 {
2725 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2726 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2727 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2728 }
paul718e3742002-12-13 20:15:29 +00002729 else
2730 BGP_EVENT_ADD (peer, BGP_Stop);
2731 }
2732 return 0;
2733}
2734
2735int
2736peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2737{
2738 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002739 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002740
2741 if (peer->update_source)
2742 {
2743 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2744 && sockunion_cmp (peer->update_source, su) == 0)
2745 return 0;
2746 sockunion_free (peer->update_source);
2747 peer->update_source = NULL;
2748 }
2749
2750 if (peer->update_if)
2751 {
2752 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2753 peer->update_if = NULL;
2754 }
2755
2756 peer->update_source = sockunion_dup (su);
2757
2758 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2759 {
2760 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002761 {
2762 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2763 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2764 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2765 }
paul718e3742002-12-13 20:15:29 +00002766 else
2767 BGP_EVENT_ADD (peer, BGP_Stop);
2768 return 0;
2769 }
2770
2771 /* peer-group member updates. */
2772 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002773 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002774 {
2775 if (peer->update_source)
2776 {
2777 if (sockunion_cmp (peer->update_source, su) == 0)
2778 continue;
2779 sockunion_free (peer->update_source);
2780 peer->update_source = NULL;
2781 }
2782
2783 if (peer->update_if)
2784 {
2785 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2786 peer->update_if = NULL;
2787 }
2788
2789 peer->update_source = sockunion_dup (su);
2790
2791 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002792 {
2793 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2794 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2795 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2796 }
paul718e3742002-12-13 20:15:29 +00002797 else
2798 BGP_EVENT_ADD (peer, BGP_Stop);
2799 }
2800 return 0;
2801}
2802
2803int
2804peer_update_source_unset (struct peer *peer)
2805{
2806 union sockunion *su;
2807 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002808 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002809
2810 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2811 && ! peer->update_source
2812 && ! peer->update_if)
2813 return 0;
2814
2815 if (peer->update_source)
2816 {
2817 sockunion_free (peer->update_source);
2818 peer->update_source = NULL;
2819 }
2820 if (peer->update_if)
2821 {
2822 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2823 peer->update_if = NULL;
2824 }
2825
2826 if (peer_group_active (peer))
2827 {
2828 group = peer->group;
2829
2830 if (group->conf->update_source)
2831 {
2832 su = sockunion_dup (group->conf->update_source);
2833 peer->update_source = su;
2834 }
2835 else if (group->conf->update_if)
2836 peer->update_if =
2837 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2838 }
2839
2840 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2841 {
2842 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002843 {
2844 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2845 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2846 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2847 }
paul718e3742002-12-13 20:15:29 +00002848 else
2849 BGP_EVENT_ADD (peer, BGP_Stop);
2850 return 0;
2851 }
2852
2853 /* peer-group member updates. */
2854 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002855 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002856 {
2857 if (! peer->update_source && ! peer->update_if)
2858 continue;
2859
2860 if (peer->update_source)
2861 {
2862 sockunion_free (peer->update_source);
2863 peer->update_source = NULL;
2864 }
2865
2866 if (peer->update_if)
2867 {
2868 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2869 peer->update_if = NULL;
2870 }
2871
2872 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002873 {
2874 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2875 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2876 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2877 }
paul718e3742002-12-13 20:15:29 +00002878 else
2879 BGP_EVENT_ADD (peer, BGP_Stop);
2880 }
2881 return 0;
2882}
2883
2884int
2885peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00002886 const char *rmap)
paul718e3742002-12-13 20:15:29 +00002887{
2888 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002889 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002890
2891 /* Adress family must be activated. */
2892 if (! peer->afc[afi][safi])
2893 return BGP_ERR_PEER_INACTIVE;
2894
2895 /* Default originate can't be used for peer group memeber. */
2896 if (peer_is_group_member (peer, afi, safi))
2897 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2898
2899 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
2900 || (rmap && ! peer->default_rmap[afi][safi].name)
2901 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
2902 {
2903 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2904
2905 if (rmap)
2906 {
2907 if (peer->default_rmap[afi][safi].name)
2908 free (peer->default_rmap[afi][safi].name);
2909 peer->default_rmap[afi][safi].name = strdup (rmap);
2910 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2911 }
2912 }
2913
2914 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2915 {
2916 if (peer->status == Established && peer->afc_nego[afi][safi])
2917 bgp_default_originate (peer, afi, safi, 0);
2918 return 0;
2919 }
2920
2921 /* peer-group member updates. */
2922 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002923 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002924 {
2925 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2926
2927 if (rmap)
2928 {
2929 if (peer->default_rmap[afi][safi].name)
2930 free (peer->default_rmap[afi][safi].name);
2931 peer->default_rmap[afi][safi].name = strdup (rmap);
2932 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2933 }
2934
2935 if (peer->status == Established && peer->afc_nego[afi][safi])
2936 bgp_default_originate (peer, afi, safi, 0);
2937 }
2938 return 0;
2939}
2940
2941int
2942peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
2943{
2944 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002945 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002946
2947 /* Adress family must be activated. */
2948 if (! peer->afc[afi][safi])
2949 return BGP_ERR_PEER_INACTIVE;
2950
2951 /* Default originate can't be used for peer group memeber. */
2952 if (peer_is_group_member (peer, afi, safi))
2953 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2954
2955 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
2956 {
2957 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2958
2959 if (peer->default_rmap[afi][safi].name)
2960 free (peer->default_rmap[afi][safi].name);
2961 peer->default_rmap[afi][safi].name = NULL;
2962 peer->default_rmap[afi][safi].map = NULL;
2963 }
2964
2965 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2966 {
2967 if (peer->status == Established && peer->afc_nego[afi][safi])
2968 bgp_default_originate (peer, afi, safi, 1);
2969 return 0;
2970 }
2971
2972 /* peer-group member updates. */
2973 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002974 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002975 {
2976 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2977
2978 if (peer->default_rmap[afi][safi].name)
2979 free (peer->default_rmap[afi][safi].name);
2980 peer->default_rmap[afi][safi].name = NULL;
2981 peer->default_rmap[afi][safi].map = NULL;
2982
2983 if (peer->status == Established && peer->afc_nego[afi][safi])
2984 bgp_default_originate (peer, afi, safi, 1);
2985 }
2986 return 0;
2987}
2988
2989int
2990peer_port_set (struct peer *peer, u_int16_t port)
2991{
2992 peer->port = port;
2993 return 0;
2994}
2995
2996int
2997peer_port_unset (struct peer *peer)
2998{
2999 peer->port = BGP_PORT_DEFAULT;
3000 return 0;
3001}
3002
3003/* neighbor weight. */
3004int
3005peer_weight_set (struct peer *peer, u_int16_t weight)
3006{
3007 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003008 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003009
3010 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3011 peer->weight = weight;
3012
3013 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3014 return 0;
3015
3016 /* peer-group member updates. */
3017 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003018 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003019 {
3020 peer->weight = group->conf->weight;
3021 }
3022 return 0;
3023}
3024
3025int
3026peer_weight_unset (struct peer *peer)
3027{
3028 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003029 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003030
3031 /* Set default weight. */
3032 if (peer_group_active (peer))
3033 peer->weight = peer->group->conf->weight;
3034 else
3035 peer->weight = 0;
3036
3037 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
3038
3039 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3040 return 0;
3041
3042 /* peer-group member updates. */
3043 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003044 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003045 {
3046 peer->weight = 0;
3047 }
3048 return 0;
3049}
3050
3051int
3052peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
3053{
3054 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003055 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003056
3057 /* Not for peer group memeber. */
3058 if (peer_group_active (peer))
3059 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3060
3061 /* keepalive value check. */
3062 if (keepalive > 65535)
3063 return BGP_ERR_INVALID_VALUE;
3064
3065 /* Holdtime value check. */
3066 if (holdtime > 65535)
3067 return BGP_ERR_INVALID_VALUE;
3068
3069 /* Holdtime value must be either 0 or greater than 3. */
3070 if (holdtime < 3 && holdtime != 0)
3071 return BGP_ERR_INVALID_VALUE;
3072
3073 /* Set value to the configuration. */
3074 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3075 peer->holdtime = holdtime;
3076 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
3077
3078 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3079 return 0;
3080
3081 /* peer-group member updates. */
3082 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003083 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003084 {
3085 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
3086 peer->holdtime = group->conf->holdtime;
3087 peer->keepalive = group->conf->keepalive;
3088 }
3089 return 0;
3090}
3091
3092int
3093peer_timers_unset (struct peer *peer)
3094{
3095 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003096 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003097
3098 if (peer_group_active (peer))
3099 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3100
3101 /* Clear configuration. */
3102 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3103 peer->keepalive = 0;
3104 peer->holdtime = 0;
3105
3106 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3107 return 0;
3108
3109 /* peer-group member updates. */
3110 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003111 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003112 {
3113 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3114 peer->holdtime = 0;
3115 peer->keepalive = 0;
3116 }
3117
3118 return 0;
3119}
3120
3121int
3122peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3123{
3124 if (peer_group_active (peer))
3125 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3126
3127 if (connect > 65535)
3128 return BGP_ERR_INVALID_VALUE;
3129
3130 /* Set value to the configuration. */
3131 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3132 peer->connect = connect;
3133
3134 /* Set value to timer setting. */
3135 peer->v_connect = connect;
3136
3137 return 0;
3138}
3139
3140int
3141peer_timers_connect_unset (struct peer *peer)
3142{
3143 if (peer_group_active (peer))
3144 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3145
3146 /* Clear configuration. */
3147 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3148 peer->connect = 0;
3149
3150 /* Set timer setting to default value. */
3151 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3152
3153 return 0;
3154}
3155
3156int
3157peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3158{
3159 if (peer_group_active (peer))
3160 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3161
3162 if (routeadv > 600)
3163 return BGP_ERR_INVALID_VALUE;
3164
3165 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3166 peer->routeadv = routeadv;
3167 peer->v_routeadv = routeadv;
3168
3169 return 0;
3170}
3171
3172int
3173peer_advertise_interval_unset (struct peer *peer)
3174{
3175 if (peer_group_active (peer))
3176 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3177
3178 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3179 peer->routeadv = 0;
3180
3181 if (peer_sort (peer) == BGP_PEER_IBGP)
3182 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3183 else
3184 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3185
3186 return 0;
3187}
3188
paul718e3742002-12-13 20:15:29 +00003189/* neighbor interface */
3190int
paulfd79ac92004-10-13 05:06:08 +00003191peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003192{
3193 if (peer->ifname)
3194 free (peer->ifname);
3195 peer->ifname = strdup (str);
3196
3197 return 0;
3198}
3199
3200int
3201peer_interface_unset (struct peer *peer)
3202{
3203 if (peer->ifname)
3204 free (peer->ifname);
3205 peer->ifname = NULL;
3206
3207 return 0;
3208}
3209
3210/* Allow-as in. */
3211int
3212peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3213{
3214 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003215 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003216
3217 if (allow_num < 1 || allow_num > 10)
3218 return BGP_ERR_INVALID_VALUE;
3219
3220 if (peer->allowas_in[afi][safi] != allow_num)
3221 {
3222 peer->allowas_in[afi][safi] = allow_num;
3223 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3224 peer_change_action (peer, afi, safi, peer_change_reset_in);
3225 }
3226
3227 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3228 return 0;
3229
3230 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003231 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003232 {
3233 if (peer->allowas_in[afi][safi] != allow_num)
3234 {
3235 peer->allowas_in[afi][safi] = allow_num;
3236 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3237 peer_change_action (peer, afi, safi, peer_change_reset_in);
3238 }
3239
3240 }
3241 return 0;
3242}
3243
3244int
3245peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3246{
3247 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003248 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003249
3250 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3251 {
3252 peer->allowas_in[afi][safi] = 0;
3253 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3254 }
3255
3256 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3257 return 0;
3258
3259 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003260 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003261 {
3262 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3263 {
3264 peer->allowas_in[afi][safi] = 0;
3265 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3266 }
3267 }
3268 return 0;
3269}
3270
3271int
3272peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3273{
3274 struct bgp *bgp = peer->bgp;
3275 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003276 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003277
3278 if (peer_sort (peer) != BGP_PEER_EBGP
3279 && peer_sort (peer) != BGP_PEER_INTERNAL)
3280 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3281
3282 if (bgp->as == as)
3283 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3284
3285 if (peer_group_active (peer))
3286 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3287
3288 if (peer->change_local_as == as &&
3289 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3290 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3291 return 0;
3292
3293 peer->change_local_as = as;
3294 if (no_prepend)
3295 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3296 else
3297 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3298
3299 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3300 {
3301 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003302 {
3303 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3304 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3305 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3306 }
paul718e3742002-12-13 20:15:29 +00003307 else
3308 BGP_EVENT_ADD (peer, BGP_Stop);
3309
3310 return 0;
3311 }
3312
3313 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003314 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003315 {
3316 peer->change_local_as = as;
3317 if (no_prepend)
3318 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3319 else
3320 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3321
3322 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003323 {
3324 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3325 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3326 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3327 }
paul718e3742002-12-13 20:15:29 +00003328 else
3329 BGP_EVENT_ADD (peer, BGP_Stop);
3330 }
3331
3332 return 0;
3333}
3334
3335int
3336peer_local_as_unset (struct peer *peer)
3337{
3338 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003339 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003340
3341 if (peer_group_active (peer))
3342 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3343
3344 if (! peer->change_local_as)
3345 return 0;
3346
3347 peer->change_local_as = 0;
3348 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3349
3350 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3351 {
3352 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003353 {
3354 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3355 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3356 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3357 }
paul718e3742002-12-13 20:15:29 +00003358 else
3359 BGP_EVENT_ADD (peer, BGP_Stop);
3360
3361 return 0;
3362 }
3363
3364 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003365 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003366 {
3367 peer->change_local_as = 0;
3368 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3369
3370 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003371 {
3372 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3373 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3374 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3375 }
paul718e3742002-12-13 20:15:29 +00003376 else
3377 BGP_EVENT_ADD (peer, BGP_Stop);
3378 }
3379 return 0;
3380}
3381
3382/* Set distribute list to the peer. */
3383int
3384peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003385 const char *name)
paul718e3742002-12-13 20:15:29 +00003386{
3387 struct bgp_filter *filter;
3388 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003389 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003390
3391 if (! peer->afc[afi][safi])
3392 return BGP_ERR_PEER_INACTIVE;
3393
3394 if (direct != FILTER_IN && direct != FILTER_OUT)
3395 return BGP_ERR_INVALID_VALUE;
3396
3397 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3398 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3399
3400 filter = &peer->filter[afi][safi];
3401
3402 if (filter->plist[direct].name)
3403 return BGP_ERR_PEER_FILTER_CONFLICT;
3404
3405 if (filter->dlist[direct].name)
3406 free (filter->dlist[direct].name);
3407 filter->dlist[direct].name = strdup (name);
3408 filter->dlist[direct].alist = access_list_lookup (afi, name);
3409
3410 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3411 return 0;
3412
3413 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003414 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003415 {
3416 filter = &peer->filter[afi][safi];
3417
3418 if (! peer->af_group[afi][safi])
3419 continue;
3420
3421 if (filter->dlist[direct].name)
3422 free (filter->dlist[direct].name);
3423 filter->dlist[direct].name = strdup (name);
3424 filter->dlist[direct].alist = access_list_lookup (afi, name);
3425 }
3426
3427 return 0;
3428}
3429
3430int
3431peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3432{
3433 struct bgp_filter *filter;
3434 struct bgp_filter *gfilter;
3435 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003436 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003437
3438 if (! peer->afc[afi][safi])
3439 return BGP_ERR_PEER_INACTIVE;
3440
3441 if (direct != FILTER_IN && direct != FILTER_OUT)
3442 return BGP_ERR_INVALID_VALUE;
3443
3444 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3445 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3446
3447 filter = &peer->filter[afi][safi];
3448
3449 /* apply peer-group filter */
3450 if (peer->af_group[afi][safi])
3451 {
3452 gfilter = &peer->group->conf->filter[afi][safi];
3453
3454 if (gfilter->dlist[direct].name)
3455 {
3456 if (filter->dlist[direct].name)
3457 free (filter->dlist[direct].name);
3458 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3459 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3460 return 0;
3461 }
3462 }
3463
3464 if (filter->dlist[direct].name)
3465 free (filter->dlist[direct].name);
3466 filter->dlist[direct].name = NULL;
3467 filter->dlist[direct].alist = NULL;
3468
3469 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3470 return 0;
3471
3472 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003473 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003474 {
3475 filter = &peer->filter[afi][safi];
3476
3477 if (! peer->af_group[afi][safi])
3478 continue;
3479
3480 if (filter->dlist[direct].name)
3481 free (filter->dlist[direct].name);
3482 filter->dlist[direct].name = NULL;
3483 filter->dlist[direct].alist = NULL;
3484 }
3485
3486 return 0;
3487}
3488
3489/* Update distribute list. */
paul94f2b392005-06-28 12:44:16 +00003490static void
paul718e3742002-12-13 20:15:29 +00003491peer_distribute_update (struct access_list *access)
3492{
3493 afi_t afi;
3494 safi_t safi;
3495 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003496 struct listnode *mnode, *mnnode;
3497 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003498 struct bgp *bgp;
3499 struct peer *peer;
3500 struct peer_group *group;
3501 struct bgp_filter *filter;
3502
paul1eb8ef22005-04-07 07:30:20 +00003503 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003504 {
paul1eb8ef22005-04-07 07:30:20 +00003505 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003506 {
3507 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3508 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3509 {
3510 filter = &peer->filter[afi][safi];
3511
3512 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3513 {
3514 if (filter->dlist[direct].name)
3515 filter->dlist[direct].alist =
3516 access_list_lookup (afi, filter->dlist[direct].name);
3517 else
3518 filter->dlist[direct].alist = NULL;
3519 }
3520 }
3521 }
paul1eb8ef22005-04-07 07:30:20 +00003522 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003523 {
3524 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3525 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3526 {
3527 filter = &group->conf->filter[afi][safi];
3528
3529 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3530 {
3531 if (filter->dlist[direct].name)
3532 filter->dlist[direct].alist =
3533 access_list_lookup (afi, filter->dlist[direct].name);
3534 else
3535 filter->dlist[direct].alist = NULL;
3536 }
3537 }
3538 }
3539 }
3540}
3541
3542/* Set prefix list to the peer. */
3543int
3544peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003545 const char *name)
paul718e3742002-12-13 20:15:29 +00003546{
3547 struct bgp_filter *filter;
3548 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003549 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003550
3551 if (! peer->afc[afi][safi])
3552 return BGP_ERR_PEER_INACTIVE;
3553
3554 if (direct != FILTER_IN && direct != FILTER_OUT)
3555 return BGP_ERR_INVALID_VALUE;
3556
3557 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3558 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3559
3560 filter = &peer->filter[afi][safi];
3561
3562 if (filter->dlist[direct].name)
3563 return BGP_ERR_PEER_FILTER_CONFLICT;
3564
3565 if (filter->plist[direct].name)
3566 free (filter->plist[direct].name);
3567 filter->plist[direct].name = strdup (name);
3568 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3569
3570 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3571 return 0;
3572
3573 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003574 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003575 {
3576 filter = &peer->filter[afi][safi];
3577
3578 if (! peer->af_group[afi][safi])
3579 continue;
3580
3581 if (filter->plist[direct].name)
3582 free (filter->plist[direct].name);
3583 filter->plist[direct].name = strdup (name);
3584 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3585 }
3586 return 0;
3587}
3588
3589int
3590peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3591{
3592 struct bgp_filter *filter;
3593 struct bgp_filter *gfilter;
3594 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003595 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003596
3597 if (! peer->afc[afi][safi])
3598 return BGP_ERR_PEER_INACTIVE;
3599
3600 if (direct != FILTER_IN && direct != FILTER_OUT)
3601 return BGP_ERR_INVALID_VALUE;
3602
3603 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3604 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3605
3606 filter = &peer->filter[afi][safi];
3607
3608 /* apply peer-group filter */
3609 if (peer->af_group[afi][safi])
3610 {
3611 gfilter = &peer->group->conf->filter[afi][safi];
3612
3613 if (gfilter->plist[direct].name)
3614 {
3615 if (filter->plist[direct].name)
3616 free (filter->plist[direct].name);
3617 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3618 filter->plist[direct].plist = gfilter->plist[direct].plist;
3619 return 0;
3620 }
3621 }
3622
3623 if (filter->plist[direct].name)
3624 free (filter->plist[direct].name);
3625 filter->plist[direct].name = NULL;
3626 filter->plist[direct].plist = NULL;
3627
3628 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3629 return 0;
3630
3631 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003632 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003633 {
3634 filter = &peer->filter[afi][safi];
3635
3636 if (! peer->af_group[afi][safi])
3637 continue;
3638
3639 if (filter->plist[direct].name)
3640 free (filter->plist[direct].name);
3641 filter->plist[direct].name = NULL;
3642 filter->plist[direct].plist = NULL;
3643 }
3644
3645 return 0;
3646}
3647
3648/* Update prefix-list list. */
paul94f2b392005-06-28 12:44:16 +00003649static void
paul718e3742002-12-13 20:15:29 +00003650peer_prefix_list_update (struct prefix_list *plist)
3651{
paul1eb8ef22005-04-07 07:30:20 +00003652 struct listnode *mnode, *mnnode;
3653 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003654 struct bgp *bgp;
3655 struct peer *peer;
3656 struct peer_group *group;
3657 struct bgp_filter *filter;
3658 afi_t afi;
3659 safi_t safi;
3660 int direct;
3661
paul1eb8ef22005-04-07 07:30:20 +00003662 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003663 {
paul1eb8ef22005-04-07 07:30:20 +00003664 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003665 {
3666 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3667 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3668 {
3669 filter = &peer->filter[afi][safi];
3670
3671 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3672 {
3673 if (filter->plist[direct].name)
3674 filter->plist[direct].plist =
3675 prefix_list_lookup (afi, filter->plist[direct].name);
3676 else
3677 filter->plist[direct].plist = NULL;
3678 }
3679 }
3680 }
paul1eb8ef22005-04-07 07:30:20 +00003681 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003682 {
3683 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3684 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3685 {
3686 filter = &group->conf->filter[afi][safi];
3687
3688 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3689 {
3690 if (filter->plist[direct].name)
3691 filter->plist[direct].plist =
3692 prefix_list_lookup (afi, filter->plist[direct].name);
3693 else
3694 filter->plist[direct].plist = NULL;
3695 }
3696 }
3697 }
3698 }
3699}
3700
3701int
3702peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003703 const char *name)
paul718e3742002-12-13 20:15:29 +00003704{
3705 struct bgp_filter *filter;
3706 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003707 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003708
3709 if (! peer->afc[afi][safi])
3710 return BGP_ERR_PEER_INACTIVE;
3711
3712 if (direct != FILTER_IN && direct != FILTER_OUT)
3713 return BGP_ERR_INVALID_VALUE;
3714
3715 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3716 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3717
3718 filter = &peer->filter[afi][safi];
3719
3720 if (filter->aslist[direct].name)
3721 free (filter->aslist[direct].name);
3722 filter->aslist[direct].name = strdup (name);
3723 filter->aslist[direct].aslist = as_list_lookup (name);
3724
3725 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3726 return 0;
3727
3728 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003729 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003730 {
3731 filter = &peer->filter[afi][safi];
3732
3733 if (! peer->af_group[afi][safi])
3734 continue;
3735
3736 if (filter->aslist[direct].name)
3737 free (filter->aslist[direct].name);
3738 filter->aslist[direct].name = strdup (name);
3739 filter->aslist[direct].aslist = as_list_lookup (name);
3740 }
3741 return 0;
3742}
3743
3744int
3745peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3746{
3747 struct bgp_filter *filter;
3748 struct bgp_filter *gfilter;
3749 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003750 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003751
3752 if (! peer->afc[afi][safi])
3753 return BGP_ERR_PEER_INACTIVE;
3754
hassob5f29602005-05-25 21:00:28 +00003755 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00003756 return BGP_ERR_INVALID_VALUE;
3757
hassob5f29602005-05-25 21:00:28 +00003758 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003759 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3760
3761 filter = &peer->filter[afi][safi];
3762
3763 /* apply peer-group filter */
3764 if (peer->af_group[afi][safi])
3765 {
3766 gfilter = &peer->group->conf->filter[afi][safi];
3767
3768 if (gfilter->aslist[direct].name)
3769 {
3770 if (filter->aslist[direct].name)
3771 free (filter->aslist[direct].name);
3772 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
3773 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
3774 return 0;
3775 }
3776 }
3777
3778 if (filter->aslist[direct].name)
3779 free (filter->aslist[direct].name);
3780 filter->aslist[direct].name = NULL;
3781 filter->aslist[direct].aslist = NULL;
3782
3783 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3784 return 0;
3785
3786 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003787 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003788 {
3789 filter = &peer->filter[afi][safi];
3790
3791 if (! peer->af_group[afi][safi])
3792 continue;
3793
3794 if (filter->aslist[direct].name)
3795 free (filter->aslist[direct].name);
3796 filter->aslist[direct].name = NULL;
3797 filter->aslist[direct].aslist = NULL;
3798 }
3799
3800 return 0;
3801}
3802
paul94f2b392005-06-28 12:44:16 +00003803static void
paul718e3742002-12-13 20:15:29 +00003804peer_aslist_update ()
3805{
3806 afi_t afi;
3807 safi_t safi;
3808 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003809 struct listnode *mnode, *mnnode;
3810 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003811 struct bgp *bgp;
3812 struct peer *peer;
3813 struct peer_group *group;
3814 struct bgp_filter *filter;
3815
paul1eb8ef22005-04-07 07:30:20 +00003816 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003817 {
paul1eb8ef22005-04-07 07:30:20 +00003818 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003819 {
3820 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3821 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3822 {
3823 filter = &peer->filter[afi][safi];
3824
3825 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3826 {
3827 if (filter->aslist[direct].name)
3828 filter->aslist[direct].aslist =
3829 as_list_lookup (filter->aslist[direct].name);
3830 else
3831 filter->aslist[direct].aslist = NULL;
3832 }
3833 }
3834 }
paul1eb8ef22005-04-07 07:30:20 +00003835 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003836 {
3837 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3838 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3839 {
3840 filter = &group->conf->filter[afi][safi];
3841
3842 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3843 {
3844 if (filter->aslist[direct].name)
3845 filter->aslist[direct].aslist =
3846 as_list_lookup (filter->aslist[direct].name);
3847 else
3848 filter->aslist[direct].aslist = NULL;
3849 }
3850 }
3851 }
3852 }
3853}
3854
3855/* Set route-map to the peer. */
3856int
3857peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003858 const char *name)
paul718e3742002-12-13 20:15:29 +00003859{
3860 struct bgp_filter *filter;
3861 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003862 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003863
3864 if (! peer->afc[afi][safi])
3865 return BGP_ERR_PEER_INACTIVE;
3866
paulfee0f4c2004-09-13 05:12:46 +00003867 if (direct != RMAP_IN && direct != RMAP_OUT &&
3868 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003869 return BGP_ERR_INVALID_VALUE;
3870
paulfee0f4c2004-09-13 05:12:46 +00003871 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
3872 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003873 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3874
3875 filter = &peer->filter[afi][safi];
3876
3877 if (filter->map[direct].name)
3878 free (filter->map[direct].name);
3879
3880 filter->map[direct].name = strdup (name);
3881 filter->map[direct].map = route_map_lookup_by_name (name);
3882
3883 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3884 return 0;
3885
3886 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003887 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003888 {
3889 filter = &peer->filter[afi][safi];
3890
3891 if (! peer->af_group[afi][safi])
3892 continue;
3893
3894 if (filter->map[direct].name)
3895 free (filter->map[direct].name);
3896 filter->map[direct].name = strdup (name);
3897 filter->map[direct].map = route_map_lookup_by_name (name);
3898 }
3899 return 0;
3900}
3901
3902/* Unset route-map from the peer. */
3903int
3904peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3905{
3906 struct bgp_filter *filter;
3907 struct bgp_filter *gfilter;
3908 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003909 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003910
3911 if (! peer->afc[afi][safi])
3912 return BGP_ERR_PEER_INACTIVE;
3913
hassob5f29602005-05-25 21:00:28 +00003914 if (direct != RMAP_IN && direct != RMAP_OUT &&
3915 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003916 return BGP_ERR_INVALID_VALUE;
3917
hassob5f29602005-05-25 21:00:28 +00003918 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
3919 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003920 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3921
3922 filter = &peer->filter[afi][safi];
3923
3924 /* apply peer-group filter */
3925 if (peer->af_group[afi][safi])
3926 {
3927 gfilter = &peer->group->conf->filter[afi][safi];
3928
3929 if (gfilter->map[direct].name)
3930 {
3931 if (filter->map[direct].name)
3932 free (filter->map[direct].name);
3933 filter->map[direct].name = strdup (gfilter->map[direct].name);
3934 filter->map[direct].map = gfilter->map[direct].map;
3935 return 0;
3936 }
3937 }
3938
3939 if (filter->map[direct].name)
3940 free (filter->map[direct].name);
3941 filter->map[direct].name = NULL;
3942 filter->map[direct].map = NULL;
3943
3944 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3945 return 0;
3946
3947 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003948 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003949 {
3950 filter = &peer->filter[afi][safi];
3951
3952 if (! peer->af_group[afi][safi])
3953 continue;
3954
3955 if (filter->map[direct].name)
3956 free (filter->map[direct].name);
3957 filter->map[direct].name = NULL;
3958 filter->map[direct].map = NULL;
3959 }
3960 return 0;
3961}
3962
3963/* Set unsuppress-map to the peer. */
3964int
paulfd79ac92004-10-13 05:06:08 +00003965peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
3966 const char *name)
paul718e3742002-12-13 20:15:29 +00003967{
3968 struct bgp_filter *filter;
3969 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003970 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003971
3972 if (! peer->afc[afi][safi])
3973 return BGP_ERR_PEER_INACTIVE;
3974
3975 if (peer_is_group_member (peer, afi, safi))
3976 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3977
3978 filter = &peer->filter[afi][safi];
3979
3980 if (filter->usmap.name)
3981 free (filter->usmap.name);
3982
3983 filter->usmap.name = strdup (name);
3984 filter->usmap.map = route_map_lookup_by_name (name);
3985
3986 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3987 return 0;
3988
3989 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003990 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003991 {
3992 filter = &peer->filter[afi][safi];
3993
3994 if (! peer->af_group[afi][safi])
3995 continue;
3996
3997 if (filter->usmap.name)
3998 free (filter->usmap.name);
3999 filter->usmap.name = strdup (name);
4000 filter->usmap.map = route_map_lookup_by_name (name);
4001 }
4002 return 0;
4003}
4004
4005/* Unset route-map from the peer. */
4006int
4007peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
4008{
4009 struct bgp_filter *filter;
4010 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004011 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004012
4013 if (! peer->afc[afi][safi])
4014 return BGP_ERR_PEER_INACTIVE;
4015
4016 if (peer_is_group_member (peer, afi, safi))
4017 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
4018
4019 filter = &peer->filter[afi][safi];
4020
4021 if (filter->usmap.name)
4022 free (filter->usmap.name);
4023 filter->usmap.name = NULL;
4024 filter->usmap.map = NULL;
4025
4026 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4027 return 0;
4028
4029 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004030 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004031 {
4032 filter = &peer->filter[afi][safi];
4033
4034 if (! peer->af_group[afi][safi])
4035 continue;
4036
4037 if (filter->usmap.name)
4038 free (filter->usmap.name);
4039 filter->usmap.name = NULL;
4040 filter->usmap.map = NULL;
4041 }
4042 return 0;
4043}
4044
4045int
4046peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00004047 u_int32_t max, u_char threshold,
4048 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00004049{
4050 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004051 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004052
4053 if (! peer->afc[afi][safi])
4054 return BGP_ERR_PEER_INACTIVE;
4055
4056 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4057 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004058 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004059 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004060 if (warning)
4061 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4062 else
4063 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4064
4065 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4066 return 0;
4067
4068 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004069 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004070 {
4071 if (! peer->af_group[afi][safi])
4072 continue;
4073
4074 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4075 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00004076 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00004077 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00004078 if (warning)
4079 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4080 else
4081 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4082 }
4083 return 0;
4084}
4085
4086int
4087peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
4088{
4089 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004090 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004091
4092 if (! peer->afc[afi][safi])
4093 return BGP_ERR_PEER_INACTIVE;
4094
4095 /* apply peer-group config */
4096 if (peer->af_group[afi][safi])
4097 {
4098 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4099 PEER_FLAG_MAX_PREFIX))
4100 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4101 else
4102 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4103
4104 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
4105 PEER_FLAG_MAX_PREFIX_WARNING))
4106 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4107 else
4108 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4109
4110 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004111 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004112 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004113 return 0;
4114 }
4115
4116 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4117 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4118 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004119 peer->pmax_threshold[afi][safi] = 0;
4120 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004121
4122 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4123 return 0;
4124
4125 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004126 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004127 {
4128 if (! peer->af_group[afi][safi])
4129 continue;
4130
4131 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4132 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4133 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004134 peer->pmax_threshold[afi][safi] = 0;
4135 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004136 }
4137 return 0;
4138}
4139
4140int
4141peer_clear (struct peer *peer)
4142{
4143 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4144 {
hasso0a486e52005-02-01 20:57:17 +00004145 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4146 {
4147 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4148 if (peer->t_pmax_restart)
4149 {
4150 BGP_TIMER_OFF (peer->t_pmax_restart);
4151 if (BGP_DEBUG (events, EVENTS))
4152 zlog_debug ("%s Maximum-prefix restart timer canceled",
4153 peer->host);
4154 }
4155 BGP_EVENT_ADD (peer, BGP_Start);
4156 return 0;
4157 }
4158
paul718e3742002-12-13 20:15:29 +00004159 peer->v_start = BGP_INIT_START_TIMER;
4160 if (peer->status == Established)
4161 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4162 BGP_NOTIFY_CEASE_ADMIN_RESET);
4163 else
4164 BGP_EVENT_ADD (peer, BGP_Stop);
4165 }
4166 return 0;
4167}
4168
4169int
4170peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4171 enum bgp_clear_type stype)
4172{
4173 if (peer->status != Established)
4174 return 0;
4175
4176 if (! peer->afc[afi][safi])
4177 return BGP_ERR_AF_UNCONFIGURED;
4178
paulfee0f4c2004-09-13 05:12:46 +00004179 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4180 {
4181 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4182 return 0;
4183 bgp_check_local_routes_rsclient (peer, afi, safi);
4184 bgp_soft_reconfig_rsclient (peer, afi, safi);
4185 }
4186
paul718e3742002-12-13 20:15:29 +00004187 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4188 bgp_announce_route (peer, afi, safi);
4189
4190 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4191 {
4192 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4193 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4194 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4195 {
4196 struct bgp_filter *filter = &peer->filter[afi][safi];
4197 u_char prefix_type;
4198
4199 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4200 prefix_type = ORF_TYPE_PREFIX;
4201 else
4202 prefix_type = ORF_TYPE_PREFIX_OLD;
4203
4204 if (filter->plist[FILTER_IN].plist)
4205 {
4206 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4207 bgp_route_refresh_send (peer, afi, safi,
4208 prefix_type, REFRESH_DEFER, 1);
4209 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4210 REFRESH_IMMEDIATE, 0);
4211 }
4212 else
4213 {
4214 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4215 bgp_route_refresh_send (peer, afi, safi,
4216 prefix_type, REFRESH_IMMEDIATE, 1);
4217 else
4218 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4219 }
4220 return 0;
4221 }
4222 }
4223
4224 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4225 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4226 {
4227 /* If neighbor has soft reconfiguration inbound flag.
4228 Use Adj-RIB-In database. */
4229 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4230 bgp_soft_reconfig_in (peer, afi, safi);
4231 else
4232 {
4233 /* If neighbor has route refresh capability, send route refresh
4234 message to the peer. */
4235 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4236 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4237 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4238 else
4239 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4240 }
4241 }
4242 return 0;
4243}
4244
paulfd79ac92004-10-13 05:06:08 +00004245/* Display peer uptime.*/
4246/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004247char *
4248peer_uptime (time_t uptime2, char *buf, size_t len)
4249{
4250 time_t uptime1;
4251 struct tm *tm;
4252
4253 /* Check buffer length. */
4254 if (len < BGP_UPTIME_LEN)
4255 {
Andrew J. Schorr0cd1c322006-09-19 18:51:53 +00004256 zlog_warn ("peer_uptime (): buffer shortage %lu", (u_long)len);
paulfd79ac92004-10-13 05:06:08 +00004257 /* XXX: should return status instead of buf... */
4258 snprintf (buf, len, "<error> ");
4259 return buf;
paul718e3742002-12-13 20:15:29 +00004260 }
4261
4262 /* If there is no connection has been done before print `never'. */
4263 if (uptime2 == 0)
4264 {
4265 snprintf (buf, len, "never ");
4266 return buf;
4267 }
4268
4269 /* Get current time. */
4270 uptime1 = time (NULL);
4271 uptime1 -= uptime2;
4272 tm = gmtime (&uptime1);
4273
4274 /* Making formatted timer strings. */
4275#define ONE_DAY_SECOND 60*60*24
4276#define ONE_WEEK_SECOND 60*60*24*7
4277
4278 if (uptime1 < ONE_DAY_SECOND)
4279 snprintf (buf, len, "%02d:%02d:%02d",
4280 tm->tm_hour, tm->tm_min, tm->tm_sec);
4281 else if (uptime1 < ONE_WEEK_SECOND)
4282 snprintf (buf, len, "%dd%02dh%02dm",
4283 tm->tm_yday, tm->tm_hour, tm->tm_min);
4284 else
4285 snprintf (buf, len, "%02dw%dd%02dh",
4286 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4287 return buf;
4288}
4289
paul94f2b392005-06-28 12:44:16 +00004290static void
paul718e3742002-12-13 20:15:29 +00004291bgp_config_write_filter (struct vty *vty, struct peer *peer,
4292 afi_t afi, safi_t safi)
4293{
4294 struct bgp_filter *filter;
4295 struct bgp_filter *gfilter = NULL;
4296 char *addr;
4297 int in = FILTER_IN;
4298 int out = FILTER_OUT;
4299
4300 addr = peer->host;
4301 filter = &peer->filter[afi][safi];
4302 if (peer->af_group[afi][safi])
4303 gfilter = &peer->group->conf->filter[afi][safi];
4304
4305 /* distribute-list. */
4306 if (filter->dlist[in].name)
4307 if (! gfilter || ! gfilter->dlist[in].name
4308 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4309 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4310 filter->dlist[in].name, VTY_NEWLINE);
4311 if (filter->dlist[out].name && ! gfilter)
4312 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4313 filter->dlist[out].name, VTY_NEWLINE);
4314
4315 /* prefix-list. */
4316 if (filter->plist[in].name)
4317 if (! gfilter || ! gfilter->plist[in].name
4318 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4319 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4320 filter->plist[in].name, VTY_NEWLINE);
4321 if (filter->plist[out].name && ! gfilter)
4322 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4323 filter->plist[out].name, VTY_NEWLINE);
4324
4325 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004326 if (filter->map[RMAP_IN].name)
4327 if (! gfilter || ! gfilter->map[RMAP_IN].name
4328 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004329 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004330 filter->map[RMAP_IN].name, VTY_NEWLINE);
4331 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004332 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004333 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4334 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4335 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4336 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4337 if (filter->map[RMAP_EXPORT].name)
4338 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4339 || strcmp (filter->map[RMAP_EXPORT].name,
4340 gfilter->map[RMAP_EXPORT].name) != 0)
4341 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4342 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004343
4344 /* unsuppress-map */
4345 if (filter->usmap.name && ! gfilter)
4346 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4347 filter->usmap.name, VTY_NEWLINE);
4348
4349 /* filter-list. */
4350 if (filter->aslist[in].name)
4351 if (! gfilter || ! gfilter->aslist[in].name
4352 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4353 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4354 filter->aslist[in].name, VTY_NEWLINE);
4355 if (filter->aslist[out].name && ! gfilter)
4356 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4357 filter->aslist[out].name, VTY_NEWLINE);
4358}
4359
4360/* BGP peer configuration display function. */
paul94f2b392005-06-28 12:44:16 +00004361static void
paul718e3742002-12-13 20:15:29 +00004362bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4363 struct peer *peer, afi_t afi, safi_t safi)
4364{
4365 struct bgp_filter *filter;
4366 struct peer *g_peer = NULL;
4367 char buf[SU_ADDRSTRLEN];
4368 char *addr;
4369
4370 filter = &peer->filter[afi][safi];
4371 addr = peer->host;
4372 if (peer_group_active (peer))
4373 g_peer = peer->group->conf;
4374
4375 /************************************
4376 ****** Global to the neighbor ******
4377 ************************************/
4378 if (afi == AFI_IP && safi == SAFI_UNICAST)
4379 {
4380 /* remote-as. */
4381 if (! peer_group_active (peer))
4382 {
4383 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4384 vty_out (vty, " neighbor %s peer-group%s", addr,
4385 VTY_NEWLINE);
4386 if (peer->as)
4387 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4388 VTY_NEWLINE);
4389 }
4390 else
4391 {
4392 if (! g_peer->as)
4393 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4394 VTY_NEWLINE);
4395 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4396 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4397 peer->group->name, VTY_NEWLINE);
4398 }
4399
4400 /* local-as. */
4401 if (peer->change_local_as)
4402 if (! peer_group_active (peer))
4403 vty_out (vty, " neighbor %s local-as %d%s%s", addr,
4404 peer->change_local_as,
4405 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4406 " no-prepend" : "", VTY_NEWLINE);
4407
4408 /* Description. */
4409 if (peer->desc)
4410 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4411 VTY_NEWLINE);
4412
4413 /* Shutdown. */
4414 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4415 if (! peer_group_active (peer) ||
4416 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4417 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4418
4419 /* BGP port. */
4420 if (peer->port != BGP_PORT_DEFAULT)
4421 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
4422 VTY_NEWLINE);
4423
4424 /* Local interface name. */
4425 if (peer->ifname)
4426 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4427 VTY_NEWLINE);
4428
4429 /* Passive. */
4430 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4431 if (! peer_group_active (peer) ||
4432 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4433 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4434
4435 /* EBGP multihop. */
4436 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
4437 if (! peer_group_active (peer) ||
4438 g_peer->ttl != peer->ttl)
4439 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4440 VTY_NEWLINE);
4441
hasso6ffd2072005-02-02 14:50:11 +00004442 /* disable-connected-check. */
4443 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004444 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004445 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4446 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004447
4448 /* Update-source. */
4449 if (peer->update_if)
4450 if (! peer_group_active (peer) || ! g_peer->update_if
4451 || strcmp (g_peer->update_if, peer->update_if) != 0)
4452 vty_out (vty, " neighbor %s update-source %s%s", addr,
4453 peer->update_if, VTY_NEWLINE);
4454 if (peer->update_source)
4455 if (! peer_group_active (peer) || ! g_peer->update_source
4456 || sockunion_cmp (g_peer->update_source,
4457 peer->update_source) != 0)
4458 vty_out (vty, " neighbor %s update-source %s%s", addr,
4459 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4460 VTY_NEWLINE);
4461
paul718e3742002-12-13 20:15:29 +00004462 /* advertisement-interval */
4463 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4464 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4465 addr, peer->v_routeadv, VTY_NEWLINE);
4466
4467 /* timers. */
4468 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4469 && ! peer_group_active (peer))
4470 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4471 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4472
4473 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4474 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4475 peer->connect, VTY_NEWLINE);
4476
4477 /* Default weight. */
4478 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4479 if (! peer_group_active (peer) ||
4480 g_peer->weight != peer->weight)
4481 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4482 VTY_NEWLINE);
4483
paul718e3742002-12-13 20:15:29 +00004484 /* Dynamic capability. */
4485 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4486 if (! peer_group_active (peer) ||
4487 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4488 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4489 VTY_NEWLINE);
4490
4491 /* dont capability negotiation. */
4492 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4493 if (! peer_group_active (peer) ||
4494 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4495 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4496 VTY_NEWLINE);
4497
4498 /* override capability negotiation. */
4499 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4500 if (! peer_group_active (peer) ||
4501 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4502 vty_out (vty, " neighbor %s override-capability%s", addr,
4503 VTY_NEWLINE);
4504
4505 /* strict capability negotiation. */
4506 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4507 if (! peer_group_active (peer) ||
4508 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4509 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4510 VTY_NEWLINE);
4511
4512 if (! peer_group_active (peer))
4513 {
4514 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4515 {
4516 if (peer->afc[AFI_IP][SAFI_UNICAST])
4517 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4518 }
4519 else
4520 {
4521 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4522 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4523 }
4524 }
4525 }
4526
4527
4528 /************************************
4529 ****** Per AF to the neighbor ******
4530 ************************************/
4531
4532 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4533 {
4534 if (peer->af_group[afi][safi])
4535 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4536 peer->group->name, VTY_NEWLINE);
4537 else
4538 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4539 }
4540
4541 /* ORF capability. */
4542 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4543 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4544 if (! peer->af_group[afi][safi])
4545 {
4546 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4547
4548 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4549 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4550 vty_out (vty, " both");
4551 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4552 vty_out (vty, " send");
4553 else
4554 vty_out (vty, " receive");
4555 vty_out (vty, "%s", VTY_NEWLINE);
4556 }
4557
4558 /* Route reflector client. */
4559 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4560 && ! peer->af_group[afi][safi])
4561 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4562 VTY_NEWLINE);
4563
4564 /* Nexthop self. */
4565 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4566 && ! peer->af_group[afi][safi])
4567 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4568
4569 /* Remove private AS. */
4570 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4571 && ! peer->af_group[afi][safi])
4572 vty_out (vty, " neighbor %s remove-private-AS%s",
4573 addr, VTY_NEWLINE);
4574
4575 /* send-community print. */
4576 if (! peer->af_group[afi][safi])
4577 {
4578 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4579 {
4580 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4581 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4582 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4583 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4584 vty_out (vty, " neighbor %s send-community extended%s",
4585 addr, VTY_NEWLINE);
4586 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4587 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4588 }
4589 else
4590 {
4591 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4592 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4593 vty_out (vty, " no neighbor %s send-community both%s",
4594 addr, VTY_NEWLINE);
4595 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4596 vty_out (vty, " no neighbor %s send-community extended%s",
4597 addr, VTY_NEWLINE);
4598 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4599 vty_out (vty, " no neighbor %s send-community%s",
4600 addr, VTY_NEWLINE);
4601 }
4602 }
4603
4604 /* Default information */
4605 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4606 && ! peer->af_group[afi][safi])
4607 {
4608 vty_out (vty, " neighbor %s default-originate", addr);
4609 if (peer->default_rmap[afi][safi].name)
4610 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4611 vty_out (vty, "%s", VTY_NEWLINE);
4612 }
4613
4614 /* Soft reconfiguration inbound. */
4615 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4616 if (! peer->af_group[afi][safi] ||
4617 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4618 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4619 VTY_NEWLINE);
4620
4621 /* maximum-prefix. */
4622 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4623 if (! peer->af_group[afi][safi]
4624 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004625 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004626 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4627 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00004628 {
hasso0a486e52005-02-01 20:57:17 +00004629 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
4630 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
4631 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
4632 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
4633 vty_out (vty, " warning-only");
4634 if (peer->pmax_restart[afi][safi])
4635 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
4636 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00004637 }
paul718e3742002-12-13 20:15:29 +00004638
4639 /* Route server client. */
4640 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
4641 && ! peer->af_group[afi][safi])
4642 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
4643
4644 /* Allow AS in. */
4645 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
4646 if (! peer_group_active (peer)
4647 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
4648 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
4649 {
4650 if (peer->allowas_in[afi][safi] == 3)
4651 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
4652 else
4653 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
4654 peer->allowas_in[afi][safi], VTY_NEWLINE);
4655 }
4656
4657 /* Filter. */
4658 bgp_config_write_filter (vty, peer, afi, safi);
4659
4660 /* atribute-unchanged. */
4661 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4662 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4663 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4664 && ! peer->af_group[afi][safi])
4665 {
4666 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4667 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4668 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4669 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
4670 else
4671 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
4672 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
4673 " as-path" : "",
4674 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
4675 " next-hop" : "",
4676 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
4677 " med" : "", VTY_NEWLINE);
4678 }
4679}
4680
4681/* Display "address-family" configuration header. */
4682void
4683bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
4684 int *write)
4685{
4686 if (*write)
4687 return;
4688
4689 if (afi == AFI_IP && safi == SAFI_UNICAST)
4690 return;
4691
4692 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
4693
4694 if (afi == AFI_IP)
4695 {
4696 if (safi == SAFI_MULTICAST)
4697 vty_out (vty, "ipv4 multicast");
4698 else if (safi == SAFI_MPLS_VPN)
4699 vty_out (vty, "vpnv4 unicast");
4700 }
4701 else if (afi == AFI_IP6)
Paul Jakma37a217a2007-04-10 19:20:29 +00004702 {
4703 vty_out (vty, "ipv6");
4704
4705 if (safi == SAFI_MULTICAST)
4706 vty_out (vty, " multicast");
4707 }
paul718e3742002-12-13 20:15:29 +00004708
4709 vty_out (vty, "%s", VTY_NEWLINE);
4710
4711 *write = 1;
4712}
4713
4714/* Address family based peer configuration display. */
paul94f2b392005-06-28 12:44:16 +00004715static int
paul718e3742002-12-13 20:15:29 +00004716bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
4717 safi_t safi)
4718{
4719 int write = 0;
4720 struct peer *peer;
4721 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004722 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004723
4724 bgp_config_write_network (vty, bgp, afi, safi, &write);
4725
4726 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
4727
paul1eb8ef22005-04-07 07:30:20 +00004728 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004729 {
4730 if (group->conf->afc[afi][safi])
4731 {
4732 bgp_config_write_family_header (vty, afi, safi, &write);
4733 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
4734 }
4735 }
paul1eb8ef22005-04-07 07:30:20 +00004736 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004737 {
4738 if (peer->afc[afi][safi])
4739 {
4740 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4741 {
4742 bgp_config_write_family_header (vty, afi, safi, &write);
4743 bgp_config_write_peer (vty, bgp, peer, afi, safi);
4744 }
4745 }
4746 }
4747 if (write)
4748 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
4749
4750 return write;
4751}
4752
4753int
4754bgp_config_write (struct vty *vty)
4755{
4756 int write = 0;
4757 struct bgp *bgp;
4758 struct peer_group *group;
4759 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004760 struct listnode *node, *nnode;
4761 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00004762
4763 /* BGP Multiple instance. */
4764 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4765 {
4766 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
4767 write++;
4768 }
4769
4770 /* BGP Config type. */
4771 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4772 {
4773 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
4774 write++;
4775 }
4776
4777 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004778 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004779 {
4780 if (write)
4781 vty_out (vty, "!%s", VTY_NEWLINE);
4782
4783 /* Router bgp ASN */
4784 vty_out (vty, "router bgp %d", bgp->as);
4785
4786 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4787 {
4788 if (bgp->name)
4789 vty_out (vty, " view %s", bgp->name);
4790 }
4791 vty_out (vty, "%s", VTY_NEWLINE);
4792
4793 /* No Synchronization */
4794 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4795 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
4796
4797 /* BGP fast-external-failover. */
4798 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
4799 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
4800
4801 /* BGP router ID. */
4802 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
4803 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
4804 VTY_NEWLINE);
4805
paul848973c2003-08-13 00:32:49 +00004806 /* BGP log-neighbor-changes. */
4807 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
4808 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
4809
paul718e3742002-12-13 20:15:29 +00004810 /* BGP configuration. */
4811 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
4812 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
4813
4814 /* BGP default ipv4-unicast. */
4815 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4816 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
4817
4818 /* BGP default local-preference. */
4819 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
4820 vty_out (vty, " bgp default local-preference %d%s",
4821 bgp->default_local_pref, VTY_NEWLINE);
4822
4823 /* BGP client-to-client reflection. */
4824 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
4825 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
4826
4827 /* BGP cluster ID. */
4828 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
4829 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
4830 VTY_NEWLINE);
4831
hassoe0701b72004-05-20 09:19:34 +00004832 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00004833 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00004834 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
4835 VTY_NEWLINE);
4836
4837 /* Confederation peer */
4838 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00004839 {
hassoe0701b72004-05-20 09:19:34 +00004840 int i;
paul718e3742002-12-13 20:15:29 +00004841
hassoe0701b72004-05-20 09:19:34 +00004842 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00004843
hassoe0701b72004-05-20 09:19:34 +00004844 for (i = 0; i < bgp->confed_peers_cnt; i++)
4845 vty_out(vty, " %d", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00004846
hassoe0701b72004-05-20 09:19:34 +00004847 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004848 }
4849
4850 /* BGP enforce-first-as. */
4851 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
4852 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
4853
4854 /* BGP deterministic-med. */
4855 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
4856 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00004857
4858 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00004859 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
4860 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
4861 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00004862 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
4863 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
4864
paul718e3742002-12-13 20:15:29 +00004865 /* BGP bestpath method. */
4866 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
4867 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00004868 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
4869 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004870 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
4871 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
4872 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
4873 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4874 {
4875 vty_out (vty, " bgp bestpath med");
4876 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
4877 vty_out (vty, " confed");
4878 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4879 vty_out (vty, " missing-as-worst");
4880 vty_out (vty, "%s", VTY_NEWLINE);
4881 }
4882
4883 /* BGP network import check. */
4884 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
4885 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
4886
4887 /* BGP scan interval. */
4888 bgp_config_write_scan_time (vty);
4889
4890 /* BGP flag dampening. */
4891 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
4892 BGP_CONFIG_DAMPENING))
4893 bgp_config_write_damp (vty);
4894
4895 /* BGP static route configuration. */
4896 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4897
4898 /* BGP redistribute configuration. */
4899 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4900
4901 /* BGP timers configuration. */
4902 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
4903 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
4904 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
4905 bgp->default_holdtime, VTY_NEWLINE);
4906
4907 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00004908 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004909 {
4910 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
4911 }
4912
4913 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004914 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004915 {
4916 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4917 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
4918 }
4919
4920 /* Distance configuration. */
4921 bgp_config_write_distance (vty, bgp);
4922
4923 /* No auto-summary */
4924 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4925 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
4926
4927 /* IPv4 multicast configuration. */
4928 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
4929
4930 /* IPv4 VPN configuration. */
4931 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
4932
4933 /* IPv6 unicast configuration. */
4934 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
4935
Paul Jakma37a217a2007-04-10 19:20:29 +00004936 /* IPv6 multicast configuration. */
4937 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_MULTICAST);
4938
paul718e3742002-12-13 20:15:29 +00004939 write++;
4940 }
4941 return write;
4942}
4943
4944void
paul94f2b392005-06-28 12:44:16 +00004945bgp_master_init (void)
paul718e3742002-12-13 20:15:29 +00004946{
4947 memset (&bgp_master, 0, sizeof (struct bgp_master));
4948
4949 bm = &bgp_master;
4950 bm->bgp = list_new ();
4951 bm->port = BGP_PORT_DEFAULT;
4952 bm->master = thread_master_create ();
4953 bm->start_time = time (NULL);
4954}
paul200df112005-06-01 11:17:05 +00004955
paul718e3742002-12-13 20:15:29 +00004956
4957void
paul94f2b392005-06-28 12:44:16 +00004958bgp_init (void)
paul718e3742002-12-13 20:15:29 +00004959{
paul718e3742002-12-13 20:15:29 +00004960 /* BGP VTY commands installation. */
4961 bgp_vty_init ();
4962
4963 /* Create BGP server socket. */
Paul Jakma3a02d1f2007-11-01 14:29:11 +00004964 bgp_socket (NULL, bm->port, bm->address);
paul718e3742002-12-13 20:15:29 +00004965
4966 /* Init zebra. */
4967 bgp_zebra_init ();
4968
4969 /* BGP inits. */
4970 bgp_attr_init ();
4971 bgp_debug_init ();
4972 bgp_dump_init ();
4973 bgp_route_init ();
4974 bgp_route_map_init ();
4975 bgp_scan_init ();
4976 bgp_mplsvpn_init ();
4977
4978 /* Access list initialize. */
4979 access_list_init ();
4980 access_list_add_hook (peer_distribute_update);
4981 access_list_delete_hook (peer_distribute_update);
4982
4983 /* Filter list initialize. */
4984 bgp_filter_init ();
4985 as_list_add_hook (peer_aslist_update);
4986 as_list_delete_hook (peer_aslist_update);
4987
4988 /* Prefix list initialize.*/
4989 prefix_list_init ();
4990 prefix_list_add_hook (peer_prefix_list_update);
4991 prefix_list_delete_hook (peer_prefix_list_update);
4992
4993 /* Community list initialize. */
4994 bgp_clist = community_list_init ();
4995
4996#ifdef HAVE_SNMP
4997 bgp_snmp_init ();
4998#endif /* HAVE_SNMP */
4999}
paul545acaf2004-04-20 15:13:15 +00005000
5001void
5002bgp_terminate ()
5003{
paul545acaf2004-04-20 15:13:15 +00005004 struct bgp *bgp;
5005 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00005006 struct listnode *node, *nnode;
5007 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00005008
paul1eb8ef22005-04-07 07:30:20 +00005009 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
5010 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00005011 if (peer->status == Established)
5012 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
5013 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00005014
paul545acaf2004-04-20 15:13:15 +00005015 bgp_cleanup_routes ();
paule210cf92005-06-15 19:15:35 +00005016 if (bm->process_main_queue)
5017 work_queue_free (bm->process_main_queue);
5018 if (bm->process_rsclient_queue)
5019 work_queue_free (bm->process_rsclient_queue);
paul545acaf2004-04-20 15:13:15 +00005020}
5021