blob: 26c4455355dc539fd15c06268f0584b6ff9bf93e [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;
708 peer->version = BGP_VERSION_4;
709 peer->weight = 0;
710
711 /* Set default flags. */
712 for (afi = AFI_IP; afi < AFI_MAX; afi++)
713 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
714 {
715 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
716 {
717 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
718 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
719 }
720 peer->orf_plist[afi][safi] = NULL;
721 }
722 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
723
724 /* Create buffers. */
725 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
726 peer->obuf = stream_fifo_new ();
727 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
728
729 bgp_sync_init (peer);
730
731 /* Get service port number. */
732 sp = getservbyname ("bgp", "tcp");
733 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
734
735 return peer;
736}
737
738/* Create new BGP peer. */
739struct peer *
740peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
741 as_t remote_as, afi_t afi, safi_t safi)
742{
743 int active;
744 struct peer *peer;
745 char buf[SU_ADDRSTRLEN];
746
747 peer = peer_new ();
748 peer->bgp = bgp;
749 peer->su = *su;
750 peer->local_as = local_as;
751 peer->as = remote_as;
752 peer->local_id = bgp->router_id;
753 peer->v_holdtime = bgp->default_holdtime;
754 peer->v_keepalive = bgp->default_keepalive;
755 if (peer_sort (peer) == BGP_PEER_IBGP)
756 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
757 else
758 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
759 listnode_add_sort (bgp->peer, peer);
760
761 active = peer_active (peer);
762
763 if (afi && safi)
764 peer->afc[afi][safi] = 1;
765
766 /* Last read time set */
767 peer->readtime = time (NULL);
768
paul848973c2003-08-13 00:32:49 +0000769 /* Last reset time set */
770 peer->resettime = time (NULL);
771
paul718e3742002-12-13 20:15:29 +0000772 /* Default TTL set. */
773 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
774
775 /* Make peer's address string. */
776 sockunion2str (su, buf, SU_ADDRSTRLEN);
777 peer->host = strdup (buf);
778
779 /* Set up peer's events and timers. */
780 if (! active && peer_active (peer))
781 bgp_timer_set (peer);
782
783 return peer;
784}
785
pauleb821182004-05-01 08:44:08 +0000786/* Make accept BGP peer. Called from bgp_accept (). */
787struct peer *
788peer_create_accept (struct bgp *bgp)
789{
790 struct peer *peer;
791
792 peer = peer_new ();
793 peer->bgp = bgp;
794 listnode_add_sort (bgp->peer, peer);
795
796 return peer;
797}
798
paul718e3742002-12-13 20:15:29 +0000799/* Change peer's AS number. */
800void
801peer_as_change (struct peer *peer, as_t as)
802{
803 int type;
804
805 /* Stop peer. */
806 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
807 {
808 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000809 {
810 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
811 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
812 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
813 }
paul718e3742002-12-13 20:15:29 +0000814 else
815 BGP_EVENT_ADD (peer, BGP_Stop);
816 }
817 type = peer_sort (peer);
818 peer->as = as;
819
paul848973c2003-08-13 00:32:49 +0000820 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
821 && ! bgp_confederation_peers_check (peer->bgp, as)
822 && peer->bgp->as != as)
823 peer->local_as = peer->bgp->confed_id;
824 else
825 peer->local_as = peer->bgp->as;
826
paul718e3742002-12-13 20:15:29 +0000827 /* Advertisement-interval reset */
828 if (peer_sort (peer) == BGP_PEER_IBGP)
829 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
830 else
831 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
832
833 /* TTL reset */
834 if (peer_sort (peer) == BGP_PEER_IBGP)
835 peer->ttl = 255;
836 else if (type == BGP_PEER_IBGP)
837 peer->ttl = 1;
838
839 /* reflector-client reset */
840 if (peer_sort (peer) != BGP_PEER_IBGP)
841 {
842 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
843 PEER_FLAG_REFLECTOR_CLIENT);
844 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
845 PEER_FLAG_REFLECTOR_CLIENT);
846 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
847 PEER_FLAG_REFLECTOR_CLIENT);
848 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
849 PEER_FLAG_REFLECTOR_CLIENT);
850 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
851 PEER_FLAG_REFLECTOR_CLIENT);
852 }
853
854 /* local-as reset */
855 if (peer_sort (peer) != BGP_PEER_EBGP)
856 {
857 peer->change_local_as = 0;
858 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
859 }
860}
861
862/* If peer does not exist, create new one. If peer already exists,
863 set AS number to the peer. */
864int
865peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
866 afi_t afi, safi_t safi)
867{
868 struct peer *peer;
869 as_t local_as;
870
871 peer = peer_lookup (bgp, su);
872
873 if (peer)
874 {
875 /* When this peer is a member of peer-group. */
876 if (peer->group)
877 {
878 if (peer->group->conf->as)
879 {
880 /* Return peer group's AS number. */
881 *as = peer->group->conf->as;
882 return BGP_ERR_PEER_GROUP_MEMBER;
883 }
884 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
885 {
886 if (bgp->as != *as)
887 {
888 *as = peer->as;
889 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
890 }
891 }
892 else
893 {
894 if (bgp->as == *as)
895 {
896 *as = peer->as;
897 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
898 }
899 }
900 }
901
902 /* Existing peer's AS number change. */
903 if (peer->as != *as)
904 peer_as_change (peer, *as);
905 }
906 else
907 {
908
909 /* If the peer is not part of our confederation, and its not an
910 iBGP peer then spoof the source AS */
911 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
912 && ! bgp_confederation_peers_check (bgp, *as)
913 && bgp->as != *as)
914 local_as = bgp->confed_id;
915 else
916 local_as = bgp->as;
917
918 /* If this is IPv4 unicast configuration and "no bgp default
919 ipv4-unicast" is specified. */
920
921 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
922 && afi == AFI_IP && safi == SAFI_UNICAST)
923 peer = peer_create (su, bgp, local_as, *as, 0, 0);
924 else
925 peer = peer_create (su, bgp, local_as, *as, afi, safi);
926 }
927
928 return 0;
929}
930
931/* Activate the peer or peer group for specified AFI and SAFI. */
932int
933peer_activate (struct peer *peer, afi_t afi, safi_t safi)
934{
935 int active;
936
937 if (peer->afc[afi][safi])
938 return 0;
939
940 /* Activate the address family configuration. */
941 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
942 peer->afc[afi][safi] = 1;
943 else
944 {
945 active = peer_active (peer);
946
947 peer->afc[afi][safi] = 1;
948
949 if (! active && peer_active (peer))
950 bgp_timer_set (peer);
951 else
952 {
953 if (peer->status == Established)
954 {
955 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
956 {
957 peer->afc_adv[afi][safi] = 1;
958 bgp_capability_send (peer, afi, safi,
959 CAPABILITY_CODE_MP,
960 CAPABILITY_ACTION_SET);
961 if (peer->afc_recv[afi][safi])
962 {
963 peer->afc_nego[afi][safi] = 1;
964 bgp_announce_route (peer, afi, safi);
965 }
966 }
967 else
hassoe0701b72004-05-20 09:19:34 +0000968 {
969 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
970 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
971 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
972 }
paul718e3742002-12-13 20:15:29 +0000973 }
974 }
975 }
976 return 0;
977}
978
979int
980peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
981{
982 struct peer_group *group;
983 struct peer *peer1;
984 struct listnode *nn;
985
986 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
987 {
988 group = peer->group;
989
990 LIST_LOOP (group->peer, peer1, nn)
991 {
992 if (peer1->af_group[afi][safi])
993 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
994 }
995 }
996 else
997 {
998 if (peer->af_group[afi][safi])
999 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1000 }
1001
1002 if (! peer->afc[afi][safi])
1003 return 0;
1004
1005 /* De-activate the address family configuration. */
1006 peer->afc[afi][safi] = 0;
1007 peer_af_flag_reset (peer, afi, safi);
1008
1009 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1010 {
1011 if (peer->status == Established)
1012 {
1013 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1014 {
1015 peer->afc_adv[afi][safi] = 0;
1016 peer->afc_nego[afi][safi] = 0;
1017
1018 if (peer_active_nego (peer))
1019 {
1020 bgp_capability_send (peer, afi, safi,
1021 CAPABILITY_CODE_MP,
1022 CAPABILITY_ACTION_UNSET);
1023 bgp_clear_route (peer, afi, safi);
1024 peer->pcount[afi][safi] = 0;
1025 }
1026 else
hassoe0701b72004-05-20 09:19:34 +00001027 {
1028 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1029 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1030 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1031 }
paul718e3742002-12-13 20:15:29 +00001032 }
1033 else
hassoe0701b72004-05-20 09:19:34 +00001034 {
1035 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1036 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1037 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1038 }
paul718e3742002-12-13 20:15:29 +00001039 }
1040 }
1041 return 0;
1042}
1043
1044/* Delete peer from confguration. */
1045int
1046peer_delete (struct peer *peer)
1047{
1048 int i;
1049 afi_t afi;
1050 safi_t safi;
1051 struct bgp *bgp;
1052 struct bgp_filter *filter;
1053
1054 bgp = peer->bgp;
1055
1056 /* If this peer belongs to peer group. Clearn up the
1057 relationship. */
1058 if (peer->group)
1059 {
1060 listnode_delete (peer->group->peer, peer);
1061 peer->group = NULL;
1062 }
1063
1064 /* Withdraw all information from routing table. We can not use
1065 BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1066 executed after peer structure is deleted. */
hassoe0701b72004-05-20 09:19:34 +00001067 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001068 bgp_stop (peer);
1069 bgp_fsm_change_status (peer, Idle);
1070
1071 /* Stop all timers. */
1072 BGP_TIMER_OFF (peer->t_start);
1073 BGP_TIMER_OFF (peer->t_connect);
1074 BGP_TIMER_OFF (peer->t_holdtime);
1075 BGP_TIMER_OFF (peer->t_keepalive);
1076 BGP_TIMER_OFF (peer->t_asorig);
1077 BGP_TIMER_OFF (peer->t_routeadv);
1078
1079 /* Delete from all peer list. */
1080 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
paulfee0f4c2004-09-13 05:12:46 +00001081 {
paul718e3742002-12-13 20:15:29 +00001082 listnode_delete (bgp->peer, peer);
paulfee0f4c2004-09-13 05:12:46 +00001083 if (peer_rsclient_active (peer))
1084 listnode_delete (bgp->rsclient, peer);
1085 }
1086
1087 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1088 member of a peer_group. */
1089 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1090 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1091 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
1092 bgp_table_finish (peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001093
1094 /* Buffer. */
1095 if (peer->ibuf)
1096 stream_free (peer->ibuf);
1097
1098 if (peer->obuf)
1099 stream_fifo_free (peer->obuf);
1100
1101 if (peer->work)
1102 stream_free (peer->work);
1103
1104 /* Free allocated host character. */
1105 if (peer->host)
1106 free (peer->host);
1107
1108 /* Local and remote addresses. */
1109 if (peer->su_local)
1110 XFREE (MTYPE_TMP, peer->su_local);
1111 if (peer->su_remote)
1112 XFREE (MTYPE_TMP, peer->su_remote);
1113
1114 /* Peer description string. */
1115 if (peer->desc)
1116 XFREE (MTYPE_TMP, peer->desc);
1117
1118 bgp_sync_delete (peer);
1119
1120 /* Free filter related memory. */
1121 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1122 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1123 {
1124 filter = &peer->filter[afi][safi];
1125
1126 for (i = FILTER_IN; i < FILTER_MAX; i++)
1127 {
1128 if (filter->dlist[i].name)
1129 free (filter->dlist[i].name);
1130 if (filter->plist[i].name)
1131 free (filter->plist[i].name);
1132 if (filter->aslist[i].name)
1133 free (filter->aslist[i].name);
paulfee0f4c2004-09-13 05:12:46 +00001134 }
1135 for (i = RMAP_IN; i < RMAP_MAX; i++)
1136 {
paul718e3742002-12-13 20:15:29 +00001137 if (filter->map[i].name)
1138 free (filter->map[i].name);
1139 }
1140
1141 if (filter->usmap.name)
1142 free (filter->usmap.name);
1143
1144 if (peer->default_rmap[afi][safi].name)
1145 free (peer->default_rmap[afi][safi].name);
1146 }
1147
1148 /* Update source configuration. */
1149 if (peer->update_source)
1150 {
1151 sockunion_free (peer->update_source);
1152 peer->update_source = NULL;
1153 }
1154 if (peer->update_if)
1155 {
1156 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1157 peer->update_if = NULL;
1158 }
1159
1160 /* Free peer structure. */
1161 XFREE (MTYPE_BGP_PEER, peer);
1162
1163 return 0;
1164}
1165
1166int
1167peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1168{
1169 return strcmp (g1->name, g2->name);
1170}
1171
1172/* If peer is configured at least one address family return 1. */
1173int
1174peer_group_active (struct peer *peer)
1175{
1176 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1177 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1178 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1179 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1180 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1181 return 1;
1182 return 0;
1183}
1184
1185/* Peer group cofiguration. */
1186static struct peer_group *
1187peer_group_new ()
1188{
1189 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1190 sizeof (struct peer_group));
1191}
1192
1193void
1194peer_group_free (struct peer_group *group)
1195{
1196 XFREE (MTYPE_PEER_GROUP, group);
1197}
1198
1199struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001200peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001201{
1202 struct peer_group *group;
1203 struct listnode *nn;
1204
1205 LIST_LOOP (bgp->group, group, nn)
1206 {
1207 if (strcmp (group->name, name) == 0)
1208 return group;
1209 }
1210 return NULL;
1211}
1212
1213struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001214peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001215{
1216 struct peer_group *group;
1217
1218 group = peer_group_lookup (bgp, name);
1219 if (group)
1220 return group;
1221
1222 group = peer_group_new ();
1223 group->bgp = bgp;
1224 group->name = strdup (name);
1225 group->peer = list_new ();
1226 group->conf = peer_new ();
1227 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1228 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
1229 group->conf->host = strdup (name);
1230 group->conf->bgp = bgp;
1231 group->conf->group = group;
1232 group->conf->as = 0;
1233 group->conf->ttl = 1;
1234 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1235 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1236 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1237 group->conf->keepalive = 0;
1238 group->conf->holdtime = 0;
1239 group->conf->connect = 0;
1240 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1241 listnode_add_sort (bgp->group, group);
1242
1243 return 0;
1244}
1245
1246void
1247peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1248 afi_t afi, safi_t safi)
1249{
1250 int in = FILTER_IN;
1251 int out = FILTER_OUT;
1252 struct peer *conf;
1253 struct bgp_filter *pfilter;
1254 struct bgp_filter *gfilter;
1255
1256 conf = group->conf;
1257 pfilter = &peer->filter[afi][safi];
1258 gfilter = &conf->filter[afi][safi];
1259
1260 /* remote-as */
1261 if (conf->as)
1262 peer->as = conf->as;
1263
1264 /* remote-as */
1265 if (conf->change_local_as)
1266 peer->change_local_as = conf->change_local_as;
1267
1268 /* TTL */
1269 peer->ttl = conf->ttl;
1270
1271 /* Weight */
1272 peer->weight = conf->weight;
1273
1274 /* peer flags apply */
1275 peer->flags = conf->flags;
1276 /* peer af_flags apply */
1277 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1278 /* peer config apply */
1279 peer->config = conf->config;
1280
1281 /* peer timers apply */
1282 peer->holdtime = conf->holdtime;
1283 peer->keepalive = conf->keepalive;
1284 peer->connect = conf->connect;
1285 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1286 peer->v_connect = conf->connect;
1287 else
1288 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1289
1290 /* advertisement-interval reset */
1291 if (peer_sort (peer) == BGP_PEER_IBGP)
1292 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1293 else
1294 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1295
1296 /* maximum-prefix */
1297 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001298 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
paul718e3742002-12-13 20:15:29 +00001299
1300 /* allowas-in */
1301 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1302
paulfee0f4c2004-09-13 05:12:46 +00001303 /* route-server-client */
1304 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1305 {
1306 /* Make peer's RIB point to group's RIB. */
1307 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1308
1309 /* Import policy. */
1310 if (pfilter->map[RMAP_IMPORT].name)
1311 free (pfilter->map[RMAP_IMPORT].name);
1312 if (gfilter->map[RMAP_IMPORT].name)
1313 {
1314 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1315 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1316 }
1317 else
1318 {
1319 pfilter->map[RMAP_IMPORT].name = NULL;
1320 pfilter->map[RMAP_IMPORT].map = NULL;
1321 }
1322
1323 /* Export policy. */
1324 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1325 {
1326 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1327 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1328 }
1329 }
1330
paul718e3742002-12-13 20:15:29 +00001331 /* default-originate route-map */
1332 if (conf->default_rmap[afi][safi].name)
1333 {
1334 if (peer->default_rmap[afi][safi].name)
1335 free (peer->default_rmap[afi][safi].name);
1336 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1337 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1338 }
1339
1340 /* update-source apply */
1341 if (conf->update_source)
1342 {
1343 if (peer->update_source)
1344 sockunion_free (peer->update_source);
1345 if (peer->update_if)
1346 {
1347 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1348 peer->update_if = NULL;
1349 }
1350 peer->update_source = sockunion_dup (conf->update_source);
1351 }
1352 else if (conf->update_if)
1353 {
1354 if (peer->update_if)
1355 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1356 if (peer->update_source)
1357 {
1358 sockunion_free (peer->update_source);
1359 peer->update_source = NULL;
1360 }
1361 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1362 }
1363
1364 /* inbound filter apply */
1365 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1366 {
1367 if (pfilter->dlist[in].name)
1368 free (pfilter->dlist[in].name);
1369 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1370 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1371 }
1372 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1373 {
1374 if (pfilter->plist[in].name)
1375 free (pfilter->plist[in].name);
1376 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1377 pfilter->plist[in].plist = gfilter->plist[in].plist;
1378 }
1379 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1380 {
1381 if (pfilter->aslist[in].name)
1382 free (pfilter->aslist[in].name);
1383 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1384 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1385 }
paulfee0f4c2004-09-13 05:12:46 +00001386 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001387 {
paulfee0f4c2004-09-13 05:12:46 +00001388 if (pfilter->map[RMAP_IN].name)
1389 free (pfilter->map[RMAP_IN].name);
1390 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1391 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001392 }
1393
1394 /* outbound filter apply */
1395 if (gfilter->dlist[out].name)
1396 {
1397 if (pfilter->dlist[out].name)
1398 free (pfilter->dlist[out].name);
1399 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1400 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1401 }
1402 else
1403 {
1404 if (pfilter->dlist[out].name)
1405 free (pfilter->dlist[out].name);
1406 pfilter->dlist[out].name = NULL;
1407 pfilter->dlist[out].alist = NULL;
1408 }
1409 if (gfilter->plist[out].name)
1410 {
1411 if (pfilter->plist[out].name)
1412 free (pfilter->plist[out].name);
1413 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1414 pfilter->plist[out].plist = gfilter->plist[out].plist;
1415 }
1416 else
1417 {
1418 if (pfilter->plist[out].name)
1419 free (pfilter->plist[out].name);
1420 pfilter->plist[out].name = NULL;
1421 pfilter->plist[out].plist = NULL;
1422 }
1423 if (gfilter->aslist[out].name)
1424 {
1425 if (pfilter->aslist[out].name)
1426 free (pfilter->aslist[out].name);
1427 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1428 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1429 }
1430 else
1431 {
1432 if (pfilter->aslist[out].name)
1433 free (pfilter->aslist[out].name);
1434 pfilter->aslist[out].name = NULL;
1435 pfilter->aslist[out].aslist = NULL;
1436 }
paulfee0f4c2004-09-13 05:12:46 +00001437 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001438 {
paulfee0f4c2004-09-13 05:12:46 +00001439 if (pfilter->map[RMAP_OUT].name)
1440 free (pfilter->map[RMAP_OUT].name);
1441 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1442 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001443 }
1444 else
1445 {
paulfee0f4c2004-09-13 05:12:46 +00001446 if (pfilter->map[RMAP_OUT].name)
1447 free (pfilter->map[RMAP_OUT].name);
1448 pfilter->map[RMAP_OUT].name = NULL;
1449 pfilter->map[RMAP_OUT].map = NULL;
1450 }
1451
1452 /* RS-client's import/export route-maps. */
1453 if (gfilter->map[RMAP_IMPORT].name)
1454 {
1455 if (pfilter->map[RMAP_IMPORT].name)
1456 free (pfilter->map[RMAP_IMPORT].name);
1457 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1458 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1459 }
1460 else
1461 {
1462 if (pfilter->map[RMAP_IMPORT].name)
1463 free (pfilter->map[RMAP_IMPORT].name);
1464 pfilter->map[RMAP_IMPORT].name = NULL;
1465 pfilter->map[RMAP_IMPORT].map = NULL;
1466 }
1467 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1468 {
1469 if (pfilter->map[RMAP_EXPORT].name)
1470 free (pfilter->map[RMAP_EXPORT].name);
1471 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1472 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001473 }
1474
1475 if (gfilter->usmap.name)
1476 {
1477 if (pfilter->usmap.name)
1478 free (pfilter->usmap.name);
1479 pfilter->usmap.name = strdup (gfilter->usmap.name);
1480 pfilter->usmap.map = gfilter->usmap.map;
1481 }
1482 else
1483 {
1484 if (pfilter->usmap.name)
1485 free (pfilter->usmap.name);
1486 pfilter->usmap.name = NULL;
1487 pfilter->usmap.map = NULL;
1488 }
1489}
1490
1491/* Peer group's remote AS configuration. */
1492int
paulfd79ac92004-10-13 05:06:08 +00001493peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001494{
1495 struct peer_group *group;
1496 struct peer *peer;
1497 struct listnode *nn;
1498
1499 group = peer_group_lookup (bgp, group_name);
1500 if (! group)
1501 return -1;
1502
1503 if (group->conf->as == *as)
1504 return 0;
1505
1506 /* When we setup peer-group AS number all peer group member's AS
1507 number must be updated to same number. */
1508 peer_as_change (group->conf, *as);
1509
1510 LIST_LOOP (group->peer, peer, nn)
1511 {
1512 if (peer->as != *as)
1513 peer_as_change (peer, *as);
1514 }
1515
1516 return 0;
1517}
1518
1519int
1520peer_group_delete (struct peer_group *group)
1521{
1522 struct bgp *bgp;
1523 struct peer *peer;
1524 struct listnode *nn;
1525
1526 bgp = group->bgp;
1527
1528 LIST_LOOP (group->peer, peer, nn)
1529 {
1530 peer->group = NULL;
1531 peer_delete (peer);
1532 }
1533 list_delete (group->peer);
1534
1535 free (group->name);
1536 group->name = NULL;
1537
1538 group->conf->group = NULL;
1539 peer_delete (group->conf);
1540
1541 /* Delete from all peer_group list. */
1542 listnode_delete (bgp->group, group);
1543
1544 peer_group_free (group);
1545
1546 return 0;
1547}
1548
1549int
1550peer_group_remote_as_delete (struct peer_group *group)
1551{
1552 struct peer *peer;
1553 struct listnode *nn;
1554
1555 if (! group->conf->as)
1556 return 0;
1557
1558 LIST_LOOP (group->peer, peer, nn)
1559 {
1560 peer->group = NULL;
1561 peer_delete (peer);
1562 }
1563 list_delete_all_node (group->peer);
1564
1565 group->conf->as = 0;
1566
1567 return 0;
1568}
1569
1570/* Bind specified peer to peer group. */
1571int
1572peer_group_bind (struct bgp *bgp, union sockunion *su,
1573 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1574{
1575 struct peer *peer;
1576 int first_member = 0;
1577
1578 /* Check peer group's address family. */
1579 if (! group->conf->afc[afi][safi])
1580 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1581
1582 /* Lookup the peer. */
1583 peer = peer_lookup (bgp, su);
1584
1585 /* Create a new peer. */
1586 if (! peer)
1587 {
1588 if (! group->conf->as)
1589 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1590
1591 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1592 peer->group = group;
1593 peer->af_group[afi][safi] = 1;
1594 listnode_add (group->peer, peer);
1595 peer_group2peer_config_copy (group, peer, afi, safi);
1596
1597 return 0;
1598 }
1599
1600 /* When the peer already belongs to peer group, check the consistency. */
1601 if (peer->af_group[afi][safi])
1602 {
1603 if (strcmp (peer->group->name, group->name) != 0)
1604 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1605
1606 return 0;
1607 }
1608
1609 /* Check current peer group configuration. */
1610 if (peer_group_active (peer)
1611 && strcmp (peer->group->name, group->name) != 0)
1612 return BGP_ERR_PEER_GROUP_MISMATCH;
1613
1614 if (! group->conf->as)
1615 {
1616 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1617 && peer_sort (group->conf) != peer_sort (peer))
1618 {
1619 if (as)
1620 *as = peer->as;
1621 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1622 }
1623
1624 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1625 first_member = 1;
1626 }
1627
1628 peer->af_group[afi][safi] = 1;
1629 peer->afc[afi][safi] = 1;
1630 if (! peer->group)
1631 {
1632 peer->group = group;
1633 listnode_add (group->peer, peer);
1634 }
1635
1636 if (first_member)
1637 {
1638 /* Advertisement-interval reset */
1639 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1640 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1641 else
1642 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1643
1644 /* ebgp-multihop reset */
1645 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1646 group->conf->ttl = 255;
1647
1648 /* local-as reset */
1649 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1650 {
1651 group->conf->change_local_as = 0;
1652 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1653 }
1654 }
paulfee0f4c2004-09-13 05:12:46 +00001655
1656 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1657 {
1658 /* If it's not configured as RSERVER_CLIENT in any other address
1659 family, without being member of a peer_group, remove it from
1660 list bgp->rsclient.*/
1661 if (! peer_rsclient_active (peer))
1662 listnode_delete (bgp->rsclient, peer);
1663
1664 bgp_table_finish (peer->rib[afi][safi]);
1665
1666 /* Import policy. */
1667 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1668 {
1669 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1670 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1671 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1672 }
1673
1674 /* Export policy. */
1675 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1676 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1677 {
1678 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1679 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1680 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1681 }
1682 }
1683
paul718e3742002-12-13 20:15:29 +00001684 peer_group2peer_config_copy (group, peer, afi, safi);
1685
1686 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001687 {
1688 peer->last_reset = PEER_DOWN_RMAP_BIND;
1689 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1690 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1691 }
paul718e3742002-12-13 20:15:29 +00001692 else
1693 BGP_EVENT_ADD (peer, BGP_Stop);
1694
1695 return 0;
1696}
1697
1698int
1699peer_group_unbind (struct bgp *bgp, struct peer *peer,
1700 struct peer_group *group, afi_t afi, safi_t safi)
1701{
1702 if (! peer->af_group[afi][safi])
1703 return 0;
1704
1705 if (group != peer->group)
1706 return BGP_ERR_PEER_GROUP_MISMATCH;
1707
1708 peer->af_group[afi][safi] = 0;
1709 peer->afc[afi][safi] = 0;
1710 peer_af_flag_reset (peer, afi, safi);
1711
paulfee0f4c2004-09-13 05:12:46 +00001712 if (peer->rib[afi][safi])
1713 peer->rib[afi][safi] = NULL;
1714
paul718e3742002-12-13 20:15:29 +00001715 if (! peer_group_active (peer))
1716 {
1717 listnode_delete (group->peer, peer);
1718 peer->group = NULL;
1719 if (group->conf->as)
1720 {
1721 peer_delete (peer);
1722 return 0;
1723 }
1724 peer_global_config_reset (peer);
1725 }
1726
1727 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001728 {
1729 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1730 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1731 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1732 }
paul718e3742002-12-13 20:15:29 +00001733 else
1734 BGP_EVENT_ADD (peer, BGP_Stop);
1735
1736 return 0;
1737}
1738
1739/* BGP instance creation by `router bgp' commands. */
1740struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001741bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001742{
1743 struct bgp *bgp;
1744 afi_t afi;
1745 safi_t safi;
1746
1747 bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp));
1748
1749 bgp->peer_self = peer_new ();
paulfd79ac92004-10-13 05:06:08 +00001750 bgp->peer_self->host = strdup ("Static announcement");
paul718e3742002-12-13 20:15:29 +00001751
1752 bgp->peer = list_new ();
1753 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1754
1755 bgp->group = list_new ();
1756 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1757
paulfee0f4c2004-09-13 05:12:46 +00001758 bgp->rsclient = list_new ();
1759 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1760
paul718e3742002-12-13 20:15:29 +00001761 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1762 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1763 {
1764 bgp->route[afi][safi] = bgp_table_init ();
1765 bgp->aggregate[afi][safi] = bgp_table_init ();
1766 bgp->rib[afi][safi] = bgp_table_init ();
1767 }
1768
1769 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1770 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1771 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001772 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1773 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001774
1775 bgp->as = *as;
1776
1777 if (name)
1778 bgp->name = strdup (name);
1779
1780 return bgp;
1781}
1782
paul848973c2003-08-13 00:32:49 +00001783/* Return master of BGP. */
1784struct bgp_master *
1785bgp_get_master ()
1786{
1787 if (bm)
1788 return bm;
1789 return NULL;
1790}
1791
paul718e3742002-12-13 20:15:29 +00001792/* Return first entry of BGP. */
1793struct bgp *
1794bgp_get_default ()
1795{
1796 if (bm->bgp->head)
1797 return bm->bgp->head->data;
1798 return NULL;
1799}
1800
1801/* Lookup BGP entry. */
1802struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001803bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001804{
1805 struct bgp *bgp;
1806 struct listnode *nn;
1807
1808 LIST_LOOP (bm->bgp, bgp, nn)
1809 if (bgp->as == as
1810 && ((bgp->name == NULL && name == NULL)
1811 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1812 return bgp;
1813 return NULL;
1814}
1815
1816/* Lookup BGP structure by view name. */
1817struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001818bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00001819{
1820 struct bgp *bgp;
1821 struct listnode *nn;
1822
1823 LIST_LOOP (bm->bgp, bgp, nn)
1824 if ((bgp->name == NULL && name == NULL)
1825 || (bgp->name && name && strcmp (bgp->name, name) == 0))
1826 return bgp;
1827 return NULL;
1828}
1829
1830/* Called from VTY commands. */
1831int
paulfd79ac92004-10-13 05:06:08 +00001832bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001833{
1834 struct bgp *bgp;
1835
1836 /* Multiple instance check. */
1837 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
1838 {
1839 if (name)
1840 bgp = bgp_lookup_by_name (name);
1841 else
1842 bgp = bgp_get_default ();
1843
1844 /* Already exists. */
1845 if (bgp)
1846 {
1847 if (bgp->as != *as)
1848 {
1849 *as = bgp->as;
1850 return BGP_ERR_INSTANCE_MISMATCH;
1851 }
1852 *bgp_val = bgp;
1853 return 0;
1854 }
1855 }
1856 else
1857 {
1858 /* BGP instance name can not be specified for single instance. */
1859 if (name)
1860 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
1861
1862 /* Get default BGP structure if exists. */
1863 bgp = bgp_get_default ();
1864
1865 if (bgp)
1866 {
1867 if (bgp->as != *as)
1868 {
1869 *as = bgp->as;
1870 return BGP_ERR_AS_MISMATCH;
1871 }
1872 *bgp_val = bgp;
1873 return 0;
1874 }
1875 }
1876
1877 bgp = bgp_create (as, name);
1878 listnode_add (bm->bgp, bgp);
hasso18a6dce2004-10-03 18:18:34 +00001879 bgp_router_id_set(bgp, &router_id_zebra);
paul718e3742002-12-13 20:15:29 +00001880 *bgp_val = bgp;
1881
1882 return 0;
1883}
1884
1885/* Delete BGP instance. */
1886int
1887bgp_delete (struct bgp *bgp)
1888{
1889 struct peer *peer;
1890 struct listnode *nn;
1891 struct listnode *next;
1892 afi_t afi;
1893 safi_t safi;
1894 int i;
1895
1896 /* Delete static route. */
1897 bgp_static_delete (bgp);
1898
1899 /* Unset redistribution. */
1900 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1901 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
1902 if (i != ZEBRA_ROUTE_BGP)
1903 bgp_redistribute_unset (bgp, afi, i);
1904
1905 bgp->group->del = (void (*)(void *)) peer_group_delete;
1906 list_delete (bgp->group);
1907
1908 for (nn = bgp->peer->head; nn; nn = next)
1909 {
1910 peer = nn->data;
1911 next = nn->next;
1912 peer_delete (peer);
1913 }
1914
paulfee0f4c2004-09-13 05:12:46 +00001915 bgp->rsclient->del = (void (*)(void *)) peer_delete;
1916 list_delete (bgp->rsclient);
1917
paul718e3742002-12-13 20:15:29 +00001918 listnode_delete (bm->bgp, bgp);
1919
1920 if (bgp->name)
1921 free (bgp->name);
1922
1923 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1924 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1925 {
1926 if (bgp->route[afi][safi])
1927 XFREE (MTYPE_ROUTE_TABLE, bgp->route[afi][safi]);
1928 if (bgp->aggregate[afi][safi])
1929 XFREE (MTYPE_ROUTE_TABLE,bgp->aggregate[afi][safi]) ;
1930 if (bgp->rib[afi][safi])
1931 XFREE (MTYPE_ROUTE_TABLE,bgp->rib[afi][safi]);
1932 }
1933 XFREE (MTYPE_BGP, bgp);
1934
1935 return 0;
1936}
1937
1938struct peer *
1939peer_lookup (struct bgp *bgp, union sockunion *su)
1940{
1941 struct peer *peer;
1942 struct listnode *nn;
1943
1944 if (! bgp)
1945 bgp = bgp_get_default ();
1946
1947 if (! bgp)
1948 return NULL;
1949
1950 LIST_LOOP (bgp->peer, peer, nn)
1951 {
pauleb821182004-05-01 08:44:08 +00001952 if (sockunion_same (&peer->su, su)
1953 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1954 return peer;
paul718e3742002-12-13 20:15:29 +00001955 }
1956 return NULL;
1957}
1958
1959struct peer *
1960peer_lookup_with_open (union sockunion *su, as_t remote_as,
1961 struct in_addr *remote_id, int *as)
1962{
1963 struct peer *peer;
1964 struct listnode *nn;
1965 struct bgp *bgp;
1966
1967 bgp = bgp_get_default ();
1968 if (! bgp)
1969 return NULL;
1970
1971 LIST_LOOP (bgp->peer, peer, nn)
1972 {
pauleb821182004-05-01 08:44:08 +00001973 if (sockunion_same (&peer->su, su)
1974 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1975 {
1976 if (peer->as == remote_as
1977 && peer->remote_id.s_addr == remote_id->s_addr)
1978 return peer;
1979 if (peer->as == remote_as)
1980 *as = 1;
1981 }
paul718e3742002-12-13 20:15:29 +00001982 }
1983 LIST_LOOP (bgp->peer, peer, nn)
1984 {
pauleb821182004-05-01 08:44:08 +00001985 if (sockunion_same (&peer->su, su)
1986 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1987 {
1988 if (peer->as == remote_as
1989 && peer->remote_id.s_addr == 0)
1990 return peer;
1991 if (peer->as == remote_as)
1992 *as = 1;
1993 }
paul718e3742002-12-13 20:15:29 +00001994 }
1995 return NULL;
1996}
1997
1998/* If peer is configured at least one address family return 1. */
1999int
2000peer_active (struct peer *peer)
2001{
2002 if (peer->afc[AFI_IP][SAFI_UNICAST]
2003 || peer->afc[AFI_IP][SAFI_MULTICAST]
2004 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2005 || peer->afc[AFI_IP6][SAFI_UNICAST]
2006 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2007 return 1;
2008 return 0;
2009}
2010
2011/* If peer is negotiated at least one address family return 1. */
2012int
2013peer_active_nego (struct peer *peer)
2014{
2015 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2016 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2017 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2018 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2019 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2020 return 1;
2021 return 0;
2022}
2023
2024/* peer_flag_change_type. */
2025enum peer_change_type
2026{
2027 peer_change_none,
2028 peer_change_reset,
2029 peer_change_reset_in,
2030 peer_change_reset_out,
2031};
2032
2033void
2034peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2035 enum peer_change_type type)
2036{
2037 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2038 return;
2039
2040 if (type == peer_change_reset)
2041 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2042 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2043 else if (type == peer_change_reset_in)
2044 {
2045 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2046 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2047 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2048 else
2049 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2050 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2051 }
2052 else if (type == peer_change_reset_out)
2053 bgp_announce_route (peer, afi, safi);
2054}
2055
2056struct peer_flag_action
2057{
2058 /* Peer's flag. */
2059 u_int32_t flag;
2060
2061 /* This flag can be set for peer-group member. */
2062 u_char not_for_member;
2063
2064 /* Action when the flag is changed. */
2065 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002066
2067 /* Peer down cause */
2068 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002069};
2070
2071struct peer_flag_action peer_flag_action_list[] =
2072 {
2073 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2074 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2075 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2076 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2077 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
2078 { PEER_FLAG_NO_ROUTE_REFRESH_CAP, 0, peer_change_reset },
2079 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
2080 { PEER_FLAG_ENFORCE_MULTIHOP, 0, peer_change_reset },
2081 { 0, 0, 0 }
2082 };
2083
2084struct peer_flag_action peer_af_flag_action_list[] =
2085 {
2086 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2087 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2088 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2089 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2090 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2091 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2092 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2093 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2094 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2095 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2096 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2097 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2098 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002099 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002100 { 0, 0, 0 }
2101 };
2102
2103/* Proper action set. */
2104int
2105peer_flag_action_set (struct peer_flag_action *action_list, int size,
2106 struct peer_flag_action *action, u_int32_t flag)
2107{
2108 int i;
2109 int found = 0;
2110 int reset_in = 0;
2111 int reset_out = 0;
2112 struct peer_flag_action *match = NULL;
2113
2114 /* Check peer's frag action. */
2115 for (i = 0; i < size; i++)
2116 {
2117 match = &action_list[i];
2118
2119 if (match->flag == 0)
2120 break;
2121
2122 if (match->flag & flag)
2123 {
2124 found = 1;
2125
2126 if (match->type == peer_change_reset_in)
2127 reset_in = 1;
2128 if (match->type == peer_change_reset_out)
2129 reset_out = 1;
2130 if (match->type == peer_change_reset)
2131 {
2132 reset_in = 1;
2133 reset_out = 1;
2134 }
2135 if (match->not_for_member)
2136 action->not_for_member = 1;
2137 }
2138 }
2139
2140 /* Set peer clear type. */
2141 if (reset_in && reset_out)
2142 action->type = peer_change_reset;
2143 else if (reset_in)
2144 action->type = peer_change_reset_in;
2145 else if (reset_out)
2146 action->type = peer_change_reset_out;
2147 else
2148 action->type = peer_change_none;
2149
2150 return found;
2151}
2152
2153void
2154peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2155{
2156 if (flag == PEER_FLAG_SHUTDOWN)
2157 {
2158 if (CHECK_FLAG (peer->flags, flag))
2159 {
2160 if (peer->status == Established)
2161 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2162 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2163 else
2164 BGP_EVENT_ADD (peer, BGP_Stop);
2165 }
2166 else
2167 {
2168 peer->v_start = BGP_INIT_START_TIMER;
2169 BGP_EVENT_ADD (peer, BGP_Stop);
2170 }
2171 }
2172 else if (peer->status == Established)
2173 {
2174 if (flag == PEER_FLAG_NO_ROUTE_REFRESH_CAP
2175 && CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
2176 {
2177 if (CHECK_FLAG (peer->flags, flag))
2178 UNSET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
2179 else
2180 SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
2181
2182 bgp_capability_send (peer, AFI_IP, SAFI_UNICAST,
2183 CAPABILITY_CODE_REFRESH,
2184 CHECK_FLAG (peer->flags, flag) ?
2185 CAPABILITY_ACTION_UNSET : CAPABILITY_ACTION_SET);
2186 }
2187 else
hassoe0701b72004-05-20 09:19:34 +00002188 {
2189 if (flag == PEER_FLAG_NO_ROUTE_REFRESH_CAP)
2190 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2191 else if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2192 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2193 else if (flag == PEER_FLAG_PASSIVE)
2194 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
2195 else if (flag == PEER_FLAG_ENFORCE_MULTIHOP)
2196 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
2197
2198 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2199 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2200 }
paul718e3742002-12-13 20:15:29 +00002201 }
2202 else
2203 BGP_EVENT_ADD (peer, BGP_Stop);
2204}
2205
2206/* Change specified peer flag. */
2207int
2208peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2209{
2210 int found;
2211 int size;
2212 struct peer_group *group;
2213 struct listnode *nn;
2214 struct peer_flag_action action;
2215
2216 memset (&action, 0, sizeof (struct peer_flag_action));
2217 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2218
2219 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2220
2221 /* No flag action is found. */
2222 if (! found)
2223 return BGP_ERR_INVALID_FLAG;
2224
2225 /* Not for peer-group member. */
2226 if (action.not_for_member && peer_group_active (peer))
2227 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2228
2229 /* When unset the peer-group member's flag we have to check
2230 peer-group configuration. */
2231 if (! set && peer_group_active (peer))
2232 if (CHECK_FLAG (peer->group->conf->flags, flag))
2233 {
2234 if (flag == PEER_FLAG_SHUTDOWN)
2235 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2236 else
2237 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2238 }
2239
2240 /* Flag conflict check. */
2241 if (set
2242 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2243 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2244 return BGP_ERR_PEER_FLAG_CONFLICT;
2245
2246 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2247 {
2248 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2249 return 0;
2250 if (! set && ! CHECK_FLAG (peer->flags, flag))
2251 return 0;
2252 }
2253
2254 if (set)
2255 SET_FLAG (peer->flags, flag);
2256 else
2257 UNSET_FLAG (peer->flags, flag);
2258
2259 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2260 {
2261 if (action.type == peer_change_reset)
2262 peer_flag_modify_action (peer, flag);
2263
2264 return 0;
2265 }
2266
2267 /* peer-group member updates. */
2268 group = peer->group;
2269
2270 LIST_LOOP (group->peer, peer, nn)
2271 {
2272 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2273 continue;
2274
2275 if (! set && ! CHECK_FLAG (peer->flags, flag))
2276 continue;
2277
2278 if (set)
2279 SET_FLAG (peer->flags, flag);
2280 else
2281 UNSET_FLAG (peer->flags, flag);
2282
2283 if (action.type == peer_change_reset)
2284 peer_flag_modify_action (peer, flag);
2285 }
2286 return 0;
2287}
2288
2289int
2290peer_flag_set (struct peer *peer, u_int32_t flag)
2291{
2292 return peer_flag_modify (peer, flag, 1);
2293}
2294
2295int
2296peer_flag_unset (struct peer *peer, u_int32_t flag)
2297{
2298 return peer_flag_modify (peer, flag, 0);
2299}
2300
2301int
2302peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2303{
2304 if (peer->af_group[afi][safi])
2305 return 1;
2306 return 0;
2307}
2308
2309int
2310peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2311 int set)
2312{
2313 int found;
2314 int size;
2315 struct listnode *nn;
2316 struct peer_group *group;
2317 struct peer_flag_action action;
2318
2319 memset (&action, 0, sizeof (struct peer_flag_action));
2320 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2321
2322 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2323
2324 /* No flag action is found. */
2325 if (! found)
2326 return BGP_ERR_INVALID_FLAG;
2327
2328 /* Adress family must be activated. */
2329 if (! peer->afc[afi][safi])
2330 return BGP_ERR_PEER_INACTIVE;
2331
2332 /* Not for peer-group member. */
2333 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2334 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2335
2336 /* Spcecial check for reflector client. */
2337 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2338 && peer_sort (peer) != BGP_PEER_IBGP)
2339 return BGP_ERR_NOT_INTERNAL_PEER;
2340
2341 /* Spcecial check for remove-private-AS. */
2342 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2343 && peer_sort (peer) == BGP_PEER_IBGP)
2344 return BGP_ERR_REMOVE_PRIVATE_AS;
2345
2346 /* When unset the peer-group member's flag we have to check
2347 peer-group configuration. */
2348 if (! set && peer->af_group[afi][safi])
2349 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2350 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2351
2352 /* When current flag configuration is same as requested one. */
2353 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2354 {
2355 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2356 return 0;
2357 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2358 return 0;
2359 }
2360
2361 if (set)
2362 SET_FLAG (peer->af_flags[afi][safi], flag);
2363 else
2364 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2365
2366 /* Execute action when peer is established. */
2367 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2368 && peer->status == Established)
2369 {
2370 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2371 bgp_clear_adj_in (peer, afi, safi);
2372 else
hassoe0701b72004-05-20 09:19:34 +00002373 {
2374 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2375 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2376 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2377 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2378 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2379 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2380 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2381 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2382
2383 peer_change_action (peer, afi, safi, action.type);
2384 }
2385
paul718e3742002-12-13 20:15:29 +00002386 }
2387
2388 /* Peer group member updates. */
2389 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2390 {
2391 group = peer->group;
2392
2393 LIST_LOOP (group->peer, peer, nn)
2394 {
2395 if (! peer->af_group[afi][safi])
2396 continue;
2397
2398 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2399 continue;
2400
2401 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2402 continue;
2403
2404 if (set)
2405 SET_FLAG (peer->af_flags[afi][safi], flag);
2406 else
2407 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2408
2409 if (peer->status == Established)
2410 {
2411 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2412 bgp_clear_adj_in (peer, afi, safi);
2413 else
hassoe0701b72004-05-20 09:19:34 +00002414 {
2415 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2416 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2417 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2418 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2419 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2420 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2421 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2422 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2423
2424 peer_change_action (peer, afi, safi, action.type);
2425 }
paul718e3742002-12-13 20:15:29 +00002426 }
2427 }
2428 }
2429 return 0;
2430}
2431
2432int
2433peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2434{
2435 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2436}
2437
2438int
2439peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2440{
2441 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2442}
2443
2444/* EBGP multihop configuration. */
2445int
2446peer_ebgp_multihop_set (struct peer *peer, int ttl)
2447{
2448 struct peer_group *group;
2449 struct listnode *nn;
2450
2451 if (peer_sort (peer) == BGP_PEER_IBGP)
2452 return 0;
2453
2454 peer->ttl = ttl;
2455
2456 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2457 {
pauleb821182004-05-01 08:44:08 +00002458 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2459 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002460 }
2461 else
2462 {
2463 group = peer->group;
2464 LIST_LOOP (group->peer, peer, nn)
pauleb821182004-05-01 08:44:08 +00002465 {
2466 if (peer_sort (peer) == BGP_PEER_IBGP)
2467 continue;
paul718e3742002-12-13 20:15:29 +00002468
pauleb821182004-05-01 08:44:08 +00002469 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002470
pauleb821182004-05-01 08:44:08 +00002471 if (peer->fd >= 0)
2472 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2473 }
paul718e3742002-12-13 20:15:29 +00002474 }
2475 return 0;
2476}
2477
2478int
2479peer_ebgp_multihop_unset (struct peer *peer)
2480{
2481 struct peer_group *group;
2482 struct listnode *nn;
2483
2484 if (peer_sort (peer) == BGP_PEER_IBGP)
2485 return 0;
2486
2487 if (peer_group_active (peer))
2488 peer->ttl = peer->group->conf->ttl;
2489 else
2490 peer->ttl = 1;
2491
2492 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2493 {
pauleb821182004-05-01 08:44:08 +00002494 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2495 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002496 }
2497 else
2498 {
2499 group = peer->group;
2500 LIST_LOOP (group->peer, peer, nn)
pauleb821182004-05-01 08:44:08 +00002501 {
2502 if (peer_sort (peer) == BGP_PEER_IBGP)
2503 continue;
paul718e3742002-12-13 20:15:29 +00002504
pauleb821182004-05-01 08:44:08 +00002505 peer->ttl = 1;
2506
2507 if (peer->fd >= 0)
2508 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2509 }
paul718e3742002-12-13 20:15:29 +00002510 }
2511 return 0;
2512}
2513
2514/* Neighbor description. */
2515int
2516peer_description_set (struct peer *peer, char *desc)
2517{
2518 if (peer->desc)
2519 XFREE (MTYPE_PEER_DESC, peer->desc);
2520
2521 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2522
2523 return 0;
2524}
2525
2526int
2527peer_description_unset (struct peer *peer)
2528{
2529 if (peer->desc)
2530 XFREE (MTYPE_PEER_DESC, peer->desc);
2531
2532 peer->desc = NULL;
2533
2534 return 0;
2535}
2536
2537/* Neighbor update-source. */
2538int
paulfd79ac92004-10-13 05:06:08 +00002539peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002540{
2541 struct peer_group *group;
2542 struct listnode *nn;
2543
2544 if (peer->update_if)
2545 {
2546 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2547 && strcmp (peer->update_if, ifname) == 0)
2548 return 0;
2549
2550 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2551 peer->update_if = NULL;
2552 }
2553
2554 if (peer->update_source)
2555 {
2556 sockunion_free (peer->update_source);
2557 peer->update_source = NULL;
2558 }
2559
2560 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2561
2562 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2563 {
2564 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002565 {
2566 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2567 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2568 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2569 }
paul718e3742002-12-13 20:15:29 +00002570 else
2571 BGP_EVENT_ADD (peer, BGP_Stop);
2572 return 0;
2573 }
2574
2575 /* peer-group member updates. */
2576 group = peer->group;
2577 LIST_LOOP (group->peer, peer, nn)
2578 {
2579 if (peer->update_if)
2580 {
2581 if (strcmp (peer->update_if, ifname) == 0)
2582 continue;
2583
2584 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2585 peer->update_if = NULL;
2586 }
2587
2588 if (peer->update_source)
2589 {
2590 sockunion_free (peer->update_source);
2591 peer->update_source = NULL;
2592 }
2593
2594 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2595
2596 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002597 {
2598 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2599 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2600 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2601 }
paul718e3742002-12-13 20:15:29 +00002602 else
2603 BGP_EVENT_ADD (peer, BGP_Stop);
2604 }
2605 return 0;
2606}
2607
2608int
2609peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2610{
2611 struct peer_group *group;
2612 struct listnode *nn;
2613
2614 if (peer->update_source)
2615 {
2616 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2617 && sockunion_cmp (peer->update_source, su) == 0)
2618 return 0;
2619 sockunion_free (peer->update_source);
2620 peer->update_source = NULL;
2621 }
2622
2623 if (peer->update_if)
2624 {
2625 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2626 peer->update_if = NULL;
2627 }
2628
2629 peer->update_source = sockunion_dup (su);
2630
2631 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2632 {
2633 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002634 {
2635 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2636 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2637 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2638 }
paul718e3742002-12-13 20:15:29 +00002639 else
2640 BGP_EVENT_ADD (peer, BGP_Stop);
2641 return 0;
2642 }
2643
2644 /* peer-group member updates. */
2645 group = peer->group;
2646 LIST_LOOP (group->peer, peer, nn)
2647 {
2648 if (peer->update_source)
2649 {
2650 if (sockunion_cmp (peer->update_source, su) == 0)
2651 continue;
2652 sockunion_free (peer->update_source);
2653 peer->update_source = NULL;
2654 }
2655
2656 if (peer->update_if)
2657 {
2658 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2659 peer->update_if = NULL;
2660 }
2661
2662 peer->update_source = sockunion_dup (su);
2663
2664 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002665 {
2666 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2667 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2668 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2669 }
paul718e3742002-12-13 20:15:29 +00002670 else
2671 BGP_EVENT_ADD (peer, BGP_Stop);
2672 }
2673 return 0;
2674}
2675
2676int
2677peer_update_source_unset (struct peer *peer)
2678{
2679 union sockunion *su;
2680 struct peer_group *group;
2681 struct listnode *nn;
2682
2683 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2684 && ! peer->update_source
2685 && ! peer->update_if)
2686 return 0;
2687
2688 if (peer->update_source)
2689 {
2690 sockunion_free (peer->update_source);
2691 peer->update_source = NULL;
2692 }
2693 if (peer->update_if)
2694 {
2695 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2696 peer->update_if = NULL;
2697 }
2698
2699 if (peer_group_active (peer))
2700 {
2701 group = peer->group;
2702
2703 if (group->conf->update_source)
2704 {
2705 su = sockunion_dup (group->conf->update_source);
2706 peer->update_source = su;
2707 }
2708 else if (group->conf->update_if)
2709 peer->update_if =
2710 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2711 }
2712
2713 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2714 {
2715 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002716 {
2717 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2718 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2719 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2720 }
paul718e3742002-12-13 20:15:29 +00002721 else
2722 BGP_EVENT_ADD (peer, BGP_Stop);
2723 return 0;
2724 }
2725
2726 /* peer-group member updates. */
2727 group = peer->group;
2728 LIST_LOOP (group->peer, peer, nn)
2729 {
2730 if (! peer->update_source && ! peer->update_if)
2731 continue;
2732
2733 if (peer->update_source)
2734 {
2735 sockunion_free (peer->update_source);
2736 peer->update_source = NULL;
2737 }
2738
2739 if (peer->update_if)
2740 {
2741 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2742 peer->update_if = NULL;
2743 }
2744
2745 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002746 {
2747 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2748 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2749 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2750 }
paul718e3742002-12-13 20:15:29 +00002751 else
2752 BGP_EVENT_ADD (peer, BGP_Stop);
2753 }
2754 return 0;
2755}
2756
2757int
2758peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00002759 const char *rmap)
paul718e3742002-12-13 20:15:29 +00002760{
2761 struct peer_group *group;
2762 struct listnode *nn;
2763
2764 /* Adress family must be activated. */
2765 if (! peer->afc[afi][safi])
2766 return BGP_ERR_PEER_INACTIVE;
2767
2768 /* Default originate can't be used for peer group memeber. */
2769 if (peer_is_group_member (peer, afi, safi))
2770 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2771
2772 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
2773 || (rmap && ! peer->default_rmap[afi][safi].name)
2774 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
2775 {
2776 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2777
2778 if (rmap)
2779 {
2780 if (peer->default_rmap[afi][safi].name)
2781 free (peer->default_rmap[afi][safi].name);
2782 peer->default_rmap[afi][safi].name = strdup (rmap);
2783 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2784 }
2785 }
2786
2787 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2788 {
2789 if (peer->status == Established && peer->afc_nego[afi][safi])
2790 bgp_default_originate (peer, afi, safi, 0);
2791 return 0;
2792 }
2793
2794 /* peer-group member updates. */
2795 group = peer->group;
2796 LIST_LOOP (group->peer, peer, nn)
2797 {
2798 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2799
2800 if (rmap)
2801 {
2802 if (peer->default_rmap[afi][safi].name)
2803 free (peer->default_rmap[afi][safi].name);
2804 peer->default_rmap[afi][safi].name = strdup (rmap);
2805 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2806 }
2807
2808 if (peer->status == Established && peer->afc_nego[afi][safi])
2809 bgp_default_originate (peer, afi, safi, 0);
2810 }
2811 return 0;
2812}
2813
2814int
2815peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
2816{
2817 struct peer_group *group;
2818 struct listnode *nn;
2819
2820 /* Adress family must be activated. */
2821 if (! peer->afc[afi][safi])
2822 return BGP_ERR_PEER_INACTIVE;
2823
2824 /* Default originate can't be used for peer group memeber. */
2825 if (peer_is_group_member (peer, afi, safi))
2826 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2827
2828 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
2829 {
2830 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2831
2832 if (peer->default_rmap[afi][safi].name)
2833 free (peer->default_rmap[afi][safi].name);
2834 peer->default_rmap[afi][safi].name = NULL;
2835 peer->default_rmap[afi][safi].map = NULL;
2836 }
2837
2838 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2839 {
2840 if (peer->status == Established && peer->afc_nego[afi][safi])
2841 bgp_default_originate (peer, afi, safi, 1);
2842 return 0;
2843 }
2844
2845 /* peer-group member updates. */
2846 group = peer->group;
2847 LIST_LOOP (group->peer, peer, nn)
2848 {
2849 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2850
2851 if (peer->default_rmap[afi][safi].name)
2852 free (peer->default_rmap[afi][safi].name);
2853 peer->default_rmap[afi][safi].name = NULL;
2854 peer->default_rmap[afi][safi].map = NULL;
2855
2856 if (peer->status == Established && peer->afc_nego[afi][safi])
2857 bgp_default_originate (peer, afi, safi, 1);
2858 }
2859 return 0;
2860}
2861
2862int
2863peer_port_set (struct peer *peer, u_int16_t port)
2864{
2865 peer->port = port;
2866 return 0;
2867}
2868
2869int
2870peer_port_unset (struct peer *peer)
2871{
2872 peer->port = BGP_PORT_DEFAULT;
2873 return 0;
2874}
2875
2876/* neighbor weight. */
2877int
2878peer_weight_set (struct peer *peer, u_int16_t weight)
2879{
2880 struct peer_group *group;
2881 struct listnode *nn;
2882
2883 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
2884 peer->weight = weight;
2885
2886 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2887 return 0;
2888
2889 /* peer-group member updates. */
2890 group = peer->group;
2891 LIST_LOOP (group->peer, peer, nn)
2892 {
2893 peer->weight = group->conf->weight;
2894 }
2895 return 0;
2896}
2897
2898int
2899peer_weight_unset (struct peer *peer)
2900{
2901 struct peer_group *group;
2902 struct listnode *nn;
2903
2904 /* Set default weight. */
2905 if (peer_group_active (peer))
2906 peer->weight = peer->group->conf->weight;
2907 else
2908 peer->weight = 0;
2909
2910 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
2911
2912 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2913 return 0;
2914
2915 /* peer-group member updates. */
2916 group = peer->group;
2917 LIST_LOOP (group->peer, peer, nn)
2918 {
2919 peer->weight = 0;
2920 }
2921 return 0;
2922}
2923
2924int
2925peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
2926{
2927 struct peer_group *group;
2928 struct listnode *nn;
2929
2930 /* Not for peer group memeber. */
2931 if (peer_group_active (peer))
2932 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2933
2934 /* keepalive value check. */
2935 if (keepalive > 65535)
2936 return BGP_ERR_INVALID_VALUE;
2937
2938 /* Holdtime value check. */
2939 if (holdtime > 65535)
2940 return BGP_ERR_INVALID_VALUE;
2941
2942 /* Holdtime value must be either 0 or greater than 3. */
2943 if (holdtime < 3 && holdtime != 0)
2944 return BGP_ERR_INVALID_VALUE;
2945
2946 /* Set value to the configuration. */
2947 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
2948 peer->holdtime = holdtime;
2949 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
2950
2951 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2952 return 0;
2953
2954 /* peer-group member updates. */
2955 group = peer->group;
2956 LIST_LOOP (group->peer, peer, nn)
2957 {
2958 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
2959 peer->holdtime = group->conf->holdtime;
2960 peer->keepalive = group->conf->keepalive;
2961 }
2962 return 0;
2963}
2964
2965int
2966peer_timers_unset (struct peer *peer)
2967{
2968 struct peer_group *group;
2969 struct listnode *nn;
2970
2971 if (peer_group_active (peer))
2972 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2973
2974 /* Clear configuration. */
2975 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
2976 peer->keepalive = 0;
2977 peer->holdtime = 0;
2978
2979 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2980 return 0;
2981
2982 /* peer-group member updates. */
2983 group = peer->group;
2984 LIST_LOOP (group->peer, peer, nn)
2985 {
2986 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
2987 peer->holdtime = 0;
2988 peer->keepalive = 0;
2989 }
2990
2991 return 0;
2992}
2993
2994int
2995peer_timers_connect_set (struct peer *peer, u_int32_t connect)
2996{
2997 if (peer_group_active (peer))
2998 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2999
3000 if (connect > 65535)
3001 return BGP_ERR_INVALID_VALUE;
3002
3003 /* Set value to the configuration. */
3004 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3005 peer->connect = connect;
3006
3007 /* Set value to timer setting. */
3008 peer->v_connect = connect;
3009
3010 return 0;
3011}
3012
3013int
3014peer_timers_connect_unset (struct peer *peer)
3015{
3016 if (peer_group_active (peer))
3017 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3018
3019 /* Clear configuration. */
3020 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3021 peer->connect = 0;
3022
3023 /* Set timer setting to default value. */
3024 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3025
3026 return 0;
3027}
3028
3029int
3030peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3031{
3032 if (peer_group_active (peer))
3033 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3034
3035 if (routeadv > 600)
3036 return BGP_ERR_INVALID_VALUE;
3037
3038 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3039 peer->routeadv = routeadv;
3040 peer->v_routeadv = routeadv;
3041
3042 return 0;
3043}
3044
3045int
3046peer_advertise_interval_unset (struct peer *peer)
3047{
3048 if (peer_group_active (peer))
3049 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3050
3051 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3052 peer->routeadv = 0;
3053
3054 if (peer_sort (peer) == BGP_PEER_IBGP)
3055 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3056 else
3057 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3058
3059 return 0;
3060}
3061
3062int
3063peer_version_set (struct peer *peer, int version)
3064{
3065 if (version != BGP_VERSION_4 && version != BGP_VERSION_MP_4_DRAFT_00)
3066 return BGP_ERR_INVALID_VALUE;
3067
3068 peer->version = version;
3069
3070 return 0;
3071}
3072
3073int
3074peer_version_unset (struct peer *peer)
3075{
3076 peer->version = BGP_VERSION_4;
3077 return 0;
3078}
3079
3080/* neighbor interface */
3081int
paulfd79ac92004-10-13 05:06:08 +00003082peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003083{
3084 if (peer->ifname)
3085 free (peer->ifname);
3086 peer->ifname = strdup (str);
3087
3088 return 0;
3089}
3090
3091int
3092peer_interface_unset (struct peer *peer)
3093{
3094 if (peer->ifname)
3095 free (peer->ifname);
3096 peer->ifname = NULL;
3097
3098 return 0;
3099}
3100
3101/* Allow-as in. */
3102int
3103peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3104{
3105 struct peer_group *group;
3106 struct listnode *nn;
3107
3108 if (allow_num < 1 || allow_num > 10)
3109 return BGP_ERR_INVALID_VALUE;
3110
3111 if (peer->allowas_in[afi][safi] != allow_num)
3112 {
3113 peer->allowas_in[afi][safi] = allow_num;
3114 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3115 peer_change_action (peer, afi, safi, peer_change_reset_in);
3116 }
3117
3118 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3119 return 0;
3120
3121 group = peer->group;
3122 LIST_LOOP (group->peer, peer, nn)
3123 {
3124 if (peer->allowas_in[afi][safi] != allow_num)
3125 {
3126 peer->allowas_in[afi][safi] = allow_num;
3127 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3128 peer_change_action (peer, afi, safi, peer_change_reset_in);
3129 }
3130
3131 }
3132 return 0;
3133}
3134
3135int
3136peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3137{
3138 struct peer_group *group;
3139 struct listnode *nn;
3140
3141 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3142 {
3143 peer->allowas_in[afi][safi] = 0;
3144 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3145 }
3146
3147 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3148 return 0;
3149
3150 group = peer->group;
3151 LIST_LOOP (group->peer, peer, nn)
3152 {
3153 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3154 {
3155 peer->allowas_in[afi][safi] = 0;
3156 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3157 }
3158 }
3159 return 0;
3160}
3161
3162int
3163peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3164{
3165 struct bgp *bgp = peer->bgp;
3166 struct peer_group *group;
3167 struct listnode *nn;
3168
3169 if (peer_sort (peer) != BGP_PEER_EBGP
3170 && peer_sort (peer) != BGP_PEER_INTERNAL)
3171 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3172
3173 if (bgp->as == as)
3174 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3175
3176 if (peer_group_active (peer))
3177 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3178
3179 if (peer->change_local_as == as &&
3180 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3181 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3182 return 0;
3183
3184 peer->change_local_as = as;
3185 if (no_prepend)
3186 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3187 else
3188 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3189
3190 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3191 {
3192 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003193 {
3194 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3195 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3196 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3197 }
paul718e3742002-12-13 20:15:29 +00003198 else
3199 BGP_EVENT_ADD (peer, BGP_Stop);
3200
3201 return 0;
3202 }
3203
3204 group = peer->group;
3205 LIST_LOOP (group->peer, peer, nn)
3206 {
3207 peer->change_local_as = as;
3208 if (no_prepend)
3209 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3210 else
3211 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3212
3213 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003214 {
3215 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3216 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3217 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3218 }
paul718e3742002-12-13 20:15:29 +00003219 else
3220 BGP_EVENT_ADD (peer, BGP_Stop);
3221 }
3222
3223 return 0;
3224}
3225
3226int
3227peer_local_as_unset (struct peer *peer)
3228{
3229 struct peer_group *group;
3230 struct listnode *nn;
3231
3232 if (peer_group_active (peer))
3233 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3234
3235 if (! peer->change_local_as)
3236 return 0;
3237
3238 peer->change_local_as = 0;
3239 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3240
3241 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3242 {
3243 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003244 {
3245 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3246 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3247 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3248 }
paul718e3742002-12-13 20:15:29 +00003249 else
3250 BGP_EVENT_ADD (peer, BGP_Stop);
3251
3252 return 0;
3253 }
3254
3255 group = peer->group;
3256 LIST_LOOP (group->peer, peer, nn)
3257 {
3258 peer->change_local_as = 0;
3259 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3260
3261 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003262 {
3263 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3264 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3265 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3266 }
paul718e3742002-12-13 20:15:29 +00003267 else
3268 BGP_EVENT_ADD (peer, BGP_Stop);
3269 }
3270 return 0;
3271}
3272
3273/* Set distribute list to the peer. */
3274int
3275peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003276 const char *name)
paul718e3742002-12-13 20:15:29 +00003277{
3278 struct bgp_filter *filter;
3279 struct peer_group *group;
3280 struct listnode *nn;
3281
3282 if (! peer->afc[afi][safi])
3283 return BGP_ERR_PEER_INACTIVE;
3284
3285 if (direct != FILTER_IN && direct != FILTER_OUT)
3286 return BGP_ERR_INVALID_VALUE;
3287
3288 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3289 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3290
3291 filter = &peer->filter[afi][safi];
3292
3293 if (filter->plist[direct].name)
3294 return BGP_ERR_PEER_FILTER_CONFLICT;
3295
3296 if (filter->dlist[direct].name)
3297 free (filter->dlist[direct].name);
3298 filter->dlist[direct].name = strdup (name);
3299 filter->dlist[direct].alist = access_list_lookup (afi, name);
3300
3301 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3302 return 0;
3303
3304 group = peer->group;
3305 LIST_LOOP (group->peer, peer, nn)
3306 {
3307 filter = &peer->filter[afi][safi];
3308
3309 if (! peer->af_group[afi][safi])
3310 continue;
3311
3312 if (filter->dlist[direct].name)
3313 free (filter->dlist[direct].name);
3314 filter->dlist[direct].name = strdup (name);
3315 filter->dlist[direct].alist = access_list_lookup (afi, name);
3316 }
3317
3318 return 0;
3319}
3320
3321int
3322peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3323{
3324 struct bgp_filter *filter;
3325 struct bgp_filter *gfilter;
3326 struct peer_group *group;
3327 struct listnode *nn;
3328
3329 if (! peer->afc[afi][safi])
3330 return BGP_ERR_PEER_INACTIVE;
3331
3332 if (direct != FILTER_IN && direct != FILTER_OUT)
3333 return BGP_ERR_INVALID_VALUE;
3334
3335 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3336 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3337
3338 filter = &peer->filter[afi][safi];
3339
3340 /* apply peer-group filter */
3341 if (peer->af_group[afi][safi])
3342 {
3343 gfilter = &peer->group->conf->filter[afi][safi];
3344
3345 if (gfilter->dlist[direct].name)
3346 {
3347 if (filter->dlist[direct].name)
3348 free (filter->dlist[direct].name);
3349 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3350 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3351 return 0;
3352 }
3353 }
3354
3355 if (filter->dlist[direct].name)
3356 free (filter->dlist[direct].name);
3357 filter->dlist[direct].name = NULL;
3358 filter->dlist[direct].alist = NULL;
3359
3360 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3361 return 0;
3362
3363 group = peer->group;
3364 LIST_LOOP (group->peer, peer, nn)
3365 {
3366 filter = &peer->filter[afi][safi];
3367
3368 if (! peer->af_group[afi][safi])
3369 continue;
3370
3371 if (filter->dlist[direct].name)
3372 free (filter->dlist[direct].name);
3373 filter->dlist[direct].name = NULL;
3374 filter->dlist[direct].alist = NULL;
3375 }
3376
3377 return 0;
3378}
3379
3380/* Update distribute list. */
3381void
3382peer_distribute_update (struct access_list *access)
3383{
3384 afi_t afi;
3385 safi_t safi;
3386 int direct;
3387 struct listnode *nn, *nm;
3388 struct bgp *bgp;
3389 struct peer *peer;
3390 struct peer_group *group;
3391 struct bgp_filter *filter;
3392
3393 LIST_LOOP (bm->bgp, bgp, nn)
3394 {
3395 LIST_LOOP (bgp->peer, peer, nm)
3396 {
3397 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3398 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3399 {
3400 filter = &peer->filter[afi][safi];
3401
3402 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3403 {
3404 if (filter->dlist[direct].name)
3405 filter->dlist[direct].alist =
3406 access_list_lookup (afi, filter->dlist[direct].name);
3407 else
3408 filter->dlist[direct].alist = NULL;
3409 }
3410 }
3411 }
3412 LIST_LOOP (bgp->group, group, nm)
3413 {
3414 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3415 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3416 {
3417 filter = &group->conf->filter[afi][safi];
3418
3419 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3420 {
3421 if (filter->dlist[direct].name)
3422 filter->dlist[direct].alist =
3423 access_list_lookup (afi, filter->dlist[direct].name);
3424 else
3425 filter->dlist[direct].alist = NULL;
3426 }
3427 }
3428 }
3429 }
3430}
3431
3432/* Set prefix list to the peer. */
3433int
3434peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003435 const char *name)
paul718e3742002-12-13 20:15:29 +00003436{
3437 struct bgp_filter *filter;
3438 struct peer_group *group;
3439 struct listnode *nn;
3440
3441 if (! peer->afc[afi][safi])
3442 return BGP_ERR_PEER_INACTIVE;
3443
3444 if (direct != FILTER_IN && direct != FILTER_OUT)
3445 return BGP_ERR_INVALID_VALUE;
3446
3447 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3448 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3449
3450 filter = &peer->filter[afi][safi];
3451
3452 if (filter->dlist[direct].name)
3453 return BGP_ERR_PEER_FILTER_CONFLICT;
3454
3455 if (filter->plist[direct].name)
3456 free (filter->plist[direct].name);
3457 filter->plist[direct].name = strdup (name);
3458 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3459
3460 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3461 return 0;
3462
3463 group = peer->group;
3464 LIST_LOOP (group->peer, peer, nn)
3465 {
3466 filter = &peer->filter[afi][safi];
3467
3468 if (! peer->af_group[afi][safi])
3469 continue;
3470
3471 if (filter->plist[direct].name)
3472 free (filter->plist[direct].name);
3473 filter->plist[direct].name = strdup (name);
3474 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3475 }
3476 return 0;
3477}
3478
3479int
3480peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3481{
3482 struct bgp_filter *filter;
3483 struct bgp_filter *gfilter;
3484 struct peer_group *group;
3485 struct listnode *nn;
3486
3487 if (! peer->afc[afi][safi])
3488 return BGP_ERR_PEER_INACTIVE;
3489
3490 if (direct != FILTER_IN && direct != FILTER_OUT)
3491 return BGP_ERR_INVALID_VALUE;
3492
3493 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3494 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3495
3496 filter = &peer->filter[afi][safi];
3497
3498 /* apply peer-group filter */
3499 if (peer->af_group[afi][safi])
3500 {
3501 gfilter = &peer->group->conf->filter[afi][safi];
3502
3503 if (gfilter->plist[direct].name)
3504 {
3505 if (filter->plist[direct].name)
3506 free (filter->plist[direct].name);
3507 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3508 filter->plist[direct].plist = gfilter->plist[direct].plist;
3509 return 0;
3510 }
3511 }
3512
3513 if (filter->plist[direct].name)
3514 free (filter->plist[direct].name);
3515 filter->plist[direct].name = NULL;
3516 filter->plist[direct].plist = NULL;
3517
3518 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3519 return 0;
3520
3521 group = peer->group;
3522 LIST_LOOP (group->peer, peer, nn)
3523 {
3524 filter = &peer->filter[afi][safi];
3525
3526 if (! peer->af_group[afi][safi])
3527 continue;
3528
3529 if (filter->plist[direct].name)
3530 free (filter->plist[direct].name);
3531 filter->plist[direct].name = NULL;
3532 filter->plist[direct].plist = NULL;
3533 }
3534
3535 return 0;
3536}
3537
3538/* Update prefix-list list. */
3539void
3540peer_prefix_list_update (struct prefix_list *plist)
3541{
3542 struct listnode *nn, *nm;
3543 struct bgp *bgp;
3544 struct peer *peer;
3545 struct peer_group *group;
3546 struct bgp_filter *filter;
3547 afi_t afi;
3548 safi_t safi;
3549 int direct;
3550
3551 LIST_LOOP (bm->bgp, bgp, nn)
3552 {
3553 LIST_LOOP (bgp->peer, peer, nm)
3554 {
3555 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3556 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3557 {
3558 filter = &peer->filter[afi][safi];
3559
3560 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3561 {
3562 if (filter->plist[direct].name)
3563 filter->plist[direct].plist =
3564 prefix_list_lookup (afi, filter->plist[direct].name);
3565 else
3566 filter->plist[direct].plist = NULL;
3567 }
3568 }
3569 }
3570 LIST_LOOP (bgp->group, group, nm)
3571 {
3572 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3573 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3574 {
3575 filter = &group->conf->filter[afi][safi];
3576
3577 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3578 {
3579 if (filter->plist[direct].name)
3580 filter->plist[direct].plist =
3581 prefix_list_lookup (afi, filter->plist[direct].name);
3582 else
3583 filter->plist[direct].plist = NULL;
3584 }
3585 }
3586 }
3587 }
3588}
3589
3590int
3591peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003592 const char *name)
paul718e3742002-12-13 20:15:29 +00003593{
3594 struct bgp_filter *filter;
3595 struct peer_group *group;
3596 struct listnode *nn;
3597
3598 if (! peer->afc[afi][safi])
3599 return BGP_ERR_PEER_INACTIVE;
3600
3601 if (direct != FILTER_IN && direct != FILTER_OUT)
3602 return BGP_ERR_INVALID_VALUE;
3603
3604 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3605 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3606
3607 filter = &peer->filter[afi][safi];
3608
3609 if (filter->aslist[direct].name)
3610 free (filter->aslist[direct].name);
3611 filter->aslist[direct].name = strdup (name);
3612 filter->aslist[direct].aslist = as_list_lookup (name);
3613
3614 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3615 return 0;
3616
3617 group = peer->group;
3618 LIST_LOOP (group->peer, peer, nn)
3619 {
3620 filter = &peer->filter[afi][safi];
3621
3622 if (! peer->af_group[afi][safi])
3623 continue;
3624
3625 if (filter->aslist[direct].name)
3626 free (filter->aslist[direct].name);
3627 filter->aslist[direct].name = strdup (name);
3628 filter->aslist[direct].aslist = as_list_lookup (name);
3629 }
3630 return 0;
3631}
3632
3633int
3634peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3635{
3636 struct bgp_filter *filter;
3637 struct bgp_filter *gfilter;
3638 struct peer_group *group;
3639 struct listnode *nn;
3640
3641 if (! peer->afc[afi][safi])
3642 return BGP_ERR_PEER_INACTIVE;
3643
paulfee0f4c2004-09-13 05:12:46 +00003644 if (direct != RMAP_IN && direct != RMAP_OUT &&
3645 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003646 return BGP_ERR_INVALID_VALUE;
3647
paulfee0f4c2004-09-13 05:12:46 +00003648 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
3649 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003650 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3651
3652 filter = &peer->filter[afi][safi];
3653
3654 /* apply peer-group filter */
3655 if (peer->af_group[afi][safi])
3656 {
3657 gfilter = &peer->group->conf->filter[afi][safi];
3658
3659 if (gfilter->aslist[direct].name)
3660 {
3661 if (filter->aslist[direct].name)
3662 free (filter->aslist[direct].name);
3663 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
3664 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
3665 return 0;
3666 }
3667 }
3668
3669 if (filter->aslist[direct].name)
3670 free (filter->aslist[direct].name);
3671 filter->aslist[direct].name = NULL;
3672 filter->aslist[direct].aslist = NULL;
3673
3674 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3675 return 0;
3676
3677 group = peer->group;
3678 LIST_LOOP (group->peer, peer, nn)
3679 {
3680 filter = &peer->filter[afi][safi];
3681
3682 if (! peer->af_group[afi][safi])
3683 continue;
3684
3685 if (filter->aslist[direct].name)
3686 free (filter->aslist[direct].name);
3687 filter->aslist[direct].name = NULL;
3688 filter->aslist[direct].aslist = NULL;
3689 }
3690
3691 return 0;
3692}
3693
3694void
3695peer_aslist_update ()
3696{
3697 afi_t afi;
3698 safi_t safi;
3699 int direct;
3700 struct listnode *nn, *nm;
3701 struct bgp *bgp;
3702 struct peer *peer;
3703 struct peer_group *group;
3704 struct bgp_filter *filter;
3705
3706 LIST_LOOP (bm->bgp, bgp, nn)
3707 {
3708 LIST_LOOP (bgp->peer, peer, nm)
3709 {
3710 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3711 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3712 {
3713 filter = &peer->filter[afi][safi];
3714
3715 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3716 {
3717 if (filter->aslist[direct].name)
3718 filter->aslist[direct].aslist =
3719 as_list_lookup (filter->aslist[direct].name);
3720 else
3721 filter->aslist[direct].aslist = NULL;
3722 }
3723 }
3724 }
3725 LIST_LOOP (bgp->group, group, nm)
3726 {
3727 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3728 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3729 {
3730 filter = &group->conf->filter[afi][safi];
3731
3732 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3733 {
3734 if (filter->aslist[direct].name)
3735 filter->aslist[direct].aslist =
3736 as_list_lookup (filter->aslist[direct].name);
3737 else
3738 filter->aslist[direct].aslist = NULL;
3739 }
3740 }
3741 }
3742 }
3743}
3744
3745/* Set route-map to the peer. */
3746int
3747peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003748 const char *name)
paul718e3742002-12-13 20:15:29 +00003749{
3750 struct bgp_filter *filter;
3751 struct peer_group *group;
3752 struct listnode *nn;
3753
3754 if (! peer->afc[afi][safi])
3755 return BGP_ERR_PEER_INACTIVE;
3756
paulfee0f4c2004-09-13 05:12:46 +00003757 if (direct != RMAP_IN && direct != RMAP_OUT &&
3758 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003759 return BGP_ERR_INVALID_VALUE;
3760
paulfee0f4c2004-09-13 05:12:46 +00003761 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
3762 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003763 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3764
3765 filter = &peer->filter[afi][safi];
3766
3767 if (filter->map[direct].name)
3768 free (filter->map[direct].name);
3769
3770 filter->map[direct].name = strdup (name);
3771 filter->map[direct].map = route_map_lookup_by_name (name);
3772
3773 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3774 return 0;
3775
3776 group = peer->group;
3777 LIST_LOOP (group->peer, peer, nn)
3778 {
3779 filter = &peer->filter[afi][safi];
3780
3781 if (! peer->af_group[afi][safi])
3782 continue;
3783
3784 if (filter->map[direct].name)
3785 free (filter->map[direct].name);
3786 filter->map[direct].name = strdup (name);
3787 filter->map[direct].map = route_map_lookup_by_name (name);
3788 }
3789 return 0;
3790}
3791
3792/* Unset route-map from the peer. */
3793int
3794peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3795{
3796 struct bgp_filter *filter;
3797 struct bgp_filter *gfilter;
3798 struct peer_group *group;
3799 struct listnode *nn;
3800
3801 if (! peer->afc[afi][safi])
3802 return BGP_ERR_PEER_INACTIVE;
3803
3804 if (direct != FILTER_IN && direct != FILTER_OUT)
3805 return BGP_ERR_INVALID_VALUE;
3806
3807 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3808 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3809
3810 filter = &peer->filter[afi][safi];
3811
3812 /* apply peer-group filter */
3813 if (peer->af_group[afi][safi])
3814 {
3815 gfilter = &peer->group->conf->filter[afi][safi];
3816
3817 if (gfilter->map[direct].name)
3818 {
3819 if (filter->map[direct].name)
3820 free (filter->map[direct].name);
3821 filter->map[direct].name = strdup (gfilter->map[direct].name);
3822 filter->map[direct].map = gfilter->map[direct].map;
3823 return 0;
3824 }
3825 }
3826
3827 if (filter->map[direct].name)
3828 free (filter->map[direct].name);
3829 filter->map[direct].name = NULL;
3830 filter->map[direct].map = NULL;
3831
3832 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3833 return 0;
3834
3835 group = peer->group;
3836 LIST_LOOP (group->peer, peer, nn)
3837 {
3838 filter = &peer->filter[afi][safi];
3839
3840 if (! peer->af_group[afi][safi])
3841 continue;
3842
3843 if (filter->map[direct].name)
3844 free (filter->map[direct].name);
3845 filter->map[direct].name = NULL;
3846 filter->map[direct].map = NULL;
3847 }
3848 return 0;
3849}
3850
3851/* Set unsuppress-map to the peer. */
3852int
paulfd79ac92004-10-13 05:06:08 +00003853peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
3854 const char *name)
paul718e3742002-12-13 20:15:29 +00003855{
3856 struct bgp_filter *filter;
3857 struct peer_group *group;
3858 struct listnode *nn;
3859
3860 if (! peer->afc[afi][safi])
3861 return BGP_ERR_PEER_INACTIVE;
3862
3863 if (peer_is_group_member (peer, afi, safi))
3864 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3865
3866 filter = &peer->filter[afi][safi];
3867
3868 if (filter->usmap.name)
3869 free (filter->usmap.name);
3870
3871 filter->usmap.name = strdup (name);
3872 filter->usmap.map = route_map_lookup_by_name (name);
3873
3874 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3875 return 0;
3876
3877 group = peer->group;
3878 LIST_LOOP (group->peer, peer, nn)
3879 {
3880 filter = &peer->filter[afi][safi];
3881
3882 if (! peer->af_group[afi][safi])
3883 continue;
3884
3885 if (filter->usmap.name)
3886 free (filter->usmap.name);
3887 filter->usmap.name = strdup (name);
3888 filter->usmap.map = route_map_lookup_by_name (name);
3889 }
3890 return 0;
3891}
3892
3893/* Unset route-map from the peer. */
3894int
3895peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
3896{
3897 struct bgp_filter *filter;
3898 struct peer_group *group;
3899 struct listnode *nn;
3900
3901 if (! peer->afc[afi][safi])
3902 return BGP_ERR_PEER_INACTIVE;
3903
3904 if (peer_is_group_member (peer, afi, safi))
3905 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3906
3907 filter = &peer->filter[afi][safi];
3908
3909 if (filter->usmap.name)
3910 free (filter->usmap.name);
3911 filter->usmap.name = NULL;
3912 filter->usmap.map = NULL;
3913
3914 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3915 return 0;
3916
3917 group = peer->group;
3918 LIST_LOOP (group->peer, peer, nn)
3919 {
3920 filter = &peer->filter[afi][safi];
3921
3922 if (! peer->af_group[afi][safi])
3923 continue;
3924
3925 if (filter->usmap.name)
3926 free (filter->usmap.name);
3927 filter->usmap.name = NULL;
3928 filter->usmap.map = NULL;
3929 }
3930 return 0;
3931}
3932
3933int
3934peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hassoe0701b72004-05-20 09:19:34 +00003935 u_int32_t max, u_char threshold, int warning)
paul718e3742002-12-13 20:15:29 +00003936{
3937 struct peer_group *group;
3938 struct listnode *nn;
3939
3940 if (! peer->afc[afi][safi])
3941 return BGP_ERR_PEER_INACTIVE;
3942
3943 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3944 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00003945 peer->pmax_threshold[afi][safi] = threshold;
paul718e3742002-12-13 20:15:29 +00003946 if (warning)
3947 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3948 else
3949 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3950
3951 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3952 return 0;
3953
3954 group = peer->group;
3955 LIST_LOOP (group->peer, peer, nn)
3956 {
3957 if (! peer->af_group[afi][safi])
3958 continue;
3959
3960 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3961 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00003962 peer->pmax_threshold[afi][safi] = threshold;
paul718e3742002-12-13 20:15:29 +00003963 if (warning)
3964 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3965 else
3966 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3967 }
3968 return 0;
3969}
3970
3971int
3972peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
3973{
3974 struct peer_group *group;
3975 struct listnode *nn;
3976
3977 if (! peer->afc[afi][safi])
3978 return BGP_ERR_PEER_INACTIVE;
3979
3980 /* apply peer-group config */
3981 if (peer->af_group[afi][safi])
3982 {
3983 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
3984 PEER_FLAG_MAX_PREFIX))
3985 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3986 else
3987 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3988
3989 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
3990 PEER_FLAG_MAX_PREFIX_WARNING))
3991 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3992 else
3993 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3994
3995 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00003996 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
paul718e3742002-12-13 20:15:29 +00003997 return 0;
3998 }
3999
4000 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4001 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4002 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +00004003 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +00004004
4005 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4006 return 0;
4007
4008 group = peer->group;
4009 LIST_LOOP (group->peer, peer, nn)
4010 {
4011 if (! peer->af_group[afi][safi])
4012 continue;
4013
4014 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4015 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4016 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +00004017 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +00004018 }
4019 return 0;
4020}
4021
4022int
4023peer_clear (struct peer *peer)
4024{
4025 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4026 {
4027 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4028 peer->v_start = BGP_INIT_START_TIMER;
4029 if (peer->status == Established)
4030 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4031 BGP_NOTIFY_CEASE_ADMIN_RESET);
4032 else
4033 BGP_EVENT_ADD (peer, BGP_Stop);
4034 }
4035 return 0;
4036}
4037
4038int
4039peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4040 enum bgp_clear_type stype)
4041{
4042 if (peer->status != Established)
4043 return 0;
4044
4045 if (! peer->afc[afi][safi])
4046 return BGP_ERR_AF_UNCONFIGURED;
4047
paulfee0f4c2004-09-13 05:12:46 +00004048 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4049 {
4050 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4051 return 0;
4052 bgp_check_local_routes_rsclient (peer, afi, safi);
4053 bgp_soft_reconfig_rsclient (peer, afi, safi);
4054 }
4055
paul718e3742002-12-13 20:15:29 +00004056 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4057 bgp_announce_route (peer, afi, safi);
4058
4059 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4060 {
4061 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4062 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4063 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4064 {
4065 struct bgp_filter *filter = &peer->filter[afi][safi];
4066 u_char prefix_type;
4067
4068 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4069 prefix_type = ORF_TYPE_PREFIX;
4070 else
4071 prefix_type = ORF_TYPE_PREFIX_OLD;
4072
4073 if (filter->plist[FILTER_IN].plist)
4074 {
4075 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4076 bgp_route_refresh_send (peer, afi, safi,
4077 prefix_type, REFRESH_DEFER, 1);
4078 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4079 REFRESH_IMMEDIATE, 0);
4080 }
4081 else
4082 {
4083 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4084 bgp_route_refresh_send (peer, afi, safi,
4085 prefix_type, REFRESH_IMMEDIATE, 1);
4086 else
4087 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4088 }
4089 return 0;
4090 }
4091 }
4092
4093 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4094 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4095 {
4096 /* If neighbor has soft reconfiguration inbound flag.
4097 Use Adj-RIB-In database. */
4098 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4099 bgp_soft_reconfig_in (peer, afi, safi);
4100 else
4101 {
4102 /* If neighbor has route refresh capability, send route refresh
4103 message to the peer. */
4104 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4105 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4106 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4107 else
4108 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4109 }
4110 }
4111 return 0;
4112}
4113
paulfd79ac92004-10-13 05:06:08 +00004114/* Display peer uptime.*/
4115/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004116char *
4117peer_uptime (time_t uptime2, char *buf, size_t len)
4118{
4119 time_t uptime1;
4120 struct tm *tm;
4121
4122 /* Check buffer length. */
4123 if (len < BGP_UPTIME_LEN)
4124 {
paula2b1ecd2004-10-31 18:58:09 +00004125 zlog_warn ("peer_uptime (): buffer shortage %ld", len);
paulfd79ac92004-10-13 05:06:08 +00004126 /* XXX: should return status instead of buf... */
4127 snprintf (buf, len, "<error> ");
4128 return buf;
paul718e3742002-12-13 20:15:29 +00004129 }
4130
4131 /* If there is no connection has been done before print `never'. */
4132 if (uptime2 == 0)
4133 {
4134 snprintf (buf, len, "never ");
4135 return buf;
4136 }
4137
4138 /* Get current time. */
4139 uptime1 = time (NULL);
4140 uptime1 -= uptime2;
4141 tm = gmtime (&uptime1);
4142
4143 /* Making formatted timer strings. */
4144#define ONE_DAY_SECOND 60*60*24
4145#define ONE_WEEK_SECOND 60*60*24*7
4146
4147 if (uptime1 < ONE_DAY_SECOND)
4148 snprintf (buf, len, "%02d:%02d:%02d",
4149 tm->tm_hour, tm->tm_min, tm->tm_sec);
4150 else if (uptime1 < ONE_WEEK_SECOND)
4151 snprintf (buf, len, "%dd%02dh%02dm",
4152 tm->tm_yday, tm->tm_hour, tm->tm_min);
4153 else
4154 snprintf (buf, len, "%02dw%dd%02dh",
4155 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4156 return buf;
4157}
4158
4159void
4160bgp_config_write_filter (struct vty *vty, struct peer *peer,
4161 afi_t afi, safi_t safi)
4162{
4163 struct bgp_filter *filter;
4164 struct bgp_filter *gfilter = NULL;
4165 char *addr;
4166 int in = FILTER_IN;
4167 int out = FILTER_OUT;
4168
4169 addr = peer->host;
4170 filter = &peer->filter[afi][safi];
4171 if (peer->af_group[afi][safi])
4172 gfilter = &peer->group->conf->filter[afi][safi];
4173
4174 /* distribute-list. */
4175 if (filter->dlist[in].name)
4176 if (! gfilter || ! gfilter->dlist[in].name
4177 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4178 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4179 filter->dlist[in].name, VTY_NEWLINE);
4180 if (filter->dlist[out].name && ! gfilter)
4181 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4182 filter->dlist[out].name, VTY_NEWLINE);
4183
4184 /* prefix-list. */
4185 if (filter->plist[in].name)
4186 if (! gfilter || ! gfilter->plist[in].name
4187 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4188 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4189 filter->plist[in].name, VTY_NEWLINE);
4190 if (filter->plist[out].name && ! gfilter)
4191 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4192 filter->plist[out].name, VTY_NEWLINE);
4193
4194 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004195 if (filter->map[RMAP_IN].name)
4196 if (! gfilter || ! gfilter->map[RMAP_IN].name
4197 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004198 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004199 filter->map[RMAP_IN].name, VTY_NEWLINE);
4200 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004201 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004202 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4203 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4204 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4205 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4206 if (filter->map[RMAP_EXPORT].name)
4207 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4208 || strcmp (filter->map[RMAP_EXPORT].name,
4209 gfilter->map[RMAP_EXPORT].name) != 0)
4210 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4211 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004212
4213 /* unsuppress-map */
4214 if (filter->usmap.name && ! gfilter)
4215 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4216 filter->usmap.name, VTY_NEWLINE);
4217
4218 /* filter-list. */
4219 if (filter->aslist[in].name)
4220 if (! gfilter || ! gfilter->aslist[in].name
4221 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4222 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4223 filter->aslist[in].name, VTY_NEWLINE);
4224 if (filter->aslist[out].name && ! gfilter)
4225 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4226 filter->aslist[out].name, VTY_NEWLINE);
4227}
4228
4229/* BGP peer configuration display function. */
4230void
4231bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4232 struct peer *peer, afi_t afi, safi_t safi)
4233{
4234 struct bgp_filter *filter;
4235 struct peer *g_peer = NULL;
4236 char buf[SU_ADDRSTRLEN];
4237 char *addr;
4238
4239 filter = &peer->filter[afi][safi];
4240 addr = peer->host;
4241 if (peer_group_active (peer))
4242 g_peer = peer->group->conf;
4243
4244 /************************************
4245 ****** Global to the neighbor ******
4246 ************************************/
4247 if (afi == AFI_IP && safi == SAFI_UNICAST)
4248 {
4249 /* remote-as. */
4250 if (! peer_group_active (peer))
4251 {
4252 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4253 vty_out (vty, " neighbor %s peer-group%s", addr,
4254 VTY_NEWLINE);
4255 if (peer->as)
4256 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4257 VTY_NEWLINE);
4258 }
4259 else
4260 {
4261 if (! g_peer->as)
4262 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4263 VTY_NEWLINE);
4264 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4265 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4266 peer->group->name, VTY_NEWLINE);
4267 }
4268
4269 /* local-as. */
4270 if (peer->change_local_as)
4271 if (! peer_group_active (peer))
4272 vty_out (vty, " neighbor %s local-as %d%s%s", addr,
4273 peer->change_local_as,
4274 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4275 " no-prepend" : "", VTY_NEWLINE);
4276
4277 /* Description. */
4278 if (peer->desc)
4279 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4280 VTY_NEWLINE);
4281
4282 /* Shutdown. */
4283 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4284 if (! peer_group_active (peer) ||
4285 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4286 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4287
4288 /* BGP port. */
4289 if (peer->port != BGP_PORT_DEFAULT)
4290 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
4291 VTY_NEWLINE);
4292
4293 /* Local interface name. */
4294 if (peer->ifname)
4295 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4296 VTY_NEWLINE);
4297
4298 /* Passive. */
4299 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4300 if (! peer_group_active (peer) ||
4301 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4302 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4303
4304 /* EBGP multihop. */
4305 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
4306 if (! peer_group_active (peer) ||
4307 g_peer->ttl != peer->ttl)
4308 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4309 VTY_NEWLINE);
4310
4311 /* Enforce multihop. */
4312 if (CHECK_FLAG (peer->flags, PEER_FLAG_ENFORCE_MULTIHOP))
4313 if (! peer_group_active (peer) ||
4314 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_ENFORCE_MULTIHOP))
4315 vty_out (vty, " neighbor %s enforce-multihop%s", addr, VTY_NEWLINE);
4316
4317 /* Update-source. */
4318 if (peer->update_if)
4319 if (! peer_group_active (peer) || ! g_peer->update_if
4320 || strcmp (g_peer->update_if, peer->update_if) != 0)
4321 vty_out (vty, " neighbor %s update-source %s%s", addr,
4322 peer->update_if, VTY_NEWLINE);
4323 if (peer->update_source)
4324 if (! peer_group_active (peer) || ! g_peer->update_source
4325 || sockunion_cmp (g_peer->update_source,
4326 peer->update_source) != 0)
4327 vty_out (vty, " neighbor %s update-source %s%s", addr,
4328 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4329 VTY_NEWLINE);
4330
4331 /* BGP version print. */
4332 if (peer->version == BGP_VERSION_MP_4_DRAFT_00)
4333 vty_out (vty, " neighbor %s version %s%s",
4334 addr,"4-", VTY_NEWLINE);
4335
4336 /* advertisement-interval */
4337 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4338 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4339 addr, peer->v_routeadv, VTY_NEWLINE);
4340
4341 /* timers. */
4342 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4343 && ! peer_group_active (peer))
4344 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4345 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4346
4347 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4348 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4349 peer->connect, VTY_NEWLINE);
4350
4351 /* Default weight. */
4352 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4353 if (! peer_group_active (peer) ||
4354 g_peer->weight != peer->weight)
4355 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4356 VTY_NEWLINE);
4357
4358 /* Route refresh. */
4359 if (CHECK_FLAG (peer->flags, PEER_FLAG_NO_ROUTE_REFRESH_CAP))
4360 if (! peer_group_active (peer) ||
4361 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_NO_ROUTE_REFRESH_CAP))
4362 vty_out (vty, " no neighbor %s capability route-refresh%s", addr,
4363 VTY_NEWLINE);
4364
4365 /* Dynamic capability. */
4366 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4367 if (! peer_group_active (peer) ||
4368 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4369 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4370 VTY_NEWLINE);
4371
4372 /* dont capability negotiation. */
4373 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4374 if (! peer_group_active (peer) ||
4375 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4376 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4377 VTY_NEWLINE);
4378
4379 /* override capability negotiation. */
4380 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4381 if (! peer_group_active (peer) ||
4382 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4383 vty_out (vty, " neighbor %s override-capability%s", addr,
4384 VTY_NEWLINE);
4385
4386 /* strict capability negotiation. */
4387 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4388 if (! peer_group_active (peer) ||
4389 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4390 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4391 VTY_NEWLINE);
4392
4393 if (! peer_group_active (peer))
4394 {
4395 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4396 {
4397 if (peer->afc[AFI_IP][SAFI_UNICAST])
4398 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4399 }
4400 else
4401 {
4402 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4403 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4404 }
4405 }
4406 }
4407
4408
4409 /************************************
4410 ****** Per AF to the neighbor ******
4411 ************************************/
4412
4413 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4414 {
4415 if (peer->af_group[afi][safi])
4416 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4417 peer->group->name, VTY_NEWLINE);
4418 else
4419 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4420 }
4421
4422 /* ORF capability. */
4423 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4424 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4425 if (! peer->af_group[afi][safi])
4426 {
4427 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4428
4429 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4430 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4431 vty_out (vty, " both");
4432 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4433 vty_out (vty, " send");
4434 else
4435 vty_out (vty, " receive");
4436 vty_out (vty, "%s", VTY_NEWLINE);
4437 }
4438
4439 /* Route reflector client. */
4440 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4441 && ! peer->af_group[afi][safi])
4442 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4443 VTY_NEWLINE);
4444
4445 /* Nexthop self. */
4446 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4447 && ! peer->af_group[afi][safi])
4448 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4449
4450 /* Remove private AS. */
4451 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4452 && ! peer->af_group[afi][safi])
4453 vty_out (vty, " neighbor %s remove-private-AS%s",
4454 addr, VTY_NEWLINE);
4455
4456 /* send-community print. */
4457 if (! peer->af_group[afi][safi])
4458 {
4459 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4460 {
4461 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4462 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4463 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4464 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4465 vty_out (vty, " neighbor %s send-community extended%s",
4466 addr, VTY_NEWLINE);
4467 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4468 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4469 }
4470 else
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, " no neighbor %s send-community both%s",
4475 addr, VTY_NEWLINE);
4476 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4477 vty_out (vty, " no neighbor %s send-community extended%s",
4478 addr, VTY_NEWLINE);
4479 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4480 vty_out (vty, " no neighbor %s send-community%s",
4481 addr, VTY_NEWLINE);
4482 }
4483 }
4484
4485 /* Default information */
4486 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4487 && ! peer->af_group[afi][safi])
4488 {
4489 vty_out (vty, " neighbor %s default-originate", addr);
4490 if (peer->default_rmap[afi][safi].name)
4491 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4492 vty_out (vty, "%s", VTY_NEWLINE);
4493 }
4494
4495 /* Soft reconfiguration inbound. */
4496 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4497 if (! peer->af_group[afi][safi] ||
4498 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4499 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4500 VTY_NEWLINE);
4501
4502 /* maximum-prefix. */
4503 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4504 if (! peer->af_group[afi][safi]
4505 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004506 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004507 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4508 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00004509 {
4510 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
4511 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
4512 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
4513 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
4514 vty_out (vty, " warning-only");
4515 vty_out (vty, "%s", VTY_NEWLINE);
4516 }
paul718e3742002-12-13 20:15:29 +00004517
4518 /* Route server client. */
4519 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
4520 && ! peer->af_group[afi][safi])
4521 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
4522
4523 /* Allow AS in. */
4524 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
4525 if (! peer_group_active (peer)
4526 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
4527 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
4528 {
4529 if (peer->allowas_in[afi][safi] == 3)
4530 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
4531 else
4532 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
4533 peer->allowas_in[afi][safi], VTY_NEWLINE);
4534 }
4535
4536 /* Filter. */
4537 bgp_config_write_filter (vty, peer, afi, safi);
4538
4539 /* atribute-unchanged. */
4540 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4541 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4542 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4543 && ! peer->af_group[afi][safi])
4544 {
4545 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4546 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4547 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4548 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
4549 else
4550 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
4551 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
4552 " as-path" : "",
4553 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
4554 " next-hop" : "",
4555 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
4556 " med" : "", VTY_NEWLINE);
4557 }
4558}
4559
4560/* Display "address-family" configuration header. */
4561void
4562bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
4563 int *write)
4564{
4565 if (*write)
4566 return;
4567
4568 if (afi == AFI_IP && safi == SAFI_UNICAST)
4569 return;
4570
4571 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
4572
4573 if (afi == AFI_IP)
4574 {
4575 if (safi == SAFI_MULTICAST)
4576 vty_out (vty, "ipv4 multicast");
4577 else if (safi == SAFI_MPLS_VPN)
4578 vty_out (vty, "vpnv4 unicast");
4579 }
4580 else if (afi == AFI_IP6)
4581 vty_out (vty, "ipv6");
4582
4583 vty_out (vty, "%s", VTY_NEWLINE);
4584
4585 *write = 1;
4586}
4587
4588/* Address family based peer configuration display. */
4589int
4590bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
4591 safi_t safi)
4592{
4593 int write = 0;
4594 struct peer *peer;
4595 struct peer_group *group;
4596 struct listnode *nn;
4597
4598 bgp_config_write_network (vty, bgp, afi, safi, &write);
4599
4600 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
4601
4602 LIST_LOOP (bgp->group, group, nn)
4603 {
4604 if (group->conf->afc[afi][safi])
4605 {
4606 bgp_config_write_family_header (vty, afi, safi, &write);
4607 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
4608 }
4609 }
4610 LIST_LOOP (bgp->peer, peer, nn)
4611 {
4612 if (peer->afc[afi][safi])
4613 {
4614 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4615 {
4616 bgp_config_write_family_header (vty, afi, safi, &write);
4617 bgp_config_write_peer (vty, bgp, peer, afi, safi);
4618 }
4619 }
4620 }
4621 if (write)
4622 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
4623
4624 return write;
4625}
4626
4627int
4628bgp_config_write (struct vty *vty)
4629{
4630 int write = 0;
4631 struct bgp *bgp;
4632 struct peer_group *group;
4633 struct peer *peer;
4634 struct listnode *nn, *nm, *no;
4635
4636 /* BGP Multiple instance. */
4637 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4638 {
4639 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
4640 write++;
4641 }
4642
4643 /* BGP Config type. */
4644 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4645 {
4646 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
4647 write++;
4648 }
4649
4650 /* BGP configuration. */
4651 LIST_LOOP (bm->bgp, bgp, nn)
4652 {
4653 if (write)
4654 vty_out (vty, "!%s", VTY_NEWLINE);
4655
4656 /* Router bgp ASN */
4657 vty_out (vty, "router bgp %d", bgp->as);
4658
4659 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4660 {
4661 if (bgp->name)
4662 vty_out (vty, " view %s", bgp->name);
4663 }
4664 vty_out (vty, "%s", VTY_NEWLINE);
4665
4666 /* No Synchronization */
4667 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4668 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
4669
4670 /* BGP fast-external-failover. */
4671 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
4672 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
4673
4674 /* BGP router ID. */
4675 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
4676 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
4677 VTY_NEWLINE);
4678
paul848973c2003-08-13 00:32:49 +00004679 /* BGP log-neighbor-changes. */
4680 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
4681 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
4682
paul718e3742002-12-13 20:15:29 +00004683 /* BGP configuration. */
4684 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
4685 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
4686
4687 /* BGP default ipv4-unicast. */
4688 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4689 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
4690
4691 /* BGP default local-preference. */
4692 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
4693 vty_out (vty, " bgp default local-preference %d%s",
4694 bgp->default_local_pref, VTY_NEWLINE);
4695
4696 /* BGP client-to-client reflection. */
4697 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
4698 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
4699
4700 /* BGP cluster ID. */
4701 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
4702 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
4703 VTY_NEWLINE);
4704
hassoe0701b72004-05-20 09:19:34 +00004705 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00004706 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00004707 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
4708 VTY_NEWLINE);
4709
4710 /* Confederation peer */
4711 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00004712 {
hassoe0701b72004-05-20 09:19:34 +00004713 int i;
paul718e3742002-12-13 20:15:29 +00004714
hassoe0701b72004-05-20 09:19:34 +00004715 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00004716
hassoe0701b72004-05-20 09:19:34 +00004717 for (i = 0; i < bgp->confed_peers_cnt; i++)
4718 vty_out(vty, " %d", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00004719
hassoe0701b72004-05-20 09:19:34 +00004720 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004721 }
4722
4723 /* BGP enforce-first-as. */
4724 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
4725 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
4726
4727 /* BGP deterministic-med. */
4728 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
4729 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00004730
4731 /* BGP graceful-restart. */
4732 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
4733 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
4734
paul718e3742002-12-13 20:15:29 +00004735 /* BGP bestpath method. */
4736 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
4737 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
4738 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
4739 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
4740 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
4741 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4742 {
4743 vty_out (vty, " bgp bestpath med");
4744 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
4745 vty_out (vty, " confed");
4746 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4747 vty_out (vty, " missing-as-worst");
4748 vty_out (vty, "%s", VTY_NEWLINE);
4749 }
4750
4751 /* BGP network import check. */
4752 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
4753 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
4754
4755 /* BGP scan interval. */
4756 bgp_config_write_scan_time (vty);
4757
4758 /* BGP flag dampening. */
4759 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
4760 BGP_CONFIG_DAMPENING))
4761 bgp_config_write_damp (vty);
4762
4763 /* BGP static route configuration. */
4764 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4765
4766 /* BGP redistribute configuration. */
4767 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4768
4769 /* BGP timers configuration. */
4770 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
4771 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
4772 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
4773 bgp->default_holdtime, VTY_NEWLINE);
4774
4775 /* peer-group */
4776 LIST_LOOP (bgp->group, group, nm)
4777 {
4778 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
4779 }
4780
4781 /* Normal neighbor configuration. */
4782 LIST_LOOP (bgp->peer, peer, no)
4783 {
4784 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4785 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
4786 }
4787
4788 /* Distance configuration. */
4789 bgp_config_write_distance (vty, bgp);
4790
4791 /* No auto-summary */
4792 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4793 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
4794
4795 /* IPv4 multicast configuration. */
4796 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
4797
4798 /* IPv4 VPN configuration. */
4799 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
4800
4801 /* IPv6 unicast configuration. */
4802 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
4803
4804 write++;
4805 }
4806 return write;
4807}
4808
4809void
4810bgp_master_init ()
4811{
4812 memset (&bgp_master, 0, sizeof (struct bgp_master));
4813
4814 bm = &bgp_master;
4815 bm->bgp = list_new ();
4816 bm->port = BGP_PORT_DEFAULT;
4817 bm->master = thread_master_create ();
4818 bm->start_time = time (NULL);
4819}
4820
4821void
4822bgp_init ()
4823{
4824 void bgp_zebra_init ();
4825 void bgp_route_map_init ();
4826 void bgp_filter_init ();
4827
4828 /* BGP VTY commands installation. */
4829 bgp_vty_init ();
4830
4831 /* Create BGP server socket. */
4832 bgp_socket (NULL, bm->port);
4833
4834 /* Init zebra. */
4835 bgp_zebra_init ();
4836
4837 /* BGP inits. */
4838 bgp_attr_init ();
4839 bgp_debug_init ();
4840 bgp_dump_init ();
4841 bgp_route_init ();
4842 bgp_route_map_init ();
4843 bgp_scan_init ();
4844 bgp_mplsvpn_init ();
4845
4846 /* Access list initialize. */
4847 access_list_init ();
4848 access_list_add_hook (peer_distribute_update);
4849 access_list_delete_hook (peer_distribute_update);
4850
4851 /* Filter list initialize. */
4852 bgp_filter_init ();
4853 as_list_add_hook (peer_aslist_update);
4854 as_list_delete_hook (peer_aslist_update);
4855
4856 /* Prefix list initialize.*/
4857 prefix_list_init ();
4858 prefix_list_add_hook (peer_prefix_list_update);
4859 prefix_list_delete_hook (peer_prefix_list_update);
4860
4861 /* Community list initialize. */
4862 bgp_clist = community_list_init ();
4863
4864#ifdef HAVE_SNMP
4865 bgp_snmp_init ();
4866#endif /* HAVE_SNMP */
4867}
paul545acaf2004-04-20 15:13:15 +00004868
4869void
4870bgp_terminate ()
4871{
4872 struct bgp_master *bm;
4873 struct bgp *bgp;
4874 struct peer *peer;
4875 struct listnode *nn;
4876 struct listnode *mm;
4877
4878 bm = bgp_get_master ();
4879
4880 LIST_LOOP (bm->bgp, bgp, nn)
4881 LIST_LOOP (bgp->peer, peer, mm)
4882 if (peer->status == Established)
4883 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4884 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
4885
4886 bgp_cleanup_routes ();
4887}
4888