blob: f96966102fa7cf6105f316e282c79f1030994eea [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* BGP-4, BGP-4+ daemon program
2 Copyright (C) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "prefix.h"
24#include "thread.h"
25#include "buffer.h"
26#include "stream.h"
27#include "command.h"
28#include "sockunion.h"
29#include "network.h"
30#include "memory.h"
31#include "filter.h"
32#include "routemap.h"
33#include "str.h"
34#include "log.h"
35#include "plist.h"
36#include "linklist.h"
37
38#include "bgpd/bgpd.h"
39#include "bgpd/bgp_table.h"
40#include "bgpd/bgp_aspath.h"
41#include "bgpd/bgp_route.h"
42#include "bgpd/bgp_dump.h"
43#include "bgpd/bgp_debug.h"
44#include "bgpd/bgp_community.h"
45#include "bgpd/bgp_attr.h"
46#include "bgpd/bgp_regex.h"
47#include "bgpd/bgp_clist.h"
48#include "bgpd/bgp_fsm.h"
49#include "bgpd/bgp_packet.h"
50#include "bgpd/bgp_zebra.h"
51#include "bgpd/bgp_open.h"
52#include "bgpd/bgp_filter.h"
53#include "bgpd/bgp_nexthop.h"
54#include "bgpd/bgp_damp.h"
55#include "bgpd/bgp_mplsvpn.h"
56#include "bgpd/bgp_advertise.h"
57#include "bgpd/bgp_network.h"
58#include "bgpd/bgp_vty.h"
59#ifdef HAVE_SNMP
60#include "bgpd/bgp_snmp.h"
61#endif /* HAVE_SNMP */
62
63/* BGP process wide configuration. */
64static struct bgp_master bgp_master;
65
hasso18a6dce2004-10-03 18:18:34 +000066extern struct in_addr router_id_zebra;
67
paul718e3742002-12-13 20:15:29 +000068/* BGP process wide configuration pointer to export. */
69struct bgp_master *bm;
70
71/* BGP community-list. */
72struct community_list_handler *bgp_clist;
73
74/* BGP global flag manipulation. */
75int
76bgp_option_set (int flag)
77{
78 switch (flag)
79 {
80 case BGP_OPT_NO_FIB:
81 case BGP_OPT_MULTIPLE_INSTANCE:
82 case BGP_OPT_CONFIG_CISCO:
83 SET_FLAG (bm->options, flag);
84 break;
85 default:
86 return BGP_ERR_INVALID_FLAG;
87 break;
88 }
89 return 0;
90}
91
92int
93bgp_option_unset (int flag)
94{
95 switch (flag)
96 {
97 case BGP_OPT_MULTIPLE_INSTANCE:
98 if (listcount (bm->bgp) > 1)
99 return BGP_ERR_MULTIPLE_INSTANCE_USED;
100 /* Fall through. */
101 case BGP_OPT_NO_FIB:
102 case BGP_OPT_CONFIG_CISCO:
103 UNSET_FLAG (bm->options, flag);
104 break;
105 default:
106 return BGP_ERR_INVALID_FLAG;
107 break;
108 }
109 return 0;
110}
111
112int
113bgp_option_check (int flag)
114{
115 return CHECK_FLAG (bm->options, flag);
116}
117
118/* BGP flag manipulation. */
119int
120bgp_flag_set (struct bgp *bgp, int flag)
121{
122 SET_FLAG (bgp->flags, flag);
123 return 0;
124}
125
126int
127bgp_flag_unset (struct bgp *bgp, int flag)
128{
129 UNSET_FLAG (bgp->flags, flag);
130 return 0;
131}
132
133int
134bgp_flag_check (struct bgp *bgp, int flag)
135{
136 return CHECK_FLAG (bgp->flags, flag);
137}
138
139/* Internal function to set BGP structure configureation flag. */
140static void
141bgp_config_set (struct bgp *bgp, int config)
142{
143 SET_FLAG (bgp->config, config);
144}
145
146static void
147bgp_config_unset (struct bgp *bgp, int config)
148{
149 UNSET_FLAG (bgp->config, config);
150}
151
152static int
153bgp_config_check (struct bgp *bgp, int config)
154{
155 return CHECK_FLAG (bgp->config, config);
156}
157
158/* Set BGP router identifier. */
159int
160bgp_router_id_set (struct bgp *bgp, struct in_addr *id)
161{
162 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000163 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000164
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. */
paul1eb8ef22005-04-07 07:30:20 +0000173 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000174 {
175 IPV4_ADDR_COPY (&peer->local_id, id);
176
177 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000178 {
179 peer->last_reset = PEER_DOWN_RID_CHANGE;
180 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
181 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
182 }
paul718e3742002-12-13 20:15:29 +0000183 }
184 return 0;
185}
186
paul718e3742002-12-13 20:15:29 +0000187/* BGP's cluster-id control. */
188int
189bgp_cluster_id_set (struct bgp *bgp, struct in_addr *cluster_id)
190{
191 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000192 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000193
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. */
paul1eb8ef22005-04-07 07:30:20 +0000202 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000203 {
204 if (peer_sort (peer) != BGP_PEER_IBGP)
205 continue;
206
207 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000208 {
209 peer->last_reset = PEER_DOWN_CLID_CHANGE;
210 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
211 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
212 }
paul718e3742002-12-13 20:15:29 +0000213 }
214 return 0;
215}
216
217int
218bgp_cluster_id_unset (struct bgp *bgp)
219{
220 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000221 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000222
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. */
paul1eb8ef22005-04-07 07:30:20 +0000230 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000231 {
232 if (peer_sort (peer) != BGP_PEER_IBGP)
233 continue;
234
235 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000236 {
237 peer->last_reset = PEER_DOWN_CLID_CHANGE;
238 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
239 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
240 }
paul718e3742002-12-13 20:15:29 +0000241 }
242 return 0;
243}
244
245/* BGP timer configuration. */
246int
247bgp_timers_set (struct bgp *bgp, u_int32_t keepalive, u_int32_t holdtime)
248{
249 bgp->default_keepalive = (keepalive < holdtime / 3
250 ? keepalive : holdtime / 3);
251 bgp->default_holdtime = holdtime;
252
253 return 0;
254}
255
256int
257bgp_timers_unset (struct bgp *bgp)
258{
259 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
260 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
261
262 return 0;
263}
264
265/* BGP confederation configuration. */
266int
267bgp_confederation_id_set (struct bgp *bgp, as_t as)
268{
269 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000270 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000271 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. */
paul1eb8ef22005-04-07 07:30:20 +0000284 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000285 {
286 /* We're looking for peers who's AS is not local or part of our
287 confederation. */
288 if (already_confed)
289 {
290 if (peer_sort (peer) == BGP_PEER_EBGP)
291 {
292 peer->local_as = as;
293 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000294 {
295 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
296 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
297 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
298 }
299
paul718e3742002-12-13 20:15:29 +0000300 else
301 BGP_EVENT_ADD (peer, BGP_Stop);
302 }
303 }
304 else
305 {
306 /* Not doign confederation before, so reset every non-local
307 session */
308 if (peer_sort (peer) != BGP_PEER_IBGP)
309 {
310 /* Reset the local_as to be our EBGP one */
311 if (peer_sort (peer) == BGP_PEER_EBGP)
312 peer->local_as = as;
313 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000314 {
315 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
316 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
317 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
318 }
paul718e3742002-12-13 20:15:29 +0000319 else
320 BGP_EVENT_ADD (peer, BGP_Stop);
321 }
322 }
323 }
324 return 0;
325}
326
327int
328bgp_confederation_id_unset (struct bgp *bgp)
329{
330 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000331 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000332
333 bgp->confed_id = 0;
334 bgp_config_unset (bgp, BGP_CONFIG_CONFEDERATION);
335
paul1eb8ef22005-04-07 07:30:20 +0000336 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000337 {
338 /* We're looking for peers who's AS is not local */
339 if (peer_sort (peer) != BGP_PEER_IBGP)
340 {
341 peer->local_as = bgp->as;
342 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000343 {
344 peer->last_reset = PEER_DOWN_CONFED_ID_CHANGE;
345 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
346 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
347 }
348
paul718e3742002-12-13 20:15:29 +0000349 else
350 BGP_EVENT_ADD (peer, BGP_Stop);
351 }
352 }
353 return 0;
354}
355
356/* Is an AS part of the confed or not? */
357int
358bgp_confederation_peers_check (struct bgp *bgp, as_t as)
359{
360 int i;
361
362 if (! bgp)
363 return 0;
364
365 for (i = 0; i < bgp->confed_peers_cnt; i++)
366 if (bgp->confed_peers[i] == as)
367 return 1;
368
369 return 0;
370}
371
372/* Add an AS to the confederation set. */
373int
374bgp_confederation_peers_add (struct bgp *bgp, as_t as)
375{
376 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000377 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000378
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 {
paul1eb8ef22005-04-07 07:30:20 +0000401 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000402 {
403 if (peer->as == as)
404 {
405 peer->local_as = bgp->as;
406 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000407 {
408 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
409 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
410 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
411 }
paul718e3742002-12-13 20:15:29 +0000412 else
413 BGP_EVENT_ADD (peer, BGP_Stop);
414 }
415 }
416 }
417 return 0;
418}
419
420/* Delete an AS from the confederation set. */
421int
422bgp_confederation_peers_remove (struct bgp *bgp, as_t as)
423{
424 int i;
425 int j;
426 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +0000427 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000428
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 {
paul1eb8ef22005-04-07 07:30:20 +0000457 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +0000458 {
459 if (peer->as == as)
460 {
461 peer->local_as = bgp->confed_id;
462 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000463 {
464 peer->last_reset = PEER_DOWN_CONFED_PEER_CHANGE;
465 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
466 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
467 }
paul718e3742002-12-13 20:15:29 +0000468 else
469 BGP_EVENT_ADD (peer, BGP_Stop);
470 }
471 }
472 }
473
474 return 0;
475}
476
477/* Local preference configuration. */
478int
479bgp_default_local_preference_set (struct bgp *bgp, u_int32_t local_pref)
480{
481 if (! bgp)
482 return -1;
483
paul718e3742002-12-13 20:15:29 +0000484 bgp->default_local_pref = local_pref;
485
486 return 0;
487}
488
489int
490bgp_default_local_preference_unset (struct bgp *bgp)
491{
492 if (! bgp)
493 return -1;
494
paul718e3742002-12-13 20:15:29 +0000495 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
496
497 return 0;
498}
499
paulfee0f4c2004-09-13 05:12:46 +0000500/* If peer is RSERVER_CLIENT in at least one address family and is not member
501 of a peer_group for that family, return 1.
502 Used to check wether the peer is included in list bgp->rsclient. */
503int
504peer_rsclient_active (struct peer *peer)
505{
506 int i;
507 int j;
508
509 for (i=AFI_IP; i < AFI_MAX; i++)
510 for (j=SAFI_UNICAST; j < SAFI_MAX; j++)
511 if (CHECK_FLAG(peer->af_flags[i][j], PEER_FLAG_RSERVER_CLIENT)
512 && ! peer->af_group[i][j])
513 return 1;
514 return 0;
515}
516
pauleb821182004-05-01 08:44:08 +0000517/* Peer comparison function for sorting. */
paul718e3742002-12-13 20:15:29 +0000518static int
519peer_cmp (struct peer *p1, struct peer *p2)
520{
pauleb821182004-05-01 08:44:08 +0000521 return sockunion_cmp (&p1->su, &p2->su);
paul718e3742002-12-13 20:15:29 +0000522}
523
524int
525peer_af_flag_check (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
526{
527 return CHECK_FLAG (peer->af_flags[afi][safi], flag);
528}
529
530/* Reset all address family specific configuration. */
531static void
532peer_af_flag_reset (struct peer *peer, afi_t afi, safi_t safi)
533{
534 int i;
535 struct bgp_filter *filter;
536 char orf_name[BUFSIZ];
537
538 filter = &peer->filter[afi][safi];
539
540 /* Clear neighbor filter and route-map */
541 for (i = FILTER_IN; i < FILTER_MAX; i++)
542 {
543 if (filter->dlist[i].name)
544 {
545 free (filter->dlist[i].name);
546 filter->dlist[i].name = NULL;
547 }
548 if (filter->plist[i].name)
549 {
550 free (filter->plist[i].name);
551 filter->plist[i].name = NULL;
552 }
553 if (filter->aslist[i].name)
554 {
555 free (filter->aslist[i].name);
556 filter->aslist[i].name = NULL;
557 }
paulfee0f4c2004-09-13 05:12:46 +0000558 }
559 for (i = RMAP_IN; i < RMAP_MAX; i++)
560 {
paul718e3742002-12-13 20:15:29 +0000561 if (filter->map[i].name)
562 {
563 free (filter->map[i].name);
564 filter->map[i].name = NULL;
565 }
566 }
567
568 /* Clear unsuppress map. */
569 if (filter->usmap.name)
570 free (filter->usmap.name);
571 filter->usmap.name = NULL;
572 filter->usmap.map = NULL;
573
574 /* Clear neighbor's all address family flags. */
575 peer->af_flags[afi][safi] = 0;
576
577 /* Clear neighbor's all address family sflags. */
578 peer->af_sflags[afi][safi] = 0;
579
580 /* Clear neighbor's all address family capabilities. */
581 peer->af_cap[afi][safi] = 0;
582
583 /* Clear ORF info */
584 peer->orf_plist[afi][safi] = NULL;
585 sprintf (orf_name, "%s.%d.%d", peer->host, afi, safi);
586 prefix_bgp_orf_remove_all (orf_name);
587
588 /* Set default neighbor send-community. */
589 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
590 {
591 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
592 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
593 }
594
595 /* Clear neighbor default_originate_rmap */
596 if (peer->default_rmap[afi][safi].name)
597 free (peer->default_rmap[afi][safi].name);
598 peer->default_rmap[afi][safi].name = NULL;
599 peer->default_rmap[afi][safi].map = NULL;
600
601 /* Clear neighbor maximum-prefix */
602 peer->pmax[afi][safi] = 0;
hassoe0701b72004-05-20 09:19:34 +0000603 peer->pmax_threshold[afi][safi] = MAXIMUM_PREFIX_THRESHOLD_DEFAULT;
paul718e3742002-12-13 20:15:29 +0000604}
605
606/* peer global config reset */
607void
608peer_global_config_reset (struct peer *peer)
609{
610 peer->weight = 0;
611 peer->change_local_as = 0;
612 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
613 if (peer->update_source)
614 {
615 sockunion_free (peer->update_source);
616 peer->update_source = NULL;
617 }
618 if (peer->update_if)
619 {
620 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
621 peer->update_if = NULL;
622 }
623
624 if (peer_sort (peer) == BGP_PEER_IBGP)
625 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
626 else
627 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
628
629 peer->flags = 0;
630 peer->config = 0;
631 peer->holdtime = 0;
632 peer->keepalive = 0;
633 peer->connect = 0;
634 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
635}
636
637/* Check peer's AS number and determin is this peer IBGP or EBGP */
638int
639peer_sort (struct peer *peer)
640{
641 struct bgp *bgp;
642
643 bgp = peer->bgp;
644
645 /* Peer-group */
646 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
647 {
648 if (peer->as)
649 return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP);
650 else
651 {
652 struct peer *peer1;
653 peer1 = listnode_head (peer->group->peer);
654 if (peer1)
655 return (peer1->local_as == peer1->as
656 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
657 }
658 return BGP_PEER_INTERNAL;
659 }
660
661 /* Normal peer */
662 if (bgp && CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
663 {
664 if (peer->local_as == 0)
665 return BGP_PEER_INTERNAL;
666
667 if (peer->local_as == peer->as)
668 {
669 if (peer->local_as == bgp->confed_id)
670 return BGP_PEER_EBGP;
671 else
672 return BGP_PEER_IBGP;
673 }
674
675 if (bgp_confederation_peers_check (bgp, peer->as))
676 return BGP_PEER_CONFED;
677
678 return BGP_PEER_EBGP;
679 }
680 else
681 {
682 return (peer->local_as == 0
683 ? BGP_PEER_INTERNAL : peer->local_as == peer->as
684 ? BGP_PEER_IBGP : BGP_PEER_EBGP);
685 }
686}
687
688/* Allocate new peer object. */
689static struct peer *
690peer_new ()
691{
692 afi_t afi;
693 safi_t safi;
694 struct peer *peer;
695 struct servent *sp;
696
697 /* Allocate new peer. */
698 peer = XMALLOC (MTYPE_BGP_PEER, sizeof (struct peer));
699 memset (peer, 0, sizeof (struct peer));
700
701 /* Set default value. */
pauleb821182004-05-01 08:44:08 +0000702 peer->fd = -1;
paul718e3742002-12-13 20:15:29 +0000703 peer->v_start = BGP_INIT_START_TIMER;
704 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
705 peer->v_asorig = BGP_DEFAULT_ASORIGINATE;
706 peer->status = Idle;
707 peer->ostatus = Idle;
paul718e3742002-12-13 20:15:29 +0000708 peer->weight = 0;
709
710 /* Set default flags. */
711 for (afi = AFI_IP; afi < AFI_MAX; afi++)
712 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
713 {
714 if (! bgp_option_check (BGP_OPT_CONFIG_CISCO))
715 {
716 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY);
717 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY);
718 }
719 peer->orf_plist[afi][safi] = NULL;
720 }
721 SET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
722
723 /* Create buffers. */
724 peer->ibuf = stream_new (BGP_MAX_PACKET_SIZE);
725 peer->obuf = stream_fifo_new ();
726 peer->work = stream_new (BGP_MAX_PACKET_SIZE);
727
728 bgp_sync_init (peer);
729
730 /* Get service port number. */
731 sp = getservbyname ("bgp", "tcp");
732 peer->port = (sp == NULL) ? BGP_PORT_DEFAULT : ntohs (sp->s_port);
733
734 return peer;
735}
736
737/* Create new BGP peer. */
738struct peer *
739peer_create (union sockunion *su, struct bgp *bgp, as_t local_as,
740 as_t remote_as, afi_t afi, safi_t safi)
741{
742 int active;
743 struct peer *peer;
744 char buf[SU_ADDRSTRLEN];
745
746 peer = peer_new ();
747 peer->bgp = bgp;
748 peer->su = *su;
749 peer->local_as = local_as;
750 peer->as = remote_as;
751 peer->local_id = bgp->router_id;
752 peer->v_holdtime = bgp->default_holdtime;
753 peer->v_keepalive = bgp->default_keepalive;
754 if (peer_sort (peer) == BGP_PEER_IBGP)
755 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
756 else
757 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
758 listnode_add_sort (bgp->peer, peer);
759
760 active = peer_active (peer);
761
762 if (afi && safi)
763 peer->afc[afi][safi] = 1;
764
765 /* Last read time set */
766 peer->readtime = time (NULL);
767
paul848973c2003-08-13 00:32:49 +0000768 /* Last reset time set */
769 peer->resettime = time (NULL);
770
paul718e3742002-12-13 20:15:29 +0000771 /* Default TTL set. */
772 peer->ttl = (peer_sort (peer) == BGP_PEER_IBGP ? 255 : 1);
773
774 /* Make peer's address string. */
775 sockunion2str (su, buf, SU_ADDRSTRLEN);
paule83e2082005-05-19 02:12:25 +0000776 peer->host = XSTRDUP (MTYPE_BGP_PEER_HOST, buf);
paul718e3742002-12-13 20:15:29 +0000777
778 /* Set up peer's events and timers. */
779 if (! active && peer_active (peer))
780 bgp_timer_set (peer);
781
782 return peer;
783}
784
pauleb821182004-05-01 08:44:08 +0000785/* Make accept BGP peer. Called from bgp_accept (). */
786struct peer *
787peer_create_accept (struct bgp *bgp)
788{
789 struct peer *peer;
790
791 peer = peer_new ();
792 peer->bgp = bgp;
793 listnode_add_sort (bgp->peer, peer);
794
795 return peer;
796}
797
paul718e3742002-12-13 20:15:29 +0000798/* Change peer's AS number. */
799void
800peer_as_change (struct peer *peer, as_t as)
801{
802 int type;
803
804 /* Stop peer. */
805 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
806 {
807 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +0000808 {
809 peer->last_reset = PEER_DOWN_REMOTE_AS_CHANGE;
810 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
811 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
812 }
paul718e3742002-12-13 20:15:29 +0000813 else
814 BGP_EVENT_ADD (peer, BGP_Stop);
815 }
816 type = peer_sort (peer);
817 peer->as = as;
818
paul848973c2003-08-13 00:32:49 +0000819 if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION)
820 && ! bgp_confederation_peers_check (peer->bgp, as)
821 && peer->bgp->as != as)
822 peer->local_as = peer->bgp->confed_id;
823 else
824 peer->local_as = peer->bgp->as;
825
paul718e3742002-12-13 20:15:29 +0000826 /* Advertisement-interval reset */
827 if (peer_sort (peer) == BGP_PEER_IBGP)
828 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
829 else
830 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
831
832 /* TTL reset */
833 if (peer_sort (peer) == BGP_PEER_IBGP)
834 peer->ttl = 255;
835 else if (type == BGP_PEER_IBGP)
836 peer->ttl = 1;
837
838 /* reflector-client reset */
839 if (peer_sort (peer) != BGP_PEER_IBGP)
840 {
841 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_UNICAST],
842 PEER_FLAG_REFLECTOR_CLIENT);
843 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MULTICAST],
844 PEER_FLAG_REFLECTOR_CLIENT);
845 UNSET_FLAG (peer->af_flags[AFI_IP][SAFI_MPLS_VPN],
846 PEER_FLAG_REFLECTOR_CLIENT);
847 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_UNICAST],
848 PEER_FLAG_REFLECTOR_CLIENT);
849 UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_MULTICAST],
850 PEER_FLAG_REFLECTOR_CLIENT);
851 }
852
853 /* local-as reset */
854 if (peer_sort (peer) != BGP_PEER_EBGP)
855 {
856 peer->change_local_as = 0;
857 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
858 }
859}
860
861/* If peer does not exist, create new one. If peer already exists,
862 set AS number to the peer. */
863int
864peer_remote_as (struct bgp *bgp, union sockunion *su, as_t *as,
865 afi_t afi, safi_t safi)
866{
867 struct peer *peer;
868 as_t local_as;
869
870 peer = peer_lookup (bgp, su);
871
872 if (peer)
873 {
874 /* When this peer is a member of peer-group. */
875 if (peer->group)
876 {
877 if (peer->group->conf->as)
878 {
879 /* Return peer group's AS number. */
880 *as = peer->group->conf->as;
881 return BGP_ERR_PEER_GROUP_MEMBER;
882 }
883 if (peer_sort (peer->group->conf) == BGP_PEER_IBGP)
884 {
885 if (bgp->as != *as)
886 {
887 *as = peer->as;
888 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
889 }
890 }
891 else
892 {
893 if (bgp->as == *as)
894 {
895 *as = peer->as;
896 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
897 }
898 }
899 }
900
901 /* Existing peer's AS number change. */
902 if (peer->as != *as)
903 peer_as_change (peer, *as);
904 }
905 else
906 {
907
908 /* If the peer is not part of our confederation, and its not an
909 iBGP peer then spoof the source AS */
910 if (bgp_config_check (bgp, BGP_CONFIG_CONFEDERATION)
911 && ! bgp_confederation_peers_check (bgp, *as)
912 && bgp->as != *as)
913 local_as = bgp->confed_id;
914 else
915 local_as = bgp->as;
916
917 /* If this is IPv4 unicast configuration and "no bgp default
918 ipv4-unicast" is specified. */
919
920 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4)
921 && afi == AFI_IP && safi == SAFI_UNICAST)
922 peer = peer_create (su, bgp, local_as, *as, 0, 0);
923 else
924 peer = peer_create (su, bgp, local_as, *as, afi, safi);
925 }
926
927 return 0;
928}
929
930/* Activate the peer or peer group for specified AFI and SAFI. */
931int
932peer_activate (struct peer *peer, afi_t afi, safi_t safi)
933{
934 int active;
935
936 if (peer->afc[afi][safi])
937 return 0;
938
939 /* Activate the address family configuration. */
940 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
941 peer->afc[afi][safi] = 1;
942 else
943 {
944 active = peer_active (peer);
945
946 peer->afc[afi][safi] = 1;
947
948 if (! active && peer_active (peer))
949 bgp_timer_set (peer);
950 else
951 {
952 if (peer->status == Established)
953 {
954 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
955 {
956 peer->afc_adv[afi][safi] = 1;
957 bgp_capability_send (peer, afi, safi,
958 CAPABILITY_CODE_MP,
959 CAPABILITY_ACTION_SET);
960 if (peer->afc_recv[afi][safi])
961 {
962 peer->afc_nego[afi][safi] = 1;
963 bgp_announce_route (peer, afi, safi);
964 }
965 }
966 else
hassoe0701b72004-05-20 09:19:34 +0000967 {
968 peer->last_reset = PEER_DOWN_AF_ACTIVATE;
969 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
970 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
971 }
paul718e3742002-12-13 20:15:29 +0000972 }
973 }
974 }
975 return 0;
976}
977
978int
979peer_deactivate (struct peer *peer, afi_t afi, safi_t safi)
980{
981 struct peer_group *group;
982 struct peer *peer1;
paul1eb8ef22005-04-07 07:30:20 +0000983 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +0000984
985 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
986 {
987 group = peer->group;
988
paul1eb8ef22005-04-07 07:30:20 +0000989 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer1))
paul718e3742002-12-13 20:15:29 +0000990 {
991 if (peer1->af_group[afi][safi])
992 return BGP_ERR_PEER_GROUP_MEMBER_EXISTS;
993 }
994 }
995 else
996 {
997 if (peer->af_group[afi][safi])
998 return BGP_ERR_PEER_BELONGS_TO_GROUP;
999 }
1000
1001 if (! peer->afc[afi][safi])
1002 return 0;
1003
1004 /* De-activate the address family configuration. */
1005 peer->afc[afi][safi] = 0;
1006 peer_af_flag_reset (peer, afi, safi);
1007
1008 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
1009 {
1010 if (peer->status == Established)
1011 {
1012 if (CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV))
1013 {
1014 peer->afc_adv[afi][safi] = 0;
1015 peer->afc_nego[afi][safi] = 0;
1016
1017 if (peer_active_nego (peer))
1018 {
1019 bgp_capability_send (peer, afi, safi,
1020 CAPABILITY_CODE_MP,
1021 CAPABILITY_ACTION_UNSET);
1022 bgp_clear_route (peer, afi, safi);
1023 peer->pcount[afi][safi] = 0;
1024 }
1025 else
hassoe0701b72004-05-20 09:19:34 +00001026 {
1027 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1028 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1029 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1030 }
paul718e3742002-12-13 20:15:29 +00001031 }
1032 else
hassoe0701b72004-05-20 09:19:34 +00001033 {
1034 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
1035 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1036 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1037 }
paul718e3742002-12-13 20:15:29 +00001038 }
1039 }
1040 return 0;
1041}
1042
hasso93406d82005-02-02 14:40:33 +00001043void
1044peer_nsf_stop (struct peer *peer)
1045{
1046 afi_t afi;
1047 safi_t safi;
1048
1049 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
1050 UNSET_FLAG (peer->sflags, PEER_STATUS_NSF_MODE);
1051
1052 for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1053 for (safi = SAFI_UNICAST ; safi < SAFI_UNICAST_MULTICAST ; safi++)
1054 peer->nsf[afi][safi] = 0;
1055
1056 if (peer->t_gr_restart)
1057 {
1058 BGP_TIMER_OFF (peer->t_gr_restart);
1059 if (BGP_DEBUG (events, EVENTS))
1060 zlog_debug ("%s graceful restart timer stopped", peer->host);
1061 }
1062 if (peer->t_gr_stale)
1063 {
1064 BGP_TIMER_OFF (peer->t_gr_stale);
1065 if (BGP_DEBUG (events, EVENTS))
1066 zlog_debug ("%s graceful restart stalepath timer stopped", peer->host);
1067 }
1068 bgp_clear_route_all (peer);
1069}
1070
paul718e3742002-12-13 20:15:29 +00001071/* Delete peer from confguration. */
1072int
1073peer_delete (struct peer *peer)
1074{
1075 int i;
1076 afi_t afi;
1077 safi_t safi;
1078 struct bgp *bgp;
1079 struct bgp_filter *filter;
1080
1081 bgp = peer->bgp;
1082
hasso93406d82005-02-02 14:40:33 +00001083 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
1084 peer_nsf_stop (peer);
1085
paul718e3742002-12-13 20:15:29 +00001086 /* If this peer belongs to peer group. Clearn up the
1087 relationship. */
1088 if (peer->group)
1089 {
1090 listnode_delete (peer->group->peer, peer);
1091 peer->group = NULL;
1092 }
1093
1094 /* Withdraw all information from routing table. We can not use
1095 BGP_EVENT_ADD (peer, BGP_Stop) at here. Because the event is
1096 executed after peer structure is deleted. */
hassoe0701b72004-05-20 09:19:34 +00001097 peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
paul718e3742002-12-13 20:15:29 +00001098 bgp_stop (peer);
1099 bgp_fsm_change_status (peer, Idle);
1100
1101 /* Stop all timers. */
1102 BGP_TIMER_OFF (peer->t_start);
1103 BGP_TIMER_OFF (peer->t_connect);
1104 BGP_TIMER_OFF (peer->t_holdtime);
1105 BGP_TIMER_OFF (peer->t_keepalive);
1106 BGP_TIMER_OFF (peer->t_asorig);
1107 BGP_TIMER_OFF (peer->t_routeadv);
hasso0a486e52005-02-01 20:57:17 +00001108 BGP_TIMER_OFF (peer->t_pmax_restart);
hasso93406d82005-02-02 14:40:33 +00001109 BGP_TIMER_OFF (peer->t_gr_restart);
1110 BGP_TIMER_OFF (peer->t_gr_stale);
paul718e3742002-12-13 20:15:29 +00001111
1112 /* Delete from all peer list. */
1113 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
paulfee0f4c2004-09-13 05:12:46 +00001114 {
paul718e3742002-12-13 20:15:29 +00001115 listnode_delete (bgp->peer, peer);
paulfee0f4c2004-09-13 05:12:46 +00001116 if (peer_rsclient_active (peer))
1117 listnode_delete (bgp->rsclient, peer);
1118 }
1119
1120 /* Free RIB for any family in which peer is RSERVER_CLIENT, and is not
1121 member of a peer_group. */
1122 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1123 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1124 if (peer->rib[afi][safi] && ! peer->af_group[afi][safi])
1125 bgp_table_finish (peer->rib[afi][safi]);
paul718e3742002-12-13 20:15:29 +00001126
1127 /* Buffer. */
1128 if (peer->ibuf)
1129 stream_free (peer->ibuf);
1130
1131 if (peer->obuf)
1132 stream_fifo_free (peer->obuf);
1133
1134 if (peer->work)
1135 stream_free (peer->work);
1136
1137 /* Free allocated host character. */
1138 if (peer->host)
paule83e2082005-05-19 02:12:25 +00001139 XFREE (MTYPE_BGP_PEER_HOST, peer->host);
paul718e3742002-12-13 20:15:29 +00001140
1141 /* Local and remote addresses. */
1142 if (peer->su_local)
paul22db9de2005-05-19 01:50:11 +00001143 sockunion_free (peer->su_local);
paul718e3742002-12-13 20:15:29 +00001144 if (peer->su_remote)
paul22db9de2005-05-19 01:50:11 +00001145 sockunion_free (peer->su_remote);
paul718e3742002-12-13 20:15:29 +00001146
1147 /* Peer description string. */
1148 if (peer->desc)
paule83e2082005-05-19 02:12:25 +00001149 XFREE (MTYPE_PEER_DESC, peer->desc);
paul718e3742002-12-13 20:15:29 +00001150
1151 bgp_sync_delete (peer);
1152
1153 /* Free filter related memory. */
1154 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1155 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1156 {
1157 filter = &peer->filter[afi][safi];
1158
1159 for (i = FILTER_IN; i < FILTER_MAX; i++)
1160 {
1161 if (filter->dlist[i].name)
1162 free (filter->dlist[i].name);
1163 if (filter->plist[i].name)
1164 free (filter->plist[i].name);
1165 if (filter->aslist[i].name)
1166 free (filter->aslist[i].name);
paulfee0f4c2004-09-13 05:12:46 +00001167 }
1168 for (i = RMAP_IN; i < RMAP_MAX; i++)
1169 {
paul718e3742002-12-13 20:15:29 +00001170 if (filter->map[i].name)
1171 free (filter->map[i].name);
1172 }
1173
1174 if (filter->usmap.name)
1175 free (filter->usmap.name);
1176
1177 if (peer->default_rmap[afi][safi].name)
1178 free (peer->default_rmap[afi][safi].name);
1179 }
1180
1181 /* Update source configuration. */
1182 if (peer->update_source)
1183 {
1184 sockunion_free (peer->update_source);
1185 peer->update_source = NULL;
1186 }
1187 if (peer->update_if)
1188 {
1189 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1190 peer->update_if = NULL;
1191 }
1192
1193 /* Free peer structure. */
1194 XFREE (MTYPE_BGP_PEER, peer);
1195
1196 return 0;
1197}
1198
1199int
1200peer_group_cmp (struct peer_group *g1, struct peer_group *g2)
1201{
1202 return strcmp (g1->name, g2->name);
1203}
1204
1205/* If peer is configured at least one address family return 1. */
1206int
1207peer_group_active (struct peer *peer)
1208{
1209 if (peer->af_group[AFI_IP][SAFI_UNICAST]
1210 || peer->af_group[AFI_IP][SAFI_MULTICAST]
1211 || peer->af_group[AFI_IP][SAFI_MPLS_VPN]
1212 || peer->af_group[AFI_IP6][SAFI_UNICAST]
1213 || peer->af_group[AFI_IP6][SAFI_MULTICAST])
1214 return 1;
1215 return 0;
1216}
1217
1218/* Peer group cofiguration. */
1219static struct peer_group *
1220peer_group_new ()
1221{
1222 return (struct peer_group *) XCALLOC (MTYPE_PEER_GROUP,
1223 sizeof (struct peer_group));
1224}
1225
1226void
1227peer_group_free (struct peer_group *group)
1228{
1229 XFREE (MTYPE_PEER_GROUP, group);
1230}
1231
1232struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001233peer_group_lookup (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001234{
1235 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001236 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001237
paul1eb8ef22005-04-07 07:30:20 +00001238 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00001239 {
1240 if (strcmp (group->name, name) == 0)
1241 return group;
1242 }
1243 return NULL;
1244}
1245
1246struct peer_group *
paulfd79ac92004-10-13 05:06:08 +00001247peer_group_get (struct bgp *bgp, const char *name)
paul718e3742002-12-13 20:15:29 +00001248{
1249 struct peer_group *group;
1250
1251 group = peer_group_lookup (bgp, name);
1252 if (group)
1253 return group;
1254
1255 group = peer_group_new ();
1256 group->bgp = bgp;
1257 group->name = strdup (name);
1258 group->peer = list_new ();
1259 group->conf = peer_new ();
1260 if (! bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
1261 group->conf->afc[AFI_IP][SAFI_UNICAST] = 1;
1262 group->conf->host = strdup (name);
1263 group->conf->bgp = bgp;
1264 group->conf->group = group;
1265 group->conf->as = 0;
1266 group->conf->ttl = 1;
1267 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1268 UNSET_FLAG (group->conf->config, PEER_CONFIG_TIMER);
1269 UNSET_FLAG (group->conf->config, PEER_CONFIG_CONNECT);
1270 group->conf->keepalive = 0;
1271 group->conf->holdtime = 0;
1272 group->conf->connect = 0;
1273 SET_FLAG (group->conf->sflags, PEER_STATUS_GROUP);
1274 listnode_add_sort (bgp->group, group);
1275
1276 return 0;
1277}
1278
1279void
1280peer_group2peer_config_copy (struct peer_group *group, struct peer *peer,
1281 afi_t afi, safi_t safi)
1282{
1283 int in = FILTER_IN;
1284 int out = FILTER_OUT;
1285 struct peer *conf;
1286 struct bgp_filter *pfilter;
1287 struct bgp_filter *gfilter;
1288
1289 conf = group->conf;
1290 pfilter = &peer->filter[afi][safi];
1291 gfilter = &conf->filter[afi][safi];
1292
1293 /* remote-as */
1294 if (conf->as)
1295 peer->as = conf->as;
1296
1297 /* remote-as */
1298 if (conf->change_local_as)
1299 peer->change_local_as = conf->change_local_as;
1300
1301 /* TTL */
1302 peer->ttl = conf->ttl;
1303
1304 /* Weight */
1305 peer->weight = conf->weight;
1306
1307 /* peer flags apply */
1308 peer->flags = conf->flags;
1309 /* peer af_flags apply */
1310 peer->af_flags[afi][safi] = conf->af_flags[afi][safi];
1311 /* peer config apply */
1312 peer->config = conf->config;
1313
1314 /* peer timers apply */
1315 peer->holdtime = conf->holdtime;
1316 peer->keepalive = conf->keepalive;
1317 peer->connect = conf->connect;
1318 if (CHECK_FLAG (conf->config, PEER_CONFIG_CONNECT))
1319 peer->v_connect = conf->connect;
1320 else
1321 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
1322
1323 /* advertisement-interval reset */
1324 if (peer_sort (peer) == BGP_PEER_IBGP)
1325 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1326 else
1327 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1328
1329 /* maximum-prefix */
1330 peer->pmax[afi][safi] = conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00001331 peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00001332 peer->pmax_restart[afi][safi] = conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00001333
1334 /* allowas-in */
1335 peer->allowas_in[afi][safi] = conf->allowas_in[afi][safi];
1336
paulfee0f4c2004-09-13 05:12:46 +00001337 /* route-server-client */
1338 if (CHECK_FLAG(conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1339 {
1340 /* Make peer's RIB point to group's RIB. */
1341 peer->rib[afi][safi] = group->conf->rib[afi][safi];
1342
1343 /* Import policy. */
1344 if (pfilter->map[RMAP_IMPORT].name)
1345 free (pfilter->map[RMAP_IMPORT].name);
1346 if (gfilter->map[RMAP_IMPORT].name)
1347 {
1348 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1349 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1350 }
1351 else
1352 {
1353 pfilter->map[RMAP_IMPORT].name = NULL;
1354 pfilter->map[RMAP_IMPORT].map = NULL;
1355 }
1356
1357 /* Export policy. */
1358 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1359 {
1360 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1361 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
1362 }
1363 }
1364
paul718e3742002-12-13 20:15:29 +00001365 /* default-originate route-map */
1366 if (conf->default_rmap[afi][safi].name)
1367 {
1368 if (peer->default_rmap[afi][safi].name)
1369 free (peer->default_rmap[afi][safi].name);
1370 peer->default_rmap[afi][safi].name = strdup (conf->default_rmap[afi][safi].name);
1371 peer->default_rmap[afi][safi].map = conf->default_rmap[afi][safi].map;
1372 }
1373
1374 /* update-source apply */
1375 if (conf->update_source)
1376 {
1377 if (peer->update_source)
1378 sockunion_free (peer->update_source);
1379 if (peer->update_if)
1380 {
1381 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1382 peer->update_if = NULL;
1383 }
1384 peer->update_source = sockunion_dup (conf->update_source);
1385 }
1386 else if (conf->update_if)
1387 {
1388 if (peer->update_if)
1389 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
1390 if (peer->update_source)
1391 {
1392 sockunion_free (peer->update_source);
1393 peer->update_source = NULL;
1394 }
1395 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, conf->update_if);
1396 }
1397
1398 /* inbound filter apply */
1399 if (gfilter->dlist[in].name && ! pfilter->dlist[in].name)
1400 {
1401 if (pfilter->dlist[in].name)
1402 free (pfilter->dlist[in].name);
1403 pfilter->dlist[in].name = strdup (gfilter->dlist[in].name);
1404 pfilter->dlist[in].alist = gfilter->dlist[in].alist;
1405 }
1406 if (gfilter->plist[in].name && ! pfilter->plist[in].name)
1407 {
1408 if (pfilter->plist[in].name)
1409 free (pfilter->plist[in].name);
1410 pfilter->plist[in].name = strdup (gfilter->plist[in].name);
1411 pfilter->plist[in].plist = gfilter->plist[in].plist;
1412 }
1413 if (gfilter->aslist[in].name && ! pfilter->aslist[in].name)
1414 {
1415 if (pfilter->aslist[in].name)
1416 free (pfilter->aslist[in].name);
1417 pfilter->aslist[in].name = strdup (gfilter->aslist[in].name);
1418 pfilter->aslist[in].aslist = gfilter->aslist[in].aslist;
1419 }
paulfee0f4c2004-09-13 05:12:46 +00001420 if (gfilter->map[RMAP_IN].name && ! pfilter->map[RMAP_IN].name)
paul718e3742002-12-13 20:15:29 +00001421 {
paulfee0f4c2004-09-13 05:12:46 +00001422 if (pfilter->map[RMAP_IN].name)
1423 free (pfilter->map[RMAP_IN].name);
1424 pfilter->map[RMAP_IN].name = strdup (gfilter->map[RMAP_IN].name);
1425 pfilter->map[RMAP_IN].map = gfilter->map[RMAP_IN].map;
paul718e3742002-12-13 20:15:29 +00001426 }
1427
1428 /* outbound filter apply */
1429 if (gfilter->dlist[out].name)
1430 {
1431 if (pfilter->dlist[out].name)
1432 free (pfilter->dlist[out].name);
1433 pfilter->dlist[out].name = strdup (gfilter->dlist[out].name);
1434 pfilter->dlist[out].alist = gfilter->dlist[out].alist;
1435 }
1436 else
1437 {
1438 if (pfilter->dlist[out].name)
1439 free (pfilter->dlist[out].name);
1440 pfilter->dlist[out].name = NULL;
1441 pfilter->dlist[out].alist = NULL;
1442 }
1443 if (gfilter->plist[out].name)
1444 {
1445 if (pfilter->plist[out].name)
1446 free (pfilter->plist[out].name);
1447 pfilter->plist[out].name = strdup (gfilter->plist[out].name);
1448 pfilter->plist[out].plist = gfilter->plist[out].plist;
1449 }
1450 else
1451 {
1452 if (pfilter->plist[out].name)
1453 free (pfilter->plist[out].name);
1454 pfilter->plist[out].name = NULL;
1455 pfilter->plist[out].plist = NULL;
1456 }
1457 if (gfilter->aslist[out].name)
1458 {
1459 if (pfilter->aslist[out].name)
1460 free (pfilter->aslist[out].name);
1461 pfilter->aslist[out].name = strdup (gfilter->aslist[out].name);
1462 pfilter->aslist[out].aslist = gfilter->aslist[out].aslist;
1463 }
1464 else
1465 {
1466 if (pfilter->aslist[out].name)
1467 free (pfilter->aslist[out].name);
1468 pfilter->aslist[out].name = NULL;
1469 pfilter->aslist[out].aslist = NULL;
1470 }
paulfee0f4c2004-09-13 05:12:46 +00001471 if (gfilter->map[RMAP_OUT].name)
paul718e3742002-12-13 20:15:29 +00001472 {
paulfee0f4c2004-09-13 05:12:46 +00001473 if (pfilter->map[RMAP_OUT].name)
1474 free (pfilter->map[RMAP_OUT].name);
1475 pfilter->map[RMAP_OUT].name = strdup (gfilter->map[RMAP_OUT].name);
1476 pfilter->map[RMAP_OUT].map = gfilter->map[RMAP_OUT].map;
paul718e3742002-12-13 20:15:29 +00001477 }
1478 else
1479 {
paulfee0f4c2004-09-13 05:12:46 +00001480 if (pfilter->map[RMAP_OUT].name)
1481 free (pfilter->map[RMAP_OUT].name);
1482 pfilter->map[RMAP_OUT].name = NULL;
1483 pfilter->map[RMAP_OUT].map = NULL;
1484 }
1485
1486 /* RS-client's import/export route-maps. */
1487 if (gfilter->map[RMAP_IMPORT].name)
1488 {
1489 if (pfilter->map[RMAP_IMPORT].name)
1490 free (pfilter->map[RMAP_IMPORT].name);
1491 pfilter->map[RMAP_IMPORT].name = strdup (gfilter->map[RMAP_IMPORT].name);
1492 pfilter->map[RMAP_IMPORT].map = gfilter->map[RMAP_IMPORT].map;
1493 }
1494 else
1495 {
1496 if (pfilter->map[RMAP_IMPORT].name)
1497 free (pfilter->map[RMAP_IMPORT].name);
1498 pfilter->map[RMAP_IMPORT].name = NULL;
1499 pfilter->map[RMAP_IMPORT].map = NULL;
1500 }
1501 if (gfilter->map[RMAP_EXPORT].name && ! pfilter->map[RMAP_EXPORT].name)
1502 {
1503 if (pfilter->map[RMAP_EXPORT].name)
1504 free (pfilter->map[RMAP_EXPORT].name);
1505 pfilter->map[RMAP_EXPORT].name = strdup (gfilter->map[RMAP_EXPORT].name);
1506 pfilter->map[RMAP_EXPORT].map = gfilter->map[RMAP_EXPORT].map;
paul718e3742002-12-13 20:15:29 +00001507 }
1508
1509 if (gfilter->usmap.name)
1510 {
1511 if (pfilter->usmap.name)
1512 free (pfilter->usmap.name);
1513 pfilter->usmap.name = strdup (gfilter->usmap.name);
1514 pfilter->usmap.map = gfilter->usmap.map;
1515 }
1516 else
1517 {
1518 if (pfilter->usmap.name)
1519 free (pfilter->usmap.name);
1520 pfilter->usmap.name = NULL;
1521 pfilter->usmap.map = NULL;
1522 }
1523}
1524
1525/* Peer group's remote AS configuration. */
1526int
paulfd79ac92004-10-13 05:06:08 +00001527peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as)
paul718e3742002-12-13 20:15:29 +00001528{
1529 struct peer_group *group;
1530 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001531 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001532
1533 group = peer_group_lookup (bgp, group_name);
1534 if (! group)
1535 return -1;
1536
1537 if (group->conf->as == *as)
1538 return 0;
1539
1540 /* When we setup peer-group AS number all peer group member's AS
1541 number must be updated to same number. */
1542 peer_as_change (group->conf, *as);
1543
paul1eb8ef22005-04-07 07:30:20 +00001544 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001545 {
1546 if (peer->as != *as)
1547 peer_as_change (peer, *as);
1548 }
1549
1550 return 0;
1551}
1552
1553int
1554peer_group_delete (struct peer_group *group)
1555{
1556 struct bgp *bgp;
1557 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001558 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001559
1560 bgp = group->bgp;
1561
paul1eb8ef22005-04-07 07:30:20 +00001562 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001563 {
1564 peer->group = NULL;
1565 peer_delete (peer);
1566 }
1567 list_delete (group->peer);
1568
1569 free (group->name);
1570 group->name = NULL;
1571
1572 group->conf->group = NULL;
1573 peer_delete (group->conf);
1574
1575 /* Delete from all peer_group list. */
1576 listnode_delete (bgp->group, group);
1577
1578 peer_group_free (group);
1579
1580 return 0;
1581}
1582
1583int
1584peer_group_remote_as_delete (struct peer_group *group)
1585{
1586 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001587 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001588
1589 if (! group->conf->as)
1590 return 0;
1591
paul1eb8ef22005-04-07 07:30:20 +00001592 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001593 {
1594 peer->group = NULL;
1595 peer_delete (peer);
1596 }
1597 list_delete_all_node (group->peer);
1598
1599 group->conf->as = 0;
1600
1601 return 0;
1602}
1603
1604/* Bind specified peer to peer group. */
1605int
1606peer_group_bind (struct bgp *bgp, union sockunion *su,
1607 struct peer_group *group, afi_t afi, safi_t safi, as_t *as)
1608{
1609 struct peer *peer;
1610 int first_member = 0;
1611
1612 /* Check peer group's address family. */
1613 if (! group->conf->afc[afi][safi])
1614 return BGP_ERR_PEER_GROUP_AF_UNCONFIGURED;
1615
1616 /* Lookup the peer. */
1617 peer = peer_lookup (bgp, su);
1618
1619 /* Create a new peer. */
1620 if (! peer)
1621 {
1622 if (! group->conf->as)
1623 return BGP_ERR_PEER_GROUP_NO_REMOTE_AS;
1624
1625 peer = peer_create (su, bgp, bgp->as, group->conf->as, afi, safi);
1626 peer->group = group;
1627 peer->af_group[afi][safi] = 1;
1628 listnode_add (group->peer, peer);
1629 peer_group2peer_config_copy (group, peer, afi, safi);
1630
1631 return 0;
1632 }
1633
1634 /* When the peer already belongs to peer group, check the consistency. */
1635 if (peer->af_group[afi][safi])
1636 {
1637 if (strcmp (peer->group->name, group->name) != 0)
1638 return BGP_ERR_PEER_GROUP_CANT_CHANGE;
1639
1640 return 0;
1641 }
1642
1643 /* Check current peer group configuration. */
1644 if (peer_group_active (peer)
1645 && strcmp (peer->group->name, group->name) != 0)
1646 return BGP_ERR_PEER_GROUP_MISMATCH;
1647
1648 if (! group->conf->as)
1649 {
1650 if (peer_sort (group->conf) != BGP_PEER_INTERNAL
1651 && peer_sort (group->conf) != peer_sort (peer))
1652 {
1653 if (as)
1654 *as = peer->as;
1655 return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT;
1656 }
1657
1658 if (peer_sort (group->conf) == BGP_PEER_INTERNAL)
1659 first_member = 1;
1660 }
1661
1662 peer->af_group[afi][safi] = 1;
1663 peer->afc[afi][safi] = 1;
1664 if (! peer->group)
1665 {
1666 peer->group = group;
1667 listnode_add (group->peer, peer);
1668 }
1669
1670 if (first_member)
1671 {
1672 /* Advertisement-interval reset */
1673 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1674 group->conf->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
1675 else
1676 group->conf->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
1677
1678 /* ebgp-multihop reset */
1679 if (peer_sort (group->conf) == BGP_PEER_IBGP)
1680 group->conf->ttl = 255;
1681
1682 /* local-as reset */
1683 if (peer_sort (group->conf) != BGP_PEER_EBGP)
1684 {
1685 group->conf->change_local_as = 0;
1686 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
1687 }
1688 }
paulfee0f4c2004-09-13 05:12:46 +00001689
1690 if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
1691 {
1692 /* If it's not configured as RSERVER_CLIENT in any other address
1693 family, without being member of a peer_group, remove it from
1694 list bgp->rsclient.*/
1695 if (! peer_rsclient_active (peer))
1696 listnode_delete (bgp->rsclient, peer);
1697
1698 bgp_table_finish (peer->rib[afi][safi]);
1699
1700 /* Import policy. */
1701 if (peer->filter[afi][safi].map[RMAP_IMPORT].name)
1702 {
1703 free (peer->filter[afi][safi].map[RMAP_IMPORT].name);
1704 peer->filter[afi][safi].map[RMAP_IMPORT].name = NULL;
1705 peer->filter[afi][safi].map[RMAP_IMPORT].map = NULL;
1706 }
1707
1708 /* Export policy. */
1709 if (! CHECK_FLAG(group->conf->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
1710 && peer->filter[afi][safi].map[RMAP_EXPORT].name)
1711 {
1712 free (peer->filter[afi][safi].map[RMAP_EXPORT].name);
1713 peer->filter[afi][safi].map[RMAP_EXPORT].name = NULL;
1714 peer->filter[afi][safi].map[RMAP_EXPORT].map = NULL;
1715 }
1716 }
1717
paul718e3742002-12-13 20:15:29 +00001718 peer_group2peer_config_copy (group, peer, afi, safi);
1719
1720 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001721 {
1722 peer->last_reset = PEER_DOWN_RMAP_BIND;
1723 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1724 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1725 }
paul718e3742002-12-13 20:15:29 +00001726 else
1727 BGP_EVENT_ADD (peer, BGP_Stop);
1728
1729 return 0;
1730}
1731
1732int
1733peer_group_unbind (struct bgp *bgp, struct peer *peer,
1734 struct peer_group *group, afi_t afi, safi_t safi)
1735{
1736 if (! peer->af_group[afi][safi])
1737 return 0;
1738
1739 if (group != peer->group)
1740 return BGP_ERR_PEER_GROUP_MISMATCH;
1741
1742 peer->af_group[afi][safi] = 0;
1743 peer->afc[afi][safi] = 0;
1744 peer_af_flag_reset (peer, afi, safi);
1745
paulfee0f4c2004-09-13 05:12:46 +00001746 if (peer->rib[afi][safi])
1747 peer->rib[afi][safi] = NULL;
1748
paul718e3742002-12-13 20:15:29 +00001749 if (! peer_group_active (peer))
1750 {
1751 listnode_delete (group->peer, peer);
1752 peer->group = NULL;
1753 if (group->conf->as)
1754 {
1755 peer_delete (peer);
1756 return 0;
1757 }
1758 peer_global_config_reset (peer);
1759 }
1760
1761 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00001762 {
1763 peer->last_reset = PEER_DOWN_RMAP_UNBIND;
1764 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1765 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
1766 }
paul718e3742002-12-13 20:15:29 +00001767 else
1768 BGP_EVENT_ADD (peer, BGP_Stop);
1769
1770 return 0;
1771}
1772
1773/* BGP instance creation by `router bgp' commands. */
1774struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001775bgp_create (as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001776{
1777 struct bgp *bgp;
1778 afi_t afi;
1779 safi_t safi;
1780
1781 bgp = XCALLOC (MTYPE_BGP, sizeof (struct bgp));
1782
1783 bgp->peer_self = peer_new ();
paulfd79ac92004-10-13 05:06:08 +00001784 bgp->peer_self->host = strdup ("Static announcement");
paul718e3742002-12-13 20:15:29 +00001785
1786 bgp->peer = list_new ();
1787 bgp->peer->cmp = (int (*)(void *, void *)) peer_cmp;
1788
1789 bgp->group = list_new ();
1790 bgp->group->cmp = (int (*)(void *, void *)) peer_group_cmp;
1791
paulfee0f4c2004-09-13 05:12:46 +00001792 bgp->rsclient = list_new ();
1793 bgp->rsclient->cmp = (int (*)(void*, void*)) peer_cmp;
1794
paul718e3742002-12-13 20:15:29 +00001795 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1796 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1797 {
1798 bgp->route[afi][safi] = bgp_table_init ();
1799 bgp->aggregate[afi][safi] = bgp_table_init ();
1800 bgp->rib[afi][safi] = bgp_table_init ();
1801 }
1802
1803 bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
1804 bgp->default_holdtime = BGP_DEFAULT_HOLDTIME;
1805 bgp->default_keepalive = BGP_DEFAULT_KEEPALIVE;
hasso538621f2004-05-21 09:31:30 +00001806 bgp->restart_time = BGP_DEFAULT_RESTART_TIME;
1807 bgp->stalepath_time = BGP_DEFAULT_STALEPATH_TIME;
paul718e3742002-12-13 20:15:29 +00001808
1809 bgp->as = *as;
1810
1811 if (name)
1812 bgp->name = strdup (name);
1813
1814 return bgp;
1815}
1816
1817/* Return first entry of BGP. */
1818struct bgp *
1819bgp_get_default ()
1820{
1821 if (bm->bgp->head)
paul1eb8ef22005-04-07 07:30:20 +00001822 return (listgetdata (listhead (bm->bgp)));
paul718e3742002-12-13 20:15:29 +00001823 return NULL;
1824}
1825
1826/* Lookup BGP entry. */
1827struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001828bgp_lookup (as_t as, const char *name)
paul718e3742002-12-13 20:15:29 +00001829{
1830 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001831 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001832
paul1eb8ef22005-04-07 07:30:20 +00001833 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001834 if (bgp->as == as
1835 && ((bgp->name == NULL && name == NULL)
1836 || (bgp->name && name && strcmp (bgp->name, name) == 0)))
1837 return bgp;
1838 return NULL;
1839}
1840
1841/* Lookup BGP structure by view name. */
1842struct bgp *
paulfd79ac92004-10-13 05:06:08 +00001843bgp_lookup_by_name (const char *name)
paul718e3742002-12-13 20:15:29 +00001844{
1845 struct bgp *bgp;
paul1eb8ef22005-04-07 07:30:20 +00001846 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001847
paul1eb8ef22005-04-07 07:30:20 +00001848 for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp))
paul718e3742002-12-13 20:15:29 +00001849 if ((bgp->name == NULL && name == NULL)
1850 || (bgp->name && name && strcmp (bgp->name, name) == 0))
1851 return bgp;
1852 return NULL;
1853}
1854
1855/* Called from VTY commands. */
1856int
paulfd79ac92004-10-13 05:06:08 +00001857bgp_get (struct bgp **bgp_val, as_t *as, const char *name)
paul718e3742002-12-13 20:15:29 +00001858{
1859 struct bgp *bgp;
1860
1861 /* Multiple instance check. */
1862 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
1863 {
1864 if (name)
1865 bgp = bgp_lookup_by_name (name);
1866 else
1867 bgp = bgp_get_default ();
1868
1869 /* Already exists. */
1870 if (bgp)
1871 {
1872 if (bgp->as != *as)
1873 {
1874 *as = bgp->as;
1875 return BGP_ERR_INSTANCE_MISMATCH;
1876 }
1877 *bgp_val = bgp;
1878 return 0;
1879 }
1880 }
1881 else
1882 {
1883 /* BGP instance name can not be specified for single instance. */
1884 if (name)
1885 return BGP_ERR_MULTIPLE_INSTANCE_NOT_SET;
1886
1887 /* Get default BGP structure if exists. */
1888 bgp = bgp_get_default ();
1889
1890 if (bgp)
1891 {
1892 if (bgp->as != *as)
1893 {
1894 *as = bgp->as;
1895 return BGP_ERR_AS_MISMATCH;
1896 }
1897 *bgp_val = bgp;
1898 return 0;
1899 }
1900 }
1901
1902 bgp = bgp_create (as, name);
1903 listnode_add (bm->bgp, bgp);
hasso18a6dce2004-10-03 18:18:34 +00001904 bgp_router_id_set(bgp, &router_id_zebra);
paul718e3742002-12-13 20:15:29 +00001905 *bgp_val = bgp;
1906
1907 return 0;
1908}
1909
1910/* Delete BGP instance. */
1911int
1912bgp_delete (struct bgp *bgp)
1913{
1914 struct peer *peer;
hassob6b7cff2005-05-26 08:29:07 +00001915 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00001916 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001917 struct listnode *next;
1918 afi_t afi;
1919 safi_t safi;
1920 int i;
1921
1922 /* Delete static route. */
1923 bgp_static_delete (bgp);
1924
1925 /* Unset redistribution. */
1926 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1927 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
1928 if (i != ZEBRA_ROUTE_BGP)
1929 bgp_redistribute_unset (bgp, afi, i);
1930
hassob6b7cff2005-05-26 08:29:07 +00001931 for (ALL_LIST_ELEMENTS (bgp->group, node, next, group))
1932 peer_group_delete (group);
paul718e3742002-12-13 20:15:29 +00001933
paul1eb8ef22005-04-07 07:30:20 +00001934 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
1935 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00001936
paulfee0f4c2004-09-13 05:12:46 +00001937 bgp->rsclient->del = (void (*)(void *)) peer_delete;
1938 list_delete (bgp->rsclient);
1939
paul718e3742002-12-13 20:15:29 +00001940 listnode_delete (bm->bgp, bgp);
1941
1942 if (bgp->name)
1943 free (bgp->name);
1944
1945 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1946 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1947 {
1948 if (bgp->route[afi][safi])
1949 XFREE (MTYPE_ROUTE_TABLE, bgp->route[afi][safi]);
1950 if (bgp->aggregate[afi][safi])
1951 XFREE (MTYPE_ROUTE_TABLE,bgp->aggregate[afi][safi]) ;
1952 if (bgp->rib[afi][safi])
1953 XFREE (MTYPE_ROUTE_TABLE,bgp->rib[afi][safi]);
1954 }
1955 XFREE (MTYPE_BGP, bgp);
1956
1957 return 0;
1958}
1959
1960struct peer *
1961peer_lookup (struct bgp *bgp, union sockunion *su)
1962{
1963 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001964 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001965
1966 if (! bgp)
1967 bgp = bgp_get_default ();
1968
1969 if (! bgp)
1970 return NULL;
1971
paul1eb8ef22005-04-07 07:30:20 +00001972 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001973 {
pauleb821182004-05-01 08:44:08 +00001974 if (sockunion_same (&peer->su, su)
1975 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1976 return peer;
paul718e3742002-12-13 20:15:29 +00001977 }
1978 return NULL;
1979}
1980
1981struct peer *
1982peer_lookup_with_open (union sockunion *su, as_t remote_as,
1983 struct in_addr *remote_id, int *as)
1984{
1985 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001986 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001987 struct bgp *bgp;
1988
1989 bgp = bgp_get_default ();
1990 if (! bgp)
1991 return NULL;
1992
paul1eb8ef22005-04-07 07:30:20 +00001993 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001994 {
pauleb821182004-05-01 08:44:08 +00001995 if (sockunion_same (&peer->su, su)
1996 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1997 {
1998 if (peer->as == remote_as
1999 && peer->remote_id.s_addr == remote_id->s_addr)
2000 return peer;
2001 if (peer->as == remote_as)
2002 *as = 1;
2003 }
paul718e3742002-12-13 20:15:29 +00002004 }
paul1eb8ef22005-04-07 07:30:20 +00002005 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002006 {
pauleb821182004-05-01 08:44:08 +00002007 if (sockunion_same (&peer->su, su)
2008 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2009 {
2010 if (peer->as == remote_as
2011 && peer->remote_id.s_addr == 0)
2012 return peer;
2013 if (peer->as == remote_as)
2014 *as = 1;
2015 }
paul718e3742002-12-13 20:15:29 +00002016 }
2017 return NULL;
2018}
2019
2020/* If peer is configured at least one address family return 1. */
2021int
2022peer_active (struct peer *peer)
2023{
2024 if (peer->afc[AFI_IP][SAFI_UNICAST]
2025 || peer->afc[AFI_IP][SAFI_MULTICAST]
2026 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2027 || peer->afc[AFI_IP6][SAFI_UNICAST]
2028 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2029 return 1;
2030 return 0;
2031}
2032
2033/* If peer is negotiated at least one address family return 1. */
2034int
2035peer_active_nego (struct peer *peer)
2036{
2037 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2038 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2039 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2040 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2041 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2042 return 1;
2043 return 0;
2044}
2045
2046/* peer_flag_change_type. */
2047enum peer_change_type
2048{
2049 peer_change_none,
2050 peer_change_reset,
2051 peer_change_reset_in,
2052 peer_change_reset_out,
2053};
2054
2055void
2056peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2057 enum peer_change_type type)
2058{
2059 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2060 return;
2061
2062 if (type == peer_change_reset)
2063 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2064 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2065 else if (type == peer_change_reset_in)
2066 {
2067 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2068 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2069 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2070 else
2071 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2072 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2073 }
2074 else if (type == peer_change_reset_out)
2075 bgp_announce_route (peer, afi, safi);
2076}
2077
2078struct peer_flag_action
2079{
2080 /* Peer's flag. */
2081 u_int32_t flag;
2082
2083 /* This flag can be set for peer-group member. */
2084 u_char not_for_member;
2085
2086 /* Action when the flag is changed. */
2087 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002088
2089 /* Peer down cause */
2090 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002091};
2092
2093struct peer_flag_action peer_flag_action_list[] =
2094 {
2095 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2096 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2097 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2098 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2099 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002100 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002101 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002102 { 0, 0, 0 }
2103 };
2104
2105struct peer_flag_action peer_af_flag_action_list[] =
2106 {
2107 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2108 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2109 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2110 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2111 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2112 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2113 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2114 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2115 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2116 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2117 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2118 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2119 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002120 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002121 { 0, 0, 0 }
2122 };
2123
2124/* Proper action set. */
2125int
2126peer_flag_action_set (struct peer_flag_action *action_list, int size,
2127 struct peer_flag_action *action, u_int32_t flag)
2128{
2129 int i;
2130 int found = 0;
2131 int reset_in = 0;
2132 int reset_out = 0;
2133 struct peer_flag_action *match = NULL;
2134
2135 /* Check peer's frag action. */
2136 for (i = 0; i < size; i++)
2137 {
2138 match = &action_list[i];
2139
2140 if (match->flag == 0)
2141 break;
2142
2143 if (match->flag & flag)
2144 {
2145 found = 1;
2146
2147 if (match->type == peer_change_reset_in)
2148 reset_in = 1;
2149 if (match->type == peer_change_reset_out)
2150 reset_out = 1;
2151 if (match->type == peer_change_reset)
2152 {
2153 reset_in = 1;
2154 reset_out = 1;
2155 }
2156 if (match->not_for_member)
2157 action->not_for_member = 1;
2158 }
2159 }
2160
2161 /* Set peer clear type. */
2162 if (reset_in && reset_out)
2163 action->type = peer_change_reset;
2164 else if (reset_in)
2165 action->type = peer_change_reset_in;
2166 else if (reset_out)
2167 action->type = peer_change_reset_out;
2168 else
2169 action->type = peer_change_none;
2170
2171 return found;
2172}
2173
2174void
2175peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2176{
2177 if (flag == PEER_FLAG_SHUTDOWN)
2178 {
2179 if (CHECK_FLAG (peer->flags, flag))
2180 {
hasso93406d82005-02-02 14:40:33 +00002181 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2182 peer_nsf_stop (peer);
2183
hasso0a486e52005-02-01 20:57:17 +00002184 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2185 if (peer->t_pmax_restart)
2186 {
2187 BGP_TIMER_OFF (peer->t_pmax_restart);
2188 if (BGP_DEBUG (events, EVENTS))
2189 zlog_debug ("%s Maximum-prefix restart timer canceled",
2190 peer->host);
2191 }
2192
hasso93406d82005-02-02 14:40:33 +00002193 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2194 peer_nsf_stop (peer);
2195
paul718e3742002-12-13 20:15:29 +00002196 if (peer->status == Established)
2197 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2198 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2199 else
2200 BGP_EVENT_ADD (peer, BGP_Stop);
2201 }
2202 else
2203 {
2204 peer->v_start = BGP_INIT_START_TIMER;
2205 BGP_EVENT_ADD (peer, BGP_Stop);
2206 }
2207 }
2208 else if (peer->status == Established)
2209 {
hassoc9502432005-02-01 22:01:48 +00002210 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2211 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2212 else if (flag == PEER_FLAG_PASSIVE)
2213 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002214 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002215 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002216
hassoc9502432005-02-01 22:01:48 +00002217 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2218 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002219 }
2220 else
2221 BGP_EVENT_ADD (peer, BGP_Stop);
2222}
2223
2224/* Change specified peer flag. */
2225int
2226peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2227{
2228 int found;
2229 int size;
2230 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002231 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002232 struct peer_flag_action action;
2233
2234 memset (&action, 0, sizeof (struct peer_flag_action));
2235 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2236
2237 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2238
2239 /* No flag action is found. */
2240 if (! found)
2241 return BGP_ERR_INVALID_FLAG;
2242
2243 /* Not for peer-group member. */
2244 if (action.not_for_member && peer_group_active (peer))
2245 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2246
2247 /* When unset the peer-group member's flag we have to check
2248 peer-group configuration. */
2249 if (! set && peer_group_active (peer))
2250 if (CHECK_FLAG (peer->group->conf->flags, flag))
2251 {
2252 if (flag == PEER_FLAG_SHUTDOWN)
2253 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2254 else
2255 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2256 }
2257
2258 /* Flag conflict check. */
2259 if (set
2260 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2261 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2262 return BGP_ERR_PEER_FLAG_CONFLICT;
2263
2264 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2265 {
2266 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2267 return 0;
2268 if (! set && ! CHECK_FLAG (peer->flags, flag))
2269 return 0;
2270 }
2271
2272 if (set)
2273 SET_FLAG (peer->flags, flag);
2274 else
2275 UNSET_FLAG (peer->flags, flag);
2276
2277 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2278 {
2279 if (action.type == peer_change_reset)
2280 peer_flag_modify_action (peer, flag);
2281
2282 return 0;
2283 }
2284
2285 /* peer-group member updates. */
2286 group = peer->group;
2287
paul1eb8ef22005-04-07 07:30:20 +00002288 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002289 {
2290 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2291 continue;
2292
2293 if (! set && ! CHECK_FLAG (peer->flags, flag))
2294 continue;
2295
2296 if (set)
2297 SET_FLAG (peer->flags, flag);
2298 else
2299 UNSET_FLAG (peer->flags, flag);
2300
2301 if (action.type == peer_change_reset)
2302 peer_flag_modify_action (peer, flag);
2303 }
2304 return 0;
2305}
2306
2307int
2308peer_flag_set (struct peer *peer, u_int32_t flag)
2309{
2310 return peer_flag_modify (peer, flag, 1);
2311}
2312
2313int
2314peer_flag_unset (struct peer *peer, u_int32_t flag)
2315{
2316 return peer_flag_modify (peer, flag, 0);
2317}
2318
2319int
2320peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2321{
2322 if (peer->af_group[afi][safi])
2323 return 1;
2324 return 0;
2325}
2326
2327int
2328peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2329 int set)
2330{
2331 int found;
2332 int size;
paul1eb8ef22005-04-07 07:30:20 +00002333 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002334 struct peer_group *group;
2335 struct peer_flag_action action;
2336
2337 memset (&action, 0, sizeof (struct peer_flag_action));
2338 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2339
2340 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2341
2342 /* No flag action is found. */
2343 if (! found)
2344 return BGP_ERR_INVALID_FLAG;
2345
2346 /* Adress family must be activated. */
2347 if (! peer->afc[afi][safi])
2348 return BGP_ERR_PEER_INACTIVE;
2349
2350 /* Not for peer-group member. */
2351 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2352 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2353
2354 /* Spcecial check for reflector client. */
2355 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2356 && peer_sort (peer) != BGP_PEER_IBGP)
2357 return BGP_ERR_NOT_INTERNAL_PEER;
2358
2359 /* Spcecial check for remove-private-AS. */
2360 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2361 && peer_sort (peer) == BGP_PEER_IBGP)
2362 return BGP_ERR_REMOVE_PRIVATE_AS;
2363
2364 /* When unset the peer-group member's flag we have to check
2365 peer-group configuration. */
2366 if (! set && peer->af_group[afi][safi])
2367 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2368 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2369
2370 /* When current flag configuration is same as requested one. */
2371 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2372 {
2373 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2374 return 0;
2375 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2376 return 0;
2377 }
2378
2379 if (set)
2380 SET_FLAG (peer->af_flags[afi][safi], flag);
2381 else
2382 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2383
2384 /* Execute action when peer is established. */
2385 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2386 && peer->status == Established)
2387 {
2388 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2389 bgp_clear_adj_in (peer, afi, safi);
2390 else
hassoe0701b72004-05-20 09:19:34 +00002391 {
2392 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2393 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2394 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2395 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2396 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2397 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2398 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2399 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2400
2401 peer_change_action (peer, afi, safi, action.type);
2402 }
2403
paul718e3742002-12-13 20:15:29 +00002404 }
2405
2406 /* Peer group member updates. */
2407 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2408 {
2409 group = peer->group;
2410
paul1eb8ef22005-04-07 07:30:20 +00002411 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002412 {
2413 if (! peer->af_group[afi][safi])
2414 continue;
2415
2416 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2417 continue;
2418
2419 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2420 continue;
2421
2422 if (set)
2423 SET_FLAG (peer->af_flags[afi][safi], flag);
2424 else
2425 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2426
2427 if (peer->status == Established)
2428 {
2429 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2430 bgp_clear_adj_in (peer, afi, safi);
2431 else
hassoe0701b72004-05-20 09:19:34 +00002432 {
2433 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2434 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2435 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2436 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2437 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2438 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2439 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2440 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2441
2442 peer_change_action (peer, afi, safi, action.type);
2443 }
paul718e3742002-12-13 20:15:29 +00002444 }
2445 }
2446 }
2447 return 0;
2448}
2449
2450int
2451peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2452{
2453 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2454}
2455
2456int
2457peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2458{
2459 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2460}
2461
2462/* EBGP multihop configuration. */
2463int
2464peer_ebgp_multihop_set (struct peer *peer, int ttl)
2465{
2466 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002467 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002468
2469 if (peer_sort (peer) == BGP_PEER_IBGP)
2470 return 0;
2471
2472 peer->ttl = ttl;
2473
2474 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2475 {
pauleb821182004-05-01 08:44:08 +00002476 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2477 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002478 }
2479 else
2480 {
2481 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002482 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002483 {
2484 if (peer_sort (peer) == BGP_PEER_IBGP)
2485 continue;
paul718e3742002-12-13 20:15:29 +00002486
pauleb821182004-05-01 08:44:08 +00002487 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002488
pauleb821182004-05-01 08:44:08 +00002489 if (peer->fd >= 0)
2490 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2491 }
paul718e3742002-12-13 20:15:29 +00002492 }
2493 return 0;
2494}
2495
2496int
2497peer_ebgp_multihop_unset (struct peer *peer)
2498{
2499 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002500 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002501
2502 if (peer_sort (peer) == BGP_PEER_IBGP)
2503 return 0;
2504
2505 if (peer_group_active (peer))
2506 peer->ttl = peer->group->conf->ttl;
2507 else
2508 peer->ttl = 1;
2509
2510 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2511 {
pauleb821182004-05-01 08:44:08 +00002512 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2513 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002514 }
2515 else
2516 {
2517 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002518 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002519 {
2520 if (peer_sort (peer) == BGP_PEER_IBGP)
2521 continue;
paul718e3742002-12-13 20:15:29 +00002522
pauleb821182004-05-01 08:44:08 +00002523 peer->ttl = 1;
2524
2525 if (peer->fd >= 0)
2526 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2527 }
paul718e3742002-12-13 20:15:29 +00002528 }
2529 return 0;
2530}
2531
2532/* Neighbor description. */
2533int
2534peer_description_set (struct peer *peer, char *desc)
2535{
2536 if (peer->desc)
2537 XFREE (MTYPE_PEER_DESC, peer->desc);
2538
2539 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2540
2541 return 0;
2542}
2543
2544int
2545peer_description_unset (struct peer *peer)
2546{
2547 if (peer->desc)
2548 XFREE (MTYPE_PEER_DESC, peer->desc);
2549
2550 peer->desc = NULL;
2551
2552 return 0;
2553}
2554
2555/* Neighbor update-source. */
2556int
paulfd79ac92004-10-13 05:06:08 +00002557peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002558{
2559 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002560 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002561
2562 if (peer->update_if)
2563 {
2564 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2565 && strcmp (peer->update_if, ifname) == 0)
2566 return 0;
2567
2568 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2569 peer->update_if = NULL;
2570 }
2571
2572 if (peer->update_source)
2573 {
2574 sockunion_free (peer->update_source);
2575 peer->update_source = NULL;
2576 }
2577
2578 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2579
2580 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2581 {
2582 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002583 {
2584 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2585 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2586 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2587 }
paul718e3742002-12-13 20:15:29 +00002588 else
2589 BGP_EVENT_ADD (peer, BGP_Stop);
2590 return 0;
2591 }
2592
2593 /* peer-group member updates. */
2594 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002595 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002596 {
2597 if (peer->update_if)
2598 {
2599 if (strcmp (peer->update_if, ifname) == 0)
2600 continue;
2601
2602 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2603 peer->update_if = NULL;
2604 }
2605
2606 if (peer->update_source)
2607 {
2608 sockunion_free (peer->update_source);
2609 peer->update_source = NULL;
2610 }
2611
2612 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2613
2614 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002615 {
2616 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2617 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2618 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2619 }
paul718e3742002-12-13 20:15:29 +00002620 else
2621 BGP_EVENT_ADD (peer, BGP_Stop);
2622 }
2623 return 0;
2624}
2625
2626int
2627peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2628{
2629 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002630 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002631
2632 if (peer->update_source)
2633 {
2634 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2635 && sockunion_cmp (peer->update_source, su) == 0)
2636 return 0;
2637 sockunion_free (peer->update_source);
2638 peer->update_source = NULL;
2639 }
2640
2641 if (peer->update_if)
2642 {
2643 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2644 peer->update_if = NULL;
2645 }
2646
2647 peer->update_source = sockunion_dup (su);
2648
2649 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2650 {
2651 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002652 {
2653 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2654 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2655 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2656 }
paul718e3742002-12-13 20:15:29 +00002657 else
2658 BGP_EVENT_ADD (peer, BGP_Stop);
2659 return 0;
2660 }
2661
2662 /* peer-group member updates. */
2663 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002664 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002665 {
2666 if (peer->update_source)
2667 {
2668 if (sockunion_cmp (peer->update_source, su) == 0)
2669 continue;
2670 sockunion_free (peer->update_source);
2671 peer->update_source = NULL;
2672 }
2673
2674 if (peer->update_if)
2675 {
2676 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2677 peer->update_if = NULL;
2678 }
2679
2680 peer->update_source = sockunion_dup (su);
2681
2682 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002683 {
2684 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2685 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2686 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2687 }
paul718e3742002-12-13 20:15:29 +00002688 else
2689 BGP_EVENT_ADD (peer, BGP_Stop);
2690 }
2691 return 0;
2692}
2693
2694int
2695peer_update_source_unset (struct peer *peer)
2696{
2697 union sockunion *su;
2698 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002699 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002700
2701 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2702 && ! peer->update_source
2703 && ! peer->update_if)
2704 return 0;
2705
2706 if (peer->update_source)
2707 {
2708 sockunion_free (peer->update_source);
2709 peer->update_source = NULL;
2710 }
2711 if (peer->update_if)
2712 {
2713 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2714 peer->update_if = NULL;
2715 }
2716
2717 if (peer_group_active (peer))
2718 {
2719 group = peer->group;
2720
2721 if (group->conf->update_source)
2722 {
2723 su = sockunion_dup (group->conf->update_source);
2724 peer->update_source = su;
2725 }
2726 else if (group->conf->update_if)
2727 peer->update_if =
2728 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2729 }
2730
2731 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2732 {
2733 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002734 {
2735 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2736 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2737 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2738 }
paul718e3742002-12-13 20:15:29 +00002739 else
2740 BGP_EVENT_ADD (peer, BGP_Stop);
2741 return 0;
2742 }
2743
2744 /* peer-group member updates. */
2745 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002746 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002747 {
2748 if (! peer->update_source && ! peer->update_if)
2749 continue;
2750
2751 if (peer->update_source)
2752 {
2753 sockunion_free (peer->update_source);
2754 peer->update_source = NULL;
2755 }
2756
2757 if (peer->update_if)
2758 {
2759 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2760 peer->update_if = NULL;
2761 }
2762
2763 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002764 {
2765 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2766 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2767 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2768 }
paul718e3742002-12-13 20:15:29 +00002769 else
2770 BGP_EVENT_ADD (peer, BGP_Stop);
2771 }
2772 return 0;
2773}
2774
2775int
2776peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00002777 const char *rmap)
paul718e3742002-12-13 20:15:29 +00002778{
2779 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002780 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002781
2782 /* Adress family must be activated. */
2783 if (! peer->afc[afi][safi])
2784 return BGP_ERR_PEER_INACTIVE;
2785
2786 /* Default originate can't be used for peer group memeber. */
2787 if (peer_is_group_member (peer, afi, safi))
2788 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2789
2790 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
2791 || (rmap && ! peer->default_rmap[afi][safi].name)
2792 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
2793 {
2794 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2795
2796 if (rmap)
2797 {
2798 if (peer->default_rmap[afi][safi].name)
2799 free (peer->default_rmap[afi][safi].name);
2800 peer->default_rmap[afi][safi].name = strdup (rmap);
2801 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2802 }
2803 }
2804
2805 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2806 {
2807 if (peer->status == Established && peer->afc_nego[afi][safi])
2808 bgp_default_originate (peer, afi, safi, 0);
2809 return 0;
2810 }
2811
2812 /* peer-group member updates. */
2813 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002814 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002815 {
2816 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2817
2818 if (rmap)
2819 {
2820 if (peer->default_rmap[afi][safi].name)
2821 free (peer->default_rmap[afi][safi].name);
2822 peer->default_rmap[afi][safi].name = strdup (rmap);
2823 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2824 }
2825
2826 if (peer->status == Established && peer->afc_nego[afi][safi])
2827 bgp_default_originate (peer, afi, safi, 0);
2828 }
2829 return 0;
2830}
2831
2832int
2833peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
2834{
2835 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002836 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002837
2838 /* Adress family must be activated. */
2839 if (! peer->afc[afi][safi])
2840 return BGP_ERR_PEER_INACTIVE;
2841
2842 /* Default originate can't be used for peer group memeber. */
2843 if (peer_is_group_member (peer, afi, safi))
2844 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2845
2846 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
2847 {
2848 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2849
2850 if (peer->default_rmap[afi][safi].name)
2851 free (peer->default_rmap[afi][safi].name);
2852 peer->default_rmap[afi][safi].name = NULL;
2853 peer->default_rmap[afi][safi].map = NULL;
2854 }
2855
2856 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2857 {
2858 if (peer->status == Established && peer->afc_nego[afi][safi])
2859 bgp_default_originate (peer, afi, safi, 1);
2860 return 0;
2861 }
2862
2863 /* peer-group member updates. */
2864 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002865 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002866 {
2867 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2868
2869 if (peer->default_rmap[afi][safi].name)
2870 free (peer->default_rmap[afi][safi].name);
2871 peer->default_rmap[afi][safi].name = NULL;
2872 peer->default_rmap[afi][safi].map = NULL;
2873
2874 if (peer->status == Established && peer->afc_nego[afi][safi])
2875 bgp_default_originate (peer, afi, safi, 1);
2876 }
2877 return 0;
2878}
2879
2880int
2881peer_port_set (struct peer *peer, u_int16_t port)
2882{
2883 peer->port = port;
2884 return 0;
2885}
2886
2887int
2888peer_port_unset (struct peer *peer)
2889{
2890 peer->port = BGP_PORT_DEFAULT;
2891 return 0;
2892}
2893
2894/* neighbor weight. */
2895int
2896peer_weight_set (struct peer *peer, u_int16_t weight)
2897{
2898 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002899 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002900
2901 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
2902 peer->weight = weight;
2903
2904 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2905 return 0;
2906
2907 /* peer-group member updates. */
2908 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002909 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002910 {
2911 peer->weight = group->conf->weight;
2912 }
2913 return 0;
2914}
2915
2916int
2917peer_weight_unset (struct peer *peer)
2918{
2919 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002920 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002921
2922 /* Set default weight. */
2923 if (peer_group_active (peer))
2924 peer->weight = peer->group->conf->weight;
2925 else
2926 peer->weight = 0;
2927
2928 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
2929
2930 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2931 return 0;
2932
2933 /* peer-group member updates. */
2934 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002935 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002936 {
2937 peer->weight = 0;
2938 }
2939 return 0;
2940}
2941
2942int
2943peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
2944{
2945 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002946 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002947
2948 /* Not for peer group memeber. */
2949 if (peer_group_active (peer))
2950 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2951
2952 /* keepalive value check. */
2953 if (keepalive > 65535)
2954 return BGP_ERR_INVALID_VALUE;
2955
2956 /* Holdtime value check. */
2957 if (holdtime > 65535)
2958 return BGP_ERR_INVALID_VALUE;
2959
2960 /* Holdtime value must be either 0 or greater than 3. */
2961 if (holdtime < 3 && holdtime != 0)
2962 return BGP_ERR_INVALID_VALUE;
2963
2964 /* Set value to the configuration. */
2965 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
2966 peer->holdtime = holdtime;
2967 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
2968
2969 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2970 return 0;
2971
2972 /* peer-group member updates. */
2973 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002974 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002975 {
2976 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
2977 peer->holdtime = group->conf->holdtime;
2978 peer->keepalive = group->conf->keepalive;
2979 }
2980 return 0;
2981}
2982
2983int
2984peer_timers_unset (struct peer *peer)
2985{
2986 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002987 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002988
2989 if (peer_group_active (peer))
2990 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2991
2992 /* Clear configuration. */
2993 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
2994 peer->keepalive = 0;
2995 peer->holdtime = 0;
2996
2997 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2998 return 0;
2999
3000 /* peer-group member updates. */
3001 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003002 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003003 {
3004 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3005 peer->holdtime = 0;
3006 peer->keepalive = 0;
3007 }
3008
3009 return 0;
3010}
3011
3012int
3013peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3014{
3015 if (peer_group_active (peer))
3016 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3017
3018 if (connect > 65535)
3019 return BGP_ERR_INVALID_VALUE;
3020
3021 /* Set value to the configuration. */
3022 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3023 peer->connect = connect;
3024
3025 /* Set value to timer setting. */
3026 peer->v_connect = connect;
3027
3028 return 0;
3029}
3030
3031int
3032peer_timers_connect_unset (struct peer *peer)
3033{
3034 if (peer_group_active (peer))
3035 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3036
3037 /* Clear configuration. */
3038 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3039 peer->connect = 0;
3040
3041 /* Set timer setting to default value. */
3042 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3043
3044 return 0;
3045}
3046
3047int
3048peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3049{
3050 if (peer_group_active (peer))
3051 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3052
3053 if (routeadv > 600)
3054 return BGP_ERR_INVALID_VALUE;
3055
3056 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3057 peer->routeadv = routeadv;
3058 peer->v_routeadv = routeadv;
3059
3060 return 0;
3061}
3062
3063int
3064peer_advertise_interval_unset (struct peer *peer)
3065{
3066 if (peer_group_active (peer))
3067 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3068
3069 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3070 peer->routeadv = 0;
3071
3072 if (peer_sort (peer) == BGP_PEER_IBGP)
3073 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3074 else
3075 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3076
3077 return 0;
3078}
3079
paul718e3742002-12-13 20:15:29 +00003080/* neighbor interface */
3081int
paulfd79ac92004-10-13 05:06:08 +00003082peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003083{
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
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;
paul1eb8ef22005-04-07 07:30:20 +00003106 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003107
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;
paul1eb8ef22005-04-07 07:30:20 +00003122 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003123 {
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;
paul1eb8ef22005-04-07 07:30:20 +00003139 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003140
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;
paul1eb8ef22005-04-07 07:30:20 +00003151 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003152 {
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
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;
paul1eb8ef22005-04-07 07:30:20 +00003167 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003168
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)
hassoe0701b72004-05-20 09:19:34 +00003193 {
3194 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3195 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3196 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3197 }
paul718e3742002-12-13 20:15:29 +00003198 else
3199 BGP_EVENT_ADD (peer, BGP_Stop);
3200
3201 return 0;
3202 }
3203
3204 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003205 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003206 {
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)
hassoe0701b72004-05-20 09:19:34 +00003214 {
3215 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3216 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3217 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3218 }
paul718e3742002-12-13 20:15:29 +00003219 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;
paul1eb8ef22005-04-07 07:30:20 +00003230 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003231
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)
hassoe0701b72004-05-20 09:19:34 +00003244 {
3245 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3246 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3247 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3248 }
paul718e3742002-12-13 20:15:29 +00003249 else
3250 BGP_EVENT_ADD (peer, BGP_Stop);
3251
3252 return 0;
3253 }
3254
3255 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003256 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003257 {
3258 peer->change_local_as = 0;
3259 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3260
3261 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003262 {
3263 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3264 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3265 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3266 }
paul718e3742002-12-13 20:15:29 +00003267 else
3268 BGP_EVENT_ADD (peer, BGP_Stop);
3269 }
3270 return 0;
3271}
3272
3273/* Set distribute list to the peer. */
3274int
3275peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003276 const char *name)
paul718e3742002-12-13 20:15:29 +00003277{
3278 struct bgp_filter *filter;
3279 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003280 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003281
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;
paul1eb8ef22005-04-07 07:30:20 +00003305 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003306 {
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;
paul1eb8ef22005-04-07 07:30:20 +00003327 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003328
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;
paul1eb8ef22005-04-07 07:30:20 +00003364 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003365 {
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;
paul1eb8ef22005-04-07 07:30:20 +00003387 struct listnode *mnode, *mnnode;
3388 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003389 struct bgp *bgp;
3390 struct peer *peer;
3391 struct peer_group *group;
3392 struct bgp_filter *filter;
3393
paul1eb8ef22005-04-07 07:30:20 +00003394 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003395 {
paul1eb8ef22005-04-07 07:30:20 +00003396 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003397 {
3398 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3399 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3400 {
3401 filter = &peer->filter[afi][safi];
3402
3403 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3404 {
3405 if (filter->dlist[direct].name)
3406 filter->dlist[direct].alist =
3407 access_list_lookup (afi, filter->dlist[direct].name);
3408 else
3409 filter->dlist[direct].alist = NULL;
3410 }
3411 }
3412 }
paul1eb8ef22005-04-07 07:30:20 +00003413 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003414 {
3415 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3416 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3417 {
3418 filter = &group->conf->filter[afi][safi];
3419
3420 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3421 {
3422 if (filter->dlist[direct].name)
3423 filter->dlist[direct].alist =
3424 access_list_lookup (afi, filter->dlist[direct].name);
3425 else
3426 filter->dlist[direct].alist = NULL;
3427 }
3428 }
3429 }
3430 }
3431}
3432
3433/* Set prefix list to the peer. */
3434int
3435peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003436 const char *name)
paul718e3742002-12-13 20:15:29 +00003437{
3438 struct bgp_filter *filter;
3439 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003440 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003441
3442 if (! peer->afc[afi][safi])
3443 return BGP_ERR_PEER_INACTIVE;
3444
3445 if (direct != FILTER_IN && direct != FILTER_OUT)
3446 return BGP_ERR_INVALID_VALUE;
3447
3448 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3449 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3450
3451 filter = &peer->filter[afi][safi];
3452
3453 if (filter->dlist[direct].name)
3454 return BGP_ERR_PEER_FILTER_CONFLICT;
3455
3456 if (filter->plist[direct].name)
3457 free (filter->plist[direct].name);
3458 filter->plist[direct].name = strdup (name);
3459 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3460
3461 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3462 return 0;
3463
3464 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003465 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003466 {
3467 filter = &peer->filter[afi][safi];
3468
3469 if (! peer->af_group[afi][safi])
3470 continue;
3471
3472 if (filter->plist[direct].name)
3473 free (filter->plist[direct].name);
3474 filter->plist[direct].name = strdup (name);
3475 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3476 }
3477 return 0;
3478}
3479
3480int
3481peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3482{
3483 struct bgp_filter *filter;
3484 struct bgp_filter *gfilter;
3485 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003486 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003487
3488 if (! peer->afc[afi][safi])
3489 return BGP_ERR_PEER_INACTIVE;
3490
3491 if (direct != FILTER_IN && direct != FILTER_OUT)
3492 return BGP_ERR_INVALID_VALUE;
3493
3494 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3495 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3496
3497 filter = &peer->filter[afi][safi];
3498
3499 /* apply peer-group filter */
3500 if (peer->af_group[afi][safi])
3501 {
3502 gfilter = &peer->group->conf->filter[afi][safi];
3503
3504 if (gfilter->plist[direct].name)
3505 {
3506 if (filter->plist[direct].name)
3507 free (filter->plist[direct].name);
3508 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3509 filter->plist[direct].plist = gfilter->plist[direct].plist;
3510 return 0;
3511 }
3512 }
3513
3514 if (filter->plist[direct].name)
3515 free (filter->plist[direct].name);
3516 filter->plist[direct].name = NULL;
3517 filter->plist[direct].plist = NULL;
3518
3519 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3520 return 0;
3521
3522 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003523 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003524 {
3525 filter = &peer->filter[afi][safi];
3526
3527 if (! peer->af_group[afi][safi])
3528 continue;
3529
3530 if (filter->plist[direct].name)
3531 free (filter->plist[direct].name);
3532 filter->plist[direct].name = NULL;
3533 filter->plist[direct].plist = NULL;
3534 }
3535
3536 return 0;
3537}
3538
3539/* Update prefix-list list. */
3540void
3541peer_prefix_list_update (struct prefix_list *plist)
3542{
paul1eb8ef22005-04-07 07:30:20 +00003543 struct listnode *mnode, *mnnode;
3544 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003545 struct bgp *bgp;
3546 struct peer *peer;
3547 struct peer_group *group;
3548 struct bgp_filter *filter;
3549 afi_t afi;
3550 safi_t safi;
3551 int direct;
3552
paul1eb8ef22005-04-07 07:30:20 +00003553 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003554 {
paul1eb8ef22005-04-07 07:30:20 +00003555 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003556 {
3557 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3558 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3559 {
3560 filter = &peer->filter[afi][safi];
3561
3562 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3563 {
3564 if (filter->plist[direct].name)
3565 filter->plist[direct].plist =
3566 prefix_list_lookup (afi, filter->plist[direct].name);
3567 else
3568 filter->plist[direct].plist = NULL;
3569 }
3570 }
3571 }
paul1eb8ef22005-04-07 07:30:20 +00003572 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003573 {
3574 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3575 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3576 {
3577 filter = &group->conf->filter[afi][safi];
3578
3579 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3580 {
3581 if (filter->plist[direct].name)
3582 filter->plist[direct].plist =
3583 prefix_list_lookup (afi, filter->plist[direct].name);
3584 else
3585 filter->plist[direct].plist = NULL;
3586 }
3587 }
3588 }
3589 }
3590}
3591
3592int
3593peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003594 const char *name)
paul718e3742002-12-13 20:15:29 +00003595{
3596 struct bgp_filter *filter;
3597 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003598 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003599
3600 if (! peer->afc[afi][safi])
3601 return BGP_ERR_PEER_INACTIVE;
3602
3603 if (direct != FILTER_IN && direct != FILTER_OUT)
3604 return BGP_ERR_INVALID_VALUE;
3605
3606 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3607 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3608
3609 filter = &peer->filter[afi][safi];
3610
3611 if (filter->aslist[direct].name)
3612 free (filter->aslist[direct].name);
3613 filter->aslist[direct].name = strdup (name);
3614 filter->aslist[direct].aslist = as_list_lookup (name);
3615
3616 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3617 return 0;
3618
3619 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003620 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003621 {
3622 filter = &peer->filter[afi][safi];
3623
3624 if (! peer->af_group[afi][safi])
3625 continue;
3626
3627 if (filter->aslist[direct].name)
3628 free (filter->aslist[direct].name);
3629 filter->aslist[direct].name = strdup (name);
3630 filter->aslist[direct].aslist = as_list_lookup (name);
3631 }
3632 return 0;
3633}
3634
3635int
3636peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3637{
3638 struct bgp_filter *filter;
3639 struct bgp_filter *gfilter;
3640 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003641 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003642
3643 if (! peer->afc[afi][safi])
3644 return BGP_ERR_PEER_INACTIVE;
3645
hassob5f29602005-05-25 21:00:28 +00003646 if (direct != FILTER_IN && direct != FILTER_OUT)
paul718e3742002-12-13 20:15:29 +00003647 return BGP_ERR_INVALID_VALUE;
3648
hassob5f29602005-05-25 21:00:28 +00003649 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003650 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;
paul1eb8ef22005-04-07 07:30:20 +00003678 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003679 {
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;
paul1eb8ef22005-04-07 07:30:20 +00003700 struct listnode *mnode, *mnnode;
3701 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003702 struct bgp *bgp;
3703 struct peer *peer;
3704 struct peer_group *group;
3705 struct bgp_filter *filter;
3706
paul1eb8ef22005-04-07 07:30:20 +00003707 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003708 {
paul1eb8ef22005-04-07 07:30:20 +00003709 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003710 {
3711 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3712 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3713 {
3714 filter = &peer->filter[afi][safi];
3715
3716 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3717 {
3718 if (filter->aslist[direct].name)
3719 filter->aslist[direct].aslist =
3720 as_list_lookup (filter->aslist[direct].name);
3721 else
3722 filter->aslist[direct].aslist = NULL;
3723 }
3724 }
3725 }
paul1eb8ef22005-04-07 07:30:20 +00003726 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003727 {
3728 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3729 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3730 {
3731 filter = &group->conf->filter[afi][safi];
3732
3733 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3734 {
3735 if (filter->aslist[direct].name)
3736 filter->aslist[direct].aslist =
3737 as_list_lookup (filter->aslist[direct].name);
3738 else
3739 filter->aslist[direct].aslist = NULL;
3740 }
3741 }
3742 }
3743 }
3744}
3745
3746/* Set route-map to the peer. */
3747int
3748peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003749 const char *name)
paul718e3742002-12-13 20:15:29 +00003750{
3751 struct bgp_filter *filter;
3752 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003753 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003754
3755 if (! peer->afc[afi][safi])
3756 return BGP_ERR_PEER_INACTIVE;
3757
paulfee0f4c2004-09-13 05:12:46 +00003758 if (direct != RMAP_IN && direct != RMAP_OUT &&
3759 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003760 return BGP_ERR_INVALID_VALUE;
3761
paulfee0f4c2004-09-13 05:12:46 +00003762 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
3763 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003764 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3765
3766 filter = &peer->filter[afi][safi];
3767
3768 if (filter->map[direct].name)
3769 free (filter->map[direct].name);
3770
3771 filter->map[direct].name = strdup (name);
3772 filter->map[direct].map = route_map_lookup_by_name (name);
3773
3774 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3775 return 0;
3776
3777 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003778 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003779 {
3780 filter = &peer->filter[afi][safi];
3781
3782 if (! peer->af_group[afi][safi])
3783 continue;
3784
3785 if (filter->map[direct].name)
3786 free (filter->map[direct].name);
3787 filter->map[direct].name = strdup (name);
3788 filter->map[direct].map = route_map_lookup_by_name (name);
3789 }
3790 return 0;
3791}
3792
3793/* Unset route-map from the peer. */
3794int
3795peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3796{
3797 struct bgp_filter *filter;
3798 struct bgp_filter *gfilter;
3799 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003800 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003801
3802 if (! peer->afc[afi][safi])
3803 return BGP_ERR_PEER_INACTIVE;
3804
hassob5f29602005-05-25 21:00:28 +00003805 if (direct != RMAP_IN && direct != RMAP_OUT &&
3806 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003807 return BGP_ERR_INVALID_VALUE;
3808
hassob5f29602005-05-25 21:00:28 +00003809 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
3810 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003811 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3812
3813 filter = &peer->filter[afi][safi];
3814
3815 /* apply peer-group filter */
3816 if (peer->af_group[afi][safi])
3817 {
3818 gfilter = &peer->group->conf->filter[afi][safi];
3819
3820 if (gfilter->map[direct].name)
3821 {
3822 if (filter->map[direct].name)
3823 free (filter->map[direct].name);
3824 filter->map[direct].name = strdup (gfilter->map[direct].name);
3825 filter->map[direct].map = gfilter->map[direct].map;
3826 return 0;
3827 }
3828 }
3829
3830 if (filter->map[direct].name)
3831 free (filter->map[direct].name);
3832 filter->map[direct].name = NULL;
3833 filter->map[direct].map = NULL;
3834
3835 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3836 return 0;
3837
3838 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003839 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003840 {
3841 filter = &peer->filter[afi][safi];
3842
3843 if (! peer->af_group[afi][safi])
3844 continue;
3845
3846 if (filter->map[direct].name)
3847 free (filter->map[direct].name);
3848 filter->map[direct].name = NULL;
3849 filter->map[direct].map = NULL;
3850 }
3851 return 0;
3852}
3853
3854/* Set unsuppress-map to the peer. */
3855int
paulfd79ac92004-10-13 05:06:08 +00003856peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
3857 const char *name)
paul718e3742002-12-13 20:15:29 +00003858{
3859 struct bgp_filter *filter;
3860 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003861 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003862
3863 if (! peer->afc[afi][safi])
3864 return BGP_ERR_PEER_INACTIVE;
3865
3866 if (peer_is_group_member (peer, afi, safi))
3867 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3868
3869 filter = &peer->filter[afi][safi];
3870
3871 if (filter->usmap.name)
3872 free (filter->usmap.name);
3873
3874 filter->usmap.name = strdup (name);
3875 filter->usmap.map = route_map_lookup_by_name (name);
3876
3877 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3878 return 0;
3879
3880 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003881 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003882 {
3883 filter = &peer->filter[afi][safi];
3884
3885 if (! peer->af_group[afi][safi])
3886 continue;
3887
3888 if (filter->usmap.name)
3889 free (filter->usmap.name);
3890 filter->usmap.name = strdup (name);
3891 filter->usmap.map = route_map_lookup_by_name (name);
3892 }
3893 return 0;
3894}
3895
3896/* Unset route-map from the peer. */
3897int
3898peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
3899{
3900 struct bgp_filter *filter;
3901 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003902 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003903
3904 if (! peer->afc[afi][safi])
3905 return BGP_ERR_PEER_INACTIVE;
3906
3907 if (peer_is_group_member (peer, afi, safi))
3908 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3909
3910 filter = &peer->filter[afi][safi];
3911
3912 if (filter->usmap.name)
3913 free (filter->usmap.name);
3914 filter->usmap.name = NULL;
3915 filter->usmap.map = NULL;
3916
3917 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3918 return 0;
3919
3920 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003921 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003922 {
3923 filter = &peer->filter[afi][safi];
3924
3925 if (! peer->af_group[afi][safi])
3926 continue;
3927
3928 if (filter->usmap.name)
3929 free (filter->usmap.name);
3930 filter->usmap.name = NULL;
3931 filter->usmap.map = NULL;
3932 }
3933 return 0;
3934}
3935
3936int
3937peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00003938 u_int32_t max, u_char threshold,
3939 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00003940{
3941 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003942 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003943
3944 if (! peer->afc[afi][safi])
3945 return BGP_ERR_PEER_INACTIVE;
3946
3947 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3948 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00003949 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00003950 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00003951 if (warning)
3952 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3953 else
3954 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3955
3956 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3957 return 0;
3958
3959 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003960 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003961 {
3962 if (! peer->af_group[afi][safi])
3963 continue;
3964
3965 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3966 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00003967 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00003968 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00003969 if (warning)
3970 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3971 else
3972 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3973 }
3974 return 0;
3975}
3976
3977int
3978peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
3979{
3980 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003981 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003982
3983 if (! peer->afc[afi][safi])
3984 return BGP_ERR_PEER_INACTIVE;
3985
3986 /* apply peer-group config */
3987 if (peer->af_group[afi][safi])
3988 {
3989 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
3990 PEER_FLAG_MAX_PREFIX))
3991 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3992 else
3993 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3994
3995 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
3996 PEER_FLAG_MAX_PREFIX_WARNING))
3997 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3998 else
3999 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4000
4001 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004002 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004003 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004004 return 0;
4005 }
4006
4007 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4008 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4009 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004010 peer->pmax_threshold[afi][safi] = 0;
4011 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004012
4013 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4014 return 0;
4015
4016 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004017 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004018 {
4019 if (! peer->af_group[afi][safi])
4020 continue;
4021
4022 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4023 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4024 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004025 peer->pmax_threshold[afi][safi] = 0;
4026 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004027 }
4028 return 0;
4029}
4030
4031int
4032peer_clear (struct peer *peer)
4033{
4034 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4035 {
hasso0a486e52005-02-01 20:57:17 +00004036 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4037 {
4038 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4039 if (peer->t_pmax_restart)
4040 {
4041 BGP_TIMER_OFF (peer->t_pmax_restart);
4042 if (BGP_DEBUG (events, EVENTS))
4043 zlog_debug ("%s Maximum-prefix restart timer canceled",
4044 peer->host);
4045 }
4046 BGP_EVENT_ADD (peer, BGP_Start);
4047 return 0;
4048 }
4049
paul718e3742002-12-13 20:15:29 +00004050 peer->v_start = BGP_INIT_START_TIMER;
4051 if (peer->status == Established)
4052 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4053 BGP_NOTIFY_CEASE_ADMIN_RESET);
4054 else
4055 BGP_EVENT_ADD (peer, BGP_Stop);
4056 }
4057 return 0;
4058}
4059
4060int
4061peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4062 enum bgp_clear_type stype)
4063{
4064 if (peer->status != Established)
4065 return 0;
4066
4067 if (! peer->afc[afi][safi])
4068 return BGP_ERR_AF_UNCONFIGURED;
4069
paulfee0f4c2004-09-13 05:12:46 +00004070 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4071 {
4072 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4073 return 0;
4074 bgp_check_local_routes_rsclient (peer, afi, safi);
4075 bgp_soft_reconfig_rsclient (peer, afi, safi);
4076 }
4077
paul718e3742002-12-13 20:15:29 +00004078 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4079 bgp_announce_route (peer, afi, safi);
4080
4081 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4082 {
4083 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4084 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4085 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4086 {
4087 struct bgp_filter *filter = &peer->filter[afi][safi];
4088 u_char prefix_type;
4089
4090 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4091 prefix_type = ORF_TYPE_PREFIX;
4092 else
4093 prefix_type = ORF_TYPE_PREFIX_OLD;
4094
4095 if (filter->plist[FILTER_IN].plist)
4096 {
4097 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4098 bgp_route_refresh_send (peer, afi, safi,
4099 prefix_type, REFRESH_DEFER, 1);
4100 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4101 REFRESH_IMMEDIATE, 0);
4102 }
4103 else
4104 {
4105 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4106 bgp_route_refresh_send (peer, afi, safi,
4107 prefix_type, REFRESH_IMMEDIATE, 1);
4108 else
4109 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4110 }
4111 return 0;
4112 }
4113 }
4114
4115 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4116 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4117 {
4118 /* If neighbor has soft reconfiguration inbound flag.
4119 Use Adj-RIB-In database. */
4120 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4121 bgp_soft_reconfig_in (peer, afi, safi);
4122 else
4123 {
4124 /* If neighbor has route refresh capability, send route refresh
4125 message to the peer. */
4126 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4127 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4128 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4129 else
4130 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4131 }
4132 }
4133 return 0;
4134}
4135
paulfd79ac92004-10-13 05:06:08 +00004136/* Display peer uptime.*/
4137/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004138char *
4139peer_uptime (time_t uptime2, char *buf, size_t len)
4140{
4141 time_t uptime1;
4142 struct tm *tm;
4143
4144 /* Check buffer length. */
4145 if (len < BGP_UPTIME_LEN)
4146 {
gdtc29fdba2004-12-09 14:46:46 +00004147 /* XXX: warning: long int format, size_t arg (arg 2) */
paula2b1ecd2004-10-31 18:58:09 +00004148 zlog_warn ("peer_uptime (): buffer shortage %ld", len);
paulfd79ac92004-10-13 05:06:08 +00004149 /* XXX: should return status instead of buf... */
4150 snprintf (buf, len, "<error> ");
4151 return buf;
paul718e3742002-12-13 20:15:29 +00004152 }
4153
4154 /* If there is no connection has been done before print `never'. */
4155 if (uptime2 == 0)
4156 {
4157 snprintf (buf, len, "never ");
4158 return buf;
4159 }
4160
4161 /* Get current time. */
4162 uptime1 = time (NULL);
4163 uptime1 -= uptime2;
4164 tm = gmtime (&uptime1);
4165
4166 /* Making formatted timer strings. */
4167#define ONE_DAY_SECOND 60*60*24
4168#define ONE_WEEK_SECOND 60*60*24*7
4169
4170 if (uptime1 < ONE_DAY_SECOND)
4171 snprintf (buf, len, "%02d:%02d:%02d",
4172 tm->tm_hour, tm->tm_min, tm->tm_sec);
4173 else if (uptime1 < ONE_WEEK_SECOND)
4174 snprintf (buf, len, "%dd%02dh%02dm",
4175 tm->tm_yday, tm->tm_hour, tm->tm_min);
4176 else
4177 snprintf (buf, len, "%02dw%dd%02dh",
4178 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4179 return buf;
4180}
4181
4182void
4183bgp_config_write_filter (struct vty *vty, struct peer *peer,
4184 afi_t afi, safi_t safi)
4185{
4186 struct bgp_filter *filter;
4187 struct bgp_filter *gfilter = NULL;
4188 char *addr;
4189 int in = FILTER_IN;
4190 int out = FILTER_OUT;
4191
4192 addr = peer->host;
4193 filter = &peer->filter[afi][safi];
4194 if (peer->af_group[afi][safi])
4195 gfilter = &peer->group->conf->filter[afi][safi];
4196
4197 /* distribute-list. */
4198 if (filter->dlist[in].name)
4199 if (! gfilter || ! gfilter->dlist[in].name
4200 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4201 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4202 filter->dlist[in].name, VTY_NEWLINE);
4203 if (filter->dlist[out].name && ! gfilter)
4204 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4205 filter->dlist[out].name, VTY_NEWLINE);
4206
4207 /* prefix-list. */
4208 if (filter->plist[in].name)
4209 if (! gfilter || ! gfilter->plist[in].name
4210 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4211 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4212 filter->plist[in].name, VTY_NEWLINE);
4213 if (filter->plist[out].name && ! gfilter)
4214 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4215 filter->plist[out].name, VTY_NEWLINE);
4216
4217 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004218 if (filter->map[RMAP_IN].name)
4219 if (! gfilter || ! gfilter->map[RMAP_IN].name
4220 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004221 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004222 filter->map[RMAP_IN].name, VTY_NEWLINE);
4223 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004224 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004225 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4226 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4227 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4228 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4229 if (filter->map[RMAP_EXPORT].name)
4230 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4231 || strcmp (filter->map[RMAP_EXPORT].name,
4232 gfilter->map[RMAP_EXPORT].name) != 0)
4233 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4234 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004235
4236 /* unsuppress-map */
4237 if (filter->usmap.name && ! gfilter)
4238 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4239 filter->usmap.name, VTY_NEWLINE);
4240
4241 /* filter-list. */
4242 if (filter->aslist[in].name)
4243 if (! gfilter || ! gfilter->aslist[in].name
4244 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4245 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4246 filter->aslist[in].name, VTY_NEWLINE);
4247 if (filter->aslist[out].name && ! gfilter)
4248 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4249 filter->aslist[out].name, VTY_NEWLINE);
4250}
4251
4252/* BGP peer configuration display function. */
4253void
4254bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4255 struct peer *peer, afi_t afi, safi_t safi)
4256{
4257 struct bgp_filter *filter;
4258 struct peer *g_peer = NULL;
4259 char buf[SU_ADDRSTRLEN];
4260 char *addr;
4261
4262 filter = &peer->filter[afi][safi];
4263 addr = peer->host;
4264 if (peer_group_active (peer))
4265 g_peer = peer->group->conf;
4266
4267 /************************************
4268 ****** Global to the neighbor ******
4269 ************************************/
4270 if (afi == AFI_IP && safi == SAFI_UNICAST)
4271 {
4272 /* remote-as. */
4273 if (! peer_group_active (peer))
4274 {
4275 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4276 vty_out (vty, " neighbor %s peer-group%s", addr,
4277 VTY_NEWLINE);
4278 if (peer->as)
4279 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4280 VTY_NEWLINE);
4281 }
4282 else
4283 {
4284 if (! g_peer->as)
4285 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4286 VTY_NEWLINE);
4287 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4288 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4289 peer->group->name, VTY_NEWLINE);
4290 }
4291
4292 /* local-as. */
4293 if (peer->change_local_as)
4294 if (! peer_group_active (peer))
4295 vty_out (vty, " neighbor %s local-as %d%s%s", addr,
4296 peer->change_local_as,
4297 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4298 " no-prepend" : "", VTY_NEWLINE);
4299
4300 /* Description. */
4301 if (peer->desc)
4302 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4303 VTY_NEWLINE);
4304
4305 /* Shutdown. */
4306 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4307 if (! peer_group_active (peer) ||
4308 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4309 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4310
4311 /* BGP port. */
4312 if (peer->port != BGP_PORT_DEFAULT)
4313 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
4314 VTY_NEWLINE);
4315
4316 /* Local interface name. */
4317 if (peer->ifname)
4318 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4319 VTY_NEWLINE);
4320
4321 /* Passive. */
4322 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4323 if (! peer_group_active (peer) ||
4324 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4325 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4326
4327 /* EBGP multihop. */
4328 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
4329 if (! peer_group_active (peer) ||
4330 g_peer->ttl != peer->ttl)
4331 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4332 VTY_NEWLINE);
4333
hasso6ffd2072005-02-02 14:50:11 +00004334 /* disable-connected-check. */
4335 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004336 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004337 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4338 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004339
4340 /* Update-source. */
4341 if (peer->update_if)
4342 if (! peer_group_active (peer) || ! g_peer->update_if
4343 || strcmp (g_peer->update_if, peer->update_if) != 0)
4344 vty_out (vty, " neighbor %s update-source %s%s", addr,
4345 peer->update_if, VTY_NEWLINE);
4346 if (peer->update_source)
4347 if (! peer_group_active (peer) || ! g_peer->update_source
4348 || sockunion_cmp (g_peer->update_source,
4349 peer->update_source) != 0)
4350 vty_out (vty, " neighbor %s update-source %s%s", addr,
4351 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4352 VTY_NEWLINE);
4353
paul718e3742002-12-13 20:15:29 +00004354 /* advertisement-interval */
4355 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4356 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4357 addr, peer->v_routeadv, VTY_NEWLINE);
4358
4359 /* timers. */
4360 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4361 && ! peer_group_active (peer))
4362 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4363 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4364
4365 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4366 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4367 peer->connect, VTY_NEWLINE);
4368
4369 /* Default weight. */
4370 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4371 if (! peer_group_active (peer) ||
4372 g_peer->weight != peer->weight)
4373 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4374 VTY_NEWLINE);
4375
paul718e3742002-12-13 20:15:29 +00004376 /* Dynamic capability. */
4377 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4378 if (! peer_group_active (peer) ||
4379 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4380 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4381 VTY_NEWLINE);
4382
4383 /* dont capability negotiation. */
4384 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4385 if (! peer_group_active (peer) ||
4386 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4387 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4388 VTY_NEWLINE);
4389
4390 /* override capability negotiation. */
4391 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4392 if (! peer_group_active (peer) ||
4393 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4394 vty_out (vty, " neighbor %s override-capability%s", addr,
4395 VTY_NEWLINE);
4396
4397 /* strict capability negotiation. */
4398 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4399 if (! peer_group_active (peer) ||
4400 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4401 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4402 VTY_NEWLINE);
4403
4404 if (! peer_group_active (peer))
4405 {
4406 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4407 {
4408 if (peer->afc[AFI_IP][SAFI_UNICAST])
4409 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4410 }
4411 else
4412 {
4413 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4414 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4415 }
4416 }
4417 }
4418
4419
4420 /************************************
4421 ****** Per AF to the neighbor ******
4422 ************************************/
4423
4424 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4425 {
4426 if (peer->af_group[afi][safi])
4427 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4428 peer->group->name, VTY_NEWLINE);
4429 else
4430 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4431 }
4432
4433 /* ORF capability. */
4434 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4435 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4436 if (! peer->af_group[afi][safi])
4437 {
4438 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4439
4440 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4441 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4442 vty_out (vty, " both");
4443 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4444 vty_out (vty, " send");
4445 else
4446 vty_out (vty, " receive");
4447 vty_out (vty, "%s", VTY_NEWLINE);
4448 }
4449
4450 /* Route reflector client. */
4451 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4452 && ! peer->af_group[afi][safi])
4453 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4454 VTY_NEWLINE);
4455
4456 /* Nexthop self. */
4457 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4458 && ! peer->af_group[afi][safi])
4459 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4460
4461 /* Remove private AS. */
4462 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4463 && ! peer->af_group[afi][safi])
4464 vty_out (vty, " neighbor %s remove-private-AS%s",
4465 addr, VTY_NEWLINE);
4466
4467 /* send-community print. */
4468 if (! peer->af_group[afi][safi])
4469 {
4470 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4471 {
4472 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4473 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4474 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4475 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4476 vty_out (vty, " neighbor %s send-community extended%s",
4477 addr, VTY_NEWLINE);
4478 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4479 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4480 }
4481 else
4482 {
4483 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4484 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4485 vty_out (vty, " no neighbor %s send-community both%s",
4486 addr, VTY_NEWLINE);
4487 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4488 vty_out (vty, " no neighbor %s send-community extended%s",
4489 addr, VTY_NEWLINE);
4490 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4491 vty_out (vty, " no neighbor %s send-community%s",
4492 addr, VTY_NEWLINE);
4493 }
4494 }
4495
4496 /* Default information */
4497 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4498 && ! peer->af_group[afi][safi])
4499 {
4500 vty_out (vty, " neighbor %s default-originate", addr);
4501 if (peer->default_rmap[afi][safi].name)
4502 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4503 vty_out (vty, "%s", VTY_NEWLINE);
4504 }
4505
4506 /* Soft reconfiguration inbound. */
4507 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4508 if (! peer->af_group[afi][safi] ||
4509 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4510 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4511 VTY_NEWLINE);
4512
4513 /* maximum-prefix. */
4514 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4515 if (! peer->af_group[afi][safi]
4516 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004517 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004518 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4519 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00004520 {
hasso0a486e52005-02-01 20:57:17 +00004521 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
4522 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
4523 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
4524 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
4525 vty_out (vty, " warning-only");
4526 if (peer->pmax_restart[afi][safi])
4527 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
4528 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00004529 }
paul718e3742002-12-13 20:15:29 +00004530
4531 /* Route server client. */
4532 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
4533 && ! peer->af_group[afi][safi])
4534 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
4535
4536 /* Allow AS in. */
4537 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
4538 if (! peer_group_active (peer)
4539 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
4540 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
4541 {
4542 if (peer->allowas_in[afi][safi] == 3)
4543 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
4544 else
4545 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
4546 peer->allowas_in[afi][safi], VTY_NEWLINE);
4547 }
4548
4549 /* Filter. */
4550 bgp_config_write_filter (vty, peer, afi, safi);
4551
4552 /* atribute-unchanged. */
4553 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4554 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4555 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4556 && ! peer->af_group[afi][safi])
4557 {
4558 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4559 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4560 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4561 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
4562 else
4563 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
4564 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
4565 " as-path" : "",
4566 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
4567 " next-hop" : "",
4568 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
4569 " med" : "", VTY_NEWLINE);
4570 }
4571}
4572
4573/* Display "address-family" configuration header. */
4574void
4575bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
4576 int *write)
4577{
4578 if (*write)
4579 return;
4580
4581 if (afi == AFI_IP && safi == SAFI_UNICAST)
4582 return;
4583
4584 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
4585
4586 if (afi == AFI_IP)
4587 {
4588 if (safi == SAFI_MULTICAST)
4589 vty_out (vty, "ipv4 multicast");
4590 else if (safi == SAFI_MPLS_VPN)
4591 vty_out (vty, "vpnv4 unicast");
4592 }
4593 else if (afi == AFI_IP6)
4594 vty_out (vty, "ipv6");
4595
4596 vty_out (vty, "%s", VTY_NEWLINE);
4597
4598 *write = 1;
4599}
4600
4601/* Address family based peer configuration display. */
4602int
4603bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
4604 safi_t safi)
4605{
4606 int write = 0;
4607 struct peer *peer;
4608 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004609 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004610
4611 bgp_config_write_network (vty, bgp, afi, safi, &write);
4612
4613 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
4614
paul1eb8ef22005-04-07 07:30:20 +00004615 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004616 {
4617 if (group->conf->afc[afi][safi])
4618 {
4619 bgp_config_write_family_header (vty, afi, safi, &write);
4620 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
4621 }
4622 }
paul1eb8ef22005-04-07 07:30:20 +00004623 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004624 {
4625 if (peer->afc[afi][safi])
4626 {
4627 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4628 {
4629 bgp_config_write_family_header (vty, afi, safi, &write);
4630 bgp_config_write_peer (vty, bgp, peer, afi, safi);
4631 }
4632 }
4633 }
4634 if (write)
4635 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
4636
4637 return write;
4638}
4639
4640int
4641bgp_config_write (struct vty *vty)
4642{
4643 int write = 0;
4644 struct bgp *bgp;
4645 struct peer_group *group;
4646 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004647 struct listnode *node, *nnode;
4648 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00004649
4650 /* BGP Multiple instance. */
4651 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4652 {
4653 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
4654 write++;
4655 }
4656
4657 /* BGP Config type. */
4658 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4659 {
4660 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
4661 write++;
4662 }
4663
4664 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004665 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004666 {
4667 if (write)
4668 vty_out (vty, "!%s", VTY_NEWLINE);
4669
4670 /* Router bgp ASN */
4671 vty_out (vty, "router bgp %d", bgp->as);
4672
4673 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4674 {
4675 if (bgp->name)
4676 vty_out (vty, " view %s", bgp->name);
4677 }
4678 vty_out (vty, "%s", VTY_NEWLINE);
4679
4680 /* No Synchronization */
4681 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4682 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
4683
4684 /* BGP fast-external-failover. */
4685 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
4686 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
4687
4688 /* BGP router ID. */
4689 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
4690 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
4691 VTY_NEWLINE);
4692
paul848973c2003-08-13 00:32:49 +00004693 /* BGP log-neighbor-changes. */
4694 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
4695 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
4696
paul718e3742002-12-13 20:15:29 +00004697 /* BGP configuration. */
4698 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
4699 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
4700
4701 /* BGP default ipv4-unicast. */
4702 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4703 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
4704
4705 /* BGP default local-preference. */
4706 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
4707 vty_out (vty, " bgp default local-preference %d%s",
4708 bgp->default_local_pref, VTY_NEWLINE);
4709
4710 /* BGP client-to-client reflection. */
4711 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
4712 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
4713
4714 /* BGP cluster ID. */
4715 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
4716 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
4717 VTY_NEWLINE);
4718
hassoe0701b72004-05-20 09:19:34 +00004719 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00004720 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00004721 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
4722 VTY_NEWLINE);
4723
4724 /* Confederation peer */
4725 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00004726 {
hassoe0701b72004-05-20 09:19:34 +00004727 int i;
paul718e3742002-12-13 20:15:29 +00004728
hassoe0701b72004-05-20 09:19:34 +00004729 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00004730
hassoe0701b72004-05-20 09:19:34 +00004731 for (i = 0; i < bgp->confed_peers_cnt; i++)
4732 vty_out(vty, " %d", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00004733
hassoe0701b72004-05-20 09:19:34 +00004734 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004735 }
4736
4737 /* BGP enforce-first-as. */
4738 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
4739 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
4740
4741 /* BGP deterministic-med. */
4742 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
4743 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00004744
4745 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00004746 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
4747 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
4748 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00004749 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
4750 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
4751
paul718e3742002-12-13 20:15:29 +00004752 /* BGP bestpath method. */
4753 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
4754 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00004755 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
4756 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004757 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
4758 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
4759 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
4760 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4761 {
4762 vty_out (vty, " bgp bestpath med");
4763 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
4764 vty_out (vty, " confed");
4765 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4766 vty_out (vty, " missing-as-worst");
4767 vty_out (vty, "%s", VTY_NEWLINE);
4768 }
4769
4770 /* BGP network import check. */
4771 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
4772 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
4773
4774 /* BGP scan interval. */
4775 bgp_config_write_scan_time (vty);
4776
4777 /* BGP flag dampening. */
4778 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
4779 BGP_CONFIG_DAMPENING))
4780 bgp_config_write_damp (vty);
4781
4782 /* BGP static route configuration. */
4783 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4784
4785 /* BGP redistribute configuration. */
4786 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4787
4788 /* BGP timers configuration. */
4789 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
4790 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
4791 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
4792 bgp->default_holdtime, VTY_NEWLINE);
4793
4794 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00004795 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004796 {
4797 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
4798 }
4799
4800 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004801 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004802 {
4803 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4804 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
4805 }
4806
4807 /* Distance configuration. */
4808 bgp_config_write_distance (vty, bgp);
4809
4810 /* No auto-summary */
4811 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4812 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
4813
4814 /* IPv4 multicast configuration. */
4815 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
4816
4817 /* IPv4 VPN configuration. */
4818 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
4819
4820 /* IPv6 unicast configuration. */
4821 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
4822
4823 write++;
4824 }
4825 return write;
4826}
4827
4828void
4829bgp_master_init ()
4830{
4831 memset (&bgp_master, 0, sizeof (struct bgp_master));
4832
4833 bm = &bgp_master;
4834 bm->bgp = list_new ();
4835 bm->port = BGP_PORT_DEFAULT;
4836 bm->master = thread_master_create ();
4837 bm->start_time = time (NULL);
4838}
4839
4840void
4841bgp_init ()
4842{
4843 void bgp_zebra_init ();
4844 void bgp_route_map_init ();
4845 void bgp_filter_init ();
4846
4847 /* BGP VTY commands installation. */
4848 bgp_vty_init ();
4849
4850 /* Create BGP server socket. */
4851 bgp_socket (NULL, bm->port);
4852
4853 /* Init zebra. */
4854 bgp_zebra_init ();
4855
4856 /* BGP inits. */
4857 bgp_attr_init ();
4858 bgp_debug_init ();
4859 bgp_dump_init ();
4860 bgp_route_init ();
4861 bgp_route_map_init ();
4862 bgp_scan_init ();
4863 bgp_mplsvpn_init ();
4864
4865 /* Access list initialize. */
4866 access_list_init ();
4867 access_list_add_hook (peer_distribute_update);
4868 access_list_delete_hook (peer_distribute_update);
4869
4870 /* Filter list initialize. */
4871 bgp_filter_init ();
4872 as_list_add_hook (peer_aslist_update);
4873 as_list_delete_hook (peer_aslist_update);
4874
4875 /* Prefix list initialize.*/
4876 prefix_list_init ();
4877 prefix_list_add_hook (peer_prefix_list_update);
4878 prefix_list_delete_hook (peer_prefix_list_update);
4879
4880 /* Community list initialize. */
4881 bgp_clist = community_list_init ();
4882
4883#ifdef HAVE_SNMP
4884 bgp_snmp_init ();
4885#endif /* HAVE_SNMP */
4886}
paul545acaf2004-04-20 15:13:15 +00004887
4888void
4889bgp_terminate ()
4890{
paul545acaf2004-04-20 15:13:15 +00004891 struct bgp *bgp;
4892 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004893 struct listnode *node, *nnode;
4894 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00004895
paul1eb8ef22005-04-07 07:30:20 +00004896 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
4897 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00004898 if (peer->status == Established)
4899 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4900 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00004901
paul545acaf2004-04-20 15:13:15 +00004902 bgp_cleanup_routes ();
4903}
4904