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