blob: cb760d9095c7bd6327c706c0b9b4356b4a1b3c9e [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
1783/* Return first entry of BGP. */
1784struct bgp *
1785bgp_get_default ()
1786{
1787 if (bm->bgp->head)
1788 return bm->bgp->head->data;
1789 return NULL;
1790}
1791
1792/* Lookup BGP entry. */
1793struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001794bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001795{
1796 struct bgp *bgp;
1797 struct listnode *nn;
1798
1799 LIST_LOOP (bm->bgp, bgp, nn)
1800 if (bgp->as == as
1801 && ((bgp->name == NULL && name == NULL)
1802 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1803 return bgp;
1804 return NULL;
1805}
1806
1807/* Lookup BGP structure by view name. */
1808struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001809bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00001810{
1811 struct bgp *bgp;
1812 struct listnode *nn;
1813
1814 LIST_LOOP (bm->bgp, bgp, nn)
1815 if ((bgp->name == NULL && name == NULL)
1816 || (bgp->name && name && strcmp (bgp->name, name) == 0))
1817 return bgp;
1818 return NULL;
1819}
1820
1821/* Called from VTY commands. */
1822int
paulfd79ac92004-10-13 05:06:08 +00001823bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001824{
1825 struct bgp *bgp;
1826
1827 /* Multiple instance check. */
1828 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
1829 {
1830 if (name)
1831 bgp = bgp_lookup_by_name (name);
1832 else
1833 bgp = bgp_get_default ();
1834
1835 /* Already exists. */
1836 if (bgp)
1837 {
1838 if (bgp->as != *as)
1839 {
1840 *as = bgp->as;
1841 return BGP_ERR_INSTANCE_MISMATCH;
1842 }
1843 *bgp_val = bgp;
1844 return 0;
1845 }
1846 }
1847 else
1848 {
1849 /* BGP instance name can not be specified for single instance. */
1850 if (name)
1851 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
1852
1853 /* Get default BGP structure if exists. */
1854 bgp = bgp_get_default ();
1855
1856 if (bgp)
1857 {
1858 if (bgp->as != *as)
1859 {
1860 *as = bgp->as;
1861 return BGP_ERR_AS_MISMATCH;
1862 }
1863 *bgp_val = bgp;
1864 return 0;
1865 }
1866 }
1867
1868 bgp = bgp_create (as, name);
1869 listnode_add (bm->bgp, bgp);
hasso18a6dce2004-10-03 18:18:34 +00001870 bgp_router_id_set(bgp, &router_id_zebra);
paul718e3742002-12-13 20:15:29 +00001871 *bgp_val = bgp;
1872
1873 return 0;
1874}
1875
1876/* Delete BGP instance. */
1877int
1878bgp_delete (struct bgp *bgp)
1879{
1880 struct peer *peer;
1881 struct listnode *nn;
1882 struct listnode *next;
1883 afi_t afi;
1884 safi_t safi;
1885 int i;
1886
1887 /* Delete static route. */
1888 bgp_static_delete (bgp);
1889
1890 /* Unset redistribution. */
1891 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1892 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
1893 if (i != ZEBRA_ROUTE_BGP)
1894 bgp_redistribute_unset (bgp, afi, i);
1895
1896 bgp->group->del = (void (*)(void *)) peer_group_delete;
1897 list_delete (bgp->group);
1898
1899 for (nn = bgp->peer->head; nn; nn = next)
1900 {
1901 peer = nn->data;
1902 next = nn->next;
1903 peer_delete (peer);
1904 }
1905
paulfee0f4c2004-09-13 05:12:46 +00001906 bgp->rsclient->del = (void (*)(void *)) peer_delete;
1907 list_delete (bgp->rsclient);
1908
paul718e3742002-12-13 20:15:29 +00001909 listnode_delete (bm->bgp, bgp);
1910
1911 if (bgp->name)
1912 free (bgp->name);
1913
1914 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1915 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1916 {
1917 if (bgp->route[afi][safi])
1918 XFREE (MTYPE_ROUTE_TABLE, bgp->route[afi][safi]);
1919 if (bgp->aggregate[afi][safi])
1920 XFREE (MTYPE_ROUTE_TABLE,bgp->aggregate[afi][safi]) ;
1921 if (bgp->rib[afi][safi])
1922 XFREE (MTYPE_ROUTE_TABLE,bgp->rib[afi][safi]);
1923 }
1924 XFREE (MTYPE_BGP, bgp);
1925
1926 return 0;
1927}
1928
1929struct peer *
1930peer_lookup (struct bgp *bgp, union sockunion *su)
1931{
1932 struct peer *peer;
1933 struct listnode *nn;
1934
1935 if (! bgp)
1936 bgp = bgp_get_default ();
1937
1938 if (! bgp)
1939 return NULL;
1940
1941 LIST_LOOP (bgp->peer, peer, nn)
1942 {
pauleb821182004-05-01 08:44:08 +00001943 if (sockunion_same (&peer->su, su)
1944 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1945 return peer;
paul718e3742002-12-13 20:15:29 +00001946 }
1947 return NULL;
1948}
1949
1950struct peer *
1951peer_lookup_with_open (union sockunion *su, as_t remote_as,
1952 struct in_addr *remote_id, int *as)
1953{
1954 struct peer *peer;
1955 struct listnode *nn;
1956 struct bgp *bgp;
1957
1958 bgp = bgp_get_default ();
1959 if (! bgp)
1960 return NULL;
1961
1962 LIST_LOOP (bgp->peer, peer, nn)
1963 {
pauleb821182004-05-01 08:44:08 +00001964 if (sockunion_same (&peer->su, su)
1965 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1966 {
1967 if (peer->as == remote_as
1968 && peer->remote_id.s_addr == remote_id->s_addr)
1969 return peer;
1970 if (peer->as == remote_as)
1971 *as = 1;
1972 }
paul718e3742002-12-13 20:15:29 +00001973 }
1974 LIST_LOOP (bgp->peer, peer, nn)
1975 {
pauleb821182004-05-01 08:44:08 +00001976 if (sockunion_same (&peer->su, su)
1977 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1978 {
1979 if (peer->as == remote_as
1980 && peer->remote_id.s_addr == 0)
1981 return peer;
1982 if (peer->as == remote_as)
1983 *as = 1;
1984 }
paul718e3742002-12-13 20:15:29 +00001985 }
1986 return NULL;
1987}
1988
1989/* If peer is configured at least one address family return 1. */
1990int
1991peer_active (struct peer *peer)
1992{
1993 if (peer->afc[AFI_IP][SAFI_UNICAST]
1994 || peer->afc[AFI_IP][SAFI_MULTICAST]
1995 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
1996 || peer->afc[AFI_IP6][SAFI_UNICAST]
1997 || peer->afc[AFI_IP6][SAFI_MULTICAST])
1998 return 1;
1999 return 0;
2000}
2001
2002/* If peer is negotiated at least one address family return 1. */
2003int
2004peer_active_nego (struct peer *peer)
2005{
2006 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2007 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2008 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2009 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2010 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2011 return 1;
2012 return 0;
2013}
2014
2015/* peer_flag_change_type. */
2016enum peer_change_type
2017{
2018 peer_change_none,
2019 peer_change_reset,
2020 peer_change_reset_in,
2021 peer_change_reset_out,
2022};
2023
2024void
2025peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2026 enum peer_change_type type)
2027{
2028 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2029 return;
2030
2031 if (type == peer_change_reset)
2032 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2033 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2034 else if (type == peer_change_reset_in)
2035 {
2036 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2037 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2038 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2039 else
2040 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2041 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2042 }
2043 else if (type == peer_change_reset_out)
2044 bgp_announce_route (peer, afi, safi);
2045}
2046
2047struct peer_flag_action
2048{
2049 /* Peer's flag. */
2050 u_int32_t flag;
2051
2052 /* This flag can be set for peer-group member. */
2053 u_char not_for_member;
2054
2055 /* Action when the flag is changed. */
2056 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002057
2058 /* Peer down cause */
2059 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002060};
2061
2062struct peer_flag_action peer_flag_action_list[] =
2063 {
2064 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2065 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2066 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2067 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2068 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
2069 { PEER_FLAG_NO_ROUTE_REFRESH_CAP, 0, peer_change_reset },
2070 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
2071 { PEER_FLAG_ENFORCE_MULTIHOP, 0, peer_change_reset },
2072 { 0, 0, 0 }
2073 };
2074
2075struct peer_flag_action peer_af_flag_action_list[] =
2076 {
2077 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2078 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2079 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2080 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2081 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2082 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2083 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2084 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2085 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2086 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2087 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2088 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2089 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002090 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002091 { 0, 0, 0 }
2092 };
2093
2094/* Proper action set. */
2095int
2096peer_flag_action_set (struct peer_flag_action *action_list, int size,
2097 struct peer_flag_action *action, u_int32_t flag)
2098{
2099 int i;
2100 int found = 0;
2101 int reset_in = 0;
2102 int reset_out = 0;
2103 struct peer_flag_action *match = NULL;
2104
2105 /* Check peer's frag action. */
2106 for (i = 0; i < size; i++)
2107 {
2108 match = &action_list[i];
2109
2110 if (match->flag == 0)
2111 break;
2112
2113 if (match->flag & flag)
2114 {
2115 found = 1;
2116
2117 if (match->type == peer_change_reset_in)
2118 reset_in = 1;
2119 if (match->type == peer_change_reset_out)
2120 reset_out = 1;
2121 if (match->type == peer_change_reset)
2122 {
2123 reset_in = 1;
2124 reset_out = 1;
2125 }
2126 if (match->not_for_member)
2127 action->not_for_member = 1;
2128 }
2129 }
2130
2131 /* Set peer clear type. */
2132 if (reset_in && reset_out)
2133 action->type = peer_change_reset;
2134 else if (reset_in)
2135 action->type = peer_change_reset_in;
2136 else if (reset_out)
2137 action->type = peer_change_reset_out;
2138 else
2139 action->type = peer_change_none;
2140
2141 return found;
2142}
2143
2144void
2145peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2146{
2147 if (flag == PEER_FLAG_SHUTDOWN)
2148 {
2149 if (CHECK_FLAG (peer->flags, flag))
2150 {
2151 if (peer->status == Established)
2152 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2153 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2154 else
2155 BGP_EVENT_ADD (peer, BGP_Stop);
2156 }
2157 else
2158 {
2159 peer->v_start = BGP_INIT_START_TIMER;
2160 BGP_EVENT_ADD (peer, BGP_Stop);
2161 }
2162 }
2163 else if (peer->status == Established)
2164 {
2165 if (flag == PEER_FLAG_NO_ROUTE_REFRESH_CAP
2166 && CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
2167 {
2168 if (CHECK_FLAG (peer->flags, flag))
2169 UNSET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
2170 else
2171 SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
2172
2173 bgp_capability_send (peer, AFI_IP, SAFI_UNICAST,
2174 CAPABILITY_CODE_REFRESH,
2175 CHECK_FLAG (peer->flags, flag) ?
2176 CAPABILITY_ACTION_UNSET : CAPABILITY_ACTION_SET);
2177 }
2178 else
hassoe0701b72004-05-20 09:19:34 +00002179 {
2180 if (flag == PEER_FLAG_NO_ROUTE_REFRESH_CAP)
2181 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2182 else if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2183 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2184 else if (flag == PEER_FLAG_PASSIVE)
2185 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
2186 else if (flag == PEER_FLAG_ENFORCE_MULTIHOP)
2187 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
2188
2189 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2190 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2191 }
paul718e3742002-12-13 20:15:29 +00002192 }
2193 else
2194 BGP_EVENT_ADD (peer, BGP_Stop);
2195}
2196
2197/* Change specified peer flag. */
2198int
2199peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2200{
2201 int found;
2202 int size;
2203 struct peer_group *group;
2204 struct listnode *nn;
2205 struct peer_flag_action action;
2206
2207 memset (&action, 0, sizeof (struct peer_flag_action));
2208 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2209
2210 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2211
2212 /* No flag action is found. */
2213 if (! found)
2214 return BGP_ERR_INVALID_FLAG;
2215
2216 /* Not for peer-group member. */
2217 if (action.not_for_member && peer_group_active (peer))
2218 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2219
2220 /* When unset the peer-group member's flag we have to check
2221 peer-group configuration. */
2222 if (! set && peer_group_active (peer))
2223 if (CHECK_FLAG (peer->group->conf->flags, flag))
2224 {
2225 if (flag == PEER_FLAG_SHUTDOWN)
2226 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2227 else
2228 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2229 }
2230
2231 /* Flag conflict check. */
2232 if (set
2233 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2234 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2235 return BGP_ERR_PEER_FLAG_CONFLICT;
2236
2237 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2238 {
2239 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2240 return 0;
2241 if (! set && ! CHECK_FLAG (peer->flags, flag))
2242 return 0;
2243 }
2244
2245 if (set)
2246 SET_FLAG (peer->flags, flag);
2247 else
2248 UNSET_FLAG (peer->flags, flag);
2249
2250 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2251 {
2252 if (action.type == peer_change_reset)
2253 peer_flag_modify_action (peer, flag);
2254
2255 return 0;
2256 }
2257
2258 /* peer-group member updates. */
2259 group = peer->group;
2260
2261 LIST_LOOP (group->peer, peer, nn)
2262 {
2263 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2264 continue;
2265
2266 if (! set && ! CHECK_FLAG (peer->flags, flag))
2267 continue;
2268
2269 if (set)
2270 SET_FLAG (peer->flags, flag);
2271 else
2272 UNSET_FLAG (peer->flags, flag);
2273
2274 if (action.type == peer_change_reset)
2275 peer_flag_modify_action (peer, flag);
2276 }
2277 return 0;
2278}
2279
2280int
2281peer_flag_set (struct peer *peer, u_int32_t flag)
2282{
2283 return peer_flag_modify (peer, flag, 1);
2284}
2285
2286int
2287peer_flag_unset (struct peer *peer, u_int32_t flag)
2288{
2289 return peer_flag_modify (peer, flag, 0);
2290}
2291
2292int
2293peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2294{
2295 if (peer->af_group[afi][safi])
2296 return 1;
2297 return 0;
2298}
2299
2300int
2301peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2302 int set)
2303{
2304 int found;
2305 int size;
2306 struct listnode *nn;
2307 struct peer_group *group;
2308 struct peer_flag_action action;
2309
2310 memset (&action, 0, sizeof (struct peer_flag_action));
2311 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2312
2313 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2314
2315 /* No flag action is found. */
2316 if (! found)
2317 return BGP_ERR_INVALID_FLAG;
2318
2319 /* Adress family must be activated. */
2320 if (! peer->afc[afi][safi])
2321 return BGP_ERR_PEER_INACTIVE;
2322
2323 /* Not for peer-group member. */
2324 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2325 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2326
2327 /* Spcecial check for reflector client. */
2328 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2329 && peer_sort (peer) != BGP_PEER_IBGP)
2330 return BGP_ERR_NOT_INTERNAL_PEER;
2331
2332 /* Spcecial check for remove-private-AS. */
2333 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2334 && peer_sort (peer) == BGP_PEER_IBGP)
2335 return BGP_ERR_REMOVE_PRIVATE_AS;
2336
2337 /* When unset the peer-group member's flag we have to check
2338 peer-group configuration. */
2339 if (! set && peer->af_group[afi][safi])
2340 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2341 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2342
2343 /* When current flag configuration is same as requested one. */
2344 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2345 {
2346 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2347 return 0;
2348 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2349 return 0;
2350 }
2351
2352 if (set)
2353 SET_FLAG (peer->af_flags[afi][safi], flag);
2354 else
2355 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2356
2357 /* Execute action when peer is established. */
2358 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2359 && peer->status == Established)
2360 {
2361 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2362 bgp_clear_adj_in (peer, afi, safi);
2363 else
hassoe0701b72004-05-20 09:19:34 +00002364 {
2365 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2366 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2367 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2368 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2369 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2370 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2371 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2372 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2373
2374 peer_change_action (peer, afi, safi, action.type);
2375 }
2376
paul718e3742002-12-13 20:15:29 +00002377 }
2378
2379 /* Peer group member updates. */
2380 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2381 {
2382 group = peer->group;
2383
2384 LIST_LOOP (group->peer, peer, nn)
2385 {
2386 if (! peer->af_group[afi][safi])
2387 continue;
2388
2389 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2390 continue;
2391
2392 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2393 continue;
2394
2395 if (set)
2396 SET_FLAG (peer->af_flags[afi][safi], flag);
2397 else
2398 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2399
2400 if (peer->status == Established)
2401 {
2402 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2403 bgp_clear_adj_in (peer, afi, safi);
2404 else
hassoe0701b72004-05-20 09:19:34 +00002405 {
2406 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2407 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2408 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2409 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2410 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2411 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2412 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2413 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2414
2415 peer_change_action (peer, afi, safi, action.type);
2416 }
paul718e3742002-12-13 20:15:29 +00002417 }
2418 }
2419 }
2420 return 0;
2421}
2422
2423int
2424peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2425{
2426 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2427}
2428
2429int
2430peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2431{
2432 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2433}
2434
2435/* EBGP multihop configuration. */
2436int
2437peer_ebgp_multihop_set (struct peer *peer, int ttl)
2438{
2439 struct peer_group *group;
2440 struct listnode *nn;
2441
2442 if (peer_sort (peer) == BGP_PEER_IBGP)
2443 return 0;
2444
2445 peer->ttl = ttl;
2446
2447 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2448 {
pauleb821182004-05-01 08:44:08 +00002449 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2450 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002451 }
2452 else
2453 {
2454 group = peer->group;
2455 LIST_LOOP (group->peer, peer, nn)
pauleb821182004-05-01 08:44:08 +00002456 {
2457 if (peer_sort (peer) == BGP_PEER_IBGP)
2458 continue;
paul718e3742002-12-13 20:15:29 +00002459
pauleb821182004-05-01 08:44:08 +00002460 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002461
pauleb821182004-05-01 08:44:08 +00002462 if (peer->fd >= 0)
2463 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2464 }
paul718e3742002-12-13 20:15:29 +00002465 }
2466 return 0;
2467}
2468
2469int
2470peer_ebgp_multihop_unset (struct peer *peer)
2471{
2472 struct peer_group *group;
2473 struct listnode *nn;
2474
2475 if (peer_sort (peer) == BGP_PEER_IBGP)
2476 return 0;
2477
2478 if (peer_group_active (peer))
2479 peer->ttl = peer->group->conf->ttl;
2480 else
2481 peer->ttl = 1;
2482
2483 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2484 {
pauleb821182004-05-01 08:44:08 +00002485 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2486 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002487 }
2488 else
2489 {
2490 group = peer->group;
2491 LIST_LOOP (group->peer, peer, nn)
pauleb821182004-05-01 08:44:08 +00002492 {
2493 if (peer_sort (peer) == BGP_PEER_IBGP)
2494 continue;
paul718e3742002-12-13 20:15:29 +00002495
pauleb821182004-05-01 08:44:08 +00002496 peer->ttl = 1;
2497
2498 if (peer->fd >= 0)
2499 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2500 }
paul718e3742002-12-13 20:15:29 +00002501 }
2502 return 0;
2503}
2504
2505/* Neighbor description. */
2506int
2507peer_description_set (struct peer *peer, char *desc)
2508{
2509 if (peer->desc)
2510 XFREE (MTYPE_PEER_DESC, peer->desc);
2511
2512 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2513
2514 return 0;
2515}
2516
2517int
2518peer_description_unset (struct peer *peer)
2519{
2520 if (peer->desc)
2521 XFREE (MTYPE_PEER_DESC, peer->desc);
2522
2523 peer->desc = NULL;
2524
2525 return 0;
2526}
2527
2528/* Neighbor update-source. */
2529int
paulfd79ac92004-10-13 05:06:08 +00002530peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002531{
2532 struct peer_group *group;
2533 struct listnode *nn;
2534
2535 if (peer->update_if)
2536 {
2537 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2538 && strcmp (peer->update_if, ifname) == 0)
2539 return 0;
2540
2541 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2542 peer->update_if = NULL;
2543 }
2544
2545 if (peer->update_source)
2546 {
2547 sockunion_free (peer->update_source);
2548 peer->update_source = NULL;
2549 }
2550
2551 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2552
2553 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2554 {
2555 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002556 {
2557 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2558 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2559 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2560 }
paul718e3742002-12-13 20:15:29 +00002561 else
2562 BGP_EVENT_ADD (peer, BGP_Stop);
2563 return 0;
2564 }
2565
2566 /* peer-group member updates. */
2567 group = peer->group;
2568 LIST_LOOP (group->peer, peer, nn)
2569 {
2570 if (peer->update_if)
2571 {
2572 if (strcmp (peer->update_if, ifname) == 0)
2573 continue;
2574
2575 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2576 peer->update_if = NULL;
2577 }
2578
2579 if (peer->update_source)
2580 {
2581 sockunion_free (peer->update_source);
2582 peer->update_source = NULL;
2583 }
2584
2585 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2586
2587 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002588 {
2589 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2590 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2591 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2592 }
paul718e3742002-12-13 20:15:29 +00002593 else
2594 BGP_EVENT_ADD (peer, BGP_Stop);
2595 }
2596 return 0;
2597}
2598
2599int
2600peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2601{
2602 struct peer_group *group;
2603 struct listnode *nn;
2604
2605 if (peer->update_source)
2606 {
2607 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2608 && sockunion_cmp (peer->update_source, su) == 0)
2609 return 0;
2610 sockunion_free (peer->update_source);
2611 peer->update_source = NULL;
2612 }
2613
2614 if (peer->update_if)
2615 {
2616 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2617 peer->update_if = NULL;
2618 }
2619
2620 peer->update_source = sockunion_dup (su);
2621
2622 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2623 {
2624 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002625 {
2626 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2627 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2628 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2629 }
paul718e3742002-12-13 20:15:29 +00002630 else
2631 BGP_EVENT_ADD (peer, BGP_Stop);
2632 return 0;
2633 }
2634
2635 /* peer-group member updates. */
2636 group = peer->group;
2637 LIST_LOOP (group->peer, peer, nn)
2638 {
2639 if (peer->update_source)
2640 {
2641 if (sockunion_cmp (peer->update_source, su) == 0)
2642 continue;
2643 sockunion_free (peer->update_source);
2644 peer->update_source = NULL;
2645 }
2646
2647 if (peer->update_if)
2648 {
2649 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2650 peer->update_if = NULL;
2651 }
2652
2653 peer->update_source = sockunion_dup (su);
2654
2655 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002656 {
2657 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2658 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2659 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2660 }
paul718e3742002-12-13 20:15:29 +00002661 else
2662 BGP_EVENT_ADD (peer, BGP_Stop);
2663 }
2664 return 0;
2665}
2666
2667int
2668peer_update_source_unset (struct peer *peer)
2669{
2670 union sockunion *su;
2671 struct peer_group *group;
2672 struct listnode *nn;
2673
2674 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2675 && ! peer->update_source
2676 && ! peer->update_if)
2677 return 0;
2678
2679 if (peer->update_source)
2680 {
2681 sockunion_free (peer->update_source);
2682 peer->update_source = NULL;
2683 }
2684 if (peer->update_if)
2685 {
2686 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2687 peer->update_if = NULL;
2688 }
2689
2690 if (peer_group_active (peer))
2691 {
2692 group = peer->group;
2693
2694 if (group->conf->update_source)
2695 {
2696 su = sockunion_dup (group->conf->update_source);
2697 peer->update_source = su;
2698 }
2699 else if (group->conf->update_if)
2700 peer->update_if =
2701 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2702 }
2703
2704 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2705 {
2706 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002707 {
2708 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2709 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2710 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2711 }
paul718e3742002-12-13 20:15:29 +00002712 else
2713 BGP_EVENT_ADD (peer, BGP_Stop);
2714 return 0;
2715 }
2716
2717 /* peer-group member updates. */
2718 group = peer->group;
2719 LIST_LOOP (group->peer, peer, nn)
2720 {
2721 if (! peer->update_source && ! peer->update_if)
2722 continue;
2723
2724 if (peer->update_source)
2725 {
2726 sockunion_free (peer->update_source);
2727 peer->update_source = NULL;
2728 }
2729
2730 if (peer->update_if)
2731 {
2732 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2733 peer->update_if = NULL;
2734 }
2735
2736 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002737 {
2738 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2739 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2740 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2741 }
paul718e3742002-12-13 20:15:29 +00002742 else
2743 BGP_EVENT_ADD (peer, BGP_Stop);
2744 }
2745 return 0;
2746}
2747
2748int
2749peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00002750 const char *rmap)
paul718e3742002-12-13 20:15:29 +00002751{
2752 struct peer_group *group;
2753 struct listnode *nn;
2754
2755 /* Adress family must be activated. */
2756 if (! peer->afc[afi][safi])
2757 return BGP_ERR_PEER_INACTIVE;
2758
2759 /* Default originate can't be used for peer group memeber. */
2760 if (peer_is_group_member (peer, afi, safi))
2761 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2762
2763 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
2764 || (rmap && ! peer->default_rmap[afi][safi].name)
2765 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
2766 {
2767 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2768
2769 if (rmap)
2770 {
2771 if (peer->default_rmap[afi][safi].name)
2772 free (peer->default_rmap[afi][safi].name);
2773 peer->default_rmap[afi][safi].name = strdup (rmap);
2774 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2775 }
2776 }
2777
2778 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2779 {
2780 if (peer->status == Established && peer->afc_nego[afi][safi])
2781 bgp_default_originate (peer, afi, safi, 0);
2782 return 0;
2783 }
2784
2785 /* peer-group member updates. */
2786 group = peer->group;
2787 LIST_LOOP (group->peer, peer, nn)
2788 {
2789 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2790
2791 if (rmap)
2792 {
2793 if (peer->default_rmap[afi][safi].name)
2794 free (peer->default_rmap[afi][safi].name);
2795 peer->default_rmap[afi][safi].name = strdup (rmap);
2796 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2797 }
2798
2799 if (peer->status == Established && peer->afc_nego[afi][safi])
2800 bgp_default_originate (peer, afi, safi, 0);
2801 }
2802 return 0;
2803}
2804
2805int
2806peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
2807{
2808 struct peer_group *group;
2809 struct listnode *nn;
2810
2811 /* Adress family must be activated. */
2812 if (! peer->afc[afi][safi])
2813 return BGP_ERR_PEER_INACTIVE;
2814
2815 /* Default originate can't be used for peer group memeber. */
2816 if (peer_is_group_member (peer, afi, safi))
2817 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2818
2819 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
2820 {
2821 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2822
2823 if (peer->default_rmap[afi][safi].name)
2824 free (peer->default_rmap[afi][safi].name);
2825 peer->default_rmap[afi][safi].name = NULL;
2826 peer->default_rmap[afi][safi].map = NULL;
2827 }
2828
2829 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2830 {
2831 if (peer->status == Established && peer->afc_nego[afi][safi])
2832 bgp_default_originate (peer, afi, safi, 1);
2833 return 0;
2834 }
2835
2836 /* peer-group member updates. */
2837 group = peer->group;
2838 LIST_LOOP (group->peer, peer, nn)
2839 {
2840 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2841
2842 if (peer->default_rmap[afi][safi].name)
2843 free (peer->default_rmap[afi][safi].name);
2844 peer->default_rmap[afi][safi].name = NULL;
2845 peer->default_rmap[afi][safi].map = NULL;
2846
2847 if (peer->status == Established && peer->afc_nego[afi][safi])
2848 bgp_default_originate (peer, afi, safi, 1);
2849 }
2850 return 0;
2851}
2852
2853int
2854peer_port_set (struct peer *peer, u_int16_t port)
2855{
2856 peer->port = port;
2857 return 0;
2858}
2859
2860int
2861peer_port_unset (struct peer *peer)
2862{
2863 peer->port = BGP_PORT_DEFAULT;
2864 return 0;
2865}
2866
2867/* neighbor weight. */
2868int
2869peer_weight_set (struct peer *peer, u_int16_t weight)
2870{
2871 struct peer_group *group;
2872 struct listnode *nn;
2873
2874 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
2875 peer->weight = weight;
2876
2877 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2878 return 0;
2879
2880 /* peer-group member updates. */
2881 group = peer->group;
2882 LIST_LOOP (group->peer, peer, nn)
2883 {
2884 peer->weight = group->conf->weight;
2885 }
2886 return 0;
2887}
2888
2889int
2890peer_weight_unset (struct peer *peer)
2891{
2892 struct peer_group *group;
2893 struct listnode *nn;
2894
2895 /* Set default weight. */
2896 if (peer_group_active (peer))
2897 peer->weight = peer->group->conf->weight;
2898 else
2899 peer->weight = 0;
2900
2901 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
2902
2903 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2904 return 0;
2905
2906 /* peer-group member updates. */
2907 group = peer->group;
2908 LIST_LOOP (group->peer, peer, nn)
2909 {
2910 peer->weight = 0;
2911 }
2912 return 0;
2913}
2914
2915int
2916peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
2917{
2918 struct peer_group *group;
2919 struct listnode *nn;
2920
2921 /* Not for peer group memeber. */
2922 if (peer_group_active (peer))
2923 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2924
2925 /* keepalive value check. */
2926 if (keepalive > 65535)
2927 return BGP_ERR_INVALID_VALUE;
2928
2929 /* Holdtime value check. */
2930 if (holdtime > 65535)
2931 return BGP_ERR_INVALID_VALUE;
2932
2933 /* Holdtime value must be either 0 or greater than 3. */
2934 if (holdtime < 3 && holdtime != 0)
2935 return BGP_ERR_INVALID_VALUE;
2936
2937 /* Set value to the configuration. */
2938 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
2939 peer->holdtime = holdtime;
2940 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
2941
2942 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2943 return 0;
2944
2945 /* peer-group member updates. */
2946 group = peer->group;
2947 LIST_LOOP (group->peer, peer, nn)
2948 {
2949 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
2950 peer->holdtime = group->conf->holdtime;
2951 peer->keepalive = group->conf->keepalive;
2952 }
2953 return 0;
2954}
2955
2956int
2957peer_timers_unset (struct peer *peer)
2958{
2959 struct peer_group *group;
2960 struct listnode *nn;
2961
2962 if (peer_group_active (peer))
2963 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2964
2965 /* Clear configuration. */
2966 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
2967 peer->keepalive = 0;
2968 peer->holdtime = 0;
2969
2970 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2971 return 0;
2972
2973 /* peer-group member updates. */
2974 group = peer->group;
2975 LIST_LOOP (group->peer, peer, nn)
2976 {
2977 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
2978 peer->holdtime = 0;
2979 peer->keepalive = 0;
2980 }
2981
2982 return 0;
2983}
2984
2985int
2986peer_timers_connect_set (struct peer *peer, u_int32_t connect)
2987{
2988 if (peer_group_active (peer))
2989 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2990
2991 if (connect > 65535)
2992 return BGP_ERR_INVALID_VALUE;
2993
2994 /* Set value to the configuration. */
2995 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
2996 peer->connect = connect;
2997
2998 /* Set value to timer setting. */
2999 peer->v_connect = connect;
3000
3001 return 0;
3002}
3003
3004int
3005peer_timers_connect_unset (struct peer *peer)
3006{
3007 if (peer_group_active (peer))
3008 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3009
3010 /* Clear configuration. */
3011 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3012 peer->connect = 0;
3013
3014 /* Set timer setting to default value. */
3015 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3016
3017 return 0;
3018}
3019
3020int
3021peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3022{
3023 if (peer_group_active (peer))
3024 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3025
3026 if (routeadv > 600)
3027 return BGP_ERR_INVALID_VALUE;
3028
3029 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3030 peer->routeadv = routeadv;
3031 peer->v_routeadv = routeadv;
3032
3033 return 0;
3034}
3035
3036int
3037peer_advertise_interval_unset (struct peer *peer)
3038{
3039 if (peer_group_active (peer))
3040 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3041
3042 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3043 peer->routeadv = 0;
3044
3045 if (peer_sort (peer) == BGP_PEER_IBGP)
3046 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3047 else
3048 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3049
3050 return 0;
3051}
3052
3053int
3054peer_version_set (struct peer *peer, int version)
3055{
3056 if (version != BGP_VERSION_4 && version != BGP_VERSION_MP_4_DRAFT_00)
3057 return BGP_ERR_INVALID_VALUE;
3058
3059 peer->version = version;
3060
3061 return 0;
3062}
3063
3064int
3065peer_version_unset (struct peer *peer)
3066{
3067 peer->version = BGP_VERSION_4;
3068 return 0;
3069}
3070
3071/* neighbor interface */
3072int
paulfd79ac92004-10-13 05:06:08 +00003073peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003074{
3075 if (peer->ifname)
3076 free (peer->ifname);
3077 peer->ifname = strdup (str);
3078
3079 return 0;
3080}
3081
3082int
3083peer_interface_unset (struct peer *peer)
3084{
3085 if (peer->ifname)
3086 free (peer->ifname);
3087 peer->ifname = NULL;
3088
3089 return 0;
3090}
3091
3092/* Allow-as in. */
3093int
3094peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3095{
3096 struct peer_group *group;
3097 struct listnode *nn;
3098
3099 if (allow_num < 1 || allow_num > 10)
3100 return BGP_ERR_INVALID_VALUE;
3101
3102 if (peer->allowas_in[afi][safi] != allow_num)
3103 {
3104 peer->allowas_in[afi][safi] = allow_num;
3105 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3106 peer_change_action (peer, afi, safi, peer_change_reset_in);
3107 }
3108
3109 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3110 return 0;
3111
3112 group = peer->group;
3113 LIST_LOOP (group->peer, peer, nn)
3114 {
3115 if (peer->allowas_in[afi][safi] != allow_num)
3116 {
3117 peer->allowas_in[afi][safi] = allow_num;
3118 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3119 peer_change_action (peer, afi, safi, peer_change_reset_in);
3120 }
3121
3122 }
3123 return 0;
3124}
3125
3126int
3127peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3128{
3129 struct peer_group *group;
3130 struct listnode *nn;
3131
3132 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3133 {
3134 peer->allowas_in[afi][safi] = 0;
3135 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3136 }
3137
3138 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3139 return 0;
3140
3141 group = peer->group;
3142 LIST_LOOP (group->peer, peer, nn)
3143 {
3144 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3145 {
3146 peer->allowas_in[afi][safi] = 0;
3147 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3148 }
3149 }
3150 return 0;
3151}
3152
3153int
3154peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3155{
3156 struct bgp *bgp = peer->bgp;
3157 struct peer_group *group;
3158 struct listnode *nn;
3159
3160 if (peer_sort (peer) != BGP_PEER_EBGP
3161 && peer_sort (peer) != BGP_PEER_INTERNAL)
3162 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3163
3164 if (bgp->as == as)
3165 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3166
3167 if (peer_group_active (peer))
3168 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3169
3170 if (peer->change_local_as == as &&
3171 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3172 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3173 return 0;
3174
3175 peer->change_local_as = as;
3176 if (no_prepend)
3177 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3178 else
3179 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3180
3181 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3182 {
3183 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003184 {
3185 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3186 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3187 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3188 }
paul718e3742002-12-13 20:15:29 +00003189 else
3190 BGP_EVENT_ADD (peer, BGP_Stop);
3191
3192 return 0;
3193 }
3194
3195 group = peer->group;
3196 LIST_LOOP (group->peer, peer, nn)
3197 {
3198 peer->change_local_as = as;
3199 if (no_prepend)
3200 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3201 else
3202 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3203
3204 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003205 {
3206 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3207 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3208 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3209 }
paul718e3742002-12-13 20:15:29 +00003210 else
3211 BGP_EVENT_ADD (peer, BGP_Stop);
3212 }
3213
3214 return 0;
3215}
3216
3217int
3218peer_local_as_unset (struct peer *peer)
3219{
3220 struct peer_group *group;
3221 struct listnode *nn;
3222
3223 if (peer_group_active (peer))
3224 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3225
3226 if (! peer->change_local_as)
3227 return 0;
3228
3229 peer->change_local_as = 0;
3230 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3231
3232 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3233 {
3234 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003235 {
3236 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3237 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3238 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3239 }
paul718e3742002-12-13 20:15:29 +00003240 else
3241 BGP_EVENT_ADD (peer, BGP_Stop);
3242
3243 return 0;
3244 }
3245
3246 group = peer->group;
3247 LIST_LOOP (group->peer, peer, nn)
3248 {
3249 peer->change_local_as = 0;
3250 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3251
3252 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003253 {
3254 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3255 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3256 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3257 }
paul718e3742002-12-13 20:15:29 +00003258 else
3259 BGP_EVENT_ADD (peer, BGP_Stop);
3260 }
3261 return 0;
3262}
3263
3264/* Set distribute list to the peer. */
3265int
3266peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003267 const char *name)
paul718e3742002-12-13 20:15:29 +00003268{
3269 struct bgp_filter *filter;
3270 struct peer_group *group;
3271 struct listnode *nn;
3272
3273 if (! peer->afc[afi][safi])
3274 return BGP_ERR_PEER_INACTIVE;
3275
3276 if (direct != FILTER_IN && direct != FILTER_OUT)
3277 return BGP_ERR_INVALID_VALUE;
3278
3279 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3280 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3281
3282 filter = &peer->filter[afi][safi];
3283
3284 if (filter->plist[direct].name)
3285 return BGP_ERR_PEER_FILTER_CONFLICT;
3286
3287 if (filter->dlist[direct].name)
3288 free (filter->dlist[direct].name);
3289 filter->dlist[direct].name = strdup (name);
3290 filter->dlist[direct].alist = access_list_lookup (afi, name);
3291
3292 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3293 return 0;
3294
3295 group = peer->group;
3296 LIST_LOOP (group->peer, peer, nn)
3297 {
3298 filter = &peer->filter[afi][safi];
3299
3300 if (! peer->af_group[afi][safi])
3301 continue;
3302
3303 if (filter->dlist[direct].name)
3304 free (filter->dlist[direct].name);
3305 filter->dlist[direct].name = strdup (name);
3306 filter->dlist[direct].alist = access_list_lookup (afi, name);
3307 }
3308
3309 return 0;
3310}
3311
3312int
3313peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3314{
3315 struct bgp_filter *filter;
3316 struct bgp_filter *gfilter;
3317 struct peer_group *group;
3318 struct listnode *nn;
3319
3320 if (! peer->afc[afi][safi])
3321 return BGP_ERR_PEER_INACTIVE;
3322
3323 if (direct != FILTER_IN && direct != FILTER_OUT)
3324 return BGP_ERR_INVALID_VALUE;
3325
3326 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3327 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3328
3329 filter = &peer->filter[afi][safi];
3330
3331 /* apply peer-group filter */
3332 if (peer->af_group[afi][safi])
3333 {
3334 gfilter = &peer->group->conf->filter[afi][safi];
3335
3336 if (gfilter->dlist[direct].name)
3337 {
3338 if (filter->dlist[direct].name)
3339 free (filter->dlist[direct].name);
3340 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3341 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3342 return 0;
3343 }
3344 }
3345
3346 if (filter->dlist[direct].name)
3347 free (filter->dlist[direct].name);
3348 filter->dlist[direct].name = NULL;
3349 filter->dlist[direct].alist = NULL;
3350
3351 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3352 return 0;
3353
3354 group = peer->group;
3355 LIST_LOOP (group->peer, peer, nn)
3356 {
3357 filter = &peer->filter[afi][safi];
3358
3359 if (! peer->af_group[afi][safi])
3360 continue;
3361
3362 if (filter->dlist[direct].name)
3363 free (filter->dlist[direct].name);
3364 filter->dlist[direct].name = NULL;
3365 filter->dlist[direct].alist = NULL;
3366 }
3367
3368 return 0;
3369}
3370
3371/* Update distribute list. */
3372void
3373peer_distribute_update (struct access_list *access)
3374{
3375 afi_t afi;
3376 safi_t safi;
3377 int direct;
3378 struct listnode *nn, *nm;
3379 struct bgp *bgp;
3380 struct peer *peer;
3381 struct peer_group *group;
3382 struct bgp_filter *filter;
3383
3384 LIST_LOOP (bm->bgp, bgp, nn)
3385 {
3386 LIST_LOOP (bgp->peer, peer, nm)
3387 {
3388 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3389 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3390 {
3391 filter = &peer->filter[afi][safi];
3392
3393 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3394 {
3395 if (filter->dlist[direct].name)
3396 filter->dlist[direct].alist =
3397 access_list_lookup (afi, filter->dlist[direct].name);
3398 else
3399 filter->dlist[direct].alist = NULL;
3400 }
3401 }
3402 }
3403 LIST_LOOP (bgp->group, group, nm)
3404 {
3405 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3406 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3407 {
3408 filter = &group->conf->filter[afi][safi];
3409
3410 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3411 {
3412 if (filter->dlist[direct].name)
3413 filter->dlist[direct].alist =
3414 access_list_lookup (afi, filter->dlist[direct].name);
3415 else
3416 filter->dlist[direct].alist = NULL;
3417 }
3418 }
3419 }
3420 }
3421}
3422
3423/* Set prefix list to the peer. */
3424int
3425peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003426 const char *name)
paul718e3742002-12-13 20:15:29 +00003427{
3428 struct bgp_filter *filter;
3429 struct peer_group *group;
3430 struct listnode *nn;
3431
3432 if (! peer->afc[afi][safi])
3433 return BGP_ERR_PEER_INACTIVE;
3434
3435 if (direct != FILTER_IN && direct != FILTER_OUT)
3436 return BGP_ERR_INVALID_VALUE;
3437
3438 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3439 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3440
3441 filter = &peer->filter[afi][safi];
3442
3443 if (filter->dlist[direct].name)
3444 return BGP_ERR_PEER_FILTER_CONFLICT;
3445
3446 if (filter->plist[direct].name)
3447 free (filter->plist[direct].name);
3448 filter->plist[direct].name = strdup (name);
3449 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3450
3451 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3452 return 0;
3453
3454 group = peer->group;
3455 LIST_LOOP (group->peer, peer, nn)
3456 {
3457 filter = &peer->filter[afi][safi];
3458
3459 if (! peer->af_group[afi][safi])
3460 continue;
3461
3462 if (filter->plist[direct].name)
3463 free (filter->plist[direct].name);
3464 filter->plist[direct].name = strdup (name);
3465 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3466 }
3467 return 0;
3468}
3469
3470int
3471peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3472{
3473 struct bgp_filter *filter;
3474 struct bgp_filter *gfilter;
3475 struct peer_group *group;
3476 struct listnode *nn;
3477
3478 if (! peer->afc[afi][safi])
3479 return BGP_ERR_PEER_INACTIVE;
3480
3481 if (direct != FILTER_IN && direct != FILTER_OUT)
3482 return BGP_ERR_INVALID_VALUE;
3483
3484 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3485 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3486
3487 filter = &peer->filter[afi][safi];
3488
3489 /* apply peer-group filter */
3490 if (peer->af_group[afi][safi])
3491 {
3492 gfilter = &peer->group->conf->filter[afi][safi];
3493
3494 if (gfilter->plist[direct].name)
3495 {
3496 if (filter->plist[direct].name)
3497 free (filter->plist[direct].name);
3498 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3499 filter->plist[direct].plist = gfilter->plist[direct].plist;
3500 return 0;
3501 }
3502 }
3503
3504 if (filter->plist[direct].name)
3505 free (filter->plist[direct].name);
3506 filter->plist[direct].name = NULL;
3507 filter->plist[direct].plist = NULL;
3508
3509 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3510 return 0;
3511
3512 group = peer->group;
3513 LIST_LOOP (group->peer, peer, nn)
3514 {
3515 filter = &peer->filter[afi][safi];
3516
3517 if (! peer->af_group[afi][safi])
3518 continue;
3519
3520 if (filter->plist[direct].name)
3521 free (filter->plist[direct].name);
3522 filter->plist[direct].name = NULL;
3523 filter->plist[direct].plist = NULL;
3524 }
3525
3526 return 0;
3527}
3528
3529/* Update prefix-list list. */
3530void
3531peer_prefix_list_update (struct prefix_list *plist)
3532{
3533 struct listnode *nn, *nm;
3534 struct bgp *bgp;
3535 struct peer *peer;
3536 struct peer_group *group;
3537 struct bgp_filter *filter;
3538 afi_t afi;
3539 safi_t safi;
3540 int direct;
3541
3542 LIST_LOOP (bm->bgp, bgp, nn)
3543 {
3544 LIST_LOOP (bgp->peer, peer, nm)
3545 {
3546 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3547 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3548 {
3549 filter = &peer->filter[afi][safi];
3550
3551 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3552 {
3553 if (filter->plist[direct].name)
3554 filter->plist[direct].plist =
3555 prefix_list_lookup (afi, filter->plist[direct].name);
3556 else
3557 filter->plist[direct].plist = NULL;
3558 }
3559 }
3560 }
3561 LIST_LOOP (bgp->group, group, nm)
3562 {
3563 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3564 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3565 {
3566 filter = &group->conf->filter[afi][safi];
3567
3568 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3569 {
3570 if (filter->plist[direct].name)
3571 filter->plist[direct].plist =
3572 prefix_list_lookup (afi, filter->plist[direct].name);
3573 else
3574 filter->plist[direct].plist = NULL;
3575 }
3576 }
3577 }
3578 }
3579}
3580
3581int
3582peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003583 const char *name)
paul718e3742002-12-13 20:15:29 +00003584{
3585 struct bgp_filter *filter;
3586 struct peer_group *group;
3587 struct listnode *nn;
3588
3589 if (! peer->afc[afi][safi])
3590 return BGP_ERR_PEER_INACTIVE;
3591
3592 if (direct != FILTER_IN && direct != FILTER_OUT)
3593 return BGP_ERR_INVALID_VALUE;
3594
3595 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3596 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3597
3598 filter = &peer->filter[afi][safi];
3599
3600 if (filter->aslist[direct].name)
3601 free (filter->aslist[direct].name);
3602 filter->aslist[direct].name = strdup (name);
3603 filter->aslist[direct].aslist = as_list_lookup (name);
3604
3605 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3606 return 0;
3607
3608 group = peer->group;
3609 LIST_LOOP (group->peer, peer, nn)
3610 {
3611 filter = &peer->filter[afi][safi];
3612
3613 if (! peer->af_group[afi][safi])
3614 continue;
3615
3616 if (filter->aslist[direct].name)
3617 free (filter->aslist[direct].name);
3618 filter->aslist[direct].name = strdup (name);
3619 filter->aslist[direct].aslist = as_list_lookup (name);
3620 }
3621 return 0;
3622}
3623
3624int
3625peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3626{
3627 struct bgp_filter *filter;
3628 struct bgp_filter *gfilter;
3629 struct peer_group *group;
3630 struct listnode *nn;
3631
3632 if (! peer->afc[afi][safi])
3633 return BGP_ERR_PEER_INACTIVE;
3634
paulfee0f4c2004-09-13 05:12:46 +00003635 if (direct != RMAP_IN && direct != RMAP_OUT &&
3636 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003637 return BGP_ERR_INVALID_VALUE;
3638
paulfee0f4c2004-09-13 05:12:46 +00003639 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
3640 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003641 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3642
3643 filter = &peer->filter[afi][safi];
3644
3645 /* apply peer-group filter */
3646 if (peer->af_group[afi][safi])
3647 {
3648 gfilter = &peer->group->conf->filter[afi][safi];
3649
3650 if (gfilter->aslist[direct].name)
3651 {
3652 if (filter->aslist[direct].name)
3653 free (filter->aslist[direct].name);
3654 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
3655 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
3656 return 0;
3657 }
3658 }
3659
3660 if (filter->aslist[direct].name)
3661 free (filter->aslist[direct].name);
3662 filter->aslist[direct].name = NULL;
3663 filter->aslist[direct].aslist = NULL;
3664
3665 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3666 return 0;
3667
3668 group = peer->group;
3669 LIST_LOOP (group->peer, peer, nn)
3670 {
3671 filter = &peer->filter[afi][safi];
3672
3673 if (! peer->af_group[afi][safi])
3674 continue;
3675
3676 if (filter->aslist[direct].name)
3677 free (filter->aslist[direct].name);
3678 filter->aslist[direct].name = NULL;
3679 filter->aslist[direct].aslist = NULL;
3680 }
3681
3682 return 0;
3683}
3684
3685void
3686peer_aslist_update ()
3687{
3688 afi_t afi;
3689 safi_t safi;
3690 int direct;
3691 struct listnode *nn, *nm;
3692 struct bgp *bgp;
3693 struct peer *peer;
3694 struct peer_group *group;
3695 struct bgp_filter *filter;
3696
3697 LIST_LOOP (bm->bgp, bgp, nn)
3698 {
3699 LIST_LOOP (bgp->peer, peer, nm)
3700 {
3701 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3702 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3703 {
3704 filter = &peer->filter[afi][safi];
3705
3706 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3707 {
3708 if (filter->aslist[direct].name)
3709 filter->aslist[direct].aslist =
3710 as_list_lookup (filter->aslist[direct].name);
3711 else
3712 filter->aslist[direct].aslist = NULL;
3713 }
3714 }
3715 }
3716 LIST_LOOP (bgp->group, group, nm)
3717 {
3718 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3719 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3720 {
3721 filter = &group->conf->filter[afi][safi];
3722
3723 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3724 {
3725 if (filter->aslist[direct].name)
3726 filter->aslist[direct].aslist =
3727 as_list_lookup (filter->aslist[direct].name);
3728 else
3729 filter->aslist[direct].aslist = NULL;
3730 }
3731 }
3732 }
3733 }
3734}
3735
3736/* Set route-map to the peer. */
3737int
3738peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003739 const char *name)
paul718e3742002-12-13 20:15:29 +00003740{
3741 struct bgp_filter *filter;
3742 struct peer_group *group;
3743 struct listnode *nn;
3744
3745 if (! peer->afc[afi][safi])
3746 return BGP_ERR_PEER_INACTIVE;
3747
paulfee0f4c2004-09-13 05:12:46 +00003748 if (direct != RMAP_IN && direct != RMAP_OUT &&
3749 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003750 return BGP_ERR_INVALID_VALUE;
3751
paulfee0f4c2004-09-13 05:12:46 +00003752 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
3753 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003754 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3755
3756 filter = &peer->filter[afi][safi];
3757
3758 if (filter->map[direct].name)
3759 free (filter->map[direct].name);
3760
3761 filter->map[direct].name = strdup (name);
3762 filter->map[direct].map = route_map_lookup_by_name (name);
3763
3764 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3765 return 0;
3766
3767 group = peer->group;
3768 LIST_LOOP (group->peer, peer, nn)
3769 {
3770 filter = &peer->filter[afi][safi];
3771
3772 if (! peer->af_group[afi][safi])
3773 continue;
3774
3775 if (filter->map[direct].name)
3776 free (filter->map[direct].name);
3777 filter->map[direct].name = strdup (name);
3778 filter->map[direct].map = route_map_lookup_by_name (name);
3779 }
3780 return 0;
3781}
3782
3783/* Unset route-map from the peer. */
3784int
3785peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3786{
3787 struct bgp_filter *filter;
3788 struct bgp_filter *gfilter;
3789 struct peer_group *group;
3790 struct listnode *nn;
3791
3792 if (! peer->afc[afi][safi])
3793 return BGP_ERR_PEER_INACTIVE;
3794
3795 if (direct != FILTER_IN && direct != FILTER_OUT)
3796 return BGP_ERR_INVALID_VALUE;
3797
3798 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3799 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3800
3801 filter = &peer->filter[afi][safi];
3802
3803 /* apply peer-group filter */
3804 if (peer->af_group[afi][safi])
3805 {
3806 gfilter = &peer->group->conf->filter[afi][safi];
3807
3808 if (gfilter->map[direct].name)
3809 {
3810 if (filter->map[direct].name)
3811 free (filter->map[direct].name);
3812 filter->map[direct].name = strdup (gfilter->map[direct].name);
3813 filter->map[direct].map = gfilter->map[direct].map;
3814 return 0;
3815 }
3816 }
3817
3818 if (filter->map[direct].name)
3819 free (filter->map[direct].name);
3820 filter->map[direct].name = NULL;
3821 filter->map[direct].map = NULL;
3822
3823 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3824 return 0;
3825
3826 group = peer->group;
3827 LIST_LOOP (group->peer, peer, nn)
3828 {
3829 filter = &peer->filter[afi][safi];
3830
3831 if (! peer->af_group[afi][safi])
3832 continue;
3833
3834 if (filter->map[direct].name)
3835 free (filter->map[direct].name);
3836 filter->map[direct].name = NULL;
3837 filter->map[direct].map = NULL;
3838 }
3839 return 0;
3840}
3841
3842/* Set unsuppress-map to the peer. */
3843int
paulfd79ac92004-10-13 05:06:08 +00003844peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
3845 const char *name)
paul718e3742002-12-13 20:15:29 +00003846{
3847 struct bgp_filter *filter;
3848 struct peer_group *group;
3849 struct listnode *nn;
3850
3851 if (! peer->afc[afi][safi])
3852 return BGP_ERR_PEER_INACTIVE;
3853
3854 if (peer_is_group_member (peer, afi, safi))
3855 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3856
3857 filter = &peer->filter[afi][safi];
3858
3859 if (filter->usmap.name)
3860 free (filter->usmap.name);
3861
3862 filter->usmap.name = strdup (name);
3863 filter->usmap.map = route_map_lookup_by_name (name);
3864
3865 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3866 return 0;
3867
3868 group = peer->group;
3869 LIST_LOOP (group->peer, peer, nn)
3870 {
3871 filter = &peer->filter[afi][safi];
3872
3873 if (! peer->af_group[afi][safi])
3874 continue;
3875
3876 if (filter->usmap.name)
3877 free (filter->usmap.name);
3878 filter->usmap.name = strdup (name);
3879 filter->usmap.map = route_map_lookup_by_name (name);
3880 }
3881 return 0;
3882}
3883
3884/* Unset route-map from the peer. */
3885int
3886peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
3887{
3888 struct bgp_filter *filter;
3889 struct peer_group *group;
3890 struct listnode *nn;
3891
3892 if (! peer->afc[afi][safi])
3893 return BGP_ERR_PEER_INACTIVE;
3894
3895 if (peer_is_group_member (peer, afi, safi))
3896 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3897
3898 filter = &peer->filter[afi][safi];
3899
3900 if (filter->usmap.name)
3901 free (filter->usmap.name);
3902 filter->usmap.name = NULL;
3903 filter->usmap.map = NULL;
3904
3905 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3906 return 0;
3907
3908 group = peer->group;
3909 LIST_LOOP (group->peer, peer, nn)
3910 {
3911 filter = &peer->filter[afi][safi];
3912
3913 if (! peer->af_group[afi][safi])
3914 continue;
3915
3916 if (filter->usmap.name)
3917 free (filter->usmap.name);
3918 filter->usmap.name = NULL;
3919 filter->usmap.map = NULL;
3920 }
3921 return 0;
3922}
3923
3924int
3925peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hassoe0701b72004-05-20 09:19:34 +00003926 u_int32_t max, u_char threshold, int warning)
paul718e3742002-12-13 20:15:29 +00003927{
3928 struct peer_group *group;
3929 struct listnode *nn;
3930
3931 if (! peer->afc[afi][safi])
3932 return BGP_ERR_PEER_INACTIVE;
3933
3934 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3935 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00003936 peer->pmax_threshold[afi][safi] = threshold;
paul718e3742002-12-13 20:15:29 +00003937 if (warning)
3938 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3939 else
3940 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3941
3942 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3943 return 0;
3944
3945 group = peer->group;
3946 LIST_LOOP (group->peer, peer, nn)
3947 {
3948 if (! peer->af_group[afi][safi])
3949 continue;
3950
3951 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3952 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00003953 peer->pmax_threshold[afi][safi] = threshold;
paul718e3742002-12-13 20:15:29 +00003954 if (warning)
3955 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3956 else
3957 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3958 }
3959 return 0;
3960}
3961
3962int
3963peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
3964{
3965 struct peer_group *group;
3966 struct listnode *nn;
3967
3968 if (! peer->afc[afi][safi])
3969 return BGP_ERR_PEER_INACTIVE;
3970
3971 /* apply peer-group config */
3972 if (peer->af_group[afi][safi])
3973 {
3974 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
3975 PEER_FLAG_MAX_PREFIX))
3976 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3977 else
3978 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3979
3980 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
3981 PEER_FLAG_MAX_PREFIX_WARNING))
3982 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3983 else
3984 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3985
3986 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00003987 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
paul718e3742002-12-13 20:15:29 +00003988 return 0;
3989 }
3990
3991 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3992 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3993 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +00003994 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +00003995
3996 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3997 return 0;
3998
3999 group = peer->group;
4000 LIST_LOOP (group->peer, peer, nn)
4001 {
4002 if (! peer->af_group[afi][safi])
4003 continue;
4004
4005 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4006 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4007 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +00004008 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +00004009 }
4010 return 0;
4011}
4012
4013int
4014peer_clear (struct peer *peer)
4015{
4016 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4017 {
4018 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4019 peer->v_start = BGP_INIT_START_TIMER;
4020 if (peer->status == Established)
4021 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4022 BGP_NOTIFY_CEASE_ADMIN_RESET);
4023 else
4024 BGP_EVENT_ADD (peer, BGP_Stop);
4025 }
4026 return 0;
4027}
4028
4029int
4030peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4031 enum bgp_clear_type stype)
4032{
4033 if (peer->status != Established)
4034 return 0;
4035
4036 if (! peer->afc[afi][safi])
4037 return BGP_ERR_AF_UNCONFIGURED;
4038
paulfee0f4c2004-09-13 05:12:46 +00004039 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4040 {
4041 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4042 return 0;
4043 bgp_check_local_routes_rsclient (peer, afi, safi);
4044 bgp_soft_reconfig_rsclient (peer, afi, safi);
4045 }
4046
paul718e3742002-12-13 20:15:29 +00004047 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4048 bgp_announce_route (peer, afi, safi);
4049
4050 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4051 {
4052 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4053 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4054 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4055 {
4056 struct bgp_filter *filter = &peer->filter[afi][safi];
4057 u_char prefix_type;
4058
4059 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4060 prefix_type = ORF_TYPE_PREFIX;
4061 else
4062 prefix_type = ORF_TYPE_PREFIX_OLD;
4063
4064 if (filter->plist[FILTER_IN].plist)
4065 {
4066 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4067 bgp_route_refresh_send (peer, afi, safi,
4068 prefix_type, REFRESH_DEFER, 1);
4069 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4070 REFRESH_IMMEDIATE, 0);
4071 }
4072 else
4073 {
4074 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4075 bgp_route_refresh_send (peer, afi, safi,
4076 prefix_type, REFRESH_IMMEDIATE, 1);
4077 else
4078 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4079 }
4080 return 0;
4081 }
4082 }
4083
4084 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4085 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4086 {
4087 /* If neighbor has soft reconfiguration inbound flag.
4088 Use Adj-RIB-In database. */
4089 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4090 bgp_soft_reconfig_in (peer, afi, safi);
4091 else
4092 {
4093 /* If neighbor has route refresh capability, send route refresh
4094 message to the peer. */
4095 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4096 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4097 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4098 else
4099 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4100 }
4101 }
4102 return 0;
4103}
4104
paulfd79ac92004-10-13 05:06:08 +00004105/* Display peer uptime.*/
4106/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004107char *
4108peer_uptime (time_t uptime2, char *buf, size_t len)
4109{
4110 time_t uptime1;
4111 struct tm *tm;
4112
4113 /* Check buffer length. */
4114 if (len < BGP_UPTIME_LEN)
4115 {
gdtc29fdba2004-12-09 14:46:46 +00004116 /* XXX: warning: long int format, size_t arg (arg 2) */
paula2b1ecd2004-10-31 18:58:09 +00004117 zlog_warn ("peer_uptime (): buffer shortage %ld", len);
paulfd79ac92004-10-13 05:06:08 +00004118 /* XXX: should return status instead of buf... */
4119 snprintf (buf, len, "<error> ");
4120 return buf;
paul718e3742002-12-13 20:15:29 +00004121 }
4122
4123 /* If there is no connection has been done before print `never'. */
4124 if (uptime2 == 0)
4125 {
4126 snprintf (buf, len, "never ");
4127 return buf;
4128 }
4129
4130 /* Get current time. */
4131 uptime1 = time (NULL);
4132 uptime1 -= uptime2;
4133 tm = gmtime (&uptime1);
4134
4135 /* Making formatted timer strings. */
4136#define ONE_DAY_SECOND 60*60*24
4137#define ONE_WEEK_SECOND 60*60*24*7
4138
4139 if (uptime1 < ONE_DAY_SECOND)
4140 snprintf (buf, len, "%02d:%02d:%02d",
4141 tm->tm_hour, tm->tm_min, tm->tm_sec);
4142 else if (uptime1 < ONE_WEEK_SECOND)
4143 snprintf (buf, len, "%dd%02dh%02dm",
4144 tm->tm_yday, tm->tm_hour, tm->tm_min);
4145 else
4146 snprintf (buf, len, "%02dw%dd%02dh",
4147 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4148 return buf;
4149}
4150
4151void
4152bgp_config_write_filter (struct vty *vty, struct peer *peer,
4153 afi_t afi, safi_t safi)
4154{
4155 struct bgp_filter *filter;
4156 struct bgp_filter *gfilter = NULL;
4157 char *addr;
4158 int in = FILTER_IN;
4159 int out = FILTER_OUT;
4160
4161 addr = peer->host;
4162 filter = &peer->filter[afi][safi];
4163 if (peer->af_group[afi][safi])
4164 gfilter = &peer->group->conf->filter[afi][safi];
4165
4166 /* distribute-list. */
4167 if (filter->dlist[in].name)
4168 if (! gfilter || ! gfilter->dlist[in].name
4169 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4170 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4171 filter->dlist[in].name, VTY_NEWLINE);
4172 if (filter->dlist[out].name && ! gfilter)
4173 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4174 filter->dlist[out].name, VTY_NEWLINE);
4175
4176 /* prefix-list. */
4177 if (filter->plist[in].name)
4178 if (! gfilter || ! gfilter->plist[in].name
4179 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4180 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4181 filter->plist[in].name, VTY_NEWLINE);
4182 if (filter->plist[out].name && ! gfilter)
4183 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4184 filter->plist[out].name, VTY_NEWLINE);
4185
4186 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004187 if (filter->map[RMAP_IN].name)
4188 if (! gfilter || ! gfilter->map[RMAP_IN].name
4189 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004190 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004191 filter->map[RMAP_IN].name, VTY_NEWLINE);
4192 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004193 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004194 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4195 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4196 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4197 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4198 if (filter->map[RMAP_EXPORT].name)
4199 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4200 || strcmp (filter->map[RMAP_EXPORT].name,
4201 gfilter->map[RMAP_EXPORT].name) != 0)
4202 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4203 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004204
4205 /* unsuppress-map */
4206 if (filter->usmap.name && ! gfilter)
4207 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4208 filter->usmap.name, VTY_NEWLINE);
4209
4210 /* filter-list. */
4211 if (filter->aslist[in].name)
4212 if (! gfilter || ! gfilter->aslist[in].name
4213 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4214 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4215 filter->aslist[in].name, VTY_NEWLINE);
4216 if (filter->aslist[out].name && ! gfilter)
4217 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4218 filter->aslist[out].name, VTY_NEWLINE);
4219}
4220
4221/* BGP peer configuration display function. */
4222void
4223bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4224 struct peer *peer, afi_t afi, safi_t safi)
4225{
4226 struct bgp_filter *filter;
4227 struct peer *g_peer = NULL;
4228 char buf[SU_ADDRSTRLEN];
4229 char *addr;
4230
4231 filter = &peer->filter[afi][safi];
4232 addr = peer->host;
4233 if (peer_group_active (peer))
4234 g_peer = peer->group->conf;
4235
4236 /************************************
4237 ****** Global to the neighbor ******
4238 ************************************/
4239 if (afi == AFI_IP && safi == SAFI_UNICAST)
4240 {
4241 /* remote-as. */
4242 if (! peer_group_active (peer))
4243 {
4244 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4245 vty_out (vty, " neighbor %s peer-group%s", addr,
4246 VTY_NEWLINE);
4247 if (peer->as)
4248 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4249 VTY_NEWLINE);
4250 }
4251 else
4252 {
4253 if (! g_peer->as)
4254 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4255 VTY_NEWLINE);
4256 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4257 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4258 peer->group->name, VTY_NEWLINE);
4259 }
4260
4261 /* local-as. */
4262 if (peer->change_local_as)
4263 if (! peer_group_active (peer))
4264 vty_out (vty, " neighbor %s local-as %d%s%s", addr,
4265 peer->change_local_as,
4266 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4267 " no-prepend" : "", VTY_NEWLINE);
4268
4269 /* Description. */
4270 if (peer->desc)
4271 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4272 VTY_NEWLINE);
4273
4274 /* Shutdown. */
4275 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4276 if (! peer_group_active (peer) ||
4277 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4278 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4279
4280 /* BGP port. */
4281 if (peer->port != BGP_PORT_DEFAULT)
4282 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
4283 VTY_NEWLINE);
4284
4285 /* Local interface name. */
4286 if (peer->ifname)
4287 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4288 VTY_NEWLINE);
4289
4290 /* Passive. */
4291 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4292 if (! peer_group_active (peer) ||
4293 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4294 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4295
4296 /* EBGP multihop. */
4297 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
4298 if (! peer_group_active (peer) ||
4299 g_peer->ttl != peer->ttl)
4300 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4301 VTY_NEWLINE);
4302
4303 /* Enforce multihop. */
4304 if (CHECK_FLAG (peer->flags, PEER_FLAG_ENFORCE_MULTIHOP))
4305 if (! peer_group_active (peer) ||
4306 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_ENFORCE_MULTIHOP))
4307 vty_out (vty, " neighbor %s enforce-multihop%s", addr, VTY_NEWLINE);
4308
4309 /* Update-source. */
4310 if (peer->update_if)
4311 if (! peer_group_active (peer) || ! g_peer->update_if
4312 || strcmp (g_peer->update_if, peer->update_if) != 0)
4313 vty_out (vty, " neighbor %s update-source %s%s", addr,
4314 peer->update_if, VTY_NEWLINE);
4315 if (peer->update_source)
4316 if (! peer_group_active (peer) || ! g_peer->update_source
4317 || sockunion_cmp (g_peer->update_source,
4318 peer->update_source) != 0)
4319 vty_out (vty, " neighbor %s update-source %s%s", addr,
4320 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4321 VTY_NEWLINE);
4322
4323 /* BGP version print. */
4324 if (peer->version == BGP_VERSION_MP_4_DRAFT_00)
4325 vty_out (vty, " neighbor %s version %s%s",
4326 addr,"4-", VTY_NEWLINE);
4327
4328 /* advertisement-interval */
4329 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4330 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4331 addr, peer->v_routeadv, VTY_NEWLINE);
4332
4333 /* timers. */
4334 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4335 && ! peer_group_active (peer))
4336 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4337 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4338
4339 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4340 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4341 peer->connect, VTY_NEWLINE);
4342
4343 /* Default weight. */
4344 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4345 if (! peer_group_active (peer) ||
4346 g_peer->weight != peer->weight)
4347 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4348 VTY_NEWLINE);
4349
4350 /* Route refresh. */
4351 if (CHECK_FLAG (peer->flags, PEER_FLAG_NO_ROUTE_REFRESH_CAP))
4352 if (! peer_group_active (peer) ||
4353 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_NO_ROUTE_REFRESH_CAP))
4354 vty_out (vty, " no neighbor %s capability route-refresh%s", addr,
4355 VTY_NEWLINE);
4356
4357 /* Dynamic capability. */
4358 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4359 if (! peer_group_active (peer) ||
4360 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4361 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4362 VTY_NEWLINE);
4363
4364 /* dont capability negotiation. */
4365 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4366 if (! peer_group_active (peer) ||
4367 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4368 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4369 VTY_NEWLINE);
4370
4371 /* override capability negotiation. */
4372 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4373 if (! peer_group_active (peer) ||
4374 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4375 vty_out (vty, " neighbor %s override-capability%s", addr,
4376 VTY_NEWLINE);
4377
4378 /* strict capability negotiation. */
4379 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4380 if (! peer_group_active (peer) ||
4381 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4382 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4383 VTY_NEWLINE);
4384
4385 if (! peer_group_active (peer))
4386 {
4387 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4388 {
4389 if (peer->afc[AFI_IP][SAFI_UNICAST])
4390 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4391 }
4392 else
4393 {
4394 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4395 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4396 }
4397 }
4398 }
4399
4400
4401 /************************************
4402 ****** Per AF to the neighbor ******
4403 ************************************/
4404
4405 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4406 {
4407 if (peer->af_group[afi][safi])
4408 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4409 peer->group->name, VTY_NEWLINE);
4410 else
4411 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4412 }
4413
4414 /* ORF capability. */
4415 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4416 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4417 if (! peer->af_group[afi][safi])
4418 {
4419 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4420
4421 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4422 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4423 vty_out (vty, " both");
4424 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4425 vty_out (vty, " send");
4426 else
4427 vty_out (vty, " receive");
4428 vty_out (vty, "%s", VTY_NEWLINE);
4429 }
4430
4431 /* Route reflector client. */
4432 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4433 && ! peer->af_group[afi][safi])
4434 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4435 VTY_NEWLINE);
4436
4437 /* Nexthop self. */
4438 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4439 && ! peer->af_group[afi][safi])
4440 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4441
4442 /* Remove private AS. */
4443 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4444 && ! peer->af_group[afi][safi])
4445 vty_out (vty, " neighbor %s remove-private-AS%s",
4446 addr, VTY_NEWLINE);
4447
4448 /* send-community print. */
4449 if (! peer->af_group[afi][safi])
4450 {
4451 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4452 {
4453 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4454 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4455 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4456 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4457 vty_out (vty, " neighbor %s send-community extended%s",
4458 addr, VTY_NEWLINE);
4459 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4460 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4461 }
4462 else
4463 {
4464 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4465 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4466 vty_out (vty, " no neighbor %s send-community both%s",
4467 addr, VTY_NEWLINE);
4468 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4469 vty_out (vty, " no neighbor %s send-community extended%s",
4470 addr, VTY_NEWLINE);
4471 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4472 vty_out (vty, " no neighbor %s send-community%s",
4473 addr, VTY_NEWLINE);
4474 }
4475 }
4476
4477 /* Default information */
4478 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4479 && ! peer->af_group[afi][safi])
4480 {
4481 vty_out (vty, " neighbor %s default-originate", addr);
4482 if (peer->default_rmap[afi][safi].name)
4483 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4484 vty_out (vty, "%s", VTY_NEWLINE);
4485 }
4486
4487 /* Soft reconfiguration inbound. */
4488 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4489 if (! peer->af_group[afi][safi] ||
4490 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4491 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4492 VTY_NEWLINE);
4493
4494 /* maximum-prefix. */
4495 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4496 if (! peer->af_group[afi][safi]
4497 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004498 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004499 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4500 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00004501 {
4502 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
4503 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
4504 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
4505 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
4506 vty_out (vty, " warning-only");
4507 vty_out (vty, "%s", VTY_NEWLINE);
4508 }
paul718e3742002-12-13 20:15:29 +00004509
4510 /* Route server client. */
4511 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
4512 && ! peer->af_group[afi][safi])
4513 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
4514
4515 /* Allow AS in. */
4516 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
4517 if (! peer_group_active (peer)
4518 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
4519 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
4520 {
4521 if (peer->allowas_in[afi][safi] == 3)
4522 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
4523 else
4524 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
4525 peer->allowas_in[afi][safi], VTY_NEWLINE);
4526 }
4527
4528 /* Filter. */
4529 bgp_config_write_filter (vty, peer, afi, safi);
4530
4531 /* atribute-unchanged. */
4532 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4533 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4534 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4535 && ! peer->af_group[afi][safi])
4536 {
4537 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4538 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4539 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4540 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
4541 else
4542 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
4543 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
4544 " as-path" : "",
4545 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
4546 " next-hop" : "",
4547 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
4548 " med" : "", VTY_NEWLINE);
4549 }
4550}
4551
4552/* Display "address-family" configuration header. */
4553void
4554bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
4555 int *write)
4556{
4557 if (*write)
4558 return;
4559
4560 if (afi == AFI_IP && safi == SAFI_UNICAST)
4561 return;
4562
4563 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
4564
4565 if (afi == AFI_IP)
4566 {
4567 if (safi == SAFI_MULTICAST)
4568 vty_out (vty, "ipv4 multicast");
4569 else if (safi == SAFI_MPLS_VPN)
4570 vty_out (vty, "vpnv4 unicast");
4571 }
4572 else if (afi == AFI_IP6)
4573 vty_out (vty, "ipv6");
4574
4575 vty_out (vty, "%s", VTY_NEWLINE);
4576
4577 *write = 1;
4578}
4579
4580/* Address family based peer configuration display. */
4581int
4582bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
4583 safi_t safi)
4584{
4585 int write = 0;
4586 struct peer *peer;
4587 struct peer_group *group;
4588 struct listnode *nn;
4589
4590 bgp_config_write_network (vty, bgp, afi, safi, &write);
4591
4592 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
4593
4594 LIST_LOOP (bgp->group, group, nn)
4595 {
4596 if (group->conf->afc[afi][safi])
4597 {
4598 bgp_config_write_family_header (vty, afi, safi, &write);
4599 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
4600 }
4601 }
4602 LIST_LOOP (bgp->peer, peer, nn)
4603 {
4604 if (peer->afc[afi][safi])
4605 {
4606 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4607 {
4608 bgp_config_write_family_header (vty, afi, safi, &write);
4609 bgp_config_write_peer (vty, bgp, peer, afi, safi);
4610 }
4611 }
4612 }
4613 if (write)
4614 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
4615
4616 return write;
4617}
4618
4619int
4620bgp_config_write (struct vty *vty)
4621{
4622 int write = 0;
4623 struct bgp *bgp;
4624 struct peer_group *group;
4625 struct peer *peer;
4626 struct listnode *nn, *nm, *no;
4627
4628 /* BGP Multiple instance. */
4629 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4630 {
4631 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
4632 write++;
4633 }
4634
4635 /* BGP Config type. */
4636 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4637 {
4638 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
4639 write++;
4640 }
4641
4642 /* BGP configuration. */
4643 LIST_LOOP (bm->bgp, bgp, nn)
4644 {
4645 if (write)
4646 vty_out (vty, "!%s", VTY_NEWLINE);
4647
4648 /* Router bgp ASN */
4649 vty_out (vty, "router bgp %d", bgp->as);
4650
4651 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4652 {
4653 if (bgp->name)
4654 vty_out (vty, " view %s", bgp->name);
4655 }
4656 vty_out (vty, "%s", VTY_NEWLINE);
4657
4658 /* No Synchronization */
4659 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4660 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
4661
4662 /* BGP fast-external-failover. */
4663 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
4664 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
4665
4666 /* BGP router ID. */
4667 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
4668 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
4669 VTY_NEWLINE);
4670
paul848973c2003-08-13 00:32:49 +00004671 /* BGP log-neighbor-changes. */
4672 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
4673 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
4674
paul718e3742002-12-13 20:15:29 +00004675 /* BGP configuration. */
4676 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
4677 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
4678
4679 /* BGP default ipv4-unicast. */
4680 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4681 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
4682
4683 /* BGP default local-preference. */
4684 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
4685 vty_out (vty, " bgp default local-preference %d%s",
4686 bgp->default_local_pref, VTY_NEWLINE);
4687
4688 /* BGP client-to-client reflection. */
4689 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
4690 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
4691
4692 /* BGP cluster ID. */
4693 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
4694 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
4695 VTY_NEWLINE);
4696
hassoe0701b72004-05-20 09:19:34 +00004697 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00004698 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00004699 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
4700 VTY_NEWLINE);
4701
4702 /* Confederation peer */
4703 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00004704 {
hassoe0701b72004-05-20 09:19:34 +00004705 int i;
paul718e3742002-12-13 20:15:29 +00004706
hassoe0701b72004-05-20 09:19:34 +00004707 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00004708
hassoe0701b72004-05-20 09:19:34 +00004709 for (i = 0; i < bgp->confed_peers_cnt; i++)
4710 vty_out(vty, " %d", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00004711
hassoe0701b72004-05-20 09:19:34 +00004712 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004713 }
4714
4715 /* BGP enforce-first-as. */
4716 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
4717 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
4718
4719 /* BGP deterministic-med. */
4720 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
4721 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00004722
4723 /* BGP graceful-restart. */
4724 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
4725 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
4726
paul718e3742002-12-13 20:15:29 +00004727 /* BGP bestpath method. */
4728 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
4729 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
4730 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
4731 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
4732 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
4733 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4734 {
4735 vty_out (vty, " bgp bestpath med");
4736 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
4737 vty_out (vty, " confed");
4738 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4739 vty_out (vty, " missing-as-worst");
4740 vty_out (vty, "%s", VTY_NEWLINE);
4741 }
4742
4743 /* BGP network import check. */
4744 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
4745 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
4746
4747 /* BGP scan interval. */
4748 bgp_config_write_scan_time (vty);
4749
4750 /* BGP flag dampening. */
4751 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
4752 BGP_CONFIG_DAMPENING))
4753 bgp_config_write_damp (vty);
4754
4755 /* BGP static route configuration. */
4756 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4757
4758 /* BGP redistribute configuration. */
4759 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4760
4761 /* BGP timers configuration. */
4762 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
4763 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
4764 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
4765 bgp->default_holdtime, VTY_NEWLINE);
4766
4767 /* peer-group */
4768 LIST_LOOP (bgp->group, group, nm)
4769 {
4770 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
4771 }
4772
4773 /* Normal neighbor configuration. */
4774 LIST_LOOP (bgp->peer, peer, no)
4775 {
4776 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4777 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
4778 }
4779
4780 /* Distance configuration. */
4781 bgp_config_write_distance (vty, bgp);
4782
4783 /* No auto-summary */
4784 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4785 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
4786
4787 /* IPv4 multicast configuration. */
4788 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
4789
4790 /* IPv4 VPN configuration. */
4791 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
4792
4793 /* IPv6 unicast configuration. */
4794 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
4795
4796 write++;
4797 }
4798 return write;
4799}
4800
4801void
4802bgp_master_init ()
4803{
4804 memset (&bgp_master, 0, sizeof (struct bgp_master));
4805
4806 bm = &bgp_master;
4807 bm->bgp = list_new ();
4808 bm->port = BGP_PORT_DEFAULT;
4809 bm->master = thread_master_create ();
4810 bm->start_time = time (NULL);
4811}
4812
4813void
4814bgp_init ()
4815{
4816 void bgp_zebra_init ();
4817 void bgp_route_map_init ();
4818 void bgp_filter_init ();
4819
4820 /* BGP VTY commands installation. */
4821 bgp_vty_init ();
4822
4823 /* Create BGP server socket. */
4824 bgp_socket (NULL, bm->port);
4825
4826 /* Init zebra. */
4827 bgp_zebra_init ();
4828
4829 /* BGP inits. */
4830 bgp_attr_init ();
4831 bgp_debug_init ();
4832 bgp_dump_init ();
4833 bgp_route_init ();
4834 bgp_route_map_init ();
4835 bgp_scan_init ();
4836 bgp_mplsvpn_init ();
4837
4838 /* Access list initialize. */
4839 access_list_init ();
4840 access_list_add_hook (peer_distribute_update);
4841 access_list_delete_hook (peer_distribute_update);
4842
4843 /* Filter list initialize. */
4844 bgp_filter_init ();
4845 as_list_add_hook (peer_aslist_update);
4846 as_list_delete_hook (peer_aslist_update);
4847
4848 /* Prefix list initialize.*/
4849 prefix_list_init ();
4850 prefix_list_add_hook (peer_prefix_list_update);
4851 prefix_list_delete_hook (peer_prefix_list_update);
4852
4853 /* Community list initialize. */
4854 bgp_clist = community_list_init ();
4855
4856#ifdef HAVE_SNMP
4857 bgp_snmp_init ();
4858#endif /* HAVE_SNMP */
4859}
paul545acaf2004-04-20 15:13:15 +00004860
4861void
4862bgp_terminate ()
4863{
paul545acaf2004-04-20 15:13:15 +00004864 struct bgp *bgp;
4865 struct peer *peer;
4866 struct listnode *nn;
4867 struct listnode *mm;
4868
paul545acaf2004-04-20 15:13:15 +00004869 LIST_LOOP (bm->bgp, bgp, nn)
4870 LIST_LOOP (bgp->peer, peer, mm)
4871 if (peer->status == Established)
4872 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4873 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
4874
4875 bgp_cleanup_routes ();
4876}
4877