blob: 881a3c7babb1772471e806315ab81bb23086efac [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;
paul1eb8ef22005-04-07 07:30:20 +00001915 struct listnode *node;
paul718e3742002-12-13 20:15:29 +00001916 struct listnode *next;
1917 afi_t afi;
1918 safi_t safi;
1919 int i;
1920
1921 /* Delete static route. */
1922 bgp_static_delete (bgp);
1923
1924 /* Unset redistribution. */
1925 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1926 for (i = 0; i < ZEBRA_ROUTE_MAX; i++)
1927 if (i != ZEBRA_ROUTE_BGP)
1928 bgp_redistribute_unset (bgp, afi, i);
1929
1930 bgp->group->del = (void (*)(void *)) peer_group_delete;
1931 list_delete (bgp->group);
1932
paul1eb8ef22005-04-07 07:30:20 +00001933 for (ALL_LIST_ELEMENTS (bgp->peer, node, next, peer))
1934 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00001935
paulfee0f4c2004-09-13 05:12:46 +00001936 bgp->rsclient->del = (void (*)(void *)) peer_delete;
1937 list_delete (bgp->rsclient);
1938
paul718e3742002-12-13 20:15:29 +00001939 listnode_delete (bm->bgp, bgp);
1940
1941 if (bgp->name)
1942 free (bgp->name);
1943
1944 for (afi = AFI_IP; afi < AFI_MAX; afi++)
1945 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
1946 {
1947 if (bgp->route[afi][safi])
1948 XFREE (MTYPE_ROUTE_TABLE, bgp->route[afi][safi]);
1949 if (bgp->aggregate[afi][safi])
1950 XFREE (MTYPE_ROUTE_TABLE,bgp->aggregate[afi][safi]) ;
1951 if (bgp->rib[afi][safi])
1952 XFREE (MTYPE_ROUTE_TABLE,bgp->rib[afi][safi]);
1953 }
1954 XFREE (MTYPE_BGP, bgp);
1955
1956 return 0;
1957}
1958
1959struct peer *
1960peer_lookup (struct bgp *bgp, union sockunion *su)
1961{
1962 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001963 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001964
1965 if (! bgp)
1966 bgp = bgp_get_default ();
1967
1968 if (! bgp)
1969 return NULL;
1970
paul1eb8ef22005-04-07 07:30:20 +00001971 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001972 {
pauleb821182004-05-01 08:44:08 +00001973 if (sockunion_same (&peer->su, su)
1974 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1975 return peer;
paul718e3742002-12-13 20:15:29 +00001976 }
1977 return NULL;
1978}
1979
1980struct peer *
1981peer_lookup_with_open (union sockunion *su, as_t remote_as,
1982 struct in_addr *remote_id, int *as)
1983{
1984 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001985 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001986 struct bgp *bgp;
1987
1988 bgp = bgp_get_default ();
1989 if (! bgp)
1990 return NULL;
1991
paul1eb8ef22005-04-07 07:30:20 +00001992 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001993 {
pauleb821182004-05-01 08:44:08 +00001994 if (sockunion_same (&peer->su, su)
1995 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1996 {
1997 if (peer->as == remote_as
1998 && peer->remote_id.s_addr == remote_id->s_addr)
1999 return peer;
2000 if (peer->as == remote_as)
2001 *as = 1;
2002 }
paul718e3742002-12-13 20:15:29 +00002003 }
paul1eb8ef22005-04-07 07:30:20 +00002004 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002005 {
pauleb821182004-05-01 08:44:08 +00002006 if (sockunion_same (&peer->su, su)
2007 && ! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2008 {
2009 if (peer->as == remote_as
2010 && peer->remote_id.s_addr == 0)
2011 return peer;
2012 if (peer->as == remote_as)
2013 *as = 1;
2014 }
paul718e3742002-12-13 20:15:29 +00002015 }
2016 return NULL;
2017}
2018
2019/* If peer is configured at least one address family return 1. */
2020int
2021peer_active (struct peer *peer)
2022{
2023 if (peer->afc[AFI_IP][SAFI_UNICAST]
2024 || peer->afc[AFI_IP][SAFI_MULTICAST]
2025 || peer->afc[AFI_IP][SAFI_MPLS_VPN]
2026 || peer->afc[AFI_IP6][SAFI_UNICAST]
2027 || peer->afc[AFI_IP6][SAFI_MULTICAST])
2028 return 1;
2029 return 0;
2030}
2031
2032/* If peer is negotiated at least one address family return 1. */
2033int
2034peer_active_nego (struct peer *peer)
2035{
2036 if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
2037 || peer->afc_nego[AFI_IP][SAFI_MULTICAST]
2038 || peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
2039 || peer->afc_nego[AFI_IP6][SAFI_UNICAST]
2040 || peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
2041 return 1;
2042 return 0;
2043}
2044
2045/* peer_flag_change_type. */
2046enum peer_change_type
2047{
2048 peer_change_none,
2049 peer_change_reset,
2050 peer_change_reset_in,
2051 peer_change_reset_out,
2052};
2053
2054void
2055peer_change_action (struct peer *peer, afi_t afi, safi_t safi,
2056 enum peer_change_type type)
2057{
2058 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2059 return;
2060
2061 if (type == peer_change_reset)
2062 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2063 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2064 else if (type == peer_change_reset_in)
2065 {
2066 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
2067 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
2068 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
2069 else
2070 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2071 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2072 }
2073 else if (type == peer_change_reset_out)
2074 bgp_announce_route (peer, afi, safi);
2075}
2076
2077struct peer_flag_action
2078{
2079 /* Peer's flag. */
2080 u_int32_t flag;
2081
2082 /* This flag can be set for peer-group member. */
2083 u_char not_for_member;
2084
2085 /* Action when the flag is changed. */
2086 enum peer_change_type type;
hassoe0701b72004-05-20 09:19:34 +00002087
2088 /* Peer down cause */
2089 u_char peer_down;
paul718e3742002-12-13 20:15:29 +00002090};
2091
2092struct peer_flag_action peer_flag_action_list[] =
2093 {
2094 { PEER_FLAG_PASSIVE, 0, peer_change_reset },
2095 { PEER_FLAG_SHUTDOWN, 0, peer_change_reset },
2096 { PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none },
2097 { PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none },
2098 { PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none },
paul718e3742002-12-13 20:15:29 +00002099 { PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset },
hasso6ffd2072005-02-02 14:50:11 +00002100 { PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset },
paul718e3742002-12-13 20:15:29 +00002101 { 0, 0, 0 }
2102 };
2103
2104struct peer_flag_action peer_af_flag_action_list[] =
2105 {
2106 { PEER_FLAG_NEXTHOP_SELF, 1, peer_change_reset_out },
2107 { PEER_FLAG_SEND_COMMUNITY, 1, peer_change_reset_out },
2108 { PEER_FLAG_SEND_EXT_COMMUNITY, 1, peer_change_reset_out },
2109 { PEER_FLAG_SOFT_RECONFIG, 0, peer_change_reset_in },
2110 { PEER_FLAG_REFLECTOR_CLIENT, 1, peer_change_reset },
2111 { PEER_FLAG_RSERVER_CLIENT, 1, peer_change_reset },
2112 { PEER_FLAG_AS_PATH_UNCHANGED, 1, peer_change_reset_out },
2113 { PEER_FLAG_NEXTHOP_UNCHANGED, 1, peer_change_reset_out },
2114 { PEER_FLAG_MED_UNCHANGED, 1, peer_change_reset_out },
2115 { PEER_FLAG_REMOVE_PRIVATE_AS, 1, peer_change_reset_out },
2116 { PEER_FLAG_ALLOWAS_IN, 0, peer_change_reset_in },
2117 { PEER_FLAG_ORF_PREFIX_SM, 1, peer_change_reset },
2118 { PEER_FLAG_ORF_PREFIX_RM, 1, peer_change_reset },
paulfee0f4c2004-09-13 05:12:46 +00002119 { PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED, 0, peer_change_reset_out },
paul718e3742002-12-13 20:15:29 +00002120 { 0, 0, 0 }
2121 };
2122
2123/* Proper action set. */
2124int
2125peer_flag_action_set (struct peer_flag_action *action_list, int size,
2126 struct peer_flag_action *action, u_int32_t flag)
2127{
2128 int i;
2129 int found = 0;
2130 int reset_in = 0;
2131 int reset_out = 0;
2132 struct peer_flag_action *match = NULL;
2133
2134 /* Check peer's frag action. */
2135 for (i = 0; i < size; i++)
2136 {
2137 match = &action_list[i];
2138
2139 if (match->flag == 0)
2140 break;
2141
2142 if (match->flag & flag)
2143 {
2144 found = 1;
2145
2146 if (match->type == peer_change_reset_in)
2147 reset_in = 1;
2148 if (match->type == peer_change_reset_out)
2149 reset_out = 1;
2150 if (match->type == peer_change_reset)
2151 {
2152 reset_in = 1;
2153 reset_out = 1;
2154 }
2155 if (match->not_for_member)
2156 action->not_for_member = 1;
2157 }
2158 }
2159
2160 /* Set peer clear type. */
2161 if (reset_in && reset_out)
2162 action->type = peer_change_reset;
2163 else if (reset_in)
2164 action->type = peer_change_reset_in;
2165 else if (reset_out)
2166 action->type = peer_change_reset_out;
2167 else
2168 action->type = peer_change_none;
2169
2170 return found;
2171}
2172
2173void
2174peer_flag_modify_action (struct peer *peer, u_int32_t flag)
2175{
2176 if (flag == PEER_FLAG_SHUTDOWN)
2177 {
2178 if (CHECK_FLAG (peer->flags, flag))
2179 {
hasso93406d82005-02-02 14:40:33 +00002180 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2181 peer_nsf_stop (peer);
2182
hasso0a486e52005-02-01 20:57:17 +00002183 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
2184 if (peer->t_pmax_restart)
2185 {
2186 BGP_TIMER_OFF (peer->t_pmax_restart);
2187 if (BGP_DEBUG (events, EVENTS))
2188 zlog_debug ("%s Maximum-prefix restart timer canceled",
2189 peer->host);
2190 }
2191
hasso93406d82005-02-02 14:40:33 +00002192 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT))
2193 peer_nsf_stop (peer);
2194
paul718e3742002-12-13 20:15:29 +00002195 if (peer->status == Established)
2196 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2197 BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
2198 else
2199 BGP_EVENT_ADD (peer, BGP_Stop);
2200 }
2201 else
2202 {
2203 peer->v_start = BGP_INIT_START_TIMER;
2204 BGP_EVENT_ADD (peer, BGP_Stop);
2205 }
2206 }
2207 else if (peer->status == Established)
2208 {
hassoc9502432005-02-01 22:01:48 +00002209 if (flag == PEER_FLAG_DYNAMIC_CAPABILITY)
2210 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2211 else if (flag == PEER_FLAG_PASSIVE)
2212 peer->last_reset = PEER_DOWN_PASSIVE_CHANGE;
hasso6ffd2072005-02-02 14:50:11 +00002213 else if (flag == PEER_FLAG_DISABLE_CONNECTED_CHECK)
hassoc9502432005-02-01 22:01:48 +00002214 peer->last_reset = PEER_DOWN_MULTIHOP_CHANGE;
paul718e3742002-12-13 20:15:29 +00002215
hassoc9502432005-02-01 22:01:48 +00002216 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2217 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
paul718e3742002-12-13 20:15:29 +00002218 }
2219 else
2220 BGP_EVENT_ADD (peer, BGP_Stop);
2221}
2222
2223/* Change specified peer flag. */
2224int
2225peer_flag_modify (struct peer *peer, u_int32_t flag, int set)
2226{
2227 int found;
2228 int size;
2229 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002230 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002231 struct peer_flag_action action;
2232
2233 memset (&action, 0, sizeof (struct peer_flag_action));
2234 size = sizeof peer_flag_action_list / sizeof (struct peer_flag_action);
2235
2236 found = peer_flag_action_set (peer_flag_action_list, size, &action, flag);
2237
2238 /* No flag action is found. */
2239 if (! found)
2240 return BGP_ERR_INVALID_FLAG;
2241
2242 /* Not for peer-group member. */
2243 if (action.not_for_member && peer_group_active (peer))
2244 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2245
2246 /* When unset the peer-group member's flag we have to check
2247 peer-group configuration. */
2248 if (! set && peer_group_active (peer))
2249 if (CHECK_FLAG (peer->group->conf->flags, flag))
2250 {
2251 if (flag == PEER_FLAG_SHUTDOWN)
2252 return BGP_ERR_PEER_GROUP_SHUTDOWN;
2253 else
2254 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2255 }
2256
2257 /* Flag conflict check. */
2258 if (set
2259 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_STRICT_CAP_MATCH)
2260 && CHECK_FLAG (peer->flags | flag, PEER_FLAG_OVERRIDE_CAPABILITY))
2261 return BGP_ERR_PEER_FLAG_CONFLICT;
2262
2263 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2264 {
2265 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2266 return 0;
2267 if (! set && ! CHECK_FLAG (peer->flags, flag))
2268 return 0;
2269 }
2270
2271 if (set)
2272 SET_FLAG (peer->flags, flag);
2273 else
2274 UNSET_FLAG (peer->flags, flag);
2275
2276 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2277 {
2278 if (action.type == peer_change_reset)
2279 peer_flag_modify_action (peer, flag);
2280
2281 return 0;
2282 }
2283
2284 /* peer-group member updates. */
2285 group = peer->group;
2286
paul1eb8ef22005-04-07 07:30:20 +00002287 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002288 {
2289 if (set && CHECK_FLAG (peer->flags, flag) == flag)
2290 continue;
2291
2292 if (! set && ! CHECK_FLAG (peer->flags, flag))
2293 continue;
2294
2295 if (set)
2296 SET_FLAG (peer->flags, flag);
2297 else
2298 UNSET_FLAG (peer->flags, flag);
2299
2300 if (action.type == peer_change_reset)
2301 peer_flag_modify_action (peer, flag);
2302 }
2303 return 0;
2304}
2305
2306int
2307peer_flag_set (struct peer *peer, u_int32_t flag)
2308{
2309 return peer_flag_modify (peer, flag, 1);
2310}
2311
2312int
2313peer_flag_unset (struct peer *peer, u_int32_t flag)
2314{
2315 return peer_flag_modify (peer, flag, 0);
2316}
2317
2318int
2319peer_is_group_member (struct peer *peer, afi_t afi, safi_t safi)
2320{
2321 if (peer->af_group[afi][safi])
2322 return 1;
2323 return 0;
2324}
2325
2326int
2327peer_af_flag_modify (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag,
2328 int set)
2329{
2330 int found;
2331 int size;
paul1eb8ef22005-04-07 07:30:20 +00002332 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002333 struct peer_group *group;
2334 struct peer_flag_action action;
2335
2336 memset (&action, 0, sizeof (struct peer_flag_action));
2337 size = sizeof peer_af_flag_action_list / sizeof (struct peer_flag_action);
2338
2339 found = peer_flag_action_set (peer_af_flag_action_list, size, &action, flag);
2340
2341 /* No flag action is found. */
2342 if (! found)
2343 return BGP_ERR_INVALID_FLAG;
2344
2345 /* Adress family must be activated. */
2346 if (! peer->afc[afi][safi])
2347 return BGP_ERR_PEER_INACTIVE;
2348
2349 /* Not for peer-group member. */
2350 if (action.not_for_member && peer_is_group_member (peer, afi, safi))
2351 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2352
2353 /* Spcecial check for reflector client. */
2354 if (flag & PEER_FLAG_REFLECTOR_CLIENT
2355 && peer_sort (peer) != BGP_PEER_IBGP)
2356 return BGP_ERR_NOT_INTERNAL_PEER;
2357
2358 /* Spcecial check for remove-private-AS. */
2359 if (flag & PEER_FLAG_REMOVE_PRIVATE_AS
2360 && peer_sort (peer) == BGP_PEER_IBGP)
2361 return BGP_ERR_REMOVE_PRIVATE_AS;
2362
2363 /* When unset the peer-group member's flag we have to check
2364 peer-group configuration. */
2365 if (! set && peer->af_group[afi][safi])
2366 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi], flag))
2367 return BGP_ERR_PEER_GROUP_HAS_THE_FLAG;
2368
2369 /* When current flag configuration is same as requested one. */
2370 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2371 {
2372 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2373 return 0;
2374 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2375 return 0;
2376 }
2377
2378 if (set)
2379 SET_FLAG (peer->af_flags[afi][safi], flag);
2380 else
2381 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2382
2383 /* Execute action when peer is established. */
2384 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2385 && peer->status == Established)
2386 {
2387 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2388 bgp_clear_adj_in (peer, afi, safi);
2389 else
hassoe0701b72004-05-20 09:19:34 +00002390 {
2391 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2392 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2393 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2394 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2395 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2396 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2397 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2398 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2399
2400 peer_change_action (peer, afi, safi, action.type);
2401 }
2402
paul718e3742002-12-13 20:15:29 +00002403 }
2404
2405 /* Peer group member updates. */
2406 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2407 {
2408 group = peer->group;
2409
paul1eb8ef22005-04-07 07:30:20 +00002410 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002411 {
2412 if (! peer->af_group[afi][safi])
2413 continue;
2414
2415 if (set && CHECK_FLAG (peer->af_flags[afi][safi], flag) == flag)
2416 continue;
2417
2418 if (! set && ! CHECK_FLAG (peer->af_flags[afi][safi], flag))
2419 continue;
2420
2421 if (set)
2422 SET_FLAG (peer->af_flags[afi][safi], flag);
2423 else
2424 UNSET_FLAG (peer->af_flags[afi][safi], flag);
2425
2426 if (peer->status == Established)
2427 {
2428 if (! set && flag == PEER_FLAG_SOFT_RECONFIG)
2429 bgp_clear_adj_in (peer, afi, safi);
2430 else
hassoe0701b72004-05-20 09:19:34 +00002431 {
2432 if (flag == PEER_FLAG_REFLECTOR_CLIENT)
2433 peer->last_reset = PEER_DOWN_RR_CLIENT_CHANGE;
2434 else if (flag == PEER_FLAG_RSERVER_CLIENT)
2435 peer->last_reset = PEER_DOWN_RS_CLIENT_CHANGE;
2436 else if (flag == PEER_FLAG_ORF_PREFIX_SM)
2437 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2438 else if (flag == PEER_FLAG_ORF_PREFIX_RM)
2439 peer->last_reset = PEER_DOWN_CAPABILITY_CHANGE;
2440
2441 peer_change_action (peer, afi, safi, action.type);
2442 }
paul718e3742002-12-13 20:15:29 +00002443 }
2444 }
2445 }
2446 return 0;
2447}
2448
2449int
2450peer_af_flag_set (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2451{
2452 return peer_af_flag_modify (peer, afi, safi, flag, 1);
2453}
2454
2455int
2456peer_af_flag_unset (struct peer *peer, afi_t afi, safi_t safi, u_int32_t flag)
2457{
2458 return peer_af_flag_modify (peer, afi, safi, flag, 0);
2459}
2460
2461/* EBGP multihop configuration. */
2462int
2463peer_ebgp_multihop_set (struct peer *peer, int ttl)
2464{
2465 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002466 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002467
2468 if (peer_sort (peer) == BGP_PEER_IBGP)
2469 return 0;
2470
2471 peer->ttl = ttl;
2472
2473 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2474 {
pauleb821182004-05-01 08:44:08 +00002475 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2476 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002477 }
2478 else
2479 {
2480 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002481 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002482 {
2483 if (peer_sort (peer) == BGP_PEER_IBGP)
2484 continue;
paul718e3742002-12-13 20:15:29 +00002485
pauleb821182004-05-01 08:44:08 +00002486 peer->ttl = group->conf->ttl;
paul718e3742002-12-13 20:15:29 +00002487
pauleb821182004-05-01 08:44:08 +00002488 if (peer->fd >= 0)
2489 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2490 }
paul718e3742002-12-13 20:15:29 +00002491 }
2492 return 0;
2493}
2494
2495int
2496peer_ebgp_multihop_unset (struct peer *peer)
2497{
2498 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002499 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002500
2501 if (peer_sort (peer) == BGP_PEER_IBGP)
2502 return 0;
2503
2504 if (peer_group_active (peer))
2505 peer->ttl = peer->group->conf->ttl;
2506 else
2507 peer->ttl = 1;
2508
2509 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2510 {
pauleb821182004-05-01 08:44:08 +00002511 if (peer->fd >= 0 && peer_sort (peer) != BGP_PEER_IBGP)
2512 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
paul718e3742002-12-13 20:15:29 +00002513 }
2514 else
2515 {
2516 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002517 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
pauleb821182004-05-01 08:44:08 +00002518 {
2519 if (peer_sort (peer) == BGP_PEER_IBGP)
2520 continue;
paul718e3742002-12-13 20:15:29 +00002521
pauleb821182004-05-01 08:44:08 +00002522 peer->ttl = 1;
2523
2524 if (peer->fd >= 0)
2525 sockopt_ttl (peer->su.sa.sa_family, peer->fd, peer->ttl);
2526 }
paul718e3742002-12-13 20:15:29 +00002527 }
2528 return 0;
2529}
2530
2531/* Neighbor description. */
2532int
2533peer_description_set (struct peer *peer, char *desc)
2534{
2535 if (peer->desc)
2536 XFREE (MTYPE_PEER_DESC, peer->desc);
2537
2538 peer->desc = XSTRDUP (MTYPE_PEER_DESC, desc);
2539
2540 return 0;
2541}
2542
2543int
2544peer_description_unset (struct peer *peer)
2545{
2546 if (peer->desc)
2547 XFREE (MTYPE_PEER_DESC, peer->desc);
2548
2549 peer->desc = NULL;
2550
2551 return 0;
2552}
2553
2554/* Neighbor update-source. */
2555int
paulfd79ac92004-10-13 05:06:08 +00002556peer_update_source_if_set (struct peer *peer, const char *ifname)
paul718e3742002-12-13 20:15:29 +00002557{
2558 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002559 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002560
2561 if (peer->update_if)
2562 {
2563 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2564 && strcmp (peer->update_if, ifname) == 0)
2565 return 0;
2566
2567 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2568 peer->update_if = NULL;
2569 }
2570
2571 if (peer->update_source)
2572 {
2573 sockunion_free (peer->update_source);
2574 peer->update_source = NULL;
2575 }
2576
2577 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2578
2579 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2580 {
2581 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002582 {
2583 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2584 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2585 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2586 }
paul718e3742002-12-13 20:15:29 +00002587 else
2588 BGP_EVENT_ADD (peer, BGP_Stop);
2589 return 0;
2590 }
2591
2592 /* peer-group member updates. */
2593 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002594 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002595 {
2596 if (peer->update_if)
2597 {
2598 if (strcmp (peer->update_if, ifname) == 0)
2599 continue;
2600
2601 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2602 peer->update_if = NULL;
2603 }
2604
2605 if (peer->update_source)
2606 {
2607 sockunion_free (peer->update_source);
2608 peer->update_source = NULL;
2609 }
2610
2611 peer->update_if = XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, ifname);
2612
2613 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002614 {
2615 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2616 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2617 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2618 }
paul718e3742002-12-13 20:15:29 +00002619 else
2620 BGP_EVENT_ADD (peer, BGP_Stop);
2621 }
2622 return 0;
2623}
2624
2625int
2626peer_update_source_addr_set (struct peer *peer, union sockunion *su)
2627{
2628 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002629 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002630
2631 if (peer->update_source)
2632 {
2633 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2634 && sockunion_cmp (peer->update_source, su) == 0)
2635 return 0;
2636 sockunion_free (peer->update_source);
2637 peer->update_source = NULL;
2638 }
2639
2640 if (peer->update_if)
2641 {
2642 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2643 peer->update_if = NULL;
2644 }
2645
2646 peer->update_source = sockunion_dup (su);
2647
2648 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2649 {
2650 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002651 {
2652 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2653 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2654 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2655 }
paul718e3742002-12-13 20:15:29 +00002656 else
2657 BGP_EVENT_ADD (peer, BGP_Stop);
2658 return 0;
2659 }
2660
2661 /* peer-group member updates. */
2662 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002663 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002664 {
2665 if (peer->update_source)
2666 {
2667 if (sockunion_cmp (peer->update_source, su) == 0)
2668 continue;
2669 sockunion_free (peer->update_source);
2670 peer->update_source = NULL;
2671 }
2672
2673 if (peer->update_if)
2674 {
2675 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2676 peer->update_if = NULL;
2677 }
2678
2679 peer->update_source = sockunion_dup (su);
2680
2681 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002682 {
2683 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2684 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2685 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2686 }
paul718e3742002-12-13 20:15:29 +00002687 else
2688 BGP_EVENT_ADD (peer, BGP_Stop);
2689 }
2690 return 0;
2691}
2692
2693int
2694peer_update_source_unset (struct peer *peer)
2695{
2696 union sockunion *su;
2697 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002698 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002699
2700 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
2701 && ! peer->update_source
2702 && ! peer->update_if)
2703 return 0;
2704
2705 if (peer->update_source)
2706 {
2707 sockunion_free (peer->update_source);
2708 peer->update_source = NULL;
2709 }
2710 if (peer->update_if)
2711 {
2712 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2713 peer->update_if = NULL;
2714 }
2715
2716 if (peer_group_active (peer))
2717 {
2718 group = peer->group;
2719
2720 if (group->conf->update_source)
2721 {
2722 su = sockunion_dup (group->conf->update_source);
2723 peer->update_source = su;
2724 }
2725 else if (group->conf->update_if)
2726 peer->update_if =
2727 XSTRDUP (MTYPE_PEER_UPDATE_SOURCE, group->conf->update_if);
2728 }
2729
2730 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2731 {
2732 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002733 {
2734 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2735 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2736 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2737 }
paul718e3742002-12-13 20:15:29 +00002738 else
2739 BGP_EVENT_ADD (peer, BGP_Stop);
2740 return 0;
2741 }
2742
2743 /* peer-group member updates. */
2744 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002745 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002746 {
2747 if (! peer->update_source && ! peer->update_if)
2748 continue;
2749
2750 if (peer->update_source)
2751 {
2752 sockunion_free (peer->update_source);
2753 peer->update_source = NULL;
2754 }
2755
2756 if (peer->update_if)
2757 {
2758 XFREE (MTYPE_PEER_UPDATE_SOURCE, peer->update_if);
2759 peer->update_if = NULL;
2760 }
2761
2762 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00002763 {
2764 peer->last_reset = PEER_DOWN_UPDATE_SOURCE_CHANGE;
2765 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
2766 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
2767 }
paul718e3742002-12-13 20:15:29 +00002768 else
2769 BGP_EVENT_ADD (peer, BGP_Stop);
2770 }
2771 return 0;
2772}
2773
2774int
2775peer_default_originate_set (struct peer *peer, afi_t afi, safi_t safi,
paulfd79ac92004-10-13 05:06:08 +00002776 const char *rmap)
paul718e3742002-12-13 20:15:29 +00002777{
2778 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002779 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002780
2781 /* Adress family must be activated. */
2782 if (! peer->afc[afi][safi])
2783 return BGP_ERR_PEER_INACTIVE;
2784
2785 /* Default originate can't be used for peer group memeber. */
2786 if (peer_is_group_member (peer, afi, safi))
2787 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2788
2789 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)
2790 || (rmap && ! peer->default_rmap[afi][safi].name)
2791 || (rmap && strcmp (rmap, peer->default_rmap[afi][safi].name) != 0))
2792 {
2793 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2794
2795 if (rmap)
2796 {
2797 if (peer->default_rmap[afi][safi].name)
2798 free (peer->default_rmap[afi][safi].name);
2799 peer->default_rmap[afi][safi].name = strdup (rmap);
2800 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2801 }
2802 }
2803
2804 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2805 {
2806 if (peer->status == Established && peer->afc_nego[afi][safi])
2807 bgp_default_originate (peer, afi, safi, 0);
2808 return 0;
2809 }
2810
2811 /* peer-group member updates. */
2812 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002813 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002814 {
2815 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2816
2817 if (rmap)
2818 {
2819 if (peer->default_rmap[afi][safi].name)
2820 free (peer->default_rmap[afi][safi].name);
2821 peer->default_rmap[afi][safi].name = strdup (rmap);
2822 peer->default_rmap[afi][safi].map = route_map_lookup_by_name (rmap);
2823 }
2824
2825 if (peer->status == Established && peer->afc_nego[afi][safi])
2826 bgp_default_originate (peer, afi, safi, 0);
2827 }
2828 return 0;
2829}
2830
2831int
2832peer_default_originate_unset (struct peer *peer, afi_t afi, safi_t safi)
2833{
2834 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002835 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002836
2837 /* Adress family must be activated. */
2838 if (! peer->afc[afi][safi])
2839 return BGP_ERR_PEER_INACTIVE;
2840
2841 /* Default originate can't be used for peer group memeber. */
2842 if (peer_is_group_member (peer, afi, safi))
2843 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2844
2845 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE))
2846 {
2847 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2848
2849 if (peer->default_rmap[afi][safi].name)
2850 free (peer->default_rmap[afi][safi].name);
2851 peer->default_rmap[afi][safi].name = NULL;
2852 peer->default_rmap[afi][safi].map = NULL;
2853 }
2854
2855 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2856 {
2857 if (peer->status == Established && peer->afc_nego[afi][safi])
2858 bgp_default_originate (peer, afi, safi, 1);
2859 return 0;
2860 }
2861
2862 /* peer-group member updates. */
2863 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002864 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002865 {
2866 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE);
2867
2868 if (peer->default_rmap[afi][safi].name)
2869 free (peer->default_rmap[afi][safi].name);
2870 peer->default_rmap[afi][safi].name = NULL;
2871 peer->default_rmap[afi][safi].map = NULL;
2872
2873 if (peer->status == Established && peer->afc_nego[afi][safi])
2874 bgp_default_originate (peer, afi, safi, 1);
2875 }
2876 return 0;
2877}
2878
2879int
2880peer_port_set (struct peer *peer, u_int16_t port)
2881{
2882 peer->port = port;
2883 return 0;
2884}
2885
2886int
2887peer_port_unset (struct peer *peer)
2888{
2889 peer->port = BGP_PORT_DEFAULT;
2890 return 0;
2891}
2892
2893/* neighbor weight. */
2894int
2895peer_weight_set (struct peer *peer, u_int16_t weight)
2896{
2897 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002898 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002899
2900 SET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
2901 peer->weight = weight;
2902
2903 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2904 return 0;
2905
2906 /* peer-group member updates. */
2907 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002908 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002909 {
2910 peer->weight = group->conf->weight;
2911 }
2912 return 0;
2913}
2914
2915int
2916peer_weight_unset (struct peer *peer)
2917{
2918 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002919 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002920
2921 /* Set default weight. */
2922 if (peer_group_active (peer))
2923 peer->weight = peer->group->conf->weight;
2924 else
2925 peer->weight = 0;
2926
2927 UNSET_FLAG (peer->config, PEER_CONFIG_WEIGHT);
2928
2929 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2930 return 0;
2931
2932 /* peer-group member updates. */
2933 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002934 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002935 {
2936 peer->weight = 0;
2937 }
2938 return 0;
2939}
2940
2941int
2942peer_timers_set (struct peer *peer, u_int32_t keepalive, u_int32_t holdtime)
2943{
2944 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002945 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002946
2947 /* Not for peer group memeber. */
2948 if (peer_group_active (peer))
2949 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2950
2951 /* keepalive value check. */
2952 if (keepalive > 65535)
2953 return BGP_ERR_INVALID_VALUE;
2954
2955 /* Holdtime value check. */
2956 if (holdtime > 65535)
2957 return BGP_ERR_INVALID_VALUE;
2958
2959 /* Holdtime value must be either 0 or greater than 3. */
2960 if (holdtime < 3 && holdtime != 0)
2961 return BGP_ERR_INVALID_VALUE;
2962
2963 /* Set value to the configuration. */
2964 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
2965 peer->holdtime = holdtime;
2966 peer->keepalive = (keepalive < holdtime / 3 ? keepalive : holdtime / 3);
2967
2968 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2969 return 0;
2970
2971 /* peer-group member updates. */
2972 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00002973 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00002974 {
2975 SET_FLAG (peer->config, PEER_CONFIG_TIMER);
2976 peer->holdtime = group->conf->holdtime;
2977 peer->keepalive = group->conf->keepalive;
2978 }
2979 return 0;
2980}
2981
2982int
2983peer_timers_unset (struct peer *peer)
2984{
2985 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00002986 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00002987
2988 if (peer_group_active (peer))
2989 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
2990
2991 /* Clear configuration. */
2992 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
2993 peer->keepalive = 0;
2994 peer->holdtime = 0;
2995
2996 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
2997 return 0;
2998
2999 /* peer-group member updates. */
3000 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003001 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003002 {
3003 UNSET_FLAG (peer->config, PEER_CONFIG_TIMER);
3004 peer->holdtime = 0;
3005 peer->keepalive = 0;
3006 }
3007
3008 return 0;
3009}
3010
3011int
3012peer_timers_connect_set (struct peer *peer, u_int32_t connect)
3013{
3014 if (peer_group_active (peer))
3015 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3016
3017 if (connect > 65535)
3018 return BGP_ERR_INVALID_VALUE;
3019
3020 /* Set value to the configuration. */
3021 SET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3022 peer->connect = connect;
3023
3024 /* Set value to timer setting. */
3025 peer->v_connect = connect;
3026
3027 return 0;
3028}
3029
3030int
3031peer_timers_connect_unset (struct peer *peer)
3032{
3033 if (peer_group_active (peer))
3034 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3035
3036 /* Clear configuration. */
3037 UNSET_FLAG (peer->config, PEER_CONFIG_CONNECT);
3038 peer->connect = 0;
3039
3040 /* Set timer setting to default value. */
3041 peer->v_connect = BGP_DEFAULT_CONNECT_RETRY;
3042
3043 return 0;
3044}
3045
3046int
3047peer_advertise_interval_set (struct peer *peer, u_int32_t routeadv)
3048{
3049 if (peer_group_active (peer))
3050 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3051
3052 if (routeadv > 600)
3053 return BGP_ERR_INVALID_VALUE;
3054
3055 SET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3056 peer->routeadv = routeadv;
3057 peer->v_routeadv = routeadv;
3058
3059 return 0;
3060}
3061
3062int
3063peer_advertise_interval_unset (struct peer *peer)
3064{
3065 if (peer_group_active (peer))
3066 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3067
3068 UNSET_FLAG (peer->config, PEER_CONFIG_ROUTEADV);
3069 peer->routeadv = 0;
3070
3071 if (peer_sort (peer) == BGP_PEER_IBGP)
3072 peer->v_routeadv = BGP_DEFAULT_IBGP_ROUTEADV;
3073 else
3074 peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
3075
3076 return 0;
3077}
3078
paul718e3742002-12-13 20:15:29 +00003079/* neighbor interface */
3080int
paulfd79ac92004-10-13 05:06:08 +00003081peer_interface_set (struct peer *peer, const char *str)
paul718e3742002-12-13 20:15:29 +00003082{
3083 if (peer->ifname)
3084 free (peer->ifname);
3085 peer->ifname = strdup (str);
3086
3087 return 0;
3088}
3089
3090int
3091peer_interface_unset (struct peer *peer)
3092{
3093 if (peer->ifname)
3094 free (peer->ifname);
3095 peer->ifname = NULL;
3096
3097 return 0;
3098}
3099
3100/* Allow-as in. */
3101int
3102peer_allowas_in_set (struct peer *peer, afi_t afi, safi_t safi, int allow_num)
3103{
3104 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003105 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003106
3107 if (allow_num < 1 || allow_num > 10)
3108 return BGP_ERR_INVALID_VALUE;
3109
3110 if (peer->allowas_in[afi][safi] != allow_num)
3111 {
3112 peer->allowas_in[afi][safi] = allow_num;
3113 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3114 peer_change_action (peer, afi, safi, peer_change_reset_in);
3115 }
3116
3117 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3118 return 0;
3119
3120 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003121 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003122 {
3123 if (peer->allowas_in[afi][safi] != allow_num)
3124 {
3125 peer->allowas_in[afi][safi] = allow_num;
3126 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN);
3127 peer_change_action (peer, afi, safi, peer_change_reset_in);
3128 }
3129
3130 }
3131 return 0;
3132}
3133
3134int
3135peer_allowas_in_unset (struct peer *peer, afi_t afi, safi_t safi)
3136{
3137 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003138 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003139
3140 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3141 {
3142 peer->allowas_in[afi][safi] = 0;
3143 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3144 }
3145
3146 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3147 return 0;
3148
3149 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003150 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003151 {
3152 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ALLOWAS_IN))
3153 {
3154 peer->allowas_in[afi][safi] = 0;
3155 peer_af_flag_unset (peer, afi, safi, PEER_FLAG_ALLOWAS_IN);
3156 }
3157 }
3158 return 0;
3159}
3160
3161int
3162peer_local_as_set (struct peer *peer, as_t as, int no_prepend)
3163{
3164 struct bgp *bgp = peer->bgp;
3165 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003166 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003167
3168 if (peer_sort (peer) != BGP_PEER_EBGP
3169 && peer_sort (peer) != BGP_PEER_INTERNAL)
3170 return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
3171
3172 if (bgp->as == as)
3173 return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
3174
3175 if (peer_group_active (peer))
3176 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3177
3178 if (peer->change_local_as == as &&
3179 ((CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && no_prepend)
3180 || (! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) && ! no_prepend)))
3181 return 0;
3182
3183 peer->change_local_as = as;
3184 if (no_prepend)
3185 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3186 else
3187 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3188
3189 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3190 {
3191 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003192 {
3193 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3194 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3195 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3196 }
paul718e3742002-12-13 20:15:29 +00003197 else
3198 BGP_EVENT_ADD (peer, BGP_Stop);
3199
3200 return 0;
3201 }
3202
3203 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003204 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003205 {
3206 peer->change_local_as = as;
3207 if (no_prepend)
3208 SET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3209 else
3210 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3211
3212 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003213 {
3214 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3215 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3216 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3217 }
paul718e3742002-12-13 20:15:29 +00003218 else
3219 BGP_EVENT_ADD (peer, BGP_Stop);
3220 }
3221
3222 return 0;
3223}
3224
3225int
3226peer_local_as_unset (struct peer *peer)
3227{
3228 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003229 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003230
3231 if (peer_group_active (peer))
3232 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3233
3234 if (! peer->change_local_as)
3235 return 0;
3236
3237 peer->change_local_as = 0;
3238 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3239
3240 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3241 {
3242 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003243 {
3244 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3245 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3246 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3247 }
paul718e3742002-12-13 20:15:29 +00003248 else
3249 BGP_EVENT_ADD (peer, BGP_Stop);
3250
3251 return 0;
3252 }
3253
3254 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003255 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003256 {
3257 peer->change_local_as = 0;
3258 UNSET_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
3259
3260 if (peer->status == Established)
hassoe0701b72004-05-20 09:19:34 +00003261 {
3262 peer->last_reset = PEER_DOWN_LOCAL_AS_CHANGE;
3263 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
3264 BGP_NOTIFY_CEASE_CONFIG_CHANGE);
3265 }
paul718e3742002-12-13 20:15:29 +00003266 else
3267 BGP_EVENT_ADD (peer, BGP_Stop);
3268 }
3269 return 0;
3270}
3271
3272/* Set distribute list to the peer. */
3273int
3274peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003275 const char *name)
paul718e3742002-12-13 20:15:29 +00003276{
3277 struct bgp_filter *filter;
3278 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003279 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003280
3281 if (! peer->afc[afi][safi])
3282 return BGP_ERR_PEER_INACTIVE;
3283
3284 if (direct != FILTER_IN && direct != FILTER_OUT)
3285 return BGP_ERR_INVALID_VALUE;
3286
3287 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3288 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3289
3290 filter = &peer->filter[afi][safi];
3291
3292 if (filter->plist[direct].name)
3293 return BGP_ERR_PEER_FILTER_CONFLICT;
3294
3295 if (filter->dlist[direct].name)
3296 free (filter->dlist[direct].name);
3297 filter->dlist[direct].name = strdup (name);
3298 filter->dlist[direct].alist = access_list_lookup (afi, name);
3299
3300 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3301 return 0;
3302
3303 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003304 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003305 {
3306 filter = &peer->filter[afi][safi];
3307
3308 if (! peer->af_group[afi][safi])
3309 continue;
3310
3311 if (filter->dlist[direct].name)
3312 free (filter->dlist[direct].name);
3313 filter->dlist[direct].name = strdup (name);
3314 filter->dlist[direct].alist = access_list_lookup (afi, name);
3315 }
3316
3317 return 0;
3318}
3319
3320int
3321peer_distribute_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3322{
3323 struct bgp_filter *filter;
3324 struct bgp_filter *gfilter;
3325 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003326 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003327
3328 if (! peer->afc[afi][safi])
3329 return BGP_ERR_PEER_INACTIVE;
3330
3331 if (direct != FILTER_IN && direct != FILTER_OUT)
3332 return BGP_ERR_INVALID_VALUE;
3333
3334 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3335 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3336
3337 filter = &peer->filter[afi][safi];
3338
3339 /* apply peer-group filter */
3340 if (peer->af_group[afi][safi])
3341 {
3342 gfilter = &peer->group->conf->filter[afi][safi];
3343
3344 if (gfilter->dlist[direct].name)
3345 {
3346 if (filter->dlist[direct].name)
3347 free (filter->dlist[direct].name);
3348 filter->dlist[direct].name = strdup (gfilter->dlist[direct].name);
3349 filter->dlist[direct].alist = gfilter->dlist[direct].alist;
3350 return 0;
3351 }
3352 }
3353
3354 if (filter->dlist[direct].name)
3355 free (filter->dlist[direct].name);
3356 filter->dlist[direct].name = NULL;
3357 filter->dlist[direct].alist = NULL;
3358
3359 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3360 return 0;
3361
3362 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003363 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003364 {
3365 filter = &peer->filter[afi][safi];
3366
3367 if (! peer->af_group[afi][safi])
3368 continue;
3369
3370 if (filter->dlist[direct].name)
3371 free (filter->dlist[direct].name);
3372 filter->dlist[direct].name = NULL;
3373 filter->dlist[direct].alist = NULL;
3374 }
3375
3376 return 0;
3377}
3378
3379/* Update distribute list. */
3380void
3381peer_distribute_update (struct access_list *access)
3382{
3383 afi_t afi;
3384 safi_t safi;
3385 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003386 struct listnode *mnode, *mnnode;
3387 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003388 struct bgp *bgp;
3389 struct peer *peer;
3390 struct peer_group *group;
3391 struct bgp_filter *filter;
3392
paul1eb8ef22005-04-07 07:30:20 +00003393 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003394 {
paul1eb8ef22005-04-07 07:30:20 +00003395 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003396 {
3397 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3398 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3399 {
3400 filter = &peer->filter[afi][safi];
3401
3402 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3403 {
3404 if (filter->dlist[direct].name)
3405 filter->dlist[direct].alist =
3406 access_list_lookup (afi, filter->dlist[direct].name);
3407 else
3408 filter->dlist[direct].alist = NULL;
3409 }
3410 }
3411 }
paul1eb8ef22005-04-07 07:30:20 +00003412 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003413 {
3414 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3415 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3416 {
3417 filter = &group->conf->filter[afi][safi];
3418
3419 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3420 {
3421 if (filter->dlist[direct].name)
3422 filter->dlist[direct].alist =
3423 access_list_lookup (afi, filter->dlist[direct].name);
3424 else
3425 filter->dlist[direct].alist = NULL;
3426 }
3427 }
3428 }
3429 }
3430}
3431
3432/* Set prefix list to the peer. */
3433int
3434peer_prefix_list_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003435 const char *name)
paul718e3742002-12-13 20:15:29 +00003436{
3437 struct bgp_filter *filter;
3438 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003439 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003440
3441 if (! peer->afc[afi][safi])
3442 return BGP_ERR_PEER_INACTIVE;
3443
3444 if (direct != FILTER_IN && direct != FILTER_OUT)
3445 return BGP_ERR_INVALID_VALUE;
3446
3447 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3448 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3449
3450 filter = &peer->filter[afi][safi];
3451
3452 if (filter->dlist[direct].name)
3453 return BGP_ERR_PEER_FILTER_CONFLICT;
3454
3455 if (filter->plist[direct].name)
3456 free (filter->plist[direct].name);
3457 filter->plist[direct].name = strdup (name);
3458 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3459
3460 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3461 return 0;
3462
3463 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003464 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003465 {
3466 filter = &peer->filter[afi][safi];
3467
3468 if (! peer->af_group[afi][safi])
3469 continue;
3470
3471 if (filter->plist[direct].name)
3472 free (filter->plist[direct].name);
3473 filter->plist[direct].name = strdup (name);
3474 filter->plist[direct].plist = prefix_list_lookup (afi, name);
3475 }
3476 return 0;
3477}
3478
3479int
3480peer_prefix_list_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3481{
3482 struct bgp_filter *filter;
3483 struct bgp_filter *gfilter;
3484 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003485 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003486
3487 if (! peer->afc[afi][safi])
3488 return BGP_ERR_PEER_INACTIVE;
3489
3490 if (direct != FILTER_IN && direct != FILTER_OUT)
3491 return BGP_ERR_INVALID_VALUE;
3492
3493 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3494 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3495
3496 filter = &peer->filter[afi][safi];
3497
3498 /* apply peer-group filter */
3499 if (peer->af_group[afi][safi])
3500 {
3501 gfilter = &peer->group->conf->filter[afi][safi];
3502
3503 if (gfilter->plist[direct].name)
3504 {
3505 if (filter->plist[direct].name)
3506 free (filter->plist[direct].name);
3507 filter->plist[direct].name = strdup (gfilter->plist[direct].name);
3508 filter->plist[direct].plist = gfilter->plist[direct].plist;
3509 return 0;
3510 }
3511 }
3512
3513 if (filter->plist[direct].name)
3514 free (filter->plist[direct].name);
3515 filter->plist[direct].name = NULL;
3516 filter->plist[direct].plist = NULL;
3517
3518 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3519 return 0;
3520
3521 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003522 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003523 {
3524 filter = &peer->filter[afi][safi];
3525
3526 if (! peer->af_group[afi][safi])
3527 continue;
3528
3529 if (filter->plist[direct].name)
3530 free (filter->plist[direct].name);
3531 filter->plist[direct].name = NULL;
3532 filter->plist[direct].plist = NULL;
3533 }
3534
3535 return 0;
3536}
3537
3538/* Update prefix-list list. */
3539void
3540peer_prefix_list_update (struct prefix_list *plist)
3541{
paul1eb8ef22005-04-07 07:30:20 +00003542 struct listnode *mnode, *mnnode;
3543 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003544 struct bgp *bgp;
3545 struct peer *peer;
3546 struct peer_group *group;
3547 struct bgp_filter *filter;
3548 afi_t afi;
3549 safi_t safi;
3550 int direct;
3551
paul1eb8ef22005-04-07 07:30:20 +00003552 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003553 {
paul1eb8ef22005-04-07 07:30:20 +00003554 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003555 {
3556 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3557 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3558 {
3559 filter = &peer->filter[afi][safi];
3560
3561 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3562 {
3563 if (filter->plist[direct].name)
3564 filter->plist[direct].plist =
3565 prefix_list_lookup (afi, filter->plist[direct].name);
3566 else
3567 filter->plist[direct].plist = NULL;
3568 }
3569 }
3570 }
paul1eb8ef22005-04-07 07:30:20 +00003571 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003572 {
3573 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3574 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3575 {
3576 filter = &group->conf->filter[afi][safi];
3577
3578 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3579 {
3580 if (filter->plist[direct].name)
3581 filter->plist[direct].plist =
3582 prefix_list_lookup (afi, filter->plist[direct].name);
3583 else
3584 filter->plist[direct].plist = NULL;
3585 }
3586 }
3587 }
3588 }
3589}
3590
3591int
3592peer_aslist_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003593 const char *name)
paul718e3742002-12-13 20:15:29 +00003594{
3595 struct bgp_filter *filter;
3596 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003597 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003598
3599 if (! peer->afc[afi][safi])
3600 return BGP_ERR_PEER_INACTIVE;
3601
3602 if (direct != FILTER_IN && direct != FILTER_OUT)
3603 return BGP_ERR_INVALID_VALUE;
3604
3605 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3606 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3607
3608 filter = &peer->filter[afi][safi];
3609
3610 if (filter->aslist[direct].name)
3611 free (filter->aslist[direct].name);
3612 filter->aslist[direct].name = strdup (name);
3613 filter->aslist[direct].aslist = as_list_lookup (name);
3614
3615 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3616 return 0;
3617
3618 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003619 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003620 {
3621 filter = &peer->filter[afi][safi];
3622
3623 if (! peer->af_group[afi][safi])
3624 continue;
3625
3626 if (filter->aslist[direct].name)
3627 free (filter->aslist[direct].name);
3628 filter->aslist[direct].name = strdup (name);
3629 filter->aslist[direct].aslist = as_list_lookup (name);
3630 }
3631 return 0;
3632}
3633
3634int
3635peer_aslist_unset (struct peer *peer,afi_t afi, safi_t safi, int direct)
3636{
3637 struct bgp_filter *filter;
3638 struct bgp_filter *gfilter;
3639 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003640 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003641
3642 if (! peer->afc[afi][safi])
3643 return BGP_ERR_PEER_INACTIVE;
3644
paulfee0f4c2004-09-13 05:12:46 +00003645 if (direct != RMAP_IN && direct != RMAP_OUT &&
3646 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003647 return BGP_ERR_INVALID_VALUE;
3648
paulfee0f4c2004-09-13 05:12:46 +00003649 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
3650 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003651 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3652
3653 filter = &peer->filter[afi][safi];
3654
3655 /* apply peer-group filter */
3656 if (peer->af_group[afi][safi])
3657 {
3658 gfilter = &peer->group->conf->filter[afi][safi];
3659
3660 if (gfilter->aslist[direct].name)
3661 {
3662 if (filter->aslist[direct].name)
3663 free (filter->aslist[direct].name);
3664 filter->aslist[direct].name = strdup (gfilter->aslist[direct].name);
3665 filter->aslist[direct].aslist = gfilter->aslist[direct].aslist;
3666 return 0;
3667 }
3668 }
3669
3670 if (filter->aslist[direct].name)
3671 free (filter->aslist[direct].name);
3672 filter->aslist[direct].name = NULL;
3673 filter->aslist[direct].aslist = NULL;
3674
3675 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3676 return 0;
3677
3678 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003679 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003680 {
3681 filter = &peer->filter[afi][safi];
3682
3683 if (! peer->af_group[afi][safi])
3684 continue;
3685
3686 if (filter->aslist[direct].name)
3687 free (filter->aslist[direct].name);
3688 filter->aslist[direct].name = NULL;
3689 filter->aslist[direct].aslist = NULL;
3690 }
3691
3692 return 0;
3693}
3694
3695void
3696peer_aslist_update ()
3697{
3698 afi_t afi;
3699 safi_t safi;
3700 int direct;
paul1eb8ef22005-04-07 07:30:20 +00003701 struct listnode *mnode, *mnnode;
3702 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003703 struct bgp *bgp;
3704 struct peer *peer;
3705 struct peer_group *group;
3706 struct bgp_filter *filter;
3707
paul1eb8ef22005-04-07 07:30:20 +00003708 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00003709 {
paul1eb8ef22005-04-07 07:30:20 +00003710 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003711 {
3712 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3713 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3714 {
3715 filter = &peer->filter[afi][safi];
3716
3717 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3718 {
3719 if (filter->aslist[direct].name)
3720 filter->aslist[direct].aslist =
3721 as_list_lookup (filter->aslist[direct].name);
3722 else
3723 filter->aslist[direct].aslist = NULL;
3724 }
3725 }
3726 }
paul1eb8ef22005-04-07 07:30:20 +00003727 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00003728 {
3729 for (afi = AFI_IP; afi < AFI_MAX; afi++)
3730 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
3731 {
3732 filter = &group->conf->filter[afi][safi];
3733
3734 for (direct = FILTER_IN; direct < FILTER_MAX; direct++)
3735 {
3736 if (filter->aslist[direct].name)
3737 filter->aslist[direct].aslist =
3738 as_list_lookup (filter->aslist[direct].name);
3739 else
3740 filter->aslist[direct].aslist = NULL;
3741 }
3742 }
3743 }
3744 }
3745}
3746
3747/* Set route-map to the peer. */
3748int
3749peer_route_map_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
paulfd79ac92004-10-13 05:06:08 +00003750 const char *name)
paul718e3742002-12-13 20:15:29 +00003751{
3752 struct bgp_filter *filter;
3753 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003754 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003755
3756 if (! peer->afc[afi][safi])
3757 return BGP_ERR_PEER_INACTIVE;
3758
paulfee0f4c2004-09-13 05:12:46 +00003759 if (direct != RMAP_IN && direct != RMAP_OUT &&
3760 direct != RMAP_IMPORT && direct != RMAP_EXPORT)
paul718e3742002-12-13 20:15:29 +00003761 return BGP_ERR_INVALID_VALUE;
3762
paulfee0f4c2004-09-13 05:12:46 +00003763 if ( (direct == RMAP_OUT || direct == RMAP_IMPORT)
3764 && peer_is_group_member (peer, afi, safi))
paul718e3742002-12-13 20:15:29 +00003765 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3766
3767 filter = &peer->filter[afi][safi];
3768
3769 if (filter->map[direct].name)
3770 free (filter->map[direct].name);
3771
3772 filter->map[direct].name = strdup (name);
3773 filter->map[direct].map = route_map_lookup_by_name (name);
3774
3775 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3776 return 0;
3777
3778 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003779 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003780 {
3781 filter = &peer->filter[afi][safi];
3782
3783 if (! peer->af_group[afi][safi])
3784 continue;
3785
3786 if (filter->map[direct].name)
3787 free (filter->map[direct].name);
3788 filter->map[direct].name = strdup (name);
3789 filter->map[direct].map = route_map_lookup_by_name (name);
3790 }
3791 return 0;
3792}
3793
3794/* Unset route-map from the peer. */
3795int
3796peer_route_map_unset (struct peer *peer, afi_t afi, safi_t safi, int direct)
3797{
3798 struct bgp_filter *filter;
3799 struct bgp_filter *gfilter;
3800 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003801 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003802
3803 if (! peer->afc[afi][safi])
3804 return BGP_ERR_PEER_INACTIVE;
3805
3806 if (direct != FILTER_IN && direct != FILTER_OUT)
3807 return BGP_ERR_INVALID_VALUE;
3808
3809 if (direct == FILTER_OUT && peer_is_group_member (peer, afi, safi))
3810 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3811
3812 filter = &peer->filter[afi][safi];
3813
3814 /* apply peer-group filter */
3815 if (peer->af_group[afi][safi])
3816 {
3817 gfilter = &peer->group->conf->filter[afi][safi];
3818
3819 if (gfilter->map[direct].name)
3820 {
3821 if (filter->map[direct].name)
3822 free (filter->map[direct].name);
3823 filter->map[direct].name = strdup (gfilter->map[direct].name);
3824 filter->map[direct].map = gfilter->map[direct].map;
3825 return 0;
3826 }
3827 }
3828
3829 if (filter->map[direct].name)
3830 free (filter->map[direct].name);
3831 filter->map[direct].name = NULL;
3832 filter->map[direct].map = NULL;
3833
3834 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3835 return 0;
3836
3837 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003838 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003839 {
3840 filter = &peer->filter[afi][safi];
3841
3842 if (! peer->af_group[afi][safi])
3843 continue;
3844
3845 if (filter->map[direct].name)
3846 free (filter->map[direct].name);
3847 filter->map[direct].name = NULL;
3848 filter->map[direct].map = NULL;
3849 }
3850 return 0;
3851}
3852
3853/* Set unsuppress-map to the peer. */
3854int
paulfd79ac92004-10-13 05:06:08 +00003855peer_unsuppress_map_set (struct peer *peer, afi_t afi, safi_t safi,
3856 const char *name)
paul718e3742002-12-13 20:15:29 +00003857{
3858 struct bgp_filter *filter;
3859 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003860 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003861
3862 if (! peer->afc[afi][safi])
3863 return BGP_ERR_PEER_INACTIVE;
3864
3865 if (peer_is_group_member (peer, afi, safi))
3866 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3867
3868 filter = &peer->filter[afi][safi];
3869
3870 if (filter->usmap.name)
3871 free (filter->usmap.name);
3872
3873 filter->usmap.name = strdup (name);
3874 filter->usmap.map = route_map_lookup_by_name (name);
3875
3876 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3877 return 0;
3878
3879 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003880 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003881 {
3882 filter = &peer->filter[afi][safi];
3883
3884 if (! peer->af_group[afi][safi])
3885 continue;
3886
3887 if (filter->usmap.name)
3888 free (filter->usmap.name);
3889 filter->usmap.name = strdup (name);
3890 filter->usmap.map = route_map_lookup_by_name (name);
3891 }
3892 return 0;
3893}
3894
3895/* Unset route-map from the peer. */
3896int
3897peer_unsuppress_map_unset (struct peer *peer, afi_t afi, safi_t safi)
3898{
3899 struct bgp_filter *filter;
3900 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003901 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003902
3903 if (! peer->afc[afi][safi])
3904 return BGP_ERR_PEER_INACTIVE;
3905
3906 if (peer_is_group_member (peer, afi, safi))
3907 return BGP_ERR_INVALID_FOR_PEER_GROUP_MEMBER;
3908
3909 filter = &peer->filter[afi][safi];
3910
3911 if (filter->usmap.name)
3912 free (filter->usmap.name);
3913 filter->usmap.name = NULL;
3914 filter->usmap.map = NULL;
3915
3916 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3917 return 0;
3918
3919 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003920 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003921 {
3922 filter = &peer->filter[afi][safi];
3923
3924 if (! peer->af_group[afi][safi])
3925 continue;
3926
3927 if (filter->usmap.name)
3928 free (filter->usmap.name);
3929 filter->usmap.name = NULL;
3930 filter->usmap.map = NULL;
3931 }
3932 return 0;
3933}
3934
3935int
3936peer_maximum_prefix_set (struct peer *peer, afi_t afi, safi_t safi,
hasso0a486e52005-02-01 20:57:17 +00003937 u_int32_t max, u_char threshold,
3938 int warning, u_int16_t restart)
paul718e3742002-12-13 20:15:29 +00003939{
3940 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003941 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003942
3943 if (! peer->afc[afi][safi])
3944 return BGP_ERR_PEER_INACTIVE;
3945
3946 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3947 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00003948 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00003949 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00003950 if (warning)
3951 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3952 else
3953 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3954
3955 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
3956 return 0;
3957
3958 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00003959 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00003960 {
3961 if (! peer->af_group[afi][safi])
3962 continue;
3963
3964 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3965 peer->pmax[afi][safi] = max;
hassoe0701b72004-05-20 09:19:34 +00003966 peer->pmax_threshold[afi][safi] = threshold;
hasso0a486e52005-02-01 20:57:17 +00003967 peer->pmax_restart[afi][safi] = restart;
paul718e3742002-12-13 20:15:29 +00003968 if (warning)
3969 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3970 else
3971 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3972 }
3973 return 0;
3974}
3975
3976int
3977peer_maximum_prefix_unset (struct peer *peer, afi_t afi, safi_t safi)
3978{
3979 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00003980 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00003981
3982 if (! peer->afc[afi][safi])
3983 return BGP_ERR_PEER_INACTIVE;
3984
3985 /* apply peer-group config */
3986 if (peer->af_group[afi][safi])
3987 {
3988 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
3989 PEER_FLAG_MAX_PREFIX))
3990 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3991 else
3992 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
3993
3994 if (CHECK_FLAG (peer->group->conf->af_flags[afi][safi],
3995 PEER_FLAG_MAX_PREFIX_WARNING))
3996 SET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3997 else
3998 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
3999
4000 peer->pmax[afi][safi] = peer->group->conf->pmax[afi][safi];
hassoe0701b72004-05-20 09:19:34 +00004001 peer->pmax_threshold[afi][safi] = peer->group->conf->pmax_threshold[afi][safi];
hasso0a486e52005-02-01 20:57:17 +00004002 peer->pmax_restart[afi][safi] = peer->group->conf->pmax_restart[afi][safi];
paul718e3742002-12-13 20:15:29 +00004003 return 0;
4004 }
4005
4006 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4007 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4008 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004009 peer->pmax_threshold[afi][safi] = 0;
4010 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004011
4012 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4013 return 0;
4014
4015 group = peer->group;
paul1eb8ef22005-04-07 07:30:20 +00004016 for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004017 {
4018 if (! peer->af_group[afi][safi])
4019 continue;
4020
4021 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX);
4022 UNSET_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING);
4023 peer->pmax[afi][safi] = 0;
hasso0a486e52005-02-01 20:57:17 +00004024 peer->pmax_threshold[afi][safi] = 0;
4025 peer->pmax_restart[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00004026 }
4027 return 0;
4028}
4029
4030int
4031peer_clear (struct peer *peer)
4032{
4033 if (! CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4034 {
hasso0a486e52005-02-01 20:57:17 +00004035 if (CHECK_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
4036 {
4037 UNSET_FLAG (peer->sflags, PEER_STATUS_PREFIX_OVERFLOW);
4038 if (peer->t_pmax_restart)
4039 {
4040 BGP_TIMER_OFF (peer->t_pmax_restart);
4041 if (BGP_DEBUG (events, EVENTS))
4042 zlog_debug ("%s Maximum-prefix restart timer canceled",
4043 peer->host);
4044 }
4045 BGP_EVENT_ADD (peer, BGP_Start);
4046 return 0;
4047 }
4048
paul718e3742002-12-13 20:15:29 +00004049 peer->v_start = BGP_INIT_START_TIMER;
4050 if (peer->status == Established)
4051 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4052 BGP_NOTIFY_CEASE_ADMIN_RESET);
4053 else
4054 BGP_EVENT_ADD (peer, BGP_Stop);
4055 }
4056 return 0;
4057}
4058
4059int
4060peer_clear_soft (struct peer *peer, afi_t afi, safi_t safi,
4061 enum bgp_clear_type stype)
4062{
4063 if (peer->status != Established)
4064 return 0;
4065
4066 if (! peer->afc[afi][safi])
4067 return BGP_ERR_AF_UNCONFIGURED;
4068
paulfee0f4c2004-09-13 05:12:46 +00004069 if (stype == BGP_CLEAR_SOFT_RSCLIENT)
4070 {
4071 if (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))
4072 return 0;
4073 bgp_check_local_routes_rsclient (peer, afi, safi);
4074 bgp_soft_reconfig_rsclient (peer, afi, safi);
4075 }
4076
paul718e3742002-12-13 20:15:29 +00004077 if (stype == BGP_CLEAR_SOFT_OUT || stype == BGP_CLEAR_SOFT_BOTH)
4078 bgp_announce_route (peer, afi, safi);
4079
4080 if (stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4081 {
4082 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV)
4083 && (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV)
4084 || CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
4085 {
4086 struct bgp_filter *filter = &peer->filter[afi][safi];
4087 u_char prefix_type;
4088
4089 if (CHECK_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_RCV))
4090 prefix_type = ORF_TYPE_PREFIX;
4091 else
4092 prefix_type = ORF_TYPE_PREFIX_OLD;
4093
4094 if (filter->plist[FILTER_IN].plist)
4095 {
4096 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4097 bgp_route_refresh_send (peer, afi, safi,
4098 prefix_type, REFRESH_DEFER, 1);
4099 bgp_route_refresh_send (peer, afi, safi, prefix_type,
4100 REFRESH_IMMEDIATE, 0);
4101 }
4102 else
4103 {
4104 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND))
4105 bgp_route_refresh_send (peer, afi, safi,
4106 prefix_type, REFRESH_IMMEDIATE, 1);
4107 else
4108 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4109 }
4110 return 0;
4111 }
4112 }
4113
4114 if (stype == BGP_CLEAR_SOFT_IN || stype == BGP_CLEAR_SOFT_BOTH
4115 || stype == BGP_CLEAR_SOFT_IN_ORF_PREFIX)
4116 {
4117 /* If neighbor has soft reconfiguration inbound flag.
4118 Use Adj-RIB-In database. */
4119 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4120 bgp_soft_reconfig_in (peer, afi, safi);
4121 else
4122 {
4123 /* If neighbor has route refresh capability, send route refresh
4124 message to the peer. */
4125 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV)
4126 || CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
4127 bgp_route_refresh_send (peer, afi, safi, 0, 0, 0);
4128 else
4129 return BGP_ERR_SOFT_RECONFIG_UNCONFIGURED;
4130 }
4131 }
4132 return 0;
4133}
4134
paulfd79ac92004-10-13 05:06:08 +00004135/* Display peer uptime.*/
4136/* XXX: why does this function return char * when it takes buffer? */
paul718e3742002-12-13 20:15:29 +00004137char *
4138peer_uptime (time_t uptime2, char *buf, size_t len)
4139{
4140 time_t uptime1;
4141 struct tm *tm;
4142
4143 /* Check buffer length. */
4144 if (len < BGP_UPTIME_LEN)
4145 {
gdtc29fdba2004-12-09 14:46:46 +00004146 /* XXX: warning: long int format, size_t arg (arg 2) */
paula2b1ecd2004-10-31 18:58:09 +00004147 zlog_warn ("peer_uptime (): buffer shortage %ld", len);
paulfd79ac92004-10-13 05:06:08 +00004148 /* XXX: should return status instead of buf... */
4149 snprintf (buf, len, "<error> ");
4150 return buf;
paul718e3742002-12-13 20:15:29 +00004151 }
4152
4153 /* If there is no connection has been done before print `never'. */
4154 if (uptime2 == 0)
4155 {
4156 snprintf (buf, len, "never ");
4157 return buf;
4158 }
4159
4160 /* Get current time. */
4161 uptime1 = time (NULL);
4162 uptime1 -= uptime2;
4163 tm = gmtime (&uptime1);
4164
4165 /* Making formatted timer strings. */
4166#define ONE_DAY_SECOND 60*60*24
4167#define ONE_WEEK_SECOND 60*60*24*7
4168
4169 if (uptime1 < ONE_DAY_SECOND)
4170 snprintf (buf, len, "%02d:%02d:%02d",
4171 tm->tm_hour, tm->tm_min, tm->tm_sec);
4172 else if (uptime1 < ONE_WEEK_SECOND)
4173 snprintf (buf, len, "%dd%02dh%02dm",
4174 tm->tm_yday, tm->tm_hour, tm->tm_min);
4175 else
4176 snprintf (buf, len, "%02dw%dd%02dh",
4177 tm->tm_yday/7, tm->tm_yday - ((tm->tm_yday/7) * 7), tm->tm_hour);
4178 return buf;
4179}
4180
4181void
4182bgp_config_write_filter (struct vty *vty, struct peer *peer,
4183 afi_t afi, safi_t safi)
4184{
4185 struct bgp_filter *filter;
4186 struct bgp_filter *gfilter = NULL;
4187 char *addr;
4188 int in = FILTER_IN;
4189 int out = FILTER_OUT;
4190
4191 addr = peer->host;
4192 filter = &peer->filter[afi][safi];
4193 if (peer->af_group[afi][safi])
4194 gfilter = &peer->group->conf->filter[afi][safi];
4195
4196 /* distribute-list. */
4197 if (filter->dlist[in].name)
4198 if (! gfilter || ! gfilter->dlist[in].name
4199 || strcmp (filter->dlist[in].name, gfilter->dlist[in].name) != 0)
4200 vty_out (vty, " neighbor %s distribute-list %s in%s", addr,
4201 filter->dlist[in].name, VTY_NEWLINE);
4202 if (filter->dlist[out].name && ! gfilter)
4203 vty_out (vty, " neighbor %s distribute-list %s out%s", addr,
4204 filter->dlist[out].name, VTY_NEWLINE);
4205
4206 /* prefix-list. */
4207 if (filter->plist[in].name)
4208 if (! gfilter || ! gfilter->plist[in].name
4209 || strcmp (filter->plist[in].name, gfilter->plist[in].name) != 0)
4210 vty_out (vty, " neighbor %s prefix-list %s in%s", addr,
4211 filter->plist[in].name, VTY_NEWLINE);
4212 if (filter->plist[out].name && ! gfilter)
4213 vty_out (vty, " neighbor %s prefix-list %s out%s", addr,
4214 filter->plist[out].name, VTY_NEWLINE);
4215
4216 /* route-map. */
paulfee0f4c2004-09-13 05:12:46 +00004217 if (filter->map[RMAP_IN].name)
4218 if (! gfilter || ! gfilter->map[RMAP_IN].name
4219 || strcmp (filter->map[RMAP_IN].name, gfilter->map[RMAP_IN].name) != 0)
paul718e3742002-12-13 20:15:29 +00004220 vty_out (vty, " neighbor %s route-map %s in%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004221 filter->map[RMAP_IN].name, VTY_NEWLINE);
4222 if (filter->map[RMAP_OUT].name && ! gfilter)
paul718e3742002-12-13 20:15:29 +00004223 vty_out (vty, " neighbor %s route-map %s out%s", addr,
paulfee0f4c2004-09-13 05:12:46 +00004224 filter->map[RMAP_OUT].name, VTY_NEWLINE);
4225 if (filter->map[RMAP_IMPORT].name && ! gfilter)
4226 vty_out (vty, " neighbor %s route-map %s import%s", addr,
4227 filter->map[RMAP_IMPORT].name, VTY_NEWLINE);
4228 if (filter->map[RMAP_EXPORT].name)
4229 if (! gfilter || ! gfilter->map[RMAP_EXPORT].name
4230 || strcmp (filter->map[RMAP_EXPORT].name,
4231 gfilter->map[RMAP_EXPORT].name) != 0)
4232 vty_out (vty, " neighbor %s route-map %s export%s", addr,
4233 filter->map[RMAP_EXPORT].name, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004234
4235 /* unsuppress-map */
4236 if (filter->usmap.name && ! gfilter)
4237 vty_out (vty, " neighbor %s unsuppress-map %s%s", addr,
4238 filter->usmap.name, VTY_NEWLINE);
4239
4240 /* filter-list. */
4241 if (filter->aslist[in].name)
4242 if (! gfilter || ! gfilter->aslist[in].name
4243 || strcmp (filter->aslist[in].name, gfilter->aslist[in].name) != 0)
4244 vty_out (vty, " neighbor %s filter-list %s in%s", addr,
4245 filter->aslist[in].name, VTY_NEWLINE);
4246 if (filter->aslist[out].name && ! gfilter)
4247 vty_out (vty, " neighbor %s filter-list %s out%s", addr,
4248 filter->aslist[out].name, VTY_NEWLINE);
4249}
4250
4251/* BGP peer configuration display function. */
4252void
4253bgp_config_write_peer (struct vty *vty, struct bgp *bgp,
4254 struct peer *peer, afi_t afi, safi_t safi)
4255{
4256 struct bgp_filter *filter;
4257 struct peer *g_peer = NULL;
4258 char buf[SU_ADDRSTRLEN];
4259 char *addr;
4260
4261 filter = &peer->filter[afi][safi];
4262 addr = peer->host;
4263 if (peer_group_active (peer))
4264 g_peer = peer->group->conf;
4265
4266 /************************************
4267 ****** Global to the neighbor ******
4268 ************************************/
4269 if (afi == AFI_IP && safi == SAFI_UNICAST)
4270 {
4271 /* remote-as. */
4272 if (! peer_group_active (peer))
4273 {
4274 if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP))
4275 vty_out (vty, " neighbor %s peer-group%s", addr,
4276 VTY_NEWLINE);
4277 if (peer->as)
4278 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4279 VTY_NEWLINE);
4280 }
4281 else
4282 {
4283 if (! g_peer->as)
4284 vty_out (vty, " neighbor %s remote-as %d%s", addr, peer->as,
4285 VTY_NEWLINE);
4286 if (peer->af_group[AFI_IP][SAFI_UNICAST])
4287 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4288 peer->group->name, VTY_NEWLINE);
4289 }
4290
4291 /* local-as. */
4292 if (peer->change_local_as)
4293 if (! peer_group_active (peer))
4294 vty_out (vty, " neighbor %s local-as %d%s%s", addr,
4295 peer->change_local_as,
4296 CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND) ?
4297 " no-prepend" : "", VTY_NEWLINE);
4298
4299 /* Description. */
4300 if (peer->desc)
4301 vty_out (vty, " neighbor %s description %s%s", addr, peer->desc,
4302 VTY_NEWLINE);
4303
4304 /* Shutdown. */
4305 if (CHECK_FLAG (peer->flags, PEER_FLAG_SHUTDOWN))
4306 if (! peer_group_active (peer) ||
4307 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
4308 vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
4309
4310 /* BGP port. */
4311 if (peer->port != BGP_PORT_DEFAULT)
4312 vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
4313 VTY_NEWLINE);
4314
4315 /* Local interface name. */
4316 if (peer->ifname)
4317 vty_out (vty, " neighbor %s interface %s%s", addr, peer->ifname,
4318 VTY_NEWLINE);
4319
4320 /* Passive. */
4321 if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSIVE))
4322 if (! peer_group_active (peer) ||
4323 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSIVE))
4324 vty_out (vty, " neighbor %s passive%s", addr, VTY_NEWLINE);
4325
4326 /* EBGP multihop. */
4327 if (peer_sort (peer) != BGP_PEER_IBGP && peer->ttl != 1)
4328 if (! peer_group_active (peer) ||
4329 g_peer->ttl != peer->ttl)
4330 vty_out (vty, " neighbor %s ebgp-multihop %d%s", addr, peer->ttl,
4331 VTY_NEWLINE);
4332
hasso6ffd2072005-02-02 14:50:11 +00004333 /* disable-connected-check. */
4334 if (CHECK_FLAG (peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
paul718e3742002-12-13 20:15:29 +00004335 if (! peer_group_active (peer) ||
hasso6ffd2072005-02-02 14:50:11 +00004336 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK))
4337 vty_out (vty, " neighbor %s disable-connected-check%s", addr, VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004338
4339 /* Update-source. */
4340 if (peer->update_if)
4341 if (! peer_group_active (peer) || ! g_peer->update_if
4342 || strcmp (g_peer->update_if, peer->update_if) != 0)
4343 vty_out (vty, " neighbor %s update-source %s%s", addr,
4344 peer->update_if, VTY_NEWLINE);
4345 if (peer->update_source)
4346 if (! peer_group_active (peer) || ! g_peer->update_source
4347 || sockunion_cmp (g_peer->update_source,
4348 peer->update_source) != 0)
4349 vty_out (vty, " neighbor %s update-source %s%s", addr,
4350 sockunion2str (peer->update_source, buf, SU_ADDRSTRLEN),
4351 VTY_NEWLINE);
4352
paul718e3742002-12-13 20:15:29 +00004353 /* advertisement-interval */
4354 if (CHECK_FLAG (peer->config, PEER_CONFIG_ROUTEADV))
4355 vty_out (vty, " neighbor %s advertisement-interval %d%s",
4356 addr, peer->v_routeadv, VTY_NEWLINE);
4357
4358 /* timers. */
4359 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER)
4360 && ! peer_group_active (peer))
4361 vty_out (vty, " neighbor %s timers %d %d%s", addr,
4362 peer->keepalive, peer->holdtime, VTY_NEWLINE);
4363
4364 if (CHECK_FLAG (peer->config, PEER_CONFIG_CONNECT))
4365 vty_out (vty, " neighbor %s timers connect %d%s", addr,
4366 peer->connect, VTY_NEWLINE);
4367
4368 /* Default weight. */
4369 if (CHECK_FLAG (peer->config, PEER_CONFIG_WEIGHT))
4370 if (! peer_group_active (peer) ||
4371 g_peer->weight != peer->weight)
4372 vty_out (vty, " neighbor %s weight %d%s", addr, peer->weight,
4373 VTY_NEWLINE);
4374
paul718e3742002-12-13 20:15:29 +00004375 /* Dynamic capability. */
4376 if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4377 if (! peer_group_active (peer) ||
4378 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
4379 vty_out (vty, " neighbor %s capability dynamic%s", addr,
4380 VTY_NEWLINE);
4381
4382 /* dont capability negotiation. */
4383 if (CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
4384 if (! peer_group_active (peer) ||
4385 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_DONT_CAPABILITY))
4386 vty_out (vty, " neighbor %s dont-capability-negotiate%s", addr,
4387 VTY_NEWLINE);
4388
4389 /* override capability negotiation. */
4390 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4391 if (! peer_group_active (peer) ||
4392 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
4393 vty_out (vty, " neighbor %s override-capability%s", addr,
4394 VTY_NEWLINE);
4395
4396 /* strict capability negotiation. */
4397 if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4398 if (! peer_group_active (peer) ||
4399 ! CHECK_FLAG (g_peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
4400 vty_out (vty, " neighbor %s strict-capability-match%s", addr,
4401 VTY_NEWLINE);
4402
4403 if (! peer_group_active (peer))
4404 {
4405 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4406 {
4407 if (peer->afc[AFI_IP][SAFI_UNICAST])
4408 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4409 }
4410 else
4411 {
4412 if (! peer->afc[AFI_IP][SAFI_UNICAST])
4413 vty_out (vty, " no neighbor %s activate%s", addr, VTY_NEWLINE);
4414 }
4415 }
4416 }
4417
4418
4419 /************************************
4420 ****** Per AF to the neighbor ******
4421 ************************************/
4422
4423 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
4424 {
4425 if (peer->af_group[afi][safi])
4426 vty_out (vty, " neighbor %s peer-group %s%s", addr,
4427 peer->group->name, VTY_NEWLINE);
4428 else
4429 vty_out (vty, " neighbor %s activate%s", addr, VTY_NEWLINE);
4430 }
4431
4432 /* ORF capability. */
4433 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4434 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4435 if (! peer->af_group[afi][safi])
4436 {
4437 vty_out (vty, " neighbor %s capability orf prefix-list", addr);
4438
4439 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
4440 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
4441 vty_out (vty, " both");
4442 else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
4443 vty_out (vty, " send");
4444 else
4445 vty_out (vty, " receive");
4446 vty_out (vty, "%s", VTY_NEWLINE);
4447 }
4448
4449 /* Route reflector client. */
4450 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REFLECTOR_CLIENT)
4451 && ! peer->af_group[afi][safi])
4452 vty_out (vty, " neighbor %s route-reflector-client%s", addr,
4453 VTY_NEWLINE);
4454
4455 /* Nexthop self. */
4456 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_NEXTHOP_SELF)
4457 && ! peer->af_group[afi][safi])
4458 vty_out (vty, " neighbor %s next-hop-self%s", addr, VTY_NEWLINE);
4459
4460 /* Remove private AS. */
4461 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_REMOVE_PRIVATE_AS)
4462 && ! peer->af_group[afi][safi])
4463 vty_out (vty, " neighbor %s remove-private-AS%s",
4464 addr, VTY_NEWLINE);
4465
4466 /* send-community print. */
4467 if (! peer->af_group[afi][safi])
4468 {
4469 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4470 {
4471 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4472 && peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4473 vty_out (vty, " neighbor %s send-community both%s", addr, VTY_NEWLINE);
4474 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4475 vty_out (vty, " neighbor %s send-community extended%s",
4476 addr, VTY_NEWLINE);
4477 else if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4478 vty_out (vty, " neighbor %s send-community%s", addr, VTY_NEWLINE);
4479 }
4480 else
4481 {
4482 if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY)
4483 && ! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4484 vty_out (vty, " no neighbor %s send-community both%s",
4485 addr, VTY_NEWLINE);
4486 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_EXT_COMMUNITY))
4487 vty_out (vty, " no neighbor %s send-community extended%s",
4488 addr, VTY_NEWLINE);
4489 else if (! peer_af_flag_check (peer, afi, safi, PEER_FLAG_SEND_COMMUNITY))
4490 vty_out (vty, " no neighbor %s send-community%s",
4491 addr, VTY_NEWLINE);
4492 }
4493 }
4494
4495 /* Default information */
4496 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_DEFAULT_ORIGINATE)
4497 && ! peer->af_group[afi][safi])
4498 {
4499 vty_out (vty, " neighbor %s default-originate", addr);
4500 if (peer->default_rmap[afi][safi].name)
4501 vty_out (vty, " route-map %s", peer->default_rmap[afi][safi].name);
4502 vty_out (vty, "%s", VTY_NEWLINE);
4503 }
4504
4505 /* Soft reconfiguration inbound. */
4506 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4507 if (! peer->af_group[afi][safi] ||
4508 ! CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_SOFT_RECONFIG))
4509 vty_out (vty, " neighbor %s soft-reconfiguration inbound%s", addr,
4510 VTY_NEWLINE);
4511
4512 /* maximum-prefix. */
4513 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX))
4514 if (! peer->af_group[afi][safi]
4515 || g_peer->pmax[afi][safi] != peer->pmax[afi][safi]
hassoe0701b72004-05-20 09:19:34 +00004516 || g_peer->pmax_threshold[afi][safi] != peer->pmax_threshold[afi][safi]
paul718e3742002-12-13 20:15:29 +00004517 || CHECK_FLAG (g_peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING)
4518 != CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
hassoe0701b72004-05-20 09:19:34 +00004519 {
hasso0a486e52005-02-01 20:57:17 +00004520 vty_out (vty, " neighbor %s maximum-prefix %ld", addr, peer->pmax[afi][safi]);
4521 if (peer->pmax_threshold[afi][safi] != MAXIMUM_PREFIX_THRESHOLD_DEFAULT)
4522 vty_out (vty, " %d", peer->pmax_threshold[afi][safi]);
4523 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX_WARNING))
4524 vty_out (vty, " warning-only");
4525 if (peer->pmax_restart[afi][safi])
4526 vty_out (vty, " restart %d", peer->pmax_restart[afi][safi]);
4527 vty_out (vty, "%s", VTY_NEWLINE);
hassoe0701b72004-05-20 09:19:34 +00004528 }
paul718e3742002-12-13 20:15:29 +00004529
4530 /* Route server client. */
4531 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)
4532 && ! peer->af_group[afi][safi])
4533 vty_out (vty, " neighbor %s route-server-client%s", addr, VTY_NEWLINE);
4534
4535 /* Allow AS in. */
4536 if (peer_af_flag_check (peer, afi, safi, PEER_FLAG_ALLOWAS_IN))
4537 if (! peer_group_active (peer)
4538 || ! peer_af_flag_check (g_peer, afi, safi, PEER_FLAG_ALLOWAS_IN)
4539 || peer->allowas_in[afi][safi] != g_peer->allowas_in[afi][safi])
4540 {
4541 if (peer->allowas_in[afi][safi] == 3)
4542 vty_out (vty, " neighbor %s allowas-in%s", addr, VTY_NEWLINE);
4543 else
4544 vty_out (vty, " neighbor %s allowas-in %d%s", addr,
4545 peer->allowas_in[afi][safi], VTY_NEWLINE);
4546 }
4547
4548 /* Filter. */
4549 bgp_config_write_filter (vty, peer, afi, safi);
4550
4551 /* atribute-unchanged. */
4552 if ((CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4553 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4554 || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4555 && ! peer->af_group[afi][safi])
4556 {
4557 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)
4558 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)
4559 && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED))
4560 vty_out (vty, " neighbor %s attribute-unchanged%s", addr, VTY_NEWLINE);
4561 else
4562 vty_out (vty, " neighbor %s attribute-unchanged%s%s%s%s", addr,
4563 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED)) ?
4564 " as-path" : "",
4565 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) ?
4566 " next-hop" : "",
4567 (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_MED_UNCHANGED)) ?
4568 " med" : "", VTY_NEWLINE);
4569 }
4570}
4571
4572/* Display "address-family" configuration header. */
4573void
4574bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi,
4575 int *write)
4576{
4577 if (*write)
4578 return;
4579
4580 if (afi == AFI_IP && safi == SAFI_UNICAST)
4581 return;
4582
4583 vty_out (vty, "!%s address-family ", VTY_NEWLINE);
4584
4585 if (afi == AFI_IP)
4586 {
4587 if (safi == SAFI_MULTICAST)
4588 vty_out (vty, "ipv4 multicast");
4589 else if (safi == SAFI_MPLS_VPN)
4590 vty_out (vty, "vpnv4 unicast");
4591 }
4592 else if (afi == AFI_IP6)
4593 vty_out (vty, "ipv6");
4594
4595 vty_out (vty, "%s", VTY_NEWLINE);
4596
4597 *write = 1;
4598}
4599
4600/* Address family based peer configuration display. */
4601int
4602bgp_config_write_family (struct vty *vty, struct bgp *bgp, afi_t afi,
4603 safi_t safi)
4604{
4605 int write = 0;
4606 struct peer *peer;
4607 struct peer_group *group;
paul1eb8ef22005-04-07 07:30:20 +00004608 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00004609
4610 bgp_config_write_network (vty, bgp, afi, safi, &write);
4611
4612 bgp_config_write_redistribute (vty, bgp, afi, safi, &write);
4613
paul1eb8ef22005-04-07 07:30:20 +00004614 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004615 {
4616 if (group->conf->afc[afi][safi])
4617 {
4618 bgp_config_write_family_header (vty, afi, safi, &write);
4619 bgp_config_write_peer (vty, bgp, group->conf, afi, safi);
4620 }
4621 }
paul1eb8ef22005-04-07 07:30:20 +00004622 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004623 {
4624 if (peer->afc[afi][safi])
4625 {
4626 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4627 {
4628 bgp_config_write_family_header (vty, afi, safi, &write);
4629 bgp_config_write_peer (vty, bgp, peer, afi, safi);
4630 }
4631 }
4632 }
4633 if (write)
4634 vty_out (vty, " exit-address-family%s", VTY_NEWLINE);
4635
4636 return write;
4637}
4638
4639int
4640bgp_config_write (struct vty *vty)
4641{
4642 int write = 0;
4643 struct bgp *bgp;
4644 struct peer_group *group;
4645 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004646 struct listnode *node, *nnode;
4647 struct listnode *mnode, *mnnode;
paul718e3742002-12-13 20:15:29 +00004648
4649 /* BGP Multiple instance. */
4650 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4651 {
4652 vty_out (vty, "bgp multiple-instance%s", VTY_NEWLINE);
4653 write++;
4654 }
4655
4656 /* BGP Config type. */
4657 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4658 {
4659 vty_out (vty, "bgp config-type cisco%s", VTY_NEWLINE);
4660 write++;
4661 }
4662
4663 /* BGP configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004664 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
paul718e3742002-12-13 20:15:29 +00004665 {
4666 if (write)
4667 vty_out (vty, "!%s", VTY_NEWLINE);
4668
4669 /* Router bgp ASN */
4670 vty_out (vty, "router bgp %d", bgp->as);
4671
4672 if (bgp_option_check (BGP_OPT_MULTIPLE_INSTANCE))
4673 {
4674 if (bgp->name)
4675 vty_out (vty, " view %s", bgp->name);
4676 }
4677 vty_out (vty, "%s", VTY_NEWLINE);
4678
4679 /* No Synchronization */
4680 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4681 vty_out (vty, " no synchronization%s", VTY_NEWLINE);
4682
4683 /* BGP fast-external-failover. */
4684 if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER))
4685 vty_out (vty, " no bgp fast-external-failover%s", VTY_NEWLINE);
4686
4687 /* BGP router ID. */
4688 if (CHECK_FLAG (bgp->config, BGP_CONFIG_ROUTER_ID))
4689 vty_out (vty, " bgp router-id %s%s", inet_ntoa (bgp->router_id),
4690 VTY_NEWLINE);
4691
paul848973c2003-08-13 00:32:49 +00004692 /* BGP log-neighbor-changes. */
4693 if (bgp_flag_check (bgp, BGP_FLAG_LOG_NEIGHBOR_CHANGES))
4694 vty_out (vty, " bgp log-neighbor-changes%s", VTY_NEWLINE);
4695
paul718e3742002-12-13 20:15:29 +00004696 /* BGP configuration. */
4697 if (bgp_flag_check (bgp, BGP_FLAG_ALWAYS_COMPARE_MED))
4698 vty_out (vty, " bgp always-compare-med%s", VTY_NEWLINE);
4699
4700 /* BGP default ipv4-unicast. */
4701 if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4))
4702 vty_out (vty, " no bgp default ipv4-unicast%s", VTY_NEWLINE);
4703
4704 /* BGP default local-preference. */
4705 if (bgp->default_local_pref != BGP_DEFAULT_LOCAL_PREF)
4706 vty_out (vty, " bgp default local-preference %d%s",
4707 bgp->default_local_pref, VTY_NEWLINE);
4708
4709 /* BGP client-to-client reflection. */
4710 if (bgp_flag_check (bgp, BGP_FLAG_NO_CLIENT_TO_CLIENT))
4711 vty_out (vty, " no bgp client-to-client reflection%s", VTY_NEWLINE);
4712
4713 /* BGP cluster ID. */
4714 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CLUSTER_ID))
4715 vty_out (vty, " bgp cluster-id %s%s", inet_ntoa (bgp->cluster_id),
4716 VTY_NEWLINE);
4717
hassoe0701b72004-05-20 09:19:34 +00004718 /* Confederation identifier*/
paul718e3742002-12-13 20:15:29 +00004719 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION))
hassoe0701b72004-05-20 09:19:34 +00004720 vty_out (vty, " bgp confederation identifier %i%s", bgp->confed_id,
4721 VTY_NEWLINE);
4722
4723 /* Confederation peer */
4724 if (bgp->confed_peers_cnt > 0)
paul718e3742002-12-13 20:15:29 +00004725 {
hassoe0701b72004-05-20 09:19:34 +00004726 int i;
paul718e3742002-12-13 20:15:29 +00004727
hassoe0701b72004-05-20 09:19:34 +00004728 vty_out (vty, " bgp confederation peers");
paul718e3742002-12-13 20:15:29 +00004729
hassoe0701b72004-05-20 09:19:34 +00004730 for (i = 0; i < bgp->confed_peers_cnt; i++)
4731 vty_out(vty, " %d", bgp->confed_peers[i]);
paul718e3742002-12-13 20:15:29 +00004732
hassoe0701b72004-05-20 09:19:34 +00004733 vty_out (vty, "%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004734 }
4735
4736 /* BGP enforce-first-as. */
4737 if (bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS))
4738 vty_out (vty, " bgp enforce-first-as%s", VTY_NEWLINE);
4739
4740 /* BGP deterministic-med. */
4741 if (bgp_flag_check (bgp, BGP_FLAG_DETERMINISTIC_MED))
4742 vty_out (vty, " bgp deterministic-med%s", VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00004743
4744 /* BGP graceful-restart. */
hasso93406d82005-02-02 14:40:33 +00004745 if (bgp->stalepath_time != BGP_DEFAULT_STALEPATH_TIME)
4746 vty_out (vty, " bgp graceful-restart stalepath-time %d%s",
4747 bgp->stalepath_time, VTY_NEWLINE);
hasso538621f2004-05-21 09:31:30 +00004748 if (bgp_flag_check (bgp, BGP_FLAG_GRACEFUL_RESTART))
4749 vty_out (vty, " bgp graceful-restart%s", VTY_NEWLINE);
4750
paul718e3742002-12-13 20:15:29 +00004751 /* BGP bestpath method. */
4752 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_IGNORE))
4753 vty_out (vty, " bgp bestpath as-path ignore%s", VTY_NEWLINE);
hasso68118452005-04-08 15:40:36 +00004754 if (bgp_flag_check (bgp, BGP_FLAG_ASPATH_CONFED))
4755 vty_out (vty, " bgp bestpath as-path confed%s", VTY_NEWLINE);
paul718e3742002-12-13 20:15:29 +00004756 if (bgp_flag_check (bgp, BGP_FLAG_COMPARE_ROUTER_ID))
4757 vty_out (vty, " bgp bestpath compare-routerid%s", VTY_NEWLINE);
4758 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED)
4759 || bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4760 {
4761 vty_out (vty, " bgp bestpath med");
4762 if (bgp_flag_check (bgp, BGP_FLAG_MED_CONFED))
4763 vty_out (vty, " confed");
4764 if (bgp_flag_check (bgp, BGP_FLAG_MED_MISSING_AS_WORST))
4765 vty_out (vty, " missing-as-worst");
4766 vty_out (vty, "%s", VTY_NEWLINE);
4767 }
4768
4769 /* BGP network import check. */
4770 if (bgp_flag_check (bgp, BGP_FLAG_IMPORT_CHECK))
4771 vty_out (vty, " bgp network import-check%s", VTY_NEWLINE);
4772
4773 /* BGP scan interval. */
4774 bgp_config_write_scan_time (vty);
4775
4776 /* BGP flag dampening. */
4777 if (CHECK_FLAG (bgp->af_flags[AFI_IP][SAFI_UNICAST],
4778 BGP_CONFIG_DAMPENING))
4779 bgp_config_write_damp (vty);
4780
4781 /* BGP static route configuration. */
4782 bgp_config_write_network (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4783
4784 /* BGP redistribute configuration. */
4785 bgp_config_write_redistribute (vty, bgp, AFI_IP, SAFI_UNICAST, &write);
4786
4787 /* BGP timers configuration. */
4788 if (bgp->default_keepalive != BGP_DEFAULT_KEEPALIVE
4789 && bgp->default_holdtime != BGP_DEFAULT_HOLDTIME)
4790 vty_out (vty, " timers bgp %d %d%s", bgp->default_keepalive,
4791 bgp->default_holdtime, VTY_NEWLINE);
4792
4793 /* peer-group */
paul1eb8ef22005-04-07 07:30:20 +00004794 for (ALL_LIST_ELEMENTS (bgp->group, node, nnode, group))
paul718e3742002-12-13 20:15:29 +00004795 {
4796 bgp_config_write_peer (vty, bgp, group->conf, AFI_IP, SAFI_UNICAST);
4797 }
4798
4799 /* Normal neighbor configuration. */
paul1eb8ef22005-04-07 07:30:20 +00004800 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00004801 {
4802 if (! CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
4803 bgp_config_write_peer (vty, bgp, peer, AFI_IP, SAFI_UNICAST);
4804 }
4805
4806 /* Distance configuration. */
4807 bgp_config_write_distance (vty, bgp);
4808
4809 /* No auto-summary */
4810 if (bgp_option_check (BGP_OPT_CONFIG_CISCO))
4811 vty_out (vty, " no auto-summary%s", VTY_NEWLINE);
4812
4813 /* IPv4 multicast configuration. */
4814 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MULTICAST);
4815
4816 /* IPv4 VPN configuration. */
4817 write += bgp_config_write_family (vty, bgp, AFI_IP, SAFI_MPLS_VPN);
4818
4819 /* IPv6 unicast configuration. */
4820 write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_UNICAST);
4821
4822 write++;
4823 }
4824 return write;
4825}
4826
4827void
4828bgp_master_init ()
4829{
4830 memset (&bgp_master, 0, sizeof (struct bgp_master));
4831
4832 bm = &bgp_master;
4833 bm->bgp = list_new ();
4834 bm->port = BGP_PORT_DEFAULT;
4835 bm->master = thread_master_create ();
4836 bm->start_time = time (NULL);
4837}
4838
4839void
4840bgp_init ()
4841{
4842 void bgp_zebra_init ();
4843 void bgp_route_map_init ();
4844 void bgp_filter_init ();
4845
4846 /* BGP VTY commands installation. */
4847 bgp_vty_init ();
4848
4849 /* Create BGP server socket. */
4850 bgp_socket (NULL, bm->port);
4851
4852 /* Init zebra. */
4853 bgp_zebra_init ();
4854
4855 /* BGP inits. */
4856 bgp_attr_init ();
4857 bgp_debug_init ();
4858 bgp_dump_init ();
4859 bgp_route_init ();
4860 bgp_route_map_init ();
4861 bgp_scan_init ();
4862 bgp_mplsvpn_init ();
4863
4864 /* Access list initialize. */
4865 access_list_init ();
4866 access_list_add_hook (peer_distribute_update);
4867 access_list_delete_hook (peer_distribute_update);
4868
4869 /* Filter list initialize. */
4870 bgp_filter_init ();
4871 as_list_add_hook (peer_aslist_update);
4872 as_list_delete_hook (peer_aslist_update);
4873
4874 /* Prefix list initialize.*/
4875 prefix_list_init ();
4876 prefix_list_add_hook (peer_prefix_list_update);
4877 prefix_list_delete_hook (peer_prefix_list_update);
4878
4879 /* Community list initialize. */
4880 bgp_clist = community_list_init ();
4881
4882#ifdef HAVE_SNMP
4883 bgp_snmp_init ();
4884#endif /* HAVE_SNMP */
4885}
paul545acaf2004-04-20 15:13:15 +00004886
4887void
4888bgp_terminate ()
4889{
paul545acaf2004-04-20 15:13:15 +00004890 struct bgp *bgp;
4891 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00004892 struct listnode *node, *nnode;
4893 struct listnode *mnode, *mnnode;
paul545acaf2004-04-20 15:13:15 +00004894
paul1eb8ef22005-04-07 07:30:20 +00004895 for (ALL_LIST_ELEMENTS (bm->bgp, mnode, mnnode, bgp))
4896 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul545acaf2004-04-20 15:13:15 +00004897 if (peer->status == Established)
4898 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
4899 BGP_NOTIFY_CEASE_PEER_UNCONFIG);
paul1eb8ef22005-04-07 07:30:20 +00004900
paul545acaf2004-04-20 15:13:15 +00004901 bgp_cleanup_routes ();
4902}
4903