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