blob: 47df3c83e110b8098a8fdb7710909c4ebf3c68b4 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* BGP-4, BGP-4+ daemon program
2 Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "prefix.h"
24#include "thread.h"
25#include "buffer.h"
26#include "stream.h"
27#include "command.h"
28#include "sockunion.h"
29#include "network.h"
30#include "memory.h"
31#include "filter.h"
32#include "routemap.h"
33#include "str.h"
34#include "log.h"
35#include "plist.h"
36#include "linklist.h"
37
38#include "bgpd/bgpd.h"
39#include "bgpd/bgp_table.h"
40#include "bgpd/bgp_aspath.h"
41#include "bgpd/bgp_route.h"
42#include "bgpd/bgp_dump.h"
43#include "bgpd/bgp_debug.h"
44#include "bgpd/bgp_community.h"
45#include "bgpd/bgp_attr.h"
46#include "bgpd/bgp_regex.h"
47#include "bgpd/bgp_clist.h"
48#include "bgpd/bgp_fsm.h"
49#include "bgpd/bgp_packet.h"
50#include "bgpd/bgp_zebra.h"
51#include "bgpd/bgp_open.h"
52#include "bgpd/bgp_filter.h"
53#include "bgpd/bgp_nexthop.h"
54#include "bgpd/bgp_damp.h"
55#include "bgpd/bgp_mplsvpn.h"
56#include "bgpd/bgp_advertise.h"
57#include "bgpd/bgp_network.h"
58#include "bgpd/bgp_vty.h"
59#ifdef HAVE_SNMP
60#include "bgpd/bgp_snmp.h"
61#endif /* HAVE_SNMP */
62
63/* BGP process wide configuration. */
64static struct bgp_master bgp_master;
65
66/* BGP process wide configuration pointer to export. */
67struct bgp_master *bm;
68
69/* BGP community-list. */
70struct community_list_handler *bgp_clist;
71
72/* BGP global flag manipulation. */
73int
74bgp_option_set (int flag)
75{
76 switch (flag)
77 {
78 case BGP_OPT_NO_FIB:
79 case BGP_OPT_MULTIPLE_INSTANCE:
80 case BGP_OPT_CONFIG_CISCO:
81 SET_FLAG (bm->options, flag);
82 break;
83 default:
84 return BGP_ERR_INVALID_FLAG;
85 break;
86 }
87 return 0;
88}
89
90int
91bgp_option_unset (int flag)
92{
93 switch (flag)
94 {
95 case BGP_OPT_MULTIPLE_INSTANCE:
96 if (listcount (bm->bgp) > 1)
97 return BGP_ERR_MULTIPLE_INSTANCE_USED;
98 /* Fall through. */
99 case BGP_OPT_NO_FIB:
100 case BGP_OPT_CONFIG_CISCO:
101 UNSET_FLAG (bm->options, flag);
102 break;
103 default:
104 return BGP_ERR_INVALID_FLAG;
105 break;
106 }
107 return 0;
108}
109
110int
111bgp_option_check (int flag)
112{
113 return CHECK_FLAG (bm->options, flag);
114}
115
116/* BGP flag manipulation. */
117int
118bgp_flag_set (struct bgp *bgp, int flag)
119{
120 SET_FLAG (bgp->flags, flag);
121 return 0;
122}
123
124int
125bgp_flag_unset (struct bgp *bgp, int flag)
126{
127 UNSET_FLAG (bgp->flags, flag);
128 return 0;
129}
130
131int
132bgp_flag_check (struct bgp *bgp, int flag)
133{
134 return CHECK_FLAG (bgp->flags, flag);
135}
136
137/* Internal function to set BGP structure configureation flag. */
138static void
139bgp_config_set (struct bgp *bgp, int config)
140{
141 SET_FLAG (bgp->config, config);
142}
143
144static void
145bgp_config_unset (struct bgp *bgp, int config)
146{
147 UNSET_FLAG (bgp->config, config);
148}
149
150static int
151bgp_config_check (struct bgp *bgp, int config)
152{
153 return CHECK_FLAG (bgp->config, config);
154}
155
156/* Set BGP router identifier. */
157int
158bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
159{
160 struct peer *peer;
161 struct listnode *nn;
162
163 if (bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID)
164 && IPV4_ADDR_SAME (&bgp->router_id, id))
165 return 0;
166
167 IPV4_ADDR_COPY (&bgp->router_id, id);
168 bgp_config_set (bgp, BGP_CONFIG_ROUTER_ID);
169
170 /* Set all peer's local identifier with this value. */
171 LIST_LOOP (bgp->peer, peer, nn)
172 {
173 IPV4_ADDR_COPY (&peer->local_id, id);
174
175 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000176 {
177 peer->last_reset = PEER_DOWN_RID_CHANGE;
178 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
179 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
180 }
paul718e3742002-12-13 20:15:29 +0000181 }
182 return 0;
183}
184
185/* Unset BGP router identifier. */
186int
187bgp_router_id_unset (struct bgp *bgp)
188{
189 struct peer *peer;
190 struct listnode *nn;
191
192 if (! bgp_config_check (bgp, BGP_CONFIG_ROUTER_ID))
193 return 0;
194
195 bgp->router_id.s_addr = 0;
196 bgp_config_unset (bgp, BGP_CONFIG_ROUTER_ID);
197
198 /* Clear peer router id configuration. */
199 LIST_LOOP (bgp->peer, peer, nn)
200 {
201 peer->local_id.s_addr = 0;
202 }
203
204 /* Set router-id from interface's address. */
205 bgp_if_update_all ();
206
207 /* Reset all BGP sessions to use new router-id. */
208 LIST_LOOP (bgp->peer, peer, nn)
209 {
210 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000211 {
212 peer->last_reset = PEER_DOWN_RID_CHANGE;
213 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
214 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
215 }
paul718e3742002-12-13 20:15:29 +0000216 }
217
218 return 0;
219}
220
221/* BGP's cluster-id control. */
222int
223bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
224{
225 struct peer *peer;
226 struct listnode *nn;
227
228 if (bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID)
229 && IPV4_ADDR_SAME (&bgp->cluster_id, cluster_id))
230 return 0;
231
232 IPV4_ADDR_COPY (&bgp->cluster_id, cluster_id);
233 bgp_config_set (bgp, BGP_CONFIG_CLUSTER_ID);
234
235 /* Clear all IBGP peer. */
236 LIST_LOOP (bgp->peer, peer, nn)
237 {
238 if (peer_sort (peer) != BGP_PEER_IBGP)
239 continue;
240
241 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000242 {
243 peer->last_reset = PEER_DOWN_CLID_CHANGE;
244 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
245 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
246 }
paul718e3742002-12-13 20:15:29 +0000247 }
248 return 0;
249}
250
251int
252bgp_cluster_id_unset (struct bgp *bgp)
253{
254 struct peer *peer;
255 struct listnode *nn;
256
257 if (! bgp_config_check (bgp, BGP_CONFIG_CLUSTER_ID))
258 return 0;
259
260 bgp->cluster_id.s_addr = 0;
261 bgp_config_unset (bgp, BGP_CONFIG_CLUSTER_ID);
262
263 /* Clear all IBGP peer. */
264 LIST_LOOP (bgp->peer, peer, nn)
265 {
266 if (peer_sort (peer) != BGP_PEER_IBGP)
267 continue;
268
269 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000270 {
271 peer->last_reset = PEER_DOWN_CLID_CHANGE;
272 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
273 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
274 }
paul718e3742002-12-13 20:15:29 +0000275 }
276 return 0;
277}
278
279/* BGP timer configuration. */
280int
281bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
282{
283 bgp->default_keepalive = (keepalive < holdtime / 3
284 ? keepalive : holdtime / 3);
285 bgp->default_holdtime = holdtime;
286
287 return 0;
288}
289
290int
291bgp_timers_unset (struct bgp *bgp)
292{
293 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
294 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
295
296 return 0;
297}
298
299/* BGP confederation configuration. */
300int
301bgp_confederation_id_set (struct bgp *bgp, as_t as)
302{
303 struct peer *peer;
304 struct listnode *nn;
305 int already_confed;
306
307 if (as == 0)
308 return BGP_ERR_INVALID_AS;
309
310 /* Remember - were we doing confederation before? */
311 already_confed = bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION);
312 bgp->confed_id = as;
313 bgp_config_set (bgp, BGP_CONFIG_CONFEDERATION);
314
315 /* If we were doing confederation already, this is just an external
316 AS change. Just Reset EBGP sessions, not CONFED sessions. If we
317 were not doing confederation before, reset all EBGP sessions. */
318 LIST_LOOP (bgp->peer, peer, nn)
319 {
320 /* We're looking for peers who's AS is not local or part of our
321 confederation. */
322 if (already_confed)
323 {
324 if (peer_sort (peer) == BGP_PEER_EBGP)
325 {
326 peer->local_as = as;
327 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000328 {
329 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
330 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
331 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
332 }
333
paul718e3742002-12-13 20:15:29 +0000334 else
335 BGP_EVENT_ADD (peer, BGP_Stop);
336 }
337 }
338 else
339 {
340 /* Not doign confederation before, so reset every non-local
341 session */
342 if (peer_sort (peer) != BGP_PEER_IBGP)
343 {
344 /* Reset the local_as to be our EBGP one */
345 if (peer_sort (peer) == BGP_PEER_EBGP)
346 peer->local_as = as;
347 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000348 {
349 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
350 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
351 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
352 }
paul718e3742002-12-13 20:15:29 +0000353 else
354 BGP_EVENT_ADD (peer, BGP_Stop);
355 }
356 }
357 }
358 return 0;
359}
360
361int
362bgp_confederation_id_unset (struct bgp *bgp)
363{
364 struct peer *peer;
365 struct listnode *nn;
366
367 bgp->confed_id = 0;
368 bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
369
370 LIST_LOOP (bgp->peer, peer, nn)
371 {
372 /* We're looking for peers who's AS is not local */
373 if (peer_sort (peer) != BGP_PEER_IBGP)
374 {
375 peer->local_as = bgp->as;
376 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000377 {
378 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
379 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
380 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
381 }
382
paul718e3742002-12-13 20:15:29 +0000383 else
384 BGP_EVENT_ADD (peer, BGP_Stop);
385 }
386 }
387 return 0;
388}
389
390/* Is an AS part of the confed or not? */
391int
392bgp_confederation_peers_check (struct bgp *bgp, as_t as)
393{
394 int i;
395
396 if (! bgp)
397 return 0;
398
399 for (i = 0; i < bgp->confed_peers_cnt; i++)
400 if (bgp->confed_peers[i] == as)
401 return 1;
402
403 return 0;
404}
405
406/* Add an AS to the confederation set. */
407int
408bgp_confederation_peers_add (struct bgp *bgp, as_t as)
409{
410 struct peer *peer;
411 struct listnode *nn;
412
413 if (! bgp)
414 return BGP_ERR_INVALID_BGP;
415
416 if (bgp->as == as)
417 return BGP_ERR_INVALID_AS;
418
419 if (bgp_confederation_peers_check (bgp, as))
420 return -1;
421
422 if (bgp->confed_peers)
423 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
424 bgp->confed_peers,
425 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
426 else
427 bgp->confed_peers = XMALLOC (MTYPE_BGP_CONFED_LIST,
428 (bgp->confed_peers_cnt + 1) * sizeof (as_t));
429
430 bgp->confed_peers[bgp->confed_peers_cnt] = as;
431 bgp->confed_peers_cnt++;
432
433 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
434 {
435 LIST_LOOP (bgp->peer, peer, nn)
436 {
437 if (peer->as == as)
438 {
439 peer->local_as = bgp->as;
440 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000441 {
442 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
443 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
444 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
445 }
paul718e3742002-12-13 20:15:29 +0000446 else
447 BGP_EVENT_ADD (peer, BGP_Stop);
448 }
449 }
450 }
451 return 0;
452}
453
454/* Delete an AS from the confederation set. */
455int
456bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
457{
458 int i;
459 int j;
460 struct peer *peer;
461 struct listnode *nn;
462
463 if (! bgp)
464 return -1;
465
466 if (! bgp_confederation_peers_check (bgp, as))
467 return -1;
468
469 for (i = 0; i < bgp->confed_peers_cnt; i++)
470 if (bgp->confed_peers[i] == as)
471 for(j = i + 1; j < bgp->confed_peers_cnt; j++)
472 bgp->confed_peers[j - 1] = bgp->confed_peers[j];
473
474 bgp->confed_peers_cnt--;
475
476 if (bgp->confed_peers_cnt == 0)
477 {
478 if (bgp->confed_peers)
479 XFREE (MTYPE_BGP_CONFED_LIST, bgp->confed_peers);
480 bgp->confed_peers = NULL;
481 }
482 else
483 bgp->confed_peers = XREALLOC (MTYPE_BGP_CONFED_LIST,
484 bgp->confed_peers,
485 bgp->confed_peers_cnt * sizeof (as_t));
486
487 /* Now reset any peer who's remote AS has just been removed from the
488 CONFED */
489 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION))
490 {
491 LIST_LOOP (bgp->peer, peer, nn)
492 {
493 if (peer->as == as)
494 {
495 peer->local_as = bgp->confed_id;
496 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000497 {
498 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
499 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
500 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
501 }
paul718e3742002-12-13 20:15:29 +0000502 else
503 BGP_EVENT_ADD (peer, BGP_Stop);
504 }
505 }
506 }
507
508 return 0;
509}
510
511/* Local preference configuration. */
512int
513bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
514{
515 if (! bgp)
516 return -1;
517
paul718e3742002-12-13 20:15:29 +0000518 bgp->default_local_pref = local_pref;
519
520 return 0;
521}
522
523int
524bgp_default_local_preference_unset (struct bgp *bgp)
525{
526 if (! bgp)
527 return -1;
528
paul718e3742002-12-13 20:15:29 +0000529 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
530
531 return 0;
532}
533
pauleb821182004-05-01 08:44:08 +0000534/* Peer comparison function for sorting. */
paul718e3742002-12-13 20:15:29 +0000535static int
536peer_cmp (struct peer *p1, struct peer *p2)
537{
pauleb821182004-05-01 08:44:08 +0000538 return sockunion_cmp (&p1->su, &p2->su);
paul718e3742002-12-13 20:15:29 +0000539}
540
541int
542peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
543{
544 return CHECK_FLAG (peer->af_flags[afi][safi], flag);
545}
546
547/* Reset all address family specific configuration. */
548static void
549peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
550{
551 int i;
552 struct bgp_filter *filter;
553 char orf_name[BUFSIZ];
554
555 filter = &peer->filter[afi][safi];
556
557 /* Clear neighbor filter and route-map */
558 for (i = FILTER_IN; i < FILTER_MAX; i++)
559 {
560 if (filter->dlist[i].name)
561 {
562 free (filter->dlist[i].name);
563 filter->dlist[i].name = NULL;
564 }
565 if (filter->plist[i].name)
566 {
567 free (filter->plist[i].name);
568 filter->plist[i].name = NULL;
569 }
570 if (filter->aslist[i].name)
571 {
572 free (filter->aslist[i].name);
573 filter->aslist[i].name = NULL;
574 }
575 if (filter->map[i].name)
576 {
577 free (filter->map[i].name);
578 filter->map[i].name = NULL;
579 }
580 }
581
582 /* Clear unsuppress map. */
583 if (filter->usmap.name)
584 free (filter->usmap.name);
585 filter->usmap.name = NULL;
586 filter->usmap.map = NULL;
587
588 /* Clear neighbor's all address family flags. */
589 peer->af_flags[afi][safi] = 0;
590
591 /* Clear neighbor's all address family sflags. */
592 peer->af_sflags[afi][safi] = 0;
593
594 /* Clear neighbor's all address family capabilities. */
595 peer->af_cap[afi][safi] = 0;
596
597 /* Clear ORF info */
598 peer->orf_plist[afi][safi] = NULL;
599 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
600 prefix_bgp_orf_remove_all (orf_name);
601
602 /* Set default neighbor send-community. */
603 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
604 {
605 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
606 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
607 }
608
609 /* Clear neighbor default_originate_rmap */
610 if (peer->default_rmap[afi][safi].name)
611 free (peer->default_rmap[afi][safi].name);
612 peer->default_rmap[afi][safi].name = NULL;
613 peer->default_rmap[afi][safi].map = NULL;
614
615 /* Clear neighbor maximum-prefix */
616 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +0000617 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000618}
619
620/* peer global config reset */
621void
622peer_global_config_reset (struct peer *peer)
623{
624 peer->weight = 0;
625 peer->change_local_as = 0;
626 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
627 if (peer->update_source)
628 {
629 sockunion_free (peer->update_source);
630 peer->update_source = NULL;
631 }
632 if (peer->update_if)
633 {
634 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
635 peer->update_if = NULL;
636 }
637
638 if (peer_sort (peer) == BGP_PEER_IBGP)
639 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
640 else
641 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
642
643 peer->flags = 0;
644 peer->config = 0;
645 peer->holdtime = 0;
646 peer->keepalive = 0;
647 peer->connect = 0;
648 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
649}
650
651/* Check peer's AS number and determin is this peer IBGP or EBGP */
652int
653peer_sort (struct peer *peer)
654{
655 struct bgp *bgp;
656
657 bgp = peer->bgp;
658
659 /* Peer-group */
660 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
661 {
662 if (peer->as)
663 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
664 else
665 {
666 struct peer *peer1;
667 peer1 = listnode_head (peer->group->peer);
668 if (peer1)
669 return (peer1->local_as == peer1->as
670 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
671 }
672 return BGP_PEER_INTERNAL;
673 }
674
675 /* Normal peer */
676 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
677 {
678 if (peer->local_as == 0)
679 return BGP_PEER_INTERNAL;
680
681 if (peer->local_as == peer->as)
682 {
683 if (peer->local_as == bgp->confed_id)
684 return BGP_PEER_EBGP;
685 else
686 return BGP_PEER_IBGP;
687 }
688
689 if (bgp_confederation_peers_check (bgp, peer->as))
690 return BGP_PEER_CONFED;
691
692 return BGP_PEER_EBGP;
693 }
694 else
695 {
696 return (peer->local_as == 0
697 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
698 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
699 }
700}
701
702/* Allocate new peer object. */
703static struct peer *
704peer_new ()
705{
706 afi_t afi;
707 safi_t safi;
708 struct peer *peer;
709 struct servent *sp;
710
711 /* Allocate new peer. */
712 peer = XMALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
713 memset (peer, 0, sizeof (struct peer));
714
715 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000716 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000717 peer->v_start = BGP_INIT_START_TIMER;
718 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
719 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
720 peer->status = Idle;
721 peer->ostatus = Idle;
722 peer->version = BGP_VERSION_4;
723 peer->weight = 0;
724
725 /* Set default flags. */
726 for (afi = AFI_IP; afi < AFI_MAX; afi++)
727 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
728 {
729 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
730 {
731 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
732 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
733 }
734 peer->orf_plist[afi][safi] = NULL;
735 }
736 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
737
738 /* Create buffers. */
739 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
740 peer->obuf = stream_fifo_new ();
741 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
742
743 bgp_sync_init (peer);
744
745 /* Get service port number. */
746 sp = getservbyname ("bgp", "tcp");
747 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
748
749 return peer;
750}
751
752/* Create new BGP peer. */
753struct peer *
754peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
755 as_t remote_as, afi_t afi, safi_t safi)
756{
757 int active;
758 struct peer *peer;
759 char buf[SU_ADDRSTRLEN];
760
761 peer = peer_new ();
762 peer->bgp = bgp;
763 peer->su = *su;
764 peer->local_as = local_as;
765 peer->as = remote_as;
766 peer->local_id = bgp->router_id;
767 peer->v_holdtime = bgp->default_holdtime;
768 peer->v_keepalive = bgp->default_keepalive;
769 if (peer_sort (peer) == BGP_PEER_IBGP)
770 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
771 else
772 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
773 listnode_add_sort (bgp->peer, peer);
774
775 active = peer_active (peer);
776
777 if (afi && safi)
778 peer->afc[afi][safi] = 1;
779
780 /* Last read time set */
781 peer->readtime = time (NULL);
782
paul848973c2003-08-13 00:32:49 +0000783 /* Last reset time set */
784 peer->resettime = time (NULL);
785
paul718e3742002-12-13 20:15:29 +0000786 /* Default TTL set. */
787 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
788
789 /* Make peer's address string. */
790 sockunion2str (su, buf, SU_ADDRSTRLEN);
791 peer->host = strdup (buf);
792
793 /* Set up peer's events and timers. */
794 if (! active && peer_active (peer))
795 bgp_timer_set (peer);
796
797 return peer;
798}
799
pauleb821182004-05-01 08:44:08 +0000800/* Make accept BGP peer. Called from bgp_accept (). */
801struct peer *
802peer_create_accept (struct bgp *bgp)
803{
804 struct peer *peer;
805
806 peer = peer_new ();
807 peer->bgp = bgp;
808 listnode_add_sort (bgp->peer, peer);
809
810 return peer;
811}
812
paul718e3742002-12-13 20:15:29 +0000813/* Change peer's AS number. */
814void
815peer_as_change (struct peer *peer, as_t as)
816{
817 int type;
818
819 /* Stop peer. */
820 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
821 {
822 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000823 {
824 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
825 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
826 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
827 }
paul718e3742002-12-13 20:15:29 +0000828 else
829 BGP_EVENT_ADD (peer, BGP_Stop);
830 }
831 type = peer_sort (peer);
832 peer->as = as;
833
paul848973c2003-08-13 00:32:49 +0000834 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
835 && ! bgp_confederation_peers_check (peer->bgp, as)
836 && peer->bgp->as != as)
837 peer->local_as = peer->bgp->confed_id;
838 else
839 peer->local_as = peer->bgp->as;
840
paul718e3742002-12-13 20:15:29 +0000841 /* Advertisement-interval reset */
842 if (peer_sort (peer) == BGP_PEER_IBGP)
843 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
844 else
845 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
846
847 /* TTL reset */
848 if (peer_sort (peer) == BGP_PEER_IBGP)
849 peer->ttl = 255;
850 else if (type == BGP_PEER_IBGP)
851 peer->ttl = 1;
852
853 /* reflector-client reset */
854 if (peer_sort (peer) != BGP_PEER_IBGP)
855 {
856 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
857 PEER_FLAG_REFLECTOR_CLIENT);
858 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
859 PEER_FLAG_REFLECTOR_CLIENT);
860 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
861 PEER_FLAG_REFLECTOR_CLIENT);
862 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
863 PEER_FLAG_REFLECTOR_CLIENT);
864 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
865 PEER_FLAG_REFLECTOR_CLIENT);
866 }
867
868 /* local-as reset */
869 if (peer_sort (peer) != BGP_PEER_EBGP)
870 {
871 peer->change_local_as = 0;
872 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
873 }
874}
875
876/* If peer does not exist, create new one. If peer already exists,
877 set AS number to the peer. */
878int
879peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
880 afi_t afi, safi_t safi)
881{
882 struct peer *peer;
883 as_t local_as;
884
885 peer = peer_lookup (bgp, su);
886
887 if (peer)
888 {
889 /* When this peer is a member of peer-group. */
890 if (peer->group)
891 {
892 if (peer->group->conf->as)
893 {
894 /* Return peer group's AS number. */
895 *as = peer->group->conf->as;
896 return BGP_ERR_PEER_GROUP_MEMBER;
897 }
898 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
899 {
900 if (bgp->as != *as)
901 {
902 *as = peer->as;
903 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
904 }
905 }
906 else
907 {
908 if (bgp->as == *as)
909 {
910 *as = peer->as;
911 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
912 }
913 }
914 }
915
916 /* Existing peer's AS number change. */
917 if (peer->as != *as)
918 peer_as_change (peer, *as);
919 }
920 else
921 {
922
923 /* If the peer is not part of our confederation, and its not an
924 iBGP peer then spoof the source AS */
925 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
926 && ! bgp_confederation_peers_check (bgp, *as)
927 && bgp->as != *as)
928 local_as = bgp->confed_id;
929 else
930 local_as = bgp->as;
931
932 /* If this is IPv4 unicast configuration and "no bgp default
933 ipv4-unicast" is specified. */
934
935 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
936 && afi == AFI_IP && safi == SAFI_UNICAST)
937 peer = peer_create (su, bgp, local_as, *as, 0, 0);
938 else
939 peer = peer_create (su, bgp, local_as, *as, afi, safi);
940 }
941
942 return 0;
943}
944
945/* Activate the peer or peer group for specified AFI and SAFI. */
946int
947peer_activate (struct peer *peer, afi_t afi, safi_t safi)
948{
949 int active;
950
951 if (peer->afc[afi][safi])
952 return 0;
953
954 /* Activate the address family configuration. */
955 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
956 peer->afc[afi][safi] = 1;
957 else
958 {
959 active = peer_active (peer);
960
961 peer->afc[afi][safi] = 1;
962
963 if (! active && peer_active (peer))
964 bgp_timer_set (peer);
965 else
966 {
967 if (peer->status == Established)
968 {
969 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
970 {
971 peer->afc_adv[afi][safi] = 1;
972 bgp_capability_send (peer, afi, safi,
973 CAPABILITY_CODE_MP,
974 CAPABILITY_ACTION_SET);
975 if (peer->afc_recv[afi][safi])
976 {
977 peer->afc_nego[afi][safi] = 1;
978 bgp_announce_route (peer, afi, safi);
979 }
980 }
981 else
hassoe0701b72004-05-20 09:19:34 +0000982 {
983 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
984 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
985 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
986 }
paul718e3742002-12-13 20:15:29 +0000987 }
988 }
989 }
990 return 0;
991}
992
993int
994peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
995{
996 struct peer_group *group;
997 struct peer *peer1;
998 struct listnode *nn;
999
1000 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1001 {
1002 group = peer->group;
1003
1004 LIST_LOOP (group->peer, peer1, nn)
1005 {
1006 if (peer1->af_group[afi][safi])
1007 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
1008 }
1009 }
1010 else
1011 {
1012 if (peer->af_group[afi][safi])
1013 return BGP_ERR_PEER_BELONGS_TO_GROUP;
1014 }
1015
1016 if (! peer->afc[afi][safi])
1017 return 0;
1018
1019 /* De-activate the address family configuration. */
1020 peer->afc[afi][safi] = 0;
1021 peer_af_flag_reset (peer, afi, safi);
1022
1023 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1024 {
1025 if (peer->status == Established)
1026 {
1027 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1028 {
1029 peer->afc_adv[afi][safi] = 0;
1030 peer->afc_nego[afi][safi] = 0;
1031
1032 if (peer_active_nego (peer))
1033 {
1034 bgp_capability_send (peer, afi, safi,
1035 CAPABILITY_CODE_MP,
1036 CAPABILITY_ACTION_UNSET);
1037 bgp_clear_route (peer, afi, safi);
1038 peer->pcount[afi][safi] = 0;
1039 }
1040 else
hassoe0701b72004-05-20 09:19:34 +00001041 {
1042 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1043 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1044 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1045 }
paul718e3742002-12-13 20:15:29 +00001046 }
1047 else
hassoe0701b72004-05-20 09:19:34 +00001048 {
1049 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1050 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1051 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1052 }
paul718e3742002-12-13 20:15:29 +00001053 }
1054 }
1055 return 0;
1056}
1057
1058/* Delete peer from confguration. */
1059int
1060peer_delete (struct peer *peer)
1061{
1062 int i;
1063 afi_t afi;
1064 safi_t safi;
1065 struct bgp *bgp;
1066 struct bgp_filter *filter;
1067
1068 bgp = peer->bgp;
1069
1070 /* If this peer belongs to peer group. Clearn up the
1071 relationship. */
1072 if (peer->group)
1073 {
1074 listnode_delete (peer->group->peer, peer);
1075 peer->group = NULL;
1076 }
1077
1078 /* Withdraw all information from routing table. We can not use
1079 BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1080 executed after peer structure is deleted. */
hassoe0701b72004-05-20 09:19:34 +00001081 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001082 bgp_stop (peer);
1083 bgp_fsm_change_status (peer, Idle);
1084
1085 /* Stop all timers. */
1086 BGP_TIMER_OFF (peer->t_start);
1087 BGP_TIMER_OFF (peer->t_connect);
1088 BGP_TIMER_OFF (peer->t_holdtime);
1089 BGP_TIMER_OFF (peer->t_keepalive);
1090 BGP_TIMER_OFF (peer->t_asorig);
1091 BGP_TIMER_OFF (peer->t_routeadv);
1092
1093 /* Delete from all peer list. */
1094 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1095 listnode_delete (bgp->peer, peer);
1096
1097 /* Buffer. */
1098 if (peer->ibuf)
1099 stream_free (peer->ibuf);
1100
1101 if (peer->obuf)
1102 stream_fifo_free (peer->obuf);
1103
1104 if (peer->work)
1105 stream_free (peer->work);
1106
1107 /* Free allocated host character. */
1108 if (peer->host)
1109 free (peer->host);
1110
1111 /* Local and remote addresses. */
1112 if (peer->su_local)
1113 XFREE (MTYPE_TMP, peer->su_local);
1114 if (peer->su_remote)
1115 XFREE (MTYPE_TMP, peer->su_remote);
1116
1117 /* Peer description string. */
1118 if (peer->desc)
1119 XFREE (MTYPE_TMP, peer->desc);
1120
1121 bgp_sync_delete (peer);
1122
1123 /* Free filter related memory. */
1124 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1125 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1126 {
1127 filter = &peer->filter[afi][safi];
1128
1129 for (i = FILTER_IN; i < FILTER_MAX; i++)
1130 {
1131 if (filter->dlist[i].name)
1132 free (filter->dlist[i].name);
1133 if (filter->plist[i].name)
1134 free (filter->plist[i].name);
1135 if (filter->aslist[i].name)
1136 free (filter->aslist[i].name);
1137 if (filter->map[i].name)
1138 free (filter->map[i].name);
1139 }
1140
1141 if (filter->usmap.name)
1142 free (filter->usmap.name);
1143
1144 if (peer->default_rmap[afi][safi].name)
1145 free (peer->default_rmap[afi][safi].name);
1146 }
1147
1148 /* Update source configuration. */
1149 if (peer->update_source)
1150 {
1151 sockunion_free (peer->update_source);
1152 peer->update_source = NULL;
1153 }
1154 if (peer->update_if)
1155 {
1156 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1157 peer->update_if = NULL;
1158 }
1159
1160 /* Free peer structure. */
1161 XFREE (MTYPE_BGP_PEER, peer);
1162
1163 return 0;
1164}
1165
1166int
1167peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1168{
1169 return strcmp (g1->name, g2->name);
1170}
1171
1172/* If peer is configured at least one address family return 1. */
1173int
1174peer_group_active (struct peer *peer)
1175{
1176 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1177 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1178 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1179 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1180 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1181 return 1;
1182 return 0;
1183}
1184
1185/* Peer group cofiguration. */
1186static struct peer_group *
1187peer_group_new ()
1188{
1189 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1190 sizeof (struct peer_group));
1191}
1192
1193void
1194peer_group_free (struct peer_group *group)
1195{
1196 XFREE (MTYPE_PEER_GROUP, group);
1197}
1198
1199struct peer_group *
1200peer_group_lookup (struct bgp *bgp, char *name)
1201{
1202 struct peer_group *group;
1203 struct listnode *nn;
1204
1205 LIST_LOOP (bgp->group, group, nn)
1206 {
1207 if (strcmp (group->name, name) == 0)
1208 return group;
1209 }
1210 return NULL;
1211}
1212
1213struct peer_group *
1214peer_group_get (struct bgp *bgp, char *name)
1215{
1216 struct peer_group *group;
1217
1218 group = peer_group_lookup (bgp, name);
1219 if (group)
1220 return group;
1221
1222 group = peer_group_new ();
1223 group->bgp = bgp;
1224 group->name = strdup (name);
1225 group->peer = list_new ();
1226 group->conf = peer_new ();
1227 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1228 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
1229 group->conf->host = strdup (name);
1230 group->conf->bgp = bgp;
1231 group->conf->group = group;
1232 group->conf->as = 0;
1233 group->conf->ttl = 1;
1234 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1235 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1236 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1237 group->conf->keepalive = 0;
1238 group->conf->holdtime = 0;
1239 group->conf->connect = 0;
1240 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1241 listnode_add_sort (bgp->group, group);
1242
1243 return 0;
1244}
1245
1246void
1247peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1248 afi_t afi, safi_t safi)
1249{
1250 int in = FILTER_IN;
1251 int out = FILTER_OUT;
1252 struct peer *conf;
1253 struct bgp_filter *pfilter;
1254 struct bgp_filter *gfilter;
1255
1256 conf = group->conf;
1257 pfilter = &peer->filter[afi][safi];
1258 gfilter = &conf->filter[afi][safi];
1259
1260 /* remote-as */
1261 if (conf->as)
1262 peer->as = conf->as;
1263
1264 /* remote-as */
1265 if (conf->change_local_as)
1266 peer->change_local_as = conf->change_local_as;
1267
1268 /* TTL */
1269 peer->ttl = conf->ttl;
1270
1271 /* Weight */
1272 peer->weight = conf->weight;
1273
1274 /* peer flags apply */
1275 peer->flags = conf->flags;
1276 /* peer af_flags apply */
1277 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1278 /* peer config apply */
1279 peer->config = conf->config;
1280
1281 /* peer timers apply */
1282 peer->holdtime = conf->holdtime;
1283 peer->keepalive = conf->keepalive;
1284 peer->connect = conf->connect;
1285 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1286 peer->v_connect = conf->connect;
1287 else
1288 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1289
1290 /* advertisement-interval reset */
1291 if (peer_sort (peer) == BGP_PEER_IBGP)
1292 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1293 else
1294 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1295
1296 /* maximum-prefix */
1297 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001298 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
paul718e3742002-12-13 20:15:29 +00001299
1300 /* allowas-in */
1301 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1302
1303 /* default-originate route-map */
1304 if (conf->default_rmap[afi][safi].name)
1305 {
1306 if (peer->default_rmap[afi][safi].name)
1307 free (peer->default_rmap[afi][safi].name);
1308 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1309 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1310 }
1311
1312 /* update-source apply */
1313 if (conf->update_source)
1314 {
1315 if (peer->update_source)
1316 sockunion_free (peer->update_source);
1317 if (peer->update_if)
1318 {
1319 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1320 peer->update_if = NULL;
1321 }
1322 peer->update_source = sockunion_dup (conf->update_source);
1323 }
1324 else if (conf->update_if)
1325 {
1326 if (peer->update_if)
1327 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1328 if (peer->update_source)
1329 {
1330 sockunion_free (peer->update_source);
1331 peer->update_source = NULL;
1332 }
1333 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1334 }
1335
1336 /* inbound filter apply */
1337 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1338 {
1339 if (pfilter->dlist[in].name)
1340 free (pfilter->dlist[in].name);
1341 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1342 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1343 }
1344 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1345 {
1346 if (pfilter->plist[in].name)
1347 free (pfilter->plist[in].name);
1348 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1349 pfilter->plist[in].plist = gfilter->plist[in].plist;
1350 }
1351 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1352 {
1353 if (pfilter->aslist[in].name)
1354 free (pfilter->aslist[in].name);
1355 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1356 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1357 }
1358 if (gfilter->map[in].name && ! pfilter->map[in].name)
1359 {
1360 if (pfilter->map[in].name)
1361 free (pfilter->map[in].name);
1362 pfilter->map[in].name = strdup (gfilter->map[in].name);
1363 pfilter->map[in].map = gfilter->map[in].map;
1364 }
1365
1366 /* outbound filter apply */
1367 if (gfilter->dlist[out].name)
1368 {
1369 if (pfilter->dlist[out].name)
1370 free (pfilter->dlist[out].name);
1371 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1372 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1373 }
1374 else
1375 {
1376 if (pfilter->dlist[out].name)
1377 free (pfilter->dlist[out].name);
1378 pfilter->dlist[out].name = NULL;
1379 pfilter->dlist[out].alist = NULL;
1380 }
1381 if (gfilter->plist[out].name)
1382 {
1383 if (pfilter->plist[out].name)
1384 free (pfilter->plist[out].name);
1385 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1386 pfilter->plist[out].plist = gfilter->plist[out].plist;
1387 }
1388 else
1389 {
1390 if (pfilter->plist[out].name)
1391 free (pfilter->plist[out].name);
1392 pfilter->plist[out].name = NULL;
1393 pfilter->plist[out].plist = NULL;
1394 }
1395 if (gfilter->aslist[out].name)
1396 {
1397 if (pfilter->aslist[out].name)
1398 free (pfilter->aslist[out].name);
1399 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1400 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1401 }
1402 else
1403 {
1404 if (pfilter->aslist[out].name)
1405 free (pfilter->aslist[out].name);
1406 pfilter->aslist[out].name = NULL;
1407 pfilter->aslist[out].aslist = NULL;
1408 }
1409 if (gfilter->map[out].name)
1410 {
1411 if (pfilter->map[out].name)
1412 free (pfilter->map[out].name);
1413 pfilter->map[out].name = strdup (gfilter->map[out].name);
1414 pfilter->map[out].map = gfilter->map[out].map;
1415 }
1416 else
1417 {
1418 if (pfilter->map[out].name)
1419 free (pfilter->map[out].name);
1420 pfilter->map[out].name = NULL;
1421 pfilter->map[out].map = NULL;
1422 }
1423
1424 if (gfilter->usmap.name)
1425 {
1426 if (pfilter->usmap.name)
1427 free (pfilter->usmap.name);
1428 pfilter->usmap.name = strdup (gfilter->usmap.name);
1429 pfilter->usmap.map = gfilter->usmap.map;
1430 }
1431 else
1432 {
1433 if (pfilter->usmap.name)
1434 free (pfilter->usmap.name);
1435 pfilter->usmap.name = NULL;
1436 pfilter->usmap.map = NULL;
1437 }
1438}
1439
1440/* Peer group's remote AS configuration. */
1441int
1442peer_group_remote_as (struct bgp *bgp, char *group_name, as_t *as)
1443{
1444 struct peer_group *group;
1445 struct peer *peer;
1446 struct listnode *nn;
1447
1448 group = peer_group_lookup (bgp, group_name);
1449 if (! group)
1450 return -1;
1451
1452 if (group->conf->as == *as)
1453 return 0;
1454
1455 /* When we setup peer-group AS number all peer group member's AS
1456 number must be updated to same number. */
1457 peer_as_change (group->conf, *as);
1458
1459 LIST_LOOP (group->peer, peer, nn)
1460 {
1461 if (peer->as != *as)
1462 peer_as_change (peer, *as);
1463 }
1464
1465 return 0;
1466}
1467
1468int
1469peer_group_delete (struct peer_group *group)
1470{
1471 struct bgp *bgp;
1472 struct peer *peer;
1473 struct listnode *nn;
1474
1475 bgp = group->bgp;
1476
1477 LIST_LOOP (group->peer, peer, nn)
1478 {
1479 peer->group = NULL;
1480 peer_delete (peer);
1481 }
1482 list_delete (group->peer);
1483
1484 free (group->name);
1485 group->name = NULL;
1486
1487 group->conf->group = NULL;
1488 peer_delete (group->conf);
1489
1490 /* Delete from all peer_group list. */
1491 listnode_delete (bgp->group, group);
1492
1493 peer_group_free (group);
1494
1495 return 0;
1496}
1497
1498int
1499peer_group_remote_as_delete (struct peer_group *group)
1500{
1501 struct peer *peer;
1502 struct listnode *nn;
1503
1504 if (! group->conf->as)
1505 return 0;
1506
1507 LIST_LOOP (group->peer, peer, nn)
1508 {
1509 peer->group = NULL;
1510 peer_delete (peer);
1511 }
1512 list_delete_all_node (group->peer);
1513
1514 group->conf->as = 0;
1515
1516 return 0;
1517}
1518
1519/* Bind specified peer to peer group. */
1520int
1521peer_group_bind (struct bgp *bgp, union sockunion *su,
1522 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1523{
1524 struct peer *peer;
1525 int first_member = 0;
1526
1527 /* Check peer group's address family. */
1528 if (! group->conf->afc[afi][safi])
1529 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1530
1531 /* Lookup the peer. */
1532 peer = peer_lookup (bgp, su);
1533
1534 /* Create a new peer. */
1535 if (! peer)
1536 {
1537 if (! group->conf->as)
1538 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1539
1540 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1541 peer->group = group;
1542 peer->af_group[afi][safi] = 1;
1543 listnode_add (group->peer, peer);
1544 peer_group2peer_config_copy (group, peer, afi, safi);
1545
1546 return 0;
1547 }
1548
1549 /* When the peer already belongs to peer group, check the consistency. */
1550 if (peer->af_group[afi][safi])
1551 {
1552 if (strcmp (peer->group->name, group->name) != 0)
1553 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1554
1555 return 0;
1556 }
1557
1558 /* Check current peer group configuration. */
1559 if (peer_group_active (peer)
1560 && strcmp (peer->group->name, group->name) != 0)
1561 return BGP_ERR_PEER_GROUP_MISMATCH;
1562
1563 if (! group->conf->as)
1564 {
1565 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1566 && peer_sort (group->conf) != peer_sort (peer))
1567 {
1568 if (as)
1569 *as = peer->as;
1570 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1571 }
1572
1573 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1574 first_member = 1;
1575 }
1576
1577 peer->af_group[afi][safi] = 1;
1578 peer->afc[afi][safi] = 1;
1579 if (! peer->group)
1580 {
1581 peer->group = group;
1582 listnode_add (group->peer, peer);
1583 }
1584
1585 if (first_member)
1586 {
1587 /* Advertisement-interval reset */
1588 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1589 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1590 else
1591 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1592
1593 /* ebgp-multihop reset */
1594 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1595 group->conf->ttl = 255;
1596
1597 /* local-as reset */
1598 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1599 {
1600 group->conf->change_local_as = 0;
1601 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1602 }
1603 }
1604 peer_group2peer_config_copy (group, peer, afi, safi);
1605
1606 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001607 {
1608 peer->last_reset = PEER_DOWN_RMAP_BIND;
1609 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1610 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1611 }
paul718e3742002-12-13 20:15:29 +00001612 else
1613 BGP_EVENT_ADD (peer, BGP_Stop);
1614
1615 return 0;
1616}
1617
1618int
1619peer_group_unbind (struct bgp *bgp, struct peer *peer,
1620 struct peer_group *group, afi_t afi, safi_t safi)
1621{
1622 if (! peer->af_group[afi][safi])
1623 return 0;
1624
1625 if (group != peer->group)
1626 return BGP_ERR_PEER_GROUP_MISMATCH;
1627
1628 peer->af_group[afi][safi] = 0;
1629 peer->afc[afi][safi] = 0;
1630 peer_af_flag_reset (peer, afi, safi);
1631
1632 if (! peer_group_active (peer))
1633 {
1634 listnode_delete (group->peer, peer);
1635 peer->group = NULL;
1636 if (group->conf->as)
1637 {
1638 peer_delete (peer);
1639 return 0;
1640 }
1641 peer_global_config_reset (peer);
1642 }
1643
1644 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001645 {
1646 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1647 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1648 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1649 }
paul718e3742002-12-13 20:15:29 +00001650 else
1651 BGP_EVENT_ADD (peer, BGP_Stop);
1652
1653 return 0;
1654}
1655
1656/* BGP instance creation by `router bgp' commands. */
1657struct bgp *
1658bgp_create (as_t *as, char *name)
1659{
1660 struct bgp *bgp;
1661 afi_t afi;
1662 safi_t safi;
1663
1664 bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp));
1665
1666 bgp->peer_self = peer_new ();
1667 bgp->peer_self->host = "Static announcement";
1668
1669 bgp->peer = list_new ();
1670 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1671
1672 bgp->group = list_new ();
1673 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1674
1675 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1676 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1677 {
1678 bgp->route[afi][safi] = bgp_table_init ();
1679 bgp->aggregate[afi][safi] = bgp_table_init ();
1680 bgp->rib[afi][safi] = bgp_table_init ();
1681 }
1682
1683 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1684 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1685 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001686 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1687 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001688
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);
hasso538621f2004-05-21 09:31:30 +00004615
4616 /* BGP graceful-restart. */
4617 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
4618 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
4619
paul718e3742002-12-13 20:15:29 +00004620 /* BGP bestpath method. */
4621 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
4622 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
4623 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
4624 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
4625 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
4626 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4627 {
4628 vty_out (vty, " bgp bestpath med");
4629 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
4630 vty_out (vty, " confed");
4631 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4632 vty_out (vty, " missing-as-worst");
4633 vty_out (vty, "%s", VTY_NEWLINE);
4634 }
4635
4636 /* BGP network import check. */
4637 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
4638 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
4639
4640 /* BGP scan interval. */
4641 bgp_config_write_scan_time (vty);
4642
4643 /* BGP flag dampening. */
4644 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
4645 BGP_CONFIG_DAMPENING))
4646 bgp_config_write_damp (vty);
4647
4648 /* BGP static route configuration. */
4649 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4650
4651 /* BGP redistribute configuration. */
4652 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4653
4654 /* BGP timers configuration. */
4655 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
4656 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
4657 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
4658 bgp->default_holdtime, VTY_NEWLINE);
4659
4660 /* peer-group */
4661 LIST_LOOP (bgp->group, group, nm)
4662 {
4663 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
4664 }
4665
4666 /* Normal neighbor configuration. */
4667 LIST_LOOP (bgp->peer, peer, no)
4668 {
4669 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4670 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
4671 }
4672
4673 /* Distance configuration. */
4674 bgp_config_write_distance (vty, bgp);
4675
4676 /* No auto-summary */
4677 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4678 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
4679
4680 /* IPv4 multicast configuration. */
4681 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
4682
4683 /* IPv4 VPN configuration. */
4684 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
4685
4686 /* IPv6 unicast configuration. */
4687 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
4688
4689 write++;
4690 }
4691 return write;
4692}
4693
4694void
4695bgp_master_init ()
4696{
4697 memset (&bgp_master, 0, sizeof (struct bgp_master));
4698
4699 bm = &bgp_master;
4700 bm->bgp = list_new ();
4701 bm->port = BGP_PORT_DEFAULT;
4702 bm->master = thread_master_create ();
4703 bm->start_time = time (NULL);
4704}
4705
4706void
4707bgp_init ()
4708{
4709 void bgp_zebra_init ();
4710 void bgp_route_map_init ();
4711 void bgp_filter_init ();
4712
4713 /* BGP VTY commands installation. */
4714 bgp_vty_init ();
4715
4716 /* Create BGP server socket. */
4717 bgp_socket (NULL, bm->port);
4718
4719 /* Init zebra. */
4720 bgp_zebra_init ();
4721
4722 /* BGP inits. */
4723 bgp_attr_init ();
4724 bgp_debug_init ();
4725 bgp_dump_init ();
4726 bgp_route_init ();
4727 bgp_route_map_init ();
4728 bgp_scan_init ();
4729 bgp_mplsvpn_init ();
4730
4731 /* Access list initialize. */
4732 access_list_init ();
4733 access_list_add_hook (peer_distribute_update);
4734 access_list_delete_hook (peer_distribute_update);
4735
4736 /* Filter list initialize. */
4737 bgp_filter_init ();
4738 as_list_add_hook (peer_aslist_update);
4739 as_list_delete_hook (peer_aslist_update);
4740
4741 /* Prefix list initialize.*/
4742 prefix_list_init ();
4743 prefix_list_add_hook (peer_prefix_list_update);
4744 prefix_list_delete_hook (peer_prefix_list_update);
4745
4746 /* Community list initialize. */
4747 bgp_clist = community_list_init ();
4748
4749#ifdef HAVE_SNMP
4750 bgp_snmp_init ();
4751#endif /* HAVE_SNMP */
4752}
paul545acaf2004-04-20 15:13:15 +00004753
4754void
4755bgp_terminate ()
4756{
4757 struct bgp_master *bm;
4758 struct bgp *bgp;
4759 struct peer *peer;
4760 struct listnode *nn;
4761 struct listnode *mm;
4762
4763 bm = bgp_get_master ();
4764
4765 LIST_LOOP (bm->bgp, bgp, nn)
4766 LIST_LOOP (bgp->peer, peer, mm)
4767 if (peer->status == Established)
4768 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4769 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
4770
4771 bgp_cleanup_routes ();
4772}
4773