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