blob: 097b235c2fa6aa41e266cf5035af9fa315923a77 [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);
hasso0a486e52005-02-01 20:57:17 +00001078 BGP_TIMER_OFF (peer->t_pmax_restart);
paul718e3742002-12-13 20:15:29 +00001079
1080 /* Delete from all peer list. */
1081 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
paulfee0f4c2004-09-13 05:12:46 +00001082 {
paul718e3742002-12-13 20:15:29 +00001083 listnode_delete (bgp->peer, peer);
paulfee0f4c2004-09-13 05:12:46 +00001084 if (peer_rsclient_active (peer))
1085 listnode_delete (bgp->rsclient, peer);
1086 }
1087
1088 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1089 member of a peer_group. */
1090 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1091 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1092 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
1093 bgp_table_finish (peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001094
1095 /* Buffer. */
1096 if (peer->ibuf)
1097 stream_free (peer->ibuf);
1098
1099 if (peer->obuf)
1100 stream_fifo_free (peer->obuf);
1101
1102 if (peer->work)
1103 stream_free (peer->work);
1104
1105 /* Free allocated host character. */
1106 if (peer->host)
1107 free (peer->host);
1108
1109 /* Local and remote addresses. */
1110 if (peer->su_local)
1111 XFREE (MTYPE_TMP, peer->su_local);
1112 if (peer->su_remote)
1113 XFREE (MTYPE_TMP, peer->su_remote);
1114
1115 /* Peer description string. */
1116 if (peer->desc)
1117 XFREE (MTYPE_TMP, peer->desc);
1118
1119 bgp_sync_delete (peer);
1120
1121 /* Free filter related memory. */
1122 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1123 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1124 {
1125 filter = &peer->filter[afi][safi];
1126
1127 for (i = FILTER_IN; i < FILTER_MAX; i++)
1128 {
1129 if (filter->dlist[i].name)
1130 free (filter->dlist[i].name);
1131 if (filter->plist[i].name)
1132 free (filter->plist[i].name);
1133 if (filter->aslist[i].name)
1134 free (filter->aslist[i].name);
paulfee0f4c2004-09-13 05:12:46 +00001135 }
1136 for (i = RMAP_IN; i < RMAP_MAX; i++)
1137 {
paul718e3742002-12-13 20:15:29 +00001138 if (filter->map[i].name)
1139 free (filter->map[i].name);
1140 }
1141
1142 if (filter->usmap.name)
1143 free (filter->usmap.name);
1144
1145 if (peer->default_rmap[afi][safi].name)
1146 free (peer->default_rmap[afi][safi].name);
1147 }
1148
1149 /* Update source configuration. */
1150 if (peer->update_source)
1151 {
1152 sockunion_free (peer->update_source);
1153 peer->update_source = NULL;
1154 }
1155 if (peer->update_if)
1156 {
1157 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1158 peer->update_if = NULL;
1159 }
1160
1161 /* Free peer structure. */
1162 XFREE (MTYPE_BGP_PEER, peer);
1163
1164 return 0;
1165}
1166
1167int
1168peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1169{
1170 return strcmp (g1->name, g2->name);
1171}
1172
1173/* If peer is configured at least one address family return 1. */
1174int
1175peer_group_active (struct peer *peer)
1176{
1177 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1178 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1179 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1180 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1181 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1182 return 1;
1183 return 0;
1184}
1185
1186/* Peer group cofiguration. */
1187static struct peer_group *
1188peer_group_new ()
1189{
1190 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1191 sizeof (struct peer_group));
1192}
1193
1194void
1195peer_group_free (struct peer_group *group)
1196{
1197 XFREE (MTYPE_PEER_GROUP, group);
1198}
1199
1200struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001201peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001202{
1203 struct peer_group *group;
1204 struct listnode *nn;
1205
1206 LIST_LOOP (bgp->group, group, nn)
1207 {
1208 if (strcmp (group->name, name) == 0)
1209 return group;
1210 }
1211 return NULL;
1212}
1213
1214struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001215peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001216{
1217 struct peer_group *group;
1218
1219 group = peer_group_lookup (bgp, name);
1220 if (group)
1221 return group;
1222
1223 group = peer_group_new ();
1224 group->bgp = bgp;
1225 group->name = strdup (name);
1226 group->peer = list_new ();
1227 group->conf = peer_new ();
1228 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1229 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
1230 group->conf->host = strdup (name);
1231 group->conf->bgp = bgp;
1232 group->conf->group = group;
1233 group->conf->as = 0;
1234 group->conf->ttl = 1;
1235 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1236 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1237 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1238 group->conf->keepalive = 0;
1239 group->conf->holdtime = 0;
1240 group->conf->connect = 0;
1241 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1242 listnode_add_sort (bgp->group, group);
1243
1244 return 0;
1245}
1246
1247void
1248peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1249 afi_t afi, safi_t safi)
1250{
1251 int in = FILTER_IN;
1252 int out = FILTER_OUT;
1253 struct peer *conf;
1254 struct bgp_filter *pfilter;
1255 struct bgp_filter *gfilter;
1256
1257 conf = group->conf;
1258 pfilter = &peer->filter[afi][safi];
1259 gfilter = &conf->filter[afi][safi];
1260
1261 /* remote-as */
1262 if (conf->as)
1263 peer->as = conf->as;
1264
1265 /* remote-as */
1266 if (conf->change_local_as)
1267 peer->change_local_as = conf->change_local_as;
1268
1269 /* TTL */
1270 peer->ttl = conf->ttl;
1271
1272 /* Weight */
1273 peer->weight = conf->weight;
1274
1275 /* peer flags apply */
1276 peer->flags = conf->flags;
1277 /* peer af_flags apply */
1278 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1279 /* peer config apply */
1280 peer->config = conf->config;
1281
1282 /* peer timers apply */
1283 peer->holdtime = conf->holdtime;
1284 peer->keepalive = conf->keepalive;
1285 peer->connect = conf->connect;
1286 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1287 peer->v_connect = conf->connect;
1288 else
1289 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1290
1291 /* advertisement-interval reset */
1292 if (peer_sort (peer) == BGP_PEER_IBGP)
1293 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1294 else
1295 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1296
1297 /* maximum-prefix */
1298 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001299 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001300 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001301
1302 /* allowas-in */
1303 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1304
paulfee0f4c2004-09-13 05:12:46 +00001305 /* route-server-client */
1306 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1307 {
1308 /* Make peer's RIB point to group's RIB. */
1309 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1310
1311 /* Import policy. */
1312 if (pfilter->map[RMAP_IMPORT].name)
1313 free (pfilter->map[RMAP_IMPORT].name);
1314 if (gfilter->map[RMAP_IMPORT].name)
1315 {
1316 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1317 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1318 }
1319 else
1320 {
1321 pfilter->map[RMAP_IMPORT].name = NULL;
1322 pfilter->map[RMAP_IMPORT].map = NULL;
1323 }
1324
1325 /* Export policy. */
1326 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1327 {
1328 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1329 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1330 }
1331 }
1332
paul718e3742002-12-13 20:15:29 +00001333 /* default-originate route-map */
1334 if (conf->default_rmap[afi][safi].name)
1335 {
1336 if (peer->default_rmap[afi][safi].name)
1337 free (peer->default_rmap[afi][safi].name);
1338 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1339 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1340 }
1341
1342 /* update-source apply */
1343 if (conf->update_source)
1344 {
1345 if (peer->update_source)
1346 sockunion_free (peer->update_source);
1347 if (peer->update_if)
1348 {
1349 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1350 peer->update_if = NULL;
1351 }
1352 peer->update_source = sockunion_dup (conf->update_source);
1353 }
1354 else if (conf->update_if)
1355 {
1356 if (peer->update_if)
1357 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1358 if (peer->update_source)
1359 {
1360 sockunion_free (peer->update_source);
1361 peer->update_source = NULL;
1362 }
1363 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1364 }
1365
1366 /* inbound filter apply */
1367 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1368 {
1369 if (pfilter->dlist[in].name)
1370 free (pfilter->dlist[in].name);
1371 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1372 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1373 }
1374 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1375 {
1376 if (pfilter->plist[in].name)
1377 free (pfilter->plist[in].name);
1378 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1379 pfilter->plist[in].plist = gfilter->plist[in].plist;
1380 }
1381 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1382 {
1383 if (pfilter->aslist[in].name)
1384 free (pfilter->aslist[in].name);
1385 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1386 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1387 }
paulfee0f4c2004-09-13 05:12:46 +00001388 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001389 {
paulfee0f4c2004-09-13 05:12:46 +00001390 if (pfilter->map[RMAP_IN].name)
1391 free (pfilter->map[RMAP_IN].name);
1392 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1393 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001394 }
1395
1396 /* outbound filter apply */
1397 if (gfilter->dlist[out].name)
1398 {
1399 if (pfilter->dlist[out].name)
1400 free (pfilter->dlist[out].name);
1401 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1402 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1403 }
1404 else
1405 {
1406 if (pfilter->dlist[out].name)
1407 free (pfilter->dlist[out].name);
1408 pfilter->dlist[out].name = NULL;
1409 pfilter->dlist[out].alist = NULL;
1410 }
1411 if (gfilter->plist[out].name)
1412 {
1413 if (pfilter->plist[out].name)
1414 free (pfilter->plist[out].name);
1415 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1416 pfilter->plist[out].plist = gfilter->plist[out].plist;
1417 }
1418 else
1419 {
1420 if (pfilter->plist[out].name)
1421 free (pfilter->plist[out].name);
1422 pfilter->plist[out].name = NULL;
1423 pfilter->plist[out].plist = NULL;
1424 }
1425 if (gfilter->aslist[out].name)
1426 {
1427 if (pfilter->aslist[out].name)
1428 free (pfilter->aslist[out].name);
1429 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1430 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1431 }
1432 else
1433 {
1434 if (pfilter->aslist[out].name)
1435 free (pfilter->aslist[out].name);
1436 pfilter->aslist[out].name = NULL;
1437 pfilter->aslist[out].aslist = NULL;
1438 }
paulfee0f4c2004-09-13 05:12:46 +00001439 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001440 {
paulfee0f4c2004-09-13 05:12:46 +00001441 if (pfilter->map[RMAP_OUT].name)
1442 free (pfilter->map[RMAP_OUT].name);
1443 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1444 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001445 }
1446 else
1447 {
paulfee0f4c2004-09-13 05:12:46 +00001448 if (pfilter->map[RMAP_OUT].name)
1449 free (pfilter->map[RMAP_OUT].name);
1450 pfilter->map[RMAP_OUT].name = NULL;
1451 pfilter->map[RMAP_OUT].map = NULL;
1452 }
1453
1454 /* RS-client's import/export route-maps. */
1455 if (gfilter->map[RMAP_IMPORT].name)
1456 {
1457 if (pfilter->map[RMAP_IMPORT].name)
1458 free (pfilter->map[RMAP_IMPORT].name);
1459 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1460 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1461 }
1462 else
1463 {
1464 if (pfilter->map[RMAP_IMPORT].name)
1465 free (pfilter->map[RMAP_IMPORT].name);
1466 pfilter->map[RMAP_IMPORT].name = NULL;
1467 pfilter->map[RMAP_IMPORT].map = NULL;
1468 }
1469 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1470 {
1471 if (pfilter->map[RMAP_EXPORT].name)
1472 free (pfilter->map[RMAP_EXPORT].name);
1473 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1474 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001475 }
1476
1477 if (gfilter->usmap.name)
1478 {
1479 if (pfilter->usmap.name)
1480 free (pfilter->usmap.name);
1481 pfilter->usmap.name = strdup (gfilter->usmap.name);
1482 pfilter->usmap.map = gfilter->usmap.map;
1483 }
1484 else
1485 {
1486 if (pfilter->usmap.name)
1487 free (pfilter->usmap.name);
1488 pfilter->usmap.name = NULL;
1489 pfilter->usmap.map = NULL;
1490 }
1491}
1492
1493/* Peer group's remote AS configuration. */
1494int
paulfd79ac92004-10-13 05:06:08 +00001495peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001496{
1497 struct peer_group *group;
1498 struct peer *peer;
1499 struct listnode *nn;
1500
1501 group = peer_group_lookup (bgp, group_name);
1502 if (! group)
1503 return -1;
1504
1505 if (group->conf->as == *as)
1506 return 0;
1507
1508 /* When we setup peer-group AS number all peer group member's AS
1509 number must be updated to same number. */
1510 peer_as_change (group->conf, *as);
1511
1512 LIST_LOOP (group->peer, peer, nn)
1513 {
1514 if (peer->as != *as)
1515 peer_as_change (peer, *as);
1516 }
1517
1518 return 0;
1519}
1520
1521int
1522peer_group_delete (struct peer_group *group)
1523{
1524 struct bgp *bgp;
1525 struct peer *peer;
1526 struct listnode *nn;
1527
1528 bgp = group->bgp;
1529
1530 LIST_LOOP (group->peer, peer, nn)
1531 {
1532 peer->group = NULL;
1533 peer_delete (peer);
1534 }
1535 list_delete (group->peer);
1536
1537 free (group->name);
1538 group->name = NULL;
1539
1540 group->conf->group = NULL;
1541 peer_delete (group->conf);
1542
1543 /* Delete from all peer_group list. */
1544 listnode_delete (bgp->group, group);
1545
1546 peer_group_free (group);
1547
1548 return 0;
1549}
1550
1551int
1552peer_group_remote_as_delete (struct peer_group *group)
1553{
1554 struct peer *peer;
1555 struct listnode *nn;
1556
1557 if (! group->conf->as)
1558 return 0;
1559
1560 LIST_LOOP (group->peer, peer, nn)
1561 {
1562 peer->group = NULL;
1563 peer_delete (peer);
1564 }
1565 list_delete_all_node (group->peer);
1566
1567 group->conf->as = 0;
1568
1569 return 0;
1570}
1571
1572/* Bind specified peer to peer group. */
1573int
1574peer_group_bind (struct bgp *bgp, union sockunion *su,
1575 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1576{
1577 struct peer *peer;
1578 int first_member = 0;
1579
1580 /* Check peer group's address family. */
1581 if (! group->conf->afc[afi][safi])
1582 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1583
1584 /* Lookup the peer. */
1585 peer = peer_lookup (bgp, su);
1586
1587 /* Create a new peer. */
1588 if (! peer)
1589 {
1590 if (! group->conf->as)
1591 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1592
1593 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1594 peer->group = group;
1595 peer->af_group[afi][safi] = 1;
1596 listnode_add (group->peer, peer);
1597 peer_group2peer_config_copy (group, peer, afi, safi);
1598
1599 return 0;
1600 }
1601
1602 /* When the peer already belongs to peer group, check the consistency. */
1603 if (peer->af_group[afi][safi])
1604 {
1605 if (strcmp (peer->group->name, group->name) != 0)
1606 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1607
1608 return 0;
1609 }
1610
1611 /* Check current peer group configuration. */
1612 if (peer_group_active (peer)
1613 && strcmp (peer->group->name, group->name) != 0)
1614 return BGP_ERR_PEER_GROUP_MISMATCH;
1615
1616 if (! group->conf->as)
1617 {
1618 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1619 && peer_sort (group->conf) != peer_sort (peer))
1620 {
1621 if (as)
1622 *as = peer->as;
1623 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1624 }
1625
1626 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1627 first_member = 1;
1628 }
1629
1630 peer->af_group[afi][safi] = 1;
1631 peer->afc[afi][safi] = 1;
1632 if (! peer->group)
1633 {
1634 peer->group = group;
1635 listnode_add (group->peer, peer);
1636 }
1637
1638 if (first_member)
1639 {
1640 /* Advertisement-interval reset */
1641 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1642 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1643 else
1644 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1645
1646 /* ebgp-multihop reset */
1647 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1648 group->conf->ttl = 255;
1649
1650 /* local-as reset */
1651 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1652 {
1653 group->conf->change_local_as = 0;
1654 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1655 }
1656 }
paulfee0f4c2004-09-13 05:12:46 +00001657
1658 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1659 {
1660 /* If it's not configured as RSERVER_CLIENT in any other address
1661 family, without being member of a peer_group, remove it from
1662 list bgp->rsclient.*/
1663 if (! peer_rsclient_active (peer))
1664 listnode_delete (bgp->rsclient, peer);
1665
1666 bgp_table_finish (peer->rib[afi][safi]);
1667
1668 /* Import policy. */
1669 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1670 {
1671 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1672 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1673 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1674 }
1675
1676 /* Export policy. */
1677 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1678 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1679 {
1680 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1681 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1682 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1683 }
1684 }
1685
paul718e3742002-12-13 20:15:29 +00001686 peer_group2peer_config_copy (group, peer, afi, safi);
1687
1688 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001689 {
1690 peer->last_reset = PEER_DOWN_RMAP_BIND;
1691 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1692 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1693 }
paul718e3742002-12-13 20:15:29 +00001694 else
1695 BGP_EVENT_ADD (peer, BGP_Stop);
1696
1697 return 0;
1698}
1699
1700int
1701peer_group_unbind (struct bgp *bgp, struct peer *peer,
1702 struct peer_group *group, afi_t afi, safi_t safi)
1703{
1704 if (! peer->af_group[afi][safi])
1705 return 0;
1706
1707 if (group != peer->group)
1708 return BGP_ERR_PEER_GROUP_MISMATCH;
1709
1710 peer->af_group[afi][safi] = 0;
1711 peer->afc[afi][safi] = 0;
1712 peer_af_flag_reset (peer, afi, safi);
1713
paulfee0f4c2004-09-13 05:12:46 +00001714 if (peer->rib[afi][safi])
1715 peer->rib[afi][safi] = NULL;
1716
paul718e3742002-12-13 20:15:29 +00001717 if (! peer_group_active (peer))
1718 {
1719 listnode_delete (group->peer, peer);
1720 peer->group = NULL;
1721 if (group->conf->as)
1722 {
1723 peer_delete (peer);
1724 return 0;
1725 }
1726 peer_global_config_reset (peer);
1727 }
1728
1729 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001730 {
1731 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1732 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1733 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1734 }
paul718e3742002-12-13 20:15:29 +00001735 else
1736 BGP_EVENT_ADD (peer, BGP_Stop);
1737
1738 return 0;
1739}
1740
1741/* BGP instance creation by `router bgp' commands. */
1742struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001743bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001744{
1745 struct bgp *bgp;
1746 afi_t afi;
1747 safi_t safi;
1748
1749 bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp));
1750
1751 bgp->peer_self = peer_new ();
paulfd79ac92004-10-13 05:06:08 +00001752 bgp->peer_self->host = strdup ("Static announcement");
paul718e3742002-12-13 20:15:29 +00001753
1754 bgp->peer = list_new ();
1755 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1756
1757 bgp->group = list_new ();
1758 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1759
paulfee0f4c2004-09-13 05:12:46 +00001760 bgp->rsclient = list_new ();
1761 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1762
paul718e3742002-12-13 20:15:29 +00001763 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1764 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1765 {
1766 bgp->route[afi][safi] = bgp_table_init ();
1767 bgp->aggregate[afi][safi] = bgp_table_init ();
1768 bgp->rib[afi][safi] = bgp_table_init ();
1769 }
1770
1771 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1772 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1773 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001774 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1775 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001776
1777 bgp->as = *as;
1778
1779 if (name)
1780 bgp->name = strdup (name);
1781
1782 return bgp;
1783}
1784
1785/* Return first entry of BGP. */
1786struct bgp *
1787bgp_get_default ()
1788{
1789 if (bm->bgp->head)
1790 return bm->bgp->head->data;
1791 return NULL;
1792}
1793
1794/* Lookup BGP entry. */
1795struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001796bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001797{
1798 struct bgp *bgp;
1799 struct listnode *nn;
1800
1801 LIST_LOOP (bm->bgp, bgp, nn)
1802 if (bgp->as == as
1803 && ((bgp->name == NULL && name == NULL)
1804 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1805 return bgp;
1806 return NULL;
1807}
1808
1809/* Lookup BGP structure by view name. */
1810struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001811bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00001812{
1813 struct bgp *bgp;
1814 struct listnode *nn;
1815
1816 LIST_LOOP (bm->bgp, bgp, nn)
1817 if ((bgp->name == NULL && name == NULL)
1818 || (bgp->name && name && strcmp (bgp->name, name) == 0))
1819 return bgp;
1820 return NULL;
1821}
1822
1823/* Called from VTY commands. */
1824int
paulfd79ac92004-10-13 05:06:08 +00001825bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001826{
1827 struct bgp *bgp;
1828
1829 /* Multiple instance check. */
1830 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
1831 {
1832 if (name)
1833 bgp = bgp_lookup_by_name (name);
1834 else
1835 bgp = bgp_get_default ();
1836
1837 /* Already exists. */
1838 if (bgp)
1839 {
1840 if (bgp->as != *as)
1841 {
1842 *as = bgp->as;
1843 return BGP_ERR_INSTANCE_MISMATCH;
1844 }
1845 *bgp_val = bgp;
1846 return 0;
1847 }
1848 }
1849 else
1850 {
1851 /* BGP instance name can not be specified for single instance. */
1852 if (name)
1853 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
1854
1855 /* Get default BGP structure if exists. */
1856 bgp = bgp_get_default ();
1857
1858 if (bgp)
1859 {
1860 if (bgp->as != *as)
1861 {
1862 *as = bgp->as;
1863 return BGP_ERR_AS_MISMATCH;
1864 }
1865 *bgp_val = bgp;
1866 return 0;
1867 }
1868 }
1869
1870 bgp = bgp_create (as, name);
1871 listnode_add (bm->bgp, bgp);
hasso18a6dce2004-10-03 18:18:34 +00001872 bgp_router_id_set(bgp, &router_id_zebra);
paul718e3742002-12-13 20:15:29 +00001873 *bgp_val = bgp;
1874
1875 return 0;
1876}
1877
1878/* Delete BGP instance. */
1879int
1880bgp_delete (struct bgp *bgp)
1881{
1882 struct peer *peer;
1883 struct listnode *nn;
1884 struct listnode *next;
1885 afi_t afi;
1886 safi_t safi;
1887 int i;
1888
1889 /* Delete static route. */
1890 bgp_static_delete (bgp);
1891
1892 /* Unset redistribution. */
1893 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1894 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
1895 if (i != ZEBRA_ROUTE_BGP)
1896 bgp_redistribute_unset (bgp, afi, i);
1897
1898 bgp->group->del = (void (*)(void *)) peer_group_delete;
1899 list_delete (bgp->group);
1900
1901 for (nn = bgp->peer->head; nn; nn = next)
1902 {
1903 peer = nn->data;
1904 next = nn->next;
1905 peer_delete (peer);
1906 }
1907
paulfee0f4c2004-09-13 05:12:46 +00001908 bgp->rsclient->del = (void (*)(void *)) peer_delete;
1909 list_delete (bgp->rsclient);
1910
paul718e3742002-12-13 20:15:29 +00001911 listnode_delete (bm->bgp, bgp);
1912
1913 if (bgp->name)
1914 free (bgp->name);
1915
1916 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1917 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1918 {
1919 if (bgp->route[afi][safi])
1920 XFREE (MTYPE_ROUTE_TABLE, bgp->route[afi][safi]);
1921 if (bgp->aggregate[afi][safi])
1922 XFREE (MTYPE_ROUTE_TABLE,bgp->aggregate[afi][safi]) ;
1923 if (bgp->rib[afi][safi])
1924 XFREE (MTYPE_ROUTE_TABLE,bgp->rib[afi][safi]);
1925 }
1926 XFREE (MTYPE_BGP, bgp);
1927
1928 return 0;
1929}
1930
1931struct peer *
1932peer_lookup (struct bgp *bgp, union sockunion *su)
1933{
1934 struct peer *peer;
1935 struct listnode *nn;
1936
1937 if (! bgp)
1938 bgp = bgp_get_default ();
1939
1940 if (! bgp)
1941 return NULL;
1942
1943 LIST_LOOP (bgp->peer, peer, nn)
1944 {
pauleb821182004-05-01 08:44:08 +00001945 if (sockunion_same (&peer->su, su)
1946 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1947 return peer;
paul718e3742002-12-13 20:15:29 +00001948 }
1949 return NULL;
1950}
1951
1952struct peer *
1953peer_lookup_with_open (union sockunion *su, as_t remote_as,
1954 struct in_addr *remote_id, int *as)
1955{
1956 struct peer *peer;
1957 struct listnode *nn;
1958 struct bgp *bgp;
1959
1960 bgp = bgp_get_default ();
1961 if (! bgp)
1962 return NULL;
1963
1964 LIST_LOOP (bgp->peer, peer, nn)
1965 {
pauleb821182004-05-01 08:44:08 +00001966 if (sockunion_same (&peer->su, su)
1967 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1968 {
1969 if (peer->as == remote_as
1970 && peer->remote_id.s_addr == remote_id->s_addr)
1971 return peer;
1972 if (peer->as == remote_as)
1973 *as = 1;
1974 }
paul718e3742002-12-13 20:15:29 +00001975 }
1976 LIST_LOOP (bgp->peer, peer, nn)
1977 {
pauleb821182004-05-01 08:44:08 +00001978 if (sockunion_same (&peer->su, su)
1979 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1980 {
1981 if (peer->as == remote_as
1982 && peer->remote_id.s_addr == 0)
1983 return peer;
1984 if (peer->as == remote_as)
1985 *as = 1;
1986 }
paul718e3742002-12-13 20:15:29 +00001987 }
1988 return NULL;
1989}
1990
1991/* If peer is configured at least one address family return 1. */
1992int
1993peer_active (struct peer *peer)
1994{
1995 if (peer->afc[AFI_IP][SAFI_UNICAST]
1996 || peer->afc[AFI_IP][SAFI_MULTICAST]
1997 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
1998 || peer->afc[AFI_IP6][SAFI_UNICAST]
1999 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2000 return 1;
2001 return 0;
2002}
2003
2004/* If peer is negotiated at least one address family return 1. */
2005int
2006peer_active_nego (struct peer *peer)
2007{
2008 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2009 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2010 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2011 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2012 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2013 return 1;
2014 return 0;
2015}
2016
2017/* peer_flag_change_type. */
2018enum peer_change_type
2019{
2020 peer_change_none,
2021 peer_change_reset,
2022 peer_change_reset_in,
2023 peer_change_reset_out,
2024};
2025
2026void
2027peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2028 enum peer_change_type type)
2029{
2030 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2031 return;
2032
2033 if (type == peer_change_reset)
2034 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2035 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2036 else if (type == peer_change_reset_in)
2037 {
2038 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2039 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2040 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2041 else
2042 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2043 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2044 }
2045 else if (type == peer_change_reset_out)
2046 bgp_announce_route (peer, afi, safi);
2047}
2048
2049struct peer_flag_action
2050{
2051 /* Peer's flag. */
2052 u_int32_t flag;
2053
2054 /* This flag can be set for peer-group member. */
2055 u_char not_for_member;
2056
2057 /* Action when the flag is changed. */
2058 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002059
2060 /* Peer down cause */
2061 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002062};
2063
2064struct peer_flag_action peer_flag_action_list[] =
2065 {
2066 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2067 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2068 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2069 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2070 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
2071 { PEER_FLAG_NO_ROUTE_REFRESH_CAP, 0, peer_change_reset },
2072 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
2073 { PEER_FLAG_ENFORCE_MULTIHOP, 0, peer_change_reset },
2074 { 0, 0, 0 }
2075 };
2076
2077struct peer_flag_action peer_af_flag_action_list[] =
2078 {
2079 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2080 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2081 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2082 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2083 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2084 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2085 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2086 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2087 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2088 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2089 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2090 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2091 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002092 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002093 { 0, 0, 0 }
2094 };
2095
2096/* Proper action set. */
2097int
2098peer_flag_action_set (struct peer_flag_action *action_list, int size,
2099 struct peer_flag_action *action, u_int32_t flag)
2100{
2101 int i;
2102 int found = 0;
2103 int reset_in = 0;
2104 int reset_out = 0;
2105 struct peer_flag_action *match = NULL;
2106
2107 /* Check peer's frag action. */
2108 for (i = 0; i < size; i++)
2109 {
2110 match = &action_list[i];
2111
2112 if (match->flag == 0)
2113 break;
2114
2115 if (match->flag & flag)
2116 {
2117 found = 1;
2118
2119 if (match->type == peer_change_reset_in)
2120 reset_in = 1;
2121 if (match->type == peer_change_reset_out)
2122 reset_out = 1;
2123 if (match->type == peer_change_reset)
2124 {
2125 reset_in = 1;
2126 reset_out = 1;
2127 }
2128 if (match->not_for_member)
2129 action->not_for_member = 1;
2130 }
2131 }
2132
2133 /* Set peer clear type. */
2134 if (reset_in && reset_out)
2135 action->type = peer_change_reset;
2136 else if (reset_in)
2137 action->type = peer_change_reset_in;
2138 else if (reset_out)
2139 action->type = peer_change_reset_out;
2140 else
2141 action->type = peer_change_none;
2142
2143 return found;
2144}
2145
2146void
2147peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2148{
2149 if (flag == PEER_FLAG_SHUTDOWN)
2150 {
2151 if (CHECK_FLAG (peer->flags, flag))
2152 {
hasso0a486e52005-02-01 20:57:17 +00002153 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2154 if (peer->t_pmax_restart)
2155 {
2156 BGP_TIMER_OFF (peer->t_pmax_restart);
2157 if (BGP_DEBUG (events, EVENTS))
2158 zlog_debug ("%s Maximum-prefix restart timer canceled",
2159 peer->host);
2160 }
2161
paul718e3742002-12-13 20:15:29 +00002162 if (peer->status == Established)
2163 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2164 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2165 else
2166 BGP_EVENT_ADD (peer, BGP_Stop);
2167 }
2168 else
2169 {
2170 peer->v_start = BGP_INIT_START_TIMER;
2171 BGP_EVENT_ADD (peer, BGP_Stop);
2172 }
2173 }
2174 else if (peer->status == Established)
2175 {
2176 if (flag == PEER_FLAG_NO_ROUTE_REFRESH_CAP
2177 && CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
2178 {
2179 if (CHECK_FLAG (peer->flags, flag))
2180 UNSET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
2181 else
2182 SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
2183
2184 bgp_capability_send (peer, AFI_IP, SAFI_UNICAST,
2185 CAPABILITY_CODE_REFRESH,
2186 CHECK_FLAG (peer->flags, flag) ?
2187 CAPABILITY_ACTION_UNSET : CAPABILITY_ACTION_SET);
2188 }
2189 else
hassoe0701b72004-05-20 09:19:34 +00002190 {
2191 if (flag == PEER_FLAG_NO_ROUTE_REFRESH_CAP)
2192 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2193 else if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2194 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2195 else if (flag == PEER_FLAG_PASSIVE)
2196 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
2197 else if (flag == PEER_FLAG_ENFORCE_MULTIHOP)
2198 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
2199
2200 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2201 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2202 }
paul718e3742002-12-13 20:15:29 +00002203 }
2204 else
2205 BGP_EVENT_ADD (peer, BGP_Stop);
2206}
2207
2208/* Change specified peer flag. */
2209int
2210peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2211{
2212 int found;
2213 int size;
2214 struct peer_group *group;
2215 struct listnode *nn;
2216 struct peer_flag_action action;
2217
2218 memset (&action, 0, sizeof (struct peer_flag_action));
2219 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2220
2221 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2222
2223 /* No flag action is found. */
2224 if (! found)
2225 return BGP_ERR_INVALID_FLAG;
2226
2227 /* Not for peer-group member. */
2228 if (action.not_for_member && peer_group_active (peer))
2229 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2230
2231 /* When unset the peer-group member's flag we have to check
2232 peer-group configuration. */
2233 if (! set && peer_group_active (peer))
2234 if (CHECK_FLAG (peer->group->conf->flags, flag))
2235 {
2236 if (flag == PEER_FLAG_SHUTDOWN)
2237 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2238 else
2239 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2240 }
2241
2242 /* Flag conflict check. */
2243 if (set
2244 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2245 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2246 return BGP_ERR_PEER_FLAG_CONFLICT;
2247
2248 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2249 {
2250 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2251 return 0;
2252 if (! set && ! CHECK_FLAG (peer->flags, flag))
2253 return 0;
2254 }
2255
2256 if (set)
2257 SET_FLAG (peer->flags, flag);
2258 else
2259 UNSET_FLAG (peer->flags, flag);
2260
2261 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2262 {
2263 if (action.type == peer_change_reset)
2264 peer_flag_modify_action (peer, flag);
2265
2266 return 0;
2267 }
2268
2269 /* peer-group member updates. */
2270 group = peer->group;
2271
2272 LIST_LOOP (group->peer, peer, nn)
2273 {
2274 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2275 continue;
2276
2277 if (! set && ! CHECK_FLAG (peer->flags, flag))
2278 continue;
2279
2280 if (set)
2281 SET_FLAG (peer->flags, flag);
2282 else
2283 UNSET_FLAG (peer->flags, flag);
2284
2285 if (action.type == peer_change_reset)
2286 peer_flag_modify_action (peer, flag);
2287 }
2288 return 0;
2289}
2290
2291int
2292peer_flag_set (struct peer *peer, u_int32_t flag)
2293{
2294 return peer_flag_modify (peer, flag, 1);
2295}
2296
2297int
2298peer_flag_unset (struct peer *peer, u_int32_t flag)
2299{
2300 return peer_flag_modify (peer, flag, 0);
2301}
2302
2303int
2304peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2305{
2306 if (peer->af_group[afi][safi])
2307 return 1;
2308 return 0;
2309}
2310
2311int
2312peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2313 int set)
2314{
2315 int found;
2316 int size;
2317 struct listnode *nn;
2318 struct peer_group *group;
2319 struct peer_flag_action action;
2320
2321 memset (&action, 0, sizeof (struct peer_flag_action));
2322 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2323
2324 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2325
2326 /* No flag action is found. */
2327 if (! found)
2328 return BGP_ERR_INVALID_FLAG;
2329
2330 /* Adress family must be activated. */
2331 if (! peer->afc[afi][safi])
2332 return BGP_ERR_PEER_INACTIVE;
2333
2334 /* Not for peer-group member. */
2335 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2336 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2337
2338 /* Spcecial check for reflector client. */
2339 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2340 && peer_sort (peer) != BGP_PEER_IBGP)
2341 return BGP_ERR_NOT_INTERNAL_PEER;
2342
2343 /* Spcecial check for remove-private-AS. */
2344 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2345 && peer_sort (peer) == BGP_PEER_IBGP)
2346 return BGP_ERR_REMOVE_PRIVATE_AS;
2347
2348 /* When unset the peer-group member's flag we have to check
2349 peer-group configuration. */
2350 if (! set && peer->af_group[afi][safi])
2351 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2352 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2353
2354 /* When current flag configuration is same as requested one. */
2355 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2356 {
2357 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2358 return 0;
2359 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2360 return 0;
2361 }
2362
2363 if (set)
2364 SET_FLAG (peer->af_flags[afi][safi], flag);
2365 else
2366 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2367
2368 /* Execute action when peer is established. */
2369 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2370 && peer->status == Established)
2371 {
2372 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2373 bgp_clear_adj_in (peer, afi, safi);
2374 else
hassoe0701b72004-05-20 09:19:34 +00002375 {
2376 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2377 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2378 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2379 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2380 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2381 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2382 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2383 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2384
2385 peer_change_action (peer, afi, safi, action.type);
2386 }
2387
paul718e3742002-12-13 20:15:29 +00002388 }
2389
2390 /* Peer group member updates. */
2391 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2392 {
2393 group = peer->group;
2394
2395 LIST_LOOP (group->peer, peer, nn)
2396 {
2397 if (! peer->af_group[afi][safi])
2398 continue;
2399
2400 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2401 continue;
2402
2403 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2404 continue;
2405
2406 if (set)
2407 SET_FLAG (peer->af_flags[afi][safi], flag);
2408 else
2409 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2410
2411 if (peer->status == Established)
2412 {
2413 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2414 bgp_clear_adj_in (peer, afi, safi);
2415 else
hassoe0701b72004-05-20 09:19:34 +00002416 {
2417 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2418 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2419 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2420 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2421 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2422 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2423 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2424 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2425
2426 peer_change_action (peer, afi, safi, action.type);
2427 }
paul718e3742002-12-13 20:15:29 +00002428 }
2429 }
2430 }
2431 return 0;
2432}
2433
2434int
2435peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2436{
2437 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2438}
2439
2440int
2441peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2442{
2443 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2444}
2445
2446/* EBGP multihop configuration. */
2447int
2448peer_ebgp_multihop_set (struct peer *peer, int ttl)
2449{
2450 struct peer_group *group;
2451 struct listnode *nn;
2452
2453 if (peer_sort (peer) == BGP_PEER_IBGP)
2454 return 0;
2455
2456 peer->ttl = ttl;
2457
2458 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2459 {
pauleb821182004-05-01 08:44:08 +00002460 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2461 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002462 }
2463 else
2464 {
2465 group = peer->group;
2466 LIST_LOOP (group->peer, peer, nn)
pauleb821182004-05-01 08:44:08 +00002467 {
2468 if (peer_sort (peer) == BGP_PEER_IBGP)
2469 continue;
paul718e3742002-12-13 20:15:29 +00002470
pauleb821182004-05-01 08:44:08 +00002471 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002472
pauleb821182004-05-01 08:44:08 +00002473 if (peer->fd >= 0)
2474 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2475 }
paul718e3742002-12-13 20:15:29 +00002476 }
2477 return 0;
2478}
2479
2480int
2481peer_ebgp_multihop_unset (struct peer *peer)
2482{
2483 struct peer_group *group;
2484 struct listnode *nn;
2485
2486 if (peer_sort (peer) == BGP_PEER_IBGP)
2487 return 0;
2488
2489 if (peer_group_active (peer))
2490 peer->ttl = peer->group->conf->ttl;
2491 else
2492 peer->ttl = 1;
2493
2494 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2495 {
pauleb821182004-05-01 08:44:08 +00002496 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2497 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002498 }
2499 else
2500 {
2501 group = peer->group;
2502 LIST_LOOP (group->peer, peer, nn)
pauleb821182004-05-01 08:44:08 +00002503 {
2504 if (peer_sort (peer) == BGP_PEER_IBGP)
2505 continue;
paul718e3742002-12-13 20:15:29 +00002506
pauleb821182004-05-01 08:44:08 +00002507 peer->ttl = 1;
2508
2509 if (peer->fd >= 0)
2510 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2511 }
paul718e3742002-12-13 20:15:29 +00002512 }
2513 return 0;
2514}
2515
2516/* Neighbor description. */
2517int
2518peer_description_set (struct peer *peer, char *desc)
2519{
2520 if (peer->desc)
2521 XFREE (MTYPE_PEER_DESC, peer->desc);
2522
2523 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2524
2525 return 0;
2526}
2527
2528int
2529peer_description_unset (struct peer *peer)
2530{
2531 if (peer->desc)
2532 XFREE (MTYPE_PEER_DESC, peer->desc);
2533
2534 peer->desc = NULL;
2535
2536 return 0;
2537}
2538
2539/* Neighbor update-source. */
2540int
paulfd79ac92004-10-13 05:06:08 +00002541peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002542{
2543 struct peer_group *group;
2544 struct listnode *nn;
2545
2546 if (peer->update_if)
2547 {
2548 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2549 && strcmp (peer->update_if, ifname) == 0)
2550 return 0;
2551
2552 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2553 peer->update_if = NULL;
2554 }
2555
2556 if (peer->update_source)
2557 {
2558 sockunion_free (peer->update_source);
2559 peer->update_source = NULL;
2560 }
2561
2562 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2563
2564 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2565 {
2566 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002567 {
2568 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2569 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2570 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2571 }
paul718e3742002-12-13 20:15:29 +00002572 else
2573 BGP_EVENT_ADD (peer, BGP_Stop);
2574 return 0;
2575 }
2576
2577 /* peer-group member updates. */
2578 group = peer->group;
2579 LIST_LOOP (group->peer, peer, nn)
2580 {
2581 if (peer->update_if)
2582 {
2583 if (strcmp (peer->update_if, ifname) == 0)
2584 continue;
2585
2586 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2587 peer->update_if = NULL;
2588 }
2589
2590 if (peer->update_source)
2591 {
2592 sockunion_free (peer->update_source);
2593 peer->update_source = NULL;
2594 }
2595
2596 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2597
2598 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002599 {
2600 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2601 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2602 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2603 }
paul718e3742002-12-13 20:15:29 +00002604 else
2605 BGP_EVENT_ADD (peer, BGP_Stop);
2606 }
2607 return 0;
2608}
2609
2610int
2611peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2612{
2613 struct peer_group *group;
2614 struct listnode *nn;
2615
2616 if (peer->update_source)
2617 {
2618 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2619 && sockunion_cmp (peer->update_source, su) == 0)
2620 return 0;
2621 sockunion_free (peer->update_source);
2622 peer->update_source = NULL;
2623 }
2624
2625 if (peer->update_if)
2626 {
2627 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2628 peer->update_if = NULL;
2629 }
2630
2631 peer->update_source = sockunion_dup (su);
2632
2633 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2634 {
2635 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002636 {
2637 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2638 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2639 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2640 }
paul718e3742002-12-13 20:15:29 +00002641 else
2642 BGP_EVENT_ADD (peer, BGP_Stop);
2643 return 0;
2644 }
2645
2646 /* peer-group member updates. */
2647 group = peer->group;
2648 LIST_LOOP (group->peer, peer, nn)
2649 {
2650 if (peer->update_source)
2651 {
2652 if (sockunion_cmp (peer->update_source, su) == 0)
2653 continue;
2654 sockunion_free (peer->update_source);
2655 peer->update_source = NULL;
2656 }
2657
2658 if (peer->update_if)
2659 {
2660 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2661 peer->update_if = NULL;
2662 }
2663
2664 peer->update_source = sockunion_dup (su);
2665
2666 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002667 {
2668 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2669 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2670 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2671 }
paul718e3742002-12-13 20:15:29 +00002672 else
2673 BGP_EVENT_ADD (peer, BGP_Stop);
2674 }
2675 return 0;
2676}
2677
2678int
2679peer_update_source_unset (struct peer *peer)
2680{
2681 union sockunion *su;
2682 struct peer_group *group;
2683 struct listnode *nn;
2684
2685 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2686 && ! peer->update_source
2687 && ! peer->update_if)
2688 return 0;
2689
2690 if (peer->update_source)
2691 {
2692 sockunion_free (peer->update_source);
2693 peer->update_source = NULL;
2694 }
2695 if (peer->update_if)
2696 {
2697 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2698 peer->update_if = NULL;
2699 }
2700
2701 if (peer_group_active (peer))
2702 {
2703 group = peer->group;
2704
2705 if (group->conf->update_source)
2706 {
2707 su = sockunion_dup (group->conf->update_source);
2708 peer->update_source = su;
2709 }
2710 else if (group->conf->update_if)
2711 peer->update_if =
2712 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2713 }
2714
2715 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2716 {
2717 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002718 {
2719 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2720 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2721 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2722 }
paul718e3742002-12-13 20:15:29 +00002723 else
2724 BGP_EVENT_ADD (peer, BGP_Stop);
2725 return 0;
2726 }
2727
2728 /* peer-group member updates. */
2729 group = peer->group;
2730 LIST_LOOP (group->peer, peer, nn)
2731 {
2732 if (! peer->update_source && ! peer->update_if)
2733 continue;
2734
2735 if (peer->update_source)
2736 {
2737 sockunion_free (peer->update_source);
2738 peer->update_source = NULL;
2739 }
2740
2741 if (peer->update_if)
2742 {
2743 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2744 peer->update_if = NULL;
2745 }
2746
2747 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002748 {
2749 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2750 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2751 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2752 }
paul718e3742002-12-13 20:15:29 +00002753 else
2754 BGP_EVENT_ADD (peer, BGP_Stop);
2755 }
2756 return 0;
2757}
2758
2759int
2760peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00002761 const char *rmap)
paul718e3742002-12-13 20:15:29 +00002762{
2763 struct peer_group *group;
2764 struct listnode *nn;
2765
2766 /* Adress family must be activated. */
2767 if (! peer->afc[afi][safi])
2768 return BGP_ERR_PEER_INACTIVE;
2769
2770 /* Default originate can't be used for peer group memeber. */
2771 if (peer_is_group_member (peer, afi, safi))
2772 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2773
2774 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
2775 || (rmap && ! peer->default_rmap[afi][safi].name)
2776 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
2777 {
2778 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2779
2780 if (rmap)
2781 {
2782 if (peer->default_rmap[afi][safi].name)
2783 free (peer->default_rmap[afi][safi].name);
2784 peer->default_rmap[afi][safi].name = strdup (rmap);
2785 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2786 }
2787 }
2788
2789 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2790 {
2791 if (peer->status == Established && peer->afc_nego[afi][safi])
2792 bgp_default_originate (peer, afi, safi, 0);
2793 return 0;
2794 }
2795
2796 /* peer-group member updates. */
2797 group = peer->group;
2798 LIST_LOOP (group->peer, peer, nn)
2799 {
2800 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2801
2802 if (rmap)
2803 {
2804 if (peer->default_rmap[afi][safi].name)
2805 free (peer->default_rmap[afi][safi].name);
2806 peer->default_rmap[afi][safi].name = strdup (rmap);
2807 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2808 }
2809
2810 if (peer->status == Established && peer->afc_nego[afi][safi])
2811 bgp_default_originate (peer, afi, safi, 0);
2812 }
2813 return 0;
2814}
2815
2816int
2817peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
2818{
2819 struct peer_group *group;
2820 struct listnode *nn;
2821
2822 /* Adress family must be activated. */
2823 if (! peer->afc[afi][safi])
2824 return BGP_ERR_PEER_INACTIVE;
2825
2826 /* Default originate can't be used for peer group memeber. */
2827 if (peer_is_group_member (peer, afi, safi))
2828 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2829
2830 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
2831 {
2832 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2833
2834 if (peer->default_rmap[afi][safi].name)
2835 free (peer->default_rmap[afi][safi].name);
2836 peer->default_rmap[afi][safi].name = NULL;
2837 peer->default_rmap[afi][safi].map = NULL;
2838 }
2839
2840 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2841 {
2842 if (peer->status == Established && peer->afc_nego[afi][safi])
2843 bgp_default_originate (peer, afi, safi, 1);
2844 return 0;
2845 }
2846
2847 /* peer-group member updates. */
2848 group = peer->group;
2849 LIST_LOOP (group->peer, peer, nn)
2850 {
2851 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2852
2853 if (peer->default_rmap[afi][safi].name)
2854 free (peer->default_rmap[afi][safi].name);
2855 peer->default_rmap[afi][safi].name = NULL;
2856 peer->default_rmap[afi][safi].map = NULL;
2857
2858 if (peer->status == Established && peer->afc_nego[afi][safi])
2859 bgp_default_originate (peer, afi, safi, 1);
2860 }
2861 return 0;
2862}
2863
2864int
2865peer_port_set (struct peer *peer, u_int16_t port)
2866{
2867 peer->port = port;
2868 return 0;
2869}
2870
2871int
2872peer_port_unset (struct peer *peer)
2873{
2874 peer->port = BGP_PORT_DEFAULT;
2875 return 0;
2876}
2877
2878/* neighbor weight. */
2879int
2880peer_weight_set (struct peer *peer, u_int16_t weight)
2881{
2882 struct peer_group *group;
2883 struct listnode *nn;
2884
2885 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
2886 peer->weight = weight;
2887
2888 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2889 return 0;
2890
2891 /* peer-group member updates. */
2892 group = peer->group;
2893 LIST_LOOP (group->peer, peer, nn)
2894 {
2895 peer->weight = group->conf->weight;
2896 }
2897 return 0;
2898}
2899
2900int
2901peer_weight_unset (struct peer *peer)
2902{
2903 struct peer_group *group;
2904 struct listnode *nn;
2905
2906 /* Set default weight. */
2907 if (peer_group_active (peer))
2908 peer->weight = peer->group->conf->weight;
2909 else
2910 peer->weight = 0;
2911
2912 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
2913
2914 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2915 return 0;
2916
2917 /* peer-group member updates. */
2918 group = peer->group;
2919 LIST_LOOP (group->peer, peer, nn)
2920 {
2921 peer->weight = 0;
2922 }
2923 return 0;
2924}
2925
2926int
2927peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
2928{
2929 struct peer_group *group;
2930 struct listnode *nn;
2931
2932 /* Not for peer group memeber. */
2933 if (peer_group_active (peer))
2934 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2935
2936 /* keepalive value check. */
2937 if (keepalive > 65535)
2938 return BGP_ERR_INVALID_VALUE;
2939
2940 /* Holdtime value check. */
2941 if (holdtime > 65535)
2942 return BGP_ERR_INVALID_VALUE;
2943
2944 /* Holdtime value must be either 0 or greater than 3. */
2945 if (holdtime < 3 && holdtime != 0)
2946 return BGP_ERR_INVALID_VALUE;
2947
2948 /* Set value to the configuration. */
2949 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
2950 peer->holdtime = holdtime;
2951 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
2952
2953 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2954 return 0;
2955
2956 /* peer-group member updates. */
2957 group = peer->group;
2958 LIST_LOOP (group->peer, peer, nn)
2959 {
2960 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
2961 peer->holdtime = group->conf->holdtime;
2962 peer->keepalive = group->conf->keepalive;
2963 }
2964 return 0;
2965}
2966
2967int
2968peer_timers_unset (struct peer *peer)
2969{
2970 struct peer_group *group;
2971 struct listnode *nn;
2972
2973 if (peer_group_active (peer))
2974 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2975
2976 /* Clear configuration. */
2977 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
2978 peer->keepalive = 0;
2979 peer->holdtime = 0;
2980
2981 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2982 return 0;
2983
2984 /* peer-group member updates. */
2985 group = peer->group;
2986 LIST_LOOP (group->peer, peer, nn)
2987 {
2988 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
2989 peer->holdtime = 0;
2990 peer->keepalive = 0;
2991 }
2992
2993 return 0;
2994}
2995
2996int
2997peer_timers_connect_set (struct peer *peer, u_int32_t connect)
2998{
2999 if (peer_group_active (peer))
3000 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3001
3002 if (connect > 65535)
3003 return BGP_ERR_INVALID_VALUE;
3004
3005 /* Set value to the configuration. */
3006 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3007 peer->connect = connect;
3008
3009 /* Set value to timer setting. */
3010 peer->v_connect = connect;
3011
3012 return 0;
3013}
3014
3015int
3016peer_timers_connect_unset (struct peer *peer)
3017{
3018 if (peer_group_active (peer))
3019 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3020
3021 /* Clear configuration. */
3022 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3023 peer->connect = 0;
3024
3025 /* Set timer setting to default value. */
3026 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3027
3028 return 0;
3029}
3030
3031int
3032peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3033{
3034 if (peer_group_active (peer))
3035 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3036
3037 if (routeadv > 600)
3038 return BGP_ERR_INVALID_VALUE;
3039
3040 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3041 peer->routeadv = routeadv;
3042 peer->v_routeadv = routeadv;
3043
3044 return 0;
3045}
3046
3047int
3048peer_advertise_interval_unset (struct peer *peer)
3049{
3050 if (peer_group_active (peer))
3051 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3052
3053 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3054 peer->routeadv = 0;
3055
3056 if (peer_sort (peer) == BGP_PEER_IBGP)
3057 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3058 else
3059 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3060
3061 return 0;
3062}
3063
3064int
3065peer_version_set (struct peer *peer, int version)
3066{
3067 if (version != BGP_VERSION_4 && version != BGP_VERSION_MP_4_DRAFT_00)
3068 return BGP_ERR_INVALID_VALUE;
3069
3070 peer->version = version;
3071
3072 return 0;
3073}
3074
3075int
3076peer_version_unset (struct peer *peer)
3077{
3078 peer->version = BGP_VERSION_4;
3079 return 0;
3080}
3081
3082/* neighbor interface */
3083int
paulfd79ac92004-10-13 05:06:08 +00003084peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003085{
3086 if (peer->ifname)
3087 free (peer->ifname);
3088 peer->ifname = strdup (str);
3089
3090 return 0;
3091}
3092
3093int
3094peer_interface_unset (struct peer *peer)
3095{
3096 if (peer->ifname)
3097 free (peer->ifname);
3098 peer->ifname = NULL;
3099
3100 return 0;
3101}
3102
3103/* Allow-as in. */
3104int
3105peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3106{
3107 struct peer_group *group;
3108 struct listnode *nn;
3109
3110 if (allow_num < 1 || allow_num > 10)
3111 return BGP_ERR_INVALID_VALUE;
3112
3113 if (peer->allowas_in[afi][safi] != allow_num)
3114 {
3115 peer->allowas_in[afi][safi] = allow_num;
3116 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3117 peer_change_action (peer, afi, safi, peer_change_reset_in);
3118 }
3119
3120 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3121 return 0;
3122
3123 group = peer->group;
3124 LIST_LOOP (group->peer, peer, nn)
3125 {
3126 if (peer->allowas_in[afi][safi] != allow_num)
3127 {
3128 peer->allowas_in[afi][safi] = allow_num;
3129 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3130 peer_change_action (peer, afi, safi, peer_change_reset_in);
3131 }
3132
3133 }
3134 return 0;
3135}
3136
3137int
3138peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3139{
3140 struct peer_group *group;
3141 struct listnode *nn;
3142
3143 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3144 {
3145 peer->allowas_in[afi][safi] = 0;
3146 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3147 }
3148
3149 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3150 return 0;
3151
3152 group = peer->group;
3153 LIST_LOOP (group->peer, peer, nn)
3154 {
3155 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3156 {
3157 peer->allowas_in[afi][safi] = 0;
3158 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3159 }
3160 }
3161 return 0;
3162}
3163
3164int
3165peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3166{
3167 struct bgp *bgp = peer->bgp;
3168 struct peer_group *group;
3169 struct listnode *nn;
3170
3171 if (peer_sort (peer) != BGP_PEER_EBGP
3172 && peer_sort (peer) != BGP_PEER_INTERNAL)
3173 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3174
3175 if (bgp->as == as)
3176 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3177
3178 if (peer_group_active (peer))
3179 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3180
3181 if (peer->change_local_as == as &&
3182 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3183 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3184 return 0;
3185
3186 peer->change_local_as = as;
3187 if (no_prepend)
3188 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3189 else
3190 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3191
3192 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3193 {
3194 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003195 {
3196 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3197 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3198 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3199 }
paul718e3742002-12-13 20:15:29 +00003200 else
3201 BGP_EVENT_ADD (peer, BGP_Stop);
3202
3203 return 0;
3204 }
3205
3206 group = peer->group;
3207 LIST_LOOP (group->peer, peer, nn)
3208 {
3209 peer->change_local_as = as;
3210 if (no_prepend)
3211 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3212 else
3213 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3214
3215 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003216 {
3217 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3218 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3219 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3220 }
paul718e3742002-12-13 20:15:29 +00003221 else
3222 BGP_EVENT_ADD (peer, BGP_Stop);
3223 }
3224
3225 return 0;
3226}
3227
3228int
3229peer_local_as_unset (struct peer *peer)
3230{
3231 struct peer_group *group;
3232 struct listnode *nn;
3233
3234 if (peer_group_active (peer))
3235 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3236
3237 if (! peer->change_local_as)
3238 return 0;
3239
3240 peer->change_local_as = 0;
3241 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3242
3243 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3244 {
3245 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003246 {
3247 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3248 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3249 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3250 }
paul718e3742002-12-13 20:15:29 +00003251 else
3252 BGP_EVENT_ADD (peer, BGP_Stop);
3253
3254 return 0;
3255 }
3256
3257 group = peer->group;
3258 LIST_LOOP (group->peer, peer, nn)
3259 {
3260 peer->change_local_as = 0;
3261 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3262
3263 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003264 {
3265 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3266 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3267 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3268 }
paul718e3742002-12-13 20:15:29 +00003269 else
3270 BGP_EVENT_ADD (peer, BGP_Stop);
3271 }
3272 return 0;
3273}
3274
3275/* Set distribute list to the peer. */
3276int
3277peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003278 const char *name)
paul718e3742002-12-13 20:15:29 +00003279{
3280 struct bgp_filter *filter;
3281 struct peer_group *group;
3282 struct listnode *nn;
3283
3284 if (! peer->afc[afi][safi])
3285 return BGP_ERR_PEER_INACTIVE;
3286
3287 if (direct != FILTER_IN && direct != FILTER_OUT)
3288 return BGP_ERR_INVALID_VALUE;
3289
3290 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3291 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3292
3293 filter = &peer->filter[afi][safi];
3294
3295 if (filter->plist[direct].name)
3296 return BGP_ERR_PEER_FILTER_CONFLICT;
3297
3298 if (filter->dlist[direct].name)
3299 free (filter->dlist[direct].name);
3300 filter->dlist[direct].name = strdup (name);
3301 filter->dlist[direct].alist = access_list_lookup (afi, name);
3302
3303 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3304 return 0;
3305
3306 group = peer->group;
3307 LIST_LOOP (group->peer, peer, nn)
3308 {
3309 filter = &peer->filter[afi][safi];
3310
3311 if (! peer->af_group[afi][safi])
3312 continue;
3313
3314 if (filter->dlist[direct].name)
3315 free (filter->dlist[direct].name);
3316 filter->dlist[direct].name = strdup (name);
3317 filter->dlist[direct].alist = access_list_lookup (afi, name);
3318 }
3319
3320 return 0;
3321}
3322
3323int
3324peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3325{
3326 struct bgp_filter *filter;
3327 struct bgp_filter *gfilter;
3328 struct peer_group *group;
3329 struct listnode *nn;
3330
3331 if (! peer->afc[afi][safi])
3332 return BGP_ERR_PEER_INACTIVE;
3333
3334 if (direct != FILTER_IN && direct != FILTER_OUT)
3335 return BGP_ERR_INVALID_VALUE;
3336
3337 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3338 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3339
3340 filter = &peer->filter[afi][safi];
3341
3342 /* apply peer-group filter */
3343 if (peer->af_group[afi][safi])
3344 {
3345 gfilter = &peer->group->conf->filter[afi][safi];
3346
3347 if (gfilter->dlist[direct].name)
3348 {
3349 if (filter->dlist[direct].name)
3350 free (filter->dlist[direct].name);
3351 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3352 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3353 return 0;
3354 }
3355 }
3356
3357 if (filter->dlist[direct].name)
3358 free (filter->dlist[direct].name);
3359 filter->dlist[direct].name = NULL;
3360 filter->dlist[direct].alist = NULL;
3361
3362 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3363 return 0;
3364
3365 group = peer->group;
3366 LIST_LOOP (group->peer, peer, nn)
3367 {
3368 filter = &peer->filter[afi][safi];
3369
3370 if (! peer->af_group[afi][safi])
3371 continue;
3372
3373 if (filter->dlist[direct].name)
3374 free (filter->dlist[direct].name);
3375 filter->dlist[direct].name = NULL;
3376 filter->dlist[direct].alist = NULL;
3377 }
3378
3379 return 0;
3380}
3381
3382/* Update distribute list. */
3383void
3384peer_distribute_update (struct access_list *access)
3385{
3386 afi_t afi;
3387 safi_t safi;
3388 int direct;
3389 struct listnode *nn, *nm;
3390 struct bgp *bgp;
3391 struct peer *peer;
3392 struct peer_group *group;
3393 struct bgp_filter *filter;
3394
3395 LIST_LOOP (bm->bgp, bgp, nn)
3396 {
3397 LIST_LOOP (bgp->peer, peer, nm)
3398 {
3399 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3400 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3401 {
3402 filter = &peer->filter[afi][safi];
3403
3404 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3405 {
3406 if (filter->dlist[direct].name)
3407 filter->dlist[direct].alist =
3408 access_list_lookup (afi, filter->dlist[direct].name);
3409 else
3410 filter->dlist[direct].alist = NULL;
3411 }
3412 }
3413 }
3414 LIST_LOOP (bgp->group, group, nm)
3415 {
3416 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3417 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3418 {
3419 filter = &group->conf->filter[afi][safi];
3420
3421 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3422 {
3423 if (filter->dlist[direct].name)
3424 filter->dlist[direct].alist =
3425 access_list_lookup (afi, filter->dlist[direct].name);
3426 else
3427 filter->dlist[direct].alist = NULL;
3428 }
3429 }
3430 }
3431 }
3432}
3433
3434/* Set prefix list to the peer. */
3435int
3436peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003437 const char *name)
paul718e3742002-12-13 20:15:29 +00003438{
3439 struct bgp_filter *filter;
3440 struct peer_group *group;
3441 struct listnode *nn;
3442
3443 if (! peer->afc[afi][safi])
3444 return BGP_ERR_PEER_INACTIVE;
3445
3446 if (direct != FILTER_IN && direct != FILTER_OUT)
3447 return BGP_ERR_INVALID_VALUE;
3448
3449 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3450 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3451
3452 filter = &peer->filter[afi][safi];
3453
3454 if (filter->dlist[direct].name)
3455 return BGP_ERR_PEER_FILTER_CONFLICT;
3456
3457 if (filter->plist[direct].name)
3458 free (filter->plist[direct].name);
3459 filter->plist[direct].name = strdup (name);
3460 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3461
3462 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3463 return 0;
3464
3465 group = peer->group;
3466 LIST_LOOP (group->peer, peer, nn)
3467 {
3468 filter = &peer->filter[afi][safi];
3469
3470 if (! peer->af_group[afi][safi])
3471 continue;
3472
3473 if (filter->plist[direct].name)
3474 free (filter->plist[direct].name);
3475 filter->plist[direct].name = strdup (name);
3476 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3477 }
3478 return 0;
3479}
3480
3481int
3482peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3483{
3484 struct bgp_filter *filter;
3485 struct bgp_filter *gfilter;
3486 struct peer_group *group;
3487 struct listnode *nn;
3488
3489 if (! peer->afc[afi][safi])
3490 return BGP_ERR_PEER_INACTIVE;
3491
3492 if (direct != FILTER_IN && direct != FILTER_OUT)
3493 return BGP_ERR_INVALID_VALUE;
3494
3495 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3496 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3497
3498 filter = &peer->filter[afi][safi];
3499
3500 /* apply peer-group filter */
3501 if (peer->af_group[afi][safi])
3502 {
3503 gfilter = &peer->group->conf->filter[afi][safi];
3504
3505 if (gfilter->plist[direct].name)
3506 {
3507 if (filter->plist[direct].name)
3508 free (filter->plist[direct].name);
3509 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3510 filter->plist[direct].plist = gfilter->plist[direct].plist;
3511 return 0;
3512 }
3513 }
3514
3515 if (filter->plist[direct].name)
3516 free (filter->plist[direct].name);
3517 filter->plist[direct].name = NULL;
3518 filter->plist[direct].plist = NULL;
3519
3520 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3521 return 0;
3522
3523 group = peer->group;
3524 LIST_LOOP (group->peer, peer, nn)
3525 {
3526 filter = &peer->filter[afi][safi];
3527
3528 if (! peer->af_group[afi][safi])
3529 continue;
3530
3531 if (filter->plist[direct].name)
3532 free (filter->plist[direct].name);
3533 filter->plist[direct].name = NULL;
3534 filter->plist[direct].plist = NULL;
3535 }
3536
3537 return 0;
3538}
3539
3540/* Update prefix-list list. */
3541void
3542peer_prefix_list_update (struct prefix_list *plist)
3543{
3544 struct listnode *nn, *nm;
3545 struct bgp *bgp;
3546 struct peer *peer;
3547 struct peer_group *group;
3548 struct bgp_filter *filter;
3549 afi_t afi;
3550 safi_t safi;
3551 int direct;
3552
3553 LIST_LOOP (bm->bgp, bgp, nn)
3554 {
3555 LIST_LOOP (bgp->peer, peer, nm)
3556 {
3557 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3558 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3559 {
3560 filter = &peer->filter[afi][safi];
3561
3562 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3563 {
3564 if (filter->plist[direct].name)
3565 filter->plist[direct].plist =
3566 prefix_list_lookup (afi, filter->plist[direct].name);
3567 else
3568 filter->plist[direct].plist = NULL;
3569 }
3570 }
3571 }
3572 LIST_LOOP (bgp->group, group, nm)
3573 {
3574 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3575 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3576 {
3577 filter = &group->conf->filter[afi][safi];
3578
3579 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3580 {
3581 if (filter->plist[direct].name)
3582 filter->plist[direct].plist =
3583 prefix_list_lookup (afi, filter->plist[direct].name);
3584 else
3585 filter->plist[direct].plist = NULL;
3586 }
3587 }
3588 }
3589 }
3590}
3591
3592int
3593peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003594 const char *name)
paul718e3742002-12-13 20:15:29 +00003595{
3596 struct bgp_filter *filter;
3597 struct peer_group *group;
3598 struct listnode *nn;
3599
3600 if (! peer->afc[afi][safi])
3601 return BGP_ERR_PEER_INACTIVE;
3602
3603 if (direct != FILTER_IN && direct != FILTER_OUT)
3604 return BGP_ERR_INVALID_VALUE;
3605
3606 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3607 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3608
3609 filter = &peer->filter[afi][safi];
3610
3611 if (filter->aslist[direct].name)
3612 free (filter->aslist[direct].name);
3613 filter->aslist[direct].name = strdup (name);
3614 filter->aslist[direct].aslist = as_list_lookup (name);
3615
3616 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3617 return 0;
3618
3619 group = peer->group;
3620 LIST_LOOP (group->peer, peer, nn)
3621 {
3622 filter = &peer->filter[afi][safi];
3623
3624 if (! peer->af_group[afi][safi])
3625 continue;
3626
3627 if (filter->aslist[direct].name)
3628 free (filter->aslist[direct].name);
3629 filter->aslist[direct].name = strdup (name);
3630 filter->aslist[direct].aslist = as_list_lookup (name);
3631 }
3632 return 0;
3633}
3634
3635int
3636peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3637{
3638 struct bgp_filter *filter;
3639 struct bgp_filter *gfilter;
3640 struct peer_group *group;
3641 struct listnode *nn;
3642
3643 if (! peer->afc[afi][safi])
3644 return BGP_ERR_PEER_INACTIVE;
3645
paulfee0f4c2004-09-13 05:12:46 +00003646 if (direct != RMAP_IN && direct != RMAP_OUT &&
3647 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003648 return BGP_ERR_INVALID_VALUE;
3649
paulfee0f4c2004-09-13 05:12:46 +00003650 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
3651 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003652 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3653
3654 filter = &peer->filter[afi][safi];
3655
3656 /* apply peer-group filter */
3657 if (peer->af_group[afi][safi])
3658 {
3659 gfilter = &peer->group->conf->filter[afi][safi];
3660
3661 if (gfilter->aslist[direct].name)
3662 {
3663 if (filter->aslist[direct].name)
3664 free (filter->aslist[direct].name);
3665 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
3666 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
3667 return 0;
3668 }
3669 }
3670
3671 if (filter->aslist[direct].name)
3672 free (filter->aslist[direct].name);
3673 filter->aslist[direct].name = NULL;
3674 filter->aslist[direct].aslist = NULL;
3675
3676 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3677 return 0;
3678
3679 group = peer->group;
3680 LIST_LOOP (group->peer, peer, nn)
3681 {
3682 filter = &peer->filter[afi][safi];
3683
3684 if (! peer->af_group[afi][safi])
3685 continue;
3686
3687 if (filter->aslist[direct].name)
3688 free (filter->aslist[direct].name);
3689 filter->aslist[direct].name = NULL;
3690 filter->aslist[direct].aslist = NULL;
3691 }
3692
3693 return 0;
3694}
3695
3696void
3697peer_aslist_update ()
3698{
3699 afi_t afi;
3700 safi_t safi;
3701 int direct;
3702 struct listnode *nn, *nm;
3703 struct bgp *bgp;
3704 struct peer *peer;
3705 struct peer_group *group;
3706 struct bgp_filter *filter;
3707
3708 LIST_LOOP (bm->bgp, bgp, nn)
3709 {
3710 LIST_LOOP (bgp->peer, peer, nm)
3711 {
3712 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3713 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3714 {
3715 filter = &peer->filter[afi][safi];
3716
3717 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3718 {
3719 if (filter->aslist[direct].name)
3720 filter->aslist[direct].aslist =
3721 as_list_lookup (filter->aslist[direct].name);
3722 else
3723 filter->aslist[direct].aslist = NULL;
3724 }
3725 }
3726 }
3727 LIST_LOOP (bgp->group, group, nm)
3728 {
3729 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3730 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3731 {
3732 filter = &group->conf->filter[afi][safi];
3733
3734 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3735 {
3736 if (filter->aslist[direct].name)
3737 filter->aslist[direct].aslist =
3738 as_list_lookup (filter->aslist[direct].name);
3739 else
3740 filter->aslist[direct].aslist = NULL;
3741 }
3742 }
3743 }
3744 }
3745}
3746
3747/* Set route-map to the peer. */
3748int
3749peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003750 const char *name)
paul718e3742002-12-13 20:15:29 +00003751{
3752 struct bgp_filter *filter;
3753 struct peer_group *group;
3754 struct listnode *nn;
3755
3756 if (! peer->afc[afi][safi])
3757 return BGP_ERR_PEER_INACTIVE;
3758
paulfee0f4c2004-09-13 05:12:46 +00003759 if (direct != RMAP_IN && direct != RMAP_OUT &&
3760 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003761 return BGP_ERR_INVALID_VALUE;
3762
paulfee0f4c2004-09-13 05:12:46 +00003763 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
3764 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003765 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3766
3767 filter = &peer->filter[afi][safi];
3768
3769 if (filter->map[direct].name)
3770 free (filter->map[direct].name);
3771
3772 filter->map[direct].name = strdup (name);
3773 filter->map[direct].map = route_map_lookup_by_name (name);
3774
3775 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3776 return 0;
3777
3778 group = peer->group;
3779 LIST_LOOP (group->peer, peer, nn)
3780 {
3781 filter = &peer->filter[afi][safi];
3782
3783 if (! peer->af_group[afi][safi])
3784 continue;
3785
3786 if (filter->map[direct].name)
3787 free (filter->map[direct].name);
3788 filter->map[direct].name = strdup (name);
3789 filter->map[direct].map = route_map_lookup_by_name (name);
3790 }
3791 return 0;
3792}
3793
3794/* Unset route-map from the peer. */
3795int
3796peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3797{
3798 struct bgp_filter *filter;
3799 struct bgp_filter *gfilter;
3800 struct peer_group *group;
3801 struct listnode *nn;
3802
3803 if (! peer->afc[afi][safi])
3804 return BGP_ERR_PEER_INACTIVE;
3805
3806 if (direct != FILTER_IN && direct != FILTER_OUT)
3807 return BGP_ERR_INVALID_VALUE;
3808
3809 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3810 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3811
3812 filter = &peer->filter[afi][safi];
3813
3814 /* apply peer-group filter */
3815 if (peer->af_group[afi][safi])
3816 {
3817 gfilter = &peer->group->conf->filter[afi][safi];
3818
3819 if (gfilter->map[direct].name)
3820 {
3821 if (filter->map[direct].name)
3822 free (filter->map[direct].name);
3823 filter->map[direct].name = strdup (gfilter->map[direct].name);
3824 filter->map[direct].map = gfilter->map[direct].map;
3825 return 0;
3826 }
3827 }
3828
3829 if (filter->map[direct].name)
3830 free (filter->map[direct].name);
3831 filter->map[direct].name = NULL;
3832 filter->map[direct].map = NULL;
3833
3834 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3835 return 0;
3836
3837 group = peer->group;
3838 LIST_LOOP (group->peer, peer, nn)
3839 {
3840 filter = &peer->filter[afi][safi];
3841
3842 if (! peer->af_group[afi][safi])
3843 continue;
3844
3845 if (filter->map[direct].name)
3846 free (filter->map[direct].name);
3847 filter->map[direct].name = NULL;
3848 filter->map[direct].map = NULL;
3849 }
3850 return 0;
3851}
3852
3853/* Set unsuppress-map to the peer. */
3854int
paulfd79ac92004-10-13 05:06:08 +00003855peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
3856 const char *name)
paul718e3742002-12-13 20:15:29 +00003857{
3858 struct bgp_filter *filter;
3859 struct peer_group *group;
3860 struct listnode *nn;
3861
3862 if (! peer->afc[afi][safi])
3863 return BGP_ERR_PEER_INACTIVE;
3864
3865 if (peer_is_group_member (peer, afi, safi))
3866 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3867
3868 filter = &peer->filter[afi][safi];
3869
3870 if (filter->usmap.name)
3871 free (filter->usmap.name);
3872
3873 filter->usmap.name = strdup (name);
3874 filter->usmap.map = route_map_lookup_by_name (name);
3875
3876 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3877 return 0;
3878
3879 group = peer->group;
3880 LIST_LOOP (group->peer, peer, nn)
3881 {
3882 filter = &peer->filter[afi][safi];
3883
3884 if (! peer->af_group[afi][safi])
3885 continue;
3886
3887 if (filter->usmap.name)
3888 free (filter->usmap.name);
3889 filter->usmap.name = strdup (name);
3890 filter->usmap.map = route_map_lookup_by_name (name);
3891 }
3892 return 0;
3893}
3894
3895/* Unset route-map from the peer. */
3896int
3897peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
3898{
3899 struct bgp_filter *filter;
3900 struct peer_group *group;
3901 struct listnode *nn;
3902
3903 if (! peer->afc[afi][safi])
3904 return BGP_ERR_PEER_INACTIVE;
3905
3906 if (peer_is_group_member (peer, afi, safi))
3907 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3908
3909 filter = &peer->filter[afi][safi];
3910
3911 if (filter->usmap.name)
3912 free (filter->usmap.name);
3913 filter->usmap.name = NULL;
3914 filter->usmap.map = NULL;
3915
3916 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3917 return 0;
3918
3919 group = peer->group;
3920 LIST_LOOP (group->peer, peer, nn)
3921 {
3922 filter = &peer->filter[afi][safi];
3923
3924 if (! peer->af_group[afi][safi])
3925 continue;
3926
3927 if (filter->usmap.name)
3928 free (filter->usmap.name);
3929 filter->usmap.name = NULL;
3930 filter->usmap.map = NULL;
3931 }
3932 return 0;
3933}
3934
3935int
3936peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00003937 u_int32_t max, u_char threshold,
3938 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00003939{
3940 struct peer_group *group;
3941 struct listnode *nn;
3942
3943 if (! peer->afc[afi][safi])
3944 return BGP_ERR_PEER_INACTIVE;
3945
3946 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3947 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00003948 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00003949 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00003950 if (warning)
3951 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3952 else
3953 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3954
3955 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3956 return 0;
3957
3958 group = peer->group;
3959 LIST_LOOP (group->peer, peer, nn)
3960 {
3961 if (! peer->af_group[afi][safi])
3962 continue;
3963
3964 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3965 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00003966 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00003967 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00003968 if (warning)
3969 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3970 else
3971 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3972 }
3973 return 0;
3974}
3975
3976int
3977peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
3978{
3979 struct peer_group *group;
3980 struct listnode *nn;
3981
3982 if (! peer->afc[afi][safi])
3983 return BGP_ERR_PEER_INACTIVE;
3984
3985 /* apply peer-group config */
3986 if (peer->af_group[afi][safi])
3987 {
3988 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
3989 PEER_FLAG_MAX_PREFIX))
3990 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3991 else
3992 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3993
3994 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
3995 PEER_FLAG_MAX_PREFIX_WARNING))
3996 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3997 else
3998 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3999
4000 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004001 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004002 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004003 return 0;
4004 }
4005
4006 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4007 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4008 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004009 peer->pmax_threshold[afi][safi] = 0;
4010 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004011
4012 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4013 return 0;
4014
4015 group = peer->group;
4016 LIST_LOOP (group->peer, peer, nn)
4017 {
4018 if (! peer->af_group[afi][safi])
4019 continue;
4020
4021 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4022 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4023 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004024 peer->pmax_threshold[afi][safi] = 0;
4025 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004026 }
4027 return 0;
4028}
4029
4030int
4031peer_clear (struct peer *peer)
4032{
4033 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4034 {
hasso0a486e52005-02-01 20:57:17 +00004035 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4036 {
4037 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4038 if (peer->t_pmax_restart)
4039 {
4040 BGP_TIMER_OFF (peer->t_pmax_restart);
4041 if (BGP_DEBUG (events, EVENTS))
4042 zlog_debug ("%s Maximum-prefix restart timer canceled",
4043 peer->host);
4044 }
4045 BGP_EVENT_ADD (peer, BGP_Start);
4046 return 0;
4047 }
4048
paul718e3742002-12-13 20:15:29 +00004049 peer->v_start = BGP_INIT_START_TIMER;
4050 if (peer->status == Established)
4051 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4052 BGP_NOTIFY_CEASE_ADMIN_RESET);
4053 else
4054 BGP_EVENT_ADD (peer, BGP_Stop);
4055 }
4056 return 0;
4057}
4058
4059int
4060peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4061 enum bgp_clear_type stype)
4062{
4063 if (peer->status != Established)
4064 return 0;
4065
4066 if (! peer->afc[afi][safi])
4067 return BGP_ERR_AF_UNCONFIGURED;
4068
paulfee0f4c2004-09-13 05:12:46 +00004069 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4070 {
4071 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4072 return 0;
4073 bgp_check_local_routes_rsclient (peer, afi, safi);
4074 bgp_soft_reconfig_rsclient (peer, afi, safi);
4075 }
4076
paul718e3742002-12-13 20:15:29 +00004077 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4078 bgp_announce_route (peer, afi, safi);
4079
4080 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4081 {
4082 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4083 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4084 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4085 {
4086 struct bgp_filter *filter = &peer->filter[afi][safi];
4087 u_char prefix_type;
4088
4089 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4090 prefix_type = ORF_TYPE_PREFIX;
4091 else
4092 prefix_type = ORF_TYPE_PREFIX_OLD;
4093
4094 if (filter->plist[FILTER_IN].plist)
4095 {
4096 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4097 bgp_route_refresh_send (peer, afi, safi,
4098 prefix_type, REFRESH_DEFER, 1);
4099 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4100 REFRESH_IMMEDIATE, 0);
4101 }
4102 else
4103 {
4104 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4105 bgp_route_refresh_send (peer, afi, safi,
4106 prefix_type, REFRESH_IMMEDIATE, 1);
4107 else
4108 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4109 }
4110 return 0;
4111 }
4112 }
4113
4114 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4115 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4116 {
4117 /* If neighbor has soft reconfiguration inbound flag.
4118 Use Adj-RIB-In database. */
4119 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4120 bgp_soft_reconfig_in (peer, afi, safi);
4121 else
4122 {
4123 /* If neighbor has route refresh capability, send route refresh
4124 message to the peer. */
4125 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4126 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4127 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4128 else
4129 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4130 }
4131 }
4132 return 0;
4133}
4134
paulfd79ac92004-10-13 05:06:08 +00004135/* Display peer uptime.*/
4136/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004137char *
4138peer_uptime (time_t uptime2, char *buf, size_t len)
4139{
4140 time_t uptime1;
4141 struct tm *tm;
4142
4143 /* Check buffer length. */
4144 if (len < BGP_UPTIME_LEN)
4145 {
gdtc29fdba2004-12-09 14:46:46 +00004146 /* XXX: warning: long int format, size_t arg (arg 2) */
paula2b1ecd2004-10-31 18:58:09 +00004147 zlog_warn ("peer_uptime (): buffer shortage %ld", len);
paulfd79ac92004-10-13 05:06:08 +00004148 /* XXX: should return status instead of buf... */
4149 snprintf (buf, len, "<error> ");
4150 return buf;
paul718e3742002-12-13 20:15:29 +00004151 }
4152
4153 /* If there is no connection has been done before print `never'. */
4154 if (uptime2 == 0)
4155 {
4156 snprintf (buf, len, "never ");
4157 return buf;
4158 }
4159
4160 /* Get current time. */
4161 uptime1 = time (NULL);
4162 uptime1 -= uptime2;
4163 tm = gmtime (&uptime1);
4164
4165 /* Making formatted timer strings. */
4166#define ONE_DAY_SECOND 60*60*24
4167#define ONE_WEEK_SECOND 60*60*24*7
4168
4169 if (uptime1 < ONE_DAY_SECOND)
4170 snprintf (buf, len, "%02d:%02d:%02d",
4171 tm->tm_hour, tm->tm_min, tm->tm_sec);
4172 else if (uptime1 < ONE_WEEK_SECOND)
4173 snprintf (buf, len, "%dd%02dh%02dm",
4174 tm->tm_yday, tm->tm_hour, tm->tm_min);
4175 else
4176 snprintf (buf, len, "%02dw%dd%02dh",
4177 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4178 return buf;
4179}
4180
4181void
4182bgp_config_write_filter (struct vty *vty, struct peer *peer,
4183 afi_t afi, safi_t safi)
4184{
4185 struct bgp_filter *filter;
4186 struct bgp_filter *gfilter = NULL;
4187 char *addr;
4188 int in = FILTER_IN;
4189 int out = FILTER_OUT;
4190
4191 addr = peer->host;
4192 filter = &peer->filter[afi][safi];
4193 if (peer->af_group[afi][safi])
4194 gfilter = &peer->group->conf->filter[afi][safi];
4195
4196 /* distribute-list. */
4197 if (filter->dlist[in].name)
4198 if (! gfilter || ! gfilter->dlist[in].name
4199 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4200 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4201 filter->dlist[in].name, VTY_NEWLINE);
4202 if (filter->dlist[out].name && ! gfilter)
4203 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4204 filter->dlist[out].name, VTY_NEWLINE);
4205
4206 /* prefix-list. */
4207 if (filter->plist[in].name)
4208 if (! gfilter || ! gfilter->plist[in].name
4209 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4210 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4211 filter->plist[in].name, VTY_NEWLINE);
4212 if (filter->plist[out].name && ! gfilter)
4213 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4214 filter->plist[out].name, VTY_NEWLINE);
4215
4216 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004217 if (filter->map[RMAP_IN].name)
4218 if (! gfilter || ! gfilter->map[RMAP_IN].name
4219 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004220 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004221 filter->map[RMAP_IN].name, VTY_NEWLINE);
4222 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004223 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004224 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4225 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4226 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4227 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4228 if (filter->map[RMAP_EXPORT].name)
4229 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4230 || strcmp (filter->map[RMAP_EXPORT].name,
4231 gfilter->map[RMAP_EXPORT].name) != 0)
4232 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4233 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004234
4235 /* unsuppress-map */
4236 if (filter->usmap.name && ! gfilter)
4237 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4238 filter->usmap.name, VTY_NEWLINE);
4239
4240 /* filter-list. */
4241 if (filter->aslist[in].name)
4242 if (! gfilter || ! gfilter->aslist[in].name
4243 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4244 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4245 filter->aslist[in].name, VTY_NEWLINE);
4246 if (filter->aslist[out].name && ! gfilter)
4247 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4248 filter->aslist[out].name, VTY_NEWLINE);
4249}
4250
4251/* BGP peer configuration display function. */
4252void
4253bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4254 struct peer *peer, afi_t afi, safi_t safi)
4255{
4256 struct bgp_filter *filter;
4257 struct peer *g_peer = NULL;
4258 char buf[SU_ADDRSTRLEN];
4259 char *addr;
4260
4261 filter = &peer->filter[afi][safi];
4262 addr = peer->host;
4263 if (peer_group_active (peer))
4264 g_peer = peer->group->conf;
4265
4266 /************************************
4267 ****** Global to the neighbor ******
4268 ************************************/
4269 if (afi == AFI_IP && safi == SAFI_UNICAST)
4270 {
4271 /* remote-as. */
4272 if (! peer_group_active (peer))
4273 {
4274 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4275 vty_out (vty, " neighbor %s peer-group%s", addr,
4276 VTY_NEWLINE);
4277 if (peer->as)
4278 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4279 VTY_NEWLINE);
4280 }
4281 else
4282 {
4283 if (! g_peer->as)
4284 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4285 VTY_NEWLINE);
4286 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4287 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4288 peer->group->name, VTY_NEWLINE);
4289 }
4290
4291 /* local-as. */
4292 if (peer->change_local_as)
4293 if (! peer_group_active (peer))
4294 vty_out (vty, " neighbor %s local-as %d%s%s", addr,
4295 peer->change_local_as,
4296 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4297 " no-prepend" : "", VTY_NEWLINE);
4298
4299 /* Description. */
4300 if (peer->desc)
4301 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4302 VTY_NEWLINE);
4303
4304 /* Shutdown. */
4305 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4306 if (! peer_group_active (peer) ||
4307 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4308 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4309
4310 /* BGP port. */
4311 if (peer->port != BGP_PORT_DEFAULT)
4312 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
4313 VTY_NEWLINE);
4314
4315 /* Local interface name. */
4316 if (peer->ifname)
4317 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4318 VTY_NEWLINE);
4319
4320 /* Passive. */
4321 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4322 if (! peer_group_active (peer) ||
4323 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4324 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4325
4326 /* EBGP multihop. */
4327 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
4328 if (! peer_group_active (peer) ||
4329 g_peer->ttl != peer->ttl)
4330 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4331 VTY_NEWLINE);
4332
4333 /* Enforce multihop. */
4334 if (CHECK_FLAG (peer->flags, PEER_FLAG_ENFORCE_MULTIHOP))
4335 if (! peer_group_active (peer) ||
4336 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_ENFORCE_MULTIHOP))
4337 vty_out (vty, " neighbor %s enforce-multihop%s", addr, VTY_NEWLINE);
4338
4339 /* Update-source. */
4340 if (peer->update_if)
4341 if (! peer_group_active (peer) || ! g_peer->update_if
4342 || strcmp (g_peer->update_if, peer->update_if) != 0)
4343 vty_out (vty, " neighbor %s update-source %s%s", addr,
4344 peer->update_if, VTY_NEWLINE);
4345 if (peer->update_source)
4346 if (! peer_group_active (peer) || ! g_peer->update_source
4347 || sockunion_cmp (g_peer->update_source,
4348 peer->update_source) != 0)
4349 vty_out (vty, " neighbor %s update-source %s%s", addr,
4350 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4351 VTY_NEWLINE);
4352
4353 /* BGP version print. */
4354 if (peer->version == BGP_VERSION_MP_4_DRAFT_00)
4355 vty_out (vty, " neighbor %s version %s%s",
4356 addr,"4-", VTY_NEWLINE);
4357
4358 /* advertisement-interval */
4359 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4360 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4361 addr, peer->v_routeadv, VTY_NEWLINE);
4362
4363 /* timers. */
4364 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4365 && ! peer_group_active (peer))
4366 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4367 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4368
4369 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4370 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4371 peer->connect, VTY_NEWLINE);
4372
4373 /* Default weight. */
4374 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4375 if (! peer_group_active (peer) ||
4376 g_peer->weight != peer->weight)
4377 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4378 VTY_NEWLINE);
4379
4380 /* Route refresh. */
4381 if (CHECK_FLAG (peer->flags, PEER_FLAG_NO_ROUTE_REFRESH_CAP))
4382 if (! peer_group_active (peer) ||
4383 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_NO_ROUTE_REFRESH_CAP))
4384 vty_out (vty, " no neighbor %s capability route-refresh%s", addr,
4385 VTY_NEWLINE);
4386
4387 /* Dynamic capability. */
4388 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4389 if (! peer_group_active (peer) ||
4390 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4391 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4392 VTY_NEWLINE);
4393
4394 /* dont capability negotiation. */
4395 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4396 if (! peer_group_active (peer) ||
4397 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4398 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4399 VTY_NEWLINE);
4400
4401 /* override capability negotiation. */
4402 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4403 if (! peer_group_active (peer) ||
4404 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4405 vty_out (vty, " neighbor %s override-capability%s", addr,
4406 VTY_NEWLINE);
4407
4408 /* strict capability negotiation. */
4409 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4410 if (! peer_group_active (peer) ||
4411 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4412 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4413 VTY_NEWLINE);
4414
4415 if (! peer_group_active (peer))
4416 {
4417 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4418 {
4419 if (peer->afc[AFI_IP][SAFI_UNICAST])
4420 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4421 }
4422 else
4423 {
4424 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4425 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4426 }
4427 }
4428 }
4429
4430
4431 /************************************
4432 ****** Per AF to the neighbor ******
4433 ************************************/
4434
4435 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4436 {
4437 if (peer->af_group[afi][safi])
4438 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4439 peer->group->name, VTY_NEWLINE);
4440 else
4441 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4442 }
4443
4444 /* ORF capability. */
4445 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4446 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4447 if (! peer->af_group[afi][safi])
4448 {
4449 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4450
4451 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4452 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4453 vty_out (vty, " both");
4454 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4455 vty_out (vty, " send");
4456 else
4457 vty_out (vty, " receive");
4458 vty_out (vty, "%s", VTY_NEWLINE);
4459 }
4460
4461 /* Route reflector client. */
4462 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4463 && ! peer->af_group[afi][safi])
4464 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4465 VTY_NEWLINE);
4466
4467 /* Nexthop self. */
4468 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4469 && ! peer->af_group[afi][safi])
4470 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4471
4472 /* Remove private AS. */
4473 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4474 && ! peer->af_group[afi][safi])
4475 vty_out (vty, " neighbor %s remove-private-AS%s",
4476 addr, VTY_NEWLINE);
4477
4478 /* send-community print. */
4479 if (! peer->af_group[afi][safi])
4480 {
4481 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4482 {
4483 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4484 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4485 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4486 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4487 vty_out (vty, " neighbor %s send-community extended%s",
4488 addr, VTY_NEWLINE);
4489 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4490 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4491 }
4492 else
4493 {
4494 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4495 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4496 vty_out (vty, " no neighbor %s send-community both%s",
4497 addr, VTY_NEWLINE);
4498 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4499 vty_out (vty, " no neighbor %s send-community extended%s",
4500 addr, VTY_NEWLINE);
4501 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4502 vty_out (vty, " no neighbor %s send-community%s",
4503 addr, VTY_NEWLINE);
4504 }
4505 }
4506
4507 /* Default information */
4508 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4509 && ! peer->af_group[afi][safi])
4510 {
4511 vty_out (vty, " neighbor %s default-originate", addr);
4512 if (peer->default_rmap[afi][safi].name)
4513 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4514 vty_out (vty, "%s", VTY_NEWLINE);
4515 }
4516
4517 /* Soft reconfiguration inbound. */
4518 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4519 if (! peer->af_group[afi][safi] ||
4520 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4521 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4522 VTY_NEWLINE);
4523
4524 /* maximum-prefix. */
4525 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4526 if (! peer->af_group[afi][safi]
4527 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004528 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004529 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4530 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00004531 {
hasso0a486e52005-02-01 20:57:17 +00004532 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
4533 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
4534 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
4535 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
4536 vty_out (vty, " warning-only");
4537 if (peer->pmax_restart[afi][safi])
4538 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
4539 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00004540 }
paul718e3742002-12-13 20:15:29 +00004541
4542 /* Route server client. */
4543 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
4544 && ! peer->af_group[afi][safi])
4545 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
4546
4547 /* Allow AS in. */
4548 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
4549 if (! peer_group_active (peer)
4550 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
4551 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
4552 {
4553 if (peer->allowas_in[afi][safi] == 3)
4554 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
4555 else
4556 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
4557 peer->allowas_in[afi][safi], VTY_NEWLINE);
4558 }
4559
4560 /* Filter. */
4561 bgp_config_write_filter (vty, peer, afi, safi);
4562
4563 /* atribute-unchanged. */
4564 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4565 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4566 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4567 && ! peer->af_group[afi][safi])
4568 {
4569 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4570 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4571 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4572 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
4573 else
4574 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
4575 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
4576 " as-path" : "",
4577 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
4578 " next-hop" : "",
4579 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
4580 " med" : "", VTY_NEWLINE);
4581 }
4582}
4583
4584/* Display "address-family" configuration header. */
4585void
4586bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
4587 int *write)
4588{
4589 if (*write)
4590 return;
4591
4592 if (afi == AFI_IP && safi == SAFI_UNICAST)
4593 return;
4594
4595 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
4596
4597 if (afi == AFI_IP)
4598 {
4599 if (safi == SAFI_MULTICAST)
4600 vty_out (vty, "ipv4 multicast");
4601 else if (safi == SAFI_MPLS_VPN)
4602 vty_out (vty, "vpnv4 unicast");
4603 }
4604 else if (afi == AFI_IP6)
4605 vty_out (vty, "ipv6");
4606
4607 vty_out (vty, "%s", VTY_NEWLINE);
4608
4609 *write = 1;
4610}
4611
4612/* Address family based peer configuration display. */
4613int
4614bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
4615 safi_t safi)
4616{
4617 int write = 0;
4618 struct peer *peer;
4619 struct peer_group *group;
4620 struct listnode *nn;
4621
4622 bgp_config_write_network (vty, bgp, afi, safi, &write);
4623
4624 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
4625
4626 LIST_LOOP (bgp->group, group, nn)
4627 {
4628 if (group->conf->afc[afi][safi])
4629 {
4630 bgp_config_write_family_header (vty, afi, safi, &write);
4631 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
4632 }
4633 }
4634 LIST_LOOP (bgp->peer, peer, nn)
4635 {
4636 if (peer->afc[afi][safi])
4637 {
4638 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4639 {
4640 bgp_config_write_family_header (vty, afi, safi, &write);
4641 bgp_config_write_peer (vty, bgp, peer, afi, safi);
4642 }
4643 }
4644 }
4645 if (write)
4646 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
4647
4648 return write;
4649}
4650
4651int
4652bgp_config_write (struct vty *vty)
4653{
4654 int write = 0;
4655 struct bgp *bgp;
4656 struct peer_group *group;
4657 struct peer *peer;
4658 struct listnode *nn, *nm, *no;
4659
4660 /* BGP Multiple instance. */
4661 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4662 {
4663 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
4664 write++;
4665 }
4666
4667 /* BGP Config type. */
4668 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4669 {
4670 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
4671 write++;
4672 }
4673
4674 /* BGP configuration. */
4675 LIST_LOOP (bm->bgp, bgp, nn)
4676 {
4677 if (write)
4678 vty_out (vty, "!%s", VTY_NEWLINE);
4679
4680 /* Router bgp ASN */
4681 vty_out (vty, "router bgp %d", bgp->as);
4682
4683 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4684 {
4685 if (bgp->name)
4686 vty_out (vty, " view %s", bgp->name);
4687 }
4688 vty_out (vty, "%s", VTY_NEWLINE);
4689
4690 /* No Synchronization */
4691 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4692 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
4693
4694 /* BGP fast-external-failover. */
4695 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
4696 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
4697
4698 /* BGP router ID. */
4699 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
4700 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
4701 VTY_NEWLINE);
4702
paul848973c2003-08-13 00:32:49 +00004703 /* BGP log-neighbor-changes. */
4704 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
4705 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
4706
paul718e3742002-12-13 20:15:29 +00004707 /* BGP configuration. */
4708 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
4709 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
4710
4711 /* BGP default ipv4-unicast. */
4712 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4713 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
4714
4715 /* BGP default local-preference. */
4716 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
4717 vty_out (vty, " bgp default local-preference %d%s",
4718 bgp->default_local_pref, VTY_NEWLINE);
4719
4720 /* BGP client-to-client reflection. */
4721 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
4722 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
4723
4724 /* BGP cluster ID. */
4725 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
4726 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
4727 VTY_NEWLINE);
4728
hassoe0701b72004-05-20 09:19:34 +00004729 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00004730 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00004731 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
4732 VTY_NEWLINE);
4733
4734 /* Confederation peer */
4735 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00004736 {
hassoe0701b72004-05-20 09:19:34 +00004737 int i;
paul718e3742002-12-13 20:15:29 +00004738
hassoe0701b72004-05-20 09:19:34 +00004739 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00004740
hassoe0701b72004-05-20 09:19:34 +00004741 for (i = 0; i < bgp->confed_peers_cnt; i++)
4742 vty_out(vty, " %d", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00004743
hassoe0701b72004-05-20 09:19:34 +00004744 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004745 }
4746
4747 /* BGP enforce-first-as. */
4748 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
4749 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
4750
4751 /* BGP deterministic-med. */
4752 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
4753 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00004754
4755 /* BGP graceful-restart. */
4756 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
4757 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
4758
paul718e3742002-12-13 20:15:29 +00004759 /* BGP bestpath method. */
4760 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
4761 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
4762 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
4763 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
4764 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
4765 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4766 {
4767 vty_out (vty, " bgp bestpath med");
4768 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
4769 vty_out (vty, " confed");
4770 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4771 vty_out (vty, " missing-as-worst");
4772 vty_out (vty, "%s", VTY_NEWLINE);
4773 }
4774
4775 /* BGP network import check. */
4776 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
4777 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
4778
4779 /* BGP scan interval. */
4780 bgp_config_write_scan_time (vty);
4781
4782 /* BGP flag dampening. */
4783 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
4784 BGP_CONFIG_DAMPENING))
4785 bgp_config_write_damp (vty);
4786
4787 /* BGP static route configuration. */
4788 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4789
4790 /* BGP redistribute configuration. */
4791 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4792
4793 /* BGP timers configuration. */
4794 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
4795 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
4796 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
4797 bgp->default_holdtime, VTY_NEWLINE);
4798
4799 /* peer-group */
4800 LIST_LOOP (bgp->group, group, nm)
4801 {
4802 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
4803 }
4804
4805 /* Normal neighbor configuration. */
4806 LIST_LOOP (bgp->peer, peer, no)
4807 {
4808 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4809 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
4810 }
4811
4812 /* Distance configuration. */
4813 bgp_config_write_distance (vty, bgp);
4814
4815 /* No auto-summary */
4816 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4817 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
4818
4819 /* IPv4 multicast configuration. */
4820 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
4821
4822 /* IPv4 VPN configuration. */
4823 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
4824
4825 /* IPv6 unicast configuration. */
4826 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
4827
4828 write++;
4829 }
4830 return write;
4831}
4832
4833void
4834bgp_master_init ()
4835{
4836 memset (&bgp_master, 0, sizeof (struct bgp_master));
4837
4838 bm = &bgp_master;
4839 bm->bgp = list_new ();
4840 bm->port = BGP_PORT_DEFAULT;
4841 bm->master = thread_master_create ();
4842 bm->start_time = time (NULL);
4843}
4844
4845void
4846bgp_init ()
4847{
4848 void bgp_zebra_init ();
4849 void bgp_route_map_init ();
4850 void bgp_filter_init ();
4851
4852 /* BGP VTY commands installation. */
4853 bgp_vty_init ();
4854
4855 /* Create BGP server socket. */
4856 bgp_socket (NULL, bm->port);
4857
4858 /* Init zebra. */
4859 bgp_zebra_init ();
4860
4861 /* BGP inits. */
4862 bgp_attr_init ();
4863 bgp_debug_init ();
4864 bgp_dump_init ();
4865 bgp_route_init ();
4866 bgp_route_map_init ();
4867 bgp_scan_init ();
4868 bgp_mplsvpn_init ();
4869
4870 /* Access list initialize. */
4871 access_list_init ();
4872 access_list_add_hook (peer_distribute_update);
4873 access_list_delete_hook (peer_distribute_update);
4874
4875 /* Filter list initialize. */
4876 bgp_filter_init ();
4877 as_list_add_hook (peer_aslist_update);
4878 as_list_delete_hook (peer_aslist_update);
4879
4880 /* Prefix list initialize.*/
4881 prefix_list_init ();
4882 prefix_list_add_hook (peer_prefix_list_update);
4883 prefix_list_delete_hook (peer_prefix_list_update);
4884
4885 /* Community list initialize. */
4886 bgp_clist = community_list_init ();
4887
4888#ifdef HAVE_SNMP
4889 bgp_snmp_init ();
4890#endif /* HAVE_SNMP */
4891}
paul545acaf2004-04-20 15:13:15 +00004892
4893void
4894bgp_terminate ()
4895{
paul545acaf2004-04-20 15:13:15 +00004896 struct bgp *bgp;
4897 struct peer *peer;
4898 struct listnode *nn;
4899 struct listnode *mm;
4900
paul545acaf2004-04-20 15:13:15 +00004901 LIST_LOOP (bm->bgp, bgp, nn)
4902 LIST_LOOP (bgp->peer, peer, mm)
4903 if (peer->status == Established)
4904 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4905 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
4906
4907 bgp_cleanup_routes ();
4908}
4909