blob: 279c54671b00ce52f08e0b8c983eca47be098064 [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"
37
38#include "bgpd/bgpd.h"
39#include "bgpd/bgp_table.h"
40#include "bgpd/bgp_aspath.h"
41#include "bgpd/bgp_route.h"
42#include "bgpd/bgp_dump.h"
43#include "bgpd/bgp_debug.h"
44#include "bgpd/bgp_community.h"
45#include "bgpd/bgp_attr.h"
46#include "bgpd/bgp_regex.h"
47#include "bgpd/bgp_clist.h"
48#include "bgpd/bgp_fsm.h"
49#include "bgpd/bgp_packet.h"
50#include "bgpd/bgp_zebra.h"
51#include "bgpd/bgp_open.h"
52#include "bgpd/bgp_filter.h"
53#include "bgpd/bgp_nexthop.h"
54#include "bgpd/bgp_damp.h"
55#include "bgpd/bgp_mplsvpn.h"
56#include "bgpd/bgp_advertise.h"
57#include "bgpd/bgp_network.h"
58#include "bgpd/bgp_vty.h"
59#ifdef HAVE_SNMP
60#include "bgpd/bgp_snmp.h"
61#endif /* HAVE_SNMP */
62
63/* BGP process wide configuration. */
64static struct bgp_master bgp_master;
65
hasso18a6dce2004-10-03 18:18:34 +000066extern struct in_addr router_id_zebra;
67
paul718e3742002-12-13 20:15:29 +000068/* BGP process wide configuration pointer to export. */
69struct bgp_master *bm;
70
71/* BGP community-list. */
72struct community_list_handler *bgp_clist;
73
74/* BGP global flag manipulation. */
75int
76bgp_option_set (int flag)
77{
78 switch (flag)
79 {
80 case BGP_OPT_NO_FIB:
81 case BGP_OPT_MULTIPLE_INSTANCE:
82 case BGP_OPT_CONFIG_CISCO:
83 SET_FLAG (bm->options, flag);
84 break;
85 default:
86 return BGP_ERR_INVALID_FLAG;
87 break;
88 }
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;
107 break;
108 }
109 return 0;
110}
111
112int
113bgp_option_check (int flag)
114{
115 return CHECK_FLAG (bm->options, flag);
116}
117
118/* BGP flag manipulation. */
119int
120bgp_flag_set (struct bgp *bgp, int flag)
121{
122 SET_FLAG (bgp->flags, flag);
123 return 0;
124}
125
126int
127bgp_flag_unset (struct bgp *bgp, int flag)
128{
129 UNSET_FLAG (bgp->flags, flag);
130 return 0;
131}
132
133int
134bgp_flag_check (struct bgp *bgp, int flag)
135{
136 return CHECK_FLAG (bgp->flags, flag);
137}
138
139/* Internal function to set BGP structure configureation flag. */
140static void
141bgp_config_set (struct bgp *bgp, int config)
142{
143 SET_FLAG (bgp->config, config);
144}
145
146static void
147bgp_config_unset (struct bgp *bgp, int config)
148{
149 UNSET_FLAG (bgp->config, config);
150}
151
152static int
153bgp_config_check (struct bgp *bgp, int config)
154{
155 return CHECK_FLAG (bgp->config, config);
156}
157
158/* Set BGP router identifier. */
159int
160bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
161{
162 struct peer *peer;
163 struct listnode *nn;
164
165 if (bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID)
166 && IPV4_ADDR_SAME (&bgp->router_id, id))
167 return 0;
168
169 IPV4_ADDR_COPY (&bgp->router_id, id);
170 bgp_config_set (bgp, BGP_CONFIG_ROUTER_ID);
171
172 /* Set all peer's local identifier with this value. */
173 LIST_LOOP (bgp->peer, peer, nn)
174 {
175 IPV4_ADDR_COPY (&peer->local_id, id);
176
177 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000178 {
179 peer->last_reset = PEER_DOWN_RID_CHANGE;
180 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
181 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
182 }
paul718e3742002-12-13 20:15:29 +0000183 }
184 return 0;
185}
186
paul718e3742002-12-13 20:15:29 +0000187/* BGP's cluster-id control. */
188int
189bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
190{
191 struct peer *peer;
192 struct listnode *nn;
193
194 if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)
195 && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id))
196 return 0;
197
198 IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id);
199 bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID);
200
201 /* Clear all IBGP peer. */
202 LIST_LOOP (bgp->peer, peer, nn)
203 {
204 if (peer_sort (peer) != BGP_PEER_IBGP)
205 continue;
206
207 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000208 {
209 peer->last_reset = PEER_DOWN_CLID_CHANGE;
210 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
211 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
212 }
paul718e3742002-12-13 20:15:29 +0000213 }
214 return 0;
215}
216
217int
218bgp_cluster_id_unset (struct bgp *bgp)
219{
220 struct peer *peer;
221 struct listnode *nn;
222
223 if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID))
224 return 0;
225
226 bgp->cluster_id.s_addr = 0;
227 bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID);
228
229 /* Clear all IBGP peer. */
230 LIST_LOOP (bgp->peer, peer, nn)
231 {
232 if (peer_sort (peer) != BGP_PEER_IBGP)
233 continue;
234
235 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000236 {
237 peer->last_reset = PEER_DOWN_CLID_CHANGE;
238 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
239 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
240 }
paul718e3742002-12-13 20:15:29 +0000241 }
242 return 0;
243}
244
245/* BGP timer configuration. */
246int
247bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
248{
249 bgp->default_keepalive = (keepalive < holdtime / 3
250 ? keepalive : holdtime / 3);
251 bgp->default_holdtime = holdtime;
252
253 return 0;
254}
255
256int
257bgp_timers_unset (struct bgp *bgp)
258{
259 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
260 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
261
262 return 0;
263}
264
265/* BGP confederation configuration. */
266int
267bgp_confederation_id_set (struct bgp *bgp, as_t as)
268{
269 struct peer *peer;
270 struct listnode *nn;
271 int already_confed;
272
273 if (as == 0)
274 return BGP_ERR_INVALID_AS;
275
276 /* Remember - were we doing confederation before? */
277 already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);
278 bgp->confed_id = as;
279 bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);
280
281 /* If we were doing confederation already, this is just an external
282 AS change. Just Reset EBGP sessions, not CONFED sessions. If we
283 were not doing confederation before, reset all EBGP sessions. */
284 LIST_LOOP (bgp->peer, peer, nn)
285 {
286 /* We're looking for peers who's AS is not local or part of our
287 confederation. */
288 if (already_confed)
289 {
290 if (peer_sort (peer) == BGP_PEER_EBGP)
291 {
292 peer->local_as = as;
293 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000294 {
295 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
296 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
297 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
298 }
299
paul718e3742002-12-13 20:15:29 +0000300 else
301 BGP_EVENT_ADD (peer, BGP_Stop);
302 }
303 }
304 else
305 {
306 /* Not doign confederation before, so reset every non-local
307 session */
308 if (peer_sort (peer) != BGP_PEER_IBGP)
309 {
310 /* Reset the local_as to be our EBGP one */
311 if (peer_sort (peer) == BGP_PEER_EBGP)
312 peer->local_as = as;
313 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000314 {
315 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
316 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
317 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
318 }
paul718e3742002-12-13 20:15:29 +0000319 else
320 BGP_EVENT_ADD (peer, BGP_Stop);
321 }
322 }
323 }
324 return 0;
325}
326
327int
328bgp_confederation_id_unset (struct bgp *bgp)
329{
330 struct peer *peer;
331 struct listnode *nn;
332
333 bgp->confed_id = 0;
334 bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
335
336 LIST_LOOP (bgp->peer, peer, nn)
337 {
338 /* We're looking for peers who's AS is not local */
339 if (peer_sort (peer) != BGP_PEER_IBGP)
340 {
341 peer->local_as = bgp->as;
342 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000343 {
344 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
345 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
346 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
347 }
348
paul718e3742002-12-13 20:15:29 +0000349 else
350 BGP_EVENT_ADD (peer, BGP_Stop);
351 }
352 }
353 return 0;
354}
355
356/* Is an AS part of the confed or not? */
357int
358bgp_confederation_peers_check (struct bgp *bgp, as_t as)
359{
360 int i;
361
362 if (! bgp)
363 return 0;
364
365 for (i = 0; i < bgp->confed_peers_cnt; i++)
366 if (bgp->confed_peers[i] == as)
367 return 1;
368
369 return 0;
370}
371
372/* Add an AS to the confederation set. */
373int
374bgp_confederation_peers_add (struct bgp *bgp, as_t as)
375{
376 struct peer *peer;
377 struct listnode *nn;
378
379 if (! bgp)
380 return BGP_ERR_INVALID_BGP;
381
382 if (bgp->as == as)
383 return BGP_ERR_INVALID_AS;
384
385 if (bgp_confederation_peers_check (bgp, as))
386 return -1;
387
388 if (bgp->confed_peers)
389 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
390 bgp->confed_peers,
391 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
392 else
393 bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST,
394 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
395
396 bgp->confed_peers[bgp->confed_peers_cnt] = as;
397 bgp->confed_peers_cnt++;
398
399 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
400 {
401 LIST_LOOP (bgp->peer, peer, nn)
402 {
403 if (peer->as == as)
404 {
405 peer->local_as = bgp->as;
406 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000407 {
408 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
409 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
410 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
411 }
paul718e3742002-12-13 20:15:29 +0000412 else
413 BGP_EVENT_ADD (peer, BGP_Stop);
414 }
415 }
416 }
417 return 0;
418}
419
420/* Delete an AS from the confederation set. */
421int
422bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
423{
424 int i;
425 int j;
426 struct peer *peer;
427 struct listnode *nn;
428
429 if (! bgp)
430 return -1;
431
432 if (! bgp_confederation_peers_check (bgp, as))
433 return -1;
434
435 for (i = 0; i < bgp->confed_peers_cnt; i++)
436 if (bgp->confed_peers[i] == as)
437 for(j = i + 1; j < bgp->confed_peers_cnt; j++)
438 bgp->confed_peers[j - 1] = bgp->confed_peers[j];
439
440 bgp->confed_peers_cnt--;
441
442 if (bgp->confed_peers_cnt == 0)
443 {
444 if (bgp->confed_peers)
445 XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
446 bgp->confed_peers = NULL;
447 }
448 else
449 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
450 bgp->confed_peers,
451 bgp->confed_peers_cnt * sizeof (as_t));
452
453 /* Now reset any peer who's remote AS has just been removed from the
454 CONFED */
455 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
456 {
457 LIST_LOOP (bgp->peer, peer, nn)
458 {
459 if (peer->as == as)
460 {
461 peer->local_as = bgp->confed_id;
462 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000463 {
464 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
465 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
466 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
467 }
paul718e3742002-12-13 20:15:29 +0000468 else
469 BGP_EVENT_ADD (peer, BGP_Stop);
470 }
471 }
472 }
473
474 return 0;
475}
476
477/* Local preference configuration. */
478int
479bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
480{
481 if (! bgp)
482 return -1;
483
paul718e3742002-12-13 20:15:29 +0000484 bgp->default_local_pref = local_pref;
485
486 return 0;
487}
488
489int
490bgp_default_local_preference_unset (struct bgp *bgp)
491{
492 if (! bgp)
493 return -1;
494
paul718e3742002-12-13 20:15:29 +0000495 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
496
497 return 0;
498}
499
paulfee0f4c2004-09-13 05:12:46 +0000500/* If peer is RSERVER_CLIENT in at least one address family and is not member
501 of a peer_group for that family, return 1.
502 Used to check wether the peer is included in list bgp->rsclient. */
503int
504peer_rsclient_active (struct peer *peer)
505{
506 int i;
507 int j;
508
509 for (i=AFI_IP; i < AFI_MAX; i++)
510 for (j=SAFI_UNICAST; j < SAFI_MAX; j++)
511 if (CHECK_FLAG(peer->af_flags[i][j], PEER_FLAG_RSERVER_CLIENT)
512 && ! peer->af_group[i][j])
513 return 1;
514 return 0;
515}
516
pauleb821182004-05-01 08:44:08 +0000517/* Peer comparison function for sorting. */
paul718e3742002-12-13 20:15:29 +0000518static int
519peer_cmp (struct peer *p1, struct peer *p2)
520{
pauleb821182004-05-01 08:44:08 +0000521 return sockunion_cmp (&p1->su, &p2->su);
paul718e3742002-12-13 20:15:29 +0000522}
523
524int
525peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
526{
527 return CHECK_FLAG (peer->af_flags[afi][safi], flag);
528}
529
530/* Reset all address family specific configuration. */
531static void
532peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
533{
534 int i;
535 struct bgp_filter *filter;
536 char orf_name[BUFSIZ];
537
538 filter = &peer->filter[afi][safi];
539
540 /* Clear neighbor filter and route-map */
541 for (i = FILTER_IN; i < FILTER_MAX; i++)
542 {
543 if (filter->dlist[i].name)
544 {
545 free (filter->dlist[i].name);
546 filter->dlist[i].name = NULL;
547 }
548 if (filter->plist[i].name)
549 {
550 free (filter->plist[i].name);
551 filter->plist[i].name = NULL;
552 }
553 if (filter->aslist[i].name)
554 {
555 free (filter->aslist[i].name);
556 filter->aslist[i].name = NULL;
557 }
paulfee0f4c2004-09-13 05:12:46 +0000558 }
559 for (i = RMAP_IN; i < RMAP_MAX; i++)
560 {
paul718e3742002-12-13 20:15:29 +0000561 if (filter->map[i].name)
562 {
563 free (filter->map[i].name);
564 filter->map[i].name = NULL;
565 }
566 }
567
568 /* Clear unsuppress map. */
569 if (filter->usmap.name)
570 free (filter->usmap.name);
571 filter->usmap.name = NULL;
572 filter->usmap.map = NULL;
573
574 /* Clear neighbor's all address family flags. */
575 peer->af_flags[afi][safi] = 0;
576
577 /* Clear neighbor's all address family sflags. */
578 peer->af_sflags[afi][safi] = 0;
579
580 /* Clear neighbor's all address family capabilities. */
581 peer->af_cap[afi][safi] = 0;
582
583 /* Clear ORF info */
584 peer->orf_plist[afi][safi] = NULL;
585 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
586 prefix_bgp_orf_remove_all (orf_name);
587
588 /* Set default neighbor send-community. */
589 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
590 {
591 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
592 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
593 }
594
595 /* Clear neighbor default_originate_rmap */
596 if (peer->default_rmap[afi][safi].name)
597 free (peer->default_rmap[afi][safi].name);
598 peer->default_rmap[afi][safi].name = NULL;
599 peer->default_rmap[afi][safi].map = NULL;
600
601 /* Clear neighbor maximum-prefix */
602 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +0000603 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000604}
605
606/* peer global config reset */
607void
608peer_global_config_reset (struct peer *peer)
609{
610 peer->weight = 0;
611 peer->change_local_as = 0;
612 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
613 if (peer->update_source)
614 {
615 sockunion_free (peer->update_source);
616 peer->update_source = NULL;
617 }
618 if (peer->update_if)
619 {
620 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
621 peer->update_if = NULL;
622 }
623
624 if (peer_sort (peer) == BGP_PEER_IBGP)
625 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
626 else
627 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
628
629 peer->flags = 0;
630 peer->config = 0;
631 peer->holdtime = 0;
632 peer->keepalive = 0;
633 peer->connect = 0;
634 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
635}
636
637/* Check peer's AS number and determin is this peer IBGP or EBGP */
638int
639peer_sort (struct peer *peer)
640{
641 struct bgp *bgp;
642
643 bgp = peer->bgp;
644
645 /* Peer-group */
646 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
647 {
648 if (peer->as)
649 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
650 else
651 {
652 struct peer *peer1;
653 peer1 = listnode_head (peer->group->peer);
654 if (peer1)
655 return (peer1->local_as == peer1->as
656 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
657 }
658 return BGP_PEER_INTERNAL;
659 }
660
661 /* Normal peer */
662 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
663 {
664 if (peer->local_as == 0)
665 return BGP_PEER_INTERNAL;
666
667 if (peer->local_as == peer->as)
668 {
669 if (peer->local_as == bgp->confed_id)
670 return BGP_PEER_EBGP;
671 else
672 return BGP_PEER_IBGP;
673 }
674
675 if (bgp_confederation_peers_check (bgp, peer->as))
676 return BGP_PEER_CONFED;
677
678 return BGP_PEER_EBGP;
679 }
680 else
681 {
682 return (peer->local_as == 0
683 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
684 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
685 }
686}
687
688/* Allocate new peer object. */
689static struct peer *
690peer_new ()
691{
692 afi_t afi;
693 safi_t safi;
694 struct peer *peer;
695 struct servent *sp;
696
697 /* Allocate new peer. */
698 peer = XMALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
699 memset (peer, 0, sizeof (struct peer));
700
701 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000702 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000703 peer->v_start = BGP_INIT_START_TIMER;
704 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
705 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
706 peer->status = Idle;
707 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000708 peer->weight = 0;
709
710 /* Set default flags. */
711 for (afi = AFI_IP; afi < AFI_MAX; afi++)
712 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
713 {
714 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
715 {
716 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
717 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
718 }
719 peer->orf_plist[afi][safi] = NULL;
720 }
721 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
722
723 /* Create buffers. */
724 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
725 peer->obuf = stream_fifo_new ();
726 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
727
728 bgp_sync_init (peer);
729
730 /* Get service port number. */
731 sp = getservbyname ("bgp", "tcp");
732 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
733
734 return peer;
735}
736
737/* Create new BGP peer. */
738struct peer *
739peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
740 as_t remote_as, afi_t afi, safi_t safi)
741{
742 int active;
743 struct peer *peer;
744 char buf[SU_ADDRSTRLEN];
745
746 peer = peer_new ();
747 peer->bgp = bgp;
748 peer->su = *su;
749 peer->local_as = local_as;
750 peer->as = remote_as;
751 peer->local_id = bgp->router_id;
752 peer->v_holdtime = bgp->default_holdtime;
753 peer->v_keepalive = bgp->default_keepalive;
754 if (peer_sort (peer) == BGP_PEER_IBGP)
755 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
756 else
757 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
758 listnode_add_sort (bgp->peer, peer);
759
760 active = peer_active (peer);
761
762 if (afi && safi)
763 peer->afc[afi][safi] = 1;
764
765 /* Last read time set */
766 peer->readtime = time (NULL);
767
paul848973c2003-08-13 00:32:49 +0000768 /* Last reset time set */
769 peer->resettime = time (NULL);
770
paul718e3742002-12-13 20:15:29 +0000771 /* Default TTL set. */
772 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
773
774 /* Make peer's address string. */
775 sockunion2str (su, buf, SU_ADDRSTRLEN);
776 peer->host = strdup (buf);
777
778 /* Set up peer's events and timers. */
779 if (! active && peer_active (peer))
780 bgp_timer_set (peer);
781
782 return peer;
783}
784
pauleb821182004-05-01 08:44:08 +0000785/* Make accept BGP peer. Called from bgp_accept (). */
786struct peer *
787peer_create_accept (struct bgp *bgp)
788{
789 struct peer *peer;
790
791 peer = peer_new ();
792 peer->bgp = bgp;
793 listnode_add_sort (bgp->peer, peer);
794
795 return peer;
796}
797
paul718e3742002-12-13 20:15:29 +0000798/* Change peer's AS number. */
799void
800peer_as_change (struct peer *peer, as_t as)
801{
802 int type;
803
804 /* Stop peer. */
805 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
806 {
807 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000808 {
809 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
810 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
811 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
812 }
paul718e3742002-12-13 20:15:29 +0000813 else
814 BGP_EVENT_ADD (peer, BGP_Stop);
815 }
816 type = peer_sort (peer);
817 peer->as = as;
818
paul848973c2003-08-13 00:32:49 +0000819 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
820 && ! bgp_confederation_peers_check (peer->bgp, as)
821 && peer->bgp->as != as)
822 peer->local_as = peer->bgp->confed_id;
823 else
824 peer->local_as = peer->bgp->as;
825
paul718e3742002-12-13 20:15:29 +0000826 /* Advertisement-interval reset */
827 if (peer_sort (peer) == BGP_PEER_IBGP)
828 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
829 else
830 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
831
832 /* TTL reset */
833 if (peer_sort (peer) == BGP_PEER_IBGP)
834 peer->ttl = 255;
835 else if (type == BGP_PEER_IBGP)
836 peer->ttl = 1;
837
838 /* reflector-client reset */
839 if (peer_sort (peer) != BGP_PEER_IBGP)
840 {
841 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
842 PEER_FLAG_REFLECTOR_CLIENT);
843 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
844 PEER_FLAG_REFLECTOR_CLIENT);
845 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
846 PEER_FLAG_REFLECTOR_CLIENT);
847 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
848 PEER_FLAG_REFLECTOR_CLIENT);
849 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
850 PEER_FLAG_REFLECTOR_CLIENT);
851 }
852
853 /* local-as reset */
854 if (peer_sort (peer) != BGP_PEER_EBGP)
855 {
856 peer->change_local_as = 0;
857 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
858 }
859}
860
861/* If peer does not exist, create new one. If peer already exists,
862 set AS number to the peer. */
863int
864peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
865 afi_t afi, safi_t safi)
866{
867 struct peer *peer;
868 as_t local_as;
869
870 peer = peer_lookup (bgp, su);
871
872 if (peer)
873 {
874 /* When this peer is a member of peer-group. */
875 if (peer->group)
876 {
877 if (peer->group->conf->as)
878 {
879 /* Return peer group's AS number. */
880 *as = peer->group->conf->as;
881 return BGP_ERR_PEER_GROUP_MEMBER;
882 }
883 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
884 {
885 if (bgp->as != *as)
886 {
887 *as = peer->as;
888 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
889 }
890 }
891 else
892 {
893 if (bgp->as == *as)
894 {
895 *as = peer->as;
896 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
897 }
898 }
899 }
900
901 /* Existing peer's AS number change. */
902 if (peer->as != *as)
903 peer_as_change (peer, *as);
904 }
905 else
906 {
907
908 /* If the peer is not part of our confederation, and its not an
909 iBGP peer then spoof the source AS */
910 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
911 && ! bgp_confederation_peers_check (bgp, *as)
912 && bgp->as != *as)
913 local_as = bgp->confed_id;
914 else
915 local_as = bgp->as;
916
917 /* If this is IPv4 unicast configuration and "no bgp default
918 ipv4-unicast" is specified. */
919
920 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
921 && afi == AFI_IP && safi == SAFI_UNICAST)
922 peer = peer_create (su, bgp, local_as, *as, 0, 0);
923 else
924 peer = peer_create (su, bgp, local_as, *as, afi, safi);
925 }
926
927 return 0;
928}
929
930/* Activate the peer or peer group for specified AFI and SAFI. */
931int
932peer_activate (struct peer *peer, afi_t afi, safi_t safi)
933{
934 int active;
935
936 if (peer->afc[afi][safi])
937 return 0;
938
939 /* Activate the address family configuration. */
940 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
941 peer->afc[afi][safi] = 1;
942 else
943 {
944 active = peer_active (peer);
945
946 peer->afc[afi][safi] = 1;
947
948 if (! active && peer_active (peer))
949 bgp_timer_set (peer);
950 else
951 {
952 if (peer->status == Established)
953 {
954 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
955 {
956 peer->afc_adv[afi][safi] = 1;
957 bgp_capability_send (peer, afi, safi,
958 CAPABILITY_CODE_MP,
959 CAPABILITY_ACTION_SET);
960 if (peer->afc_recv[afi][safi])
961 {
962 peer->afc_nego[afi][safi] = 1;
963 bgp_announce_route (peer, afi, safi);
964 }
965 }
966 else
hassoe0701b72004-05-20 09:19:34 +0000967 {
968 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
969 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
970 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
971 }
paul718e3742002-12-13 20:15:29 +0000972 }
973 }
974 }
975 return 0;
976}
977
978int
979peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
980{
981 struct peer_group *group;
982 struct peer *peer1;
983 struct listnode *nn;
984
985 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
986 {
987 group = peer->group;
988
989 LIST_LOOP (group->peer, peer1, nn)
990 {
991 if (peer1->af_group[afi][safi])
992 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
993 }
994 }
995 else
996 {
997 if (peer->af_group[afi][safi])
998 return BGP_ERR_PEER_BELONGS_TO_GROUP;
999 }
1000
1001 if (! peer->afc[afi][safi])
1002 return 0;
1003
1004 /* De-activate the address family configuration. */
1005 peer->afc[afi][safi] = 0;
1006 peer_af_flag_reset (peer, afi, safi);
1007
1008 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1009 {
1010 if (peer->status == Established)
1011 {
1012 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1013 {
1014 peer->afc_adv[afi][safi] = 0;
1015 peer->afc_nego[afi][safi] = 0;
1016
1017 if (peer_active_nego (peer))
1018 {
1019 bgp_capability_send (peer, afi, safi,
1020 CAPABILITY_CODE_MP,
1021 CAPABILITY_ACTION_UNSET);
1022 bgp_clear_route (peer, afi, safi);
1023 peer->pcount[afi][safi] = 0;
1024 }
1025 else
hassoe0701b72004-05-20 09:19:34 +00001026 {
1027 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1028 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1029 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1030 }
paul718e3742002-12-13 20:15:29 +00001031 }
1032 else
hassoe0701b72004-05-20 09:19:34 +00001033 {
1034 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1035 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1036 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1037 }
paul718e3742002-12-13 20:15:29 +00001038 }
1039 }
1040 return 0;
1041}
1042
hasso93406d82005-02-02 14:40:33 +00001043void
1044peer_nsf_stop (struct peer *peer)
1045{
1046 afi_t afi;
1047 safi_t safi;
1048
1049 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1050 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1051
1052 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1053 for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
1054 peer->nsf[afi][safi] = 0;
1055
1056 if (peer->t_gr_restart)
1057 {
1058 BGP_TIMER_OFF (peer->t_gr_restart);
1059 if (BGP_DEBUG (events, EVENTS))
1060 zlog_debug ("%s graceful restart timer stopped", peer->host);
1061 }
1062 if (peer->t_gr_stale)
1063 {
1064 BGP_TIMER_OFF (peer->t_gr_stale);
1065 if (BGP_DEBUG (events, EVENTS))
1066 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1067 }
1068 bgp_clear_route_all (peer);
1069}
1070
paul718e3742002-12-13 20:15:29 +00001071/* Delete peer from confguration. */
1072int
1073peer_delete (struct peer *peer)
1074{
1075 int i;
1076 afi_t afi;
1077 safi_t safi;
1078 struct bgp *bgp;
1079 struct bgp_filter *filter;
1080
1081 bgp = peer->bgp;
1082
hasso93406d82005-02-02 14:40:33 +00001083 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1084 peer_nsf_stop (peer);
1085
paul718e3742002-12-13 20:15:29 +00001086 /* If this peer belongs to peer group. Clearn up the
1087 relationship. */
1088 if (peer->group)
1089 {
1090 listnode_delete (peer->group->peer, peer);
1091 peer->group = NULL;
1092 }
1093
1094 /* Withdraw all information from routing table. We can not use
1095 BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1096 executed after peer structure is deleted. */
hassoe0701b72004-05-20 09:19:34 +00001097 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001098 bgp_stop (peer);
1099 bgp_fsm_change_status (peer, Idle);
1100
1101 /* Stop all timers. */
1102 BGP_TIMER_OFF (peer->t_start);
1103 BGP_TIMER_OFF (peer->t_connect);
1104 BGP_TIMER_OFF (peer->t_holdtime);
1105 BGP_TIMER_OFF (peer->t_keepalive);
1106 BGP_TIMER_OFF (peer->t_asorig);
1107 BGP_TIMER_OFF (peer->t_routeadv);
hasso0a486e52005-02-01 20:57:17 +00001108 BGP_TIMER_OFF (peer->t_pmax_restart);
hasso93406d82005-02-02 14:40:33 +00001109 BGP_TIMER_OFF (peer->t_gr_restart);
1110 BGP_TIMER_OFF (peer->t_gr_stale);
paul718e3742002-12-13 20:15:29 +00001111
1112 /* Delete from all peer list. */
1113 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
paulfee0f4c2004-09-13 05:12:46 +00001114 {
paul718e3742002-12-13 20:15:29 +00001115 listnode_delete (bgp->peer, peer);
paulfee0f4c2004-09-13 05:12:46 +00001116 if (peer_rsclient_active (peer))
1117 listnode_delete (bgp->rsclient, peer);
1118 }
1119
1120 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1121 member of a peer_group. */
1122 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1123 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1124 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
1125 bgp_table_finish (peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001126
1127 /* Buffer. */
1128 if (peer->ibuf)
1129 stream_free (peer->ibuf);
1130
1131 if (peer->obuf)
1132 stream_fifo_free (peer->obuf);
1133
1134 if (peer->work)
1135 stream_free (peer->work);
1136
1137 /* Free allocated host character. */
1138 if (peer->host)
1139 free (peer->host);
1140
1141 /* Local and remote addresses. */
1142 if (peer->su_local)
1143 XFREE (MTYPE_TMP, peer->su_local);
1144 if (peer->su_remote)
1145 XFREE (MTYPE_TMP, peer->su_remote);
1146
1147 /* Peer description string. */
1148 if (peer->desc)
1149 XFREE (MTYPE_TMP, peer->desc);
1150
1151 bgp_sync_delete (peer);
1152
1153 /* Free filter related memory. */
1154 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1155 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1156 {
1157 filter = &peer->filter[afi][safi];
1158
1159 for (i = FILTER_IN; i < FILTER_MAX; i++)
1160 {
1161 if (filter->dlist[i].name)
1162 free (filter->dlist[i].name);
1163 if (filter->plist[i].name)
1164 free (filter->plist[i].name);
1165 if (filter->aslist[i].name)
1166 free (filter->aslist[i].name);
paulfee0f4c2004-09-13 05:12:46 +00001167 }
1168 for (i = RMAP_IN; i < RMAP_MAX; i++)
1169 {
paul718e3742002-12-13 20:15:29 +00001170 if (filter->map[i].name)
1171 free (filter->map[i].name);
1172 }
1173
1174 if (filter->usmap.name)
1175 free (filter->usmap.name);
1176
1177 if (peer->default_rmap[afi][safi].name)
1178 free (peer->default_rmap[afi][safi].name);
1179 }
1180
1181 /* Update source configuration. */
1182 if (peer->update_source)
1183 {
1184 sockunion_free (peer->update_source);
1185 peer->update_source = NULL;
1186 }
1187 if (peer->update_if)
1188 {
1189 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1190 peer->update_if = NULL;
1191 }
1192
1193 /* Free peer structure. */
1194 XFREE (MTYPE_BGP_PEER, peer);
1195
1196 return 0;
1197}
1198
1199int
1200peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1201{
1202 return strcmp (g1->name, g2->name);
1203}
1204
1205/* If peer is configured at least one address family return 1. */
1206int
1207peer_group_active (struct peer *peer)
1208{
1209 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1210 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1211 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1212 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1213 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1214 return 1;
1215 return 0;
1216}
1217
1218/* Peer group cofiguration. */
1219static struct peer_group *
1220peer_group_new ()
1221{
1222 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1223 sizeof (struct peer_group));
1224}
1225
1226void
1227peer_group_free (struct peer_group *group)
1228{
1229 XFREE (MTYPE_PEER_GROUP, group);
1230}
1231
1232struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001233peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001234{
1235 struct peer_group *group;
1236 struct listnode *nn;
1237
1238 LIST_LOOP (bgp->group, group, nn)
1239 {
1240 if (strcmp (group->name, name) == 0)
1241 return group;
1242 }
1243 return NULL;
1244}
1245
1246struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001247peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001248{
1249 struct peer_group *group;
1250
1251 group = peer_group_lookup (bgp, name);
1252 if (group)
1253 return group;
1254
1255 group = peer_group_new ();
1256 group->bgp = bgp;
1257 group->name = strdup (name);
1258 group->peer = list_new ();
1259 group->conf = peer_new ();
1260 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1261 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
1262 group->conf->host = strdup (name);
1263 group->conf->bgp = bgp;
1264 group->conf->group = group;
1265 group->conf->as = 0;
1266 group->conf->ttl = 1;
1267 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1268 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1269 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1270 group->conf->keepalive = 0;
1271 group->conf->holdtime = 0;
1272 group->conf->connect = 0;
1273 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1274 listnode_add_sort (bgp->group, group);
1275
1276 return 0;
1277}
1278
1279void
1280peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1281 afi_t afi, safi_t safi)
1282{
1283 int in = FILTER_IN;
1284 int out = FILTER_OUT;
1285 struct peer *conf;
1286 struct bgp_filter *pfilter;
1287 struct bgp_filter *gfilter;
1288
1289 conf = group->conf;
1290 pfilter = &peer->filter[afi][safi];
1291 gfilter = &conf->filter[afi][safi];
1292
1293 /* remote-as */
1294 if (conf->as)
1295 peer->as = conf->as;
1296
1297 /* remote-as */
1298 if (conf->change_local_as)
1299 peer->change_local_as = conf->change_local_as;
1300
1301 /* TTL */
1302 peer->ttl = conf->ttl;
1303
1304 /* Weight */
1305 peer->weight = conf->weight;
1306
1307 /* peer flags apply */
1308 peer->flags = conf->flags;
1309 /* peer af_flags apply */
1310 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1311 /* peer config apply */
1312 peer->config = conf->config;
1313
1314 /* peer timers apply */
1315 peer->holdtime = conf->holdtime;
1316 peer->keepalive = conf->keepalive;
1317 peer->connect = conf->connect;
1318 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1319 peer->v_connect = conf->connect;
1320 else
1321 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1322
1323 /* advertisement-interval reset */
1324 if (peer_sort (peer) == BGP_PEER_IBGP)
1325 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1326 else
1327 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1328
1329 /* maximum-prefix */
1330 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001331 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001332 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001333
1334 /* allowas-in */
1335 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1336
paulfee0f4c2004-09-13 05:12:46 +00001337 /* route-server-client */
1338 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1339 {
1340 /* Make peer's RIB point to group's RIB. */
1341 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1342
1343 /* Import policy. */
1344 if (pfilter->map[RMAP_IMPORT].name)
1345 free (pfilter->map[RMAP_IMPORT].name);
1346 if (gfilter->map[RMAP_IMPORT].name)
1347 {
1348 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1349 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1350 }
1351 else
1352 {
1353 pfilter->map[RMAP_IMPORT].name = NULL;
1354 pfilter->map[RMAP_IMPORT].map = NULL;
1355 }
1356
1357 /* Export policy. */
1358 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1359 {
1360 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1361 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1362 }
1363 }
1364
paul718e3742002-12-13 20:15:29 +00001365 /* default-originate route-map */
1366 if (conf->default_rmap[afi][safi].name)
1367 {
1368 if (peer->default_rmap[afi][safi].name)
1369 free (peer->default_rmap[afi][safi].name);
1370 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1371 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1372 }
1373
1374 /* update-source apply */
1375 if (conf->update_source)
1376 {
1377 if (peer->update_source)
1378 sockunion_free (peer->update_source);
1379 if (peer->update_if)
1380 {
1381 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1382 peer->update_if = NULL;
1383 }
1384 peer->update_source = sockunion_dup (conf->update_source);
1385 }
1386 else if (conf->update_if)
1387 {
1388 if (peer->update_if)
1389 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1390 if (peer->update_source)
1391 {
1392 sockunion_free (peer->update_source);
1393 peer->update_source = NULL;
1394 }
1395 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1396 }
1397
1398 /* inbound filter apply */
1399 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1400 {
1401 if (pfilter->dlist[in].name)
1402 free (pfilter->dlist[in].name);
1403 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1404 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1405 }
1406 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1407 {
1408 if (pfilter->plist[in].name)
1409 free (pfilter->plist[in].name);
1410 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1411 pfilter->plist[in].plist = gfilter->plist[in].plist;
1412 }
1413 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1414 {
1415 if (pfilter->aslist[in].name)
1416 free (pfilter->aslist[in].name);
1417 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1418 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1419 }
paulfee0f4c2004-09-13 05:12:46 +00001420 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001421 {
paulfee0f4c2004-09-13 05:12:46 +00001422 if (pfilter->map[RMAP_IN].name)
1423 free (pfilter->map[RMAP_IN].name);
1424 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1425 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001426 }
1427
1428 /* outbound filter apply */
1429 if (gfilter->dlist[out].name)
1430 {
1431 if (pfilter->dlist[out].name)
1432 free (pfilter->dlist[out].name);
1433 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1434 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1435 }
1436 else
1437 {
1438 if (pfilter->dlist[out].name)
1439 free (pfilter->dlist[out].name);
1440 pfilter->dlist[out].name = NULL;
1441 pfilter->dlist[out].alist = NULL;
1442 }
1443 if (gfilter->plist[out].name)
1444 {
1445 if (pfilter->plist[out].name)
1446 free (pfilter->plist[out].name);
1447 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1448 pfilter->plist[out].plist = gfilter->plist[out].plist;
1449 }
1450 else
1451 {
1452 if (pfilter->plist[out].name)
1453 free (pfilter->plist[out].name);
1454 pfilter->plist[out].name = NULL;
1455 pfilter->plist[out].plist = NULL;
1456 }
1457 if (gfilter->aslist[out].name)
1458 {
1459 if (pfilter->aslist[out].name)
1460 free (pfilter->aslist[out].name);
1461 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1462 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1463 }
1464 else
1465 {
1466 if (pfilter->aslist[out].name)
1467 free (pfilter->aslist[out].name);
1468 pfilter->aslist[out].name = NULL;
1469 pfilter->aslist[out].aslist = NULL;
1470 }
paulfee0f4c2004-09-13 05:12:46 +00001471 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001472 {
paulfee0f4c2004-09-13 05:12:46 +00001473 if (pfilter->map[RMAP_OUT].name)
1474 free (pfilter->map[RMAP_OUT].name);
1475 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1476 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001477 }
1478 else
1479 {
paulfee0f4c2004-09-13 05:12:46 +00001480 if (pfilter->map[RMAP_OUT].name)
1481 free (pfilter->map[RMAP_OUT].name);
1482 pfilter->map[RMAP_OUT].name = NULL;
1483 pfilter->map[RMAP_OUT].map = NULL;
1484 }
1485
1486 /* RS-client's import/export route-maps. */
1487 if (gfilter->map[RMAP_IMPORT].name)
1488 {
1489 if (pfilter->map[RMAP_IMPORT].name)
1490 free (pfilter->map[RMAP_IMPORT].name);
1491 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1492 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1493 }
1494 else
1495 {
1496 if (pfilter->map[RMAP_IMPORT].name)
1497 free (pfilter->map[RMAP_IMPORT].name);
1498 pfilter->map[RMAP_IMPORT].name = NULL;
1499 pfilter->map[RMAP_IMPORT].map = NULL;
1500 }
1501 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1502 {
1503 if (pfilter->map[RMAP_EXPORT].name)
1504 free (pfilter->map[RMAP_EXPORT].name);
1505 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1506 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001507 }
1508
1509 if (gfilter->usmap.name)
1510 {
1511 if (pfilter->usmap.name)
1512 free (pfilter->usmap.name);
1513 pfilter->usmap.name = strdup (gfilter->usmap.name);
1514 pfilter->usmap.map = gfilter->usmap.map;
1515 }
1516 else
1517 {
1518 if (pfilter->usmap.name)
1519 free (pfilter->usmap.name);
1520 pfilter->usmap.name = NULL;
1521 pfilter->usmap.map = NULL;
1522 }
1523}
1524
1525/* Peer group's remote AS configuration. */
1526int
paulfd79ac92004-10-13 05:06:08 +00001527peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001528{
1529 struct peer_group *group;
1530 struct peer *peer;
1531 struct listnode *nn;
1532
1533 group = peer_group_lookup (bgp, group_name);
1534 if (! group)
1535 return -1;
1536
1537 if (group->conf->as == *as)
1538 return 0;
1539
1540 /* When we setup peer-group AS number all peer group member's AS
1541 number must be updated to same number. */
1542 peer_as_change (group->conf, *as);
1543
1544 LIST_LOOP (group->peer, peer, nn)
1545 {
1546 if (peer->as != *as)
1547 peer_as_change (peer, *as);
1548 }
1549
1550 return 0;
1551}
1552
1553int
1554peer_group_delete (struct peer_group *group)
1555{
1556 struct bgp *bgp;
1557 struct peer *peer;
1558 struct listnode *nn;
1559
1560 bgp = group->bgp;
1561
1562 LIST_LOOP (group->peer, peer, nn)
1563 {
1564 peer->group = NULL;
1565 peer_delete (peer);
1566 }
1567 list_delete (group->peer);
1568
1569 free (group->name);
1570 group->name = NULL;
1571
1572 group->conf->group = NULL;
1573 peer_delete (group->conf);
1574
1575 /* Delete from all peer_group list. */
1576 listnode_delete (bgp->group, group);
1577
1578 peer_group_free (group);
1579
1580 return 0;
1581}
1582
1583int
1584peer_group_remote_as_delete (struct peer_group *group)
1585{
1586 struct peer *peer;
1587 struct listnode *nn;
1588
1589 if (! group->conf->as)
1590 return 0;
1591
1592 LIST_LOOP (group->peer, peer, nn)
1593 {
1594 peer->group = NULL;
1595 peer_delete (peer);
1596 }
1597 list_delete_all_node (group->peer);
1598
1599 group->conf->as = 0;
1600
1601 return 0;
1602}
1603
1604/* Bind specified peer to peer group. */
1605int
1606peer_group_bind (struct bgp *bgp, union sockunion *su,
1607 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1608{
1609 struct peer *peer;
1610 int first_member = 0;
1611
1612 /* Check peer group's address family. */
1613 if (! group->conf->afc[afi][safi])
1614 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1615
1616 /* Lookup the peer. */
1617 peer = peer_lookup (bgp, su);
1618
1619 /* Create a new peer. */
1620 if (! peer)
1621 {
1622 if (! group->conf->as)
1623 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1624
1625 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1626 peer->group = group;
1627 peer->af_group[afi][safi] = 1;
1628 listnode_add (group->peer, peer);
1629 peer_group2peer_config_copy (group, peer, afi, safi);
1630
1631 return 0;
1632 }
1633
1634 /* When the peer already belongs to peer group, check the consistency. */
1635 if (peer->af_group[afi][safi])
1636 {
1637 if (strcmp (peer->group->name, group->name) != 0)
1638 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1639
1640 return 0;
1641 }
1642
1643 /* Check current peer group configuration. */
1644 if (peer_group_active (peer)
1645 && strcmp (peer->group->name, group->name) != 0)
1646 return BGP_ERR_PEER_GROUP_MISMATCH;
1647
1648 if (! group->conf->as)
1649 {
1650 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1651 && peer_sort (group->conf) != peer_sort (peer))
1652 {
1653 if (as)
1654 *as = peer->as;
1655 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1656 }
1657
1658 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1659 first_member = 1;
1660 }
1661
1662 peer->af_group[afi][safi] = 1;
1663 peer->afc[afi][safi] = 1;
1664 if (! peer->group)
1665 {
1666 peer->group = group;
1667 listnode_add (group->peer, peer);
1668 }
1669
1670 if (first_member)
1671 {
1672 /* Advertisement-interval reset */
1673 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1674 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1675 else
1676 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1677
1678 /* ebgp-multihop reset */
1679 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1680 group->conf->ttl = 255;
1681
1682 /* local-as reset */
1683 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1684 {
1685 group->conf->change_local_as = 0;
1686 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1687 }
1688 }
paulfee0f4c2004-09-13 05:12:46 +00001689
1690 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1691 {
1692 /* If it's not configured as RSERVER_CLIENT in any other address
1693 family, without being member of a peer_group, remove it from
1694 list bgp->rsclient.*/
1695 if (! peer_rsclient_active (peer))
1696 listnode_delete (bgp->rsclient, peer);
1697
1698 bgp_table_finish (peer->rib[afi][safi]);
1699
1700 /* Import policy. */
1701 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1702 {
1703 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1704 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1705 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1706 }
1707
1708 /* Export policy. */
1709 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1710 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1711 {
1712 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1713 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1714 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1715 }
1716 }
1717
paul718e3742002-12-13 20:15:29 +00001718 peer_group2peer_config_copy (group, peer, afi, safi);
1719
1720 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001721 {
1722 peer->last_reset = PEER_DOWN_RMAP_BIND;
1723 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1724 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1725 }
paul718e3742002-12-13 20:15:29 +00001726 else
1727 BGP_EVENT_ADD (peer, BGP_Stop);
1728
1729 return 0;
1730}
1731
1732int
1733peer_group_unbind (struct bgp *bgp, struct peer *peer,
1734 struct peer_group *group, afi_t afi, safi_t safi)
1735{
1736 if (! peer->af_group[afi][safi])
1737 return 0;
1738
1739 if (group != peer->group)
1740 return BGP_ERR_PEER_GROUP_MISMATCH;
1741
1742 peer->af_group[afi][safi] = 0;
1743 peer->afc[afi][safi] = 0;
1744 peer_af_flag_reset (peer, afi, safi);
1745
paulfee0f4c2004-09-13 05:12:46 +00001746 if (peer->rib[afi][safi])
1747 peer->rib[afi][safi] = NULL;
1748
paul718e3742002-12-13 20:15:29 +00001749 if (! peer_group_active (peer))
1750 {
1751 listnode_delete (group->peer, peer);
1752 peer->group = NULL;
1753 if (group->conf->as)
1754 {
1755 peer_delete (peer);
1756 return 0;
1757 }
1758 peer_global_config_reset (peer);
1759 }
1760
1761 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001762 {
1763 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1764 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1765 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1766 }
paul718e3742002-12-13 20:15:29 +00001767 else
1768 BGP_EVENT_ADD (peer, BGP_Stop);
1769
1770 return 0;
1771}
1772
1773/* BGP instance creation by `router bgp' commands. */
1774struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001775bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001776{
1777 struct bgp *bgp;
1778 afi_t afi;
1779 safi_t safi;
1780
1781 bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp));
1782
1783 bgp->peer_self = peer_new ();
paulfd79ac92004-10-13 05:06:08 +00001784 bgp->peer_self->host = strdup ("Static announcement");
paul718e3742002-12-13 20:15:29 +00001785
1786 bgp->peer = list_new ();
1787 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1788
1789 bgp->group = list_new ();
1790 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1791
paulfee0f4c2004-09-13 05:12:46 +00001792 bgp->rsclient = list_new ();
1793 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1794
paul718e3742002-12-13 20:15:29 +00001795 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1796 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1797 {
1798 bgp->route[afi][safi] = bgp_table_init ();
1799 bgp->aggregate[afi][safi] = bgp_table_init ();
1800 bgp->rib[afi][safi] = bgp_table_init ();
1801 }
1802
1803 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1804 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1805 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001806 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1807 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001808
1809 bgp->as = *as;
1810
1811 if (name)
1812 bgp->name = strdup (name);
1813
1814 return bgp;
1815}
1816
1817/* Return first entry of BGP. */
1818struct bgp *
1819bgp_get_default ()
1820{
1821 if (bm->bgp->head)
1822 return bm->bgp->head->data;
1823 return NULL;
1824}
1825
1826/* Lookup BGP entry. */
1827struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001828bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001829{
1830 struct bgp *bgp;
1831 struct listnode *nn;
1832
1833 LIST_LOOP (bm->bgp, bgp, nn)
1834 if (bgp->as == as
1835 && ((bgp->name == NULL && name == NULL)
1836 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1837 return bgp;
1838 return NULL;
1839}
1840
1841/* Lookup BGP structure by view name. */
1842struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001843bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00001844{
1845 struct bgp *bgp;
1846 struct listnode *nn;
1847
1848 LIST_LOOP (bm->bgp, bgp, nn)
1849 if ((bgp->name == NULL && name == NULL)
1850 || (bgp->name && name && strcmp (bgp->name, name) == 0))
1851 return bgp;
1852 return NULL;
1853}
1854
1855/* Called from VTY commands. */
1856int
paulfd79ac92004-10-13 05:06:08 +00001857bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001858{
1859 struct bgp *bgp;
1860
1861 /* Multiple instance check. */
1862 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
1863 {
1864 if (name)
1865 bgp = bgp_lookup_by_name (name);
1866 else
1867 bgp = bgp_get_default ();
1868
1869 /* Already exists. */
1870 if (bgp)
1871 {
1872 if (bgp->as != *as)
1873 {
1874 *as = bgp->as;
1875 return BGP_ERR_INSTANCE_MISMATCH;
1876 }
1877 *bgp_val = bgp;
1878 return 0;
1879 }
1880 }
1881 else
1882 {
1883 /* BGP instance name can not be specified for single instance. */
1884 if (name)
1885 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
1886
1887 /* Get default BGP structure if exists. */
1888 bgp = bgp_get_default ();
1889
1890 if (bgp)
1891 {
1892 if (bgp->as != *as)
1893 {
1894 *as = bgp->as;
1895 return BGP_ERR_AS_MISMATCH;
1896 }
1897 *bgp_val = bgp;
1898 return 0;
1899 }
1900 }
1901
1902 bgp = bgp_create (as, name);
1903 listnode_add (bm->bgp, bgp);
hasso18a6dce2004-10-03 18:18:34 +00001904 bgp_router_id_set(bgp, &router_id_zebra);
paul718e3742002-12-13 20:15:29 +00001905 *bgp_val = bgp;
1906
1907 return 0;
1908}
1909
1910/* Delete BGP instance. */
1911int
1912bgp_delete (struct bgp *bgp)
1913{
1914 struct peer *peer;
1915 struct listnode *nn;
1916 struct listnode *next;
1917 afi_t afi;
1918 safi_t safi;
1919 int i;
1920
1921 /* Delete static route. */
1922 bgp_static_delete (bgp);
1923
1924 /* Unset redistribution. */
1925 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1926 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
1927 if (i != ZEBRA_ROUTE_BGP)
1928 bgp_redistribute_unset (bgp, afi, i);
1929
1930 bgp->group->del = (void (*)(void *)) peer_group_delete;
1931 list_delete (bgp->group);
1932
1933 for (nn = bgp->peer->head; nn; nn = next)
1934 {
1935 peer = nn->data;
1936 next = nn->next;
1937 peer_delete (peer);
1938 }
1939
paulfee0f4c2004-09-13 05:12:46 +00001940 bgp->rsclient->del = (void (*)(void *)) peer_delete;
1941 list_delete (bgp->rsclient);
1942
paul718e3742002-12-13 20:15:29 +00001943 listnode_delete (bm->bgp, bgp);
1944
1945 if (bgp->name)
1946 free (bgp->name);
1947
1948 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1949 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1950 {
1951 if (bgp->route[afi][safi])
1952 XFREE (MTYPE_ROUTE_TABLE, bgp->route[afi][safi]);
1953 if (bgp->aggregate[afi][safi])
1954 XFREE (MTYPE_ROUTE_TABLE,bgp->aggregate[afi][safi]) ;
1955 if (bgp->rib[afi][safi])
1956 XFREE (MTYPE_ROUTE_TABLE,bgp->rib[afi][safi]);
1957 }
1958 XFREE (MTYPE_BGP, bgp);
1959
1960 return 0;
1961}
1962
1963struct peer *
1964peer_lookup (struct bgp *bgp, union sockunion *su)
1965{
1966 struct peer *peer;
1967 struct listnode *nn;
1968
1969 if (! bgp)
1970 bgp = bgp_get_default ();
1971
1972 if (! bgp)
1973 return NULL;
1974
1975 LIST_LOOP (bgp->peer, peer, nn)
1976 {
pauleb821182004-05-01 08:44:08 +00001977 if (sockunion_same (&peer->su, su)
1978 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1979 return peer;
paul718e3742002-12-13 20:15:29 +00001980 }
1981 return NULL;
1982}
1983
1984struct peer *
1985peer_lookup_with_open (union sockunion *su, as_t remote_as,
1986 struct in_addr *remote_id, int *as)
1987{
1988 struct peer *peer;
1989 struct listnode *nn;
1990 struct bgp *bgp;
1991
1992 bgp = bgp_get_default ();
1993 if (! bgp)
1994 return NULL;
1995
1996 LIST_LOOP (bgp->peer, peer, nn)
1997 {
pauleb821182004-05-01 08:44:08 +00001998 if (sockunion_same (&peer->su, su)
1999 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2000 {
2001 if (peer->as == remote_as
2002 && peer->remote_id.s_addr == remote_id->s_addr)
2003 return peer;
2004 if (peer->as == remote_as)
2005 *as = 1;
2006 }
paul718e3742002-12-13 20:15:29 +00002007 }
2008 LIST_LOOP (bgp->peer, peer, nn)
2009 {
pauleb821182004-05-01 08:44:08 +00002010 if (sockunion_same (&peer->su, su)
2011 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2012 {
2013 if (peer->as == remote_as
2014 && peer->remote_id.s_addr == 0)
2015 return peer;
2016 if (peer->as == remote_as)
2017 *as = 1;
2018 }
paul718e3742002-12-13 20:15:29 +00002019 }
2020 return NULL;
2021}
2022
2023/* If peer is configured at least one address family return 1. */
2024int
2025peer_active (struct peer *peer)
2026{
2027 if (peer->afc[AFI_IP][SAFI_UNICAST]
2028 || peer->afc[AFI_IP][SAFI_MULTICAST]
2029 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2030 || peer->afc[AFI_IP6][SAFI_UNICAST]
2031 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2032 return 1;
2033 return 0;
2034}
2035
2036/* If peer is negotiated at least one address family return 1. */
2037int
2038peer_active_nego (struct peer *peer)
2039{
2040 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2041 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2042 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2043 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2044 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2045 return 1;
2046 return 0;
2047}
2048
2049/* peer_flag_change_type. */
2050enum peer_change_type
2051{
2052 peer_change_none,
2053 peer_change_reset,
2054 peer_change_reset_in,
2055 peer_change_reset_out,
2056};
2057
2058void
2059peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2060 enum peer_change_type type)
2061{
2062 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2063 return;
2064
2065 if (type == peer_change_reset)
2066 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2067 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2068 else if (type == peer_change_reset_in)
2069 {
2070 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2071 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2072 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2073 else
2074 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2075 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2076 }
2077 else if (type == peer_change_reset_out)
2078 bgp_announce_route (peer, afi, safi);
2079}
2080
2081struct peer_flag_action
2082{
2083 /* Peer's flag. */
2084 u_int32_t flag;
2085
2086 /* This flag can be set for peer-group member. */
2087 u_char not_for_member;
2088
2089 /* Action when the flag is changed. */
2090 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002091
2092 /* Peer down cause */
2093 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002094};
2095
2096struct peer_flag_action peer_flag_action_list[] =
2097 {
2098 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2099 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2100 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2101 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2102 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002103 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
2104 { PEER_FLAG_ENFORCE_MULTIHOP, 0, peer_change_reset },
2105 { 0, 0, 0 }
2106 };
2107
2108struct peer_flag_action peer_af_flag_action_list[] =
2109 {
2110 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2111 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2112 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2113 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2114 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2115 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2116 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2117 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2118 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2119 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2120 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2121 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2122 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002123 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002124 { 0, 0, 0 }
2125 };
2126
2127/* Proper action set. */
2128int
2129peer_flag_action_set (struct peer_flag_action *action_list, int size,
2130 struct peer_flag_action *action, u_int32_t flag)
2131{
2132 int i;
2133 int found = 0;
2134 int reset_in = 0;
2135 int reset_out = 0;
2136 struct peer_flag_action *match = NULL;
2137
2138 /* Check peer's frag action. */
2139 for (i = 0; i < size; i++)
2140 {
2141 match = &action_list[i];
2142
2143 if (match->flag == 0)
2144 break;
2145
2146 if (match->flag & flag)
2147 {
2148 found = 1;
2149
2150 if (match->type == peer_change_reset_in)
2151 reset_in = 1;
2152 if (match->type == peer_change_reset_out)
2153 reset_out = 1;
2154 if (match->type == peer_change_reset)
2155 {
2156 reset_in = 1;
2157 reset_out = 1;
2158 }
2159 if (match->not_for_member)
2160 action->not_for_member = 1;
2161 }
2162 }
2163
2164 /* Set peer clear type. */
2165 if (reset_in && reset_out)
2166 action->type = peer_change_reset;
2167 else if (reset_in)
2168 action->type = peer_change_reset_in;
2169 else if (reset_out)
2170 action->type = peer_change_reset_out;
2171 else
2172 action->type = peer_change_none;
2173
2174 return found;
2175}
2176
2177void
2178peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2179{
2180 if (flag == PEER_FLAG_SHUTDOWN)
2181 {
2182 if (CHECK_FLAG (peer->flags, flag))
2183 {
hasso93406d82005-02-02 14:40:33 +00002184 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2185 peer_nsf_stop (peer);
2186
hasso0a486e52005-02-01 20:57:17 +00002187 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2188 if (peer->t_pmax_restart)
2189 {
2190 BGP_TIMER_OFF (peer->t_pmax_restart);
2191 if (BGP_DEBUG (events, EVENTS))
2192 zlog_debug ("%s Maximum-prefix restart timer canceled",
2193 peer->host);
2194 }
2195
hasso93406d82005-02-02 14:40:33 +00002196 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2197 peer_nsf_stop (peer);
2198
paul718e3742002-12-13 20:15:29 +00002199 if (peer->status == Established)
2200 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2201 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2202 else
2203 BGP_EVENT_ADD (peer, BGP_Stop);
2204 }
2205 else
2206 {
2207 peer->v_start = BGP_INIT_START_TIMER;
2208 BGP_EVENT_ADD (peer, BGP_Stop);
2209 }
2210 }
2211 else if (peer->status == Established)
2212 {
hassoc9502432005-02-01 22:01:48 +00002213 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2214 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2215 else if (flag == PEER_FLAG_PASSIVE)
2216 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
2217 else if (flag == PEER_FLAG_ENFORCE_MULTIHOP)
2218 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002219
hassoc9502432005-02-01 22:01:48 +00002220 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2221 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002222 }
2223 else
2224 BGP_EVENT_ADD (peer, BGP_Stop);
2225}
2226
2227/* Change specified peer flag. */
2228int
2229peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2230{
2231 int found;
2232 int size;
2233 struct peer_group *group;
2234 struct listnode *nn;
2235 struct peer_flag_action action;
2236
2237 memset (&action, 0, sizeof (struct peer_flag_action));
2238 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2239
2240 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2241
2242 /* No flag action is found. */
2243 if (! found)
2244 return BGP_ERR_INVALID_FLAG;
2245
2246 /* Not for peer-group member. */
2247 if (action.not_for_member && peer_group_active (peer))
2248 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2249
2250 /* When unset the peer-group member's flag we have to check
2251 peer-group configuration. */
2252 if (! set && peer_group_active (peer))
2253 if (CHECK_FLAG (peer->group->conf->flags, flag))
2254 {
2255 if (flag == PEER_FLAG_SHUTDOWN)
2256 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2257 else
2258 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2259 }
2260
2261 /* Flag conflict check. */
2262 if (set
2263 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2264 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2265 return BGP_ERR_PEER_FLAG_CONFLICT;
2266
2267 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2268 {
2269 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2270 return 0;
2271 if (! set && ! CHECK_FLAG (peer->flags, flag))
2272 return 0;
2273 }
2274
2275 if (set)
2276 SET_FLAG (peer->flags, flag);
2277 else
2278 UNSET_FLAG (peer->flags, flag);
2279
2280 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2281 {
2282 if (action.type == peer_change_reset)
2283 peer_flag_modify_action (peer, flag);
2284
2285 return 0;
2286 }
2287
2288 /* peer-group member updates. */
2289 group = peer->group;
2290
2291 LIST_LOOP (group->peer, peer, nn)
2292 {
2293 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2294 continue;
2295
2296 if (! set && ! CHECK_FLAG (peer->flags, flag))
2297 continue;
2298
2299 if (set)
2300 SET_FLAG (peer->flags, flag);
2301 else
2302 UNSET_FLAG (peer->flags, flag);
2303
2304 if (action.type == peer_change_reset)
2305 peer_flag_modify_action (peer, flag);
2306 }
2307 return 0;
2308}
2309
2310int
2311peer_flag_set (struct peer *peer, u_int32_t flag)
2312{
2313 return peer_flag_modify (peer, flag, 1);
2314}
2315
2316int
2317peer_flag_unset (struct peer *peer, u_int32_t flag)
2318{
2319 return peer_flag_modify (peer, flag, 0);
2320}
2321
2322int
2323peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2324{
2325 if (peer->af_group[afi][safi])
2326 return 1;
2327 return 0;
2328}
2329
2330int
2331peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2332 int set)
2333{
2334 int found;
2335 int size;
2336 struct listnode *nn;
2337 struct peer_group *group;
2338 struct peer_flag_action action;
2339
2340 memset (&action, 0, sizeof (struct peer_flag_action));
2341 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2342
2343 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2344
2345 /* No flag action is found. */
2346 if (! found)
2347 return BGP_ERR_INVALID_FLAG;
2348
2349 /* Adress family must be activated. */
2350 if (! peer->afc[afi][safi])
2351 return BGP_ERR_PEER_INACTIVE;
2352
2353 /* Not for peer-group member. */
2354 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2355 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2356
2357 /* Spcecial check for reflector client. */
2358 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2359 && peer_sort (peer) != BGP_PEER_IBGP)
2360 return BGP_ERR_NOT_INTERNAL_PEER;
2361
2362 /* Spcecial check for remove-private-AS. */
2363 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2364 && peer_sort (peer) == BGP_PEER_IBGP)
2365 return BGP_ERR_REMOVE_PRIVATE_AS;
2366
2367 /* When unset the peer-group member's flag we have to check
2368 peer-group configuration. */
2369 if (! set && peer->af_group[afi][safi])
2370 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2371 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2372
2373 /* When current flag configuration is same as requested one. */
2374 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2375 {
2376 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2377 return 0;
2378 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2379 return 0;
2380 }
2381
2382 if (set)
2383 SET_FLAG (peer->af_flags[afi][safi], flag);
2384 else
2385 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2386
2387 /* Execute action when peer is established. */
2388 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2389 && peer->status == Established)
2390 {
2391 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2392 bgp_clear_adj_in (peer, afi, safi);
2393 else
hassoe0701b72004-05-20 09:19:34 +00002394 {
2395 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2396 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2397 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2398 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2399 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2400 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2401 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2402 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2403
2404 peer_change_action (peer, afi, safi, action.type);
2405 }
2406
paul718e3742002-12-13 20:15:29 +00002407 }
2408
2409 /* Peer group member updates. */
2410 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2411 {
2412 group = peer->group;
2413
2414 LIST_LOOP (group->peer, peer, nn)
2415 {
2416 if (! peer->af_group[afi][safi])
2417 continue;
2418
2419 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2420 continue;
2421
2422 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2423 continue;
2424
2425 if (set)
2426 SET_FLAG (peer->af_flags[afi][safi], flag);
2427 else
2428 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2429
2430 if (peer->status == Established)
2431 {
2432 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2433 bgp_clear_adj_in (peer, afi, safi);
2434 else
hassoe0701b72004-05-20 09:19:34 +00002435 {
2436 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2437 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2438 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2439 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2440 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2441 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2442 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2443 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2444
2445 peer_change_action (peer, afi, safi, action.type);
2446 }
paul718e3742002-12-13 20:15:29 +00002447 }
2448 }
2449 }
2450 return 0;
2451}
2452
2453int
2454peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2455{
2456 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2457}
2458
2459int
2460peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2461{
2462 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2463}
2464
2465/* EBGP multihop configuration. */
2466int
2467peer_ebgp_multihop_set (struct peer *peer, int ttl)
2468{
2469 struct peer_group *group;
2470 struct listnode *nn;
2471
2472 if (peer_sort (peer) == BGP_PEER_IBGP)
2473 return 0;
2474
2475 peer->ttl = ttl;
2476
2477 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2478 {
pauleb821182004-05-01 08:44:08 +00002479 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2480 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002481 }
2482 else
2483 {
2484 group = peer->group;
2485 LIST_LOOP (group->peer, peer, nn)
pauleb821182004-05-01 08:44:08 +00002486 {
2487 if (peer_sort (peer) == BGP_PEER_IBGP)
2488 continue;
paul718e3742002-12-13 20:15:29 +00002489
pauleb821182004-05-01 08:44:08 +00002490 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002491
pauleb821182004-05-01 08:44:08 +00002492 if (peer->fd >= 0)
2493 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2494 }
paul718e3742002-12-13 20:15:29 +00002495 }
2496 return 0;
2497}
2498
2499int
2500peer_ebgp_multihop_unset (struct peer *peer)
2501{
2502 struct peer_group *group;
2503 struct listnode *nn;
2504
2505 if (peer_sort (peer) == BGP_PEER_IBGP)
2506 return 0;
2507
2508 if (peer_group_active (peer))
2509 peer->ttl = peer->group->conf->ttl;
2510 else
2511 peer->ttl = 1;
2512
2513 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2514 {
pauleb821182004-05-01 08:44:08 +00002515 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2516 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002517 }
2518 else
2519 {
2520 group = peer->group;
2521 LIST_LOOP (group->peer, peer, nn)
pauleb821182004-05-01 08:44:08 +00002522 {
2523 if (peer_sort (peer) == BGP_PEER_IBGP)
2524 continue;
paul718e3742002-12-13 20:15:29 +00002525
pauleb821182004-05-01 08:44:08 +00002526 peer->ttl = 1;
2527
2528 if (peer->fd >= 0)
2529 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2530 }
paul718e3742002-12-13 20:15:29 +00002531 }
2532 return 0;
2533}
2534
2535/* Neighbor description. */
2536int
2537peer_description_set (struct peer *peer, char *desc)
2538{
2539 if (peer->desc)
2540 XFREE (MTYPE_PEER_DESC, peer->desc);
2541
2542 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2543
2544 return 0;
2545}
2546
2547int
2548peer_description_unset (struct peer *peer)
2549{
2550 if (peer->desc)
2551 XFREE (MTYPE_PEER_DESC, peer->desc);
2552
2553 peer->desc = NULL;
2554
2555 return 0;
2556}
2557
2558/* Neighbor update-source. */
2559int
paulfd79ac92004-10-13 05:06:08 +00002560peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002561{
2562 struct peer_group *group;
2563 struct listnode *nn;
2564
2565 if (peer->update_if)
2566 {
2567 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2568 && strcmp (peer->update_if, ifname) == 0)
2569 return 0;
2570
2571 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2572 peer->update_if = NULL;
2573 }
2574
2575 if (peer->update_source)
2576 {
2577 sockunion_free (peer->update_source);
2578 peer->update_source = NULL;
2579 }
2580
2581 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2582
2583 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2584 {
2585 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002586 {
2587 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2588 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2589 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2590 }
paul718e3742002-12-13 20:15:29 +00002591 else
2592 BGP_EVENT_ADD (peer, BGP_Stop);
2593 return 0;
2594 }
2595
2596 /* peer-group member updates. */
2597 group = peer->group;
2598 LIST_LOOP (group->peer, peer, nn)
2599 {
2600 if (peer->update_if)
2601 {
2602 if (strcmp (peer->update_if, ifname) == 0)
2603 continue;
2604
2605 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2606 peer->update_if = NULL;
2607 }
2608
2609 if (peer->update_source)
2610 {
2611 sockunion_free (peer->update_source);
2612 peer->update_source = NULL;
2613 }
2614
2615 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2616
2617 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002618 {
2619 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2620 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2621 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2622 }
paul718e3742002-12-13 20:15:29 +00002623 else
2624 BGP_EVENT_ADD (peer, BGP_Stop);
2625 }
2626 return 0;
2627}
2628
2629int
2630peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2631{
2632 struct peer_group *group;
2633 struct listnode *nn;
2634
2635 if (peer->update_source)
2636 {
2637 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2638 && sockunion_cmp (peer->update_source, su) == 0)
2639 return 0;
2640 sockunion_free (peer->update_source);
2641 peer->update_source = NULL;
2642 }
2643
2644 if (peer->update_if)
2645 {
2646 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2647 peer->update_if = NULL;
2648 }
2649
2650 peer->update_source = sockunion_dup (su);
2651
2652 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2653 {
2654 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002655 {
2656 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2657 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2658 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2659 }
paul718e3742002-12-13 20:15:29 +00002660 else
2661 BGP_EVENT_ADD (peer, BGP_Stop);
2662 return 0;
2663 }
2664
2665 /* peer-group member updates. */
2666 group = peer->group;
2667 LIST_LOOP (group->peer, peer, nn)
2668 {
2669 if (peer->update_source)
2670 {
2671 if (sockunion_cmp (peer->update_source, su) == 0)
2672 continue;
2673 sockunion_free (peer->update_source);
2674 peer->update_source = NULL;
2675 }
2676
2677 if (peer->update_if)
2678 {
2679 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2680 peer->update_if = NULL;
2681 }
2682
2683 peer->update_source = sockunion_dup (su);
2684
2685 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002686 {
2687 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2688 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2689 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2690 }
paul718e3742002-12-13 20:15:29 +00002691 else
2692 BGP_EVENT_ADD (peer, BGP_Stop);
2693 }
2694 return 0;
2695}
2696
2697int
2698peer_update_source_unset (struct peer *peer)
2699{
2700 union sockunion *su;
2701 struct peer_group *group;
2702 struct listnode *nn;
2703
2704 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2705 && ! peer->update_source
2706 && ! peer->update_if)
2707 return 0;
2708
2709 if (peer->update_source)
2710 {
2711 sockunion_free (peer->update_source);
2712 peer->update_source = NULL;
2713 }
2714 if (peer->update_if)
2715 {
2716 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2717 peer->update_if = NULL;
2718 }
2719
2720 if (peer_group_active (peer))
2721 {
2722 group = peer->group;
2723
2724 if (group->conf->update_source)
2725 {
2726 su = sockunion_dup (group->conf->update_source);
2727 peer->update_source = su;
2728 }
2729 else if (group->conf->update_if)
2730 peer->update_if =
2731 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2732 }
2733
2734 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2735 {
2736 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002737 {
2738 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2739 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2740 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2741 }
paul718e3742002-12-13 20:15:29 +00002742 else
2743 BGP_EVENT_ADD (peer, BGP_Stop);
2744 return 0;
2745 }
2746
2747 /* peer-group member updates. */
2748 group = peer->group;
2749 LIST_LOOP (group->peer, peer, nn)
2750 {
2751 if (! peer->update_source && ! peer->update_if)
2752 continue;
2753
2754 if (peer->update_source)
2755 {
2756 sockunion_free (peer->update_source);
2757 peer->update_source = NULL;
2758 }
2759
2760 if (peer->update_if)
2761 {
2762 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2763 peer->update_if = NULL;
2764 }
2765
2766 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002767 {
2768 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2769 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2770 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2771 }
paul718e3742002-12-13 20:15:29 +00002772 else
2773 BGP_EVENT_ADD (peer, BGP_Stop);
2774 }
2775 return 0;
2776}
2777
2778int
2779peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00002780 const char *rmap)
paul718e3742002-12-13 20:15:29 +00002781{
2782 struct peer_group *group;
2783 struct listnode *nn;
2784
2785 /* Adress family must be activated. */
2786 if (! peer->afc[afi][safi])
2787 return BGP_ERR_PEER_INACTIVE;
2788
2789 /* Default originate can't be used for peer group memeber. */
2790 if (peer_is_group_member (peer, afi, safi))
2791 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2792
2793 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
2794 || (rmap && ! peer->default_rmap[afi][safi].name)
2795 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
2796 {
2797 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2798
2799 if (rmap)
2800 {
2801 if (peer->default_rmap[afi][safi].name)
2802 free (peer->default_rmap[afi][safi].name);
2803 peer->default_rmap[afi][safi].name = strdup (rmap);
2804 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2805 }
2806 }
2807
2808 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2809 {
2810 if (peer->status == Established && peer->afc_nego[afi][safi])
2811 bgp_default_originate (peer, afi, safi, 0);
2812 return 0;
2813 }
2814
2815 /* peer-group member updates. */
2816 group = peer->group;
2817 LIST_LOOP (group->peer, peer, nn)
2818 {
2819 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2820
2821 if (rmap)
2822 {
2823 if (peer->default_rmap[afi][safi].name)
2824 free (peer->default_rmap[afi][safi].name);
2825 peer->default_rmap[afi][safi].name = strdup (rmap);
2826 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2827 }
2828
2829 if (peer->status == Established && peer->afc_nego[afi][safi])
2830 bgp_default_originate (peer, afi, safi, 0);
2831 }
2832 return 0;
2833}
2834
2835int
2836peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
2837{
2838 struct peer_group *group;
2839 struct listnode *nn;
2840
2841 /* Adress family must be activated. */
2842 if (! peer->afc[afi][safi])
2843 return BGP_ERR_PEER_INACTIVE;
2844
2845 /* Default originate can't be used for peer group memeber. */
2846 if (peer_is_group_member (peer, afi, safi))
2847 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2848
2849 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
2850 {
2851 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2852
2853 if (peer->default_rmap[afi][safi].name)
2854 free (peer->default_rmap[afi][safi].name);
2855 peer->default_rmap[afi][safi].name = NULL;
2856 peer->default_rmap[afi][safi].map = NULL;
2857 }
2858
2859 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2860 {
2861 if (peer->status == Established && peer->afc_nego[afi][safi])
2862 bgp_default_originate (peer, afi, safi, 1);
2863 return 0;
2864 }
2865
2866 /* peer-group member updates. */
2867 group = peer->group;
2868 LIST_LOOP (group->peer, peer, nn)
2869 {
2870 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2871
2872 if (peer->default_rmap[afi][safi].name)
2873 free (peer->default_rmap[afi][safi].name);
2874 peer->default_rmap[afi][safi].name = NULL;
2875 peer->default_rmap[afi][safi].map = NULL;
2876
2877 if (peer->status == Established && peer->afc_nego[afi][safi])
2878 bgp_default_originate (peer, afi, safi, 1);
2879 }
2880 return 0;
2881}
2882
2883int
2884peer_port_set (struct peer *peer, u_int16_t port)
2885{
2886 peer->port = port;
2887 return 0;
2888}
2889
2890int
2891peer_port_unset (struct peer *peer)
2892{
2893 peer->port = BGP_PORT_DEFAULT;
2894 return 0;
2895}
2896
2897/* neighbor weight. */
2898int
2899peer_weight_set (struct peer *peer, u_int16_t weight)
2900{
2901 struct peer_group *group;
2902 struct listnode *nn;
2903
2904 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
2905 peer->weight = weight;
2906
2907 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2908 return 0;
2909
2910 /* peer-group member updates. */
2911 group = peer->group;
2912 LIST_LOOP (group->peer, peer, nn)
2913 {
2914 peer->weight = group->conf->weight;
2915 }
2916 return 0;
2917}
2918
2919int
2920peer_weight_unset (struct peer *peer)
2921{
2922 struct peer_group *group;
2923 struct listnode *nn;
2924
2925 /* Set default weight. */
2926 if (peer_group_active (peer))
2927 peer->weight = peer->group->conf->weight;
2928 else
2929 peer->weight = 0;
2930
2931 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
2932
2933 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2934 return 0;
2935
2936 /* peer-group member updates. */
2937 group = peer->group;
2938 LIST_LOOP (group->peer, peer, nn)
2939 {
2940 peer->weight = 0;
2941 }
2942 return 0;
2943}
2944
2945int
2946peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
2947{
2948 struct peer_group *group;
2949 struct listnode *nn;
2950
2951 /* Not for peer group memeber. */
2952 if (peer_group_active (peer))
2953 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2954
2955 /* keepalive value check. */
2956 if (keepalive > 65535)
2957 return BGP_ERR_INVALID_VALUE;
2958
2959 /* Holdtime value check. */
2960 if (holdtime > 65535)
2961 return BGP_ERR_INVALID_VALUE;
2962
2963 /* Holdtime value must be either 0 or greater than 3. */
2964 if (holdtime < 3 && holdtime != 0)
2965 return BGP_ERR_INVALID_VALUE;
2966
2967 /* Set value to the configuration. */
2968 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
2969 peer->holdtime = holdtime;
2970 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
2971
2972 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2973 return 0;
2974
2975 /* peer-group member updates. */
2976 group = peer->group;
2977 LIST_LOOP (group->peer, peer, nn)
2978 {
2979 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
2980 peer->holdtime = group->conf->holdtime;
2981 peer->keepalive = group->conf->keepalive;
2982 }
2983 return 0;
2984}
2985
2986int
2987peer_timers_unset (struct peer *peer)
2988{
2989 struct peer_group *group;
2990 struct listnode *nn;
2991
2992 if (peer_group_active (peer))
2993 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2994
2995 /* Clear configuration. */
2996 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
2997 peer->keepalive = 0;
2998 peer->holdtime = 0;
2999
3000 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3001 return 0;
3002
3003 /* peer-group member updates. */
3004 group = peer->group;
3005 LIST_LOOP (group->peer, peer, nn)
3006 {
3007 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3008 peer->holdtime = 0;
3009 peer->keepalive = 0;
3010 }
3011
3012 return 0;
3013}
3014
3015int
3016peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3017{
3018 if (peer_group_active (peer))
3019 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3020
3021 if (connect > 65535)
3022 return BGP_ERR_INVALID_VALUE;
3023
3024 /* Set value to the configuration. */
3025 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3026 peer->connect = connect;
3027
3028 /* Set value to timer setting. */
3029 peer->v_connect = connect;
3030
3031 return 0;
3032}
3033
3034int
3035peer_timers_connect_unset (struct peer *peer)
3036{
3037 if (peer_group_active (peer))
3038 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3039
3040 /* Clear configuration. */
3041 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3042 peer->connect = 0;
3043
3044 /* Set timer setting to default value. */
3045 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3046
3047 return 0;
3048}
3049
3050int
3051peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3052{
3053 if (peer_group_active (peer))
3054 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3055
3056 if (routeadv > 600)
3057 return BGP_ERR_INVALID_VALUE;
3058
3059 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3060 peer->routeadv = routeadv;
3061 peer->v_routeadv = routeadv;
3062
3063 return 0;
3064}
3065
3066int
3067peer_advertise_interval_unset (struct peer *peer)
3068{
3069 if (peer_group_active (peer))
3070 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3071
3072 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3073 peer->routeadv = 0;
3074
3075 if (peer_sort (peer) == BGP_PEER_IBGP)
3076 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3077 else
3078 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3079
3080 return 0;
3081}
3082
paul718e3742002-12-13 20:15:29 +00003083/* neighbor interface */
3084int
paulfd79ac92004-10-13 05:06:08 +00003085peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003086{
3087 if (peer->ifname)
3088 free (peer->ifname);
3089 peer->ifname = strdup (str);
3090
3091 return 0;
3092}
3093
3094int
3095peer_interface_unset (struct peer *peer)
3096{
3097 if (peer->ifname)
3098 free (peer->ifname);
3099 peer->ifname = NULL;
3100
3101 return 0;
3102}
3103
3104/* Allow-as in. */
3105int
3106peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3107{
3108 struct peer_group *group;
3109 struct listnode *nn;
3110
3111 if (allow_num < 1 || allow_num > 10)
3112 return BGP_ERR_INVALID_VALUE;
3113
3114 if (peer->allowas_in[afi][safi] != allow_num)
3115 {
3116 peer->allowas_in[afi][safi] = allow_num;
3117 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3118 peer_change_action (peer, afi, safi, peer_change_reset_in);
3119 }
3120
3121 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3122 return 0;
3123
3124 group = peer->group;
3125 LIST_LOOP (group->peer, peer, nn)
3126 {
3127 if (peer->allowas_in[afi][safi] != allow_num)
3128 {
3129 peer->allowas_in[afi][safi] = allow_num;
3130 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3131 peer_change_action (peer, afi, safi, peer_change_reset_in);
3132 }
3133
3134 }
3135 return 0;
3136}
3137
3138int
3139peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3140{
3141 struct peer_group *group;
3142 struct listnode *nn;
3143
3144 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3145 {
3146 peer->allowas_in[afi][safi] = 0;
3147 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3148 }
3149
3150 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3151 return 0;
3152
3153 group = peer->group;
3154 LIST_LOOP (group->peer, peer, nn)
3155 {
3156 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3157 {
3158 peer->allowas_in[afi][safi] = 0;
3159 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3160 }
3161 }
3162 return 0;
3163}
3164
3165int
3166peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3167{
3168 struct bgp *bgp = peer->bgp;
3169 struct peer_group *group;
3170 struct listnode *nn;
3171
3172 if (peer_sort (peer) != BGP_PEER_EBGP
3173 && peer_sort (peer) != BGP_PEER_INTERNAL)
3174 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3175
3176 if (bgp->as == as)
3177 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3178
3179 if (peer_group_active (peer))
3180 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3181
3182 if (peer->change_local_as == as &&
3183 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3184 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3185 return 0;
3186
3187 peer->change_local_as = as;
3188 if (no_prepend)
3189 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3190 else
3191 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3192
3193 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3194 {
3195 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003196 {
3197 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3198 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3199 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3200 }
paul718e3742002-12-13 20:15:29 +00003201 else
3202 BGP_EVENT_ADD (peer, BGP_Stop);
3203
3204 return 0;
3205 }
3206
3207 group = peer->group;
3208 LIST_LOOP (group->peer, peer, nn)
3209 {
3210 peer->change_local_as = as;
3211 if (no_prepend)
3212 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3213 else
3214 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3215
3216 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003217 {
3218 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3219 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3220 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3221 }
paul718e3742002-12-13 20:15:29 +00003222 else
3223 BGP_EVENT_ADD (peer, BGP_Stop);
3224 }
3225
3226 return 0;
3227}
3228
3229int
3230peer_local_as_unset (struct peer *peer)
3231{
3232 struct peer_group *group;
3233 struct listnode *nn;
3234
3235 if (peer_group_active (peer))
3236 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3237
3238 if (! peer->change_local_as)
3239 return 0;
3240
3241 peer->change_local_as = 0;
3242 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3243
3244 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3245 {
3246 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003247 {
3248 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3249 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3250 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3251 }
paul718e3742002-12-13 20:15:29 +00003252 else
3253 BGP_EVENT_ADD (peer, BGP_Stop);
3254
3255 return 0;
3256 }
3257
3258 group = peer->group;
3259 LIST_LOOP (group->peer, peer, nn)
3260 {
3261 peer->change_local_as = 0;
3262 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3263
3264 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003265 {
3266 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3267 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3268 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3269 }
paul718e3742002-12-13 20:15:29 +00003270 else
3271 BGP_EVENT_ADD (peer, BGP_Stop);
3272 }
3273 return 0;
3274}
3275
3276/* Set distribute list to the peer. */
3277int
3278peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003279 const char *name)
paul718e3742002-12-13 20:15:29 +00003280{
3281 struct bgp_filter *filter;
3282 struct peer_group *group;
3283 struct listnode *nn;
3284
3285 if (! peer->afc[afi][safi])
3286 return BGP_ERR_PEER_INACTIVE;
3287
3288 if (direct != FILTER_IN && direct != FILTER_OUT)
3289 return BGP_ERR_INVALID_VALUE;
3290
3291 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3292 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3293
3294 filter = &peer->filter[afi][safi];
3295
3296 if (filter->plist[direct].name)
3297 return BGP_ERR_PEER_FILTER_CONFLICT;
3298
3299 if (filter->dlist[direct].name)
3300 free (filter->dlist[direct].name);
3301 filter->dlist[direct].name = strdup (name);
3302 filter->dlist[direct].alist = access_list_lookup (afi, name);
3303
3304 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3305 return 0;
3306
3307 group = peer->group;
3308 LIST_LOOP (group->peer, peer, nn)
3309 {
3310 filter = &peer->filter[afi][safi];
3311
3312 if (! peer->af_group[afi][safi])
3313 continue;
3314
3315 if (filter->dlist[direct].name)
3316 free (filter->dlist[direct].name);
3317 filter->dlist[direct].name = strdup (name);
3318 filter->dlist[direct].alist = access_list_lookup (afi, name);
3319 }
3320
3321 return 0;
3322}
3323
3324int
3325peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3326{
3327 struct bgp_filter *filter;
3328 struct bgp_filter *gfilter;
3329 struct peer_group *group;
3330 struct listnode *nn;
3331
3332 if (! peer->afc[afi][safi])
3333 return BGP_ERR_PEER_INACTIVE;
3334
3335 if (direct != FILTER_IN && direct != FILTER_OUT)
3336 return BGP_ERR_INVALID_VALUE;
3337
3338 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3339 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3340
3341 filter = &peer->filter[afi][safi];
3342
3343 /* apply peer-group filter */
3344 if (peer->af_group[afi][safi])
3345 {
3346 gfilter = &peer->group->conf->filter[afi][safi];
3347
3348 if (gfilter->dlist[direct].name)
3349 {
3350 if (filter->dlist[direct].name)
3351 free (filter->dlist[direct].name);
3352 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3353 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3354 return 0;
3355 }
3356 }
3357
3358 if (filter->dlist[direct].name)
3359 free (filter->dlist[direct].name);
3360 filter->dlist[direct].name = NULL;
3361 filter->dlist[direct].alist = NULL;
3362
3363 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3364 return 0;
3365
3366 group = peer->group;
3367 LIST_LOOP (group->peer, peer, nn)
3368 {
3369 filter = &peer->filter[afi][safi];
3370
3371 if (! peer->af_group[afi][safi])
3372 continue;
3373
3374 if (filter->dlist[direct].name)
3375 free (filter->dlist[direct].name);
3376 filter->dlist[direct].name = NULL;
3377 filter->dlist[direct].alist = NULL;
3378 }
3379
3380 return 0;
3381}
3382
3383/* Update distribute list. */
3384void
3385peer_distribute_update (struct access_list *access)
3386{
3387 afi_t afi;
3388 safi_t safi;
3389 int direct;
3390 struct listnode *nn, *nm;
3391 struct bgp *bgp;
3392 struct peer *peer;
3393 struct peer_group *group;
3394 struct bgp_filter *filter;
3395
3396 LIST_LOOP (bm->bgp, bgp, nn)
3397 {
3398 LIST_LOOP (bgp->peer, peer, nm)
3399 {
3400 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3401 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3402 {
3403 filter = &peer->filter[afi][safi];
3404
3405 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3406 {
3407 if (filter->dlist[direct].name)
3408 filter->dlist[direct].alist =
3409 access_list_lookup (afi, filter->dlist[direct].name);
3410 else
3411 filter->dlist[direct].alist = NULL;
3412 }
3413 }
3414 }
3415 LIST_LOOP (bgp->group, group, nm)
3416 {
3417 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3418 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3419 {
3420 filter = &group->conf->filter[afi][safi];
3421
3422 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3423 {
3424 if (filter->dlist[direct].name)
3425 filter->dlist[direct].alist =
3426 access_list_lookup (afi, filter->dlist[direct].name);
3427 else
3428 filter->dlist[direct].alist = NULL;
3429 }
3430 }
3431 }
3432 }
3433}
3434
3435/* Set prefix list to the peer. */
3436int
3437peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003438 const char *name)
paul718e3742002-12-13 20:15:29 +00003439{
3440 struct bgp_filter *filter;
3441 struct peer_group *group;
3442 struct listnode *nn;
3443
3444 if (! peer->afc[afi][safi])
3445 return BGP_ERR_PEER_INACTIVE;
3446
3447 if (direct != FILTER_IN && direct != FILTER_OUT)
3448 return BGP_ERR_INVALID_VALUE;
3449
3450 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3451 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3452
3453 filter = &peer->filter[afi][safi];
3454
3455 if (filter->dlist[direct].name)
3456 return BGP_ERR_PEER_FILTER_CONFLICT;
3457
3458 if (filter->plist[direct].name)
3459 free (filter->plist[direct].name);
3460 filter->plist[direct].name = strdup (name);
3461 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3462
3463 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3464 return 0;
3465
3466 group = peer->group;
3467 LIST_LOOP (group->peer, peer, nn)
3468 {
3469 filter = &peer->filter[afi][safi];
3470
3471 if (! peer->af_group[afi][safi])
3472 continue;
3473
3474 if (filter->plist[direct].name)
3475 free (filter->plist[direct].name);
3476 filter->plist[direct].name = strdup (name);
3477 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3478 }
3479 return 0;
3480}
3481
3482int
3483peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3484{
3485 struct bgp_filter *filter;
3486 struct bgp_filter *gfilter;
3487 struct peer_group *group;
3488 struct listnode *nn;
3489
3490 if (! peer->afc[afi][safi])
3491 return BGP_ERR_PEER_INACTIVE;
3492
3493 if (direct != FILTER_IN && direct != FILTER_OUT)
3494 return BGP_ERR_INVALID_VALUE;
3495
3496 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3497 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3498
3499 filter = &peer->filter[afi][safi];
3500
3501 /* apply peer-group filter */
3502 if (peer->af_group[afi][safi])
3503 {
3504 gfilter = &peer->group->conf->filter[afi][safi];
3505
3506 if (gfilter->plist[direct].name)
3507 {
3508 if (filter->plist[direct].name)
3509 free (filter->plist[direct].name);
3510 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3511 filter->plist[direct].plist = gfilter->plist[direct].plist;
3512 return 0;
3513 }
3514 }
3515
3516 if (filter->plist[direct].name)
3517 free (filter->plist[direct].name);
3518 filter->plist[direct].name = NULL;
3519 filter->plist[direct].plist = NULL;
3520
3521 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3522 return 0;
3523
3524 group = peer->group;
3525 LIST_LOOP (group->peer, peer, nn)
3526 {
3527 filter = &peer->filter[afi][safi];
3528
3529 if (! peer->af_group[afi][safi])
3530 continue;
3531
3532 if (filter->plist[direct].name)
3533 free (filter->plist[direct].name);
3534 filter->plist[direct].name = NULL;
3535 filter->plist[direct].plist = NULL;
3536 }
3537
3538 return 0;
3539}
3540
3541/* Update prefix-list list. */
3542void
3543peer_prefix_list_update (struct prefix_list *plist)
3544{
3545 struct listnode *nn, *nm;
3546 struct bgp *bgp;
3547 struct peer *peer;
3548 struct peer_group *group;
3549 struct bgp_filter *filter;
3550 afi_t afi;
3551 safi_t safi;
3552 int direct;
3553
3554 LIST_LOOP (bm->bgp, bgp, nn)
3555 {
3556 LIST_LOOP (bgp->peer, peer, nm)
3557 {
3558 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3559 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3560 {
3561 filter = &peer->filter[afi][safi];
3562
3563 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3564 {
3565 if (filter->plist[direct].name)
3566 filter->plist[direct].plist =
3567 prefix_list_lookup (afi, filter->plist[direct].name);
3568 else
3569 filter->plist[direct].plist = NULL;
3570 }
3571 }
3572 }
3573 LIST_LOOP (bgp->group, group, nm)
3574 {
3575 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3576 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3577 {
3578 filter = &group->conf->filter[afi][safi];
3579
3580 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3581 {
3582 if (filter->plist[direct].name)
3583 filter->plist[direct].plist =
3584 prefix_list_lookup (afi, filter->plist[direct].name);
3585 else
3586 filter->plist[direct].plist = NULL;
3587 }
3588 }
3589 }
3590 }
3591}
3592
3593int
3594peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003595 const char *name)
paul718e3742002-12-13 20:15:29 +00003596{
3597 struct bgp_filter *filter;
3598 struct peer_group *group;
3599 struct listnode *nn;
3600
3601 if (! peer->afc[afi][safi])
3602 return BGP_ERR_PEER_INACTIVE;
3603
3604 if (direct != FILTER_IN && direct != FILTER_OUT)
3605 return BGP_ERR_INVALID_VALUE;
3606
3607 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3608 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3609
3610 filter = &peer->filter[afi][safi];
3611
3612 if (filter->aslist[direct].name)
3613 free (filter->aslist[direct].name);
3614 filter->aslist[direct].name = strdup (name);
3615 filter->aslist[direct].aslist = as_list_lookup (name);
3616
3617 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3618 return 0;
3619
3620 group = peer->group;
3621 LIST_LOOP (group->peer, peer, nn)
3622 {
3623 filter = &peer->filter[afi][safi];
3624
3625 if (! peer->af_group[afi][safi])
3626 continue;
3627
3628 if (filter->aslist[direct].name)
3629 free (filter->aslist[direct].name);
3630 filter->aslist[direct].name = strdup (name);
3631 filter->aslist[direct].aslist = as_list_lookup (name);
3632 }
3633 return 0;
3634}
3635
3636int
3637peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3638{
3639 struct bgp_filter *filter;
3640 struct bgp_filter *gfilter;
3641 struct peer_group *group;
3642 struct listnode *nn;
3643
3644 if (! peer->afc[afi][safi])
3645 return BGP_ERR_PEER_INACTIVE;
3646
paulfee0f4c2004-09-13 05:12:46 +00003647 if (direct != RMAP_IN && direct != RMAP_OUT &&
3648 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003649 return BGP_ERR_INVALID_VALUE;
3650
paulfee0f4c2004-09-13 05:12:46 +00003651 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
3652 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003653 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3654
3655 filter = &peer->filter[afi][safi];
3656
3657 /* apply peer-group filter */
3658 if (peer->af_group[afi][safi])
3659 {
3660 gfilter = &peer->group->conf->filter[afi][safi];
3661
3662 if (gfilter->aslist[direct].name)
3663 {
3664 if (filter->aslist[direct].name)
3665 free (filter->aslist[direct].name);
3666 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
3667 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
3668 return 0;
3669 }
3670 }
3671
3672 if (filter->aslist[direct].name)
3673 free (filter->aslist[direct].name);
3674 filter->aslist[direct].name = NULL;
3675 filter->aslist[direct].aslist = NULL;
3676
3677 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3678 return 0;
3679
3680 group = peer->group;
3681 LIST_LOOP (group->peer, peer, nn)
3682 {
3683 filter = &peer->filter[afi][safi];
3684
3685 if (! peer->af_group[afi][safi])
3686 continue;
3687
3688 if (filter->aslist[direct].name)
3689 free (filter->aslist[direct].name);
3690 filter->aslist[direct].name = NULL;
3691 filter->aslist[direct].aslist = NULL;
3692 }
3693
3694 return 0;
3695}
3696
3697void
3698peer_aslist_update ()
3699{
3700 afi_t afi;
3701 safi_t safi;
3702 int direct;
3703 struct listnode *nn, *nm;
3704 struct bgp *bgp;
3705 struct peer *peer;
3706 struct peer_group *group;
3707 struct bgp_filter *filter;
3708
3709 LIST_LOOP (bm->bgp, bgp, nn)
3710 {
3711 LIST_LOOP (bgp->peer, peer, nm)
3712 {
3713 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3714 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3715 {
3716 filter = &peer->filter[afi][safi];
3717
3718 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3719 {
3720 if (filter->aslist[direct].name)
3721 filter->aslist[direct].aslist =
3722 as_list_lookup (filter->aslist[direct].name);
3723 else
3724 filter->aslist[direct].aslist = NULL;
3725 }
3726 }
3727 }
3728 LIST_LOOP (bgp->group, group, nm)
3729 {
3730 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3731 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3732 {
3733 filter = &group->conf->filter[afi][safi];
3734
3735 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3736 {
3737 if (filter->aslist[direct].name)
3738 filter->aslist[direct].aslist =
3739 as_list_lookup (filter->aslist[direct].name);
3740 else
3741 filter->aslist[direct].aslist = NULL;
3742 }
3743 }
3744 }
3745 }
3746}
3747
3748/* Set route-map to the peer. */
3749int
3750peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003751 const char *name)
paul718e3742002-12-13 20:15:29 +00003752{
3753 struct bgp_filter *filter;
3754 struct peer_group *group;
3755 struct listnode *nn;
3756
3757 if (! peer->afc[afi][safi])
3758 return BGP_ERR_PEER_INACTIVE;
3759
paulfee0f4c2004-09-13 05:12:46 +00003760 if (direct != RMAP_IN && direct != RMAP_OUT &&
3761 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003762 return BGP_ERR_INVALID_VALUE;
3763
paulfee0f4c2004-09-13 05:12:46 +00003764 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
3765 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003766 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3767
3768 filter = &peer->filter[afi][safi];
3769
3770 if (filter->map[direct].name)
3771 free (filter->map[direct].name);
3772
3773 filter->map[direct].name = strdup (name);
3774 filter->map[direct].map = route_map_lookup_by_name (name);
3775
3776 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3777 return 0;
3778
3779 group = peer->group;
3780 LIST_LOOP (group->peer, peer, nn)
3781 {
3782 filter = &peer->filter[afi][safi];
3783
3784 if (! peer->af_group[afi][safi])
3785 continue;
3786
3787 if (filter->map[direct].name)
3788 free (filter->map[direct].name);
3789 filter->map[direct].name = strdup (name);
3790 filter->map[direct].map = route_map_lookup_by_name (name);
3791 }
3792 return 0;
3793}
3794
3795/* Unset route-map from the peer. */
3796int
3797peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3798{
3799 struct bgp_filter *filter;
3800 struct bgp_filter *gfilter;
3801 struct peer_group *group;
3802 struct listnode *nn;
3803
3804 if (! peer->afc[afi][safi])
3805 return BGP_ERR_PEER_INACTIVE;
3806
3807 if (direct != FILTER_IN && direct != FILTER_OUT)
3808 return BGP_ERR_INVALID_VALUE;
3809
3810 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3811 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3812
3813 filter = &peer->filter[afi][safi];
3814
3815 /* apply peer-group filter */
3816 if (peer->af_group[afi][safi])
3817 {
3818 gfilter = &peer->group->conf->filter[afi][safi];
3819
3820 if (gfilter->map[direct].name)
3821 {
3822 if (filter->map[direct].name)
3823 free (filter->map[direct].name);
3824 filter->map[direct].name = strdup (gfilter->map[direct].name);
3825 filter->map[direct].map = gfilter->map[direct].map;
3826 return 0;
3827 }
3828 }
3829
3830 if (filter->map[direct].name)
3831 free (filter->map[direct].name);
3832 filter->map[direct].name = NULL;
3833 filter->map[direct].map = NULL;
3834
3835 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3836 return 0;
3837
3838 group = peer->group;
3839 LIST_LOOP (group->peer, peer, nn)
3840 {
3841 filter = &peer->filter[afi][safi];
3842
3843 if (! peer->af_group[afi][safi])
3844 continue;
3845
3846 if (filter->map[direct].name)
3847 free (filter->map[direct].name);
3848 filter->map[direct].name = NULL;
3849 filter->map[direct].map = NULL;
3850 }
3851 return 0;
3852}
3853
3854/* Set unsuppress-map to the peer. */
3855int
paulfd79ac92004-10-13 05:06:08 +00003856peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
3857 const char *name)
paul718e3742002-12-13 20:15:29 +00003858{
3859 struct bgp_filter *filter;
3860 struct peer_group *group;
3861 struct listnode *nn;
3862
3863 if (! peer->afc[afi][safi])
3864 return BGP_ERR_PEER_INACTIVE;
3865
3866 if (peer_is_group_member (peer, afi, safi))
3867 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3868
3869 filter = &peer->filter[afi][safi];
3870
3871 if (filter->usmap.name)
3872 free (filter->usmap.name);
3873
3874 filter->usmap.name = strdup (name);
3875 filter->usmap.map = route_map_lookup_by_name (name);
3876
3877 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3878 return 0;
3879
3880 group = peer->group;
3881 LIST_LOOP (group->peer, peer, nn)
3882 {
3883 filter = &peer->filter[afi][safi];
3884
3885 if (! peer->af_group[afi][safi])
3886 continue;
3887
3888 if (filter->usmap.name)
3889 free (filter->usmap.name);
3890 filter->usmap.name = strdup (name);
3891 filter->usmap.map = route_map_lookup_by_name (name);
3892 }
3893 return 0;
3894}
3895
3896/* Unset route-map from the peer. */
3897int
3898peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
3899{
3900 struct bgp_filter *filter;
3901 struct peer_group *group;
3902 struct listnode *nn;
3903
3904 if (! peer->afc[afi][safi])
3905 return BGP_ERR_PEER_INACTIVE;
3906
3907 if (peer_is_group_member (peer, afi, safi))
3908 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3909
3910 filter = &peer->filter[afi][safi];
3911
3912 if (filter->usmap.name)
3913 free (filter->usmap.name);
3914 filter->usmap.name = NULL;
3915 filter->usmap.map = NULL;
3916
3917 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3918 return 0;
3919
3920 group = peer->group;
3921 LIST_LOOP (group->peer, peer, nn)
3922 {
3923 filter = &peer->filter[afi][safi];
3924
3925 if (! peer->af_group[afi][safi])
3926 continue;
3927
3928 if (filter->usmap.name)
3929 free (filter->usmap.name);
3930 filter->usmap.name = NULL;
3931 filter->usmap.map = NULL;
3932 }
3933 return 0;
3934}
3935
3936int
3937peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00003938 u_int32_t max, u_char threshold,
3939 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00003940{
3941 struct peer_group *group;
3942 struct listnode *nn;
3943
3944 if (! peer->afc[afi][safi])
3945 return BGP_ERR_PEER_INACTIVE;
3946
3947 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3948 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00003949 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00003950 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00003951 if (warning)
3952 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3953 else
3954 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3955
3956 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3957 return 0;
3958
3959 group = peer->group;
3960 LIST_LOOP (group->peer, peer, nn)
3961 {
3962 if (! peer->af_group[afi][safi])
3963 continue;
3964
3965 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3966 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00003967 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00003968 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00003969 if (warning)
3970 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3971 else
3972 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3973 }
3974 return 0;
3975}
3976
3977int
3978peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
3979{
3980 struct peer_group *group;
3981 struct listnode *nn;
3982
3983 if (! peer->afc[afi][safi])
3984 return BGP_ERR_PEER_INACTIVE;
3985
3986 /* apply peer-group config */
3987 if (peer->af_group[afi][safi])
3988 {
3989 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
3990 PEER_FLAG_MAX_PREFIX))
3991 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3992 else
3993 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3994
3995 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
3996 PEER_FLAG_MAX_PREFIX_WARNING))
3997 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3998 else
3999 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4000
4001 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004002 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004003 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004004 return 0;
4005 }
4006
4007 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4008 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4009 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004010 peer->pmax_threshold[afi][safi] = 0;
4011 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004012
4013 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4014 return 0;
4015
4016 group = peer->group;
4017 LIST_LOOP (group->peer, peer, nn)
4018 {
4019 if (! peer->af_group[afi][safi])
4020 continue;
4021
4022 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4023 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4024 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004025 peer->pmax_threshold[afi][safi] = 0;
4026 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004027 }
4028 return 0;
4029}
4030
4031int
4032peer_clear (struct peer *peer)
4033{
4034 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4035 {
hasso0a486e52005-02-01 20:57:17 +00004036 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4037 {
4038 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4039 if (peer->t_pmax_restart)
4040 {
4041 BGP_TIMER_OFF (peer->t_pmax_restart);
4042 if (BGP_DEBUG (events, EVENTS))
4043 zlog_debug ("%s Maximum-prefix restart timer canceled",
4044 peer->host);
4045 }
4046 BGP_EVENT_ADD (peer, BGP_Start);
4047 return 0;
4048 }
4049
paul718e3742002-12-13 20:15:29 +00004050 peer->v_start = BGP_INIT_START_TIMER;
4051 if (peer->status == Established)
4052 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4053 BGP_NOTIFY_CEASE_ADMIN_RESET);
4054 else
4055 BGP_EVENT_ADD (peer, BGP_Stop);
4056 }
4057 return 0;
4058}
4059
4060int
4061peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4062 enum bgp_clear_type stype)
4063{
4064 if (peer->status != Established)
4065 return 0;
4066
4067 if (! peer->afc[afi][safi])
4068 return BGP_ERR_AF_UNCONFIGURED;
4069
paulfee0f4c2004-09-13 05:12:46 +00004070 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4071 {
4072 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4073 return 0;
4074 bgp_check_local_routes_rsclient (peer, afi, safi);
4075 bgp_soft_reconfig_rsclient (peer, afi, safi);
4076 }
4077
paul718e3742002-12-13 20:15:29 +00004078 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4079 bgp_announce_route (peer, afi, safi);
4080
4081 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4082 {
4083 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4084 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4085 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4086 {
4087 struct bgp_filter *filter = &peer->filter[afi][safi];
4088 u_char prefix_type;
4089
4090 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4091 prefix_type = ORF_TYPE_PREFIX;
4092 else
4093 prefix_type = ORF_TYPE_PREFIX_OLD;
4094
4095 if (filter->plist[FILTER_IN].plist)
4096 {
4097 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4098 bgp_route_refresh_send (peer, afi, safi,
4099 prefix_type, REFRESH_DEFER, 1);
4100 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4101 REFRESH_IMMEDIATE, 0);
4102 }
4103 else
4104 {
4105 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4106 bgp_route_refresh_send (peer, afi, safi,
4107 prefix_type, REFRESH_IMMEDIATE, 1);
4108 else
4109 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4110 }
4111 return 0;
4112 }
4113 }
4114
4115 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4116 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4117 {
4118 /* If neighbor has soft reconfiguration inbound flag.
4119 Use Adj-RIB-In database. */
4120 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4121 bgp_soft_reconfig_in (peer, afi, safi);
4122 else
4123 {
4124 /* If neighbor has route refresh capability, send route refresh
4125 message to the peer. */
4126 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4127 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4128 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4129 else
4130 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4131 }
4132 }
4133 return 0;
4134}
4135
paulfd79ac92004-10-13 05:06:08 +00004136/* Display peer uptime.*/
4137/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004138char *
4139peer_uptime (time_t uptime2, char *buf, size_t len)
4140{
4141 time_t uptime1;
4142 struct tm *tm;
4143
4144 /* Check buffer length. */
4145 if (len < BGP_UPTIME_LEN)
4146 {
gdtc29fdba2004-12-09 14:46:46 +00004147 /* XXX: warning: long int format, size_t arg (arg 2) */
paula2b1ecd2004-10-31 18:58:09 +00004148 zlog_warn ("peer_uptime (): buffer shortage %ld", len);
paulfd79ac92004-10-13 05:06:08 +00004149 /* XXX: should return status instead of buf... */
4150 snprintf (buf, len, "<error> ");
4151 return buf;
paul718e3742002-12-13 20:15:29 +00004152 }
4153
4154 /* If there is no connection has been done before print `never'. */
4155 if (uptime2 == 0)
4156 {
4157 snprintf (buf, len, "never ");
4158 return buf;
4159 }
4160
4161 /* Get current time. */
4162 uptime1 = time (NULL);
4163 uptime1 -= uptime2;
4164 tm = gmtime (&uptime1);
4165
4166 /* Making formatted timer strings. */
4167#define ONE_DAY_SECOND 60*60*24
4168#define ONE_WEEK_SECOND 60*60*24*7
4169
4170 if (uptime1 < ONE_DAY_SECOND)
4171 snprintf (buf, len, "%02d:%02d:%02d",
4172 tm->tm_hour, tm->tm_min, tm->tm_sec);
4173 else if (uptime1 < ONE_WEEK_SECOND)
4174 snprintf (buf, len, "%dd%02dh%02dm",
4175 tm->tm_yday, tm->tm_hour, tm->tm_min);
4176 else
4177 snprintf (buf, len, "%02dw%dd%02dh",
4178 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4179 return buf;
4180}
4181
4182void
4183bgp_config_write_filter (struct vty *vty, struct peer *peer,
4184 afi_t afi, safi_t safi)
4185{
4186 struct bgp_filter *filter;
4187 struct bgp_filter *gfilter = NULL;
4188 char *addr;
4189 int in = FILTER_IN;
4190 int out = FILTER_OUT;
4191
4192 addr = peer->host;
4193 filter = &peer->filter[afi][safi];
4194 if (peer->af_group[afi][safi])
4195 gfilter = &peer->group->conf->filter[afi][safi];
4196
4197 /* distribute-list. */
4198 if (filter->dlist[in].name)
4199 if (! gfilter || ! gfilter->dlist[in].name
4200 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4201 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4202 filter->dlist[in].name, VTY_NEWLINE);
4203 if (filter->dlist[out].name && ! gfilter)
4204 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4205 filter->dlist[out].name, VTY_NEWLINE);
4206
4207 /* prefix-list. */
4208 if (filter->plist[in].name)
4209 if (! gfilter || ! gfilter->plist[in].name
4210 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4211 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4212 filter->plist[in].name, VTY_NEWLINE);
4213 if (filter->plist[out].name && ! gfilter)
4214 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4215 filter->plist[out].name, VTY_NEWLINE);
4216
4217 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004218 if (filter->map[RMAP_IN].name)
4219 if (! gfilter || ! gfilter->map[RMAP_IN].name
4220 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004221 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004222 filter->map[RMAP_IN].name, VTY_NEWLINE);
4223 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004224 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004225 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4226 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4227 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4228 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4229 if (filter->map[RMAP_EXPORT].name)
4230 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4231 || strcmp (filter->map[RMAP_EXPORT].name,
4232 gfilter->map[RMAP_EXPORT].name) != 0)
4233 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4234 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004235
4236 /* unsuppress-map */
4237 if (filter->usmap.name && ! gfilter)
4238 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4239 filter->usmap.name, VTY_NEWLINE);
4240
4241 /* filter-list. */
4242 if (filter->aslist[in].name)
4243 if (! gfilter || ! gfilter->aslist[in].name
4244 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4245 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4246 filter->aslist[in].name, VTY_NEWLINE);
4247 if (filter->aslist[out].name && ! gfilter)
4248 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4249 filter->aslist[out].name, VTY_NEWLINE);
4250}
4251
4252/* BGP peer configuration display function. */
4253void
4254bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4255 struct peer *peer, afi_t afi, safi_t safi)
4256{
4257 struct bgp_filter *filter;
4258 struct peer *g_peer = NULL;
4259 char buf[SU_ADDRSTRLEN];
4260 char *addr;
4261
4262 filter = &peer->filter[afi][safi];
4263 addr = peer->host;
4264 if (peer_group_active (peer))
4265 g_peer = peer->group->conf;
4266
4267 /************************************
4268 ****** Global to the neighbor ******
4269 ************************************/
4270 if (afi == AFI_IP && safi == SAFI_UNICAST)
4271 {
4272 /* remote-as. */
4273 if (! peer_group_active (peer))
4274 {
4275 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4276 vty_out (vty, " neighbor %s peer-group%s", addr,
4277 VTY_NEWLINE);
4278 if (peer->as)
4279 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4280 VTY_NEWLINE);
4281 }
4282 else
4283 {
4284 if (! g_peer->as)
4285 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4286 VTY_NEWLINE);
4287 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4288 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4289 peer->group->name, VTY_NEWLINE);
4290 }
4291
4292 /* local-as. */
4293 if (peer->change_local_as)
4294 if (! peer_group_active (peer))
4295 vty_out (vty, " neighbor %s local-as %d%s%s", addr,
4296 peer->change_local_as,
4297 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4298 " no-prepend" : "", VTY_NEWLINE);
4299
4300 /* Description. */
4301 if (peer->desc)
4302 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4303 VTY_NEWLINE);
4304
4305 /* Shutdown. */
4306 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4307 if (! peer_group_active (peer) ||
4308 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4309 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4310
4311 /* BGP port. */
4312 if (peer->port != BGP_PORT_DEFAULT)
4313 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
4314 VTY_NEWLINE);
4315
4316 /* Local interface name. */
4317 if (peer->ifname)
4318 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4319 VTY_NEWLINE);
4320
4321 /* Passive. */
4322 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4323 if (! peer_group_active (peer) ||
4324 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4325 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4326
4327 /* EBGP multihop. */
4328 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
4329 if (! peer_group_active (peer) ||
4330 g_peer->ttl != peer->ttl)
4331 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4332 VTY_NEWLINE);
4333
4334 /* Enforce multihop. */
4335 if (CHECK_FLAG (peer->flags, PEER_FLAG_ENFORCE_MULTIHOP))
4336 if (! peer_group_active (peer) ||
4337 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_ENFORCE_MULTIHOP))
4338 vty_out (vty, " neighbor %s enforce-multihop%s", addr, VTY_NEWLINE);
4339
4340 /* Update-source. */
4341 if (peer->update_if)
4342 if (! peer_group_active (peer) || ! g_peer->update_if
4343 || strcmp (g_peer->update_if, peer->update_if) != 0)
4344 vty_out (vty, " neighbor %s update-source %s%s", addr,
4345 peer->update_if, VTY_NEWLINE);
4346 if (peer->update_source)
4347 if (! peer_group_active (peer) || ! g_peer->update_source
4348 || sockunion_cmp (g_peer->update_source,
4349 peer->update_source) != 0)
4350 vty_out (vty, " neighbor %s update-source %s%s", addr,
4351 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4352 VTY_NEWLINE);
4353
paul718e3742002-12-13 20:15:29 +00004354 /* advertisement-interval */
4355 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4356 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4357 addr, peer->v_routeadv, VTY_NEWLINE);
4358
4359 /* timers. */
4360 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4361 && ! peer_group_active (peer))
4362 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4363 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4364
4365 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4366 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4367 peer->connect, VTY_NEWLINE);
4368
4369 /* Default weight. */
4370 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4371 if (! peer_group_active (peer) ||
4372 g_peer->weight != peer->weight)
4373 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4374 VTY_NEWLINE);
4375
paul718e3742002-12-13 20:15:29 +00004376 /* Dynamic capability. */
4377 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4378 if (! peer_group_active (peer) ||
4379 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4380 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4381 VTY_NEWLINE);
4382
4383 /* dont capability negotiation. */
4384 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4385 if (! peer_group_active (peer) ||
4386 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4387 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4388 VTY_NEWLINE);
4389
4390 /* override capability negotiation. */
4391 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4392 if (! peer_group_active (peer) ||
4393 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4394 vty_out (vty, " neighbor %s override-capability%s", addr,
4395 VTY_NEWLINE);
4396
4397 /* strict capability negotiation. */
4398 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4399 if (! peer_group_active (peer) ||
4400 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4401 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4402 VTY_NEWLINE);
4403
4404 if (! peer_group_active (peer))
4405 {
4406 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4407 {
4408 if (peer->afc[AFI_IP][SAFI_UNICAST])
4409 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4410 }
4411 else
4412 {
4413 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4414 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4415 }
4416 }
4417 }
4418
4419
4420 /************************************
4421 ****** Per AF to the neighbor ******
4422 ************************************/
4423
4424 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4425 {
4426 if (peer->af_group[afi][safi])
4427 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4428 peer->group->name, VTY_NEWLINE);
4429 else
4430 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4431 }
4432
4433 /* ORF capability. */
4434 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4435 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4436 if (! peer->af_group[afi][safi])
4437 {
4438 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4439
4440 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4441 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4442 vty_out (vty, " both");
4443 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4444 vty_out (vty, " send");
4445 else
4446 vty_out (vty, " receive");
4447 vty_out (vty, "%s", VTY_NEWLINE);
4448 }
4449
4450 /* Route reflector client. */
4451 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4452 && ! peer->af_group[afi][safi])
4453 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4454 VTY_NEWLINE);
4455
4456 /* Nexthop self. */
4457 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4458 && ! peer->af_group[afi][safi])
4459 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4460
4461 /* Remove private AS. */
4462 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4463 && ! peer->af_group[afi][safi])
4464 vty_out (vty, " neighbor %s remove-private-AS%s",
4465 addr, VTY_NEWLINE);
4466
4467 /* send-community print. */
4468 if (! peer->af_group[afi][safi])
4469 {
4470 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4471 {
4472 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4473 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4474 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4475 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4476 vty_out (vty, " neighbor %s send-community extended%s",
4477 addr, VTY_NEWLINE);
4478 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4479 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4480 }
4481 else
4482 {
4483 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4484 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4485 vty_out (vty, " no neighbor %s send-community both%s",
4486 addr, VTY_NEWLINE);
4487 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4488 vty_out (vty, " no neighbor %s send-community extended%s",
4489 addr, VTY_NEWLINE);
4490 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4491 vty_out (vty, " no neighbor %s send-community%s",
4492 addr, VTY_NEWLINE);
4493 }
4494 }
4495
4496 /* Default information */
4497 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4498 && ! peer->af_group[afi][safi])
4499 {
4500 vty_out (vty, " neighbor %s default-originate", addr);
4501 if (peer->default_rmap[afi][safi].name)
4502 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4503 vty_out (vty, "%s", VTY_NEWLINE);
4504 }
4505
4506 /* Soft reconfiguration inbound. */
4507 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4508 if (! peer->af_group[afi][safi] ||
4509 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4510 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4511 VTY_NEWLINE);
4512
4513 /* maximum-prefix. */
4514 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4515 if (! peer->af_group[afi][safi]
4516 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004517 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004518 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4519 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00004520 {
hasso0a486e52005-02-01 20:57:17 +00004521 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
4522 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
4523 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
4524 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
4525 vty_out (vty, " warning-only");
4526 if (peer->pmax_restart[afi][safi])
4527 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
4528 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00004529 }
paul718e3742002-12-13 20:15:29 +00004530
4531 /* Route server client. */
4532 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
4533 && ! peer->af_group[afi][safi])
4534 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
4535
4536 /* Allow AS in. */
4537 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
4538 if (! peer_group_active (peer)
4539 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
4540 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
4541 {
4542 if (peer->allowas_in[afi][safi] == 3)
4543 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
4544 else
4545 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
4546 peer->allowas_in[afi][safi], VTY_NEWLINE);
4547 }
4548
4549 /* Filter. */
4550 bgp_config_write_filter (vty, peer, afi, safi);
4551
4552 /* atribute-unchanged. */
4553 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4554 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4555 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4556 && ! peer->af_group[afi][safi])
4557 {
4558 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4559 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4560 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4561 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
4562 else
4563 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
4564 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
4565 " as-path" : "",
4566 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
4567 " next-hop" : "",
4568 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
4569 " med" : "", VTY_NEWLINE);
4570 }
4571}
4572
4573/* Display "address-family" configuration header. */
4574void
4575bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
4576 int *write)
4577{
4578 if (*write)
4579 return;
4580
4581 if (afi == AFI_IP && safi == SAFI_UNICAST)
4582 return;
4583
4584 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
4585
4586 if (afi == AFI_IP)
4587 {
4588 if (safi == SAFI_MULTICAST)
4589 vty_out (vty, "ipv4 multicast");
4590 else if (safi == SAFI_MPLS_VPN)
4591 vty_out (vty, "vpnv4 unicast");
4592 }
4593 else if (afi == AFI_IP6)
4594 vty_out (vty, "ipv6");
4595
4596 vty_out (vty, "%s", VTY_NEWLINE);
4597
4598 *write = 1;
4599}
4600
4601/* Address family based peer configuration display. */
4602int
4603bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
4604 safi_t safi)
4605{
4606 int write = 0;
4607 struct peer *peer;
4608 struct peer_group *group;
4609 struct listnode *nn;
4610
4611 bgp_config_write_network (vty, bgp, afi, safi, &write);
4612
4613 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
4614
4615 LIST_LOOP (bgp->group, group, nn)
4616 {
4617 if (group->conf->afc[afi][safi])
4618 {
4619 bgp_config_write_family_header (vty, afi, safi, &write);
4620 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
4621 }
4622 }
4623 LIST_LOOP (bgp->peer, peer, nn)
4624 {
4625 if (peer->afc[afi][safi])
4626 {
4627 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4628 {
4629 bgp_config_write_family_header (vty, afi, safi, &write);
4630 bgp_config_write_peer (vty, bgp, peer, afi, safi);
4631 }
4632 }
4633 }
4634 if (write)
4635 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
4636
4637 return write;
4638}
4639
4640int
4641bgp_config_write (struct vty *vty)
4642{
4643 int write = 0;
4644 struct bgp *bgp;
4645 struct peer_group *group;
4646 struct peer *peer;
4647 struct listnode *nn, *nm, *no;
4648
4649 /* BGP Multiple instance. */
4650 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4651 {
4652 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
4653 write++;
4654 }
4655
4656 /* BGP Config type. */
4657 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4658 {
4659 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
4660 write++;
4661 }
4662
4663 /* BGP configuration. */
4664 LIST_LOOP (bm->bgp, bgp, nn)
4665 {
4666 if (write)
4667 vty_out (vty, "!%s", VTY_NEWLINE);
4668
4669 /* Router bgp ASN */
4670 vty_out (vty, "router bgp %d", bgp->as);
4671
4672 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4673 {
4674 if (bgp->name)
4675 vty_out (vty, " view %s", bgp->name);
4676 }
4677 vty_out (vty, "%s", VTY_NEWLINE);
4678
4679 /* No Synchronization */
4680 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4681 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
4682
4683 /* BGP fast-external-failover. */
4684 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
4685 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
4686
4687 /* BGP router ID. */
4688 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
4689 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
4690 VTY_NEWLINE);
4691
paul848973c2003-08-13 00:32:49 +00004692 /* BGP log-neighbor-changes. */
4693 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
4694 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
4695
paul718e3742002-12-13 20:15:29 +00004696 /* BGP configuration. */
4697 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
4698 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
4699
4700 /* BGP default ipv4-unicast. */
4701 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4702 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
4703
4704 /* BGP default local-preference. */
4705 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
4706 vty_out (vty, " bgp default local-preference %d%s",
4707 bgp->default_local_pref, VTY_NEWLINE);
4708
4709 /* BGP client-to-client reflection. */
4710 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
4711 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
4712
4713 /* BGP cluster ID. */
4714 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
4715 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
4716 VTY_NEWLINE);
4717
hassoe0701b72004-05-20 09:19:34 +00004718 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00004719 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00004720 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
4721 VTY_NEWLINE);
4722
4723 /* Confederation peer */
4724 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00004725 {
hassoe0701b72004-05-20 09:19:34 +00004726 int i;
paul718e3742002-12-13 20:15:29 +00004727
hassoe0701b72004-05-20 09:19:34 +00004728 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00004729
hassoe0701b72004-05-20 09:19:34 +00004730 for (i = 0; i < bgp->confed_peers_cnt; i++)
4731 vty_out(vty, " %d", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00004732
hassoe0701b72004-05-20 09:19:34 +00004733 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004734 }
4735
4736 /* BGP enforce-first-as. */
4737 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
4738 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
4739
4740 /* BGP deterministic-med. */
4741 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
4742 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00004743
4744 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00004745 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
4746 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
4747 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00004748 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
4749 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
4750
paul718e3742002-12-13 20:15:29 +00004751 /* BGP bestpath method. */
4752 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
4753 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
4754 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
4755 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
4756 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
4757 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4758 {
4759 vty_out (vty, " bgp bestpath med");
4760 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
4761 vty_out (vty, " confed");
4762 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4763 vty_out (vty, " missing-as-worst");
4764 vty_out (vty, "%s", VTY_NEWLINE);
4765 }
4766
4767 /* BGP network import check. */
4768 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
4769 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
4770
4771 /* BGP scan interval. */
4772 bgp_config_write_scan_time (vty);
4773
4774 /* BGP flag dampening. */
4775 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
4776 BGP_CONFIG_DAMPENING))
4777 bgp_config_write_damp (vty);
4778
4779 /* BGP static route configuration. */
4780 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4781
4782 /* BGP redistribute configuration. */
4783 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4784
4785 /* BGP timers configuration. */
4786 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
4787 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
4788 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
4789 bgp->default_holdtime, VTY_NEWLINE);
4790
4791 /* peer-group */
4792 LIST_LOOP (bgp->group, group, nm)
4793 {
4794 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
4795 }
4796
4797 /* Normal neighbor configuration. */
4798 LIST_LOOP (bgp->peer, peer, no)
4799 {
4800 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4801 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
4802 }
4803
4804 /* Distance configuration. */
4805 bgp_config_write_distance (vty, bgp);
4806
4807 /* No auto-summary */
4808 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4809 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
4810
4811 /* IPv4 multicast configuration. */
4812 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
4813
4814 /* IPv4 VPN configuration. */
4815 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
4816
4817 /* IPv6 unicast configuration. */
4818 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
4819
4820 write++;
4821 }
4822 return write;
4823}
4824
4825void
4826bgp_master_init ()
4827{
4828 memset (&bgp_master, 0, sizeof (struct bgp_master));
4829
4830 bm = &bgp_master;
4831 bm->bgp = list_new ();
4832 bm->port = BGP_PORT_DEFAULT;
4833 bm->master = thread_master_create ();
4834 bm->start_time = time (NULL);
4835}
4836
4837void
4838bgp_init ()
4839{
4840 void bgp_zebra_init ();
4841 void bgp_route_map_init ();
4842 void bgp_filter_init ();
4843
4844 /* BGP VTY commands installation. */
4845 bgp_vty_init ();
4846
4847 /* Create BGP server socket. */
4848 bgp_socket (NULL, bm->port);
4849
4850 /* Init zebra. */
4851 bgp_zebra_init ();
4852
4853 /* BGP inits. */
4854 bgp_attr_init ();
4855 bgp_debug_init ();
4856 bgp_dump_init ();
4857 bgp_route_init ();
4858 bgp_route_map_init ();
4859 bgp_scan_init ();
4860 bgp_mplsvpn_init ();
4861
4862 /* Access list initialize. */
4863 access_list_init ();
4864 access_list_add_hook (peer_distribute_update);
4865 access_list_delete_hook (peer_distribute_update);
4866
4867 /* Filter list initialize. */
4868 bgp_filter_init ();
4869 as_list_add_hook (peer_aslist_update);
4870 as_list_delete_hook (peer_aslist_update);
4871
4872 /* Prefix list initialize.*/
4873 prefix_list_init ();
4874 prefix_list_add_hook (peer_prefix_list_update);
4875 prefix_list_delete_hook (peer_prefix_list_update);
4876
4877 /* Community list initialize. */
4878 bgp_clist = community_list_init ();
4879
4880#ifdef HAVE_SNMP
4881 bgp_snmp_init ();
4882#endif /* HAVE_SNMP */
4883}
paul545acaf2004-04-20 15:13:15 +00004884
4885void
4886bgp_terminate ()
4887{
paul545acaf2004-04-20 15:13:15 +00004888 struct bgp *bgp;
4889 struct peer *peer;
4890 struct listnode *nn;
4891 struct listnode *mm;
4892
paul545acaf2004-04-20 15:13:15 +00004893 LIST_LOOP (bm->bgp, bgp, nn)
4894 LIST_LOOP (bgp->peer, peer, mm)
4895 if (peer->status == Established)
4896 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4897 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
4898
4899 bgp_cleanup_routes ();
4900}
4901