blob: 510e2960d1c8de4be3b8164ac85d2b7a4205bbb5 [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
518 bgp_config_set (bgp, BGP_CONFIG_DEFAULT_LOCAL_PREF);
519 bgp->default_local_pref = local_pref;
520
521 return 0;
522}
523
524int
525bgp_default_local_preference_unset (struct bgp *bgp)
526{
527 if (! bgp)
528 return -1;
529
530 bgp_config_unset (bgp, BGP_CONFIG_DEFAULT_LOCAL_PREF);
531 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
532
533 return 0;
534}
535
pauleb821182004-05-01 08:44:08 +0000536/* Peer comparison function for sorting. */
paul718e3742002-12-13 20:15:29 +0000537static int
538peer_cmp (struct peer *p1, struct peer *p2)
539{
pauleb821182004-05-01 08:44:08 +0000540 return sockunion_cmp (&p1->su, &p2->su);
paul718e3742002-12-13 20:15:29 +0000541}
542
543int
544peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
545{
546 return CHECK_FLAG (peer->af_flags[afi][safi], flag);
547}
548
549/* Reset all address family specific configuration. */
550static void
551peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
552{
553 int i;
554 struct bgp_filter *filter;
555 char orf_name[BUFSIZ];
556
557 filter = &peer->filter[afi][safi];
558
559 /* Clear neighbor filter and route-map */
560 for (i = FILTER_IN; i < FILTER_MAX; i++)
561 {
562 if (filter->dlist[i].name)
563 {
564 free (filter->dlist[i].name);
565 filter->dlist[i].name = NULL;
566 }
567 if (filter->plist[i].name)
568 {
569 free (filter->plist[i].name);
570 filter->plist[i].name = NULL;
571 }
572 if (filter->aslist[i].name)
573 {
574 free (filter->aslist[i].name);
575 filter->aslist[i].name = NULL;
576 }
577 if (filter->map[i].name)
578 {
579 free (filter->map[i].name);
580 filter->map[i].name = NULL;
581 }
582 }
583
584 /* Clear unsuppress map. */
585 if (filter->usmap.name)
586 free (filter->usmap.name);
587 filter->usmap.name = NULL;
588 filter->usmap.map = NULL;
589
590 /* Clear neighbor's all address family flags. */
591 peer->af_flags[afi][safi] = 0;
592
593 /* Clear neighbor's all address family sflags. */
594 peer->af_sflags[afi][safi] = 0;
595
596 /* Clear neighbor's all address family capabilities. */
597 peer->af_cap[afi][safi] = 0;
598
599 /* Clear ORF info */
600 peer->orf_plist[afi][safi] = NULL;
601 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
602 prefix_bgp_orf_remove_all (orf_name);
603
604 /* Set default neighbor send-community. */
605 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
606 {
607 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
608 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
609 }
610
611 /* Clear neighbor default_originate_rmap */
612 if (peer->default_rmap[afi][safi].name)
613 free (peer->default_rmap[afi][safi].name);
614 peer->default_rmap[afi][safi].name = NULL;
615 peer->default_rmap[afi][safi].map = NULL;
616
617 /* Clear neighbor maximum-prefix */
618 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +0000619 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000620}
621
622/* peer global config reset */
623void
624peer_global_config_reset (struct peer *peer)
625{
626 peer->weight = 0;
627 peer->change_local_as = 0;
628 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
629 if (peer->update_source)
630 {
631 sockunion_free (peer->update_source);
632 peer->update_source = NULL;
633 }
634 if (peer->update_if)
635 {
636 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
637 peer->update_if = NULL;
638 }
639
640 if (peer_sort (peer) == BGP_PEER_IBGP)
641 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
642 else
643 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
644
645 peer->flags = 0;
646 peer->config = 0;
647 peer->holdtime = 0;
648 peer->keepalive = 0;
649 peer->connect = 0;
650 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
651}
652
653/* Check peer's AS number and determin is this peer IBGP or EBGP */
654int
655peer_sort (struct peer *peer)
656{
657 struct bgp *bgp;
658
659 bgp = peer->bgp;
660
661 /* Peer-group */
662 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
663 {
664 if (peer->as)
665 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
666 else
667 {
668 struct peer *peer1;
669 peer1 = listnode_head (peer->group->peer);
670 if (peer1)
671 return (peer1->local_as == peer1->as
672 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
673 }
674 return BGP_PEER_INTERNAL;
675 }
676
677 /* Normal peer */
678 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
679 {
680 if (peer->local_as == 0)
681 return BGP_PEER_INTERNAL;
682
683 if (peer->local_as == peer->as)
684 {
685 if (peer->local_as == bgp->confed_id)
686 return BGP_PEER_EBGP;
687 else
688 return BGP_PEER_IBGP;
689 }
690
691 if (bgp_confederation_peers_check (bgp, peer->as))
692 return BGP_PEER_CONFED;
693
694 return BGP_PEER_EBGP;
695 }
696 else
697 {
698 return (peer->local_as == 0
699 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
700 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
701 }
702}
703
704/* Allocate new peer object. */
705static struct peer *
706peer_new ()
707{
708 afi_t afi;
709 safi_t safi;
710 struct peer *peer;
711 struct servent *sp;
712
713 /* Allocate new peer. */
714 peer = XMALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
715 memset (peer, 0, sizeof (struct peer));
716
717 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000718 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000719 peer->v_start = BGP_INIT_START_TIMER;
720 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
721 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
722 peer->status = Idle;
723 peer->ostatus = Idle;
724 peer->version = BGP_VERSION_4;
725 peer->weight = 0;
726
727 /* Set default flags. */
728 for (afi = AFI_IP; afi < AFI_MAX; afi++)
729 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
730 {
731 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
732 {
733 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
734 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
735 }
736 peer->orf_plist[afi][safi] = NULL;
737 }
738 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
739
740 /* Create buffers. */
741 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
742 peer->obuf = stream_fifo_new ();
743 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
744
745 bgp_sync_init (peer);
746
747 /* Get service port number. */
748 sp = getservbyname ("bgp", "tcp");
749 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
750
751 return peer;
752}
753
754/* Create new BGP peer. */
755struct peer *
756peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
757 as_t remote_as, afi_t afi, safi_t safi)
758{
759 int active;
760 struct peer *peer;
761 char buf[SU_ADDRSTRLEN];
762
763 peer = peer_new ();
764 peer->bgp = bgp;
765 peer->su = *su;
766 peer->local_as = local_as;
767 peer->as = remote_as;
768 peer->local_id = bgp->router_id;
769 peer->v_holdtime = bgp->default_holdtime;
770 peer->v_keepalive = bgp->default_keepalive;
771 if (peer_sort (peer) == BGP_PEER_IBGP)
772 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
773 else
774 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
775 listnode_add_sort (bgp->peer, peer);
776
777 active = peer_active (peer);
778
779 if (afi && safi)
780 peer->afc[afi][safi] = 1;
781
782 /* Last read time set */
783 peer->readtime = time (NULL);
784
paul848973c2003-08-13 00:32:49 +0000785 /* Last reset time set */
786 peer->resettime = time (NULL);
787
paul718e3742002-12-13 20:15:29 +0000788 /* Default TTL set. */
789 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
790
791 /* Make peer's address string. */
792 sockunion2str (su, buf, SU_ADDRSTRLEN);
793 peer->host = strdup (buf);
794
795 /* Set up peer's events and timers. */
796 if (! active && peer_active (peer))
797 bgp_timer_set (peer);
798
799 return peer;
800}
801
pauleb821182004-05-01 08:44:08 +0000802/* Make accept BGP peer. Called from bgp_accept (). */
803struct peer *
804peer_create_accept (struct bgp *bgp)
805{
806 struct peer *peer;
807
808 peer = peer_new ();
809 peer->bgp = bgp;
810 listnode_add_sort (bgp->peer, peer);
811
812 return peer;
813}
814
paul718e3742002-12-13 20:15:29 +0000815/* Change peer's AS number. */
816void
817peer_as_change (struct peer *peer, as_t as)
818{
819 int type;
820
821 /* Stop peer. */
822 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
823 {
824 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000825 {
826 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
827 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
828 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
829 }
paul718e3742002-12-13 20:15:29 +0000830 else
831 BGP_EVENT_ADD (peer, BGP_Stop);
832 }
833 type = peer_sort (peer);
834 peer->as = as;
835
paul848973c2003-08-13 00:32:49 +0000836 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
837 && ! bgp_confederation_peers_check (peer->bgp, as)
838 && peer->bgp->as != as)
839 peer->local_as = peer->bgp->confed_id;
840 else
841 peer->local_as = peer->bgp->as;
842
paul718e3742002-12-13 20:15:29 +0000843 /* Advertisement-interval reset */
844 if (peer_sort (peer) == BGP_PEER_IBGP)
845 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
846 else
847 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
848
849 /* TTL reset */
850 if (peer_sort (peer) == BGP_PEER_IBGP)
851 peer->ttl = 255;
852 else if (type == BGP_PEER_IBGP)
853 peer->ttl = 1;
854
855 /* reflector-client reset */
856 if (peer_sort (peer) != BGP_PEER_IBGP)
857 {
858 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
859 PEER_FLAG_REFLECTOR_CLIENT);
860 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
861 PEER_FLAG_REFLECTOR_CLIENT);
862 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
863 PEER_FLAG_REFLECTOR_CLIENT);
864 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
865 PEER_FLAG_REFLECTOR_CLIENT);
866 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
867 PEER_FLAG_REFLECTOR_CLIENT);
868 }
869
870 /* local-as reset */
871 if (peer_sort (peer) != BGP_PEER_EBGP)
872 {
873 peer->change_local_as = 0;
874 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
875 }
876}
877
878/* If peer does not exist, create new one. If peer already exists,
879 set AS number to the peer. */
880int
881peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
882 afi_t afi, safi_t safi)
883{
884 struct peer *peer;
885 as_t local_as;
886
887 peer = peer_lookup (bgp, su);
888
889 if (peer)
890 {
891 /* When this peer is a member of peer-group. */
892 if (peer->group)
893 {
894 if (peer->group->conf->as)
895 {
896 /* Return peer group's AS number. */
897 *as = peer->group->conf->as;
898 return BGP_ERR_PEER_GROUP_MEMBER;
899 }
900 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
901 {
902 if (bgp->as != *as)
903 {
904 *as = peer->as;
905 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
906 }
907 }
908 else
909 {
910 if (bgp->as == *as)
911 {
912 *as = peer->as;
913 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
914 }
915 }
916 }
917
918 /* Existing peer's AS number change. */
919 if (peer->as != *as)
920 peer_as_change (peer, *as);
921 }
922 else
923 {
924
925 /* If the peer is not part of our confederation, and its not an
926 iBGP peer then spoof the source AS */
927 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
928 && ! bgp_confederation_peers_check (bgp, *as)
929 && bgp->as != *as)
930 local_as = bgp->confed_id;
931 else
932 local_as = bgp->as;
933
934 /* If this is IPv4 unicast configuration and "no bgp default
935 ipv4-unicast" is specified. */
936
937 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
938 && afi == AFI_IP && safi == SAFI_UNICAST)
939 peer = peer_create (su, bgp, local_as, *as, 0, 0);
940 else
941 peer = peer_create (su, bgp, local_as, *as, afi, safi);
942 }
943
944 return 0;
945}
946
947/* Activate the peer or peer group for specified AFI and SAFI. */
948int
949peer_activate (struct peer *peer, afi_t afi, safi_t safi)
950{
951 int active;
952
953 if (peer->afc[afi][safi])
954 return 0;
955
956 /* Activate the address family configuration. */
957 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
958 peer->afc[afi][safi] = 1;
959 else
960 {
961 active = peer_active (peer);
962
963 peer->afc[afi][safi] = 1;
964
965 if (! active && peer_active (peer))
966 bgp_timer_set (peer);
967 else
968 {
969 if (peer->status == Established)
970 {
971 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
972 {
973 peer->afc_adv[afi][safi] = 1;
974 bgp_capability_send (peer, afi, safi,
975 CAPABILITY_CODE_MP,
976 CAPABILITY_ACTION_SET);
977 if (peer->afc_recv[afi][safi])
978 {
979 peer->afc_nego[afi][safi] = 1;
980 bgp_announce_route (peer, afi, safi);
981 }
982 }
983 else
hassoe0701b72004-05-20 09:19:34 +0000984 {
985 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
986 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
987 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
988 }
paul718e3742002-12-13 20:15:29 +0000989 }
990 }
991 }
992 return 0;
993}
994
995int
996peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
997{
998 struct peer_group *group;
999 struct peer *peer1;
1000 struct listnode *nn;
1001
1002 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1003 {
1004 group = peer->group;
1005
1006 LIST_LOOP (group->peer, peer1, nn)
1007 {
1008 if (peer1->af_group[afi][safi])
1009 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1010 }
1011 }
1012 else
1013 {
1014 if (peer->af_group[afi][safi])
1015 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1016 }
1017
1018 if (! peer->afc[afi][safi])
1019 return 0;
1020
1021 /* De-activate the address family configuration. */
1022 peer->afc[afi][safi] = 0;
1023 peer_af_flag_reset (peer, afi, safi);
1024
1025 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1026 {
1027 if (peer->status == Established)
1028 {
1029 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1030 {
1031 peer->afc_adv[afi][safi] = 0;
1032 peer->afc_nego[afi][safi] = 0;
1033
1034 if (peer_active_nego (peer))
1035 {
1036 bgp_capability_send (peer, afi, safi,
1037 CAPABILITY_CODE_MP,
1038 CAPABILITY_ACTION_UNSET);
1039 bgp_clear_route (peer, afi, safi);
1040 peer->pcount[afi][safi] = 0;
1041 }
1042 else
hassoe0701b72004-05-20 09:19:34 +00001043 {
1044 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1045 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1046 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1047 }
paul718e3742002-12-13 20:15:29 +00001048 }
1049 else
hassoe0701b72004-05-20 09:19:34 +00001050 {
1051 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1052 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1053 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1054 }
paul718e3742002-12-13 20:15:29 +00001055 }
1056 }
1057 return 0;
1058}
1059
1060/* Delete peer from confguration. */
1061int
1062peer_delete (struct peer *peer)
1063{
1064 int i;
1065 afi_t afi;
1066 safi_t safi;
1067 struct bgp *bgp;
1068 struct bgp_filter *filter;
1069
1070 bgp = peer->bgp;
1071
1072 /* If this peer belongs to peer group. Clearn up the
1073 relationship. */
1074 if (peer->group)
1075 {
1076 listnode_delete (peer->group->peer, peer);
1077 peer->group = NULL;
1078 }
1079
1080 /* Withdraw all information from routing table. We can not use
1081 BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1082 executed after peer structure is deleted. */
hassoe0701b72004-05-20 09:19:34 +00001083 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001084 bgp_stop (peer);
1085 bgp_fsm_change_status (peer, Idle);
1086
1087 /* Stop all timers. */
1088 BGP_TIMER_OFF (peer->t_start);
1089 BGP_TIMER_OFF (peer->t_connect);
1090 BGP_TIMER_OFF (peer->t_holdtime);
1091 BGP_TIMER_OFF (peer->t_keepalive);
1092 BGP_TIMER_OFF (peer->t_asorig);
1093 BGP_TIMER_OFF (peer->t_routeadv);
1094
1095 /* Delete from all peer list. */
1096 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1097 listnode_delete (bgp->peer, peer);
1098
1099 /* Buffer. */
1100 if (peer->ibuf)
1101 stream_free (peer->ibuf);
1102
1103 if (peer->obuf)
1104 stream_fifo_free (peer->obuf);
1105
1106 if (peer->work)
1107 stream_free (peer->work);
1108
1109 /* Free allocated host character. */
1110 if (peer->host)
1111 free (peer->host);
1112
1113 /* Local and remote addresses. */
1114 if (peer->su_local)
1115 XFREE (MTYPE_TMP, peer->su_local);
1116 if (peer->su_remote)
1117 XFREE (MTYPE_TMP, peer->su_remote);
1118
1119 /* Peer description string. */
1120 if (peer->desc)
1121 XFREE (MTYPE_TMP, peer->desc);
1122
1123 bgp_sync_delete (peer);
1124
1125 /* Free filter related memory. */
1126 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1127 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1128 {
1129 filter = &peer->filter[afi][safi];
1130
1131 for (i = FILTER_IN; i < FILTER_MAX; i++)
1132 {
1133 if (filter->dlist[i].name)
1134 free (filter->dlist[i].name);
1135 if (filter->plist[i].name)
1136 free (filter->plist[i].name);
1137 if (filter->aslist[i].name)
1138 free (filter->aslist[i].name);
1139 if (filter->map[i].name)
1140 free (filter->map[i].name);
1141 }
1142
1143 if (filter->usmap.name)
1144 free (filter->usmap.name);
1145
1146 if (peer->default_rmap[afi][safi].name)
1147 free (peer->default_rmap[afi][safi].name);
1148 }
1149
1150 /* Update source configuration. */
1151 if (peer->update_source)
1152 {
1153 sockunion_free (peer->update_source);
1154 peer->update_source = NULL;
1155 }
1156 if (peer->update_if)
1157 {
1158 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1159 peer->update_if = NULL;
1160 }
1161
1162 /* Free peer structure. */
1163 XFREE (MTYPE_BGP_PEER, peer);
1164
1165 return 0;
1166}
1167
1168int
1169peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1170{
1171 return strcmp (g1->name, g2->name);
1172}
1173
1174/* If peer is configured at least one address family return 1. */
1175int
1176peer_group_active (struct peer *peer)
1177{
1178 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1179 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1180 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1181 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1182 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1183 return 1;
1184 return 0;
1185}
1186
1187/* Peer group cofiguration. */
1188static struct peer_group *
1189peer_group_new ()
1190{
1191 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1192 sizeof (struct peer_group));
1193}
1194
1195void
1196peer_group_free (struct peer_group *group)
1197{
1198 XFREE (MTYPE_PEER_GROUP, group);
1199}
1200
1201struct peer_group *
1202peer_group_lookup (struct bgp *bgp, char *name)
1203{
1204 struct peer_group *group;
1205 struct listnode *nn;
1206
1207 LIST_LOOP (bgp->group, group, nn)
1208 {
1209 if (strcmp (group->name, name) == 0)
1210 return group;
1211 }
1212 return NULL;
1213}
1214
1215struct peer_group *
1216peer_group_get (struct bgp *bgp, char *name)
1217{
1218 struct peer_group *group;
1219
1220 group = peer_group_lookup (bgp, name);
1221 if (group)
1222 return group;
1223
1224 group = peer_group_new ();
1225 group->bgp = bgp;
1226 group->name = strdup (name);
1227 group->peer = list_new ();
1228 group->conf = peer_new ();
1229 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1230 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
1231 group->conf->host = strdup (name);
1232 group->conf->bgp = bgp;
1233 group->conf->group = group;
1234 group->conf->as = 0;
1235 group->conf->ttl = 1;
1236 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1237 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1238 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1239 group->conf->keepalive = 0;
1240 group->conf->holdtime = 0;
1241 group->conf->connect = 0;
1242 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1243 listnode_add_sort (bgp->group, group);
1244
1245 return 0;
1246}
1247
1248void
1249peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1250 afi_t afi, safi_t safi)
1251{
1252 int in = FILTER_IN;
1253 int out = FILTER_OUT;
1254 struct peer *conf;
1255 struct bgp_filter *pfilter;
1256 struct bgp_filter *gfilter;
1257
1258 conf = group->conf;
1259 pfilter = &peer->filter[afi][safi];
1260 gfilter = &conf->filter[afi][safi];
1261
1262 /* remote-as */
1263 if (conf->as)
1264 peer->as = conf->as;
1265
1266 /* remote-as */
1267 if (conf->change_local_as)
1268 peer->change_local_as = conf->change_local_as;
1269
1270 /* TTL */
1271 peer->ttl = conf->ttl;
1272
1273 /* Weight */
1274 peer->weight = conf->weight;
1275
1276 /* peer flags apply */
1277 peer->flags = conf->flags;
1278 /* peer af_flags apply */
1279 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1280 /* peer config apply */
1281 peer->config = conf->config;
1282
1283 /* peer timers apply */
1284 peer->holdtime = conf->holdtime;
1285 peer->keepalive = conf->keepalive;
1286 peer->connect = conf->connect;
1287 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1288 peer->v_connect = conf->connect;
1289 else
1290 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1291
1292 /* advertisement-interval reset */
1293 if (peer_sort (peer) == BGP_PEER_IBGP)
1294 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1295 else
1296 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1297
1298 /* maximum-prefix */
1299 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001300 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
paul718e3742002-12-13 20:15:29 +00001301
1302 /* allowas-in */
1303 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1304
1305 /* default-originate route-map */
1306 if (conf->default_rmap[afi][safi].name)
1307 {
1308 if (peer->default_rmap[afi][safi].name)
1309 free (peer->default_rmap[afi][safi].name);
1310 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1311 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1312 }
1313
1314 /* update-source apply */
1315 if (conf->update_source)
1316 {
1317 if (peer->update_source)
1318 sockunion_free (peer->update_source);
1319 if (peer->update_if)
1320 {
1321 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1322 peer->update_if = NULL;
1323 }
1324 peer->update_source = sockunion_dup (conf->update_source);
1325 }
1326 else if (conf->update_if)
1327 {
1328 if (peer->update_if)
1329 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1330 if (peer->update_source)
1331 {
1332 sockunion_free (peer->update_source);
1333 peer->update_source = NULL;
1334 }
1335 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1336 }
1337
1338 /* inbound filter apply */
1339 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1340 {
1341 if (pfilter->dlist[in].name)
1342 free (pfilter->dlist[in].name);
1343 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1344 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1345 }
1346 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1347 {
1348 if (pfilter->plist[in].name)
1349 free (pfilter->plist[in].name);
1350 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1351 pfilter->plist[in].plist = gfilter->plist[in].plist;
1352 }
1353 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1354 {
1355 if (pfilter->aslist[in].name)
1356 free (pfilter->aslist[in].name);
1357 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1358 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1359 }
1360 if (gfilter->map[in].name && ! pfilter->map[in].name)
1361 {
1362 if (pfilter->map[in].name)
1363 free (pfilter->map[in].name);
1364 pfilter->map[in].name = strdup (gfilter->map[in].name);
1365 pfilter->map[in].map = gfilter->map[in].map;
1366 }
1367
1368 /* outbound filter apply */
1369 if (gfilter->dlist[out].name)
1370 {
1371 if (pfilter->dlist[out].name)
1372 free (pfilter->dlist[out].name);
1373 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1374 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1375 }
1376 else
1377 {
1378 if (pfilter->dlist[out].name)
1379 free (pfilter->dlist[out].name);
1380 pfilter->dlist[out].name = NULL;
1381 pfilter->dlist[out].alist = NULL;
1382 }
1383 if (gfilter->plist[out].name)
1384 {
1385 if (pfilter->plist[out].name)
1386 free (pfilter->plist[out].name);
1387 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1388 pfilter->plist[out].plist = gfilter->plist[out].plist;
1389 }
1390 else
1391 {
1392 if (pfilter->plist[out].name)
1393 free (pfilter->plist[out].name);
1394 pfilter->plist[out].name = NULL;
1395 pfilter->plist[out].plist = NULL;
1396 }
1397 if (gfilter->aslist[out].name)
1398 {
1399 if (pfilter->aslist[out].name)
1400 free (pfilter->aslist[out].name);
1401 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1402 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1403 }
1404 else
1405 {
1406 if (pfilter->aslist[out].name)
1407 free (pfilter->aslist[out].name);
1408 pfilter->aslist[out].name = NULL;
1409 pfilter->aslist[out].aslist = NULL;
1410 }
1411 if (gfilter->map[out].name)
1412 {
1413 if (pfilter->map[out].name)
1414 free (pfilter->map[out].name);
1415 pfilter->map[out].name = strdup (gfilter->map[out].name);
1416 pfilter->map[out].map = gfilter->map[out].map;
1417 }
1418 else
1419 {
1420 if (pfilter->map[out].name)
1421 free (pfilter->map[out].name);
1422 pfilter->map[out].name = NULL;
1423 pfilter->map[out].map = NULL;
1424 }
1425
1426 if (gfilter->usmap.name)
1427 {
1428 if (pfilter->usmap.name)
1429 free (pfilter->usmap.name);
1430 pfilter->usmap.name = strdup (gfilter->usmap.name);
1431 pfilter->usmap.map = gfilter->usmap.map;
1432 }
1433 else
1434 {
1435 if (pfilter->usmap.name)
1436 free (pfilter->usmap.name);
1437 pfilter->usmap.name = NULL;
1438 pfilter->usmap.map = NULL;
1439 }
1440}
1441
1442/* Peer group's remote AS configuration. */
1443int
1444peer_group_remote_as (struct bgp *bgp, char *group_name, as_t *as)
1445{
1446 struct peer_group *group;
1447 struct peer *peer;
1448 struct listnode *nn;
1449
1450 group = peer_group_lookup (bgp, group_name);
1451 if (! group)
1452 return -1;
1453
1454 if (group->conf->as == *as)
1455 return 0;
1456
1457 /* When we setup peer-group AS number all peer group member's AS
1458 number must be updated to same number. */
1459 peer_as_change (group->conf, *as);
1460
1461 LIST_LOOP (group->peer, peer, nn)
1462 {
1463 if (peer->as != *as)
1464 peer_as_change (peer, *as);
1465 }
1466
1467 return 0;
1468}
1469
1470int
1471peer_group_delete (struct peer_group *group)
1472{
1473 struct bgp *bgp;
1474 struct peer *peer;
1475 struct listnode *nn;
1476
1477 bgp = group->bgp;
1478
1479 LIST_LOOP (group->peer, peer, nn)
1480 {
1481 peer->group = NULL;
1482 peer_delete (peer);
1483 }
1484 list_delete (group->peer);
1485
1486 free (group->name);
1487 group->name = NULL;
1488
1489 group->conf->group = NULL;
1490 peer_delete (group->conf);
1491
1492 /* Delete from all peer_group list. */
1493 listnode_delete (bgp->group, group);
1494
1495 peer_group_free (group);
1496
1497 return 0;
1498}
1499
1500int
1501peer_group_remote_as_delete (struct peer_group *group)
1502{
1503 struct peer *peer;
1504 struct listnode *nn;
1505
1506 if (! group->conf->as)
1507 return 0;
1508
1509 LIST_LOOP (group->peer, peer, nn)
1510 {
1511 peer->group = NULL;
1512 peer_delete (peer);
1513 }
1514 list_delete_all_node (group->peer);
1515
1516 group->conf->as = 0;
1517
1518 return 0;
1519}
1520
1521/* Bind specified peer to peer group. */
1522int
1523peer_group_bind (struct bgp *bgp, union sockunion *su,
1524 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1525{
1526 struct peer *peer;
1527 int first_member = 0;
1528
1529 /* Check peer group's address family. */
1530 if (! group->conf->afc[afi][safi])
1531 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1532
1533 /* Lookup the peer. */
1534 peer = peer_lookup (bgp, su);
1535
1536 /* Create a new peer. */
1537 if (! peer)
1538 {
1539 if (! group->conf->as)
1540 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1541
1542 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1543 peer->group = group;
1544 peer->af_group[afi][safi] = 1;
1545 listnode_add (group->peer, peer);
1546 peer_group2peer_config_copy (group, peer, afi, safi);
1547
1548 return 0;
1549 }
1550
1551 /* When the peer already belongs to peer group, check the consistency. */
1552 if (peer->af_group[afi][safi])
1553 {
1554 if (strcmp (peer->group->name, group->name) != 0)
1555 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1556
1557 return 0;
1558 }
1559
1560 /* Check current peer group configuration. */
1561 if (peer_group_active (peer)
1562 && strcmp (peer->group->name, group->name) != 0)
1563 return BGP_ERR_PEER_GROUP_MISMATCH;
1564
1565 if (! group->conf->as)
1566 {
1567 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1568 && peer_sort (group->conf) != peer_sort (peer))
1569 {
1570 if (as)
1571 *as = peer->as;
1572 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1573 }
1574
1575 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1576 first_member = 1;
1577 }
1578
1579 peer->af_group[afi][safi] = 1;
1580 peer->afc[afi][safi] = 1;
1581 if (! peer->group)
1582 {
1583 peer->group = group;
1584 listnode_add (group->peer, peer);
1585 }
1586
1587 if (first_member)
1588 {
1589 /* Advertisement-interval reset */
1590 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1591 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1592 else
1593 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1594
1595 /* ebgp-multihop reset */
1596 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1597 group->conf->ttl = 255;
1598
1599 /* local-as reset */
1600 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1601 {
1602 group->conf->change_local_as = 0;
1603 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1604 }
1605 }
1606 peer_group2peer_config_copy (group, peer, afi, safi);
1607
1608 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001609 {
1610 peer->last_reset = PEER_DOWN_RMAP_BIND;
1611 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1612 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1613 }
paul718e3742002-12-13 20:15:29 +00001614 else
1615 BGP_EVENT_ADD (peer, BGP_Stop);
1616
1617 return 0;
1618}
1619
1620int
1621peer_group_unbind (struct bgp *bgp, struct peer *peer,
1622 struct peer_group *group, afi_t afi, safi_t safi)
1623{
1624 if (! peer->af_group[afi][safi])
1625 return 0;
1626
1627 if (group != peer->group)
1628 return BGP_ERR_PEER_GROUP_MISMATCH;
1629
1630 peer->af_group[afi][safi] = 0;
1631 peer->afc[afi][safi] = 0;
1632 peer_af_flag_reset (peer, afi, safi);
1633
1634 if (! peer_group_active (peer))
1635 {
1636 listnode_delete (group->peer, peer);
1637 peer->group = NULL;
1638 if (group->conf->as)
1639 {
1640 peer_delete (peer);
1641 return 0;
1642 }
1643 peer_global_config_reset (peer);
1644 }
1645
1646 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001647 {
1648 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1649 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1650 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1651 }
paul718e3742002-12-13 20:15:29 +00001652 else
1653 BGP_EVENT_ADD (peer, BGP_Stop);
1654
1655 return 0;
1656}
1657
1658/* BGP instance creation by `router bgp' commands. */
1659struct bgp *
1660bgp_create (as_t *as, char *name)
1661{
1662 struct bgp *bgp;
1663 afi_t afi;
1664 safi_t safi;
1665
1666 bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp));
1667
1668 bgp->peer_self = peer_new ();
1669 bgp->peer_self->host = "Static announcement";
1670
1671 bgp->peer = list_new ();
1672 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1673
1674 bgp->group = list_new ();
1675 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1676
1677 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1678 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1679 {
1680 bgp->route[afi][safi] = bgp_table_init ();
1681 bgp->aggregate[afi][safi] = bgp_table_init ();
1682 bgp->rib[afi][safi] = bgp_table_init ();
1683 }
1684
1685 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1686 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1687 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
1688
1689 bgp->as = *as;
1690
1691 if (name)
1692 bgp->name = strdup (name);
1693
1694 return bgp;
1695}
1696
paul848973c2003-08-13 00:32:49 +00001697/* Return master of BGP. */
1698struct bgp_master *
1699bgp_get_master ()
1700{
1701 if (bm)
1702 return bm;
1703 return NULL;
1704}
1705
paul718e3742002-12-13 20:15:29 +00001706/* Return first entry of BGP. */
1707struct bgp *
1708bgp_get_default ()
1709{
1710 if (bm->bgp->head)
1711 return bm->bgp->head->data;
1712 return NULL;
1713}
1714
1715/* Lookup BGP entry. */
1716struct bgp *
1717bgp_lookup (as_t as, char *name)
1718{
1719 struct bgp *bgp;
1720 struct listnode *nn;
1721
1722 LIST_LOOP (bm->bgp, bgp, nn)
1723 if (bgp->as == as
1724 && ((bgp->name == NULL && name == NULL)
1725 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1726 return bgp;
1727 return NULL;
1728}
1729
1730/* Lookup BGP structure by view name. */
1731struct bgp *
1732bgp_lookup_by_name (char *name)
1733{
1734 struct bgp *bgp;
1735 struct listnode *nn;
1736
1737 LIST_LOOP (bm->bgp, bgp, nn)
1738 if ((bgp->name == NULL && name == NULL)
1739 || (bgp->name && name && strcmp (bgp->name, name) == 0))
1740 return bgp;
1741 return NULL;
1742}
1743
1744/* Called from VTY commands. */
1745int
1746bgp_get (struct bgp **bgp_val, as_t *as, char *name)
1747{
1748 struct bgp *bgp;
1749
1750 /* Multiple instance check. */
1751 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
1752 {
1753 if (name)
1754 bgp = bgp_lookup_by_name (name);
1755 else
1756 bgp = bgp_get_default ();
1757
1758 /* Already exists. */
1759 if (bgp)
1760 {
1761 if (bgp->as != *as)
1762 {
1763 *as = bgp->as;
1764 return BGP_ERR_INSTANCE_MISMATCH;
1765 }
1766 *bgp_val = bgp;
1767 return 0;
1768 }
1769 }
1770 else
1771 {
1772 /* BGP instance name can not be specified for single instance. */
1773 if (name)
1774 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
1775
1776 /* Get default BGP structure if exists. */
1777 bgp = bgp_get_default ();
1778
1779 if (bgp)
1780 {
1781 if (bgp->as != *as)
1782 {
1783 *as = bgp->as;
1784 return BGP_ERR_AS_MISMATCH;
1785 }
1786 *bgp_val = bgp;
1787 return 0;
1788 }
1789 }
1790
1791 bgp = bgp_create (as, name);
1792 listnode_add (bm->bgp, bgp);
1793 bgp_if_update_all ();
1794 *bgp_val = bgp;
1795
1796 return 0;
1797}
1798
1799/* Delete BGP instance. */
1800int
1801bgp_delete (struct bgp *bgp)
1802{
1803 struct peer *peer;
1804 struct listnode *nn;
1805 struct listnode *next;
1806 afi_t afi;
1807 safi_t safi;
1808 int i;
1809
1810 /* Delete static route. */
1811 bgp_static_delete (bgp);
1812
1813 /* Unset redistribution. */
1814 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1815 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
1816 if (i != ZEBRA_ROUTE_BGP)
1817 bgp_redistribute_unset (bgp, afi, i);
1818
1819 bgp->group->del = (void (*)(void *)) peer_group_delete;
1820 list_delete (bgp->group);
1821
1822 for (nn = bgp->peer->head; nn; nn = next)
1823 {
1824 peer = nn->data;
1825 next = nn->next;
1826 peer_delete (peer);
1827 }
1828
1829 listnode_delete (bm->bgp, bgp);
1830
1831 if (bgp->name)
1832 free (bgp->name);
1833
1834 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1835 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1836 {
1837 if (bgp->route[afi][safi])
1838 XFREE (MTYPE_ROUTE_TABLE, bgp->route[afi][safi]);
1839 if (bgp->aggregate[afi][safi])
1840 XFREE (MTYPE_ROUTE_TABLE,bgp->aggregate[afi][safi]) ;
1841 if (bgp->rib[afi][safi])
1842 XFREE (MTYPE_ROUTE_TABLE,bgp->rib[afi][safi]);
1843 }
1844 XFREE (MTYPE_BGP, bgp);
1845
1846 return 0;
1847}
1848
1849struct peer *
1850peer_lookup (struct bgp *bgp, union sockunion *su)
1851{
1852 struct peer *peer;
1853 struct listnode *nn;
1854
1855 if (! bgp)
1856 bgp = bgp_get_default ();
1857
1858 if (! bgp)
1859 return NULL;
1860
1861 LIST_LOOP (bgp->peer, peer, nn)
1862 {
pauleb821182004-05-01 08:44:08 +00001863 if (sockunion_same (&peer->su, su)
1864 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1865 return peer;
paul718e3742002-12-13 20:15:29 +00001866 }
1867 return NULL;
1868}
1869
1870struct peer *
1871peer_lookup_with_open (union sockunion *su, as_t remote_as,
1872 struct in_addr *remote_id, int *as)
1873{
1874 struct peer *peer;
1875 struct listnode *nn;
1876 struct bgp *bgp;
1877
1878 bgp = bgp_get_default ();
1879 if (! bgp)
1880 return NULL;
1881
1882 LIST_LOOP (bgp->peer, peer, nn)
1883 {
pauleb821182004-05-01 08:44:08 +00001884 if (sockunion_same (&peer->su, su)
1885 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1886 {
1887 if (peer->as == remote_as
1888 && peer->remote_id.s_addr == remote_id->s_addr)
1889 return peer;
1890 if (peer->as == remote_as)
1891 *as = 1;
1892 }
paul718e3742002-12-13 20:15:29 +00001893 }
1894 LIST_LOOP (bgp->peer, peer, nn)
1895 {
pauleb821182004-05-01 08:44:08 +00001896 if (sockunion_same (&peer->su, su)
1897 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1898 {
1899 if (peer->as == remote_as
1900 && peer->remote_id.s_addr == 0)
1901 return peer;
1902 if (peer->as == remote_as)
1903 *as = 1;
1904 }
paul718e3742002-12-13 20:15:29 +00001905 }
1906 return NULL;
1907}
1908
1909/* If peer is configured at least one address family return 1. */
1910int
1911peer_active (struct peer *peer)
1912{
1913 if (peer->afc[AFI_IP][SAFI_UNICAST]
1914 || peer->afc[AFI_IP][SAFI_MULTICAST]
1915 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
1916 || peer->afc[AFI_IP6][SAFI_UNICAST]
1917 || peer->afc[AFI_IP6][SAFI_MULTICAST])
1918 return 1;
1919 return 0;
1920}
1921
1922/* If peer is negotiated at least one address family return 1. */
1923int
1924peer_active_nego (struct peer *peer)
1925{
1926 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
1927 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
1928 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
1929 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
1930 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
1931 return 1;
1932 return 0;
1933}
1934
1935/* peer_flag_change_type. */
1936enum peer_change_type
1937{
1938 peer_change_none,
1939 peer_change_reset,
1940 peer_change_reset_in,
1941 peer_change_reset_out,
1942};
1943
1944void
1945peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
1946 enum peer_change_type type)
1947{
1948 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1949 return;
1950
1951 if (type == peer_change_reset)
1952 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1953 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1954 else if (type == peer_change_reset_in)
1955 {
1956 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
1957 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
1958 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
1959 else
1960 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1961 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1962 }
1963 else if (type == peer_change_reset_out)
1964 bgp_announce_route (peer, afi, safi);
1965}
1966
1967struct peer_flag_action
1968{
1969 /* Peer's flag. */
1970 u_int32_t flag;
1971
1972 /* This flag can be set for peer-group member. */
1973 u_char not_for_member;
1974
1975 /* Action when the flag is changed. */
1976 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00001977
1978 /* Peer down cause */
1979 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00001980};
1981
1982struct peer_flag_action peer_flag_action_list[] =
1983 {
1984 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
1985 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
1986 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
1987 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
1988 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
1989 { PEER_FLAG_NO_ROUTE_REFRESH_CAP, 0, peer_change_reset },
1990 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
1991 { PEER_FLAG_ENFORCE_MULTIHOP, 0, peer_change_reset },
1992 { 0, 0, 0 }
1993 };
1994
1995struct peer_flag_action peer_af_flag_action_list[] =
1996 {
1997 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
1998 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
1999 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2000 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2001 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2002 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2003 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2004 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2005 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2006 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2007 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2008 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2009 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
2010 { 0, 0, 0 }
2011 };
2012
2013/* Proper action set. */
2014int
2015peer_flag_action_set (struct peer_flag_action *action_list, int size,
2016 struct peer_flag_action *action, u_int32_t flag)
2017{
2018 int i;
2019 int found = 0;
2020 int reset_in = 0;
2021 int reset_out = 0;
2022 struct peer_flag_action *match = NULL;
2023
2024 /* Check peer's frag action. */
2025 for (i = 0; i < size; i++)
2026 {
2027 match = &action_list[i];
2028
2029 if (match->flag == 0)
2030 break;
2031
2032 if (match->flag & flag)
2033 {
2034 found = 1;
2035
2036 if (match->type == peer_change_reset_in)
2037 reset_in = 1;
2038 if (match->type == peer_change_reset_out)
2039 reset_out = 1;
2040 if (match->type == peer_change_reset)
2041 {
2042 reset_in = 1;
2043 reset_out = 1;
2044 }
2045 if (match->not_for_member)
2046 action->not_for_member = 1;
2047 }
2048 }
2049
2050 /* Set peer clear type. */
2051 if (reset_in && reset_out)
2052 action->type = peer_change_reset;
2053 else if (reset_in)
2054 action->type = peer_change_reset_in;
2055 else if (reset_out)
2056 action->type = peer_change_reset_out;
2057 else
2058 action->type = peer_change_none;
2059
2060 return found;
2061}
2062
2063void
2064peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2065{
2066 if (flag == PEER_FLAG_SHUTDOWN)
2067 {
2068 if (CHECK_FLAG (peer->flags, flag))
2069 {
2070 if (peer->status == Established)
2071 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2072 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2073 else
2074 BGP_EVENT_ADD (peer, BGP_Stop);
2075 }
2076 else
2077 {
2078 peer->v_start = BGP_INIT_START_TIMER;
2079 BGP_EVENT_ADD (peer, BGP_Stop);
2080 }
2081 }
2082 else if (peer->status == Established)
2083 {
2084 if (flag == PEER_FLAG_NO_ROUTE_REFRESH_CAP
2085 && CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
2086 {
2087 if (CHECK_FLAG (peer->flags, flag))
2088 UNSET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
2089 else
2090 SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
2091
2092 bgp_capability_send (peer, AFI_IP, SAFI_UNICAST,
2093 CAPABILITY_CODE_REFRESH,
2094 CHECK_FLAG (peer->flags, flag) ?
2095 CAPABILITY_ACTION_UNSET : CAPABILITY_ACTION_SET);
2096 }
2097 else
hassoe0701b72004-05-20 09:19:34 +00002098 {
2099 if (flag == PEER_FLAG_NO_ROUTE_REFRESH_CAP)
2100 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2101 else if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2102 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2103 else if (flag == PEER_FLAG_PASSIVE)
2104 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
2105 else if (flag == PEER_FLAG_ENFORCE_MULTIHOP)
2106 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
2107
2108 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2109 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2110 }
paul718e3742002-12-13 20:15:29 +00002111 }
2112 else
2113 BGP_EVENT_ADD (peer, BGP_Stop);
2114}
2115
2116/* Change specified peer flag. */
2117int
2118peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2119{
2120 int found;
2121 int size;
2122 struct peer_group *group;
2123 struct listnode *nn;
2124 struct peer_flag_action action;
2125
2126 memset (&action, 0, sizeof (struct peer_flag_action));
2127 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2128
2129 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2130
2131 /* No flag action is found. */
2132 if (! found)
2133 return BGP_ERR_INVALID_FLAG;
2134
2135 /* Not for peer-group member. */
2136 if (action.not_for_member && peer_group_active (peer))
2137 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2138
2139 /* When unset the peer-group member's flag we have to check
2140 peer-group configuration. */
2141 if (! set && peer_group_active (peer))
2142 if (CHECK_FLAG (peer->group->conf->flags, flag))
2143 {
2144 if (flag == PEER_FLAG_SHUTDOWN)
2145 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2146 else
2147 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2148 }
2149
2150 /* Flag conflict check. */
2151 if (set
2152 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2153 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2154 return BGP_ERR_PEER_FLAG_CONFLICT;
2155
2156 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2157 {
2158 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2159 return 0;
2160 if (! set && ! CHECK_FLAG (peer->flags, flag))
2161 return 0;
2162 }
2163
2164 if (set)
2165 SET_FLAG (peer->flags, flag);
2166 else
2167 UNSET_FLAG (peer->flags, flag);
2168
2169 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2170 {
2171 if (action.type == peer_change_reset)
2172 peer_flag_modify_action (peer, flag);
2173
2174 return 0;
2175 }
2176
2177 /* peer-group member updates. */
2178 group = peer->group;
2179
2180 LIST_LOOP (group->peer, peer, nn)
2181 {
2182 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2183 continue;
2184
2185 if (! set && ! CHECK_FLAG (peer->flags, flag))
2186 continue;
2187
2188 if (set)
2189 SET_FLAG (peer->flags, flag);
2190 else
2191 UNSET_FLAG (peer->flags, flag);
2192
2193 if (action.type == peer_change_reset)
2194 peer_flag_modify_action (peer, flag);
2195 }
2196 return 0;
2197}
2198
2199int
2200peer_flag_set (struct peer *peer, u_int32_t flag)
2201{
2202 return peer_flag_modify (peer, flag, 1);
2203}
2204
2205int
2206peer_flag_unset (struct peer *peer, u_int32_t flag)
2207{
2208 return peer_flag_modify (peer, flag, 0);
2209}
2210
2211int
2212peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2213{
2214 if (peer->af_group[afi][safi])
2215 return 1;
2216 return 0;
2217}
2218
2219int
2220peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2221 int set)
2222{
2223 int found;
2224 int size;
2225 struct listnode *nn;
2226 struct peer_group *group;
2227 struct peer_flag_action action;
2228
2229 memset (&action, 0, sizeof (struct peer_flag_action));
2230 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2231
2232 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2233
2234 /* No flag action is found. */
2235 if (! found)
2236 return BGP_ERR_INVALID_FLAG;
2237
2238 /* Adress family must be activated. */
2239 if (! peer->afc[afi][safi])
2240 return BGP_ERR_PEER_INACTIVE;
2241
2242 /* Not for peer-group member. */
2243 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2244 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2245
2246 /* Spcecial check for reflector client. */
2247 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2248 && peer_sort (peer) != BGP_PEER_IBGP)
2249 return BGP_ERR_NOT_INTERNAL_PEER;
2250
2251 /* Spcecial check for remove-private-AS. */
2252 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2253 && peer_sort (peer) == BGP_PEER_IBGP)
2254 return BGP_ERR_REMOVE_PRIVATE_AS;
2255
2256 /* When unset the peer-group member's flag we have to check
2257 peer-group configuration. */
2258 if (! set && peer->af_group[afi][safi])
2259 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2260 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2261
2262 /* When current flag configuration is same as requested one. */
2263 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2264 {
2265 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2266 return 0;
2267 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2268 return 0;
2269 }
2270
2271 if (set)
2272 SET_FLAG (peer->af_flags[afi][safi], flag);
2273 else
2274 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2275
2276 /* Execute action when peer is established. */
2277 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2278 && peer->status == Established)
2279 {
2280 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2281 bgp_clear_adj_in (peer, afi, safi);
2282 else
hassoe0701b72004-05-20 09:19:34 +00002283 {
2284 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2285 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2286 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2287 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2288 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2289 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2290 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2291 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2292
2293 peer_change_action (peer, afi, safi, action.type);
2294 }
2295
paul718e3742002-12-13 20:15:29 +00002296 }
2297
2298 /* Peer group member updates. */
2299 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2300 {
2301 group = peer->group;
2302
2303 LIST_LOOP (group->peer, peer, nn)
2304 {
2305 if (! peer->af_group[afi][safi])
2306 continue;
2307
2308 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2309 continue;
2310
2311 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2312 continue;
2313
2314 if (set)
2315 SET_FLAG (peer->af_flags[afi][safi], flag);
2316 else
2317 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2318
2319 if (peer->status == Established)
2320 {
2321 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2322 bgp_clear_adj_in (peer, afi, safi);
2323 else
hassoe0701b72004-05-20 09:19:34 +00002324 {
2325 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2326 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2327 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2328 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2329 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2330 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2331 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2332 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2333
2334 peer_change_action (peer, afi, safi, action.type);
2335 }
paul718e3742002-12-13 20:15:29 +00002336 }
2337 }
2338 }
2339 return 0;
2340}
2341
2342int
2343peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2344{
2345 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2346}
2347
2348int
2349peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2350{
2351 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2352}
2353
2354/* EBGP multihop configuration. */
2355int
2356peer_ebgp_multihop_set (struct peer *peer, int ttl)
2357{
2358 struct peer_group *group;
2359 struct listnode *nn;
2360
2361 if (peer_sort (peer) == BGP_PEER_IBGP)
2362 return 0;
2363
2364 peer->ttl = ttl;
2365
2366 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2367 {
pauleb821182004-05-01 08:44:08 +00002368 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2369 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002370 }
2371 else
2372 {
2373 group = peer->group;
2374 LIST_LOOP (group->peer, peer, nn)
pauleb821182004-05-01 08:44:08 +00002375 {
2376 if (peer_sort (peer) == BGP_PEER_IBGP)
2377 continue;
paul718e3742002-12-13 20:15:29 +00002378
pauleb821182004-05-01 08:44:08 +00002379 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002380
pauleb821182004-05-01 08:44:08 +00002381 if (peer->fd >= 0)
2382 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2383 }
paul718e3742002-12-13 20:15:29 +00002384 }
2385 return 0;
2386}
2387
2388int
2389peer_ebgp_multihop_unset (struct peer *peer)
2390{
2391 struct peer_group *group;
2392 struct listnode *nn;
2393
2394 if (peer_sort (peer) == BGP_PEER_IBGP)
2395 return 0;
2396
2397 if (peer_group_active (peer))
2398 peer->ttl = peer->group->conf->ttl;
2399 else
2400 peer->ttl = 1;
2401
2402 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2403 {
pauleb821182004-05-01 08:44:08 +00002404 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2405 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002406 }
2407 else
2408 {
2409 group = peer->group;
2410 LIST_LOOP (group->peer, peer, nn)
pauleb821182004-05-01 08:44:08 +00002411 {
2412 if (peer_sort (peer) == BGP_PEER_IBGP)
2413 continue;
paul718e3742002-12-13 20:15:29 +00002414
pauleb821182004-05-01 08:44:08 +00002415 peer->ttl = 1;
2416
2417 if (peer->fd >= 0)
2418 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2419 }
paul718e3742002-12-13 20:15:29 +00002420 }
2421 return 0;
2422}
2423
2424/* Neighbor description. */
2425int
2426peer_description_set (struct peer *peer, char *desc)
2427{
2428 if (peer->desc)
2429 XFREE (MTYPE_PEER_DESC, peer->desc);
2430
2431 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2432
2433 return 0;
2434}
2435
2436int
2437peer_description_unset (struct peer *peer)
2438{
2439 if (peer->desc)
2440 XFREE (MTYPE_PEER_DESC, peer->desc);
2441
2442 peer->desc = NULL;
2443
2444 return 0;
2445}
2446
2447/* Neighbor update-source. */
2448int
2449peer_update_source_if_set (struct peer *peer, char *ifname)
2450{
2451 struct peer_group *group;
2452 struct listnode *nn;
2453
2454 if (peer->update_if)
2455 {
2456 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2457 && strcmp (peer->update_if, ifname) == 0)
2458 return 0;
2459
2460 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2461 peer->update_if = NULL;
2462 }
2463
2464 if (peer->update_source)
2465 {
2466 sockunion_free (peer->update_source);
2467 peer->update_source = NULL;
2468 }
2469
2470 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2471
2472 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2473 {
2474 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002475 {
2476 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2477 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2478 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2479 }
paul718e3742002-12-13 20:15:29 +00002480 else
2481 BGP_EVENT_ADD (peer, BGP_Stop);
2482 return 0;
2483 }
2484
2485 /* peer-group member updates. */
2486 group = peer->group;
2487 LIST_LOOP (group->peer, peer, nn)
2488 {
2489 if (peer->update_if)
2490 {
2491 if (strcmp (peer->update_if, ifname) == 0)
2492 continue;
2493
2494 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2495 peer->update_if = NULL;
2496 }
2497
2498 if (peer->update_source)
2499 {
2500 sockunion_free (peer->update_source);
2501 peer->update_source = NULL;
2502 }
2503
2504 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2505
2506 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002507 {
2508 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2509 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2510 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2511 }
paul718e3742002-12-13 20:15:29 +00002512 else
2513 BGP_EVENT_ADD (peer, BGP_Stop);
2514 }
2515 return 0;
2516}
2517
2518int
2519peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2520{
2521 struct peer_group *group;
2522 struct listnode *nn;
2523
2524 if (peer->update_source)
2525 {
2526 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2527 && sockunion_cmp (peer->update_source, su) == 0)
2528 return 0;
2529 sockunion_free (peer->update_source);
2530 peer->update_source = NULL;
2531 }
2532
2533 if (peer->update_if)
2534 {
2535 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2536 peer->update_if = NULL;
2537 }
2538
2539 peer->update_source = sockunion_dup (su);
2540
2541 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2542 {
2543 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002544 {
2545 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2546 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2547 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2548 }
paul718e3742002-12-13 20:15:29 +00002549 else
2550 BGP_EVENT_ADD (peer, BGP_Stop);
2551 return 0;
2552 }
2553
2554 /* peer-group member updates. */
2555 group = peer->group;
2556 LIST_LOOP (group->peer, peer, nn)
2557 {
2558 if (peer->update_source)
2559 {
2560 if (sockunion_cmp (peer->update_source, su) == 0)
2561 continue;
2562 sockunion_free (peer->update_source);
2563 peer->update_source = NULL;
2564 }
2565
2566 if (peer->update_if)
2567 {
2568 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2569 peer->update_if = NULL;
2570 }
2571
2572 peer->update_source = sockunion_dup (su);
2573
2574 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002575 {
2576 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2577 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2578 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2579 }
paul718e3742002-12-13 20:15:29 +00002580 else
2581 BGP_EVENT_ADD (peer, BGP_Stop);
2582 }
2583 return 0;
2584}
2585
2586int
2587peer_update_source_unset (struct peer *peer)
2588{
2589 union sockunion *su;
2590 struct peer_group *group;
2591 struct listnode *nn;
2592
2593 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2594 && ! peer->update_source
2595 && ! peer->update_if)
2596 return 0;
2597
2598 if (peer->update_source)
2599 {
2600 sockunion_free (peer->update_source);
2601 peer->update_source = NULL;
2602 }
2603 if (peer->update_if)
2604 {
2605 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2606 peer->update_if = NULL;
2607 }
2608
2609 if (peer_group_active (peer))
2610 {
2611 group = peer->group;
2612
2613 if (group->conf->update_source)
2614 {
2615 su = sockunion_dup (group->conf->update_source);
2616 peer->update_source = su;
2617 }
2618 else if (group->conf->update_if)
2619 peer->update_if =
2620 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2621 }
2622
2623 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2624 {
2625 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002626 {
2627 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2628 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2629 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2630 }
paul718e3742002-12-13 20:15:29 +00002631 else
2632 BGP_EVENT_ADD (peer, BGP_Stop);
2633 return 0;
2634 }
2635
2636 /* peer-group member updates. */
2637 group = peer->group;
2638 LIST_LOOP (group->peer, peer, nn)
2639 {
2640 if (! peer->update_source && ! peer->update_if)
2641 continue;
2642
2643 if (peer->update_source)
2644 {
2645 sockunion_free (peer->update_source);
2646 peer->update_source = NULL;
2647 }
2648
2649 if (peer->update_if)
2650 {
2651 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2652 peer->update_if = NULL;
2653 }
2654
2655 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002656 {
2657 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2658 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2659 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2660 }
paul718e3742002-12-13 20:15:29 +00002661 else
2662 BGP_EVENT_ADD (peer, BGP_Stop);
2663 }
2664 return 0;
2665}
2666
2667int
2668peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
2669 char *rmap)
2670{
2671 struct peer_group *group;
2672 struct listnode *nn;
2673
2674 /* Adress family must be activated. */
2675 if (! peer->afc[afi][safi])
2676 return BGP_ERR_PEER_INACTIVE;
2677
2678 /* Default originate can't be used for peer group memeber. */
2679 if (peer_is_group_member (peer, afi, safi))
2680 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2681
2682 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
2683 || (rmap && ! peer->default_rmap[afi][safi].name)
2684 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
2685 {
2686 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2687
2688 if (rmap)
2689 {
2690 if (peer->default_rmap[afi][safi].name)
2691 free (peer->default_rmap[afi][safi].name);
2692 peer->default_rmap[afi][safi].name = strdup (rmap);
2693 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2694 }
2695 }
2696
2697 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2698 {
2699 if (peer->status == Established && peer->afc_nego[afi][safi])
2700 bgp_default_originate (peer, afi, safi, 0);
2701 return 0;
2702 }
2703
2704 /* peer-group member updates. */
2705 group = peer->group;
2706 LIST_LOOP (group->peer, peer, nn)
2707 {
2708 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2709
2710 if (rmap)
2711 {
2712 if (peer->default_rmap[afi][safi].name)
2713 free (peer->default_rmap[afi][safi].name);
2714 peer->default_rmap[afi][safi].name = strdup (rmap);
2715 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2716 }
2717
2718 if (peer->status == Established && peer->afc_nego[afi][safi])
2719 bgp_default_originate (peer, afi, safi, 0);
2720 }
2721 return 0;
2722}
2723
2724int
2725peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
2726{
2727 struct peer_group *group;
2728 struct listnode *nn;
2729
2730 /* Adress family must be activated. */
2731 if (! peer->afc[afi][safi])
2732 return BGP_ERR_PEER_INACTIVE;
2733
2734 /* Default originate can't be used for peer group memeber. */
2735 if (peer_is_group_member (peer, afi, safi))
2736 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2737
2738 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
2739 {
2740 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2741
2742 if (peer->default_rmap[afi][safi].name)
2743 free (peer->default_rmap[afi][safi].name);
2744 peer->default_rmap[afi][safi].name = NULL;
2745 peer->default_rmap[afi][safi].map = NULL;
2746 }
2747
2748 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2749 {
2750 if (peer->status == Established && peer->afc_nego[afi][safi])
2751 bgp_default_originate (peer, afi, safi, 1);
2752 return 0;
2753 }
2754
2755 /* peer-group member updates. */
2756 group = peer->group;
2757 LIST_LOOP (group->peer, peer, nn)
2758 {
2759 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2760
2761 if (peer->default_rmap[afi][safi].name)
2762 free (peer->default_rmap[afi][safi].name);
2763 peer->default_rmap[afi][safi].name = NULL;
2764 peer->default_rmap[afi][safi].map = NULL;
2765
2766 if (peer->status == Established && peer->afc_nego[afi][safi])
2767 bgp_default_originate (peer, afi, safi, 1);
2768 }
2769 return 0;
2770}
2771
2772int
2773peer_port_set (struct peer *peer, u_int16_t port)
2774{
2775 peer->port = port;
2776 return 0;
2777}
2778
2779int
2780peer_port_unset (struct peer *peer)
2781{
2782 peer->port = BGP_PORT_DEFAULT;
2783 return 0;
2784}
2785
2786/* neighbor weight. */
2787int
2788peer_weight_set (struct peer *peer, u_int16_t weight)
2789{
2790 struct peer_group *group;
2791 struct listnode *nn;
2792
2793 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
2794 peer->weight = weight;
2795
2796 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2797 return 0;
2798
2799 /* peer-group member updates. */
2800 group = peer->group;
2801 LIST_LOOP (group->peer, peer, nn)
2802 {
2803 peer->weight = group->conf->weight;
2804 }
2805 return 0;
2806}
2807
2808int
2809peer_weight_unset (struct peer *peer)
2810{
2811 struct peer_group *group;
2812 struct listnode *nn;
2813
2814 /* Set default weight. */
2815 if (peer_group_active (peer))
2816 peer->weight = peer->group->conf->weight;
2817 else
2818 peer->weight = 0;
2819
2820 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
2821
2822 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2823 return 0;
2824
2825 /* peer-group member updates. */
2826 group = peer->group;
2827 LIST_LOOP (group->peer, peer, nn)
2828 {
2829 peer->weight = 0;
2830 }
2831 return 0;
2832}
2833
2834int
2835peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
2836{
2837 struct peer_group *group;
2838 struct listnode *nn;
2839
2840 /* Not for peer group memeber. */
2841 if (peer_group_active (peer))
2842 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2843
2844 /* keepalive value check. */
2845 if (keepalive > 65535)
2846 return BGP_ERR_INVALID_VALUE;
2847
2848 /* Holdtime value check. */
2849 if (holdtime > 65535)
2850 return BGP_ERR_INVALID_VALUE;
2851
2852 /* Holdtime value must be either 0 or greater than 3. */
2853 if (holdtime < 3 && holdtime != 0)
2854 return BGP_ERR_INVALID_VALUE;
2855
2856 /* Set value to the configuration. */
2857 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
2858 peer->holdtime = holdtime;
2859 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
2860
2861 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2862 return 0;
2863
2864 /* peer-group member updates. */
2865 group = peer->group;
2866 LIST_LOOP (group->peer, peer, nn)
2867 {
2868 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
2869 peer->holdtime = group->conf->holdtime;
2870 peer->keepalive = group->conf->keepalive;
2871 }
2872 return 0;
2873}
2874
2875int
2876peer_timers_unset (struct peer *peer)
2877{
2878 struct peer_group *group;
2879 struct listnode *nn;
2880
2881 if (peer_group_active (peer))
2882 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2883
2884 /* Clear configuration. */
2885 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
2886 peer->keepalive = 0;
2887 peer->holdtime = 0;
2888
2889 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2890 return 0;
2891
2892 /* peer-group member updates. */
2893 group = peer->group;
2894 LIST_LOOP (group->peer, peer, nn)
2895 {
2896 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
2897 peer->holdtime = 0;
2898 peer->keepalive = 0;
2899 }
2900
2901 return 0;
2902}
2903
2904int
2905peer_timers_connect_set (struct peer *peer, u_int32_t connect)
2906{
2907 if (peer_group_active (peer))
2908 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2909
2910 if (connect > 65535)
2911 return BGP_ERR_INVALID_VALUE;
2912
2913 /* Set value to the configuration. */
2914 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
2915 peer->connect = connect;
2916
2917 /* Set value to timer setting. */
2918 peer->v_connect = connect;
2919
2920 return 0;
2921}
2922
2923int
2924peer_timers_connect_unset (struct peer *peer)
2925{
2926 if (peer_group_active (peer))
2927 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2928
2929 /* Clear configuration. */
2930 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
2931 peer->connect = 0;
2932
2933 /* Set timer setting to default value. */
2934 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
2935
2936 return 0;
2937}
2938
2939int
2940peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
2941{
2942 if (peer_group_active (peer))
2943 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2944
2945 if (routeadv > 600)
2946 return BGP_ERR_INVALID_VALUE;
2947
2948 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
2949 peer->routeadv = routeadv;
2950 peer->v_routeadv = routeadv;
2951
2952 return 0;
2953}
2954
2955int
2956peer_advertise_interval_unset (struct peer *peer)
2957{
2958 if (peer_group_active (peer))
2959 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2960
2961 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
2962 peer->routeadv = 0;
2963
2964 if (peer_sort (peer) == BGP_PEER_IBGP)
2965 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
2966 else
2967 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
2968
2969 return 0;
2970}
2971
2972int
2973peer_version_set (struct peer *peer, int version)
2974{
2975 if (version != BGP_VERSION_4 && version != BGP_VERSION_MP_4_DRAFT_00)
2976 return BGP_ERR_INVALID_VALUE;
2977
2978 peer->version = version;
2979
2980 return 0;
2981}
2982
2983int
2984peer_version_unset (struct peer *peer)
2985{
2986 peer->version = BGP_VERSION_4;
2987 return 0;
2988}
2989
2990/* neighbor interface */
2991int
2992peer_interface_set (struct peer *peer, char *str)
2993{
2994 if (peer->ifname)
2995 free (peer->ifname);
2996 peer->ifname = strdup (str);
2997
2998 return 0;
2999}
3000
3001int
3002peer_interface_unset (struct peer *peer)
3003{
3004 if (peer->ifname)
3005 free (peer->ifname);
3006 peer->ifname = NULL;
3007
3008 return 0;
3009}
3010
3011/* Allow-as in. */
3012int
3013peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3014{
3015 struct peer_group *group;
3016 struct listnode *nn;
3017
3018 if (allow_num < 1 || allow_num > 10)
3019 return BGP_ERR_INVALID_VALUE;
3020
3021 if (peer->allowas_in[afi][safi] != allow_num)
3022 {
3023 peer->allowas_in[afi][safi] = allow_num;
3024 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3025 peer_change_action (peer, afi, safi, peer_change_reset_in);
3026 }
3027
3028 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3029 return 0;
3030
3031 group = peer->group;
3032 LIST_LOOP (group->peer, peer, nn)
3033 {
3034 if (peer->allowas_in[afi][safi] != allow_num)
3035 {
3036 peer->allowas_in[afi][safi] = allow_num;
3037 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3038 peer_change_action (peer, afi, safi, peer_change_reset_in);
3039 }
3040
3041 }
3042 return 0;
3043}
3044
3045int
3046peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3047{
3048 struct peer_group *group;
3049 struct listnode *nn;
3050
3051 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3052 {
3053 peer->allowas_in[afi][safi] = 0;
3054 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3055 }
3056
3057 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3058 return 0;
3059
3060 group = peer->group;
3061 LIST_LOOP (group->peer, peer, nn)
3062 {
3063 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3064 {
3065 peer->allowas_in[afi][safi] = 0;
3066 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3067 }
3068 }
3069 return 0;
3070}
3071
3072int
3073peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3074{
3075 struct bgp *bgp = peer->bgp;
3076 struct peer_group *group;
3077 struct listnode *nn;
3078
3079 if (peer_sort (peer) != BGP_PEER_EBGP
3080 && peer_sort (peer) != BGP_PEER_INTERNAL)
3081 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3082
3083 if (bgp->as == as)
3084 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3085
3086 if (peer_group_active (peer))
3087 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3088
3089 if (peer->change_local_as == as &&
3090 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3091 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3092 return 0;
3093
3094 peer->change_local_as = as;
3095 if (no_prepend)
3096 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3097 else
3098 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3099
3100 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3101 {
3102 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003103 {
3104 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3105 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3106 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3107 }
paul718e3742002-12-13 20:15:29 +00003108 else
3109 BGP_EVENT_ADD (peer, BGP_Stop);
3110
3111 return 0;
3112 }
3113
3114 group = peer->group;
3115 LIST_LOOP (group->peer, peer, nn)
3116 {
3117 peer->change_local_as = as;
3118 if (no_prepend)
3119 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3120 else
3121 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3122
3123 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003124 {
3125 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3126 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3127 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3128 }
paul718e3742002-12-13 20:15:29 +00003129 else
3130 BGP_EVENT_ADD (peer, BGP_Stop);
3131 }
3132
3133 return 0;
3134}
3135
3136int
3137peer_local_as_unset (struct peer *peer)
3138{
3139 struct peer_group *group;
3140 struct listnode *nn;
3141
3142 if (peer_group_active (peer))
3143 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3144
3145 if (! peer->change_local_as)
3146 return 0;
3147
3148 peer->change_local_as = 0;
3149 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3150
3151 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3152 {
3153 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003154 {
3155 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3156 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3157 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3158 }
paul718e3742002-12-13 20:15:29 +00003159 else
3160 BGP_EVENT_ADD (peer, BGP_Stop);
3161
3162 return 0;
3163 }
3164
3165 group = peer->group;
3166 LIST_LOOP (group->peer, peer, nn)
3167 {
3168 peer->change_local_as = 0;
3169 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3170
3171 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003172 {
3173 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3174 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3175 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3176 }
paul718e3742002-12-13 20:15:29 +00003177 else
3178 BGP_EVENT_ADD (peer, BGP_Stop);
3179 }
3180 return 0;
3181}
3182
3183/* Set distribute list to the peer. */
3184int
3185peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
3186 char *name)
3187{
3188 struct bgp_filter *filter;
3189 struct peer_group *group;
3190 struct listnode *nn;
3191
3192 if (! peer->afc[afi][safi])
3193 return BGP_ERR_PEER_INACTIVE;
3194
3195 if (direct != FILTER_IN && direct != FILTER_OUT)
3196 return BGP_ERR_INVALID_VALUE;
3197
3198 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3199 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3200
3201 filter = &peer->filter[afi][safi];
3202
3203 if (filter->plist[direct].name)
3204 return BGP_ERR_PEER_FILTER_CONFLICT;
3205
3206 if (filter->dlist[direct].name)
3207 free (filter->dlist[direct].name);
3208 filter->dlist[direct].name = strdup (name);
3209 filter->dlist[direct].alist = access_list_lookup (afi, name);
3210
3211 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3212 return 0;
3213
3214 group = peer->group;
3215 LIST_LOOP (group->peer, peer, nn)
3216 {
3217 filter = &peer->filter[afi][safi];
3218
3219 if (! peer->af_group[afi][safi])
3220 continue;
3221
3222 if (filter->dlist[direct].name)
3223 free (filter->dlist[direct].name);
3224 filter->dlist[direct].name = strdup (name);
3225 filter->dlist[direct].alist = access_list_lookup (afi, name);
3226 }
3227
3228 return 0;
3229}
3230
3231int
3232peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3233{
3234 struct bgp_filter *filter;
3235 struct bgp_filter *gfilter;
3236 struct peer_group *group;
3237 struct listnode *nn;
3238
3239 if (! peer->afc[afi][safi])
3240 return BGP_ERR_PEER_INACTIVE;
3241
3242 if (direct != FILTER_IN && direct != FILTER_OUT)
3243 return BGP_ERR_INVALID_VALUE;
3244
3245 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3246 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3247
3248 filter = &peer->filter[afi][safi];
3249
3250 /* apply peer-group filter */
3251 if (peer->af_group[afi][safi])
3252 {
3253 gfilter = &peer->group->conf->filter[afi][safi];
3254
3255 if (gfilter->dlist[direct].name)
3256 {
3257 if (filter->dlist[direct].name)
3258 free (filter->dlist[direct].name);
3259 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3260 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3261 return 0;
3262 }
3263 }
3264
3265 if (filter->dlist[direct].name)
3266 free (filter->dlist[direct].name);
3267 filter->dlist[direct].name = NULL;
3268 filter->dlist[direct].alist = NULL;
3269
3270 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3271 return 0;
3272
3273 group = peer->group;
3274 LIST_LOOP (group->peer, peer, nn)
3275 {
3276 filter = &peer->filter[afi][safi];
3277
3278 if (! peer->af_group[afi][safi])
3279 continue;
3280
3281 if (filter->dlist[direct].name)
3282 free (filter->dlist[direct].name);
3283 filter->dlist[direct].name = NULL;
3284 filter->dlist[direct].alist = NULL;
3285 }
3286
3287 return 0;
3288}
3289
3290/* Update distribute list. */
3291void
3292peer_distribute_update (struct access_list *access)
3293{
3294 afi_t afi;
3295 safi_t safi;
3296 int direct;
3297 struct listnode *nn, *nm;
3298 struct bgp *bgp;
3299 struct peer *peer;
3300 struct peer_group *group;
3301 struct bgp_filter *filter;
3302
3303 LIST_LOOP (bm->bgp, bgp, nn)
3304 {
3305 LIST_LOOP (bgp->peer, peer, nm)
3306 {
3307 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3308 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3309 {
3310 filter = &peer->filter[afi][safi];
3311
3312 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3313 {
3314 if (filter->dlist[direct].name)
3315 filter->dlist[direct].alist =
3316 access_list_lookup (afi, filter->dlist[direct].name);
3317 else
3318 filter->dlist[direct].alist = NULL;
3319 }
3320 }
3321 }
3322 LIST_LOOP (bgp->group, group, nm)
3323 {
3324 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3325 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3326 {
3327 filter = &group->conf->filter[afi][safi];
3328
3329 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3330 {
3331 if (filter->dlist[direct].name)
3332 filter->dlist[direct].alist =
3333 access_list_lookup (afi, filter->dlist[direct].name);
3334 else
3335 filter->dlist[direct].alist = NULL;
3336 }
3337 }
3338 }
3339 }
3340}
3341
3342/* Set prefix list to the peer. */
3343int
3344peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
3345 char *name)
3346{
3347 struct bgp_filter *filter;
3348 struct peer_group *group;
3349 struct listnode *nn;
3350
3351 if (! peer->afc[afi][safi])
3352 return BGP_ERR_PEER_INACTIVE;
3353
3354 if (direct != FILTER_IN && direct != FILTER_OUT)
3355 return BGP_ERR_INVALID_VALUE;
3356
3357 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3358 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3359
3360 filter = &peer->filter[afi][safi];
3361
3362 if (filter->dlist[direct].name)
3363 return BGP_ERR_PEER_FILTER_CONFLICT;
3364
3365 if (filter->plist[direct].name)
3366 free (filter->plist[direct].name);
3367 filter->plist[direct].name = strdup (name);
3368 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3369
3370 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3371 return 0;
3372
3373 group = peer->group;
3374 LIST_LOOP (group->peer, peer, nn)
3375 {
3376 filter = &peer->filter[afi][safi];
3377
3378 if (! peer->af_group[afi][safi])
3379 continue;
3380
3381 if (filter->plist[direct].name)
3382 free (filter->plist[direct].name);
3383 filter->plist[direct].name = strdup (name);
3384 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3385 }
3386 return 0;
3387}
3388
3389int
3390peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3391{
3392 struct bgp_filter *filter;
3393 struct bgp_filter *gfilter;
3394 struct peer_group *group;
3395 struct listnode *nn;
3396
3397 if (! peer->afc[afi][safi])
3398 return BGP_ERR_PEER_INACTIVE;
3399
3400 if (direct != FILTER_IN && direct != FILTER_OUT)
3401 return BGP_ERR_INVALID_VALUE;
3402
3403 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3404 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3405
3406 filter = &peer->filter[afi][safi];
3407
3408 /* apply peer-group filter */
3409 if (peer->af_group[afi][safi])
3410 {
3411 gfilter = &peer->group->conf->filter[afi][safi];
3412
3413 if (gfilter->plist[direct].name)
3414 {
3415 if (filter->plist[direct].name)
3416 free (filter->plist[direct].name);
3417 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3418 filter->plist[direct].plist = gfilter->plist[direct].plist;
3419 return 0;
3420 }
3421 }
3422
3423 if (filter->plist[direct].name)
3424 free (filter->plist[direct].name);
3425 filter->plist[direct].name = NULL;
3426 filter->plist[direct].plist = NULL;
3427
3428 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3429 return 0;
3430
3431 group = peer->group;
3432 LIST_LOOP (group->peer, peer, nn)
3433 {
3434 filter = &peer->filter[afi][safi];
3435
3436 if (! peer->af_group[afi][safi])
3437 continue;
3438
3439 if (filter->plist[direct].name)
3440 free (filter->plist[direct].name);
3441 filter->plist[direct].name = NULL;
3442 filter->plist[direct].plist = NULL;
3443 }
3444
3445 return 0;
3446}
3447
3448/* Update prefix-list list. */
3449void
3450peer_prefix_list_update (struct prefix_list *plist)
3451{
3452 struct listnode *nn, *nm;
3453 struct bgp *bgp;
3454 struct peer *peer;
3455 struct peer_group *group;
3456 struct bgp_filter *filter;
3457 afi_t afi;
3458 safi_t safi;
3459 int direct;
3460
3461 LIST_LOOP (bm->bgp, bgp, nn)
3462 {
3463 LIST_LOOP (bgp->peer, peer, nm)
3464 {
3465 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3466 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3467 {
3468 filter = &peer->filter[afi][safi];
3469
3470 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3471 {
3472 if (filter->plist[direct].name)
3473 filter->plist[direct].plist =
3474 prefix_list_lookup (afi, filter->plist[direct].name);
3475 else
3476 filter->plist[direct].plist = NULL;
3477 }
3478 }
3479 }
3480 LIST_LOOP (bgp->group, group, nm)
3481 {
3482 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3483 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3484 {
3485 filter = &group->conf->filter[afi][safi];
3486
3487 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3488 {
3489 if (filter->plist[direct].name)
3490 filter->plist[direct].plist =
3491 prefix_list_lookup (afi, filter->plist[direct].name);
3492 else
3493 filter->plist[direct].plist = NULL;
3494 }
3495 }
3496 }
3497 }
3498}
3499
3500int
3501peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
3502 char *name)
3503{
3504 struct bgp_filter *filter;
3505 struct peer_group *group;
3506 struct listnode *nn;
3507
3508 if (! peer->afc[afi][safi])
3509 return BGP_ERR_PEER_INACTIVE;
3510
3511 if (direct != FILTER_IN && direct != FILTER_OUT)
3512 return BGP_ERR_INVALID_VALUE;
3513
3514 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3515 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3516
3517 filter = &peer->filter[afi][safi];
3518
3519 if (filter->aslist[direct].name)
3520 free (filter->aslist[direct].name);
3521 filter->aslist[direct].name = strdup (name);
3522 filter->aslist[direct].aslist = as_list_lookup (name);
3523
3524 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3525 return 0;
3526
3527 group = peer->group;
3528 LIST_LOOP (group->peer, peer, nn)
3529 {
3530 filter = &peer->filter[afi][safi];
3531
3532 if (! peer->af_group[afi][safi])
3533 continue;
3534
3535 if (filter->aslist[direct].name)
3536 free (filter->aslist[direct].name);
3537 filter->aslist[direct].name = strdup (name);
3538 filter->aslist[direct].aslist = as_list_lookup (name);
3539 }
3540 return 0;
3541}
3542
3543int
3544peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3545{
3546 struct bgp_filter *filter;
3547 struct bgp_filter *gfilter;
3548 struct peer_group *group;
3549 struct listnode *nn;
3550
3551 if (! peer->afc[afi][safi])
3552 return BGP_ERR_PEER_INACTIVE;
3553
3554 if (direct != FILTER_IN && direct != FILTER_OUT)
3555 return BGP_ERR_INVALID_VALUE;
3556
3557 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3558 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3559
3560 filter = &peer->filter[afi][safi];
3561
3562 /* apply peer-group filter */
3563 if (peer->af_group[afi][safi])
3564 {
3565 gfilter = &peer->group->conf->filter[afi][safi];
3566
3567 if (gfilter->aslist[direct].name)
3568 {
3569 if (filter->aslist[direct].name)
3570 free (filter->aslist[direct].name);
3571 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
3572 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
3573 return 0;
3574 }
3575 }
3576
3577 if (filter->aslist[direct].name)
3578 free (filter->aslist[direct].name);
3579 filter->aslist[direct].name = NULL;
3580 filter->aslist[direct].aslist = NULL;
3581
3582 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3583 return 0;
3584
3585 group = peer->group;
3586 LIST_LOOP (group->peer, peer, nn)
3587 {
3588 filter = &peer->filter[afi][safi];
3589
3590 if (! peer->af_group[afi][safi])
3591 continue;
3592
3593 if (filter->aslist[direct].name)
3594 free (filter->aslist[direct].name);
3595 filter->aslist[direct].name = NULL;
3596 filter->aslist[direct].aslist = NULL;
3597 }
3598
3599 return 0;
3600}
3601
3602void
3603peer_aslist_update ()
3604{
3605 afi_t afi;
3606 safi_t safi;
3607 int direct;
3608 struct listnode *nn, *nm;
3609 struct bgp *bgp;
3610 struct peer *peer;
3611 struct peer_group *group;
3612 struct bgp_filter *filter;
3613
3614 LIST_LOOP (bm->bgp, bgp, nn)
3615 {
3616 LIST_LOOP (bgp->peer, peer, nm)
3617 {
3618 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3619 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3620 {
3621 filter = &peer->filter[afi][safi];
3622
3623 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3624 {
3625 if (filter->aslist[direct].name)
3626 filter->aslist[direct].aslist =
3627 as_list_lookup (filter->aslist[direct].name);
3628 else
3629 filter->aslist[direct].aslist = NULL;
3630 }
3631 }
3632 }
3633 LIST_LOOP (bgp->group, group, nm)
3634 {
3635 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3636 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3637 {
3638 filter = &group->conf->filter[afi][safi];
3639
3640 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3641 {
3642 if (filter->aslist[direct].name)
3643 filter->aslist[direct].aslist =
3644 as_list_lookup (filter->aslist[direct].name);
3645 else
3646 filter->aslist[direct].aslist = NULL;
3647 }
3648 }
3649 }
3650 }
3651}
3652
3653/* Set route-map to the peer. */
3654int
3655peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
3656 char *name)
3657{
3658 struct bgp_filter *filter;
3659 struct peer_group *group;
3660 struct listnode *nn;
3661
3662 if (! peer->afc[afi][safi])
3663 return BGP_ERR_PEER_INACTIVE;
3664
3665 if (direct != FILTER_IN && direct != FILTER_OUT)
3666 return BGP_ERR_INVALID_VALUE;
3667
3668 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3669 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3670
3671 filter = &peer->filter[afi][safi];
3672
3673 if (filter->map[direct].name)
3674 free (filter->map[direct].name);
3675
3676 filter->map[direct].name = strdup (name);
3677 filter->map[direct].map = route_map_lookup_by_name (name);
3678
3679 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3680 return 0;
3681
3682 group = peer->group;
3683 LIST_LOOP (group->peer, peer, nn)
3684 {
3685 filter = &peer->filter[afi][safi];
3686
3687 if (! peer->af_group[afi][safi])
3688 continue;
3689
3690 if (filter->map[direct].name)
3691 free (filter->map[direct].name);
3692 filter->map[direct].name = strdup (name);
3693 filter->map[direct].map = route_map_lookup_by_name (name);
3694 }
3695 return 0;
3696}
3697
3698/* Unset route-map from the peer. */
3699int
3700peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3701{
3702 struct bgp_filter *filter;
3703 struct bgp_filter *gfilter;
3704 struct peer_group *group;
3705 struct listnode *nn;
3706
3707 if (! peer->afc[afi][safi])
3708 return BGP_ERR_PEER_INACTIVE;
3709
3710 if (direct != FILTER_IN && direct != FILTER_OUT)
3711 return BGP_ERR_INVALID_VALUE;
3712
3713 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3714 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3715
3716 filter = &peer->filter[afi][safi];
3717
3718 /* apply peer-group filter */
3719 if (peer->af_group[afi][safi])
3720 {
3721 gfilter = &peer->group->conf->filter[afi][safi];
3722
3723 if (gfilter->map[direct].name)
3724 {
3725 if (filter->map[direct].name)
3726 free (filter->map[direct].name);
3727 filter->map[direct].name = strdup (gfilter->map[direct].name);
3728 filter->map[direct].map = gfilter->map[direct].map;
3729 return 0;
3730 }
3731 }
3732
3733 if (filter->map[direct].name)
3734 free (filter->map[direct].name);
3735 filter->map[direct].name = NULL;
3736 filter->map[direct].map = NULL;
3737
3738 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3739 return 0;
3740
3741 group = peer->group;
3742 LIST_LOOP (group->peer, peer, nn)
3743 {
3744 filter = &peer->filter[afi][safi];
3745
3746 if (! peer->af_group[afi][safi])
3747 continue;
3748
3749 if (filter->map[direct].name)
3750 free (filter->map[direct].name);
3751 filter->map[direct].name = NULL;
3752 filter->map[direct].map = NULL;
3753 }
3754 return 0;
3755}
3756
3757/* Set unsuppress-map to the peer. */
3758int
3759peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi, char *name)
3760{
3761 struct bgp_filter *filter;
3762 struct peer_group *group;
3763 struct listnode *nn;
3764
3765 if (! peer->afc[afi][safi])
3766 return BGP_ERR_PEER_INACTIVE;
3767
3768 if (peer_is_group_member (peer, afi, safi))
3769 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3770
3771 filter = &peer->filter[afi][safi];
3772
3773 if (filter->usmap.name)
3774 free (filter->usmap.name);
3775
3776 filter->usmap.name = strdup (name);
3777 filter->usmap.map = route_map_lookup_by_name (name);
3778
3779 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3780 return 0;
3781
3782 group = peer->group;
3783 LIST_LOOP (group->peer, peer, nn)
3784 {
3785 filter = &peer->filter[afi][safi];
3786
3787 if (! peer->af_group[afi][safi])
3788 continue;
3789
3790 if (filter->usmap.name)
3791 free (filter->usmap.name);
3792 filter->usmap.name = strdup (name);
3793 filter->usmap.map = route_map_lookup_by_name (name);
3794 }
3795 return 0;
3796}
3797
3798/* Unset route-map from the peer. */
3799int
3800peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
3801{
3802 struct bgp_filter *filter;
3803 struct peer_group *group;
3804 struct listnode *nn;
3805
3806 if (! peer->afc[afi][safi])
3807 return BGP_ERR_PEER_INACTIVE;
3808
3809 if (peer_is_group_member (peer, afi, safi))
3810 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3811
3812 filter = &peer->filter[afi][safi];
3813
3814 if (filter->usmap.name)
3815 free (filter->usmap.name);
3816 filter->usmap.name = NULL;
3817 filter->usmap.map = NULL;
3818
3819 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3820 return 0;
3821
3822 group = peer->group;
3823 LIST_LOOP (group->peer, peer, nn)
3824 {
3825 filter = &peer->filter[afi][safi];
3826
3827 if (! peer->af_group[afi][safi])
3828 continue;
3829
3830 if (filter->usmap.name)
3831 free (filter->usmap.name);
3832 filter->usmap.name = NULL;
3833 filter->usmap.map = NULL;
3834 }
3835 return 0;
3836}
3837
3838int
3839peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hassoe0701b72004-05-20 09:19:34 +00003840 u_int32_t max, u_char threshold, int warning)
paul718e3742002-12-13 20:15:29 +00003841{
3842 struct peer_group *group;
3843 struct listnode *nn;
3844
3845 if (! peer->afc[afi][safi])
3846 return BGP_ERR_PEER_INACTIVE;
3847
3848 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3849 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00003850 peer->pmax_threshold[afi][safi] = threshold;
paul718e3742002-12-13 20:15:29 +00003851 if (warning)
3852 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3853 else
3854 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3855
3856 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3857 return 0;
3858
3859 group = peer->group;
3860 LIST_LOOP (group->peer, peer, nn)
3861 {
3862 if (! peer->af_group[afi][safi])
3863 continue;
3864
3865 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3866 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00003867 peer->pmax_threshold[afi][safi] = threshold;
paul718e3742002-12-13 20:15:29 +00003868 if (warning)
3869 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3870 else
3871 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3872 }
3873 return 0;
3874}
3875
3876int
3877peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
3878{
3879 struct peer_group *group;
3880 struct listnode *nn;
3881
3882 if (! peer->afc[afi][safi])
3883 return BGP_ERR_PEER_INACTIVE;
3884
3885 /* apply peer-group config */
3886 if (peer->af_group[afi][safi])
3887 {
3888 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
3889 PEER_FLAG_MAX_PREFIX))
3890 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3891 else
3892 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3893
3894 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
3895 PEER_FLAG_MAX_PREFIX_WARNING))
3896 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3897 else
3898 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3899
3900 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00003901 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
paul718e3742002-12-13 20:15:29 +00003902 return 0;
3903 }
3904
3905 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3906 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3907 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +00003908 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +00003909
3910 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3911 return 0;
3912
3913 group = peer->group;
3914 LIST_LOOP (group->peer, peer, nn)
3915 {
3916 if (! peer->af_group[afi][safi])
3917 continue;
3918
3919 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3920 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3921 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +00003922 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +00003923 }
3924 return 0;
3925}
3926
3927int
3928peer_clear (struct peer *peer)
3929{
3930 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
3931 {
3932 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
3933 peer->v_start = BGP_INIT_START_TIMER;
3934 if (peer->status == Established)
3935 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3936 BGP_NOTIFY_CEASE_ADMIN_RESET);
3937 else
3938 BGP_EVENT_ADD (peer, BGP_Stop);
3939 }
3940 return 0;
3941}
3942
3943int
3944peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
3945 enum bgp_clear_type stype)
3946{
3947 if (peer->status != Established)
3948 return 0;
3949
3950 if (! peer->afc[afi][safi])
3951 return BGP_ERR_AF_UNCONFIGURED;
3952
3953 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
3954 bgp_announce_route (peer, afi, safi);
3955
3956 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
3957 {
3958 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
3959 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
3960 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
3961 {
3962 struct bgp_filter *filter = &peer->filter[afi][safi];
3963 u_char prefix_type;
3964
3965 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
3966 prefix_type = ORF_TYPE_PREFIX;
3967 else
3968 prefix_type = ORF_TYPE_PREFIX_OLD;
3969
3970 if (filter->plist[FILTER_IN].plist)
3971 {
3972 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
3973 bgp_route_refresh_send (peer, afi, safi,
3974 prefix_type, REFRESH_DEFER, 1);
3975 bgp_route_refresh_send (peer, afi, safi, prefix_type,
3976 REFRESH_IMMEDIATE, 0);
3977 }
3978 else
3979 {
3980 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
3981 bgp_route_refresh_send (peer, afi, safi,
3982 prefix_type, REFRESH_IMMEDIATE, 1);
3983 else
3984 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
3985 }
3986 return 0;
3987 }
3988 }
3989
3990 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
3991 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
3992 {
3993 /* If neighbor has soft reconfiguration inbound flag.
3994 Use Adj-RIB-In database. */
3995 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
3996 bgp_soft_reconfig_in (peer, afi, safi);
3997 else
3998 {
3999 /* If neighbor has route refresh capability, send route refresh
4000 message to the peer. */
4001 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4002 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4003 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4004 else
4005 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4006 }
4007 }
4008 return 0;
4009}
4010
4011/* Display peer uptime. */
4012char *
4013peer_uptime (time_t uptime2, char *buf, size_t len)
4014{
4015 time_t uptime1;
4016 struct tm *tm;
4017
4018 /* Check buffer length. */
4019 if (len < BGP_UPTIME_LEN)
4020 {
4021 zlog_warn ("peer_uptime (): buffer shortage %d", len);
4022 return "";
4023 }
4024
4025 /* If there is no connection has been done before print `never'. */
4026 if (uptime2 == 0)
4027 {
4028 snprintf (buf, len, "never ");
4029 return buf;
4030 }
4031
4032 /* Get current time. */
4033 uptime1 = time (NULL);
4034 uptime1 -= uptime2;
4035 tm = gmtime (&uptime1);
4036
4037 /* Making formatted timer strings. */
4038#define ONE_DAY_SECOND 60*60*24
4039#define ONE_WEEK_SECOND 60*60*24*7
4040
4041 if (uptime1 < ONE_DAY_SECOND)
4042 snprintf (buf, len, "%02d:%02d:%02d",
4043 tm->tm_hour, tm->tm_min, tm->tm_sec);
4044 else if (uptime1 < ONE_WEEK_SECOND)
4045 snprintf (buf, len, "%dd%02dh%02dm",
4046 tm->tm_yday, tm->tm_hour, tm->tm_min);
4047 else
4048 snprintf (buf, len, "%02dw%dd%02dh",
4049 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4050 return buf;
4051}
4052
4053void
4054bgp_config_write_filter (struct vty *vty, struct peer *peer,
4055 afi_t afi, safi_t safi)
4056{
4057 struct bgp_filter *filter;
4058 struct bgp_filter *gfilter = NULL;
4059 char *addr;
4060 int in = FILTER_IN;
4061 int out = FILTER_OUT;
4062
4063 addr = peer->host;
4064 filter = &peer->filter[afi][safi];
4065 if (peer->af_group[afi][safi])
4066 gfilter = &peer->group->conf->filter[afi][safi];
4067
4068 /* distribute-list. */
4069 if (filter->dlist[in].name)
4070 if (! gfilter || ! gfilter->dlist[in].name
4071 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4072 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4073 filter->dlist[in].name, VTY_NEWLINE);
4074 if (filter->dlist[out].name && ! gfilter)
4075 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4076 filter->dlist[out].name, VTY_NEWLINE);
4077
4078 /* prefix-list. */
4079 if (filter->plist[in].name)
4080 if (! gfilter || ! gfilter->plist[in].name
4081 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4082 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4083 filter->plist[in].name, VTY_NEWLINE);
4084 if (filter->plist[out].name && ! gfilter)
4085 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4086 filter->plist[out].name, VTY_NEWLINE);
4087
4088 /* route-map. */
4089 if (filter->map[in].name)
4090 if (! gfilter || ! gfilter->map[in].name
4091 || strcmp (filter->map[in].name, gfilter->map[in].name) != 0)
4092 vty_out (vty, " neighbor %s route-map %s in%s", addr,
4093 filter->map[in].name, VTY_NEWLINE);
4094 if (filter->map[out].name && ! gfilter)
4095 vty_out (vty, " neighbor %s route-map %s out%s", addr,
4096 filter->map[out].name, VTY_NEWLINE);
4097
4098 /* unsuppress-map */
4099 if (filter->usmap.name && ! gfilter)
4100 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4101 filter->usmap.name, VTY_NEWLINE);
4102
4103 /* filter-list. */
4104 if (filter->aslist[in].name)
4105 if (! gfilter || ! gfilter->aslist[in].name
4106 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4107 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4108 filter->aslist[in].name, VTY_NEWLINE);
4109 if (filter->aslist[out].name && ! gfilter)
4110 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4111 filter->aslist[out].name, VTY_NEWLINE);
4112}
4113
4114/* BGP peer configuration display function. */
4115void
4116bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4117 struct peer *peer, afi_t afi, safi_t safi)
4118{
4119 struct bgp_filter *filter;
4120 struct peer *g_peer = NULL;
4121 char buf[SU_ADDRSTRLEN];
4122 char *addr;
4123
4124 filter = &peer->filter[afi][safi];
4125 addr = peer->host;
4126 if (peer_group_active (peer))
4127 g_peer = peer->group->conf;
4128
4129 /************************************
4130 ****** Global to the neighbor ******
4131 ************************************/
4132 if (afi == AFI_IP && safi == SAFI_UNICAST)
4133 {
4134 /* remote-as. */
4135 if (! peer_group_active (peer))
4136 {
4137 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4138 vty_out (vty, " neighbor %s peer-group%s", addr,
4139 VTY_NEWLINE);
4140 if (peer->as)
4141 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4142 VTY_NEWLINE);
4143 }
4144 else
4145 {
4146 if (! g_peer->as)
4147 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4148 VTY_NEWLINE);
4149 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4150 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4151 peer->group->name, VTY_NEWLINE);
4152 }
4153
4154 /* local-as. */
4155 if (peer->change_local_as)
4156 if (! peer_group_active (peer))
4157 vty_out (vty, " neighbor %s local-as %d%s%s", addr,
4158 peer->change_local_as,
4159 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4160 " no-prepend" : "", VTY_NEWLINE);
4161
4162 /* Description. */
4163 if (peer->desc)
4164 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4165 VTY_NEWLINE);
4166
4167 /* Shutdown. */
4168 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4169 if (! peer_group_active (peer) ||
4170 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4171 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4172
4173 /* BGP port. */
4174 if (peer->port != BGP_PORT_DEFAULT)
4175 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
4176 VTY_NEWLINE);
4177
4178 /* Local interface name. */
4179 if (peer->ifname)
4180 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4181 VTY_NEWLINE);
4182
4183 /* Passive. */
4184 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4185 if (! peer_group_active (peer) ||
4186 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4187 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4188
4189 /* EBGP multihop. */
4190 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
4191 if (! peer_group_active (peer) ||
4192 g_peer->ttl != peer->ttl)
4193 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4194 VTY_NEWLINE);
4195
4196 /* Enforce multihop. */
4197 if (CHECK_FLAG (peer->flags, PEER_FLAG_ENFORCE_MULTIHOP))
4198 if (! peer_group_active (peer) ||
4199 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_ENFORCE_MULTIHOP))
4200 vty_out (vty, " neighbor %s enforce-multihop%s", addr, VTY_NEWLINE);
4201
4202 /* Update-source. */
4203 if (peer->update_if)
4204 if (! peer_group_active (peer) || ! g_peer->update_if
4205 || strcmp (g_peer->update_if, peer->update_if) != 0)
4206 vty_out (vty, " neighbor %s update-source %s%s", addr,
4207 peer->update_if, VTY_NEWLINE);
4208 if (peer->update_source)
4209 if (! peer_group_active (peer) || ! g_peer->update_source
4210 || sockunion_cmp (g_peer->update_source,
4211 peer->update_source) != 0)
4212 vty_out (vty, " neighbor %s update-source %s%s", addr,
4213 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4214 VTY_NEWLINE);
4215
4216 /* BGP version print. */
4217 if (peer->version == BGP_VERSION_MP_4_DRAFT_00)
4218 vty_out (vty, " neighbor %s version %s%s",
4219 addr,"4-", VTY_NEWLINE);
4220
4221 /* advertisement-interval */
4222 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4223 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4224 addr, peer->v_routeadv, VTY_NEWLINE);
4225
4226 /* timers. */
4227 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4228 && ! peer_group_active (peer))
4229 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4230 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4231
4232 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4233 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4234 peer->connect, VTY_NEWLINE);
4235
4236 /* Default weight. */
4237 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4238 if (! peer_group_active (peer) ||
4239 g_peer->weight != peer->weight)
4240 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4241 VTY_NEWLINE);
4242
4243 /* Route refresh. */
4244 if (CHECK_FLAG (peer->flags, PEER_FLAG_NO_ROUTE_REFRESH_CAP))
4245 if (! peer_group_active (peer) ||
4246 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_NO_ROUTE_REFRESH_CAP))
4247 vty_out (vty, " no neighbor %s capability route-refresh%s", addr,
4248 VTY_NEWLINE);
4249
4250 /* Dynamic capability. */
4251 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4252 if (! peer_group_active (peer) ||
4253 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4254 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4255 VTY_NEWLINE);
4256
4257 /* dont capability negotiation. */
4258 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4259 if (! peer_group_active (peer) ||
4260 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4261 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4262 VTY_NEWLINE);
4263
4264 /* override capability negotiation. */
4265 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4266 if (! peer_group_active (peer) ||
4267 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4268 vty_out (vty, " neighbor %s override-capability%s", addr,
4269 VTY_NEWLINE);
4270
4271 /* strict capability negotiation. */
4272 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4273 if (! peer_group_active (peer) ||
4274 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4275 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4276 VTY_NEWLINE);
4277
4278 if (! peer_group_active (peer))
4279 {
4280 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4281 {
4282 if (peer->afc[AFI_IP][SAFI_UNICAST])
4283 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4284 }
4285 else
4286 {
4287 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4288 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4289 }
4290 }
4291 }
4292
4293
4294 /************************************
4295 ****** Per AF to the neighbor ******
4296 ************************************/
4297
4298 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4299 {
4300 if (peer->af_group[afi][safi])
4301 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4302 peer->group->name, VTY_NEWLINE);
4303 else
4304 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4305 }
4306
4307 /* ORF capability. */
4308 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4309 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4310 if (! peer->af_group[afi][safi])
4311 {
4312 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4313
4314 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4315 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4316 vty_out (vty, " both");
4317 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4318 vty_out (vty, " send");
4319 else
4320 vty_out (vty, " receive");
4321 vty_out (vty, "%s", VTY_NEWLINE);
4322 }
4323
4324 /* Route reflector client. */
4325 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4326 && ! peer->af_group[afi][safi])
4327 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4328 VTY_NEWLINE);
4329
4330 /* Nexthop self. */
4331 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4332 && ! peer->af_group[afi][safi])
4333 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4334
4335 /* Remove private AS. */
4336 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4337 && ! peer->af_group[afi][safi])
4338 vty_out (vty, " neighbor %s remove-private-AS%s",
4339 addr, VTY_NEWLINE);
4340
4341 /* send-community print. */
4342 if (! peer->af_group[afi][safi])
4343 {
4344 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4345 {
4346 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4347 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4348 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4349 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4350 vty_out (vty, " neighbor %s send-community extended%s",
4351 addr, VTY_NEWLINE);
4352 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4353 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4354 }
4355 else
4356 {
4357 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4358 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4359 vty_out (vty, " no neighbor %s send-community both%s",
4360 addr, VTY_NEWLINE);
4361 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4362 vty_out (vty, " no neighbor %s send-community extended%s",
4363 addr, VTY_NEWLINE);
4364 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4365 vty_out (vty, " no neighbor %s send-community%s",
4366 addr, VTY_NEWLINE);
4367 }
4368 }
4369
4370 /* Default information */
4371 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4372 && ! peer->af_group[afi][safi])
4373 {
4374 vty_out (vty, " neighbor %s default-originate", addr);
4375 if (peer->default_rmap[afi][safi].name)
4376 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4377 vty_out (vty, "%s", VTY_NEWLINE);
4378 }
4379
4380 /* Soft reconfiguration inbound. */
4381 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4382 if (! peer->af_group[afi][safi] ||
4383 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4384 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4385 VTY_NEWLINE);
4386
4387 /* maximum-prefix. */
4388 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4389 if (! peer->af_group[afi][safi]
4390 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004391 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004392 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4393 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00004394 {
4395 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
4396 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
4397 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
4398 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
4399 vty_out (vty, " warning-only");
4400 vty_out (vty, "%s", VTY_NEWLINE);
4401 }
paul718e3742002-12-13 20:15:29 +00004402
4403 /* Route server client. */
4404 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
4405 && ! peer->af_group[afi][safi])
4406 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
4407
4408 /* Allow AS in. */
4409 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
4410 if (! peer_group_active (peer)
4411 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
4412 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
4413 {
4414 if (peer->allowas_in[afi][safi] == 3)
4415 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
4416 else
4417 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
4418 peer->allowas_in[afi][safi], VTY_NEWLINE);
4419 }
4420
4421 /* Filter. */
4422 bgp_config_write_filter (vty, peer, afi, safi);
4423
4424 /* atribute-unchanged. */
4425 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4426 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4427 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4428 && ! peer->af_group[afi][safi])
4429 {
4430 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4431 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4432 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4433 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
4434 else
4435 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
4436 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
4437 " as-path" : "",
4438 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
4439 " next-hop" : "",
4440 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
4441 " med" : "", VTY_NEWLINE);
4442 }
4443}
4444
4445/* Display "address-family" configuration header. */
4446void
4447bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
4448 int *write)
4449{
4450 if (*write)
4451 return;
4452
4453 if (afi == AFI_IP && safi == SAFI_UNICAST)
4454 return;
4455
4456 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
4457
4458 if (afi == AFI_IP)
4459 {
4460 if (safi == SAFI_MULTICAST)
4461 vty_out (vty, "ipv4 multicast");
4462 else if (safi == SAFI_MPLS_VPN)
4463 vty_out (vty, "vpnv4 unicast");
4464 }
4465 else if (afi == AFI_IP6)
4466 vty_out (vty, "ipv6");
4467
4468 vty_out (vty, "%s", VTY_NEWLINE);
4469
4470 *write = 1;
4471}
4472
4473/* Address family based peer configuration display. */
4474int
4475bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
4476 safi_t safi)
4477{
4478 int write = 0;
4479 struct peer *peer;
4480 struct peer_group *group;
4481 struct listnode *nn;
4482
4483 bgp_config_write_network (vty, bgp, afi, safi, &write);
4484
4485 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
4486
4487 LIST_LOOP (bgp->group, group, nn)
4488 {
4489 if (group->conf->afc[afi][safi])
4490 {
4491 bgp_config_write_family_header (vty, afi, safi, &write);
4492 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
4493 }
4494 }
4495 LIST_LOOP (bgp->peer, peer, nn)
4496 {
4497 if (peer->afc[afi][safi])
4498 {
4499 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4500 {
4501 bgp_config_write_family_header (vty, afi, safi, &write);
4502 bgp_config_write_peer (vty, bgp, peer, afi, safi);
4503 }
4504 }
4505 }
4506 if (write)
4507 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
4508
4509 return write;
4510}
4511
4512int
4513bgp_config_write (struct vty *vty)
4514{
4515 int write = 0;
4516 struct bgp *bgp;
4517 struct peer_group *group;
4518 struct peer *peer;
4519 struct listnode *nn, *nm, *no;
4520
4521 /* BGP Multiple instance. */
4522 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4523 {
4524 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
4525 write++;
4526 }
4527
4528 /* BGP Config type. */
4529 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4530 {
4531 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
4532 write++;
4533 }
4534
4535 /* BGP configuration. */
4536 LIST_LOOP (bm->bgp, bgp, nn)
4537 {
4538 if (write)
4539 vty_out (vty, "!%s", VTY_NEWLINE);
4540
4541 /* Router bgp ASN */
4542 vty_out (vty, "router bgp %d", bgp->as);
4543
4544 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4545 {
4546 if (bgp->name)
4547 vty_out (vty, " view %s", bgp->name);
4548 }
4549 vty_out (vty, "%s", VTY_NEWLINE);
4550
4551 /* No Synchronization */
4552 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4553 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
4554
4555 /* BGP fast-external-failover. */
4556 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
4557 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
4558
4559 /* BGP router ID. */
4560 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
4561 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
4562 VTY_NEWLINE);
4563
paul848973c2003-08-13 00:32:49 +00004564 /* BGP log-neighbor-changes. */
4565 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
4566 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
4567
paul718e3742002-12-13 20:15:29 +00004568 /* BGP configuration. */
4569 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
4570 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
4571
4572 /* BGP default ipv4-unicast. */
4573 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4574 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
4575
4576 /* BGP default local-preference. */
4577 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
4578 vty_out (vty, " bgp default local-preference %d%s",
4579 bgp->default_local_pref, VTY_NEWLINE);
4580
4581 /* BGP client-to-client reflection. */
4582 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
4583 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
4584
4585 /* BGP cluster ID. */
4586 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
4587 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
4588 VTY_NEWLINE);
4589
hassoe0701b72004-05-20 09:19:34 +00004590 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00004591 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00004592 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
4593 VTY_NEWLINE);
4594
4595 /* Confederation peer */
4596 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00004597 {
hassoe0701b72004-05-20 09:19:34 +00004598 int i;
paul718e3742002-12-13 20:15:29 +00004599
hassoe0701b72004-05-20 09:19:34 +00004600 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00004601
hassoe0701b72004-05-20 09:19:34 +00004602 for (i = 0; i < bgp->confed_peers_cnt; i++)
4603 vty_out(vty, " %d", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00004604
hassoe0701b72004-05-20 09:19:34 +00004605 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004606 }
4607
4608 /* BGP enforce-first-as. */
4609 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
4610 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
4611
4612 /* BGP deterministic-med. */
4613 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
4614 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
4615
4616 /* BGP bestpath method. */
4617 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
4618 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
4619 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
4620 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
4621 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
4622 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4623 {
4624 vty_out (vty, " bgp bestpath med");
4625 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
4626 vty_out (vty, " confed");
4627 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4628 vty_out (vty, " missing-as-worst");
4629 vty_out (vty, "%s", VTY_NEWLINE);
4630 }
4631
4632 /* BGP network import check. */
4633 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
4634 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
4635
4636 /* BGP scan interval. */
4637 bgp_config_write_scan_time (vty);
4638
4639 /* BGP flag dampening. */
4640 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
4641 BGP_CONFIG_DAMPENING))
4642 bgp_config_write_damp (vty);
4643
4644 /* BGP static route configuration. */
4645 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4646
4647 /* BGP redistribute configuration. */
4648 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4649
4650 /* BGP timers configuration. */
4651 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
4652 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
4653 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
4654 bgp->default_holdtime, VTY_NEWLINE);
4655
4656 /* peer-group */
4657 LIST_LOOP (bgp->group, group, nm)
4658 {
4659 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
4660 }
4661
4662 /* Normal neighbor configuration. */
4663 LIST_LOOP (bgp->peer, peer, no)
4664 {
4665 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4666 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
4667 }
4668
4669 /* Distance configuration. */
4670 bgp_config_write_distance (vty, bgp);
4671
4672 /* No auto-summary */
4673 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4674 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
4675
4676 /* IPv4 multicast configuration. */
4677 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
4678
4679 /* IPv4 VPN configuration. */
4680 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
4681
4682 /* IPv6 unicast configuration. */
4683 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
4684
4685 write++;
4686 }
4687 return write;
4688}
4689
4690void
4691bgp_master_init ()
4692{
4693 memset (&bgp_master, 0, sizeof (struct bgp_master));
4694
4695 bm = &bgp_master;
4696 bm->bgp = list_new ();
4697 bm->port = BGP_PORT_DEFAULT;
4698 bm->master = thread_master_create ();
4699 bm->start_time = time (NULL);
4700}
4701
4702void
4703bgp_init ()
4704{
4705 void bgp_zebra_init ();
4706 void bgp_route_map_init ();
4707 void bgp_filter_init ();
4708
4709 /* BGP VTY commands installation. */
4710 bgp_vty_init ();
4711
4712 /* Create BGP server socket. */
4713 bgp_socket (NULL, bm->port);
4714
4715 /* Init zebra. */
4716 bgp_zebra_init ();
4717
4718 /* BGP inits. */
4719 bgp_attr_init ();
4720 bgp_debug_init ();
4721 bgp_dump_init ();
4722 bgp_route_init ();
4723 bgp_route_map_init ();
4724 bgp_scan_init ();
4725 bgp_mplsvpn_init ();
4726
4727 /* Access list initialize. */
4728 access_list_init ();
4729 access_list_add_hook (peer_distribute_update);
4730 access_list_delete_hook (peer_distribute_update);
4731
4732 /* Filter list initialize. */
4733 bgp_filter_init ();
4734 as_list_add_hook (peer_aslist_update);
4735 as_list_delete_hook (peer_aslist_update);
4736
4737 /* Prefix list initialize.*/
4738 prefix_list_init ();
4739 prefix_list_add_hook (peer_prefix_list_update);
4740 prefix_list_delete_hook (peer_prefix_list_update);
4741
4742 /* Community list initialize. */
4743 bgp_clist = community_list_init ();
4744
4745#ifdef HAVE_SNMP
4746 bgp_snmp_init ();
4747#endif /* HAVE_SNMP */
4748}
paul545acaf2004-04-20 15:13:15 +00004749
4750void
4751bgp_terminate ()
4752{
4753 struct bgp_master *bm;
4754 struct bgp *bgp;
4755 struct peer *peer;
4756 struct listnode *nn;
4757 struct listnode *mm;
4758
4759 bm = bgp_get_master ();
4760
4761 LIST_LOOP (bm->bgp, bgp, nn)
4762 LIST_LOOP (bgp->peer, peer, mm)
4763 if (peer->status == Established)
4764 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4765 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
4766
4767 bgp_cleanup_routes ();
4768}
4769