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